Merge branch 'next' into next_novolk
This commit is contained in:
commit
1dff82065b
|
@ -1,6 +1,11 @@
|
|||
Change Log for Releases
|
||||
==============================
|
||||
|
||||
## 17.09
|
||||
* Added MIMO 2x2 in the PHY layer and srsUE (i.e. TM3/TM4)
|
||||
* eMBMS support in the PHY layer
|
||||
* Many bug-fixes and improved stability and performance in srsUE/srsENB
|
||||
|
||||
## 002.000.000
|
||||
* Added fully functional srsENB to srsLTE code
|
||||
* Merged srsUE code into srsLTE and reestructured PHY code
|
||||
|
|
12
README.md
12
README.md
|
@ -15,12 +15,13 @@ srsLTE is released under the AGPLv3 license and uses software from the OpenLTE p
|
|||
Common Features
|
||||
---------------
|
||||
|
||||
* LTE Release 8 compliant
|
||||
* LTE Release 8 compliant (with selected features of Release 9)
|
||||
* FDD configuration
|
||||
* Tested bandwidths: 1.4, 3, 5, 10, 15 and 20 MHz
|
||||
* Transmission mode 1 (single antenna) and 2 (transmit diversity)
|
||||
* Transmission mode 1 (single antenna), 2 (transmit diversity), 3 (CCD) and 4 (closed-loop spatial multiplexing)
|
||||
* Frequency-based ZF and MMSE equalizer
|
||||
* Highly optimized Turbo Decoder available in Intel SSE4.1/AVX (+100 Mbps) and standard C (+25 Mbps)
|
||||
* Evolved multimedia broadcast and multicast service (eMBMS)
|
||||
* Highly optimized Turbo Decoder available in Intel SSE4.1/AVX2 (+100 Mbps) and standard C (+25 Mbps)
|
||||
* MAC, RLC, PDCP, RRC, NAS, S1AP and GW layers
|
||||
* Detailed log system with per-layer log levels and hex dumps
|
||||
* MAC layer wireshark packet capture
|
||||
|
@ -33,6 +34,7 @@ srsUE Features
|
|||
* Cell search and synchronization procedure for the UE
|
||||
* Soft USIM supporting Milenage and XOR authentication
|
||||
* Virtual network interface *tun_srsue* created upon network attach
|
||||
* +100 Mbps DL in 20 MHz MIMO TM4 configuration in i7 Quad-Core CPU.
|
||||
* 75 Mbps DL in 20 MHz SISO configuration in i7 Quad-Core CPU.
|
||||
* 36 Mbps DL in 10 MHz SISO configuration in i5 Dual-Core CPU.
|
||||
|
||||
|
@ -55,6 +57,8 @@ srsENB has been tested and validated with the following handsets:
|
|||
* LG Nexus 5
|
||||
* LG Nexus 4
|
||||
* Motorola Moto G4 plus
|
||||
* Huawei P9/P9lite
|
||||
* Huawei dongles: E3276 and E398
|
||||
|
||||
Hardware
|
||||
--------
|
||||
|
@ -65,7 +69,7 @@ We have tested the following hardware:
|
|||
* USRP B210
|
||||
* USRP X300
|
||||
* bladeRF
|
||||
* limeSDR
|
||||
* limeSDR (currently, only the PHY-layer examples, i.e., pdsch_enodeb/ue are supported)
|
||||
|
||||
Build Instructions
|
||||
------------------
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
# and at http://www.gnu.org/licenses/.
|
||||
#
|
||||
|
||||
SET(SRSLTE_VERSION_MAJOR 002)
|
||||
SET(SRSLTE_VERSION_MINOR 000)
|
||||
SET(SRSLTE_VERSION_PATCH 000)
|
||||
SET(SRSLTE_VERSION_MAJOR 17)
|
||||
SET(SRSLTE_VERSION_MINOR 9)
|
||||
SET(SRSLTE_VERSION_PATCH 0)
|
||||
SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}")
|
||||
|
|
|
@ -113,7 +113,7 @@ inline bool mnc_to_string(uint16_t mnc, std::string *str)
|
|||
*str += (mnc & 0x000F) + '0';
|
||||
return true;
|
||||
}
|
||||
inline std::string plmn_id_to_c_str(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
|
||||
inline std::string plmn_id_to_string(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
|
||||
std::string mcc_str, mnc_str;
|
||||
mnc_to_string(plmn_id.mnc, &mnc_str);
|
||||
mcc_to_string(plmn_id.mcc, &mcc_str);
|
||||
|
|
|
@ -44,12 +44,12 @@
|
|||
#define SRSLTE_N_DRB 8
|
||||
#define SRSLTE_N_RADIO_BEARERS 11
|
||||
|
||||
#define HARQ_DELAY_MS 6
|
||||
#define HARQ_DELAY_MS 4
|
||||
#define MSG3_DELAY_MS 6
|
||||
#define TTI_TX(tti) ((tti+HARQ_DELAY_MS)%10240)
|
||||
#define TTI_RX_ACK(tti) ((tti+(2*HARQ_DELAY_MS))%10240)
|
||||
|
||||
#define TTIMOD_SZ 20
|
||||
#define TTIMOD_SZ (((2*HARQ_DELAY_MS) < 10)?10:20)
|
||||
#define TTIMOD(tti) (tti%TTIMOD_SZ)
|
||||
|
||||
#define ASYNC_DL_SCHED (HARQ_DELAY_MS <= 4)
|
||||
|
|
|
@ -54,6 +54,7 @@ class usim_interface_nas
|
|||
public:
|
||||
virtual void get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0;
|
||||
virtual void get_imei_vec(uint8_t* imei_, uint32_t n) = 0;
|
||||
virtual int get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) = 0;
|
||||
virtual void generate_authentication_response(uint8_t *rand,
|
||||
uint8_t *autn_enb,
|
||||
uint16_t mcc,
|
||||
|
@ -104,6 +105,7 @@ public:
|
|||
virtual uint32_t get_ul_count() = 0;
|
||||
virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0;
|
||||
virtual void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0;
|
||||
virtual void plmn_search_end() = 0;
|
||||
};
|
||||
|
||||
// NAS interface for UE
|
||||
|
@ -140,6 +142,7 @@ class rrc_interface_phy
|
|||
public:
|
||||
virtual void in_sync() = 0;
|
||||
virtual void out_of_sync() = 0;
|
||||
virtual void earfcn_end() = 0;
|
||||
virtual void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ uint8_t* pdu_queue::request(uint32_t len)
|
|||
void pdu_queue::deallocate(uint8_t* pdu)
|
||||
{
|
||||
if (!pool.deallocate((pdu_t*) pdu)) {
|
||||
log_h->warning("Error deallocating from buffer pool: buffer not created in this pool.\n");
|
||||
log_h->warning("Error deallocating from buffer pool in deallocate(): buffer not created in this pool.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ bool pdu_queue::process_pdus()
|
|||
callback->process_pdu(pdu->ptr, pdu->len, pdu->tstamp);
|
||||
}
|
||||
if (!pool.deallocate(pdu)) {
|
||||
log_h->warning("Error deallocating from buffer pool: buffer not created in this pool.\n");
|
||||
log_h->warning("Error deallocating from buffer pool in process_pdus(): buffer not created in this pool.\n");
|
||||
}
|
||||
cnt++;
|
||||
have_data = true;
|
||||
|
|
|
@ -231,7 +231,8 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
srslte_vec_save_file(output_filename,buffer,11*flen*sizeof(cf_t));
|
||||
|
||||
|
||||
srslte_rf_close(&rf);
|
||||
srslte_prach_free(p);
|
||||
free(p);
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@ static rf_dev_t dev_soapy = {
|
|||
rf_soapy_recv_with_time,
|
||||
rf_soapy_recv_with_time_multi,
|
||||
rf_soapy_send_timed,
|
||||
.srslte_rf_send_timed_multi = /* FIXME: Implement srslte_rf_send_timed_multi for Soapy SDR */ NULL,
|
||||
.srslte_rf_send_timed_multi = rf_soapy_send_timed_multi,
|
||||
rf_soapy_set_tx_cal,
|
||||
rf_soapy_set_rx_cal
|
||||
};
|
||||
|
|
|
@ -88,12 +88,12 @@ void rf_soapy_register_error_handler(void *notused, srslte_rf_error_handler_t ne
|
|||
}
|
||||
|
||||
|
||||
|
||||
char* rf_soapy_devname(void* h)
|
||||
{
|
||||
return "soapy";
|
||||
}
|
||||
|
||||
|
||||
bool rf_soapy_rx_wait_lo_locked(void *h)
|
||||
{
|
||||
printf("TODO: implement rf_soapy_rx_wait_lo_locked()\n");
|
||||
|
@ -155,7 +155,6 @@ int rf_soapy_stop_tx_stream(void *h)
|
|||
if(SoapySDRDevice_deactivateStream(handler->device, handler->txStream, 0, 0) != 0)
|
||||
return SRSLTE_ERROR;
|
||||
|
||||
|
||||
handler->tx_stream_active = false;
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
@ -175,7 +174,7 @@ void rf_soapy_flush_buffer(void *h)
|
|||
|
||||
bool rf_soapy_has_rssi(void *h)
|
||||
{
|
||||
printf("TODO: implement rf_soapy_has_rssi()\n");
|
||||
// TODO: implement rf_soapy_has_rssi()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -199,9 +198,8 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
|
|||
}
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
printf("Soapy Has Found device #%d: ", (int)i);
|
||||
for (size_t j = 0; j < soapy_args[i].size; j++)
|
||||
{
|
||||
printf("Soapy has Found device #%d: ", (int)i);
|
||||
for (size_t j = 0; j < soapy_args[i].size; j++) {
|
||||
printf("%s=%s, ", soapy_args[i].keys[j], soapy_args[i].vals[j]);
|
||||
}
|
||||
printf("\n");
|
||||
|
@ -221,7 +219,6 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
|
|||
handler->tx_stream_active = false;
|
||||
handler->rx_stream_active = false;
|
||||
|
||||
|
||||
if(SoapySDRDevice_getNumChannels(handler->device,SOAPY_SDR_RX) > 0){
|
||||
printf("setting up RX stream\n");
|
||||
if(SoapySDRDevice_setupStream(handler->device, &(handler->rxStream), SOAPY_SDR_RX, SOAPY_SDR_CF32, NULL, 0, NULL) != 0) {
|
||||
|
@ -251,12 +248,12 @@ int rf_soapy_open(char *args, void **h)
|
|||
int rf_soapy_close(void *h)
|
||||
{
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
if (handler->txStream) {
|
||||
if (handler->tx_stream_active) {
|
||||
rf_soapy_stop_tx_stream(handler);
|
||||
SoapySDRDevice_closeStream(handler->device, handler->txStream);
|
||||
}
|
||||
|
||||
if (handler->rxStream) {
|
||||
if (handler->rx_stream_active) {
|
||||
rf_soapy_stop_rx_stream(handler);
|
||||
SoapySDRDevice_closeStream(handler->device, handler->rxStream);
|
||||
}
|
||||
|
@ -285,9 +282,15 @@ double rf_soapy_set_rx_srate(void *h, double rate)
|
|||
{
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
if (SoapySDRDevice_setSampleRate(handler->device, SOAPY_SDR_RX, 0, rate) != 0) {
|
||||
printf("setSampleRate fail: %s\n", SoapySDRDevice_lastError());
|
||||
printf("setSampleRate Rx fail: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_RX, 0, rate) != 0) {
|
||||
printf("setBandwidth Rx failed: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_RX,0);
|
||||
}
|
||||
|
||||
|
@ -295,9 +298,15 @@ double rf_soapy_set_tx_srate(void *h, double rate)
|
|||
{
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
if (SoapySDRDevice_setSampleRate(handler->device, SOAPY_SDR_TX, 0, rate) != 0) {
|
||||
printf("setSampleRate fail: %s\n", SoapySDRDevice_lastError());
|
||||
printf("setSampleRate Tx fail: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_TX, 0, rate) != 0) {
|
||||
printf("setBandwidth Tx failed: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_TX,0);
|
||||
}
|
||||
|
||||
|
@ -348,7 +357,15 @@ double rf_soapy_set_rx_freq(void *h, double freq)
|
|||
printf("setFrequency fail: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// Todo: expose antenna setting
|
||||
if (SoapySDRDevice_setAntenna(handler->device, SOAPY_SDR_RX, 0, "LNAH") != 0) {
|
||||
fprintf(stderr, "Failed to set Rx antenna.\n");
|
||||
}
|
||||
|
||||
char *ant = SoapySDRDevice_getAntenna(handler->device, SOAPY_SDR_RX, 0);
|
||||
printf("Rx antenna set to %s\n", ant);
|
||||
|
||||
return SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_RX, 0);
|
||||
}
|
||||
|
||||
|
@ -360,14 +377,25 @@ double rf_soapy_set_tx_freq(void *h, double freq)
|
|||
printf("setFrequency fail: %s\n", SoapySDRDevice_lastError());
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Todo: expose antenna name in arguments
|
||||
if (SoapySDRDevice_setAntenna(handler->device, SOAPY_SDR_TX, 0, "BAND1") != 0) {
|
||||
fprintf(stderr, "Failed to set Tx antenna.\n");
|
||||
}
|
||||
|
||||
char *ant = SoapySDRDevice_getAntenna(handler->device, SOAPY_SDR_TX, 0);
|
||||
printf("Tx antenna set to %s\n", ant);
|
||||
|
||||
return SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_TX, 0);
|
||||
}
|
||||
|
||||
|
||||
void rf_soapy_get_time(void *h, time_t *secs, double *frac_secs) {
|
||||
|
||||
void rf_soapy_get_time(void *h, time_t *secs, double *frac_secs)
|
||||
{
|
||||
printf("Todo: implement rf_soapy_get_time()\n");
|
||||
}
|
||||
|
||||
|
||||
//TODO: add multi-channel support
|
||||
int rf_soapy_recv_with_time_multi(void *h,
|
||||
void **data,
|
||||
|
@ -395,7 +423,7 @@ int rf_soapy_recv_with_time_multi(void *h,
|
|||
cf_t *data_c = (cf_t*) data[i];
|
||||
buffs_ptr[i] = &data_c[n];
|
||||
}
|
||||
ret = SoapySDRDevice_readStream(handler->device, handler->rxStream, buffs_ptr , rx_samples, &flags, &timeNs, 1000000);
|
||||
ret = SoapySDRDevice_readStream(handler->device, handler->rxStream, buffs_ptr, rx_samples, &flags, &timeNs, 10000);
|
||||
if(ret < 0) {
|
||||
// continue when getting overflows
|
||||
if (ret == SOAPY_SDR_OVERFLOW) {
|
||||
|
@ -407,17 +435,23 @@ int rf_soapy_recv_with_time_multi(void *h,
|
|||
}
|
||||
}
|
||||
|
||||
// update rx time
|
||||
if (secs != NULL && frac_secs != NULL) {
|
||||
*secs = timeNs / 1e9;
|
||||
*frac_secs = (timeNs % 1000000000)/1e9;
|
||||
//printf("rx_time: secs=%d, frac_secs=%lf timeNs=%lld\n", *secs, *frac_secs, timeNs);
|
||||
}
|
||||
|
||||
n += ret;
|
||||
trials++;
|
||||
} while (n < nsamples && trials < 100);
|
||||
|
||||
|
||||
//*secs = timeNs / 1000000000;
|
||||
//*frac_secs = (timeNs % 1000000000)/1000000000;
|
||||
// printf("ret=%d, flags=%d, timeNs=%lld\n", ret, flags, timeNs);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
int rf_soapy_recv_with_time(void *h,
|
||||
void *data,
|
||||
uint32_t nsamples,
|
||||
|
@ -430,49 +464,92 @@ int rf_soapy_recv_with_time(void *h,
|
|||
|
||||
|
||||
int rf_soapy_send_timed(void *h,
|
||||
void *data,
|
||||
int nsamples,
|
||||
time_t secs,
|
||||
double frac_secs,
|
||||
bool has_time_spec,
|
||||
bool blocking,
|
||||
bool is_start_of_burst,
|
||||
bool is_end_of_burst)
|
||||
void *data,
|
||||
int nsamples,
|
||||
time_t secs,
|
||||
double frac_secs,
|
||||
bool has_time_spec,
|
||||
bool blocking,
|
||||
bool is_start_of_burst,
|
||||
bool is_end_of_burst)
|
||||
{
|
||||
|
||||
int flags;
|
||||
long long timeNs;
|
||||
int trials = 0;
|
||||
int ret = 0;
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
void *_data[SRSLTE_MAX_PORTS]= {data, zero_mem, zero_mem, zero_mem};
|
||||
return rf_soapy_send_timed_multi(h, _data, nsamples, secs, frac_secs, has_time_spec, blocking, is_start_of_burst, is_end_of_burst);
|
||||
}
|
||||
|
||||
|
||||
// Todo: Check correct handling of flags, use RF metrics API, fix timed transmissions
|
||||
int rf_soapy_send_timed_multi(void *h,
|
||||
void *data[SRSLTE_MAX_PORTS],
|
||||
int nsamples,
|
||||
time_t secs,
|
||||
double frac_secs,
|
||||
bool has_time_spec,
|
||||
bool blocking,
|
||||
bool is_start_of_burst,
|
||||
bool is_end_of_burst)
|
||||
{
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t *) h;
|
||||
int flags = 0;
|
||||
const long timeoutUs = 2000; // arbitrarily chosen
|
||||
long long timeNs = 0;
|
||||
int trials = 0;
|
||||
int ret = 0;
|
||||
int n = 0;
|
||||
|
||||
|
||||
if (!handler->tx_stream_active) {
|
||||
rf_soapy_start_tx_stream(h);
|
||||
}
|
||||
|
||||
if (is_start_of_burst && is_end_of_burst) {
|
||||
flags |= SOAPY_SDR_ONE_PACKET;
|
||||
}
|
||||
|
||||
if (is_end_of_burst) {
|
||||
flags |= SOAPY_SDR_END_BURST;
|
||||
}
|
||||
|
||||
if (has_time_spec) {
|
||||
flags |= SOAPY_SDR_HAS_TIME;
|
||||
timeNs = secs * 1000000000;
|
||||
timeNs = timeNs + (frac_secs * 1000000000);
|
||||
int n = 0;
|
||||
//printf("time_spec: secs=%d, frac_secs=%lf timeNs=%lld\n", secs, frac_secs, timeNs);
|
||||
}
|
||||
|
||||
if(!handler->tx_stream_active){
|
||||
rf_soapy_start_tx_stream(h);
|
||||
do {
|
||||
size_t tx_samples = nsamples;
|
||||
if (tx_samples > nsamples - n) {
|
||||
tx_samples = nsamples - n;
|
||||
}
|
||||
|
||||
|
||||
cf_t *data_c = (cf_t*) data;
|
||||
do{
|
||||
size_t tx_samples = nsamples;
|
||||
if (tx_samples > nsamples - n) {
|
||||
tx_samples = nsamples - n;
|
||||
}
|
||||
void *buff = (void*) &data_c[n];
|
||||
const void *buffs_ptr[1] = {buff};
|
||||
ret = SoapySDRDevice_writeStream(handler->device, handler->txStream, buffs_ptr, tx_samples, &flags, timeNs, 10000);
|
||||
if(ret < 0)
|
||||
return SRSLTE_ERROR;
|
||||
|
||||
n += ret;
|
||||
trials++;
|
||||
}while (n < nsamples && trials < 100);
|
||||
|
||||
if(ret != nsamples)
|
||||
return SRSLTE_ERROR;
|
||||
|
||||
return ret;
|
||||
ret = SoapySDRDevice_writeStream(handler->device, handler->txStream, (const void *)data, tx_samples, &flags, timeNs, timeoutUs);
|
||||
if (ret == SOAPY_SDR_TIMEOUT) {
|
||||
printf("L");
|
||||
continue;
|
||||
}
|
||||
if (ret == SOAPY_SDR_OVERFLOW) {
|
||||
printf("O");
|
||||
continue;
|
||||
}
|
||||
if (ret == SOAPY_SDR_UNDERFLOW) {
|
||||
printf("U");
|
||||
continue;
|
||||
}
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error during writeStream\n");
|
||||
exit(-1);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
n += ret;
|
||||
trials++;
|
||||
} while (n < nsamples && trials < 100);
|
||||
|
||||
if (n != nsamples) {
|
||||
fprintf(stderr, "Couldn't write all samples.\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ SRSLTE_API void rf_soapy_get_time(void *h,
|
|||
time_t *secs,
|
||||
double *frac_secs);
|
||||
|
||||
SRSLTE_API int rf_soapy_send_timed(void *h,
|
||||
SRSLTE_API int rf_soapy_send_timed(void *h,
|
||||
void *data,
|
||||
int nsamples,
|
||||
time_t secs,
|
||||
|
@ -116,3 +116,12 @@ SRSLTE_API int rf_soapy_send_timed(void *h,
|
|||
bool is_start_of_burst,
|
||||
bool is_end_of_burst);
|
||||
|
||||
int rf_soapy_send_timed_multi(void *h,
|
||||
void *data[4],
|
||||
int nsamples,
|
||||
time_t secs,
|
||||
double frac_secs,
|
||||
bool has_time_spec,
|
||||
bool blocking,
|
||||
bool is_start_of_burst,
|
||||
bool is_end_of_burst);
|
||||
|
|
|
@ -513,10 +513,10 @@ void rlc_um::reassemble_rx_sdus()
|
|||
}
|
||||
|
||||
// Handle last segment
|
||||
// Handle last segment
|
||||
if (rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES ||
|
||||
rx_window[vr_ur].buf->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES ||
|
||||
rx_window[vr_ur].buf->N_bytes + rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES) {
|
||||
if (rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES &&
|
||||
rx_window[vr_ur].buf->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES &&
|
||||
rx_window[vr_ur].buf->N_bytes + rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES)
|
||||
{
|
||||
|
||||
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes);
|
||||
rx_sdu->N_bytes += rx_window[vr_ur].buf->N_bytes;
|
||||
|
|
|
@ -100,7 +100,7 @@ filename = /tmp/enb.pcap
|
|||
#
|
||||
# filename: File path to use for log output. Can be set to stdout
|
||||
# to print logs to standard output
|
||||
git c#####################################################################
|
||||
#####################################################################
|
||||
[log]
|
||||
all_level = info
|
||||
all_hex_limit = 32
|
||||
|
|
|
@ -619,6 +619,7 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST])
|
|||
tbs, user->get_pending_dl_new_data(current_tti));
|
||||
}
|
||||
} else {
|
||||
h->reset();
|
||||
Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d\n", rnti, h->get_id());
|
||||
}
|
||||
}
|
||||
|
@ -782,6 +783,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
|
|||
user->get_locations(current_cfi, sf_idx),
|
||||
aggr_level))
|
||||
{
|
||||
h->reset();
|
||||
log_h->warning("SCHED: Could not schedule UL DCI rnti=0x%x, pid=%d, L=%d\n",
|
||||
rnti, h->get_id(), aggr_level);
|
||||
sched_result->pusch[nof_dci_elems].needs_pdcch = false;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <srslte/interfaces/sched_interface.h>
|
||||
#include <srslte/phy/phch/pucch.h>
|
||||
#include <srslte/srslte.h>
|
||||
#include <srslte/phy/common/phy_common.h>
|
||||
|
||||
#include "srslte/srslte.h"
|
||||
#include "srslte/common/pdu.h"
|
||||
|
@ -699,10 +700,16 @@ uint32_t sched_ue::get_aggr_level(uint32_t nof_bits)
|
|||
uint32_t l=0;
|
||||
float max_coderate = srslte_cqi_to_coderate(dl_cqi);
|
||||
float coderate = 99;
|
||||
float factor=1.5;
|
||||
uint32_t l_max = 3;
|
||||
if (cell.nof_prb == 6) {
|
||||
factor = 1.0;
|
||||
l_max = 2;
|
||||
}
|
||||
do {
|
||||
coderate = srslte_pdcch_coderate(nof_bits, l);
|
||||
l++;
|
||||
} while(l<3 && 1.5*coderate > max_coderate);
|
||||
} while(l<l_max && factor*coderate > max_coderate);
|
||||
Debug("SCHED: CQI=%d, l=%d, nof_bits=%d, coderate=%.2f, max_coderate=%.2f\n", dl_cqi, l, nof_bits, coderate, max_coderate);
|
||||
return l;
|
||||
}
|
||||
|
|
|
@ -91,10 +91,10 @@ public:
|
|||
bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi);
|
||||
|
||||
void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code);
|
||||
void plmn_search_end();
|
||||
|
||||
// UE interface
|
||||
void attach_request();
|
||||
|
||||
void deattach_request();
|
||||
|
||||
private:
|
||||
|
|
|
@ -177,8 +177,8 @@ private:
|
|||
|
||||
// PHY interface
|
||||
void in_sync();
|
||||
|
||||
void out_of_sync();
|
||||
void earfcn_end();
|
||||
void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
|
||||
|
||||
// MAC interface
|
||||
|
|
|
@ -61,6 +61,7 @@ public:
|
|||
// NAS interface
|
||||
void get_imsi_vec(uint8_t* imsi_, uint32_t n);
|
||||
void get_imei_vec(uint8_t* imei_, uint32_t n);
|
||||
int get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id);
|
||||
|
||||
void generate_authentication_response(uint8_t *rand,
|
||||
uint8_t *autn_enb,
|
||||
|
@ -119,6 +120,8 @@ private:
|
|||
uint8_t k_asme[32];
|
||||
uint8_t k_enb[32];
|
||||
|
||||
bool initiated;
|
||||
|
||||
};
|
||||
|
||||
} // namespace srsue
|
||||
|
|
|
@ -307,7 +307,6 @@ void mac::new_grant_ul(mac_interface_phy::mac_grant_t grant, mac_interface_phy::
|
|||
|
||||
void mac::new_grant_ul_ack(mac_interface_phy::mac_grant_t grant, bool ack, mac_interface_phy::tb_action_ul_t* action)
|
||||
{
|
||||
log_h->info("new_grant_ul_ack\n");
|
||||
int tbs = ul_harq.get_current_tbs(tti);
|
||||
ul_harq.new_grant_ul_ack(grant, ack, action);
|
||||
if (!ack) {
|
||||
|
|
|
@ -171,6 +171,7 @@ void phch_recv::radio_error() {
|
|||
|
||||
// Need to find a method to effectively reset radio, reloading the driver does not work
|
||||
//radio_h->reset();
|
||||
radio_h->stop();
|
||||
|
||||
fprintf(stdout, "Error while receiving samples. Restart srsUE\n");
|
||||
exit(-1);
|
||||
|
@ -478,6 +479,7 @@ void phch_recv::cell_search_inc()
|
|||
if (cur_earfcn_index >= 0) {
|
||||
if (cur_earfcn_index >= (int) earfcn.size() - 1) {
|
||||
cur_earfcn_index = 0;
|
||||
rrc->earfcn_end();
|
||||
}
|
||||
}
|
||||
Info("SYNC: Cell Search idx %d/%d\n", cur_earfcn_index, earfcn.size());
|
||||
|
|
|
@ -922,16 +922,16 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
|
|||
#ifdef LOG_EXECTIME
|
||||
gettimeofday(&logtime_start[2], NULL);
|
||||
get_time_interval(logtime_start);
|
||||
snprintf(timestr, 64, ", total_time=%4d us", (int) logtime_start[0].tv_usec);
|
||||
snprintf(timestr, 64, ", tot_time=%4d us", (int) logtime_start[0].tv_usec);
|
||||
#endif
|
||||
|
||||
Info("PUSCH: tti_tx=%d, n_prb=%d, rb_start=%d, tbs=%d, mod=%d, mcs=%d, rv_idx=%d, ack=%s, ri=%s, cfo=%.1f Hz%s\n",
|
||||
TTI_TX(tti),
|
||||
grant->L_prb, grant->n_prb[0],
|
||||
grant->mcs.tbs/8, grant->mcs.mod, grant->mcs.idx, rv,
|
||||
Info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n",
|
||||
(tti+4)%10240,
|
||||
grant->n_prb[0], grant->n_prb[0]+grant->L_prb,
|
||||
grant->mcs.tbs/8, grant->mcs.idx, rv,
|
||||
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no",
|
||||
uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no",
|
||||
cfo*15000, timestr);
|
||||
cfo*15, timestr);
|
||||
|
||||
// Store metrics
|
||||
ul_metrics.mcs = grant->mcs.idx;
|
||||
|
@ -966,23 +966,23 @@ void phch_worker::encode_pucch()
|
|||
memcpy(&t[2], &logtime_start[2], sizeof(struct timeval));
|
||||
get_time_interval(logtime_start);
|
||||
get_time_interval(t);
|
||||
snprintf(timestr, 64, ", enc_time=%d, total_time=%d us", (int) t[0].tv_usec, (int) logtime_start[0].tv_usec);
|
||||
snprintf(timestr, 64, ", tot_time=%d us", (int) logtime_start[0].tv_usec);
|
||||
#endif
|
||||
|
||||
float tx_power = srslte_ue_ul_pucch_power(&ue_ul, phy->pathloss, ue_ul.last_pucch_format, uci_data.uci_cqi_len, uci_data.uci_ack_len);
|
||||
float gain = set_power(tx_power);
|
||||
|
||||
Info("PUCCH: tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, pmi=%s%s, sr=%s, cfo=%.1f Hz%s\n",
|
||||
TTI_TX(tti),
|
||||
last_dl_pdcch_ncce, ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb,
|
||||
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no",
|
||||
uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"",
|
||||
uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no",
|
||||
uci_data.uci_pmi_len>0?(uci_data.uci_pmi[1]?"1":"0"):"no",
|
||||
uci_data.uci_pmi_len>0?(uci_data.uci_pmi[0]?"1":"0"):"",
|
||||
uci_data.scheduling_request?"yes":"no",
|
||||
cfo*15000, timestr);
|
||||
}
|
||||
Info("PUCCH: tti_tx=%d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, pmi=%s%s, sr=%s, cfo=%.1f KHz%s\n",
|
||||
(tti+4)%10240,
|
||||
ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb,
|
||||
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no",
|
||||
uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"",
|
||||
uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no",
|
||||
uci_data.uci_pmi_len>0?(uci_data.uci_pmi[1]?"1":"0"):"no",
|
||||
uci_data.uci_pmi_len>0?(uci_data.uci_pmi[0]?"1":"0"):"",
|
||||
uci_data.scheduling_request?"yes":"no",
|
||||
cfo*15, timestr);
|
||||
}
|
||||
|
||||
if (uci_data.scheduling_request) {
|
||||
phy->sr_enabled = false;
|
||||
|
@ -1002,7 +1002,7 @@ void phch_worker::encode_srs()
|
|||
#ifdef LOG_EXECTIME
|
||||
gettimeofday(&logtime_start[2], NULL);
|
||||
get_time_interval(logtime_start);
|
||||
snprintf(timestr, 64, ", total_time=%4d us", (int) logtime_start[0].tv_usec);
|
||||
snprintf(timestr, 64, ", tot_time=%4d us", (int) logtime_start[0].tv_usec);
|
||||
#endif
|
||||
|
||||
float tx_power = srslte_ue_ul_srs_power(&ue_ul, phy->pathloss);
|
||||
|
|
|
@ -181,11 +181,10 @@ bool ue::init(all_args_t *args_)
|
|||
rlc.init(&pdcp, &rrc, this, &rlc_log, &mac, 0 /* RB_ID_SRB0 */);
|
||||
pdcp.init(&rlc, &rrc, &gw, &pdcp_log, 0 /* RB_ID_SRB0 */, SECURITY_DIRECTION_UPLINK);
|
||||
|
||||
usim.init(&args->usim, &usim_log);
|
||||
nas.init(&usim, &rrc, &gw, &nas_log, 1 /* RB_ID_SRB1 */);
|
||||
gw.init(&pdcp, &nas, &gw_log, 3 /* RB_ID_DRB1 */);
|
||||
|
||||
usim.init(&args->usim, &usim_log);
|
||||
|
||||
rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &mac, &rrc_log);
|
||||
rrc.set_ue_category(atoi(args->expert.ue_cateogry.c_str()));
|
||||
|
||||
|
|
|
@ -50,8 +50,12 @@ void nas::init(usim_interface_nas *usim_,
|
|||
nas_log = nas_log_;
|
||||
state = EMM_STATE_DEREGISTERED;
|
||||
plmn_selection = PLMN_NOT_SELECTED;
|
||||
home_plmn.mcc = 61441; // This is 001
|
||||
home_plmn.mnc = 65281; // This is 01
|
||||
|
||||
if (usim->get_home_plmn_id(&home_plmn)) {
|
||||
nas_log->error("Getting Home PLMN Id from USIM. Defaulting to 001-01\n");
|
||||
home_plmn.mcc = 61441; // This is 001
|
||||
home_plmn.mnc = 65281; // This is 01
|
||||
}
|
||||
cfg = cfg_;
|
||||
}
|
||||
|
||||
|
@ -64,6 +68,7 @@ emm_state_t nas::get_state() {
|
|||
/*******************************************************************************
|
||||
UE interface
|
||||
*******************************************************************************/
|
||||
|
||||
void nas::attach_request() {
|
||||
nas_log->info("Attach Request\n");
|
||||
if (state == EMM_STATE_DEREGISTERED) {
|
||||
|
@ -72,7 +77,7 @@ void nas::attach_request() {
|
|||
nas_log->info("Starting PLMN Search...\n");
|
||||
rrc->plmn_search();
|
||||
} else if (plmn_selection == PLMN_SELECTED) {
|
||||
nas_log->info("Selecting PLMN %s\n", plmn_id_to_c_str(current_plmn).c_str());
|
||||
nas_log->info("Selecting PLMN %s\n", plmn_id_to_string(current_plmn).c_str());
|
||||
rrc->plmn_select(current_plmn);
|
||||
selecting_plmn = current_plmn;
|
||||
}
|
||||
|
@ -96,25 +101,49 @@ RRC interface
|
|||
|
||||
void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) {
|
||||
|
||||
// Store PLMN if not registered
|
||||
// Check if already registered
|
||||
for (uint32_t i=0;i<known_plmns.size();i++) {
|
||||
if (plmn_id.mcc == known_plmns[i].mcc && plmn_id.mnc == known_plmns[i].mnc) {
|
||||
nas_log->info("Detected known PLMN %s\n", plmn_id_to_c_str(plmn_id).c_str());
|
||||
nas_log->info("Found known PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str());
|
||||
if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) {
|
||||
nas_log->info("Connecting Home PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str());
|
||||
rrc->plmn_select(plmn_id);
|
||||
selecting_plmn = plmn_id;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
nas_log->info("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_c_str(plmn_id).c_str(),
|
||||
|
||||
// Save if new PLMN
|
||||
known_plmns.push_back(plmn_id);
|
||||
|
||||
nas_log->info("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(plmn_id).c_str(),
|
||||
tracking_area_code);
|
||||
nas_log->console("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_c_str(plmn_id).c_str(),
|
||||
nas_log->console("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(plmn_id).c_str(),
|
||||
tracking_area_code);
|
||||
|
||||
if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) {
|
||||
rrc->plmn_select(plmn_id);
|
||||
selecting_plmn = plmn_id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// RRC indicates that the UE has gone through all EARFCN and finished PLMN selection
|
||||
void nas::plmn_search_end() {
|
||||
if (known_plmns.size() > 0) {
|
||||
nas_log->info("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n",
|
||||
plmn_id_to_string(home_plmn).c_str(),
|
||||
plmn_id_to_string(known_plmns[0]).c_str());
|
||||
|
||||
nas_log->console("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n",
|
||||
plmn_id_to_string(home_plmn).c_str(),
|
||||
plmn_id_to_string(known_plmns[0]).c_str());
|
||||
|
||||
rrc->plmn_select(known_plmns[0]);
|
||||
} else {
|
||||
nas_log->debug("Finished searching PLMN in current EARFCN set but no networks were found.\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool nas::is_attached() {
|
||||
|
|
|
@ -177,7 +177,7 @@ void rrc::run_thread() {
|
|||
case RRC_STATE_PLMN_SELECTION:
|
||||
plmn_select_timeout++;
|
||||
if (plmn_select_timeout >= RRC_PLMN_SELECT_TIMEOUT) {
|
||||
rrc_log->info("RRC PLMN Search: timeout expired. Searching again\n");
|
||||
rrc_log->info("RRC PLMN Search: timeout expired\n");
|
||||
phy->cell_search_stop();
|
||||
sleep(1);
|
||||
rrc_log->console("\nRRC PLMN Search: timeout expired. Searching again\n");
|
||||
|
@ -369,7 +369,7 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
|
|||
state = RRC_STATE_CELL_SELECTING;
|
||||
select_cell_timeout = 0;
|
||||
} else {
|
||||
rrc_log->info("PLMN %s selected\n", plmn_id_to_c_str(plmn_id).c_str());
|
||||
rrc_log->info("PLMN Id=%s selected\n", plmn_id_to_string(plmn_id).c_str());
|
||||
// Sort cells according to RSRP
|
||||
|
||||
selected_plmn_id = plmn_id;
|
||||
|
@ -427,10 +427,12 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
|
|||
|
||||
if (!known_cells[i].has_valid_sib1) {
|
||||
si_acquire_state = SI_ACQUIRE_SIB1;
|
||||
} else {
|
||||
} else if (state == RRC_STATE_PLMN_SELECTION) {
|
||||
for (uint32_t i = 0; i < current_cell->sib1.N_plmn_ids; i++) {
|
||||
nas->plmn_found(current_cell->sib1.plmn_id[i].id, current_cell->sib1.tracking_area_code);
|
||||
}
|
||||
usleep(5000);
|
||||
phy->cell_search_next();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -454,6 +456,15 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
|
|||
cell.earfcn, cell.rsrp);
|
||||
}
|
||||
|
||||
// PHY indicates that has gone through all known EARFCN
|
||||
void rrc::earfcn_end() {
|
||||
rrc_log->debug("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]);
|
||||
|
||||
// If searching for PLMN, indicate NAS we scanned all frequencies
|
||||
if (state == RRC_STATE_PLMN_SELECTION) {
|
||||
nas->plmn_search_end();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -25,13 +25,15 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <sstream>
|
||||
#include "upper/usim.h"
|
||||
#include "srslte/common/bcd_helpers.h"
|
||||
|
||||
using namespace srslte;
|
||||
|
||||
namespace srsue{
|
||||
|
||||
usim::usim()
|
||||
usim::usim() : initiated(false)
|
||||
{}
|
||||
|
||||
void usim::init(usim_args_t *args, srslte::log *usim_log_)
|
||||
|
@ -91,6 +93,7 @@ void usim::init(usim_args_t *args, srslte::log *usim_log_)
|
|||
if("xor" == args->algo) {
|
||||
auth_algo = auth_algo_xor;
|
||||
}
|
||||
initiated = true;
|
||||
}
|
||||
|
||||
void usim::stop()
|
||||
|
@ -102,6 +105,11 @@ void usim::stop()
|
|||
|
||||
void usim::get_imsi_vec(uint8_t* imsi_, uint32_t n)
|
||||
{
|
||||
if (!initiated)
|
||||
{
|
||||
usim_log->error("Getting IMSI: USIM not initiated\n");
|
||||
return;
|
||||
}
|
||||
if(NULL == imsi_ || n < 15)
|
||||
{
|
||||
usim_log->error("Invalid parameters to get_imsi_vec");
|
||||
|
@ -111,13 +119,18 @@ void usim::get_imsi_vec(uint8_t* imsi_, uint32_t n)
|
|||
uint64_t temp = imsi;
|
||||
for(int i=14;i>=0;i--)
|
||||
{
|
||||
imsi_[i] = temp % 10;
|
||||
temp /= 10;
|
||||
imsi_[i] = temp % 10;
|
||||
temp /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
void usim::get_imei_vec(uint8_t* imei_, uint32_t n)
|
||||
{
|
||||
if (!initiated)
|
||||
{
|
||||
usim_log->error("Getting IMEI: USIM not initiated\n");
|
||||
return;
|
||||
}
|
||||
if(NULL == imei_ || n < 15)
|
||||
{
|
||||
usim_log->error("Invalid parameters to get_imei_vec");
|
||||
|
@ -127,11 +140,53 @@ void usim::get_imei_vec(uint8_t* imei_, uint32_t n)
|
|||
uint64 temp = imei;
|
||||
for(int i=14;i>=0;i--)
|
||||
{
|
||||
imei_[i] = temp % 10;
|
||||
temp /= 10;
|
||||
imei_[i] = temp % 10;
|
||||
temp /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
int usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id)
|
||||
{
|
||||
if (!initiated)
|
||||
{
|
||||
usim_log->error("Getting Home PLMN Id: USIM not initiated\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mcc_len = 3;
|
||||
int mnc_len = 2;
|
||||
|
||||
uint8_t imsi_vec[15];
|
||||
get_imsi_vec(imsi_vec, 15);
|
||||
|
||||
std::ostringstream mcc_str, mnc_str;
|
||||
|
||||
for (int i=0;i<mcc_len;i++) {
|
||||
mcc_str << (int) imsi_vec[i];
|
||||
}
|
||||
|
||||
// US MCC uses 3 MNC digits
|
||||
if (!mcc_str.str().compare("310") ||
|
||||
!mcc_str.str().compare("311") ||
|
||||
!mcc_str.str().compare("312") ||
|
||||
!mcc_str.str().compare("313") ||
|
||||
!mcc_str.str().compare("316"))
|
||||
{
|
||||
mnc_len = 3;
|
||||
}
|
||||
for (int i=mcc_len;i<mcc_len+mnc_len;i++) {
|
||||
mnc_str << (int) imsi_vec[i];
|
||||
}
|
||||
|
||||
string_to_mcc(mcc_str.str(), &home_plmn_id->mcc);
|
||||
string_to_mnc(mnc_str.str(), &home_plmn_id->mnc);
|
||||
|
||||
usim_log->info("Read Home PLMN Id=%s\n",
|
||||
plmn_id_to_string(*home_plmn_id).c_str());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usim::generate_authentication_response(uint8_t *rand,
|
||||
uint8_t *autn_enb,
|
||||
uint16_t mcc,
|
||||
|
|
Loading…
Reference in New Issue