diff --git a/AUTHORS b/AUTHORS old mode 100644 new mode 100755 index 93c994b..6deca50 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,4 @@ Ben Wojtowicz, bwojtowi@gmail.com -Andrew Murphy, andrew.murphy@rd.bbc.co.uk (DCI 1C Unpack) +Andrew Murphy, andrew.murphy@rd.bbc.co.uk +Ziming He, ziminghe83@gmail.com +Przemek Bereski, przemobe@users.sourceforge.net diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100644 new mode 100755 index 17c9f3d..48e7880 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ ######################################################################## cmake_minimum_required(VERSION 2.6) project(openLTE CXX C) -set(openLTE_version 0.14.0) +set(openLTE_version 0.20.5) enable_testing() #select the release build type by default to get optimization flags @@ -92,7 +92,9 @@ set(GR_REQUIRED_COMPONENTS RUNTIME BLOCKS FILTER PMT) find_package(Gnuradio "3.7.0") find_package(GnuradioOsmosdr) find_package(Uhd) +find_package(LibbladeRF) find_package(FFTW3F) +find_package(MbedTLS) if(NOT GNURADIO_RUNTIME_FOUND) message(FATAL_ERROR "GNURadio required to compile openLTE") @@ -106,6 +108,10 @@ if(NOT UHD_FOUND) message(FATAL_ERROR "UHD required to compile openLTE (http://code.ettus.com/redmine/ettus/projects/uhd/wiki)") endif() +if(NOT LIBBLADERF_FOUND) + message(FATAL_ERROR "LibbladeRF required to compile openLTE") +endif() + if(NOT FFTW3F_FOUND) message(FATAL_ERROR "FFTW3 required to compile openLTE") endif() diff --git a/COPYING b/COPYING old mode 100644 new mode 100755 diff --git a/ChangeLog b/ChangeLog old mode 100644 new mode 100755 index b3b2602..0048605 --- a/ChangeLog +++ b/ChangeLog @@ -110,3 +110,164 @@ v00.14.00 Split LIBLTE_MSG_STRUCT into bit and byte messages, fixed a bug wh QoS, uplink scheduling, RRC and MME NAS message handling, and RLC AM processing support, omitting the path from __FILE__, and deleteing users on C-RNTI expiration in LTE_fdd_enodeb. +v00.14.01 Pulled in patches from Mike Peters to fix an uninitialized N_bits + value in liblte, Tim O'Shea to properly reference UHD libraries and + include directories for cmake, Jeff Long to fix a mutex double + unlock bug, Jeff Long to optimally set the master clock rate for + USRP B2X0 in the LTE_fdd_dl_scan application, and added clock source + as a configurable parameter in the LTE_fdd_enodeb application. +v00.15.00 Added make requirement for polarSSL, common, pdcp, and security + portions of liblte, more decoding/encoding to liblte_mme and + liblte_rrc, NACK support to liblte_rlc, and many changes to + LTE_fdd_enodeb (limit PCAP output, authentication vector support, + HSS interface support, message parsers/senders and state machines + for MME, RRC command messages, transmit functionality for PDCP, + RLC, and RRC, and refactoring of user identities). +v00.16.00 Added more MME decoding and encoding and security functions for + key generation and EIA2 to the LTE library. Added authentication, + security mode, and sequence number resynch support to MME/HSS, + added read only parameters for UL EARFCN, DL center frequency, and + UL center frequency, fixed bugs with stop and t_poll_retransmit, + and combined the contention resolution identity and first DL RLC + message in LTE_fdd_enodeb. +v00.17.00 Added more MME and RRC decoding and encoding and integrity protection + of PDCP control messages in the LTE library. Added configuration + and user file support, PDCP security, RRC security mode command, + SRB2 setup, RRC connection reconfiguration, MME EMM attach, MME + ESM default bearer setup, and M-TMSI assignment to LTE_fdd_enodeb. +v00.17.01 Added SIB13 packing and printing for LTE_fdd_dl_file_scan and + pulled in a patch from Andrew Murphy to add SIB13 unpacking and + printing for LTE_fdd_dl_scan. +v00.18.00 Added IP packet support to LTE_fdd_enodeb. Specifically, added the + liblte prefix to value_2_bits and bits_2_value, converted everything + except PHY and RRC to byte message struct, added more MME decoding + and encoding, added PDCP user plane support, added RLC UMD support, + and fixed a bug in RRC connection reesablishment pack and unpack + (thanks to Paul Sutton for tracking this down) in the LTE library. + Added regeneration of eNodeB security data in HSS, service request, + service reject, and activate dedicated EPS bearer context request + support in MME, timer reset, and IP gateway support, using the + latest LTE library, and refactored C-RNTI assignement and release + in LTE_fdd_enodeb. +v00.18.01 Added more MME encoding and decoding to the LTE library, pulled in + a patch from Ruben Merz to add USRP X300 support for LTE_fdd_dl_scan + and LTE_fdd_enodeb, added to enodeb_nat_script.sh, added delayed + user deletion, ol extension to all message queues, ability to send + EMM information message, and QoS for default data services to + LTE_fdd_enodeb. +v00.18.02 Fixed several bugs in LTE_fdd_enodeb. Specifically, cleaned up the + Time Zone and Time IE and added C-RNTI support to + get_tbs_mcs_and_N_prb_for_dl in liblte, added asymmetric QoS support, + dynamically determining MCS for downlink data, sending EMM information + message, added more time spec information in radio debug, copying + SRB1 PDCP config to SRB2, fixed a UMD reassembly bug, and did a hack + to get around a crash when releasing a C-RNTI in LTE_fdd_enodeb. +v00.18.03 Added more MME encoding and decoding, RLC UMD header extension + support, and higher order modulation scheme support to PHY in the LTE + library, split the error enum into common.h, moved to a new message + queue using semaphores and circular buffers, added IP PCAP support, + split UL/DL QoS TTI frequency, added user reset to RB class, added + RLC UMD multiple data support, added UTC timestamps to the debug + log port, added higher order modulation scheme support in MAC, fixed + C-RNTI assign/release management, changed RTS timing, fixed user + switch in MME/RRC, added clear RB support and fixed copy RB in the + user class for LTE_fdd_enodeb. +v00.18.04 Fixed long BSR CE and added extended power headroom CE support, added + PDCP data PDU with short SN support, and added header extension + handling to RLC AMD to LTE library, added UmTRX support to + LTE_fdd_dl_scan, fixed the start/stop/start issues by closing the TUN + device on stop, fixed the RTS issues, added a mutex to the message + queue circular buffer, fixed uninitialized variables in the configuration + database, added header extension/multiple data support for RLC AMD, + added detach handling, and added a common routine for formatting time to + LTE_fdd_enodeb. +v00.19.00 Removed rb_id from all MME pack routines (thanks to Przemek for finding + this), fixed a bug with the default value of filter_coeff in + LIBLTE_RRC_UL_POWER_CONTROL_DEDICATED_STRUCT (thanks to Paul Sutton for + finding this), added the length indicator for eps_mobile_id (thanks to + Paul Sutton for finding this), added an error return for dci_1a_unpack + (thanks to Joel Carlson for the suggestion), properly initializing + vd_w_metric (thanks for ziminghe for finding this), and limiting PUSCH + allocations to 10 PRBs for performance reasons in the LTE library, added + TX and RX gains to the config file, combined UL and DL schedule messages + into a single PHY schedule message, moved QoS structure from RB class + to the user class, fixed bugs related to the RLC AM TX and RX buffers, + changed the default timer alignment timer to 10240 subframes, removed + boost::lexical_casts from HSS, moved the dedicated bearer QoS to 9, and + moved DRBs to RLC AMD mode in LTE_fdd_enodeb. +v00.19.01 Added support for all ID types for the mobile identity IE in MME, added + support for more PDU types in PDCP, added defines for sizes of fixed + arrays in LIBLTE_PHY_STRUCT, fixed the order of sizes for rate match + and unmatch arrays in LIBLTE_PHY_STRUCT (thanks to Ziming He), added + return values for liblte_phy_get_n_cce (thanks to Damian Jarek) and + liblte_rlc_unpack_status_pdu (thanks to Mikhail Gudkov) in the LTE + library, added a scoped lock RAII class for sem_t and pthread_mutex_t + in the tools library, changed from using boost::mutex to pthread_mutex_t + and_sem_t throughout, added helper functions in MAC, changed user + deletion and C-RNTI release procedures, properly initializing SIB + scheduling info, properly construct MNC (thanks to Mikhail Gudkov), + fixed an issue with RTS response in MAC, properly initialized PHY + allocation structure in MAC (thanks to Markus Grab), fixed the updating + of VT(A) in the RLC retransmission buffer, and changed the QoS parameters + for default data in LTE_fdd_enodeb. +v00.19.02 Pulled in unit tests for the turbo decoder from Ziming He, optimized + the PBCH detection algorithm (thanks to Ziming He), and fixed the setting + of id for IMEISV in Mobile Idenity IE (thanks to Mikhail Gudkov) in the + LTE library, added the ability to print all registered users, removed + extra boost includes, added an RRC connection reestablishment state + machine, added a UE inactivity timer, actually properly constructing + MNC (thanks to Mikhail Gudkov), memcpy-ing IP packet headers instead + of typecasting (thanks to Damian Jarek), initialized present flags + and changed packet filter evaluation precedence in activate dedicated + EPS bearer context (thanks to Pedro Batista), moved the message queue + empty error to a warning, and properly updating the user list iterator + after erasing a user (thanks to Damian Jarek). +v00.19.03 Added support for PUCCH decode in liblte, added support for H-ARQ and + PUCCH in LTE_fdd_enodeb, and fixed a bug related to improper cleanup + of the inactivity timer in LTE_fdd_enodeb +v00.19.04 Fixed the calculation of n_prime_p in generate_dmrs_pucch. +v00.20.00 Increased the maximum messages size, fixed extended power headroom MAC + CE, added classmark3 support, added tracking area update request support, + fixed the fill bits in packing mobile ID IE for IMEISV and the length in + unpacking UE security capabilities IE (thanks to Przemek Bereski for + finding this), allowing NULL to be passed for key_256 in service reject + message packing (thanks to Przemek Bereski and Peter Nguyen for finding + this), added PDCCH size defines, added an error return to DCI 1C unpack, + clearing punctered turbo decode bits before decoding, added AMD PDU + segment support, padded all RRC enums to powers of 2, added support for + several RRC IEs and messages (with the help of Przemek Bereski) in the + LTE library, restructured the radio classes to ease the addition of new + radio types, set the processor affinity to allow the PHY/Radio to run + on a particular core, fixed memcpy lengths in MAC, fixed bugs in + print_all_users (thanks to Sultan Qasim Khan for finding this) and when + receiving a service request message for a non-existent user (thanks to + Peter Nguyen for finding this), fixed a long standing PHY bug that was + including UL PDCCH allocations in a check of DL PRB usage, added error + logging for received AMD PDU segments, increased the DL datarate for + default data QoS, using C-RNTI when no IMSI/IMEI are available for + printing an attached user, Przemek Bereski added UE capability enquiry + and UE capability information support and bladeRF support. +v00.20.01 Reworked the MAC RTS handling logic and limited the number of HARQ + retransmissions in LTE_fdd_enodeb. +v00.20.02 Changed the QoS DL bytes per subframe for default data to ensure QPSK + only for 5MHz other DL modulation schemes seem to not be functioning + correctly. +v00.20.03 Properly discarding sequence type extensions in liblte_rrc, properly + typecasting for bladerf_get_timestamp() in LTE_fdd_enodeb_radio, and + updated enodeb_nat_script.sh to be more generic with ethernet + interfaces. +v00.20.04 Added band 26, 27, and 28 support (thanks to Jeremy Quirke), fixed the + length skipping in liblte_mme_unpack_pdn_address_ie (thanks to Przemek + Bereski), and fixed the turbo encoder tail bits (thanks to Laurent + Louf and Jeremy Quirke) in the LTE library and fixed the handling of + multiple RLC AMD PDUs throughout. +v00.20.05 Added two codeword support, refactored PUCCH channel decoding for 1, + 1A, and 1B, added SR configuration index mapping, added liblte_common + unit tests, and properly handling FI fields for multiple AMD PDUs in + the LTE library, added helper functions and interprocess message queue + support to the tools library, added SR support, moved GW, MME, and PDCP + away from the singleton pattern, added direct IPC to a UE for MAC and + PHY, removed QOS and fixed UL scheduling in favor of SR and BSR based + UL scheduling, and refactored the AMD reception buffer to handle more + than one PDU per SN in LTE_fdd_enodeb, and fixed a typo in + lte_pucch_demod.m. diff --git a/LTE_fdd_dl_file_gen/CMakeLists.txt b/LTE_fdd_dl_file_gen/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/LTE_fdd_dl_file_gen/hdr/LTE_fdd_dl_fg_api.h b/LTE_fdd_dl_file_gen/hdr/LTE_fdd_dl_fg_api.h old mode 100644 new mode 100755 diff --git a/LTE_fdd_dl_file_gen/hdr/LTE_fdd_dl_fg_samp_buf.h b/LTE_fdd_dl_file_gen/hdr/LTE_fdd_dl_fg_samp_buf.h old mode 100644 new mode 100755 diff --git a/LTE_fdd_dl_file_gen/src/LTE_fdd_dl_fg.i b/LTE_fdd_dl_file_gen/src/LTE_fdd_dl_fg.i old mode 100644 new mode 100755 diff --git a/LTE_fdd_dl_file_gen/src/LTE_fdd_dl_fg_samp_buf.cc b/LTE_fdd_dl_file_gen/src/LTE_fdd_dl_fg_samp_buf.cc old mode 100644 new mode 100755 index a305738..bdbb23d --- a/LTE_fdd_dl_file_gen/src/LTE_fdd_dl_fg_samp_buf.cc +++ b/LTE_fdd_dl_file_gen/src/LTE_fdd_dl_fg_samp_buf.cc @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2012-2014 Ben Wojtowicz + Copyright 2012-2014, 2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -47,6 +47,8 @@ 03/26/2014 Ben Wojtowicz Using the latest LTE library. 04/12/2014 Ben Wojtowicz Using the latest LTE library. 05/04/2014 Ben Wojtowicz Added PHICH support. + 11/01/2014 Ben Wojtowicz Using the latest LTE library. + 07/29/2017 Ben Wojtowicz Using the latest LTE library. *******************************************************************************/ @@ -138,8 +140,8 @@ LTE_fdd_dl_fg_samp_buf::LTE_fdd_dl_fg_samp_buf(size_t out_size_val) sib1.intra_freq_reselection = LIBLTE_RRC_INTRA_FREQ_RESELECTION_ALLOWED; sib1.si_window_length = LIBLTE_RRC_SI_WINDOW_LENGTH_MS2; si_win_len = 2; - sib1.sf_assignment = LIBLTE_RRC_SUBFRAME_ASSIGNMENT_0; - sib1.special_sf_patterns = LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_0; + sib1.tdd_cnfg.sf_assignment = LIBLTE_RRC_SUBFRAME_ASSIGNMENT_0; + sib1.tdd_cnfg.special_sf_patterns = LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_0; sib1.cell_id = 0; sib1.csg_id = 0; sib1.tracking_area_code = 0; @@ -378,8 +380,8 @@ int32 LTE_fdd_dl_fg_samp_buf::work(int32 noutput_items, bcch_dlsch_msg.sibs[0].sib_type = LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1; memcpy(&bcch_dlsch_msg.sibs[0].sib, &sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT)); liblte_rrc_pack_bcch_dlsch_msg(&bcch_dlsch_msg, - &pdcch.alloc[pdcch.N_alloc].msg); - liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg.N_bits, + &pdcch.alloc[pdcch.N_alloc].msg[0]); + liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg[0].N_bits, subframe.num, N_rb_dl, LIBLTE_MAC_SI_RNTI, @@ -426,10 +428,10 @@ int32 LTE_fdd_dl_fg_samp_buf::work(int32 noutput_items, } } liblte_rrc_pack_bcch_dlsch_msg(&bcch_dlsch_msg, - &pdcch.alloc[pdcch.N_alloc].msg); + &pdcch.alloc[pdcch.N_alloc].msg[0]); // FIXME: This was a hack to allow SIB2 decoding with 1.4MHz BW due to overlap with MIB - if(LIBLTE_SUCCESS == liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg.N_bits, + if(LIBLTE_SUCCESS == liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg[0].N_bits, subframe.num, N_rb_dl, LIBLTE_MAC_SI_RNTI, @@ -476,8 +478,8 @@ int32 LTE_fdd_dl_fg_samp_buf::work(int32 noutput_items, if(0 != bcch_dlsch_msg.N_sibs) { liblte_rrc_pack_bcch_dlsch_msg(&bcch_dlsch_msg, - &pdcch.alloc[pdcch.N_alloc].msg); - liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg.N_bits, + &pdcch.alloc[pdcch.N_alloc].msg[0]); + liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg[0].N_bits, subframe.num, N_rb_dl, LIBLTE_MAC_SI_RNTI, @@ -497,8 +499,8 @@ int32 LTE_fdd_dl_fg_samp_buf::work(int32 noutput_items, // Add test load if(0 == pdcch.N_alloc) { - pdcch.alloc[0].msg.N_bits = 0; - pdcch.alloc[0].N_prb = 0; + pdcch.alloc[0].msg[0].N_bits = 0; + pdcch.alloc[0].N_prb = 0; liblte_phy_get_tbs_mcs_and_n_prb_for_dl(1480, subframe.num, N_rb_dl, @@ -508,8 +510,8 @@ int32 LTE_fdd_dl_fg_samp_buf::work(int32 noutput_items, &max_N_prb); while(pdcch.alloc[0].N_prb < (uint32)((float)(max_N_prb*percent_load)/100.0)) { - pdcch.alloc[0].msg.N_bits += 8; - liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[0].msg.N_bits, + pdcch.alloc[0].msg[0].N_bits += 8; + liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[0].msg[0].N_bits, subframe.num, N_rb_dl, LIBLTE_MAC_P_RNTI, @@ -517,9 +519,9 @@ int32 LTE_fdd_dl_fg_samp_buf::work(int32 noutput_items, &pdcch.alloc[0].mcs, &pdcch.alloc[0].N_prb); } - for(i=0; isystem_info_value_tag) { printf("\tSystem Info value tag changed\n"); - sib1_printed = false; - sib2_printed = false; - sib3_printed = false; - sib4_printed = false; - sib5_printed = false; - sib6_printed = false; - sib7_printed = false; - sib8_printed = false; + sib1_printed = false; + sib2_printed = false; + sib3_printed = false; + sib4_printed = false; + sib5_printed = false; + sib6_printed = false; + sib7_printed = false; + sib8_printed = false; + sib13_printed = false; } if(false == sib1_printed) @@ -847,6 +856,9 @@ void LTE_fdd_dl_fs_samp_buf::print_sib1(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT case LIBLTE_RRC_SIB_TYPE_8: sib8_expected = true; break; + case LIBLTE_RRC_SIB_TYPE_13_v920: + sib13_expected = true; + break; } } } @@ -855,8 +867,8 @@ void LTE_fdd_dl_fs_samp_buf::print_sib1(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT printf("\t\t%-40s=%20s\n", "Duplexing Mode", "FDD"); }else{ printf("\t\t%-40s=%20s\n", "Duplexing Mode", "TDD"); - printf("\t\t%-40s=%20s\n", "Subframe Assignment", liblte_rrc_subframe_assignment_text[sib1->sf_assignment]); - printf("\t\t%-40s=%20s\n", "Special Subframe Patterns", liblte_rrc_special_subframe_patterns_text[sib1->special_sf_patterns]); + printf("\t\t%-40s=%20s\n", "Subframe Assignment", liblte_rrc_subframe_assignment_text[sib1->tdd_cnfg.sf_assignment]); + printf("\t\t%-40s=%20s\n", "Special Subframe Patterns", liblte_rrc_special_subframe_patterns_text[sib1->tdd_cnfg.special_sf_patterns]); } printf("\t\t%-40s=%20u\n", "SI Value Tag", sib1->system_info_value_tag); prev_si_value_tag = sib1->system_info_value_tag; @@ -1693,6 +1705,35 @@ void LTE_fdd_dl_fs_samp_buf::print_sib8(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT } } +void LTE_fdd_dl_fs_samp_buf::print_sib13(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13) +{ + uint32 i; + + if(false == sib13_printed) + { + printf("\tSIB13 Decoded:\n"); + + printf("\t\tMBSFN Area Info List R9:\n"); + for(i=0; imbsfn_area_info_list_r9_size; i++) + { + printf("\t\t\t%-40s=%20u\n", "MBSFN Area ID R9", sib13->mbsfn_area_info_list_r9[i].mbsfn_area_id_r9); + printf("\t\t\t%-40s=%20s\n", "Non-MBSFN Region Length", liblte_rrc_non_mbsfn_region_length_text[sib13->mbsfn_area_info_list_r9[i].non_mbsfn_region_length]); + printf("\t\t\t%-40s=%20u\n", "Notification Indicator R9", sib13->mbsfn_area_info_list_r9[i].notification_indicator_r9); + printf("\t\t\t%-40s=%20s\n", "MCCH Repetition Period R9", liblte_rrc_mcch_repetition_period_r9_text[sib13->mbsfn_area_info_list_r9[i].mcch_repetition_period_r9]); + printf("\t\t\t%-40s=%20u\n", "MCCH Offset R9", sib13->mbsfn_area_info_list_r9[i].mcch_offset_r9); + printf("\t\t\t%-40s=%20s\n", "MCCH Modification Period R9", liblte_rrc_mcch_modification_period_r9_text[sib13->mbsfn_area_info_list_r9[i].mcch_modification_period_r9]); + printf("\t\t\t%-40s=%20u\n", "SF Alloc Info R9", sib13->mbsfn_area_info_list_r9[i].sf_alloc_info_r9); + printf("\t\t\t%-40s=%20s\n", "Signalling MCS R9", liblte_rrc_mcch_signalling_mcs_r9_text[sib13->mbsfn_area_info_list_r9[i].signalling_mcs_r9]); + } + + printf("\t\t%-40s=%20s\n", "Repetition Coeff", liblte_rrc_notification_repetition_coeff_r9_text[sib13->mbms_notification_config.repetition_coeff]); + printf("\t\t%-40s=%20u\n", "Offset", sib13->mbms_notification_config.offset); + printf("\t\t%-40s=%20u\n", "SF Index", sib13->mbms_notification_config.sf_index); + + sib13_printed = true; + } +} + void LTE_fdd_dl_fs_samp_buf::print_page(LIBLTE_RRC_PAGING_STRUCT *page) { uint32 i; diff --git a/LTE_fdd_dl_file_scan/src/__init__.py b/LTE_fdd_dl_file_scan/src/__init__.py old mode 100644 new mode 100755 diff --git a/LTE_fdd_dl_scan/CMakeLists.txt b/LTE_fdd_dl_scan/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_flowgraph.h b/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_flowgraph.h old mode 100644 new mode 100755 index a005bd8..d7512a6 --- a/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_flowgraph.h +++ b/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_flowgraph.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2015 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -31,6 +31,10 @@ 11/30/2013 Ben Wojtowicz Added support for bladeRF. 04/12/2014 Ben Wojtowicz Pulled in a patch from Jevgenij for supporting non-B2X0 USRPs. + 12/16/2014 Ben Wojtowicz Pulled in a patch from Ruben Merz to add + USRP X300 support. + 03/11/2015 Ben Wojtowicz Added UmTRX support. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t. *******************************************************************************/ @@ -43,7 +47,6 @@ #include "LTE_fdd_dl_scan_interface.h" #include "LTE_fdd_dl_scan_state_machine.h" -#include #include #include #include @@ -68,6 +71,8 @@ typedef enum{ LTE_FDD_DL_SCAN_HW_TYPE_HACKRF, LTE_FDD_DL_SCAN_HW_TYPE_USRP_B, LTE_FDD_DL_SCAN_HW_TYPE_USRP_N, + LTE_FDD_DL_SCAN_HW_TYPE_UMTRX, + LTE_FDD_DL_SCAN_HW_TYPE_USRP_X, LTE_FDD_DL_SCAN_HW_TYPE_BLADERF, LTE_FDD_DL_SCAN_HW_TYPE_UNKNOWN, }LTE_FDD_DL_SCAN_HW_TYPE_ENUM; @@ -105,9 +110,9 @@ class LTE_fdd_dl_scan_flowgraph osmosdr::source::sptr samp_src; LTE_fdd_dl_scan_state_machine_sptr state_machine; - pthread_t start_thread; - boost::mutex start_mutex; - bool started; + pthread_t start_thread; + pthread_mutex_t start_mutex; + bool started; }; #endif /* __LTE_FDD_DL_SCAN_FLOWGRAPH_H__ */ diff --git a/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_interface.h b/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_interface.h old mode 100644 new mode 100755 index da54702..b00277d --- a/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_interface.h +++ b/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_interface.h @@ -1,6 +1,7 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2015 Ben Wojtowicz + Copyright 2014 Andrew Murphy (SIB13 printing) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +28,8 @@ 02/26/2013 Ben Wojtowicz Created file 07/21/2013 Ben Wojtowicz Added support for decoding SIBs. 06/15/2014 Ben Wojtowicz Added PCAP support. + 09/19/2014 Andrew Murphy Added SIB13 printing. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t. *******************************************************************************/ @@ -40,7 +43,6 @@ #include "liblte_interface.h" #include "liblte_rrc.h" #include "libtools_socket_wrap.h" -#include #include /******************************************************************************* @@ -94,6 +96,7 @@ class LTE_fdd_dl_scan_interface void send_ctrl_sib6_decoded_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_6_STRUCT *sib6, uint32 sfn); void send_ctrl_sib7_decoded_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7_STRUCT *sib7, uint32 sfn); void send_ctrl_sib8_decoded_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT *sib8, uint32 sfn); + void send_ctrl_sib13_decoded_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13, uint32 sfn); void send_ctrl_channel_found_end_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data); void send_ctrl_channel_not_found_msg(void); void send_ctrl_status_msg(LTE_FDD_DL_SCAN_STATUS_ENUM status, std::string msg); @@ -103,7 +106,7 @@ class LTE_fdd_dl_scan_interface static void handle_ctrl_connect(void); static void handle_ctrl_disconnect(void); static void handle_ctrl_error(LIBTOOLS_SOCKET_WRAP_ERROR_ENUM err); - boost::mutex ctrl_mutex; + pthread_mutex_t ctrl_mutex; FILE *pcap_fd; libtools_socket_wrap *ctrl_socket; int16 ctrl_port; @@ -139,7 +142,7 @@ class LTE_fdd_dl_scan_interface void write_enable_pcap(std::string enable_pcap_str); // Variables - boost::mutex dl_earfcn_list_mutex; + pthread_mutex_t dl_earfcn_list_mutex; LIBLTE_INTERFACE_BAND_ENUM band; uint16 current_dl_earfcn; uint16 dl_earfcn_list[65535]; diff --git a/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_state_machine.h b/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_state_machine.h old mode 100644 new mode 100755 diff --git a/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_state_machine_api.h b/LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_state_machine_api.h old mode 100644 new mode 100755 diff --git a/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_flowgraph.cc b/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_flowgraph.cc old mode 100644 new mode 100755 index eb3b9d8..feb233b --- a/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_flowgraph.cc +++ b/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_flowgraph.cc @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2015 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -32,6 +32,12 @@ 11/30/2013 Ben Wojtowicz Added support for bladeRF. 04/12/2014 Ben Wojtowicz Pulled in a patch from Jevgenij for supporting non-B2X0 USRPs. + 07/22/2014 Ben Wojtowicz Pulled in a patch from Jeff Long to optimally + set the master clock rate for USRP B2X0. + 12/16/2014 Ben Wojtowicz Pulled in a patch from Ruben Merz to add + USRP X300 support. + 03/11/2015 Ben Wojtowicz Added UmTRX support. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t. *******************************************************************************/ @@ -40,6 +46,7 @@ *******************************************************************************/ #include "LTE_fdd_dl_scan_flowgraph.h" +#include "libtools_scoped_lock.h" #include "uhd/usrp/multi_usrp.hpp" /******************************************************************************* @@ -57,7 +64,7 @@ *******************************************************************************/ LTE_fdd_dl_scan_flowgraph* LTE_fdd_dl_scan_flowgraph::instance = NULL; -boost::mutex flowgraph_instance_mutex; +static pthread_mutex_t flowgraph_instance_mutex = PTHREAD_MUTEX_INITIALIZER; /******************************************************************************* CLASS IMPLEMENTATIONS @@ -66,7 +73,7 @@ boost::mutex flowgraph_instance_mutex; // Singleton LTE_fdd_dl_scan_flowgraph* LTE_fdd_dl_scan_flowgraph::get_instance(void) { - boost::mutex::scoped_lock lock(flowgraph_instance_mutex); + libtools_scoped_lock lock(flowgraph_instance_mutex); if(NULL == instance) { @@ -77,7 +84,7 @@ LTE_fdd_dl_scan_flowgraph* LTE_fdd_dl_scan_flowgraph::get_instance(void) } void LTE_fdd_dl_scan_flowgraph::cleanup(void) { - boost::mutex::scoped_lock lock(flowgraph_instance_mutex); + libtools_scoped_lock lock(flowgraph_instance_mutex); if(NULL != instance) { @@ -89,29 +96,31 @@ void LTE_fdd_dl_scan_flowgraph::cleanup(void) // Constructor/Destructor LTE_fdd_dl_scan_flowgraph::LTE_fdd_dl_scan_flowgraph() { + pthread_mutex_init(&start_mutex, NULL); started = false; } LTE_fdd_dl_scan_flowgraph::~LTE_fdd_dl_scan_flowgraph() { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_mutex); if(started) { - start_mutex.unlock(); + pthread_mutex_unlock(&start_mutex); stop(); } + pthread_mutex_destroy(&start_mutex); } // Flowgraph bool LTE_fdd_dl_scan_flowgraph::is_started(void) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_mutex); return(started); } LTE_FDD_DL_SCAN_STATUS_ENUM LTE_fdd_dl_scan_flowgraph::start(uint16 dl_earfcn) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_mutex); LTE_fdd_dl_scan_interface *interface = LTE_fdd_dl_scan_interface::get_instance(); uhd::device_addr_t hint; LTE_FDD_DL_SCAN_STATUS_ENUM err = LTE_FDD_DL_SCAN_STATUS_FAIL; @@ -129,11 +138,11 @@ LTE_FDD_DL_SCAN_STATUS_ENUM LTE_fdd_dl_scan_flowgraph::start(uint16 dl_earfcn) osmosdr::source::sptr tmp_src0 = osmosdr::source::make("uhd"); BOOST_FOREACH(const uhd::device_addr_t &dev, uhd::device::find(hint)) { - uhd::usrp::multi_usrp::make(dev)->set_master_clock_rate(30720000); + uhd::usrp::multi_usrp::make(dev)->set_master_clock_rate(15360000); mcr = uhd::usrp::multi_usrp::make(dev)->get_master_clock_rate(); } if(0 != tmp_src0->get_sample_rates().size() && - 1 >= fabs(mcr - 30720000)) + 1 >= fabs(mcr - 15360000)) { hardware_type = LTE_FDD_DL_SCAN_HW_TYPE_USRP_B; samp_src = tmp_src0; @@ -149,25 +158,51 @@ LTE_FDD_DL_SCAN_STATUS_ENUM LTE_fdd_dl_scan_flowgraph::start(uint16 dl_earfcn) hardware_type = LTE_FDD_DL_SCAN_HW_TYPE_USRP_N; samp_src = tmp_src0; }else{ - osmosdr::source::sptr tmp_src1 = osmosdr::source::make("hackrf"); - if(0 != tmp_src1->get_sample_rates().size()) + BOOST_FOREACH(const uhd::device_addr_t &dev, uhd::device::find(hint)) { - hardware_type = LTE_FDD_DL_SCAN_HW_TYPE_HACKRF; - samp_src = tmp_src1; - }else{ - osmosdr::source::sptr tmp_src2 = osmosdr::source::make("bladerf"); - if(0 != tmp_src2->get_sample_rates().size()) + if(dev["type"] == "umtrx") { - hardware_type = LTE_FDD_DL_SCAN_HW_TYPE_BLADERF; - samp_src = tmp_src2; - }else{ - osmosdr::source::sptr tmp_src3 = osmosdr::source::make("rtl=0"); - if(0 != tmp_src3->get_sample_rates().size()) + hardware_type = LTE_FDD_DL_SCAN_HW_TYPE_UMTRX; + samp_src = tmp_src0; + break; + } + } + if(hardware_type == LTE_FDD_DL_SCAN_HW_TYPE_UNKNOWN) + { + tmp_src0.reset(); + tmp_src0 = osmosdr::source::make("uhd,master_clock_rate=184320000"); + BOOST_FOREACH(const uhd::device_addr_t &dev, uhd::device::find(hint)) + { + if(dev["type"] == "x300") + { + hardware_type = LTE_FDD_DL_SCAN_HW_TYPE_USRP_X; + samp_src = tmp_src0; + break; + } + } + if(hardware_type == LTE_FDD_DL_SCAN_HW_TYPE_UNKNOWN) + { + osmosdr::source::sptr tmp_src1 = osmosdr::source::make("hackrf"); + if(0 != tmp_src1->get_sample_rates().size()) { - hardware_type = LTE_FDD_DL_SCAN_HW_TYPE_RTL_SDR; - samp_src = tmp_src3; + hardware_type = LTE_FDD_DL_SCAN_HW_TYPE_HACKRF; + samp_src = tmp_src1; }else{ - samp_src = osmosdr::source::make(); + osmosdr::source::sptr tmp_src2 = osmosdr::source::make("bladerf"); + if(0 != tmp_src2->get_sample_rates().size()) + { + hardware_type = LTE_FDD_DL_SCAN_HW_TYPE_BLADERF; + samp_src = tmp_src2; + }else{ + osmosdr::source::sptr tmp_src3 = osmosdr::source::make("rtl=0"); + if(0 != tmp_src3->get_sample_rates().size()) + { + hardware_type = LTE_FDD_DL_SCAN_HW_TYPE_RTL_SDR; + samp_src = tmp_src3; + }else{ + samp_src = osmosdr::source::make(); + } + } } } } @@ -184,6 +219,12 @@ LTE_FDD_DL_SCAN_STATUS_ENUM LTE_fdd_dl_scan_flowgraph::start(uint16 dl_earfcn) case LTE_FDD_DL_SCAN_HW_TYPE_USRP_N: state_machine = LTE_fdd_dl_scan_make_state_machine(15360000); break; + case LTE_FDD_DL_SCAN_HW_TYPE_UMTRX: + state_machine = LTE_fdd_dl_scan_make_state_machine(7680000); + break; + case LTE_FDD_DL_SCAN_HW_TYPE_USRP_X: + state_machine = LTE_fdd_dl_scan_make_state_machine(15360000); + break; case LTE_FDD_DL_SCAN_HW_TYPE_HACKRF: state_machine = LTE_fdd_dl_scan_make_state_machine(15360000); break; @@ -219,6 +260,18 @@ LTE_FDD_DL_SCAN_STATUS_ENUM LTE_fdd_dl_scan_flowgraph::start(uint16 dl_earfcn) samp_src->set_gain(35); samp_src->set_bandwidth(10000000); break; + case LTE_FDD_DL_SCAN_HW_TYPE_UMTRX: + samp_src->set_sample_rate(13000000); + samp_src->set_gain_mode(false); + samp_src->set_gain(35); + samp_src->set_bandwidth(5000000); + break; + case LTE_FDD_DL_SCAN_HW_TYPE_USRP_X: + samp_src->set_sample_rate(15360000); + samp_src->set_gain_mode(false); + samp_src->set_gain(25); + samp_src->set_bandwidth(10000000); + break; case LTE_FDD_DL_SCAN_HW_TYPE_HACKRF: samp_src->set_sample_rate(15360000); samp_src->set_gain_mode(false); @@ -249,6 +302,11 @@ LTE_FDD_DL_SCAN_STATUS_ENUM LTE_fdd_dl_scan_flowgraph::start(uint16 dl_earfcn) resampler_filter = gr::filter::rational_resampler_base_ccf::make(384, 625, resample_taps); top_block->connect(samp_src, 0, resampler_filter, 0); top_block->connect(resampler_filter, 0, state_machine, 0); + }else if(LTE_FDD_DL_SCAN_HW_TYPE_UMTRX == hardware_type){ + resample_taps = gr::filter::firdes::low_pass(192, 1, 0.00065, 0.0013, gr::filter::firdes::WIN_KAISER, 5); + resampler_filter = gr::filter::rational_resampler_base_ccf::make(192, 325, resample_taps); + top_block->connect(samp_src, 0, resampler_filter, 0); + top_block->connect(resampler_filter, 0, state_machine, 0); }else{ top_block->connect(samp_src, 0, state_machine, 0); } @@ -270,13 +328,13 @@ LTE_FDD_DL_SCAN_STATUS_ENUM LTE_fdd_dl_scan_flowgraph::start(uint16 dl_earfcn) } LTE_FDD_DL_SCAN_STATUS_ENUM LTE_fdd_dl_scan_flowgraph::stop(void) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_mutex); LTE_FDD_DL_SCAN_STATUS_ENUM err = LTE_FDD_DL_SCAN_STATUS_FAIL; if(started) { started = false; - start_mutex.unlock(); + pthread_mutex_unlock(&start_mutex); sleep(1); // Wait for state_machine to exit pthread_cancel(start_thread); pthread_join(start_thread, NULL); @@ -288,7 +346,7 @@ LTE_FDD_DL_SCAN_STATUS_ENUM LTE_fdd_dl_scan_flowgraph::stop(void) } void LTE_fdd_dl_scan_flowgraph::update_center_freq(uint16 dl_earfcn) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_mutex); if(started && NULL != samp_src.get()) diff --git a/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_interface.cc b/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_interface.cc old mode 100644 new mode 100755 index b237a36..d087cf4 --- a/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_interface.cc +++ b/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_interface.cc @@ -1,6 +1,7 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2015, 2017 Ben Wojtowicz + Copyright 2014 Andrew Murphy (SIB13 printing) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +28,10 @@ 02/26/2013 Ben Wojtowicz Created file 07/21/2013 Ben Wojtowicz Added support for decoding SIBs. 06/15/2014 Ben Wojtowicz Added PCAP support. + 09/19/2014 Andrew Murphy Added SIB13 printing. + 11/01/2014 Ben Wojtowicz Using the latest LTE library. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t. + 07/29/2017 Ben Wojtowicz Using the latest tools library. *******************************************************************************/ @@ -37,11 +42,12 @@ #include "LTE_fdd_dl_scan_interface.h" #include "LTE_fdd_dl_scan_flowgraph.h" #include "liblte_mcc_mnc_list.h" +#include "libtools_scoped_lock.h" +#include "libtools_helpers.h" #include #include #include #include -#include #include /******************************************************************************* @@ -62,9 +68,9 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_dl_scan_interface* LTE_fdd_dl_scan_interface::instance = NULL; -boost::mutex interface_instance_mutex; -boost::mutex connect_mutex; +LTE_fdd_dl_scan_interface* LTE_fdd_dl_scan_interface::instance = NULL; +static pthread_mutex_t interface_instance_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t connect_mutex = PTHREAD_MUTEX_INITIALIZER; bool LTE_fdd_dl_scan_interface::ctrl_connected = false; /******************************************************************************* @@ -74,7 +80,7 @@ bool LTE_fdd_dl_scan_interface::ctrl_connected = false; // Singleton LTE_fdd_dl_scan_interface* LTE_fdd_dl_scan_interface::get_instance(void) { - boost::mutex::scoped_lock lock(interface_instance_mutex); + libtools_scoped_lock lock(interface_instance_mutex); if(NULL == instance) { @@ -85,7 +91,7 @@ LTE_fdd_dl_scan_interface* LTE_fdd_dl_scan_interface::get_instance(void) } void LTE_fdd_dl_scan_interface::cleanup(void) { - boost::mutex::scoped_lock lock(interface_instance_mutex); + libtools_scoped_lock lock(interface_instance_mutex); if(NULL != instance) { @@ -100,11 +106,13 @@ LTE_fdd_dl_scan_interface::LTE_fdd_dl_scan_interface() uint32 i; // Communication + pthread_mutex_init(&ctrl_mutex, NULL); ctrl_socket = NULL; ctrl_port = LTE_FDD_DL_SCAN_DEFAULT_CTRL_PORT; ctrl_connected = false; // Variables + pthread_mutex_init(&dl_earfcn_list_mutex, NULL); band = LIBLTE_INTERFACE_BAND_1; dl_earfcn_list_size = liblte_interface_last_dl_earfcn[band] - liblte_interface_first_dl_earfcn[band] + 1; dl_earfcn_list_idx = 0; @@ -124,12 +132,14 @@ LTE_fdd_dl_scan_interface::~LTE_fdd_dl_scan_interface() stop_ctrl_port(); fclose(pcap_fd); + pthread_mutex_destroy(&dl_earfcn_list_mutex); + pthread_mutex_destroy(&ctrl_mutex); } // Communication void LTE_fdd_dl_scan_interface::set_ctrl_port(int16 port) { - boost::mutex::scoped_lock lock(connect_mutex); + libtools_scoped_lock lock(connect_mutex); if(!ctrl_connected) { @@ -138,7 +148,7 @@ void LTE_fdd_dl_scan_interface::set_ctrl_port(int16 port) } void LTE_fdd_dl_scan_interface::start_ctrl_port(void) { - boost::mutex::scoped_lock lock(ctrl_mutex); + libtools_scoped_lock lock(ctrl_mutex); LIBTOOLS_SOCKET_WRAP_ERROR_ENUM error; if(NULL == ctrl_socket) @@ -160,7 +170,7 @@ void LTE_fdd_dl_scan_interface::start_ctrl_port(void) } void LTE_fdd_dl_scan_interface::stop_ctrl_port(void) { - boost::mutex::scoped_lock lock(ctrl_mutex); + libtools_scoped_lock lock(ctrl_mutex); if(NULL != ctrl_socket) { @@ -170,8 +180,8 @@ void LTE_fdd_dl_scan_interface::stop_ctrl_port(void) } void LTE_fdd_dl_scan_interface::send_ctrl_msg(std::string msg) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; if(ctrl_connected) { @@ -182,8 +192,8 @@ void LTE_fdd_dl_scan_interface::send_ctrl_msg(std::string msg) } void LTE_fdd_dl_scan_interface::send_ctrl_info_msg(std::string msg) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; if(ctrl_connected) { @@ -198,28 +208,22 @@ void LTE_fdd_dl_scan_interface::send_ctrl_channel_found_begin_msg(LTE_FDD_DL_SCA uint32 sfn, uint8 N_ant) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; if(ctrl_connected) { - tmp_msg = "info channel_found_begin "; - try - { - tmp_msg += "freq=" + boost::lexical_cast(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; - tmp_msg += "dl_earfcn=" + boost::lexical_cast(current_dl_earfcn) + " "; - tmp_msg += "freq_offset=" + boost::lexical_cast(chan_data->freq_offset) + " "; - tmp_msg += "phys_cell_id=" + boost::lexical_cast(chan_data->N_id_cell) + " "; - tmp_msg += "sfn=" + boost::lexical_cast(sfn) + " "; - - tmp_msg += "n_ant=" + boost::lexical_cast((uint32)N_ant) + " "; - tmp_msg += "phich_dur=" + boost::lexical_cast(liblte_rrc_phich_duration_text[mib->phich_config.dur]) + " "; - tmp_msg += "phich_res=" + boost::lexical_cast(liblte_rrc_phich_resource_text[mib->phich_config.res]) + " "; - tmp_msg += "bandwidth=" + boost::lexical_cast(liblte_rrc_dl_bandwidth_text[mib->dl_bw]) + " "; - tmp_msg += "\n"; - }catch(boost::bad_lexical_cast &){ - tmp_msg += "\n"; - } + tmp_msg = "info channel_found_begin "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "freq_offset=" + to_string(chan_data->freq_offset) + " "; + tmp_msg += "phys_cell_id=" + to_string(chan_data->N_id_cell) + " "; + tmp_msg += "sfn=" + to_string(sfn) + " "; + tmp_msg += "n_ant=" + to_string(N_ant) + " "; + tmp_msg += "phich_dur=" + to_string(liblte_rrc_phich_duration_text[mib->phich_config.dur]) + " "; + tmp_msg += "phich_res=" + to_string(liblte_rrc_phich_resource_text[mib->phich_config.res]) + " "; + tmp_msg += "bandwidth=" + to_string(liblte_rrc_dl_bandwidth_text[mib->dl_bw]) + " "; + tmp_msg += "\n"; ctrl_socket->send(tmp_msg); } } @@ -227,117 +231,112 @@ void LTE_fdd_dl_scan_interface::send_ctrl_sib1_decoded_msg(LTE_FDD_DL_SCAN_CHAN_ LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1, uint32 sfn) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; - uint32 i; - uint32 j; - uint16 mnc; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; + uint32 i; + uint32 j; + uint16 mnc; if(ctrl_connected) { - tmp_msg = "info sib1_decoded "; - try + tmp_msg = "info sib1_decoded "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "freq_offset=" + to_string(chan_data->freq_offset) + " "; + tmp_msg += "phys_cell_id=" + to_string(chan_data->N_id_cell) + " "; + tmp_msg += "sfn=" + to_string(sfn) + " "; + + for(i=0; iN_plmn_ids; i++) { - tmp_msg += "freq=" + boost::lexical_cast(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; - tmp_msg += "dl_earfcn=" + boost::lexical_cast(current_dl_earfcn) + " "; - tmp_msg += "freq_offset=" + boost::lexical_cast(chan_data->freq_offset) + " "; - tmp_msg += "phys_cell_id=" + boost::lexical_cast(chan_data->N_id_cell) + " "; - tmp_msg += "sfn=" + boost::lexical_cast(sfn) + " "; - - for(i=0; iN_plmn_ids; i++) - { - tmp_msg += "mcc[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((sib1->plmn_id[i].id.mcc & 0x0F00) >> 8); - tmp_msg += boost::lexical_cast((sib1->plmn_id[i].id.mcc & 0x00F0) >> 4); - tmp_msg += boost::lexical_cast((sib1->plmn_id[i].id.mcc & 0x000F)) + " "; - tmp_msg += "mnc[" + boost::lexical_cast(i) + "]="; - if((sib1->plmn_id[i].id.mnc & 0xFF00) == 0xFF00) - { - mnc = sib1->plmn_id[i].id.mnc & 0x00FF; - tmp_msg += boost::lexical_cast((sib1->plmn_id[i].id.mnc & 0x00F0) >> 4); - tmp_msg += boost::lexical_cast((sib1->plmn_id[i].id.mnc & 0x000F)) + " "; - }else{ - mnc = sib1->plmn_id[i].id.mnc & 0x0FFF; - tmp_msg += boost::lexical_cast((sib1->plmn_id[i].id.mnc & 0x0F00) >> 8); - tmp_msg += boost::lexical_cast((sib1->plmn_id[i].id.mnc & 0x00F0) >> 4); - tmp_msg += boost::lexical_cast((sib1->plmn_id[i].id.mnc & 0x000F)) + " "; - } - for(j=0; jplmn_id[i].id.mcc & 0x0FFF) && - liblte_mcc_mnc_list[j].mnc == mnc) - { - tmp_msg += "network[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_mcc_mnc_list[j].net_name) + " "; - break; - } - } - if(LIBLTE_RRC_RESV_FOR_OPER == sib1->plmn_id[i].resv_for_oper) - { - tmp_msg += "resv_for_oper[" + boost::lexical_cast(i) + "]=true "; - }else{ - tmp_msg += "resv_for_oper[" + boost::lexical_cast(i) + "]=false "; - } - } - tmp_msg += "tac=" + boost::lexical_cast((uint32)sib1->tracking_area_code) + " "; - tmp_msg += "cell_id=" + boost::lexical_cast(sib1->cell_id) + " "; - if(LIBLTE_RRC_CELL_BARRED == sib1->cell_barred) + tmp_msg += "mcc[" + to_string(i) + "]="; + tmp_msg += to_string((sib1->plmn_id[i].id.mcc & 0x0F00) >> 8); + tmp_msg += to_string((sib1->plmn_id[i].id.mcc & 0x00F0) >> 4); + tmp_msg += to_string((sib1->plmn_id[i].id.mcc & 0x000F)) + " "; + tmp_msg += "mnc[" + to_string(i) + "]="; + if((sib1->plmn_id[i].id.mnc & 0xFF00) == 0xFF00) { - tmp_msg += "cell_barred=true "; + mnc = sib1->plmn_id[i].id.mnc & 0x00FF; + tmp_msg += to_string((sib1->plmn_id[i].id.mnc & 0x00F0) >> 4); + tmp_msg += to_string((sib1->plmn_id[i].id.mnc & 0x000F)) + " "; }else{ - tmp_msg += "cell_barred=false "; + mnc = sib1->plmn_id[i].id.mnc & 0x0FFF; + tmp_msg += to_string((sib1->plmn_id[i].id.mnc & 0x0F00) >> 8); + tmp_msg += to_string((sib1->plmn_id[i].id.mnc & 0x00F0) >> 4); + tmp_msg += to_string((sib1->plmn_id[i].id.mnc & 0x000F)) + " "; } - if(LIBLTE_RRC_INTRA_FREQ_RESELECTION_ALLOWED == sib1->intra_freq_reselection) + for(j=0; jplmn_id[i].id.mcc & 0x0FFF) && + liblte_mcc_mnc_list[j].mnc == mnc) + { + tmp_msg += "network[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_mcc_mnc_list[j].net_name) + " "; + break; + } } - if(LIBLTE_RRC_CSG_IDENTITY_NOT_PRESENT != sib1->csg_id) + if(LIBLTE_RRC_RESV_FOR_OPER == sib1->plmn_id[i].resv_for_oper) { - tmp_msg += "csg_id=" + boost::lexical_cast(sib1->csg_id) + " "; + tmp_msg += "resv_for_oper[" + to_string(i) + "]=true "; + }else{ + tmp_msg += "resv_for_oper[" + to_string(i) + "]=false "; } - tmp_msg += "q_rx_lev_min=" + boost::lexical_cast((int32)sib1->q_rx_lev_min) + " "; - tmp_msg += "q_rx_lev_min_offset=" + boost::lexical_cast((uint32)sib1->q_rx_lev_min_offset) + " "; - if(true == sib1->p_max_present) + } + tmp_msg += "tac=" + to_string((uint32)sib1->tracking_area_code) + " "; + tmp_msg += "cell_id=" + to_string(sib1->cell_id) + " "; + if(LIBLTE_RRC_CELL_BARRED == sib1->cell_barred) + { + tmp_msg += "cell_barred=true "; + }else{ + tmp_msg += "cell_barred=false "; + } + if(LIBLTE_RRC_INTRA_FREQ_RESELECTION_ALLOWED == sib1->intra_freq_reselection) + { + tmp_msg += "intra_freq_resel=allowed "; + }else{ + tmp_msg += "intra_freq_resel=not_allowed "; + } + if(LIBLTE_RRC_CSG_IDENTITY_NOT_PRESENT != sib1->csg_id) + { + tmp_msg += "csg_id=" + to_string(sib1->csg_id) + " "; + } + tmp_msg += "q_rx_lev_min=" + to_string(sib1->q_rx_lev_min) + " "; + tmp_msg += "q_rx_lev_min_offset=" + to_string(sib1->q_rx_lev_min_offset) + " "; + if(true == sib1->p_max_present) + { + tmp_msg += "p_max=" + to_string(sib1->p_max) + " "; + } + tmp_msg += "band=" + to_string(sib1->freq_band_indicator) + " "; + tmp_msg += "si_win_len=" + to_string(liblte_rrc_si_window_length_text[sib1->si_window_length]) + " "; + for(i=0; iN_sched_info; i++) + { + tmp_msg += "si_periodicity[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_si_periodicity_text[sib1->sched_info[i].si_periodicity]) + " "; + tmp_msg += "sib_mapping_info[" + to_string(i) + "]="; + if(0 == i) { - tmp_msg += "p_max=" + boost::lexical_cast((int32)sib1->p_max) + " "; + tmp_msg += "2"; } - tmp_msg += "band=" + boost::lexical_cast((uint32)sib1->freq_band_indicator) + " "; - tmp_msg += "si_win_len=" + boost::lexical_cast(liblte_rrc_si_window_length_text[sib1->si_window_length]) + " "; - for(i=0; iN_sched_info; i++) + for(j=0; jsched_info[i].N_sib_mapping_info; j++) { - tmp_msg += "si_periodicity[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_si_periodicity_text[sib1->sched_info[i].si_periodicity]) + " "; - tmp_msg += "sib_mapping_info[" + boost::lexical_cast(i) + "]="; - if(0 == i) + if(j > 0 || (i == 0 && j == 0)) { - tmp_msg += "2"; + tmp_msg += ","; } - for(j=0; jsched_info[i].N_sib_mapping_info; j++) - { - if(j > 0 || (i == 0 && j == 0)) - { - tmp_msg += ","; - } - tmp_msg += boost::lexical_cast(liblte_rrc_sib_type_text[sib1->sched_info[i].sib_mapping_info[j].sib_type]); - } - tmp_msg += " "; - } - if(false == sib1->tdd) - { - tmp_msg += "duplex_mode=fdd "; - }else{ - tmp_msg += "duplex_mode=tdd "; - tmp_msg += "subfr_assignment=" + boost::lexical_cast(liblte_rrc_subframe_assignment_text[sib1->sf_assignment]) + " "; - tmp_msg += "special_subfr_patterns=" + boost::lexical_cast(liblte_rrc_special_subframe_patterns_text[sib1->special_sf_patterns]) + " "; + tmp_msg += to_string(liblte_rrc_sib_type_text[sib1->sched_info[i].sib_mapping_info[j].sib_type]); } - tmp_msg += "si_value_tag=" + boost::lexical_cast((uint32)sib1->system_info_value_tag) + " "; - - tmp_msg += "\n"; - }catch(boost::bad_lexical_cast &){ - tmp_msg += "\n"; + tmp_msg += " "; + } + if(false == sib1->tdd) + { + tmp_msg += "duplex_mode=fdd "; + }else{ + tmp_msg += "duplex_mode=tdd "; + tmp_msg += "subfr_assignment=" + to_string(liblte_rrc_subframe_assignment_text[sib1->tdd_cnfg.sf_assignment]) + " "; + tmp_msg += "special_subfr_patterns=" + to_string(liblte_rrc_special_subframe_patterns_text[sib1->tdd_cnfg.special_sf_patterns]) + " "; } + tmp_msg += "si_value_tag=" + to_string(sib1->system_info_value_tag) + " "; + + tmp_msg += "\n"; ctrl_socket->send(tmp_msg); } } @@ -345,375 +344,370 @@ void LTE_fdd_dl_scan_interface::send_ctrl_sib2_decoded_msg(LTE_FDD_DL_SCAN_CHAN_ LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, uint32 sfn) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; - uint32 coeff; - uint32 T; - uint32 i; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; + uint32 coeff; + uint32 T; + uint32 i; if(ctrl_connected) { - tmp_msg = "info sib2_decoded "; - try + tmp_msg = "info sib2_decoded "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "freq_offset=" + to_string(chan_data->freq_offset) + " "; + tmp_msg += "phys_cell_id=" + to_string(chan_data->N_id_cell) + " "; + tmp_msg += "sfn=" + to_string(sfn) + " "; + + if(true == sib2->ac_barring_for_emergency) { - tmp_msg += "freq=" + boost::lexical_cast(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; - tmp_msg += "dl_earfcn=" + boost::lexical_cast(current_dl_earfcn) + " "; - tmp_msg += "freq_offset=" + boost::lexical_cast(chan_data->freq_offset) + " "; - tmp_msg += "phys_cell_id=" + boost::lexical_cast(chan_data->N_id_cell) + " "; - tmp_msg += "sfn=" + boost::lexical_cast(sfn) + " "; - - if(true == sib2->ac_barring_for_emergency) - { - tmp_msg += "emergency_barring=enabled "; - }else{ - tmp_msg += "emergency_barring=disabled "; - } - if(true == sib2->ac_barring_for_mo_signalling.enabled) - { - tmp_msg += "mo_signalling_barring=enabled "; - tmp_msg += "mo_signalling_barring_factor=" + boost::lexical_cast(liblte_rrc_ac_barring_factor_text[sib2->ac_barring_for_mo_signalling.factor]) + " "; - tmp_msg += "mo_signalling_barring_time=" + boost::lexical_cast(liblte_rrc_ac_barring_time_text[sib2->ac_barring_for_mo_signalling.time]) + " "; - tmp_msg += "mo_signalling_barring_special_ac=" + boost::lexical_cast((uint32)sib2->ac_barring_for_mo_signalling.for_special_ac) + " "; - }else{ - tmp_msg += "mo_signalling_barring=disabled "; - } - if(true == sib2->ac_barring_for_mo_data.enabled) - { - tmp_msg += "mo_data_barring=enabled "; - tmp_msg += "mo_data_barring_factor=" + boost::lexical_cast(liblte_rrc_ac_barring_factor_text[sib2->ac_barring_for_mo_data.factor]) + " "; - tmp_msg += "mo_data_barring_time=" + boost::lexical_cast(liblte_rrc_ac_barring_time_text[sib2->ac_barring_for_mo_data.time]) + " "; - tmp_msg += "mo_data_barring_special_ac=" + boost::lexical_cast((uint32)sib2->ac_barring_for_mo_data.for_special_ac) + " "; - }else{ - tmp_msg += "mo_data_barring=disabled "; - } - tmp_msg += "num_rach_preambles=" + boost::lexical_cast(liblte_rrc_number_of_ra_preambles_text[sib2->rr_config_common_sib.rach_cnfg.num_ra_preambles]) + " "; - if(true == sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.present) - { - tmp_msg += "size_of_rach_preambles_group_a=" + boost::lexical_cast(liblte_rrc_size_of_ra_preambles_group_a_text[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.size_of_ra]) + " "; - tmp_msg += "rach_msg_size_group_a=" + boost::lexical_cast(liblte_rrc_message_size_group_a_text[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.msg_size]) + " "; - tmp_msg += "rach_msg_power_offset_group_b=" + boost::lexical_cast(liblte_rrc_message_power_offset_group_b_text[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.msg_pwr_offset_group_b]) + " "; - } - tmp_msg += "power_ramping_step=" + boost::lexical_cast(liblte_rrc_power_ramping_step_text[sib2->rr_config_common_sib.rach_cnfg.pwr_ramping_step]) + " "; - tmp_msg += "preamble_init_target_rx_power=" + boost::lexical_cast(liblte_rrc_preamble_initial_received_target_power_text[sib2->rr_config_common_sib.rach_cnfg.preamble_init_rx_target_pwr]) + " "; - tmp_msg += "preamble_trans_max=" + boost::lexical_cast(liblte_rrc_preamble_trans_max_text[sib2->rr_config_common_sib.rach_cnfg.preamble_trans_max]) + " "; - tmp_msg += "ra_response_window_size=" + boost::lexical_cast(liblte_rrc_ra_response_window_size_text[sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size]) + " "; - tmp_msg += "mac_contention_resolution_timer=" + boost::lexical_cast(liblte_rrc_mac_contention_resolution_timer_text[sib2->rr_config_common_sib.rach_cnfg.mac_con_res_timer]) + " "; - tmp_msg += "max_num_harq_tx_for_msg_3=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.rach_cnfg.max_harq_msg3_tx) + " "; - tmp_msg += "modification_period_coeff=" + boost::lexical_cast(liblte_rrc_modification_period_coeff_text[sib2->rr_config_common_sib.bcch_cnfg.modification_period_coeff]) + " "; - coeff = liblte_rrc_modification_period_coeff_num[sib2->rr_config_common_sib.bcch_cnfg.modification_period_coeff]; - tmp_msg += "default_paging_cycle=" + boost::lexical_cast(liblte_rrc_default_paging_cycle_text[sib2->rr_config_common_sib.pcch_cnfg.default_paging_cycle]) + " "; - T = liblte_rrc_default_paging_cycle_num[sib2->rr_config_common_sib.pcch_cnfg.default_paging_cycle]; - tmp_msg += "modification_period=" + boost::lexical_cast(coeff * T) + " "; - tmp_msg += "n_b=" + boost::lexical_cast((uint32)(T * liblte_rrc_nb_num[sib2->rr_config_common_sib.pcch_cnfg.nB])) + " "; - tmp_msg += "root_sequence_index=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.prach_cnfg.root_sequence_index) + " "; - tmp_msg += "prach_config_index=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_config_index) + " "; - switch(sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_config_index) - { - case 0: - tmp_msg += "preamble_format=0 rach_sfn=even rach_subframe_num=1 "; - break; - case 1: - tmp_msg += "preamble_format=0 rach_sfn=even rach_subframe_num=4 "; - break; - case 2: - tmp_msg += "preamble_format=0 rach_sfn=even rach_subframe_num=7 "; - break; - case 3: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=1 "; - break; - case 4: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=4 "; - break; - case 5: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=7 "; - break; - case 6: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=1,6 "; - break; - case 7: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=2,7 "; - break; - case 8: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=3,8 "; - break; - case 9: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=1,4,7 "; - break; - case 10: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=2,5,8 "; - break; - case 11: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=3,6,9 "; - break; - case 12: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=0,2,4,6,8 "; - break; - case 13: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=1,3,5,7,9 "; - break; - case 14: - tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=0,1,2,3,4,5,6,7,8,9 "; - break; - case 15: - tmp_msg += "preamble_format=0 rach_sfn=even rach_subframe_num=9 "; - break; - case 16: - tmp_msg += "preamble_format=1 rach_sfn=even rach_subframe_num=1 "; - break; - case 17: - tmp_msg += "preamble_format=1 rach_sfn=even rach_subframe_num=4 "; - break; - case 18: - tmp_msg += "preamble_format=1 rach_sfn=even rach_subframe_num=7 "; - break; - case 19: - tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=1 "; - break; - case 20: - tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=4 "; - break; - case 21: - tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=7 "; - break; - case 22: - tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=1,6 "; - break; - case 23: - tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=2,7 "; - break; - case 24: - tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=3,8 "; - break; - case 25: - tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=1,4,7 "; - break; - case 26: - tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=2,5,8 "; - break; - case 27: - tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=3,6,9 "; - break; - case 28: - tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=0,2,4,6,8 "; - break; - case 29: - tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=1,3,5,7,9 "; - break; - case 30: - tmp_msg += "preamble_format=n/a rach_sfn=n/a rach_subframe_num=n/a "; - break; - case 31: - tmp_msg += "preamble_format=1 rach_sfn=even rach_subframe_num=9 "; - break; - case 32: - tmp_msg += "preamble_format=2 rach_sfn=even rach_subframe_num=1 "; - break; - case 33: - tmp_msg += "preamble_format=2 rach_sfn=even rach_subframe_num=4 "; - break; - case 34: - tmp_msg += "preamble_format=2 rach_sfn=even rach_subframe_num=7 "; - break; - case 35: - tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=1 "; - break; - case 36: - tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=4 "; - break; - case 37: - tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=7 "; - break; - case 38: - tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=1,6 "; - break; - case 39: - tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=2,7 "; - break; - case 40: - tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=3,8 "; - break; - case 41: - tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=1,4,7 "; - break; - case 42: - tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=2,5,8 "; - break; - case 43: - tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=3,6,9 "; - break; - case 44: - tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=0,2,4,6,8 "; - break; - case 45: - tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=1,3,5,7,9 "; - break; - case 46: - tmp_msg += "preamble_format=n/a rach_sfn=n/a rach_subframe_num=n/a "; - break; - case 47: - tmp_msg += "preamble_format=2 rach_sfn=even rach_subframe_num=9 "; - break; - case 48: - tmp_msg += "preamble_format=3 rach_sfn=even rach_subframe_num=1 "; - break; - case 49: - tmp_msg += "preamble_format=3 rach_sfn=even rach_subframe_num=4 "; - break; - case 50: - tmp_msg += "preamble_format=3 rach_sfn=even rach_subframe_num=7 "; - break; - case 51: - tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=1 "; - break; - case 52: - tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=4 "; - break; - case 53: - tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=7 "; - break; - case 54: - tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=1,6 "; - break; - case 55: - tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=2,7 "; - break; - case 56: - tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=3,8 "; - break; - case 57: - tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=1,4,7 "; - break; - case 58: - tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=2,5,8 "; - break; - case 59: - tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=3,6,9 "; - break; - case 60: - tmp_msg += "preamble_format=n/a rach_sfn=n/a rach_subframe_num=n/a "; - break; - case 61: - tmp_msg += "preamble_format=n/a rach_sfn=n/a rach_subframe_num=n/a "; - break; - case 62: - tmp_msg += "preamble_format=n/a rach_sfn=n/a rach_subframe_num=n/a "; - break; - case 63: - tmp_msg += "preamble_format=3 rach_sfn=even rach_subframe_num=9 "; - break; - } - if(true == sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.high_speed_flag) - { - tmp_msg += "high_speed_flag=restricted_set "; - }else{ - tmp_msg += "high_speed_flag=unrestricted_set "; - } - tmp_msg += "n_cs_config=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.zero_correlation_zone_config) + " "; - tmp_msg += "prach_freq_offset=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset) + " "; - tmp_msg += "reference_signal_power=" + boost::lexical_cast((int32)sib2->rr_config_common_sib.pdsch_cnfg.rs_power) + " "; - tmp_msg += "p_b=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.pdsch_cnfg.p_b) + " "; - tmp_msg += "n_sb=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.pusch_cnfg.n_sb) + " "; - switch(sib2->rr_config_common_sib.pusch_cnfg.hopping_mode) - { - case LIBLTE_RRC_HOPPING_MODE_INTER_SUBFRAME: - tmp_msg += "hopping_mode=inter_subframe "; - break; - case LIBLTE_RRC_HOPPING_MODE_INTRA_AND_INTER_SUBFRAME: - tmp_msg += "hopping_mode=intra_and_inter_subframe "; - break; - } - tmp_msg += "pusch_n_rb_hopping_offset=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.pusch_cnfg.pusch_hopping_offset) + " "; - if(true == sib2->rr_config_common_sib.pusch_cnfg.enable_64_qam) - { - tmp_msg += "64_qam=allowed "; - }else{ - tmp_msg += "64_qam=not_allowed "; - } - if(true == sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_hopping_enabled) + tmp_msg += "emergency_barring=enabled "; + }else{ + tmp_msg += "emergency_barring=disabled "; + } + if(true == sib2->ac_barring_for_mo_signalling.enabled) + { + tmp_msg += "mo_signalling_barring=enabled "; + tmp_msg += "mo_signalling_barring_factor=" + to_string(liblte_rrc_ac_barring_factor_text[sib2->ac_barring_for_mo_signalling.factor]) + " "; + tmp_msg += "mo_signalling_barring_time=" + to_string(liblte_rrc_ac_barring_time_text[sib2->ac_barring_for_mo_signalling.time]) + " "; + tmp_msg += "mo_signalling_barring_special_ac=" + to_string(sib2->ac_barring_for_mo_signalling.for_special_ac) + " "; + }else{ + tmp_msg += "mo_signalling_barring=disabled "; + } + if(true == sib2->ac_barring_for_mo_data.enabled) + { + tmp_msg += "mo_data_barring=enabled "; + tmp_msg += "mo_data_barring_factor=" + to_string(liblte_rrc_ac_barring_factor_text[sib2->ac_barring_for_mo_data.factor]) + " "; + tmp_msg += "mo_data_barring_time=" + to_string(liblte_rrc_ac_barring_time_text[sib2->ac_barring_for_mo_data.time]) + " "; + tmp_msg += "mo_data_barring_special_ac=" + to_string(sib2->ac_barring_for_mo_data.for_special_ac) + " "; + }else{ + tmp_msg += "mo_data_barring=disabled "; + } + tmp_msg += "num_rach_preambles=" + to_string(liblte_rrc_number_of_ra_preambles_text[sib2->rr_config_common_sib.rach_cnfg.num_ra_preambles]) + " "; + if(true == sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.present) + { + tmp_msg += "size_of_rach_preambles_group_a=" + to_string(liblte_rrc_size_of_ra_preambles_group_a_text[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.size_of_ra]) + " "; + tmp_msg += "rach_msg_size_group_a=" + to_string(liblte_rrc_message_size_group_a_text[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.msg_size]) + " "; + tmp_msg += "rach_msg_power_offset_group_b=" + to_string(liblte_rrc_message_power_offset_group_b_text[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.msg_pwr_offset_group_b]) + " "; + } + tmp_msg += "power_ramping_step=" + to_string(liblte_rrc_power_ramping_step_text[sib2->rr_config_common_sib.rach_cnfg.pwr_ramping_step]) + " "; + tmp_msg += "preamble_init_target_rx_power=" + to_string(liblte_rrc_preamble_initial_received_target_power_text[sib2->rr_config_common_sib.rach_cnfg.preamble_init_rx_target_pwr]) + " "; + tmp_msg += "preamble_trans_max=" + to_string(liblte_rrc_preamble_trans_max_text[sib2->rr_config_common_sib.rach_cnfg.preamble_trans_max]) + " "; + tmp_msg += "ra_response_window_size=" + to_string(liblte_rrc_ra_response_window_size_text[sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size]) + " "; + tmp_msg += "mac_contention_resolution_timer=" + to_string(liblte_rrc_mac_contention_resolution_timer_text[sib2->rr_config_common_sib.rach_cnfg.mac_con_res_timer]) + " "; + tmp_msg += "max_num_harq_tx_for_msg_3=" + to_string(sib2->rr_config_common_sib.rach_cnfg.max_harq_msg3_tx) + " "; + tmp_msg += "modification_period_coeff=" + to_string(liblte_rrc_modification_period_coeff_text[sib2->rr_config_common_sib.bcch_cnfg.modification_period_coeff]) + " "; + coeff = liblte_rrc_modification_period_coeff_num[sib2->rr_config_common_sib.bcch_cnfg.modification_period_coeff]; + tmp_msg += "default_paging_cycle=" + to_string(liblte_rrc_default_paging_cycle_text[sib2->rr_config_common_sib.pcch_cnfg.default_paging_cycle]) + " "; + T = liblte_rrc_default_paging_cycle_num[sib2->rr_config_common_sib.pcch_cnfg.default_paging_cycle]; + tmp_msg += "modification_period=" + to_string(coeff * T) + " "; + tmp_msg += "n_b=" + to_string(T * liblte_rrc_nb_num[sib2->rr_config_common_sib.pcch_cnfg.nB]) + " "; + tmp_msg += "root_sequence_index=" + to_string(sib2->rr_config_common_sib.prach_cnfg.root_sequence_index) + " "; + tmp_msg += "prach_config_index=" + to_string(sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_config_index) + " "; + switch(sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_config_index) + { + case 0: + tmp_msg += "preamble_format=0 rach_sfn=even rach_subframe_num=1 "; + break; + case 1: + tmp_msg += "preamble_format=0 rach_sfn=even rach_subframe_num=4 "; + break; + case 2: + tmp_msg += "preamble_format=0 rach_sfn=even rach_subframe_num=7 "; + break; + case 3: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=1 "; + break; + case 4: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=4 "; + break; + case 5: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=7 "; + break; + case 6: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=1,6 "; + break; + case 7: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=2,7 "; + break; + case 8: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=3,8 "; + break; + case 9: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=1,4,7 "; + break; + case 10: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=2,5,8 "; + break; + case 11: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=3,6,9 "; + break; + case 12: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=0,2,4,6,8 "; + break; + case 13: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=1,3,5,7,9 "; + break; + case 14: + tmp_msg += "preamble_format=0 rach_sfn=any rach_subframe_num=0,1,2,3,4,5,6,7,8,9 "; + break; + case 15: + tmp_msg += "preamble_format=0 rach_sfn=even rach_subframe_num=9 "; + break; + case 16: + tmp_msg += "preamble_format=1 rach_sfn=even rach_subframe_num=1 "; + break; + case 17: + tmp_msg += "preamble_format=1 rach_sfn=even rach_subframe_num=4 "; + break; + case 18: + tmp_msg += "preamble_format=1 rach_sfn=even rach_subframe_num=7 "; + break; + case 19: + tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=1 "; + break; + case 20: + tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=4 "; + break; + case 21: + tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=7 "; + break; + case 22: + tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=1,6 "; + break; + case 23: + tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=2,7 "; + break; + case 24: + tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=3,8 "; + break; + case 25: + tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=1,4,7 "; + break; + case 26: + tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=2,5,8 "; + break; + case 27: + tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=3,6,9 "; + break; + case 28: + tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=0,2,4,6,8 "; + break; + case 29: + tmp_msg += "preamble_format=1 rach_sfn=any rach_subframe_num=1,3,5,7,9 "; + break; + case 30: + tmp_msg += "preamble_format=n/a rach_sfn=n/a rach_subframe_num=n/a "; + break; + case 31: + tmp_msg += "preamble_format=1 rach_sfn=even rach_subframe_num=9 "; + break; + case 32: + tmp_msg += "preamble_format=2 rach_sfn=even rach_subframe_num=1 "; + break; + case 33: + tmp_msg += "preamble_format=2 rach_sfn=even rach_subframe_num=4 "; + break; + case 34: + tmp_msg += "preamble_format=2 rach_sfn=even rach_subframe_num=7 "; + break; + case 35: + tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=1 "; + break; + case 36: + tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=4 "; + break; + case 37: + tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=7 "; + break; + case 38: + tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=1,6 "; + break; + case 39: + tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=2,7 "; + break; + case 40: + tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=3,8 "; + break; + case 41: + tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=1,4,7 "; + break; + case 42: + tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=2,5,8 "; + break; + case 43: + tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=3,6,9 "; + break; + case 44: + tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=0,2,4,6,8 "; + break; + case 45: + tmp_msg += "preamble_format=2 rach_sfn=any rach_subframe_num=1,3,5,7,9 "; + break; + case 46: + tmp_msg += "preamble_format=n/a rach_sfn=n/a rach_subframe_num=n/a "; + break; + case 47: + tmp_msg += "preamble_format=2 rach_sfn=even rach_subframe_num=9 "; + break; + case 48: + tmp_msg += "preamble_format=3 rach_sfn=even rach_subframe_num=1 "; + break; + case 49: + tmp_msg += "preamble_format=3 rach_sfn=even rach_subframe_num=4 "; + break; + case 50: + tmp_msg += "preamble_format=3 rach_sfn=even rach_subframe_num=7 "; + break; + case 51: + tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=1 "; + break; + case 52: + tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=4 "; + break; + case 53: + tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=7 "; + break; + case 54: + tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=1,6 "; + break; + case 55: + tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=2,7 "; + break; + case 56: + tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=3,8 "; + break; + case 57: + tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=1,4,7 "; + break; + case 58: + tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=2,5,8 "; + break; + case 59: + tmp_msg += "preamble_format=3 rach_sfn=any rach_subframe_num=3,6,9 "; + break; + case 60: + tmp_msg += "preamble_format=n/a rach_sfn=n/a rach_subframe_num=n/a "; + break; + case 61: + tmp_msg += "preamble_format=n/a rach_sfn=n/a rach_subframe_num=n/a "; + break; + case 62: + tmp_msg += "preamble_format=n/a rach_sfn=n/a rach_subframe_num=n/a "; + break; + case 63: + tmp_msg += "preamble_format=3 rach_sfn=even rach_subframe_num=9 "; + break; + } + if(true == sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.high_speed_flag) + { + tmp_msg += "high_speed_flag=restricted_set "; + }else{ + tmp_msg += "high_speed_flag=unrestricted_set "; + } + tmp_msg += "n_cs_config=" + to_string(sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.zero_correlation_zone_config) + " "; + tmp_msg += "prach_freq_offset=" + to_string(sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset) + " "; + tmp_msg += "reference_signal_power=" + to_string(sib2->rr_config_common_sib.pdsch_cnfg.rs_power) + " "; + tmp_msg += "p_b=" + to_string(sib2->rr_config_common_sib.pdsch_cnfg.p_b) + " "; + tmp_msg += "n_sb=" + to_string(sib2->rr_config_common_sib.pusch_cnfg.n_sb) + " "; + switch(sib2->rr_config_common_sib.pusch_cnfg.hopping_mode) + { + case LIBLTE_RRC_HOPPING_MODE_INTER_SUBFRAME: + tmp_msg += "hopping_mode=inter_subframe "; + break; + case LIBLTE_RRC_HOPPING_MODE_INTRA_AND_INTER_SUBFRAME: + tmp_msg += "hopping_mode=intra_and_inter_subframe "; + break; + } + tmp_msg += "pusch_n_rb_hopping_offset=" + to_string(sib2->rr_config_common_sib.pusch_cnfg.pusch_hopping_offset) + " "; + if(true == sib2->rr_config_common_sib.pusch_cnfg.enable_64_qam) + { + tmp_msg += "64_qam=allowed "; + }else{ + tmp_msg += "64_qam=not_allowed "; + } + if(true == sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_hopping_enabled) + { + tmp_msg += "group_hopping=enabled "; + }else{ + tmp_msg += "group_hopping=disabled "; + } + tmp_msg += "group_assignment_pusch=" + to_string(sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch) + " "; + if(true == sib2->rr_config_common_sib.pusch_cnfg.ul_rs.sequence_hopping_enabled) + { + tmp_msg += "sequence_hopping=enabled "; + }else{ + tmp_msg += "sequence_hopping=disabled "; + } + tmp_msg += "cyclic_shift=" + to_string(sib2->rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift) + " "; + tmp_msg += "delta_pucch_shift=" + to_string(liblte_rrc_delta_pucch_shift_text[sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift]) + " "; + tmp_msg += "n_rb_cqi=" + to_string(sib2->rr_config_common_sib.pucch_cnfg.n_rb_cqi) + " "; + tmp_msg += "n_cs_an=" + to_string(sib2->rr_config_common_sib.pucch_cnfg.n_cs_an) + " "; + tmp_msg += "n1_pucch_an=" + to_string(sib2->rr_config_common_sib.pucch_cnfg.n1_pucch_an) + " "; + if(true == sib2->rr_config_common_sib.srs_ul_cnfg.present) + { + tmp_msg += "srs_bw_cnfg=" + to_string(liblte_rrc_srs_bw_config_text[sib2->rr_config_common_sib.srs_ul_cnfg.bw_cnfg]) + " "; + tmp_msg += "srs_subframe_cnfg=" + to_string(liblte_rrc_srs_subfr_config_text[sib2->rr_config_common_sib.srs_ul_cnfg.subfr_cnfg]) + " "; + if(true == sib2->rr_config_common_sib.srs_ul_cnfg.ack_nack_simul_tx) { - tmp_msg += "group_hopping=enabled "; + tmp_msg += "simultaneous_an_and_srs=true "; }else{ - tmp_msg += "group_hopping=disabled "; + tmp_msg += "simultaneous_an_and_srs=false "; } - tmp_msg += "group_assignment_pusch=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch) + " "; - if(true == sib2->rr_config_common_sib.pusch_cnfg.ul_rs.sequence_hopping_enabled) + if(true == sib2->rr_config_common_sib.srs_ul_cnfg.max_up_pts_present) { - tmp_msg += "sequence_hopping=enabled "; + tmp_msg += "srs_max_up_pts=true "; }else{ - tmp_msg += "sequence_hopping=disabled "; + tmp_msg += "srs_max_up_pts=false "; } - tmp_msg += "cyclic_shift=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift) + " "; - tmp_msg += "delta_pucch_shift=" + boost::lexical_cast(liblte_rrc_delta_pucch_shift_text[sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift]) + " "; - tmp_msg += "n_rb_cqi=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.pucch_cnfg.n_rb_cqi) + " "; - tmp_msg += "n_cs_an=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.pucch_cnfg.n_cs_an) + " "; - tmp_msg += "n1_pucch_an=" + boost::lexical_cast((uint32)sib2->rr_config_common_sib.pucch_cnfg.n1_pucch_an) + " "; - if(true == sib2->rr_config_common_sib.srs_ul_cnfg.present) - { - tmp_msg += "srs_bw_cnfg=" + boost::lexical_cast(liblte_rrc_srs_bw_config_text[sib2->rr_config_common_sib.srs_ul_cnfg.bw_cnfg]) + " "; - tmp_msg += "srs_subframe_cnfg=" + boost::lexical_cast(liblte_rrc_srs_subfr_config_text[sib2->rr_config_common_sib.srs_ul_cnfg.subfr_cnfg]) + " "; - if(true == sib2->rr_config_common_sib.srs_ul_cnfg.ack_nack_simul_tx) - { - tmp_msg += "simultaneous_an_and_srs=true "; - }else{ - tmp_msg += "simultaneous_an_and_srs=false "; - } - if(true == sib2->rr_config_common_sib.srs_ul_cnfg.max_up_pts_present) - { - tmp_msg += "srs_max_up_pts=true "; - }else{ - tmp_msg += "srs_max_up_pts=false "; - } - } - tmp_msg += "p0_nominal_pusch=" + boost::lexical_cast((int32)sib2->rr_config_common_sib.ul_pwr_ctrl.p0_nominal_pusch) + " "; - tmp_msg += "ul_power_ctrl_alpha=" + boost::lexical_cast(liblte_rrc_ul_power_control_alpha_text[sib2->rr_config_common_sib.ul_pwr_ctrl.alpha]) + " "; - tmp_msg += "p0_nominal_pucch=" + boost::lexical_cast((int32)sib2->rr_config_common_sib.ul_pwr_ctrl.p0_nominal_pucch) + " "; - tmp_msg += "delta_f_pucch_format_1=" + boost::lexical_cast(liblte_rrc_delta_f_pucch_format_1_text[sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_1]) + " "; - tmp_msg += "delta_f_pucch_format_1b=" + boost::lexical_cast(liblte_rrc_delta_f_pucch_format_1b_text[sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_1b]) + " "; - tmp_msg += "delta_f_pucch_format_2=" + boost::lexical_cast(liblte_rrc_delta_f_pucch_format_2_text[sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_2]) + " "; - tmp_msg += "delta_f_pucch_format_2a=" + boost::lexical_cast(liblte_rrc_delta_f_pucch_format_2a_text[sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_2a]) + " "; - tmp_msg += "delta_f_pucch_format_2b=" + boost::lexical_cast(liblte_rrc_delta_f_pucch_format_2b_text[sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_2b]) + " "; - tmp_msg += "delta_preamble_msg_3=" + boost::lexical_cast((int32)sib2->rr_config_common_sib.ul_pwr_ctrl.delta_preamble_msg3) + " "; - switch(sib2->rr_config_common_sib.ul_cp_length) - { - case LIBLTE_RRC_UL_CP_LENGTH_1: - tmp_msg += "ul_cp_length=normal "; - break; - case LIBLTE_RRC_UL_CP_LENGTH_2: - tmp_msg += "ul_cp_length=extended "; - break; - } - tmp_msg += "t300=" + boost::lexical_cast(liblte_rrc_t300_text[sib2->ue_timers_and_constants.t300]) + " "; - tmp_msg += "t301=" + boost::lexical_cast(liblte_rrc_t301_text[sib2->ue_timers_and_constants.t301]) + " "; - tmp_msg += "t310=" + boost::lexical_cast(liblte_rrc_t310_text[sib2->ue_timers_and_constants.t310]) + " "; - tmp_msg += "n310=" + boost::lexical_cast(liblte_rrc_n310_text[sib2->ue_timers_and_constants.n310]) + " "; - tmp_msg += "t311=" + boost::lexical_cast(liblte_rrc_t311_text[sib2->ue_timers_and_constants.t311]) + " "; - tmp_msg += "n311=" + boost::lexical_cast(liblte_rrc_n311_text[sib2->ue_timers_and_constants.n311]) + " "; - if(true == sib2->arfcn_value_eutra.present) - { - tmp_msg += "ul_earfcn=" + boost::lexical_cast((uint32)sib2->arfcn_value_eutra.value) + " "; - } - if(true == sib2->ul_bw.present) - { - tmp_msg += "ul_bw=" + boost::lexical_cast(liblte_rrc_ul_bw_text[sib2->ul_bw.bw]) + " "; - } - tmp_msg += "additional_spectrum_emission=" + boost::lexical_cast((uint32)sib2->additional_spectrum_emission) + " "; - for(i=0; imbsfn_subfr_cnfg_list_size; i++) - { - tmp_msg += "radio_frame_alloc_period[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_radio_frame_allocation_period_text[sib2->mbsfn_subfr_cnfg[i].radio_fr_alloc_period]) + " "; - tmp_msg += "radio_frame_alloc_offset[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(sib2->mbsfn_subfr_cnfg[i].subfr_alloc) + " "; - tmp_msg += "subframe_alloc_num_frames[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_subframe_allocation_num_frames_text[sib2->mbsfn_subfr_cnfg[i].subfr_alloc_num_frames]) + " "; - tmp_msg += "subframe_alloc[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(sib2->mbsfn_subfr_cnfg[i].subfr_alloc) + " "; - } - tmp_msg += "time_alignment_timer=" + boost::lexical_cast(liblte_rrc_time_alignment_timer_text[sib2->time_alignment_timer]) + " "; - - tmp_msg += "\n"; - }catch(boost::bad_lexical_cast &){ - tmp_msg += "\n"; } + tmp_msg += "p0_nominal_pusch=" + to_string(sib2->rr_config_common_sib.ul_pwr_ctrl.p0_nominal_pusch) + " "; + tmp_msg += "ul_power_ctrl_alpha=" + to_string(liblte_rrc_ul_power_control_alpha_text[sib2->rr_config_common_sib.ul_pwr_ctrl.alpha]) + " "; + tmp_msg += "p0_nominal_pucch=" + to_string(sib2->rr_config_common_sib.ul_pwr_ctrl.p0_nominal_pucch) + " "; + tmp_msg += "delta_f_pucch_format_1=" + to_string(liblte_rrc_delta_f_pucch_format_1_text[sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_1]) + " "; + tmp_msg += "delta_f_pucch_format_1b=" + to_string(liblte_rrc_delta_f_pucch_format_1b_text[sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_1b]) + " "; + tmp_msg += "delta_f_pucch_format_2=" + to_string(liblte_rrc_delta_f_pucch_format_2_text[sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_2]) + " "; + tmp_msg += "delta_f_pucch_format_2a=" + to_string(liblte_rrc_delta_f_pucch_format_2a_text[sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_2a]) + " "; + tmp_msg += "delta_f_pucch_format_2b=" + to_string(liblte_rrc_delta_f_pucch_format_2b_text[sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_2b]) + " "; + tmp_msg += "delta_preamble_msg_3=" + to_string(sib2->rr_config_common_sib.ul_pwr_ctrl.delta_preamble_msg3) + " "; + switch(sib2->rr_config_common_sib.ul_cp_length) + { + case LIBLTE_RRC_UL_CP_LENGTH_1: + tmp_msg += "ul_cp_length=normal "; + break; + case LIBLTE_RRC_UL_CP_LENGTH_2: + tmp_msg += "ul_cp_length=extended "; + break; + } + tmp_msg += "t300=" + to_string(liblte_rrc_t300_text[sib2->ue_timers_and_constants.t300]) + " "; + tmp_msg += "t301=" + to_string(liblte_rrc_t301_text[sib2->ue_timers_and_constants.t301]) + " "; + tmp_msg += "t310=" + to_string(liblte_rrc_t310_text[sib2->ue_timers_and_constants.t310]) + " "; + tmp_msg += "n310=" + to_string(liblte_rrc_n310_text[sib2->ue_timers_and_constants.n310]) + " "; + tmp_msg += "t311=" + to_string(liblte_rrc_t311_text[sib2->ue_timers_and_constants.t311]) + " "; + tmp_msg += "n311=" + to_string(liblte_rrc_n311_text[sib2->ue_timers_and_constants.n311]) + " "; + if(true == sib2->arfcn_value_eutra.present) + { + tmp_msg += "ul_earfcn=" + to_string(sib2->arfcn_value_eutra.value) + " "; + } + if(true == sib2->ul_bw.present) + { + tmp_msg += "ul_bw=" + to_string(liblte_rrc_ul_bw_text[sib2->ul_bw.bw]) + " "; + } + tmp_msg += "additional_spectrum_emission=" + to_string(sib2->additional_spectrum_emission) + " "; + for(i=0; imbsfn_subfr_cnfg_list_size; i++) + { + tmp_msg += "radio_frame_alloc_period[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_radio_frame_allocation_period_text[sib2->mbsfn_subfr_cnfg[i].radio_fr_alloc_period]) + " "; + tmp_msg += "radio_frame_alloc_offset[" + to_string(i) + "]="; + tmp_msg += to_string(sib2->mbsfn_subfr_cnfg[i].subfr_alloc) + " "; + tmp_msg += "subframe_alloc_num_frames[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_subframe_allocation_num_frames_text[sib2->mbsfn_subfr_cnfg[i].subfr_alloc_num_frames]) + " "; + tmp_msg += "subframe_alloc[" + to_string(i) + "]="; + tmp_msg += to_string(sib2->mbsfn_subfr_cnfg[i].subfr_alloc) + " "; + } + tmp_msg += "time_alignment_timer=" + to_string(liblte_rrc_time_alignment_timer_text[sib2->time_alignment_timer]) + " "; + + tmp_msg += "\n"; ctrl_socket->send(tmp_msg); } } @@ -721,67 +715,62 @@ void LTE_fdd_dl_scan_interface::send_ctrl_sib3_decoded_msg(LTE_FDD_DL_SCAN_CHAN_ LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3, uint32 sfn) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; if(ctrl_connected) { - tmp_msg = "info sib3_decoded "; - try + tmp_msg = "info sib3_decoded "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "freq_offset=" + to_string(chan_data->freq_offset) + " "; + tmp_msg += "phys_cell_id=" + to_string(chan_data->N_id_cell) + " "; + tmp_msg += "sfn=" + to_string(sfn) + " "; + + tmp_msg += "q_hyst=" + to_string(liblte_rrc_q_hyst_text[sib3->q_hyst]) + " "; + if(true == sib3->speed_state_resel_params.present) { - tmp_msg += "freq=" + boost::lexical_cast(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; - tmp_msg += "dl_earfcn=" + boost::lexical_cast(current_dl_earfcn) + " "; - tmp_msg += "freq_offset=" + boost::lexical_cast(chan_data->freq_offset) + " "; - tmp_msg += "phys_cell_id=" + boost::lexical_cast(chan_data->N_id_cell) + " "; - tmp_msg += "sfn=" + boost::lexical_cast(sfn) + " "; - - tmp_msg += "q_hyst=" + boost::lexical_cast(liblte_rrc_q_hyst_text[sib3->q_hyst]) + " "; - if(true == sib3->speed_state_resel_params.present) - { - tmp_msg += "t_evaluation=" + boost::lexical_cast(liblte_rrc_t_evaluation_text[sib3->speed_state_resel_params.mobility_state_params.t_eval]) + " "; - tmp_msg += "t_hyst_normal=" + boost::lexical_cast(liblte_rrc_t_hyst_normal_text[sib3->speed_state_resel_params.mobility_state_params.t_hyst_normal]) + " "; - tmp_msg += "n_cell_change_medium=" + boost::lexical_cast((uint32)sib3->speed_state_resel_params.mobility_state_params.n_cell_change_medium) + " "; - tmp_msg += "n_cell_change_high=" + boost::lexical_cast((uint32)sib3->speed_state_resel_params.mobility_state_params.n_cell_change_high) + " "; - tmp_msg += "q_hyst_sf_medium=" + boost::lexical_cast(liblte_rrc_sf_medium_text[sib3->speed_state_resel_params.q_hyst_sf.medium]) + " "; - tmp_msg += "q_hyst_sf_high=" + boost::lexical_cast(liblte_rrc_sf_high_text[sib3->speed_state_resel_params.q_hyst_sf.high]) + " "; - } - if(true == sib3->s_non_intra_search_present) - { - tmp_msg += "s_non_intra_search=" + boost::lexical_cast((uint32)sib3->s_non_intra_search) + " "; - } - tmp_msg += "threshold_serving_low=" + boost::lexical_cast((uint32)sib3->thresh_serving_low) + " "; - tmp_msg += "cell_resel_priority=" + boost::lexical_cast((uint32)sib3->cell_resel_prio) + " "; - tmp_msg += "q_rx_lev_min=" + boost::lexical_cast((int32)sib3->q_rx_lev_min) + " "; - if(true == sib3->p_max_present) - { - tmp_msg += "p_max=" + boost::lexical_cast((int32)sib3->p_max) + " "; - } - if(true == sib3->s_intra_search_present) - { - tmp_msg += "s_intra_search=" + boost::lexical_cast((uint32)sib3->s_intra_search) + " "; - } - if(true == sib3->allowed_meas_bw_present) - { - tmp_msg += "allowed_meas_bw=" + boost::lexical_cast(liblte_rrc_allowed_meas_bandwidth_text[sib3->allowed_meas_bw]) + " "; - } - if(true == sib3->presence_ant_port_1) - { - tmp_msg += "presence_ant_port_1=true "; - }else{ - tmp_msg += "presence_ant_port_1=false "; - } - tmp_msg += "neigh_cell_cnfg=" + boost::lexical_cast((uint32)sib3->neigh_cell_cnfg) + " "; - tmp_msg += "t_resel_eutra=" + boost::lexical_cast((uint32)sib3->t_resel_eutra) + " "; - if(true == sib3->t_resel_eutra_sf_present) - { - tmp_msg += "t_resel_eutra_sf_medium=" + boost::lexical_cast(liblte_rrc_sssf_medium_text[sib3->t_resel_eutra_sf.sf_medium]) + " "; - tmp_msg += "t_resel_eutra_sf_high=" + boost::lexical_cast(liblte_rrc_sssf_high_text[sib3->t_resel_eutra_sf.sf_high]) + " "; - } - - tmp_msg += "\n"; - }catch(boost::bad_lexical_cast &){ - tmp_msg += "\n"; + tmp_msg += "t_evaluation=" + to_string(liblte_rrc_t_evaluation_text[sib3->speed_state_resel_params.mobility_state_params.t_eval]) + " "; + tmp_msg += "t_hyst_normal=" + to_string(liblte_rrc_t_hyst_normal_text[sib3->speed_state_resel_params.mobility_state_params.t_hyst_normal]) + " "; + tmp_msg += "n_cell_change_medium=" + to_string(sib3->speed_state_resel_params.mobility_state_params.n_cell_change_medium) + " "; + tmp_msg += "n_cell_change_high=" + to_string(sib3->speed_state_resel_params.mobility_state_params.n_cell_change_high) + " "; + tmp_msg += "q_hyst_sf_medium=" + to_string(liblte_rrc_sf_medium_text[sib3->speed_state_resel_params.q_hyst_sf.medium]) + " "; + tmp_msg += "q_hyst_sf_high=" + to_string(liblte_rrc_sf_high_text[sib3->speed_state_resel_params.q_hyst_sf.high]) + " "; + } + if(true == sib3->s_non_intra_search_present) + { + tmp_msg += "s_non_intra_search=" + to_string(sib3->s_non_intra_search) + " "; + } + tmp_msg += "threshold_serving_low=" + to_string(sib3->thresh_serving_low) + " "; + tmp_msg += "cell_resel_priority=" + to_string(sib3->cell_resel_prio) + " "; + tmp_msg += "q_rx_lev_min=" + to_string(sib3->q_rx_lev_min) + " "; + if(true == sib3->p_max_present) + { + tmp_msg += "p_max=" + to_string(sib3->p_max) + " "; + } + if(true == sib3->s_intra_search_present) + { + tmp_msg += "s_intra_search=" + to_string(sib3->s_intra_search) + " "; + } + if(true == sib3->allowed_meas_bw_present) + { + tmp_msg += "allowed_meas_bw=" + to_string(liblte_rrc_allowed_meas_bandwidth_text[sib3->allowed_meas_bw]) + " "; + } + if(true == sib3->presence_ant_port_1) + { + tmp_msg += "presence_ant_port_1=true "; + }else{ + tmp_msg += "presence_ant_port_1=false "; } + tmp_msg += "neigh_cell_cnfg=" + to_string(sib3->neigh_cell_cnfg) + " "; + tmp_msg += "t_resel_eutra=" + to_string(sib3->t_resel_eutra) + " "; + if(true == sib3->t_resel_eutra_sf_present) + { + tmp_msg += "t_resel_eutra_sf_medium=" + to_string(liblte_rrc_sssf_medium_text[sib3->t_resel_eutra_sf.sf_medium]) + " "; + tmp_msg += "t_resel_eutra_sf_high=" + to_string(liblte_rrc_sssf_high_text[sib3->t_resel_eutra_sf.sf_high]) + " "; + } + + tmp_msg += "\n"; ctrl_socket->send(tmp_msg); } } @@ -789,45 +778,40 @@ void LTE_fdd_dl_scan_interface::send_ctrl_sib4_decoded_msg(LTE_FDD_DL_SCAN_CHAN_ LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *sib4, uint32 sfn) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; - uint32 i; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; + uint32 i; if(ctrl_connected) { - tmp_msg = "info sib4_decoded "; - try + tmp_msg = "info sib4_decoded "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "freq_offset=" + to_string(chan_data->freq_offset) + " "; + tmp_msg += "phys_cell_id=" + to_string(chan_data->N_id_cell) + " "; + tmp_msg += "sfn=" + to_string(sfn) + " "; + + for(i=0; iintra_freq_neigh_cell_list_size; i++) { - tmp_msg += "freq=" + boost::lexical_cast(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; - tmp_msg += "dl_earfcn=" + boost::lexical_cast(current_dl_earfcn) + " "; - tmp_msg += "freq_offset=" + boost::lexical_cast(chan_data->freq_offset) + " "; - tmp_msg += "phys_cell_id=" + boost::lexical_cast(chan_data->N_id_cell) + " "; - tmp_msg += "sfn=" + boost::lexical_cast(sfn) + " "; - - for(i=0; iintra_freq_neigh_cell_list_size; i++) - { - tmp_msg += "neigh_phys_cell_id[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib4->intra_freq_neigh_cell_list[i].phys_cell_id) + " "; - tmp_msg += "neigh_q_offset_range[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_q_offset_range_text[sib4->intra_freq_neigh_cell_list[i].q_offset_range]) + " "; - } - for(i=0; iintra_freq_black_cell_list_size; i++) - { - tmp_msg += "blacklist_phys_cell_id_begin[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib4->intra_freq_black_cell_list[i].start) + " "; - tmp_msg += "blacklist_phys_cell_id_end[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib4->intra_freq_black_cell_list[i].start + liblte_rrc_phys_cell_id_range_num[sib4->intra_freq_black_cell_list[i].range]) + " "; - } - if(true == sib4->csg_phys_cell_id_range_present) - { - tmp_msg += "csg_phys_cell_id_begin=" + boost::lexical_cast((uint32)sib4->csg_phys_cell_id_range.start) + " "; - tmp_msg += "csg_phys_cell_id_end=" + boost::lexical_cast((uint32)sib4->csg_phys_cell_id_range.start + liblte_rrc_phys_cell_id_range_num[sib4->csg_phys_cell_id_range.range]) + " "; - } - - tmp_msg += "\n"; - }catch(boost::bad_lexical_cast &){ - tmp_msg += "\n"; + tmp_msg += "neigh_phys_cell_id[" + to_string(i) + "]="; + tmp_msg += to_string(sib4->intra_freq_neigh_cell_list[i].phys_cell_id) + " "; + tmp_msg += "neigh_q_offset_range[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_q_offset_range_text[sib4->intra_freq_neigh_cell_list[i].q_offset_range]) + " "; } + for(i=0; iintra_freq_black_cell_list_size; i++) + { + tmp_msg += "blacklist_phys_cell_id_begin[" + to_string(i) + "]="; + tmp_msg += to_string(sib4->intra_freq_black_cell_list[i].start) + " "; + tmp_msg += "blacklist_phys_cell_id_end[" + to_string(i) + "]="; + tmp_msg += to_string(sib4->intra_freq_black_cell_list[i].start + liblte_rrc_phys_cell_id_range_num[sib4->intra_freq_black_cell_list[i].range]) + " "; + } + if(true == sib4->csg_phys_cell_id_range_present) + { + tmp_msg += "csg_phys_cell_id_begin=" + to_string(sib4->csg_phys_cell_id_range.start) + " "; + tmp_msg += "csg_phys_cell_id_end=" + to_string(sib4->csg_phys_cell_id_range.start + liblte_rrc_phys_cell_id_range_num[sib4->csg_phys_cell_id_range.range]) + " "; + } + + tmp_msg += "\n"; ctrl_socket->send(tmp_msg); } } @@ -835,89 +819,84 @@ void LTE_fdd_dl_scan_interface::send_ctrl_sib5_decoded_msg(LTE_FDD_DL_SCAN_CHAN_ LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_5_STRUCT *sib5, uint32 sfn) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; - uint32 i; - uint32 j; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; + uint32 i; + uint32 j; if(ctrl_connected) { - tmp_msg = "info sib5_decoded "; - try + tmp_msg = "info sib5_decoded "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "freq_offset=" + to_string(chan_data->freq_offset) + " "; + tmp_msg += "phys_cell_id=" + to_string(chan_data->N_id_cell) + " "; + tmp_msg += "sfn=" + to_string(sfn) + " "; + + for(i=0; iinter_freq_carrier_freq_list_size; i++) { - tmp_msg += "freq=" + boost::lexical_cast(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; - tmp_msg += "dl_earfcn=" + boost::lexical_cast(current_dl_earfcn) + " "; - tmp_msg += "freq_offset=" + boost::lexical_cast(chan_data->freq_offset) + " "; - tmp_msg += "phys_cell_id=" + boost::lexical_cast(chan_data->N_id_cell) + " "; - tmp_msg += "sfn=" + boost::lexical_cast(sfn) + " "; - - for(i=0; iinter_freq_carrier_freq_list_size; i++) + tmp_msg += "earfcn[" + to_string(i) + "]="; + tmp_msg += to_string(sib5->inter_freq_carrier_freq_list[i].dl_carrier_freq) + " "; + tmp_msg += "q_rx_lev_min[" + to_string(i) + "]="; + tmp_msg += to_string(sib5->inter_freq_carrier_freq_list[i].q_rx_lev_min) + " "; + if(true == sib5->inter_freq_carrier_freq_list[i].p_max_present) { - tmp_msg += "earfcn[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib5->inter_freq_carrier_freq_list[i].dl_carrier_freq) + " "; - tmp_msg += "q_rx_lev_min[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((int32)sib5->inter_freq_carrier_freq_list[i].q_rx_lev_min) + " "; - if(true == sib5->inter_freq_carrier_freq_list[i].p_max_present) - { - tmp_msg += "p_max[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((int32)sib5->inter_freq_carrier_freq_list[i].p_max) + " "; - } - tmp_msg += "t_resel_eutra[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib5->inter_freq_carrier_freq_list[i].t_resel_eutra) + " "; - if(true == sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf_present) - { - tmp_msg += "t_resel_eutra_sf_medium[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_sssf_medium_text[sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf.sf_medium]) + " "; - tmp_msg += "t_resel_eutra_sf_high[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_sssf_high_text[sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf.sf_high]) + " "; - } - tmp_msg += "thresh_x_high[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib5->inter_freq_carrier_freq_list[i].threshx_high) + " "; - tmp_msg += "thresh_x_low[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib5->inter_freq_carrier_freq_list[i].threshx_low) + " "; - tmp_msg += "allowed_meas_bw[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_allowed_meas_bandwidth_text[sib5->inter_freq_carrier_freq_list[i].allowed_meas_bw]) + " "; - if(true == sib5->inter_freq_carrier_freq_list[i].presence_ant_port_1) - { - tmp_msg += "presence_ant_port_1[" + boost::lexical_cast(i) + "]=true "; - }else{ - tmp_msg += "presence_ant_port_1[" + boost::lexical_cast(i) + "]=false "; - } - if(true == sib5->inter_freq_carrier_freq_list[i].cell_resel_prio_present) + tmp_msg += "p_max[" + to_string(i) + "]="; + tmp_msg += to_string(sib5->inter_freq_carrier_freq_list[i].p_max) + " "; + } + tmp_msg += "t_resel_eutra[" + to_string(i) + "]="; + tmp_msg += to_string(sib5->inter_freq_carrier_freq_list[i].t_resel_eutra) + " "; + if(true == sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf_present) + { + tmp_msg += "t_resel_eutra_sf_medium[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_sssf_medium_text[sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf.sf_medium]) + " "; + tmp_msg += "t_resel_eutra_sf_high[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_sssf_high_text[sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf.sf_high]) + " "; + } + tmp_msg += "thresh_x_high[" + to_string(i) + "]="; + tmp_msg += to_string(sib5->inter_freq_carrier_freq_list[i].threshx_high) + " "; + tmp_msg += "thresh_x_low[" + to_string(i) + "]="; + tmp_msg += to_string(sib5->inter_freq_carrier_freq_list[i].threshx_low) + " "; + tmp_msg += "allowed_meas_bw[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_allowed_meas_bandwidth_text[sib5->inter_freq_carrier_freq_list[i].allowed_meas_bw]) + " "; + if(true == sib5->inter_freq_carrier_freq_list[i].presence_ant_port_1) + { + tmp_msg += "presence_ant_port_1[" + to_string(i) + "]=true "; + }else{ + tmp_msg += "presence_ant_port_1[" + to_string(i) + "]=false "; + } + if(true == sib5->inter_freq_carrier_freq_list[i].cell_resel_prio_present) + { + tmp_msg += "cell_resel_prio[" + to_string(i) + "]="; + tmp_msg += to_string(sib5->inter_freq_carrier_freq_list[i].cell_resel_prio) + " "; + } + tmp_msg += "neigh_cell_cnfg[" + to_string(i) + "]="; + tmp_msg += to_string(sib5->inter_freq_carrier_freq_list[i].neigh_cell_cnfg) + " "; + tmp_msg += "q_offset_freq[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_q_offset_range_text[sib5->inter_freq_carrier_freq_list[i].q_offset_freq]) + " "; + if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size) + { + for(j=0; jinter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size; j++) { - tmp_msg += "cell_resel_prio[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib5->inter_freq_carrier_freq_list[i].cell_resel_prio) + " "; + tmp_msg += "phys_cell_id[" + to_string(i) + "][" + to_string(j) + "]="; + tmp_msg += to_string(sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list[j].phys_cell_id) + " "; + tmp_msg += "q_offset_cell[" + to_string(i) + "][" + to_string(j) + "]="; + tmp_msg += to_string(liblte_rrc_q_offset_range_text[sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list[j].q_offset_cell]) + " "; } - tmp_msg += "neigh_cell_cnfg[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib5->inter_freq_carrier_freq_list[i].neigh_cell_cnfg) + " "; - tmp_msg += "q_offset_freq[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_q_offset_range_text[sib5->inter_freq_carrier_freq_list[i].q_offset_freq]) + " "; - if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size) - { - for(j=0; jinter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size; j++) - { - tmp_msg += "phys_cell_id[" + boost::lexical_cast(i) + "][" + boost::lexical_cast(j) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list[j].phys_cell_id) + " "; - tmp_msg += "q_offset_cell[" + boost::lexical_cast(i) + "][" + boost::lexical_cast(j) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_q_offset_range_text[sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list[j].q_offset_cell]) + " "; - } - } - if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size) + } + if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size) + { + for(j=0; jinter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size; j++) { - for(j=0; jinter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size; j++) - { - tmp_msg += "blacklisted_earfcn_start[" + boost::lexical_cast(i) + "][" + boost::lexical_cast(j) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list[j].start) + " "; - tmp_msg += "blacklisted_earfcn_end[" + boost::lexical_cast(i) + "][" + boost::lexical_cast(j) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list[j].start + liblte_rrc_phys_cell_id_range_num[sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list[j].range]) + " "; - } + tmp_msg += "blacklisted_earfcn_start[" + to_string(i) + "][" + to_string(j) + "]="; + tmp_msg += to_string(sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list[j].start) + " "; + tmp_msg += "blacklisted_earfcn_end[" + to_string(i) + "][" + to_string(j) + "]="; + tmp_msg += to_string(sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list[j].start + liblte_rrc_phys_cell_id_range_num[sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list[j].range]) + " "; } } - - tmp_msg += "\n"; - }catch(boost::bad_lexical_cast &){ - tmp_msg += "\n"; } + + tmp_msg += "\n"; ctrl_socket->send(tmp_msg); } } @@ -925,393 +904,413 @@ void LTE_fdd_dl_scan_interface::send_ctrl_sib6_decoded_msg(LTE_FDD_DL_SCAN_CHAN_ LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_6_STRUCT *sib6, uint32 sfn) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; - uint32 i; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; + uint32 i; if(ctrl_connected) { - tmp_msg = "info sib6_decoded "; - try + tmp_msg = "info sib6_decoded "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "freq_offset=" + to_string(chan_data->freq_offset) + " "; + tmp_msg += "phys_cell_id=" + to_string(chan_data->N_id_cell) + " "; + tmp_msg += "sfn=" + to_string(sfn) + " "; + + for(i=0; icarrier_freq_list_utra_fdd_size; i++) + { + tmp_msg += "uarfcn[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_fdd[i].carrier_freq) + " "; + if(true == sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present) + { + tmp_msg += "cell_resel_prio[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio) + " "; + } + tmp_msg += "thresh_x_high[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_fdd[i].threshx_high) + " "; + tmp_msg += "thresh_x_low[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_fdd[i].threshx_low) + " "; + tmp_msg += "q_rx_lev_min[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_fdd[i].q_rx_lev_min) + " "; + tmp_msg += "p_max_utra[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_fdd[i].p_max_utra) + " "; + tmp_msg += "q_qual_min[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_fdd[i].q_qual_min) + " "; + } + for(i=0; icarrier_freq_list_utra_tdd_size; i++) { - tmp_msg += "freq=" + boost::lexical_cast(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; - tmp_msg += "dl_earfcn=" + boost::lexical_cast(current_dl_earfcn) + " "; - tmp_msg += "freq_offset=" + boost::lexical_cast(chan_data->freq_offset) + " "; - tmp_msg += "phys_cell_id=" + boost::lexical_cast(chan_data->N_id_cell) + " "; - tmp_msg += "sfn=" + boost::lexical_cast(sfn) + " "; + tmp_msg += "uarfcn[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_tdd[i].carrier_freq) + " "; + if(true == sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present) + { + tmp_msg += "cell_resel_prio[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio) + " "; + } + tmp_msg += "thresh_x_high[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_tdd[i].threshx_high) + " "; + tmp_msg += "thresh_x_low[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_tdd[i].threshx_low) + " "; + tmp_msg += "q_rx_lev_min[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_tdd[i].q_rx_lev_min) + " "; + tmp_msg += "p_max_utra[" + to_string(i) + "]="; + tmp_msg += to_string(sib6->carrier_freq_list_utra_tdd[i].p_max_utra) + " "; + } + tmp_msg += "t_resel_utra=" + to_string(sib6->t_resel_utra) + " "; + if(true == sib6->t_resel_utra_sf_present) + { + tmp_msg += "t_resel_utra_sf_medium=" + to_string(liblte_rrc_sssf_medium_text[sib6->t_resel_utra_sf.sf_medium]) + " "; + tmp_msg += "t_resel_utra_sf_high=" + to_string(liblte_rrc_sssf_high_text[sib6->t_resel_utra_sf.sf_high]) + " "; + } + + tmp_msg += "\n"; + ctrl_socket->send(tmp_msg); + } +} +void LTE_fdd_dl_scan_interface::send_ctrl_sib7_decoded_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data, + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7_STRUCT *sib7, + uint32 sfn) +{ + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; + uint32 i; + uint32 j; - for(i=0; icarrier_freq_list_utra_fdd_size; i++) + if(ctrl_connected) + { + tmp_msg = "info sib7_decoded "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "freq_offset=" + to_string(chan_data->freq_offset) + " "; + tmp_msg += "phys_cell_id=" + to_string(chan_data->N_id_cell) + " "; + tmp_msg += "sfn=" + to_string(sfn) + " "; + + tmp_msg += "t_resel_geran=" + to_string(sib7->t_resel_geran) + " "; + if(true == sib7->t_resel_geran_sf_present) + { + tmp_msg += "t_resel_geran_sf_medium=" + to_string(liblte_rrc_sssf_medium_text[sib7->t_resel_geran_sf.sf_medium]) + " "; + tmp_msg += "t_resel_geran_sf_high=" + to_string(liblte_rrc_sssf_high_text[sib7->t_resel_geran_sf.sf_high]) + " "; + } + for(i=0; icarrier_freqs_info_list_size; i++) + { + tmp_msg += "geran_neigh_starting_arfcn[" + to_string(i) + "]="; + tmp_msg += to_string(sib7->carrier_freqs_info_list[i].carrier_freqs.starting_arfcn) + " "; + tmp_msg += "geran_neigh_band_ind[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_band_indicator_geran_text[sib7->carrier_freqs_info_list[i].carrier_freqs.band_indicator]) + " "; + if(LIBLTE_RRC_FOLLOWING_ARFCNS_EXPLICIT_LIST == sib7->carrier_freqs_info_list[i].carrier_freqs.following_arfcns) { - tmp_msg += "uarfcn[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib6->carrier_freq_list_utra_fdd[i].carrier_freq) + " "; - if(true == sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present) + for(j=0; jcarrier_freqs_info_list[i].carrier_freqs.explicit_list_of_arfcns_size; j++) { - tmp_msg += "cell_resel_prio[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio) + " "; + tmp_msg += "geran_neigh_arfcns[" + to_string(i) + "][" + to_string(j) + "]="; + tmp_msg += to_string(sib7->carrier_freqs_info_list[i].carrier_freqs.explicit_list_of_arfcns[j]) + " "; } - tmp_msg += "thresh_x_high[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib6->carrier_freq_list_utra_fdd[i].threshx_high) + " "; - tmp_msg += "thresh_x_low[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib6->carrier_freq_list_utra_fdd[i].threshx_low) + " "; - tmp_msg += "q_rx_lev_min[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((int32)sib6->carrier_freq_list_utra_fdd[i].q_rx_lev_min) + " "; - tmp_msg += "p_max_utra[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((int32)sib6->carrier_freq_list_utra_fdd[i].p_max_utra) + " "; - tmp_msg += "q_qual_min[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((int32)sib6->carrier_freq_list_utra_fdd[i].q_qual_min) + " "; + }else if(LIBLTE_RRC_FOLLOWING_ARFCNS_EQUALLY_SPACED == sib7->carrier_freqs_info_list[i].carrier_freqs.following_arfcns){ + tmp_msg += "geran_neigh_arfcn_spacing[" + to_string(i) + "]="; + tmp_msg += to_string(sib7->carrier_freqs_info_list[i].carrier_freqs.equally_spaced_arfcns.arfcn_spacing) + " "; + tmp_msg += "geran_neigh_num_arfcns[" + to_string(i) + "]="; + tmp_msg += to_string(sib7->carrier_freqs_info_list[i].carrier_freqs.equally_spaced_arfcns.number_of_arfcns) + " "; + }else{ + tmp_msg += "geran_neigh_arfcn_bitmap[" + to_string(i) + "]="; + tmp_msg += to_string(sib7->carrier_freqs_info_list[i].carrier_freqs.variable_bit_map_of_arfcns); } - for(i=0; icarrier_freq_list_utra_tdd_size; i++) + if(true == sib7->carrier_freqs_info_list[i].cell_resel_prio_present) { - tmp_msg += "uarfcn[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib6->carrier_freq_list_utra_tdd[i].carrier_freq) + " "; - if(true == sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present) - { - tmp_msg += "cell_resel_prio[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio) + " "; - } - tmp_msg += "thresh_x_high[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib6->carrier_freq_list_utra_tdd[i].threshx_high) + " "; - tmp_msg += "thresh_x_low[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib6->carrier_freq_list_utra_tdd[i].threshx_low) + " "; - tmp_msg += "q_rx_lev_min[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((int32)sib6->carrier_freq_list_utra_tdd[i].q_rx_lev_min) + " "; - tmp_msg += "p_max_utra[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((int32)sib6->carrier_freq_list_utra_tdd[i].p_max_utra) + " "; + tmp_msg += "cell_resel_prio[" + to_string(i) + "]="; + tmp_msg += to_string(sib7->carrier_freqs_info_list[i].cell_resel_prio) + " "; } - tmp_msg += "t_resel_utra=" + boost::lexical_cast((uint32)sib6->t_resel_utra) + " "; - if(true == sib6->t_resel_utra_sf_present) + tmp_msg += "ncc_permitted[" + to_string(i) + "]="; + tmp_msg += to_string(sib7->carrier_freqs_info_list[i].ncc_permitted); + tmp_msg += "q_rx_lev_min[" + to_string(i) + "]="; + tmp_msg += to_string(sib7->carrier_freqs_info_list[i].q_rx_lev_min) + " "; + if(true == sib7->carrier_freqs_info_list[i].p_max_geran_present) { - tmp_msg += "t_resel_utra_sf_medium=" + boost::lexical_cast(liblte_rrc_sssf_medium_text[sib6->t_resel_utra_sf.sf_medium]) + " "; - tmp_msg += "t_resel_utra_sf_high=" + boost::lexical_cast(liblte_rrc_sssf_high_text[sib6->t_resel_utra_sf.sf_high]) + " "; + tmp_msg += "p_max_geran[" + to_string(i) + "]="; + tmp_msg += to_string(sib7->carrier_freqs_info_list[i].p_max_geran) + " "; } - - tmp_msg += "\n"; - }catch(boost::bad_lexical_cast &){ - tmp_msg += "\n"; + tmp_msg += "thresh_x_high[" + to_string(i) + "]="; + tmp_msg += to_string(sib7->carrier_freqs_info_list[i].threshx_high) + " "; + tmp_msg += "thresh_x_low[" + to_string(i) + "]="; + tmp_msg += to_string(sib7->carrier_freqs_info_list[i].threshx_low) + " "; } + + tmp_msg += "\n"; ctrl_socket->send(tmp_msg); } } -void LTE_fdd_dl_scan_interface::send_ctrl_sib7_decoded_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data, - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7_STRUCT *sib7, +void LTE_fdd_dl_scan_interface::send_ctrl_sib8_decoded_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data, + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT *sib8, uint32 sfn) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; - uint32 i; - uint32 j; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; + uint32 i; + uint32 j; + uint32 k; if(ctrl_connected) { - tmp_msg = "info sib7_decoded "; - try + tmp_msg = "info sib8_decoded "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "freq_offset=" + to_string(chan_data->freq_offset) + " "; + tmp_msg += "phys_cell_id=" + to_string(chan_data->N_id_cell) + " "; + tmp_msg += "sfn=" + to_string(sfn) + " "; + + if(true == sib8->sys_time_info_present) + { + if(true == sib8->sys_time_info_cdma2000.cdma_eutra_sync) + { + tmp_msg += "cdma_eutra_sync=true "; + }else{ + tmp_msg += "cdma_eutra_sync=false "; + } + if(true == sib8->sys_time_info_cdma2000.system_time_async) + { + tmp_msg += "system_time=" + to_string(sib8->sys_time_info_cdma2000.system_time * 8) + " "; + }else{ + tmp_msg += "system_time=" + to_string(sib8->sys_time_info_cdma2000.system_time * 10) + " "; + } + } + if(true == sib8->search_win_size_present) + { + tmp_msg += "search_win_size=" + to_string(sib8->search_win_size) + " "; + } + if(true == sib8->params_hrpd_present) { - tmp_msg += "freq=" + boost::lexical_cast(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; - tmp_msg += "dl_earfcn=" + boost::lexical_cast(current_dl_earfcn) + " "; - tmp_msg += "freq_offset=" + boost::lexical_cast(chan_data->freq_offset) + " "; - tmp_msg += "phys_cell_id=" + boost::lexical_cast(chan_data->N_id_cell) + " "; - tmp_msg += "sfn=" + boost::lexical_cast(sfn) + " "; - - tmp_msg += "t_resel_geran=" + boost::lexical_cast((uint32)sib7->t_resel_geran) + " "; - if(true == sib7->t_resel_geran_sf_present) + if(true == sib8->pre_reg_info_hrpd.pre_reg_allowed) + { + tmp_msg += "pre_registration=allowed "; + }else{ + tmp_msg += "pre_registration=not_allowed "; + } + if(true == sib8->pre_reg_info_hrpd.pre_reg_zone_id_present) { - tmp_msg += "t_resel_geran_sf_medium=" + boost::lexical_cast(liblte_rrc_sssf_medium_text[sib7->t_resel_geran_sf.sf_medium]) + " "; - tmp_msg += "t_resel_geran_sf_high=" + boost::lexical_cast(liblte_rrc_sssf_high_text[sib7->t_resel_geran_sf.sf_high]) + " "; + tmp_msg += "pre_reg_zone_id=" + to_string(sib8->pre_reg_info_hrpd.pre_reg_zone_id) + " "; } - for(i=0; icarrier_freqs_info_list_size; i++) + for(i=0; ipre_reg_info_hrpd.secondary_pre_reg_zone_id_list_size; i++) { - tmp_msg += "geran_neigh_starting_arfcn[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib7->carrier_freqs_info_list[i].carrier_freqs.starting_arfcn) + " "; - tmp_msg += "geran_neigh_band_ind[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_band_indicator_geran_text[sib7->carrier_freqs_info_list[i].carrier_freqs.band_indicator]) + " "; - if(LIBLTE_RRC_FOLLOWING_ARFCNS_EXPLICIT_LIST == sib7->carrier_freqs_info_list[i].carrier_freqs.following_arfcns) + tmp_msg += "secondary_pre_reg_zone_id[" + to_string(i) + "]="; + tmp_msg += to_string(sib8->pre_reg_info_hrpd.secondary_pre_reg_zone_id_list[i]) + " "; + } + if(true == sib8->cell_resel_params_hrpd_present) + { + for(i=0; icell_resel_params_hrpd.band_class_list_size; i++) { - for(j=0; jcarrier_freqs_info_list[i].carrier_freqs.explicit_list_of_arfcns_size; j++) + tmp_msg += "band_class[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_band_class_cdma2000_text[sib8->cell_resel_params_hrpd.band_class_list[i].band_class]) + " "; + if(true == sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present) { - tmp_msg += "geran_neigh_arfcns[" + boost::lexical_cast(i) + "][" + boost::lexical_cast(j) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib7->carrier_freqs_info_list[i].carrier_freqs.explicit_list_of_arfcns[j]) + " "; + tmp_msg += "cell_resel_prio[" + to_string(i) + "]="; + tmp_msg += to_string(sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio) + " "; } - }else if(LIBLTE_RRC_FOLLOWING_ARFCNS_EQUALLY_SPACED == sib7->carrier_freqs_info_list[i].carrier_freqs.following_arfcns){ - tmp_msg += "geran_neigh_arfcn_spacing[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib7->carrier_freqs_info_list[i].carrier_freqs.equally_spaced_arfcns.arfcn_spacing) + " "; - tmp_msg += "geran_neigh_num_arfcns[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib7->carrier_freqs_info_list[i].carrier_freqs.equally_spaced_arfcns.number_of_arfcns) + " "; - }else{ - tmp_msg += "geran_neigh_arfcn_bitmap[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib7->carrier_freqs_info_list[i].carrier_freqs.variable_bit_map_of_arfcns); + tmp_msg += "thresh_x_high[" + to_string(i) + "]="; + tmp_msg += to_string(sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_high) + " "; + tmp_msg += "thresh_x_low[" + to_string(i) + "]="; + tmp_msg += to_string(sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_low) + " "; } - if(true == sib7->carrier_freqs_info_list[i].cell_resel_prio_present) + for(i=0; icell_resel_params_hrpd.neigh_cell_list_size; i++) { - tmp_msg += "cell_resel_prio[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib7->carrier_freqs_info_list[i].cell_resel_prio) + " "; + tmp_msg += "neigh_band_class[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_band_class_cdma2000_text[sib8->cell_resel_params_hrpd.neigh_cell_list[i].band_class]) + " "; + for(j=0; jcell_resel_params_hrpd.neigh_cell_list[i].neigh_cells_per_freq_list_size; j++) + { + tmp_msg += "neigh_cell_arfcn[" + to_string(i) + "][" + to_string(j) + "]="; + tmp_msg += to_string(sib8->cell_resel_params_hrpd.neigh_cell_list[i].neigh_cells_per_freq_list[j].arfcn) + " "; + for(k=0; kcell_resel_params_hrpd.neigh_cell_list[i].neigh_cells_per_freq_list[j].phys_cell_id_list_size; k++) + { + tmp_msg += "neigh_phys_cell_id[" + to_string(i) + "][" + to_string(j) + "][" + to_string(k); + tmp_msg += "]=" + to_string(sib8->cell_resel_params_hrpd.neigh_cell_list[i].neigh_cells_per_freq_list[j].phys_cell_id_list[k]) + " "; + } + } } - tmp_msg += "ncc_permitted[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib7->carrier_freqs_info_list[i].ncc_permitted); - tmp_msg += "q_rx_lev_min[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(sib7->carrier_freqs_info_list[i].q_rx_lev_min) + " "; - if(true == sib7->carrier_freqs_info_list[i].p_max_geran_present) + tmp_msg += "t_resel=" + to_string(sib8->cell_resel_params_hrpd.t_resel_cdma2000) + " "; + if(true == sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf_present) { - tmp_msg += "p_max_geran[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib7->carrier_freqs_info_list[i].p_max_geran) + " "; + tmp_msg += "t_resel_sf_medium=" + to_string(liblte_rrc_sssf_medium_text[sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf.sf_medium]) + " "; + tmp_msg += "t_resel_sf_high=" + to_string(liblte_rrc_sssf_high_text[sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf.sf_high]) + " "; } - tmp_msg += "thresh_x_high[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib7->carrier_freqs_info_list[i].threshx_high) + " "; - tmp_msg += "thresh_x_low[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib7->carrier_freqs_info_list[i].threshx_low) + " "; } - - tmp_msg += "\n"; - }catch(boost::bad_lexical_cast &){ - tmp_msg += "\n"; } - ctrl_socket->send(tmp_msg); - } -} -void LTE_fdd_dl_scan_interface::send_ctrl_sib8_decoded_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data, - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT *sib8, - uint32 sfn) -{ - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; - uint32 i; - uint32 j; - uint32 k; - - if(ctrl_connected) - { - tmp_msg = "info sib8_decoded "; - try + if(true == sib8->params_1xrtt_present) { - tmp_msg += "freq=" + boost::lexical_cast(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; - tmp_msg += "dl_earfcn=" + boost::lexical_cast(current_dl_earfcn) + " "; - tmp_msg += "freq_offset=" + boost::lexical_cast(chan_data->freq_offset) + " "; - tmp_msg += "phys_cell_id=" + boost::lexical_cast(chan_data->N_id_cell) + " "; - tmp_msg += "sfn=" + boost::lexical_cast(sfn) + " "; - - if(true == sib8->sys_time_info_present) + if(true == sib8->csfb_reg_param_1xrtt_present) { - if(true == sib8->sys_time_info_cdma2000.cdma_eutra_sync) + tmp_msg += "csfb_sid=" + to_string(sib8->csfb_reg_param_1xrtt.sid) + " "; + tmp_msg += "csfb_nid=" + to_string(sib8->csfb_reg_param_1xrtt.nid) + " "; + if(true == sib8->csfb_reg_param_1xrtt.multiple_sid) { - tmp_msg += "cdma_eutra_sync=true "; + tmp_msg += "csfb_multiple_sids=true "; }else{ - tmp_msg += "cdma_eutra_sync=false "; + tmp_msg += "csfb_multiple_sids=false "; } - if(true == sib8->sys_time_info_cdma2000.system_time_async) + if(true == sib8->csfb_reg_param_1xrtt.multiple_nid) { - tmp_msg += "system_time=" + boost::lexical_cast(sib8->sys_time_info_cdma2000.system_time * 8) + " "; + tmp_msg += "csfb_multiple_nids=true "; }else{ - tmp_msg += "system_time=" + boost::lexical_cast(sib8->sys_time_info_cdma2000.system_time * 10) + " "; + tmp_msg += "csfb_multiple_nids=false "; } - } - if(true == sib8->search_win_size_present) - { - tmp_msg += "search_win_size=" + boost::lexical_cast((uint32)sib8->search_win_size) + " "; - } - if(true == sib8->params_hrpd_present) - { - if(true == sib8->pre_reg_info_hrpd.pre_reg_allowed) + if(true == sib8->csfb_reg_param_1xrtt.home_reg) { - tmp_msg += "pre_registration=allowed "; + tmp_msg += "csfb_home_reg=true "; }else{ - tmp_msg += "pre_registration=not_allowed "; + tmp_msg += "csfb_home_reg=false "; } - if(true == sib8->pre_reg_info_hrpd.pre_reg_zone_id_present) + if(true == sib8->csfb_reg_param_1xrtt.foreign_sid_reg) { - tmp_msg += "pre_reg_zone_id=" + boost::lexical_cast((uint32)sib8->pre_reg_info_hrpd.pre_reg_zone_id) + " "; + tmp_msg += "csfb_foreign_sid_reg=true "; + }else{ + tmp_msg += "csfb_foreign_sid_reg=false "; } - for(i=0; ipre_reg_info_hrpd.secondary_pre_reg_zone_id_list_size; i++) + if(true == sib8->csfb_reg_param_1xrtt.foreign_nid_reg) { - tmp_msg += "secondary_pre_reg_zone_id[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib8->pre_reg_info_hrpd.secondary_pre_reg_zone_id_list[i]) + " "; + tmp_msg += "csfb_foreign_nid_reg=true "; + }else{ + tmp_msg += "csfb_foreign_nid_reg=false "; } - if(true == sib8->cell_resel_params_hrpd_present) + if(true == sib8->csfb_reg_param_1xrtt.param_reg) { - for(i=0; icell_resel_params_hrpd.band_class_list_size; i++) - { - tmp_msg += "band_class[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_band_class_cdma2000_text[sib8->cell_resel_params_hrpd.band_class_list[i].band_class]) + " "; - if(true == sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present) - { - tmp_msg += "cell_resel_prio[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio) + " "; - } - tmp_msg += "thresh_x_high[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_high) + " "; - tmp_msg += "thresh_x_low[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_low) + " "; - } - for(i=0; icell_resel_params_hrpd.neigh_cell_list_size; i++) - { - tmp_msg += "neigh_band_class[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_band_class_cdma2000_text[sib8->cell_resel_params_hrpd.neigh_cell_list[i].band_class]) + " "; - for(j=0; jcell_resel_params_hrpd.neigh_cell_list[i].neigh_cells_per_freq_list_size; j++) - { - tmp_msg += "neigh_cell_arfcn[" + boost::lexical_cast(i) + "][" + boost::lexical_cast(j) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib8->cell_resel_params_hrpd.neigh_cell_list[i].neigh_cells_per_freq_list[j].arfcn) + " "; - for(k=0; kcell_resel_params_hrpd.neigh_cell_list[i].neigh_cells_per_freq_list[j].phys_cell_id_list_size; k++) - { - tmp_msg += "neigh_phys_cell_id[" + boost::lexical_cast(i) + "][" + boost::lexical_cast(j) + "][" + boost::lexical_cast(k); - tmp_msg += "]=" + boost::lexical_cast((uint32)sib8->cell_resel_params_hrpd.neigh_cell_list[i].neigh_cells_per_freq_list[j].phys_cell_id_list[k]) + " "; - } - } - } - tmp_msg += "t_resel=" + boost::lexical_cast((uint32)sib8->cell_resel_params_hrpd.t_resel_cdma2000) + " "; - if(true == sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf_present) - { - tmp_msg += "t_resel_sf_medium=" + boost::lexical_cast(liblte_rrc_sssf_medium_text[sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf.sf_medium]) + " "; - tmp_msg += "t_resel_sf_high=" + boost::lexical_cast(liblte_rrc_sssf_high_text[sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf.sf_high]) + " "; - } + tmp_msg += "csfb_param_reg=true "; + }else{ + tmp_msg += "csfb_param_reg=false "; + } + if(true == sib8->csfb_reg_param_1xrtt.power_up_reg) + { + tmp_msg += "csfb_power_up_reg=true "; + }else{ + tmp_msg += "csfb_power_up_reg=false "; } + tmp_msg += "csfb_reg_period=" + to_string(sib8->csfb_reg_param_1xrtt.reg_period) + " "; + tmp_msg += "csfb_reg_zone=" + to_string(sib8->csfb_reg_param_1xrtt.reg_zone) + " "; + tmp_msg += "csfb_total_zones=" + to_string(sib8->csfb_reg_param_1xrtt.total_zone) + " "; + tmp_msg += "csfb_zone_timer=" + to_string(sib8->csfb_reg_param_1xrtt.zone_timer) + " "; + } + if(true == sib8->long_code_state_1xrtt_present) + { + tmp_msg += "long_code_state=" + to_string(sib8->long_code_state_1xrtt) + " "; } - if(true == sib8->params_1xrtt_present) + if(true == sib8->cell_resel_params_1xrtt_present) { - if(true == sib8->csfb_reg_param_1xrtt_present) + for(i=0; icell_resel_params_1xrtt.band_class_list_size; i++) { - tmp_msg += "csfb_sid=" + boost::lexical_cast((uint32)sib8->csfb_reg_param_1xrtt.sid) + " "; - tmp_msg += "csfb_nid=" + boost::lexical_cast((uint32)sib8->csfb_reg_param_1xrtt.nid) + " "; - if(true == sib8->csfb_reg_param_1xrtt.multiple_sid) - { - tmp_msg += "csfb_multiple_sids=true "; - }else{ - tmp_msg += "csfb_multiple_sids=false "; - } - if(true == sib8->csfb_reg_param_1xrtt.multiple_nid) - { - tmp_msg += "csfb_multiple_nids=true "; - }else{ - tmp_msg += "csfb_multiple_nids=false "; - } - if(true == sib8->csfb_reg_param_1xrtt.home_reg) - { - tmp_msg += "csfb_home_reg=true "; - }else{ - tmp_msg += "csfb_home_reg=false "; - } - if(true == sib8->csfb_reg_param_1xrtt.foreign_sid_reg) + tmp_msg += "band_class[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_band_class_cdma2000_text[sib8->cell_resel_params_1xrtt.band_class_list[i].band_class]); + if(true == sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present) { - tmp_msg += "csfb_foreign_sid_reg=true "; - }else{ - tmp_msg += "csfb_foreign_sid_reg=false "; + tmp_msg += "cell_resel_prio[" + to_string(i) + "]="; + tmp_msg += to_string(sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio) + " "; } - if(true == sib8->csfb_reg_param_1xrtt.foreign_nid_reg) - { - tmp_msg += "csfb_foreign_nid_reg=true "; - }else{ - tmp_msg += "csfb_foreign_nid_reg=false "; - } - if(true == sib8->csfb_reg_param_1xrtt.param_reg) - { - tmp_msg += "csfb_param_reg=true "; - }else{ - tmp_msg += "csfb_param_reg=false "; - } - if(true == sib8->csfb_reg_param_1xrtt.power_up_reg) - { - tmp_msg += "csfb_power_up_reg=true "; - }else{ - tmp_msg += "csfb_power_up_reg=false "; - } - tmp_msg += "csfb_reg_period=" + boost::lexical_cast((uint32)sib8->csfb_reg_param_1xrtt.reg_period) + " "; - tmp_msg += "csfb_reg_zone=" + boost::lexical_cast((uint32)sib8->csfb_reg_param_1xrtt.reg_zone) + " "; - tmp_msg += "csfb_total_zones=" + boost::lexical_cast((uint32)sib8->csfb_reg_param_1xrtt.total_zone) + " "; - tmp_msg += "csfb_zone_timer=" + boost::lexical_cast((uint32)sib8->csfb_reg_param_1xrtt.zone_timer) + " "; + tmp_msg += "thresh_x_high[" + to_string(i) + "]="; + tmp_msg += to_string(sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_high) + " "; + tmp_msg += "thresh_x_low[" + to_string(i) + "]="; + tmp_msg += to_string(sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_low) + " "; } - if(true == sib8->long_code_state_1xrtt_present) + for(i=0; icell_resel_params_1xrtt.neigh_cell_list_size; i++) { - tmp_msg += "long_code_state=" + boost::lexical_cast(sib8->long_code_state_1xrtt) + " "; - } - if(true == sib8->cell_resel_params_1xrtt_present) - { - for(i=0; icell_resel_params_1xrtt.band_class_list_size; i++) - { - tmp_msg += "band_class[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_band_class_cdma2000_text[sib8->cell_resel_params_1xrtt.band_class_list[i].band_class]); - if(true == sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present) - { - tmp_msg += "cell_resel_prio[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio) + " "; - } - tmp_msg += "thresh_x_high[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_high) + " "; - tmp_msg += "thresh_x_low[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_low) + " "; - } - for(i=0; icell_resel_params_1xrtt.neigh_cell_list_size; i++) + tmp_msg += "neigh_band_class[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_band_class_cdma2000_text[sib8->cell_resel_params_1xrtt.neigh_cell_list[i].band_class]) + " "; + for(j=0; jcell_resel_params_1xrtt.neigh_cell_list[i].neigh_cells_per_freq_list_size; j++) { - tmp_msg += "neigh_band_class[" + boost::lexical_cast(i) + "]="; - tmp_msg += boost::lexical_cast(liblte_rrc_band_class_cdma2000_text[sib8->cell_resel_params_1xrtt.neigh_cell_list[i].band_class]) + " "; - for(j=0; jcell_resel_params_1xrtt.neigh_cell_list[i].neigh_cells_per_freq_list_size; j++) + tmp_msg += "neigh_arfcn[" + to_string(i) + "][" + to_string(j) + "]="; + tmp_msg += to_string(sib8->cell_resel_params_1xrtt.neigh_cell_list[i].neigh_cells_per_freq_list[j].arfcn) + " "; + for(k=0; kcell_resel_params_1xrtt.neigh_cell_list[i].neigh_cells_per_freq_list[j].phys_cell_id_list_size; k++) { - tmp_msg += "neigh_arfcn[" + boost::lexical_cast(i) + "][" + boost::lexical_cast(j) + "]="; - tmp_msg += boost::lexical_cast((uint32)sib8->cell_resel_params_1xrtt.neigh_cell_list[i].neigh_cells_per_freq_list[j].arfcn) + " "; - for(k=0; kcell_resel_params_1xrtt.neigh_cell_list[i].neigh_cells_per_freq_list[j].phys_cell_id_list_size; k++) - { - tmp_msg += "neigh_phys_cell_id[" + boost::lexical_cast(i) + "][" + boost::lexical_cast(j) + "][" + boost::lexical_cast(k); - tmp_msg += "]=" + boost::lexical_cast((uint32)sib8->cell_resel_params_1xrtt.neigh_cell_list[i].neigh_cells_per_freq_list[j].phys_cell_id_list[k]) + " "; - } + tmp_msg += "neigh_phys_cell_id[" + to_string(i) + "][" + to_string(j) + "][" + to_string(k); + tmp_msg += "]=" + to_string(sib8->cell_resel_params_1xrtt.neigh_cell_list[i].neigh_cells_per_freq_list[j].phys_cell_id_list[k]) + " "; } } - tmp_msg += "t_resel=" + boost::lexical_cast((uint32)sib8->cell_resel_params_1xrtt.t_resel_cdma2000) + " "; - if(true == sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf_present) - { - tmp_msg += "t_resel_sf_medium=" + boost::lexical_cast(liblte_rrc_sssf_medium_text[sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf.sf_medium]); - tmp_msg += "t_resel_sf_high=" + boost::lexical_cast(liblte_rrc_sssf_high_text[sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf.sf_high]); - } + } + tmp_msg += "t_resel=" + to_string(sib8->cell_resel_params_1xrtt.t_resel_cdma2000) + " "; + if(true == sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf_present) + { + tmp_msg += "t_resel_sf_medium=" + to_string(liblte_rrc_sssf_medium_text[sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf.sf_medium]); + tmp_msg += "t_resel_sf_high=" + to_string(liblte_rrc_sssf_high_text[sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf.sf_high]); } } - - tmp_msg += "\n"; - }catch(boost::bad_lexical_cast &){ - tmp_msg += "\n"; } + + tmp_msg += "\n"; ctrl_socket->send(tmp_msg); } } -void LTE_fdd_dl_scan_interface::send_ctrl_channel_found_end_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data) +void LTE_fdd_dl_scan_interface::send_ctrl_sib13_decoded_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data, + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13, + uint32 sfn) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; + uint32 i; if(ctrl_connected) { - tmp_msg = "info channel_found_end "; - try + tmp_msg = "info sib13_decoded "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "freq_offset=" + to_string(chan_data->freq_offset) + " "; + tmp_msg += "phys_cell_id=" + to_string(chan_data->N_id_cell) + " "; + tmp_msg += "sfn=" + to_string(sfn) + " "; + + for(i=0; imbsfn_area_info_list_r9_size; i++) { - tmp_msg += "freq=" + boost::lexical_cast(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; - tmp_msg += "dl_earfcn=" + boost::lexical_cast(current_dl_earfcn) + " "; - tmp_msg += "freq_offset=" + boost::lexical_cast(chan_data->freq_offset) + " "; - tmp_msg += "phys_cell_id=" + boost::lexical_cast(chan_data->N_id_cell) + " "; - tmp_msg += "\n"; - }catch(boost::bad_lexical_cast &){ - tmp_msg += "\n"; + tmp_msg += "mbsfn_area_id_r9[" + to_string(i) + "]="; + tmp_msg += to_string(sib13->mbsfn_area_info_list_r9[i].mbsfn_area_id_r9) + " "; + tmp_msg += "non_mbsfn_region_length[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_non_mbsfn_region_length_text[sib13->mbsfn_area_info_list_r9[i].non_mbsfn_region_length]) + " "; + tmp_msg += "notification_indicator_r9[" + to_string(i) + "]="; + tmp_msg += to_string(sib13->mbsfn_area_info_list_r9[i].notification_indicator_r9) + " "; + tmp_msg += "mcch_repetition_period_r9[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_mcch_repetition_period_r9_text[sib13->mbsfn_area_info_list_r9[i].mcch_repetition_period_r9]) + " "; + tmp_msg += "mcch_offset_r9[" + to_string(i) + "]="; + tmp_msg += to_string(sib13->mbsfn_area_info_list_r9[i].mcch_offset_r9) + " "; + tmp_msg += "mcch_modification_period_r9[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_mcch_modification_period_r9_text[sib13->mbsfn_area_info_list_r9[i].mcch_modification_period_r9]) + " "; + tmp_msg += "sf_alloc_info_r9[" + to_string(i) + "]="; + tmp_msg += to_string(sib13->mbsfn_area_info_list_r9[i].sf_alloc_info_r9) + " "; + tmp_msg += "signalling_mcs_r9[" + to_string(i) + "]="; + tmp_msg += to_string(liblte_rrc_mcch_signalling_mcs_r9_text[sib13->mbsfn_area_info_list_r9[i].signalling_mcs_r9]) + " "; } + + tmp_msg += "repetition_coeff=" + to_string(liblte_rrc_notification_repetition_coeff_r9_text[sib13->mbms_notification_config.repetition_coeff]) + " "; + tmp_msg += "offset=" + to_string(sib13->mbms_notification_config.offset) + " "; + tmp_msg += "sf_index=" + to_string(sib13->mbms_notification_config.sf_index) + " "; + + tmp_msg += "\n"; + ctrl_socket->send(tmp_msg); + } +} +void LTE_fdd_dl_scan_interface::send_ctrl_channel_found_end_msg(LTE_FDD_DL_SCAN_CHAN_DATA_STRUCT *chan_data) +{ + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; + + if(ctrl_connected) + { + tmp_msg = "info channel_found_end "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "freq_offset=" + to_string(chan_data->freq_offset) + " "; + tmp_msg += "phys_cell_id=" + to_string(chan_data->N_id_cell) + " "; + tmp_msg += "\n"; ctrl_socket->send(tmp_msg); } } void LTE_fdd_dl_scan_interface::send_ctrl_channel_not_found_msg(void) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; if(ctrl_connected) { - tmp_msg = "info channel_not_found "; - try - { - tmp_msg += "freq=" + boost::lexical_cast(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; - tmp_msg += "dl_earfcn=" + boost::lexical_cast(current_dl_earfcn) + " "; - tmp_msg += "\n"; - }catch(boost::bad_lexical_cast &){ - tmp_msg += "\n"; - } + tmp_msg = "info channel_not_found "; + tmp_msg += "freq=" + to_string(liblte_interface_dl_earfcn_to_frequency(current_dl_earfcn)) + " "; + tmp_msg += "dl_earfcn=" + to_string(current_dl_earfcn) + " "; + tmp_msg += "\n"; ctrl_socket->send(tmp_msg); } } void LTE_fdd_dl_scan_interface::send_ctrl_status_msg(LTE_FDD_DL_SCAN_STATUS_ENUM status, std::string msg) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; if(ctrl_connected) { @@ -1453,16 +1452,16 @@ void LTE_fdd_dl_scan_interface::handle_ctrl_connect(void) { LTE_fdd_dl_scan_interface *interface = LTE_fdd_dl_scan_interface::get_instance(); - connect_mutex.lock(); + pthread_mutex_lock(&connect_mutex); LTE_fdd_dl_scan_interface::ctrl_connected = true; - connect_mutex.unlock(); + pthread_mutex_unlock(&connect_mutex); interface->send_ctrl_msg("*** LTE FDD DL SCAN ***"); interface->send_ctrl_msg("Type help to see a list of commands"); } void LTE_fdd_dl_scan_interface::handle_ctrl_disconnect(void) { - boost::mutex::scoped_lock lock(connect_mutex); + libtools_scoped_lock lock(connect_mutex); LTE_fdd_dl_scan_interface::ctrl_connected = false; } @@ -1505,7 +1504,7 @@ void LTE_fdd_dl_scan_interface::handle_write(std::string msg) } void LTE_fdd_dl_scan_interface::handle_start(void) { - boost::mutex::scoped_lock lock(dl_earfcn_list_mutex); + libtools_scoped_lock lock(dl_earfcn_list_mutex); LTE_fdd_dl_scan_flowgraph *flowgraph = LTE_fdd_dl_scan_flowgraph::get_instance(); if(!flowgraph->is_started()) @@ -1540,9 +1539,9 @@ void LTE_fdd_dl_scan_interface::handle_stop(void) } void LTE_fdd_dl_scan_interface::handle_help(void) { - boost::mutex::scoped_lock lock(dl_earfcn_list_mutex); - std::string tmp_str; - uint32 i; + libtools_scoped_lock lock(dl_earfcn_list_mutex); + std::string tmp_str; + uint32 i; send_ctrl_msg("***System Configuration Parameters***"); send_ctrl_msg("\tRead parameters using read format"); @@ -1565,18 +1564,13 @@ void LTE_fdd_dl_scan_interface::handle_help(void) tmp_str = "\t\t"; tmp_str += DL_EARFCN_LIST_PARAM; tmp_str += " = "; - try + for(i=0; i(dl_earfcn_list[i]); - if(i != dl_earfcn_list_size-1) - { - tmp_str += ","; - } + tmp_str += ","; } - }catch(boost::bad_lexical_cast &){ - // Intentionally do nothing } send_ctrl_msg(tmp_str); @@ -1606,8 +1600,8 @@ void LTE_fdd_dl_scan_interface::read_band(void) } void LTE_fdd_dl_scan_interface::write_band(std::string band_str) { - boost::mutex::scoped_lock lock(dl_earfcn_list_mutex); - uint32 i; + libtools_scoped_lock lock(dl_earfcn_list_mutex); + uint32 i; for(i=0; i(dl_earfcn_list[i]); - if(i != dl_earfcn_list_size-1) - { - tmp_str += ","; - } + tmp_str += ","; } - send_ctrl_status_msg(LTE_FDD_DL_SCAN_STATUS_OK, tmp_str); - }catch(boost::bad_lexical_cast &){ - send_ctrl_status_msg(LTE_FDD_DL_SCAN_STATUS_FAIL, "bad dl_earfcn_list"); } + send_ctrl_status_msg(LTE_FDD_DL_SCAN_STATUS_OK, tmp_str); } void LTE_fdd_dl_scan_interface::write_dl_earfcn_list(std::string dl_earfcn_list_str) { - boost::mutex::scoped_lock lock(dl_earfcn_list_mutex); + libtools_scoped_lock lock(dl_earfcn_list_mutex); LTE_FDD_DL_SCAN_STATUS_ENUM stat = LTE_FDD_DL_SCAN_STATUS_OK; uint32 i; uint16 tmp_list[65535]; @@ -1661,13 +1650,7 @@ void LTE_fdd_dl_scan_interface::write_dl_earfcn_list(std::string dl_earfcn_list_ while(std::string::npos != dl_earfcn_list_str.find(",")) { - try - { - tmp_list[tmp_list_size] = boost::lexical_cast(dl_earfcn_list_str.substr(0, dl_earfcn_list_str.find(","))); - }catch(boost::bad_lexical_cast &){ - stat = LTE_FDD_DL_SCAN_STATUS_FAIL; - break; - } + to_number(dl_earfcn_list_str.substr(0, dl_earfcn_list_str.find(",")), &tmp_list[tmp_list_size]); if(tmp_list[tmp_list_size] >= liblte_interface_first_dl_earfcn[band] && tmp_list[tmp_list_size] <= liblte_interface_last_dl_earfcn[band]) { @@ -1678,12 +1661,7 @@ void LTE_fdd_dl_scan_interface::write_dl_earfcn_list(std::string dl_earfcn_list_ } dl_earfcn_list_str = dl_earfcn_list_str.substr(dl_earfcn_list_str.find(",")+1, std::string::npos); } - try - { - tmp_list[tmp_list_size] = boost::lexical_cast(dl_earfcn_list_str); - }catch(boost::bad_lexical_cast &){ - stat = LTE_FDD_DL_SCAN_STATUS_FAIL; - } + to_number(dl_earfcn_list_str, &tmp_list[tmp_list_size]); if(tmp_list[tmp_list_size] >= liblte_interface_first_dl_earfcn[band] && tmp_list[tmp_list_size] <= liblte_interface_last_dl_earfcn[band]) { @@ -1752,7 +1730,7 @@ void LTE_fdd_dl_scan_interface::write_enable_pcap(std::string enable_pcap_str) // Helpers LTE_FDD_DL_SCAN_STATUS_ENUM LTE_fdd_dl_scan_interface::switch_to_next_freq(void) { - boost::mutex::scoped_lock lock(dl_earfcn_list_mutex); + libtools_scoped_lock lock(dl_earfcn_list_mutex); LTE_fdd_dl_scan_flowgraph *flowgraph = LTE_fdd_dl_scan_flowgraph::get_instance(); LTE_FDD_DL_SCAN_STATUS_ENUM stat = LTE_FDD_DL_SCAN_STATUS_FAIL; diff --git a/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_main.cc b/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_main.cc old mode 100644 new mode 100755 diff --git a/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_state_machine.cc b/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_state_machine.cc old mode 100644 new mode 100755 index e2579c1..75d803e --- a/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_state_machine.cc +++ b/LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_state_machine.cc @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2015 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -31,6 +31,7 @@ latest LTE library. 03/26/2014 Ben Wojtowicz Using the latest LTE library. 06/15/2014 Ben Wojtowicz Added PCAP support. + 03/11/2015 Ben Wojtowicz Added 7.68MHz support. *******************************************************************************/ @@ -64,6 +65,17 @@ #define PDSCH_DECODE_SIB1_NUM_SAMPS_1_92MHZ (2 * ONE_FRAME_NUM_SAMPS_1_92MHZ) #define PDSCH_DECODE_SI_GENERIC_NUM_SAMPS_1_92MHZ (ONE_FRAME_NUM_SAMPS_1_92MHZ) +// Sample rate 7.68MHZ defines +#define ONE_SUBFRAME_NUM_SAMPS_7_68MHZ (LIBLTE_PHY_N_SAMPS_PER_SUBFR_7_68MHZ) +#define ONE_FRAME_NUM_SAMPS_7_68MHZ (10 * ONE_SUBFRAME_NUM_SAMPS_7_68MHZ) +#define FREQ_CHANGE_WAIT_NUM_SAMPS_7_68MHZ (100 * ONE_FRAME_NUM_SAMPS_7_68MHZ) +#define COARSE_TIMING_SEARCH_NUM_SAMPS_7_68MHZ (((COARSE_TIMING_N_SLOTS/2)+2) * ONE_SUBFRAME_NUM_SAMPS_7_68MHZ) +#define PSS_AND_FINE_TIMING_SEARCH_NUM_SAMPS_7_68MHZ (COARSE_TIMING_SEARCH_NUM_SAMPS_7_68MHZ) +#define SSS_SEARCH_NUM_SAMPS_7_68MHZ (COARSE_TIMING_SEARCH_NUM_SAMPS_7_68MHZ) +#define BCH_DECODE_NUM_SAMPS_7_68MHZ (2 * ONE_FRAME_NUM_SAMPS_7_68MHZ) +#define PDSCH_DECODE_SIB1_NUM_SAMPS_7_68MHZ (2 * ONE_FRAME_NUM_SAMPS_7_68MHZ) +#define PDSCH_DECODE_SI_GENERIC_NUM_SAMPS_7_68MHZ (ONE_FRAME_NUM_SAMPS_7_68MHZ) + // Sample rate 15.36MHZ defines #define ONE_SUBFRAME_NUM_SAMPS_15_36MHZ (LIBLTE_PHY_N_SAMPS_PER_SUBFR_15_36MHZ) #define ONE_FRAME_NUM_SAMPS_15_36MHZ (10 * ONE_SUBFRAME_NUM_SAMPS_15_36MHZ) @@ -125,6 +137,23 @@ LTE_fdd_dl_scan_state_machine::LTE_fdd_dl_scan_state_machine(uint32 samp_rate) bch_decode_num_samps = BCH_DECODE_NUM_SAMPS_1_92MHZ; pdsch_decode_sib1_num_samps = PDSCH_DECODE_SIB1_NUM_SAMPS_1_92MHZ; pdsch_decode_si_generic_num_samps = PDSCH_DECODE_SI_GENERIC_NUM_SAMPS_1_92MHZ; + }else if(samp_rate == 7680000){ + liblte_phy_init(&phy_struct, + LIBLTE_PHY_FS_7_68MHZ, + LIBLTE_PHY_INIT_N_ID_CELL_UNKNOWN, + 4, + LIBLTE_PHY_N_RB_DL_5MHZ, + LIBLTE_PHY_N_SC_RB_DL_NORMAL_CP, + liblte_rrc_phich_resource_num[LIBLTE_RRC_PHICH_RESOURCE_1]); + one_subframe_num_samps = ONE_SUBFRAME_NUM_SAMPS_7_68MHZ; + one_frame_num_samps = ONE_FRAME_NUM_SAMPS_7_68MHZ; + freq_change_wait_num_samps = FREQ_CHANGE_WAIT_NUM_SAMPS_7_68MHZ; + coarse_timing_search_num_samps = COARSE_TIMING_SEARCH_NUM_SAMPS_7_68MHZ; + pss_and_fine_timing_search_num_samps = PSS_AND_FINE_TIMING_SEARCH_NUM_SAMPS_7_68MHZ; + sss_search_num_samps = SSS_SEARCH_NUM_SAMPS_7_68MHZ; + bch_decode_num_samps = BCH_DECODE_NUM_SAMPS_7_68MHZ; + pdsch_decode_sib1_num_samps = PDSCH_DECODE_SIB1_NUM_SAMPS_7_68MHZ; + pdsch_decode_si_generic_num_samps = PDSCH_DECODE_SI_GENERIC_NUM_SAMPS_7_68MHZ; }else{ liblte_phy_init(&phy_struct, LIBLTE_PHY_FS_15_36MHZ, diff --git a/LTE_fdd_enodeb/CMakeLists.txt b/LTE_fdd_enodeb/CMakeLists.txt old mode 100644 new mode 100755 index 557da5c..ac71479 --- a/LTE_fdd_enodeb/CMakeLists.txt +++ b/LTE_fdd_enodeb/CMakeLists.txt @@ -22,6 +22,9 @@ add_executable(LTE_fdd_enodeb src/LTE_fdd_enb_pdcp.cc src/LTE_fdd_enb_rrc.cc src/LTE_fdd_enb_mme.cc + src/LTE_fdd_enb_gw.cc ) -target_link_libraries(LTE_fdd_enodeb lte fftw3f tools pthread rt ${UHD_LIBRARIES} ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_PMT_LIBRARIES}) +target_link_libraries(LTE_fdd_enodeb lte fftw3f tools pthread rt ${MBEDTLS_LIBRARIES} ${UHD_LIBRARIES} ${LIBBLADERF_LIBRARIES} ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_PMT_LIBRARIES}) install(TARGETS LTE_fdd_enodeb DESTINATION bin) +install(CODE "execute_process(COMMAND chmod +x \"${CMAKE_SOURCE_DIR}/enodeb_nat_script.sh\")") +#install(CODE "execute_process(COMMAND \"${CMAKE_SOURCE_DIR}/enodeb_nat_script.sh\")") diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_cnfg_db.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_cnfg_db.h old mode 100644 new mode 100755 index 1425dee..4b5a76a --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_cnfg_db.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_cnfg_db.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2014, 2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +27,11 @@ 11/09/2013 Ben Wojtowicz Created file 01/18/2014 Ben Wojtowicz Added set/get routines for uint32 values. 03/26/2014 Ben Wojtowicz Using the latest LTE library. + 08/03/2014 Ben Wojtowicz Added support for limiting PCAP output. + 09/03/2014 Ben Wojtowicz Added better MCC/MNC support. + 11/01/2014 Ben Wojtowicz Added config file support. + 07/29/2017 Ben Wojtowicz Added a routine for filling RRC physical + layer dedicated configurations. *******************************************************************************/ @@ -47,11 +52,14 @@ DEFINES *******************************************************************************/ +#define LTE_FDD_ENB_MAX_LINE_SIZE 512 /******************************************************************************* FORWARD DECLARATIONS *******************************************************************************/ +class LTE_fdd_enb_pdcp; +class LTE_fdd_enb_mme; /******************************************************************************* TYPEDEFS @@ -79,12 +87,18 @@ typedef struct{ uint32 N_sc_rb_ul; uint32 si_periodicity_T; uint32 si_win_len; + uint16 mcc; + uint16 mnc; bool sib3_present; bool sib4_present; bool sib5_present; bool sib6_present; bool sib7_present; bool sib8_present; + bool mib_pcap_sent; + bool sib1_pcap_sent; + bool sib_pcap_sent[4]; + bool continuous_sib_pcap; }LTE_FDD_ENB_SYS_INFO_STRUCT; /******************************************************************************* @@ -109,9 +123,19 @@ class LTE_fdd_enb_cnfg_db LTE_FDD_ENB_ERROR_ENUM get_param(LTE_FDD_ENB_PARAM_ENUM param, uint32 &value); // MIB/SIB Construction - void construct_sys_info(void); + void construct_sys_info(LTE_fdd_enb_pdcp *pdcp, LTE_fdd_enb_mme *mme); void get_sys_info(LTE_FDD_ENB_SYS_INFO_STRUCT &_sys_info); + // Config File + void read_cnfg_file(void); + + // Helpers + void populate_rrc_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *cnfg, + uint32 i_cqi_pmi, + uint32 i_ri, + uint32 i_sr, + uint32 n_1_p_pucch); + private: // Singleton static LTE_fdd_enb_cnfg_db *instance; @@ -125,6 +149,11 @@ class LTE_fdd_enb_cnfg_db // System information LTE_FDD_ENB_SYS_INFO_STRUCT sys_info; + + // Config File + void write_cnfg_file(void); + void delete_cnfg_file(void); + bool use_cnfg_file; }; #endif /* __LTE_FDD_ENB_CNFG_DB_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_common.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_common.h new file mode 100755 index 0000000..c9d8082 --- /dev/null +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_common.h @@ -0,0 +1,109 @@ +/******************************************************************************* + + Copyright 2015-2016 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: LTE_fdd_enb_common.h + + Description: Contains all the common definitions for the LTE FDD eNodeB. + + Revision History + ---------- ------------- -------------------------------------------- + 02/15/2015 Ben Wojtowicz Created file + 03/12/2016 Ben Wojtowicz Added error for H-ARQ info not found. + +*******************************************************************************/ + +#ifndef __LTE_FDD_ENB_COMMON_H__ +#define __LTE_FDD_ENB_COMMON_H__ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + FORWARD DECLARATIONS +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + +typedef enum{ + LTE_FDD_ENB_ERROR_NONE = 0, + LTE_FDD_ENB_ERROR_INVALID_COMMAND, + LTE_FDD_ENB_ERROR_INVALID_PARAM, + LTE_FDD_ENB_ERROR_OUT_OF_BOUNDS, + LTE_FDD_ENB_ERROR_EXCEPTION, + LTE_FDD_ENB_ERROR_ALREADY_STARTED, + LTE_FDD_ENB_ERROR_ALREADY_STOPPED, + LTE_FDD_ENB_ERROR_CANT_START, + LTE_FDD_ENB_ERROR_CANT_STOP, + LTE_FDD_ENB_ERROR_BAD_ALLOC, + LTE_FDD_ENB_ERROR_USER_NOT_FOUND, + LTE_FDD_ENB_ERROR_NO_FREE_C_RNTI, + LTE_FDD_ENB_ERROR_C_RNTI_NOT_FOUND, + LTE_FDD_ENB_ERROR_CANT_SCHEDULE, + LTE_FDD_ENB_ERROR_VARIABLE_NOT_DYNAMIC, + LTE_FDD_ENB_ERROR_MASTER_CLOCK_FAIL, + LTE_FDD_ENB_ERROR_NO_MSG_IN_QUEUE, + LTE_FDD_ENB_ERROR_RB_NOT_SETUP, + LTE_FDD_ENB_ERROR_RB_ALREADY_SETUP, + LTE_FDD_ENB_ERROR_TIMER_NOT_FOUND, + LTE_FDD_ENB_ERROR_CANT_REASSEMBLE_SDU, + LTE_FDD_ENB_ERROR_DUPLICATE_ENTRY, + LTE_FDD_ENB_ERROR_READ_ONLY, + LTE_FDD_ENB_ERROR_HARQ_INFO_NOT_FOUND, + LTE_FDD_ENB_ERROR_N_ITEMS, +}LTE_FDD_ENB_ERROR_ENUM; +static const char LTE_fdd_enb_error_text[LTE_FDD_ENB_ERROR_N_ITEMS][100] = {"none", + "invalid command", + "invalid parameter", + "out of bounds", + "exception", + "already started", + "already stopped", + "cant start", + "cant stop", + "bad alloc", + "user not found", + "no free C-RNTI", + "C-RNTI not found", + "cant schedule", + "variable not dynamic", + "unable to set master clock rate", + "no message in queue", + "RB not setup", + "RB already setup", + "timer not found", + "cant reassemble SDU", + "duplicate entry", + "read only", + "HARQ info not found"}; + +/******************************************************************************* + CLASS DECLARATIONS +*******************************************************************************/ + +#endif /* __LTE_FDD_ENB_COMMON_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_gw.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_gw.h new file mode 100755 index 0000000..ce39bc7 --- /dev/null +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_gw.h @@ -0,0 +1,98 @@ +/******************************************************************************* + + Copyright 2014-2015, 2017 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: LTE_fdd_enb_gw.h + + Description: Contains all the definitions for the LTE FDD eNodeB + IP gateway. + + Revision History + ---------- ------------- -------------------------------------------- + 11/29/2014 Ben Wojtowicz Created file + 12/16/2014 Ben Wojtowicz Added ol extension to message queue. + 02/15/2015 Ben Wojtowicz Moved to new message queue. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t. + 07/29/2017 Ben Wojtowicz Moved away from singleton pattern. + +*******************************************************************************/ + +#ifndef __LTE_FDD_ENB_GW_H__ +#define __LTE_FDD_ENB_GW_H__ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "LTE_fdd_enb_interface.h" +#include "LTE_fdd_enb_msgq.h" + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + FORWARD DECLARATIONS +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + CLASS DECLARATIONS +*******************************************************************************/ + +class LTE_fdd_enb_gw +{ +public: + // Constructor/Destructor + LTE_fdd_enb_gw(); + ~LTE_fdd_enb_gw(); + + // Start/Stop + bool is_started(void); + LTE_FDD_ENB_ERROR_ENUM start(LTE_fdd_enb_msgq *from_pdcp, LTE_fdd_enb_msgq *to_pdcp, char *err_str, LTE_fdd_enb_interface *iface); + void stop(void); + +private: + // Start/Stop + LTE_fdd_enb_interface *interface; + sem_t start_sem; + bool started; + + // Communication + void handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + LTE_fdd_enb_msgq *msgq_from_pdcp; + LTE_fdd_enb_msgq *msgq_to_pdcp; + + // PDCP Message Handlers + void handle_gw_data(LTE_FDD_ENB_GW_DATA_READY_MSG_STRUCT *gw_data); + + // GW Receive + static void* receive_thread(void *inputs); + pthread_t rx_thread; + + // TUN device + int32 tun_fd; +}; + +#endif /* __LTE_FDD_ENB_GW_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_hss.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_hss.h old mode 100644 new mode 100755 index 2cce0da..567fbb8 --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_hss.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_hss.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2014 Ben Wojtowicz + Copyright 2014-2015 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -25,6 +25,12 @@ Revision History ---------- ------------- -------------------------------------------- 06/15/2014 Ben Wojtowicz Created file + 08/03/2014 Ben Wojtowicz Added authentication vector support. + 09/03/2014 Ben Wojtowicz Added sequence number resynch. + 11/01/2014 Ben Wojtowicz Added user file support. + 11/29/2014 Ben Wojtowicz Added support for regenerating eNodeB + security data. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t. *******************************************************************************/ @@ -43,6 +49,10 @@ DEFINES *******************************************************************************/ +#define LTE_FDD_ENB_IND_HE_N_BITS 5 +#define LTE_FDD_ENB_IND_HE_MASK 0x1FUL +#define LTE_FDD_ENB_IND_HE_MAX_VALUE 31 +#define LTE_FDD_ENB_SEQ_HE_MAX_VALUE 0x7FFFFFFFFFFFUL /******************************************************************************* FORWARD DECLARATIONS @@ -53,6 +63,28 @@ TYPEDEFS *******************************************************************************/ +typedef struct{ + uint8 k[16]; +}LTE_FDD_ENB_STORED_DATA_STRUCT; + +typedef struct{ + LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT auth_vec; + uint64 sqn_he; + uint64 seq_he; + uint8 ak[6]; + uint8 mac[8]; + uint8 k_asme[32]; + uint8 k_enb[32]; + uint8 k_up_enc[32]; + uint8 k_up_int[32]; + uint8 ind_he; +}LTE_FDD_ENB_GENERATED_DATA_STRUCT; + +typedef struct{ + LTE_FDD_ENB_USER_ID_STRUCT id; + LTE_FDD_ENB_STORED_DATA_STRUCT stored_data; + LTE_FDD_ENB_GENERATED_DATA_STRUCT generated_data; +}LTE_FDD_ENB_HSS_USER_STRUCT; /******************************************************************************* CLASS DECLARATIONS @@ -66,10 +98,21 @@ class LTE_fdd_enb_hss static void cleanup(void); // External interface - LTE_FDD_ENB_ERROR_ENUM add_user(std::string imsi); - LTE_FDD_ENB_ERROR_ENUM find_user(std::string imsi, LTE_fdd_enb_user **user); + LTE_FDD_ENB_ERROR_ENUM add_user(std::string imsi, std::string imei, std::string k); LTE_FDD_ENB_ERROR_ENUM del_user(std::string imsi); std::string print_all_users(void); + bool is_imsi_allowed(uint64 imsi); + bool is_imei_allowed(uint64 imei); + LTE_FDD_ENB_USER_ID_STRUCT* get_user_id_from_imsi(uint64 imsi); + LTE_FDD_ENB_USER_ID_STRUCT* get_user_id_from_imei(uint64 imei); + void generate_security_data(LTE_FDD_ENB_USER_ID_STRUCT *id, uint16 mcc, uint16 mnc); + void security_resynch(LTE_FDD_ENB_USER_ID_STRUCT *id, uint16 mcc, uint16 mnc, uint8 *auts); + LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT* regenerate_enb_security_data(LTE_FDD_ENB_USER_ID_STRUCT *id, uint32 nas_count_ul); + LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT* get_auth_vec(LTE_FDD_ENB_USER_ID_STRUCT *id); + + // User File + void set_use_user_file(bool uuf); + void read_user_file(void); private: // Singleton @@ -78,8 +121,13 @@ class LTE_fdd_enb_hss ~LTE_fdd_enb_hss(); // Allowed users - boost::mutex user_mutex; - std::list user_list; + sem_t user_sem; + std::list user_list; + + // User File + void write_user_file(void); + void delete_user_file(void); + bool use_user_file; }; #endif /* __LTE_FDD_ENB_HSS_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_interface.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_interface.h old mode 100644 new mode 100755 index 86ce11f..8ce7128 --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_interface.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_interface.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -32,6 +32,24 @@ 05/04/2014 Ben Wojtowicz Added PCAP support and more error types. 06/15/2014 Ben Wojtowicz Added new error causes, ... support for info messages, and using the latest LTE library. + 07/22/2014 Ben Wojtowicz Added clock source as a configurable + parameter. + 08/03/2014 Ben Wojtowicz Added HSS support. + 09/03/2014 Ben Wojtowicz Added read only parameters for UL EARFCN, + DL center frequency and UL center frequency. + 11/01/2014 Ben Wojtowicz Added parameters for IP address assignment, + DNS address, config file, and user file. + 11/29/2014 Ben Wojtowicz Added support for the IP gateway. + 02/15/2015 Ben Wojtowicz Moved to new message queue, added IP pcap + support, and put error enum into common hdr. + 03/11/2015 Ben Wojtowicz Made a common routine for formatting time. + 07/25/2015 Ben Wojtowicz Made tx_gain and rx_gain into config file + tracked parameters. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t. + 02/13/2016 Ben Wojtowicz Added a command to print all registered + users. + 07/29/2017 Ben Wojtowicz Added input parameters for direct IPC to a UE + and using the latest tools library. *******************************************************************************/ @@ -42,9 +60,10 @@ INCLUDES *******************************************************************************/ +#include "LTE_fdd_enb_common.h" +#include "LTE_fdd_enb_msgq.h" #include "liblte_common.h" #include "libtools_socket_wrap.h" -#include #include /******************************************************************************* @@ -58,57 +77,14 @@ FORWARD DECLARATIONS *******************************************************************************/ +class LTE_fdd_enb_pdcp; +class LTE_fdd_enb_mme; +class LTE_fdd_enb_gw; /******************************************************************************* TYPEDEFS *******************************************************************************/ -typedef enum{ - LTE_FDD_ENB_ERROR_NONE = 0, - LTE_FDD_ENB_ERROR_INVALID_COMMAND, - LTE_FDD_ENB_ERROR_INVALID_PARAM, - LTE_FDD_ENB_ERROR_OUT_OF_BOUNDS, - LTE_FDD_ENB_ERROR_EXCEPTION, - LTE_FDD_ENB_ERROR_ALREADY_STARTED, - LTE_FDD_ENB_ERROR_ALREADY_STOPPED, - LTE_FDD_ENB_ERROR_CANT_START, - LTE_FDD_ENB_ERROR_CANT_STOP, - LTE_FDD_ENB_ERROR_BAD_ALLOC, - LTE_FDD_ENB_ERROR_USER_NOT_FOUND, - LTE_FDD_ENB_ERROR_NO_FREE_C_RNTI, - LTE_FDD_ENB_ERROR_C_RNTI_NOT_FOUND, - LTE_FDD_ENB_ERROR_CANT_SCHEDULE, - LTE_FDD_ENB_ERROR_VARIABLE_NOT_DYNAMIC, - LTE_FDD_ENB_ERROR_MASTER_CLOCK_FAIL, - LTE_FDD_ENB_ERROR_NO_MSG_IN_QUEUE, - LTE_FDD_ENB_ERROR_RB_NOT_SETUP, - LTE_FDD_ENB_ERROR_RB_ALREADY_SETUP, - LTE_FDD_ENB_ERROR_TIMER_NOT_FOUND, - LTE_FDD_ENB_ERROR_CANT_REASSEMBLE_SDU, - LTE_FDD_ENB_ERROR_N_ITEMS, -}LTE_FDD_ENB_ERROR_ENUM; -static const char LTE_fdd_enb_error_text[LTE_FDD_ENB_ERROR_N_ITEMS][100] = {"none", - "invalid command", - "invalid parameter", - "out of bounds", - "exception", - "already started", - "already stopped", - "cant start", - "cant stop", - "bad alloc", - "user not found", - "no free C-RNTI", - "C-RNTI not found", - "cant schedule", - "variable not dynamic", - "unable to set master clock rate", - "no message in queue", - "RB not setup", - "RB already setup", - "timer not found", - "cant reassemble SDU"}; - typedef enum{ LTE_FDD_ENB_DEBUG_TYPE_ERROR = 0, LTE_FDD_ENB_DEBUG_TYPE_WARNING, @@ -116,10 +92,10 @@ typedef enum{ LTE_FDD_ENB_DEBUG_TYPE_DEBUG, LTE_FDD_ENB_DEBUG_TYPE_N_ITEMS, }LTE_FDD_ENB_DEBUG_TYPE_ENUM; -static const char LTE_fdd_enb_debug_type_text[LTE_FDD_ENB_DEBUG_TYPE_N_ITEMS][100] = {"error ", +static const char LTE_fdd_enb_debug_type_text[LTE_FDD_ENB_DEBUG_TYPE_N_ITEMS][100] = {"error", "warning", - "info ", - "debug "}; + "info", + "debug"}; typedef enum{ LTE_FDD_ENB_DEBUG_LEVEL_RADIO = 0, @@ -129,23 +105,27 @@ typedef enum{ LTE_FDD_ENB_DEBUG_LEVEL_PDCP, LTE_FDD_ENB_DEBUG_LEVEL_RRC, LTE_FDD_ENB_DEBUG_LEVEL_MME, + LTE_FDD_ENB_DEBUG_LEVEL_GW, LTE_FDD_ENB_DEBUG_LEVEL_USER, LTE_FDD_ENB_DEBUG_LEVEL_RB, LTE_FDD_ENB_DEBUG_LEVEL_TIMER, LTE_FDD_ENB_DEBUG_LEVEL_IFACE, + LTE_FDD_ENB_DEBUG_LEVEL_MSGQ, LTE_FDD_ENB_DEBUG_LEVEL_N_ITEMS, }LTE_FDD_ENB_DEBUG_LEVEL_ENUM; static const char LTE_fdd_enb_debug_level_text[LTE_FDD_ENB_DEBUG_LEVEL_N_ITEMS][100] = {"radio", - "phy ", - "mac ", - "rlc ", - "pdcp ", - "rrc ", - "mme ", - "user ", - "rb ", + "phy", + "mac", + "rlc", + "pdcp", + "rrc", + "mme", + "gw", + "user", + "rb", "timer", - "iface"}; + "iface", + "msgq"}; typedef enum{ LTE_FDD_ENB_PCAP_DIRECTION_UL = 0, @@ -168,6 +148,8 @@ typedef enum{ LTE_FDD_ENB_PARAM_FREQ_BAND, LTE_FDD_ENB_PARAM_DL_EARFCN, LTE_FDD_ENB_PARAM_UL_EARFCN, + LTE_FDD_ENB_PARAM_DL_CENTER_FREQ, + LTE_FDD_ENB_PARAM_UL_CENTER_FREQ, LTE_FDD_ENB_PARAM_N_RB_DL, LTE_FDD_ENB_PARAM_N_RB_UL, LTE_FDD_ENB_PARAM_DL_BW, @@ -197,23 +179,32 @@ typedef enum{ LTE_FDD_ENB_PARAM_PHICH_RESOURCE, LTE_FDD_ENB_PARAM_N_SCHED_INFO, LTE_FDD_ENB_PARAM_SYSTEM_INFO_PERIODICITY, + LTE_FDD_ENB_PARAM_MAC_DIRECT_TO_UE, + LTE_FDD_ENB_PARAM_PHY_DIRECT_TO_UE, LTE_FDD_ENB_PARAM_DEBUG_TYPE, LTE_FDD_ENB_PARAM_DEBUG_LEVEL, LTE_FDD_ENB_PARAM_ENABLE_PCAP, + LTE_FDD_ENB_PARAM_IP_ADDR_START, + LTE_FDD_ENB_PARAM_DNS_ADDR, + LTE_FDD_ENB_PARAM_USE_CNFG_FILE, + LTE_FDD_ENB_PARAM_USE_USER_FILE, + LTE_FDD_ENB_PARAM_TX_GAIN, + LTE_FDD_ENB_PARAM_RX_GAIN, // Radio parameters managed by LTE_fdd_enb_radio LTE_FDD_ENB_PARAM_AVAILABLE_RADIOS, LTE_FDD_ENB_PARAM_SELECTED_RADIO_NAME, LTE_FDD_ENB_PARAM_SELECTED_RADIO_IDX, - LTE_FDD_ENB_PARAM_TX_GAIN, - LTE_FDD_ENB_PARAM_RX_GAIN, + LTE_FDD_ENB_PARAM_CLOCK_SOURCE, LTE_FDD_ENB_PARAM_N_ITEMS, }LTE_FDD_ENB_PARAM_ENUM; -static const char lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_N_ITEMS][100] = {"bandwidth", +static const char LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_N_ITEMS][100] = {"bandwidth", "band", "dl_earfcn", "ul_earfcn", + "dl_center_freq", + "ul_center_freq", "n_rb_dl", "n_rb_ul", "dl_bw", @@ -243,14 +234,21 @@ static const char lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_N_ITEMS][100] = {"ban "phich_resource", "n_sched_info", "system_info_periodicity", + "mac_direct_to_ue", + "phy_direct_to_ue", "debug_type", "debug_level", "enable_pcap", + "ip_addr_start", + "dns_addr", + "use_cnfg_file", + "use_user_file", + "tx_gain", + "rx_gain", "available_radios", "selected_radio_name", "selected_radio_idx", - "tx_gain", - "rx_gain"}; + "clock_source"}; typedef struct{ LTE_FDD_ENB_VAR_TYPE_ENUM var_type; @@ -261,6 +259,7 @@ typedef struct{ int64 int64_u_bound; bool special_bounds; bool dynamic; + bool read_only; }LTE_FDD_ENB_VAR_STRUCT; /******************************************************************************* @@ -284,8 +283,10 @@ class LTE_fdd_enb_interface void send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ENUM type, LTE_FDD_ENB_DEBUG_LEVEL_ENUM level, std::string file_name, int32 line, std::string msg, ...); void send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ENUM type, LTE_FDD_ENB_DEBUG_LEVEL_ENUM level, std::string file_name, int32 line, LIBLTE_BIT_MSG_STRUCT *lte_msg, std::string msg, ...); void send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ENUM type, LTE_FDD_ENB_DEBUG_LEVEL_ENUM level, std::string file_name, int32 line, LIBLTE_BYTE_MSG_STRUCT *lte_msg, std::string msg, ...); - void open_pcap_fd(void); - void send_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_ENUM dir, uint32 rnti, uint32 current_tti, uint8 *msg, uint32 N_bits); + void open_lte_pcap_fd(void); + void open_ip_pcap_fd(void); + void send_lte_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_ENUM dir, uint32 rnti, uint32 current_tti, uint8 *msg, uint32 N_bits); + void send_ip_pcap_msg(uint8 *msg, uint32 N_bytes); static void handle_ctrl_msg(std::string msg); static void handle_ctrl_connect(void); static void handle_ctrl_disconnect(void); @@ -294,9 +295,10 @@ class LTE_fdd_enb_interface static void handle_debug_connect(void); static void handle_debug_disconnect(void); static void handle_debug_error(LIBTOOLS_SOCKET_WRAP_ERROR_ENUM err); - boost::mutex ctrl_mutex; - boost::mutex debug_mutex; - FILE *pcap_fd; + sem_t ctrl_sem; + sem_t debug_sem; + FILE *lte_pcap_fd; + FILE *ip_pcap_fd; libtools_socket_wrap *ctrl_socket; libtools_socket_wrap *debug_socket; int16 ctrl_port; @@ -304,6 +306,10 @@ class LTE_fdd_enb_interface static bool ctrl_connected; static bool debug_connected; + // Handlers + LTE_FDD_ENB_ERROR_ENUM handle_write(std::string msg); + void handle_add_user(std::string msg); + // Get/Set bool get_shutdown(void); bool app_is_started(void); @@ -316,24 +322,44 @@ class LTE_fdd_enb_interface // Handlers void handle_read(std::string msg); - void handle_write(std::string msg); void handle_start(void); void handle_stop(void); void handle_help(void); + void handle_del_user(std::string msg); + void handle_print_users(void); + void handle_print_registered_users(void); // Variables - std::map var_map; - boost::mutex start_mutex; - uint32 debug_type_mask; - uint32 debug_level_mask; - bool shutdown; - bool started; + std::map var_map; + LTE_fdd_enb_pdcp *pdcp; + LTE_fdd_enb_mme *mme; + LTE_fdd_enb_gw *gw; + sem_t start_sem; + uint32 debug_type_mask; + uint32 debug_level_mask; + bool shutdown; + bool started; // Helpers LTE_FDD_ENB_ERROR_ENUM write_value(LTE_FDD_ENB_VAR_STRUCT *var, double value); LTE_FDD_ENB_ERROR_ENUM write_value(LTE_FDD_ENB_VAR_STRUCT *var, int64 value); LTE_FDD_ENB_ERROR_ENUM write_value(LTE_FDD_ENB_VAR_STRUCT *var, std::string value); LTE_FDD_ENB_ERROR_ENUM write_value(LTE_FDD_ENB_VAR_STRUCT *var, uint32 value); + + // Inter-stack communication + LTE_fdd_enb_msgq *phy_to_mac_comm; + LTE_fdd_enb_msgq *mac_to_phy_comm; + LTE_fdd_enb_msgq *mac_to_rlc_comm; + LTE_fdd_enb_msgq *mac_to_timer_comm; + LTE_fdd_enb_msgq *rlc_to_mac_comm; + LTE_fdd_enb_msgq *rlc_to_pdcp_comm; + LTE_fdd_enb_msgq *pdcp_to_rlc_comm; + LTE_fdd_enb_msgq *pdcp_to_rrc_comm; + LTE_fdd_enb_msgq *rrc_to_pdcp_comm; + LTE_fdd_enb_msgq *rrc_to_mme_comm; + LTE_fdd_enb_msgq *mme_to_rrc_comm; + LTE_fdd_enb_msgq *pdcp_to_gw_comm; + LTE_fdd_enb_msgq *gw_to_pdcp_comm; }; #endif /* __LTE_FDD_ENB_INTERFACE_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_mac.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_mac.h old mode 100644 new mode 100755 index fc6fc56..df838a9 --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_mac.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_mac.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -29,6 +29,15 @@ 05/04/2014 Ben Wojtowicz Added ULSCH handling. 06/15/2014 Ben Wojtowicz Added uplink scheduling and changed fn_combo to current_tti. + 11/29/2014 Ben Wojtowicz Using the byte message struct for SDUs. + 12/16/2014 Ben Wojtowicz Added ol extension to message queues. + 02/15/2015 Ben Wojtowicz Moved to new message queue. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t and added some + helper functions. + 02/13/2016 Ben Wojtowicz Removed boost message queue include. + 07/31/2016 Ben Wojtowicz Added a define for max HARQ retransmissions. + 07/29/2017 Ben Wojtowicz Added SR support and added IPC direct to a UE + MAC. *******************************************************************************/ @@ -44,14 +53,14 @@ #include "LTE_fdd_enb_msgq.h" #include "LTE_fdd_enb_user.h" #include "liblte_mac.h" -#include -#include +#include "libtools_ipc_msgq.h" #include /******************************************************************************* DEFINES *******************************************************************************/ +#define LTE_FDD_ENB_MAX_HARQ_RETX 5 /******************************************************************************* FORWARD DECLARATIONS @@ -80,6 +89,12 @@ typedef struct{ uint32 current_tti; }LTE_FDD_ENB_UL_SCHED_QUEUE_STRUCT; +typedef struct{ + uint32 i_sr; + uint32 n_1_p_pucch; + uint16 rnti; +}LTE_FDD_ENB_UL_SR_SCHED_QUEUE_STRUCT; + /******************************************************************************* CLASS DECLARATIONS *******************************************************************************/ @@ -92,12 +107,13 @@ class LTE_fdd_enb_mac static void cleanup(void); // Start/Stop - void start(LTE_fdd_enb_interface *iface); + void start(LTE_fdd_enb_msgq *from_phy, LTE_fdd_enb_msgq *from_rlc, LTE_fdd_enb_msgq *to_phy, LTE_fdd_enb_msgq *to_rlc, LTE_fdd_enb_msgq *to_timer, bool direct_to_ue, LTE_fdd_enb_interface *iface); void stop(void); // External interface void update_sys_info(void); - void sched_ul(LTE_fdd_enb_user *user, uint32 requested_tbs); + void add_periodic_sr_pucch(uint16 rnti, uint32 i_sr, uint32 n_1_p_pucch); + void remove_periodic_sr_pucch(uint16 rnti); private: // Singleton @@ -106,30 +122,35 @@ class LTE_fdd_enb_mac ~LTE_fdd_enb_mac(); // Start/Stop - boost::mutex start_mutex; + sem_t start_sem; LTE_fdd_enb_interface *interface; bool started; // Communication - void handle_phy_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg); - void handle_rlc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg); - LTE_fdd_enb_msgq *phy_comm_msgq; - LTE_fdd_enb_msgq *rlc_comm_msgq; - boost::interprocess::message_queue *mac_phy_mq; - boost::interprocess::message_queue *mac_rlc_mq; + void handle_phy_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + void handle_rlc_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + void handle_ue_msg(LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT *msg); + LTE_fdd_enb_msgq *msgq_from_phy; + LTE_fdd_enb_msgq *msgq_from_rlc; + LTE_fdd_enb_msgq *msgq_to_phy; + LTE_fdd_enb_msgq *msgq_to_rlc; + LTE_fdd_enb_msgq *msgq_to_timer; + libtools_ipc_msgq *msgq_to_ue; // PHY Message Handlers void handle_ready_to_send(LTE_FDD_ENB_READY_TO_SEND_MSG_STRUCT *rts); void handle_prach_decode(LTE_FDD_ENB_PRACH_DECODE_MSG_STRUCT *prach_decode); void handle_pucch_decode(LTE_FDD_ENB_PUCCH_DECODE_MSG_STRUCT *pucch_decode); + void handle_pucch_ack_nack(LTE_fdd_enb_user *user, uint32 current_tti, LIBLTE_BIT_MSG_STRUCT *msg); + void handle_pucch_sr(LTE_fdd_enb_user *user, uint32 current_tti, LIBLTE_BIT_MSG_STRUCT *msg); void handle_pusch_decode(LTE_FDD_ENB_PUSCH_DECODE_MSG_STRUCT *pusch_decode); // RLC Message Handlers void handle_sdu_ready(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT *sdu_ready); // MAC PDU Handlers - void handle_ulsch_ccch_sdu(LTE_fdd_enb_user *user, uint32 lcid, LIBLTE_BIT_MSG_STRUCT *sdu); - void handle_ulsch_dcch_sdu(LTE_fdd_enb_user *user, uint32 lcid, LIBLTE_BIT_MSG_STRUCT *sdu); + void handle_ulsch_ccch_sdu(LTE_fdd_enb_user *user, uint32 lcid, LIBLTE_BYTE_MSG_STRUCT *sdu); + void handle_ulsch_dcch_sdu(LTE_fdd_enb_user *user, uint32 lcid, LIBLTE_BYTE_MSG_STRUCT *sdu); void handle_ulsch_ext_power_headroom_report(LTE_fdd_enb_user *user, LIBLTE_MAC_EXT_POWER_HEADROOM_CE_STRUCT *ext_power_headroom); void handle_ulsch_power_headroom_report(LTE_fdd_enb_user *user, LIBLTE_MAC_POWER_HEADROOM_CE_STRUCT *power_headroom); void handle_ulsch_c_rnti(LTE_fdd_enb_user **user, LIBLTE_MAC_C_RNTI_CE_STRUCT *c_rnti); @@ -141,27 +162,32 @@ class LTE_fdd_enb_mac void construct_random_access_response(uint8 preamble, uint16 timing_adv, uint32 current_tti); // Scheduler + void sched_ul(LTE_fdd_enb_user *user, uint32 requested_tbs); void scheduler(void); LTE_FDD_ENB_ERROR_ENUM add_to_rar_sched_queue(uint32 current_tti, LIBLTE_PHY_ALLOCATION_STRUCT *dl_alloc, LIBLTE_PHY_ALLOCATION_STRUCT *ul_alloc, LIBLTE_MAC_RAR_STRUCT *rar); LTE_FDD_ENB_ERROR_ENUM add_to_dl_sched_queue(uint32 current_tti, LIBLTE_MAC_PDU_STRUCT *mac_pdu, LIBLTE_PHY_ALLOCATION_STRUCT *alloc); LTE_FDD_ENB_ERROR_ENUM add_to_ul_sched_queue(uint32 current_tti, LIBLTE_PHY_ALLOCATION_STRUCT *alloc); - boost::mutex rar_sched_queue_mutex; - boost::mutex dl_sched_queue_mutex; - boost::mutex ul_sched_queue_mutex; - std::list rar_sched_queue; - std::list dl_sched_queue; - std::list ul_sched_queue; - LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT sched_dl_subfr[10]; - LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT sched_ul_subfr[10]; - uint8 sched_cur_dl_subfn; - uint8 sched_cur_ul_subfn; + sem_t rar_sched_queue_sem; + sem_t dl_sched_queue_sem; + sem_t ul_sched_queue_sem; + sem_t ul_sr_sched_queue_sem; + std::list rar_sched_queue; + std::list dl_sched_queue; + std::list ul_sched_queue; + std::list ul_sr_sched_queue; + LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT sched_dl_subfr[10]; + LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT sched_ul_subfr[10]; + uint8 sched_cur_dl_subfn; + uint8 sched_cur_ul_subfn; // Parameters - boost::mutex sys_info_mutex; + sem_t sys_info_sem; LTE_FDD_ENB_SYS_INFO_STRUCT sys_info; // Helpers uint32 get_n_reserved_prbs(uint32 current_tti); + uint32 add_to_tti(uint32 tti, uint32 addition); + bool is_tti_in_future(uint32 tti_to_check, uint32 current_tti); }; #endif /* __LTE_FDD_ENB_MAC_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_mme.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_mme.h old mode 100644 new mode 100755 index f5f24ed..420f370 --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_mme.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_mme.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +27,21 @@ 11/09/2013 Ben Wojtowicz Created file 01/18/2014 Ben Wojtowicz Added an explicit include for boost mutexes. 06/15/2014 Ben Wojtowicz Added RRC NAS message handler. + 08/03/2014 Ben Wojtowicz Added message parsers, state machines, and + message senders. + 09/03/2014 Ben Wojtowicz Added authentication and security support. + 11/01/2014 Ben Wojtowicz Added attach accept/complete, ESM info + transfer, and default bearer setup support. + 11/29/2014 Ben Wojtowicz Added service request, service reject, and + activate dedicated EPS bearer context + request support. + 12/16/2014 Ben Wojtowicz Added ol extension to message queue and + sending of EMM information message. + 02/15/2015 Ben Wojtowicz Moved to new message queue. + 03/11/2015 Ben Wojtowicz Added detach handling. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t. + 02/13/2016 Ben Wojtowicz Removed boost message queue include. + 07/29/2017 Ben Wojtowicz Moved away from singleton pattern. *******************************************************************************/ @@ -39,8 +54,6 @@ #include "LTE_fdd_enb_cnfg_db.h" #include "LTE_fdd_enb_msgq.h" -#include -#include /******************************************************************************* DEFINES @@ -64,38 +77,73 @@ class LTE_fdd_enb_mme { public: - // Singleton - static LTE_fdd_enb_mme* get_instance(void); - static void cleanup(void); + // Constructor/Destructor + LTE_fdd_enb_mme(); + ~LTE_fdd_enb_mme(); // Start/Stop - void start(void); + void start(LTE_fdd_enb_msgq *from_rrc, LTE_fdd_enb_msgq *to_rrc, LTE_fdd_enb_interface *iface); void stop(void); // External interface void update_sys_info(void); private: - // Singleton - static LTE_fdd_enb_mme *instance; - LTE_fdd_enb_mme(); - ~LTE_fdd_enb_mme(); - // Start/Stop - boost::mutex start_mutex; - bool started; + LTE_fdd_enb_interface *interface; + sem_t start_sem; + bool started; // Communication - void handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg); - LTE_fdd_enb_msgq *rrc_comm_msgq; - boost::interprocess::message_queue *mme_rrc_mq; + void handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + LTE_fdd_enb_msgq *msgq_from_rrc; + LTE_fdd_enb_msgq *msgq_to_rrc; // RRC Message Handlers void handle_nas_msg(LTE_FDD_ENB_MME_NAS_MSG_READY_MSG_STRUCT *nas_msg); + void handle_rrc_cmd_resp(LTE_FDD_ENB_MME_RRC_CMD_RESP_MSG_STRUCT *rrc_cmd_resp); + + // Message Parsers + void parse_attach_complete(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void parse_attach_request(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user **user, LTE_fdd_enb_rb **rb); + void parse_authentication_failure(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void parse_authentication_response(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void parse_detach_request(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void parse_identity_response(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void parse_security_mode_complete(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void parse_security_mode_reject(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void parse_service_request(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void parse_activate_default_eps_bearer_context_accept(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void parse_esm_information_response(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void parse_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + + // State Machines + void attach_sm(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void service_req_sm(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void detach_sm(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + + // Message Senders + void send_attach_accept(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_attach_reject(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_authentication_reject(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_authentication_request(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_detach_accept(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_emm_information(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_identity_request(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb, uint8 id_type); + void send_security_mode_command(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_service_reject(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb, uint8 cause); + void send_activate_dedicated_eps_bearer_context_request(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_esm_information_request(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_rrc_command(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb, LTE_FDD_ENB_RRC_CMD_ENUM cmd); // Parameters - boost::mutex sys_info_mutex; + sem_t sys_info_sem; LTE_FDD_ENB_SYS_INFO_STRUCT sys_info; + + // Helpers + uint32 get_next_ip_addr(void); + uint32 next_ip_addr; + uint32 dns_addr; }; #endif /* __LTE_FDD_ENB_MME_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_msgq.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_msgq.h old mode 100644 new mode 100755 index b932c70..2aa6718 --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_msgq.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_msgq.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -30,6 +30,21 @@ 05/04/2014 Ben Wojtowicz Added messages for MAC, RLC, PDCP, and RRC communication. 06/15/2014 Ben Wojtowicz Added MME<->RRC messages. + 08/03/2014 Ben Wojtowicz Added RRC command messages. + 11/01/2014 Ben Wojtowicz Added RRC security command, RRC SRB2 setup + command, and RRC command response messages. + 11/29/2014 Ben Wojtowicz Added IP gateway communication messages. + 02/15/2015 Ben Wojtowicz Moving to new message queue with semaphores + and circular buffers and added a timer tick + message. + 03/15/2015 Ben Wojtowicz Added a mutex to the circular buffer. + 07/25/2015 Ben Wojtowicz Combined the DL and UL schedule messages into + a single PHY schedule message. + 12/06/2015 Ben Wojtowicz Changed boost::mutex and + boost::interprocess::interprocess_semaphore + to sem_t. + 03/12/2016 Ben Wojtowicz Added PUCCH support. + 07/29/2017 Ben Wojtowicz Added SR Support. *******************************************************************************/ @@ -43,14 +58,15 @@ #include "LTE_fdd_enb_user.h" #include "liblte_rrc.h" #include "liblte_phy.h" -#include +#include #include /******************************************************************************* DEFINES *******************************************************************************/ -#define LTE_FDD_ENB_N_SIB_ALLOCS 7 +#define LTE_FDD_ENB_N_SIB_ALLOCS 7 +#define LTE_FDD_ENB_N_PUCCH_PER_SUBFR 12 /******************************************************************************* FORWARD DECLARATIONS @@ -66,8 +82,7 @@ typedef enum{ LTE_FDD_ENB_MESSAGE_TYPE_KILL = 0, // MAC -> PHY Messages - LTE_FDD_ENB_MESSAGE_TYPE_DL_SCHEDULE, - LTE_FDD_ENB_MESSAGE_TYPE_UL_SCHEDULE, + LTE_FDD_ENB_MESSAGE_TYPE_PHY_SCHEDULE, // PHY -> MAC Messages LTE_FDD_ENB_MESSAGE_TYPE_READY_TO_SEND, @@ -81,6 +96,9 @@ typedef enum{ // MAC -> RLC Messages LTE_FDD_ENB_MESSAGE_TYPE_RLC_PDU_READY, + // MAC -> TIMER Messages + LTE_FDD_ENB_MESSAGE_TYPE_TIMER_TICK, + // PDCP -> RLC Messages LTE_FDD_ENB_MESSAGE_TYPE_RLC_SDU_READY, @@ -95,27 +113,39 @@ typedef enum{ // MME -> RRC Messages LTE_FDD_ENB_MESSAGE_TYPE_RRC_NAS_MSG_READY, + LTE_FDD_ENB_MESSAGE_TYPE_RRC_CMD_READY, // RRC -> MME Messages LTE_FDD_ENB_MESSAGE_TYPE_MME_NAS_MSG_READY, + LTE_FDD_ENB_MESSAGE_TYPE_MME_RRC_CMD_RESP, + + // GW -> PDCP Messages + LTE_FDD_ENB_MESSAGE_TYPE_PDCP_DATA_SDU_READY, + + // PDCP -> GW Messages + LTE_FDD_ENB_MESSAGE_TYPE_GW_DATA_READY, LTE_FDD_ENB_MESSAGE_TYPE_N_ITEMS, }LTE_FDD_ENB_MESSAGE_TYPE_ENUM; static const char LTE_fdd_enb_message_type_text[LTE_FDD_ENB_MESSAGE_TYPE_N_ITEMS][100] = {"Kill", - "DL schedule", - "UL schedule", + "PHY schedule", "Ready to send", "PRACH decode", "PUCCH decode", "PUSCH decode", "MAC sdu ready", "RLC pdu ready", + "Timer tick", "RLC sdu ready", "PDCP pdu ready", "PDCP sdu ready", "RRC pdu ready", "RRC NAS message ready", - "MME NAS message ready"}; + "RRC command ready", + "MME NAS message ready", + "MME RRC command response", + "PDCP data sdu ready", + "GW data ready"}; typedef enum{ LTE_FDD_ENB_DEST_LAYER_PHY = 0, @@ -124,6 +154,8 @@ typedef enum{ LTE_FDD_ENB_DEST_LAYER_PDCP, LTE_FDD_ENB_DEST_LAYER_RRC, LTE_FDD_ENB_DEST_LAYER_MME, + LTE_FDD_ENB_DEST_LAYER_GW, + LTE_FDD_ENB_DEST_LAYER_TIMER_MGR, LTE_FDD_ENB_DEST_LAYER_ANY, LTE_FDD_ENB_DEST_LAYER_N_ITEMS, }LTE_FDD_ENB_DEST_LAYER_ENUM; @@ -133,6 +165,8 @@ static const char LTE_fdd_enb_dest_layer_text[LTE_FDD_ENB_DEST_LAYER_N_ITEMS][10 "PDCP", "RRC", "MME", + "GW", + "TIMER_MGR", "ANY"}; // Generic Messages @@ -145,18 +179,38 @@ typedef struct{ uint32 N_sched_prbs; uint32 current_tti; }LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT; +typedef enum{ + LTE_FDD_ENB_PUCCH_TYPE_ACK_NACK = 0, + LTE_FDD_ENB_PUCCH_TYPE_SR, + LTE_FDD_ENB_PUCCH_TYPE_N_ITEMS, +}LTE_FDD_ENB_PUCCH_TYPE_ENUM; +static const char LTE_fdd_enb_pucch_type_text[LTE_FDD_ENB_PUCCH_TYPE_N_ITEMS][100] = {"ACK_NACK", + "SR"}; typedef struct{ - LIBLTE_PHY_PDCCH_STRUCT decodes; - uint32 N_avail_prbs; - uint32 N_sched_prbs; - uint32 current_tti; - uint8 next_prb; + LTE_FDD_ENB_PUCCH_TYPE_ENUM type; + uint32 n_1_p_pucch; + uint16 rnti; + bool decode; +}LTE_FDD_ENB_PUCCH_STRUCT; +typedef struct{ + LIBLTE_PHY_PDCCH_STRUCT decodes; + LTE_FDD_ENB_PUCCH_STRUCT pucch[LTE_FDD_ENB_N_PUCCH_PER_SUBFR]; + uint32 N_avail_prbs; + uint32 N_sched_prbs; + uint32 current_tti; + uint32 N_pucch; + uint8 next_prb; }LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT; +typedef struct{ + LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT dl_sched; + LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT ul_sched; +}LTE_FDD_ENB_PHY_SCHEDULE_MSG_STRUCT; // PHY -> MAC Messages typedef struct{ uint32 dl_current_tti; uint32 ul_current_tti; + bool late; }LTE_FDD_ENB_READY_TO_SEND_MSG_STRUCT; typedef struct{ uint32 current_tti; @@ -165,7 +219,10 @@ typedef struct{ uint32 num_preambles; }LTE_FDD_ENB_PRACH_DECODE_MSG_STRUCT; typedef struct{ - uint32 current_tti; + LIBLTE_BIT_MSG_STRUCT msg; + LTE_FDD_ENB_PUCCH_TYPE_ENUM type; + uint32 current_tti; + uint16 rnti; }LTE_FDD_ENB_PUCCH_DECODE_MSG_STRUCT; typedef struct{ LIBLTE_BIT_MSG_STRUCT msg; @@ -185,6 +242,11 @@ typedef struct{ LTE_fdd_enb_rb *rb; }LTE_FDD_ENB_RLC_PDU_READY_MSG_STRUCT; +// MAC -> TIMER Messages +typedef struct{ + uint32 tick; +}LTE_FDD_ENB_TIMER_TICK_MSG_STRUCT; + // PDCP -> RLC Messages typedef struct{ LTE_fdd_enb_user *user; @@ -214,19 +276,56 @@ typedef struct{ LTE_fdd_enb_user *user; LTE_fdd_enb_rb *rb; }LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT; +typedef enum{ + LTE_FDD_ENB_RRC_CMD_RELEASE = 0, + LTE_FDD_ENB_RRC_CMD_SECURITY, + LTE_FDD_ENB_RRC_CMD_SETUP_DEF_DRB, + LTE_FDD_ENB_RRC_CMD_SETUP_DED_DRB, + LTE_FDD_ENB_RRC_CMD_N_ITEMS, +}LTE_FDD_ENB_RRC_CMD_ENUM; +static const char LTE_fdd_enb_rrc_cmd_text[LTE_FDD_ENB_RRC_CMD_N_ITEMS][20] = {"Release", + "Security", + "Setup Default DRB", + "Setup Dedicated DRB"}; +typedef struct{ + LTE_fdd_enb_user *user; + LTE_fdd_enb_rb *rb; + LTE_FDD_ENB_RRC_CMD_ENUM cmd; +}LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT; // RRC -> MME Messages typedef struct{ LTE_fdd_enb_user *user; LTE_fdd_enb_rb *rb; }LTE_FDD_ENB_MME_NAS_MSG_READY_MSG_STRUCT; +typedef enum{ + LTE_FDD_ENB_MME_RRC_CMD_RESP_SECURITY = 0, + LTE_FDD_ENB_MME_RRC_CMD_RESP_N_ITEMS, +}LTE_FDD_ENB_MME_RRC_CMD_RESP_ENUM; +static const char LTE_fdd_enb_mme_rrc_cmd_resp_text[LTE_FDD_ENB_MME_RRC_CMD_RESP_N_ITEMS][20] = {"Security"}; +typedef struct{ + LTE_fdd_enb_user *user; + LTE_fdd_enb_rb *rb; + LTE_FDD_ENB_MME_RRC_CMD_RESP_ENUM cmd_resp; +}LTE_FDD_ENB_MME_RRC_CMD_RESP_MSG_STRUCT; + +// GW -> PDCP Messages +typedef struct{ + LTE_fdd_enb_user *user; + LTE_fdd_enb_rb *rb; +}LTE_FDD_ENB_PDCP_DATA_SDU_READY_MSG_STRUCT; + +// PDCP -> GW Messages +typedef struct{ + LTE_fdd_enb_user *user; + LTE_fdd_enb_rb *rb; +}LTE_FDD_ENB_GW_DATA_READY_MSG_STRUCT; typedef union{ // Generic Messages // MAC -> PHY Messages - LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT dl_schedule; - LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT ul_schedule; + LTE_FDD_ENB_PHY_SCHEDULE_MSG_STRUCT phy_schedule; // PHY -> MAC Messages LTE_FDD_ENB_READY_TO_SEND_MSG_STRUCT ready_to_send; @@ -240,6 +339,9 @@ typedef union{ // MAC -> RLC Messages LTE_FDD_ENB_RLC_PDU_READY_MSG_STRUCT rlc_pdu_ready; + // MAC -> TIMER Messages + LTE_FDD_ENB_TIMER_TICK_MSG_STRUCT timer_tick; + // PDCP -> RLC Messages LTE_FDD_ENB_RLC_SDU_READY_MSG_STRUCT rlc_sdu_ready; @@ -254,9 +356,17 @@ typedef union{ // MME -> RRC Messages LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT rrc_nas_msg_ready; + LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT rrc_cmd_ready; // RRC -> MME Messages LTE_FDD_ENB_MME_NAS_MSG_READY_MSG_STRUCT mme_nas_msg_ready; + LTE_FDD_ENB_MME_RRC_CMD_RESP_MSG_STRUCT mme_rrc_cmd_resp; + + // GW -> PDCP Messages + LTE_FDD_ENB_PDCP_DATA_SDU_READY_MSG_STRUCT pdcp_data_sdu_ready; + + // PDCP -> GW Messages + LTE_FDD_ENB_GW_DATA_READY_MSG_STRUCT gw_data_ready; }LTE_FDD_ENB_MESSAGE_UNION; typedef struct{ @@ -273,16 +383,16 @@ typedef struct{ class LTE_fdd_enb_msgq_cb { public: - typedef void (*FuncType)(void*, LTE_FDD_ENB_MESSAGE_STRUCT*); + typedef void (*FuncType)(void*, LTE_FDD_ENB_MESSAGE_STRUCT&); LTE_fdd_enb_msgq_cb(); LTE_fdd_enb_msgq_cb(FuncType f, void* o); - void operator()(LTE_FDD_ENB_MESSAGE_STRUCT *msg); + void operator()(LTE_FDD_ENB_MESSAGE_STRUCT &msg); private: FuncType func; void *obj; }; -template - void LTE_fdd_enb_msgq_cb_wrapper(void *o, LTE_FDD_ENB_MESSAGE_STRUCT *msg) +template + void LTE_fdd_enb_msgq_cb_wrapper(void *o, LTE_FDD_ENB_MESSAGE_STRUCT &msg) { return (static_cast(o)->*Func)(msg); } @@ -290,33 +400,36 @@ template *circ_buf; + std::string msgq_name; + pthread_t rx_thread; + uint32 prio; + bool rx_setup; }; #endif /* __LTE_FDD_ENB_MSGQ_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_pdcp.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_pdcp.h old mode 100644 new mode 100755 index cbede49..d76d8da --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_pdcp.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_pdcp.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -26,6 +26,12 @@ ---------- ------------- -------------------------------------------- 11/09/2013 Ben Wojtowicz Created file 05/04/2014 Ben Wojtowicz Added communication to RLC and RRC. + 11/29/2014 Ben Wojtowicz Added communication to IP gateway. + 12/16/2014 Ben Wojtowicz Added ol extension to message queues. + 02/15/2015 Ben Wojtowicz Moved to new message queue. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t. + 02/13/2016 Ben Wojtowicz Removed boost message queue include. + 07/29/2017 Ben Wojtowicz Moved away from singleton pattern. *******************************************************************************/ @@ -38,8 +44,6 @@ #include "LTE_fdd_enb_cnfg_db.h" #include "LTE_fdd_enb_msgq.h" -#include -#include /******************************************************************************* DEFINES @@ -63,34 +67,33 @@ class LTE_fdd_enb_pdcp { public: - // Singleton - static LTE_fdd_enb_pdcp* get_instance(void); - static void cleanup(void); + // Constructor/Destructor + LTE_fdd_enb_pdcp(); + ~LTE_fdd_enb_pdcp(); // Start/Stop - void start(void); + void start(LTE_fdd_enb_msgq *from_rlc, LTE_fdd_enb_msgq *from_rrc, LTE_fdd_enb_msgq *from_gw, LTE_fdd_enb_msgq *to_rlc, LTE_fdd_enb_msgq *to_rrc, LTE_fdd_enb_msgq *to_gw, LTE_fdd_enb_interface *iface); void stop(void); // External interface void update_sys_info(void); private: - // Singleton - static LTE_fdd_enb_pdcp *instance; - LTE_fdd_enb_pdcp(); - ~LTE_fdd_enb_pdcp(); - // Start/Stop - boost::mutex start_mutex; - bool started; + LTE_fdd_enb_interface *interface; + sem_t start_sem; + bool started; // Communication - void handle_rlc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg); - void handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg); - LTE_fdd_enb_msgq *rlc_comm_msgq; - LTE_fdd_enb_msgq *rrc_comm_msgq; - boost::interprocess::message_queue *pdcp_rlc_mq; - boost::interprocess::message_queue *pdcp_rrc_mq; + void handle_rlc_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + void handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + void handle_gw_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + LTE_fdd_enb_msgq *msgq_from_rlc; + LTE_fdd_enb_msgq *msgq_from_rrc; + LTE_fdd_enb_msgq *msgq_from_gw; + LTE_fdd_enb_msgq *msgq_to_rlc; + LTE_fdd_enb_msgq *msgq_to_rrc; + LTE_fdd_enb_msgq *msgq_to_gw; // RLC Message Handlers void handle_pdu_ready(LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT *pdu_ready); @@ -98,8 +101,11 @@ class LTE_fdd_enb_pdcp // RRC Message Handlers void handle_sdu_ready(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT *sdu_ready); + // GW Message Handlers + void handle_data_sdu_ready(LTE_FDD_ENB_PDCP_DATA_SDU_READY_MSG_STRUCT *data_sdu_ready); + // Parameters - boost::mutex sys_info_mutex; + sem_t sys_info_sem; LTE_FDD_ENB_SYS_INFO_STRUCT sys_info; }; diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_phy.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_phy.h old mode 100644 new mode 100755 index dc67358..4adeb42 --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_phy.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_phy.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -29,6 +29,14 @@ added the ability to handle late subframes. 05/04/2014 Ben Wojtowicz Added PHICH support. 06/15/2014 Ben Wojtowicz Changed fn_combo to current_tti. + 12/16/2014 Ben Wojtowicz Added ol extension to message queue. + 02/15/2015 Ben Wojtowicz Moved to new message queue. + 07/25/2015 Ben Wojtowicz Combined the DL and UL schedule messages into + a single PHY schedule message. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t. + 07/31/2016 Ben Wojtowicz Added an external interface for getting the + current TTIs. + 07/29/2017 Ben Wojtowicz Added IPC direct to a UE PHY. *******************************************************************************/ @@ -44,7 +52,6 @@ #include "LTE_fdd_enb_msgq.h" #include "LTE_fdd_enb_radio.h" #include "liblte_phy.h" -#include /******************************************************************************* DEFINES @@ -74,12 +81,13 @@ class LTE_fdd_enb_phy static void cleanup(void); // Start/Stop - void start(LTE_fdd_enb_interface *iface); + void start(LTE_fdd_enb_msgq *from_mac, LTE_fdd_enb_msgq *to_mac, bool direct_to_ue, LTE_fdd_enb_interface *iface); void stop(void); // External interface void update_sys_info(void); uint32 get_n_cce(void); + void get_current_ttis(uint32 *dl_tti, uint32 *ul_tti); // Radio interface void radio_interface(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf, LTE_FDD_ENB_RADIO_RX_BUF_STRUCT *rx_buf); @@ -96,20 +104,21 @@ class LTE_fdd_enb_phy bool started; // Communication - void handle_mac_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg); - LTE_fdd_enb_msgq *mac_comm_msgq; - boost::interprocess::message_queue *phy_mac_mq; + void handle_mac_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + void handle_ue_msg(LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT *msg); + LTE_fdd_enb_msgq *msgq_from_mac; + LTE_fdd_enb_msgq *msgq_to_mac; + libtools_ipc_msgq *msgq_to_ue; // Generic parameters LIBLTE_PHY_STRUCT *phy_struct; // Downlink - void handle_dl_schedule(LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT *dl_sched); - void handle_ul_schedule(LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT *ul_sched); + void handle_phy_schedule(LTE_FDD_ENB_PHY_SCHEDULE_MSG_STRUCT *phy_sched); void process_dl(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf); - boost::mutex sys_info_mutex; - boost::mutex dl_sched_mutex; - boost::mutex ul_sched_mutex; + sem_t sys_info_sem; + sem_t dl_sched_sem; + sem_t ul_sched_sem; LTE_FDD_ENB_SYS_INFO_STRUCT sys_info; LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT dl_schedule[10]; LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT ul_schedule[10]; diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_radio.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_radio.h old mode 100644 new mode 100755 index ac6bf37..8345c1c --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_radio.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_radio.h @@ -1,6 +1,7 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz + Copyright 2016 Przemek Bereski (bladeRF support) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -28,6 +29,15 @@ 01/18/2014 Ben Wojtowicz Handling EARFCN updates and multiple antennas. 06/15/2014 Ben Wojtowicz Changed fn_combo to current_tti. + 07/22/2014 Ben Wojtowicz Added clock source as a configurable + parameter. + 07/25/2015 Ben Wojtowicz Added parameters to abstract PHY sample rate + from radio sample rate. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t. + 07/03/2016 Ben Wojtowicz Massive restructuring to support the addition + of bladeRF as a radio choice. + 07/03/2016 Przemek Bereski Addition of bladeRF as a radio choice. + 07/29/2017 Ben Wojtowicz Using the latest tools library. *******************************************************************************/ @@ -40,9 +50,10 @@ #include "LTE_fdd_enb_interface.h" #include "liblte_phy.h" +#include "libtools_ipc_msgq.h" #include #include -#include +#include /******************************************************************************* DEFINES @@ -58,8 +69,15 @@ TYPEDEFS *******************************************************************************/ +typedef enum{ + LTE_FDD_ENB_RADIO_TYPE_NO_RF = 0, + LTE_FDD_ENB_RADIO_TYPE_USRP_B2X0, + LTE_FDD_ENB_RADIO_TYPE_BLADERF, +}LTE_FDD_ENB_RADIO_TYPE_ENUM; + typedef struct{ - std::string name; + std::string name; + LTE_FDD_ENB_RADIO_TYPE_ENUM type; }LTE_FDD_ENB_RADIO_STRUCT; typedef struct{ @@ -67,22 +85,110 @@ typedef struct{ uint32 num_radios; }LTE_FDD_ENB_AVAILABLE_RADIOS_STRUCT; -typedef struct{ - float i_buf[4][LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ]; - float q_buf[4][LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ]; - uint16 current_tti; -}LTE_FDD_ENB_RADIO_TX_BUF_STRUCT; +typedef LIBTOOLS_IPC_MSGQ_PHY_SAMPS_MSG_STRUCT LTE_FDD_ENB_RADIO_TX_BUF_STRUCT; +typedef LIBTOOLS_IPC_MSGQ_PHY_SAMPS_MSG_STRUCT LTE_FDD_ENB_RADIO_RX_BUF_STRUCT; +class LTE_fdd_enb_phy; typedef struct{ - float i_buf[LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ]; - float q_buf[LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ]; - uint16 current_tti; -}LTE_FDD_ENB_RADIO_RX_BUF_STRUCT; + LTE_fdd_enb_interface *interface; + LTE_fdd_enb_phy *phy; + LTE_FDD_ENB_RADIO_TX_BUF_STRUCT tx_radio_buf[2]; + LTE_FDD_ENB_RADIO_RX_BUF_STRUCT rx_radio_buf[2]; + uint32 N_subfrs_dropped; + uint32 samp_rate; + uint32 buf_idx; + uint32 recv_idx; + uint32 samp_idx; + uint32 num_samps; + uint32 N_samps_per_subfr; + uint32 fs; + uint16 rx_current_tti; + uint8 N_ant; + bool init_needed; + bool rx_synced; +}LTE_FDD_ENB_RADIO_PARAMS_STRUCT; /******************************************************************************* CLASS DECLARATIONS *******************************************************************************/ +class LTE_fdd_enb_radio_no_rf +{ +public: + // Constructor/Destructor + LTE_fdd_enb_radio_no_rf(); + ~LTE_fdd_enb_radio_no_rf(); + + // Radio functions + LTE_FDD_ENB_ERROR_ENUM setup(void); + void teardown(void); + void send(void); + void receive(LTE_FDD_ENB_RADIO_PARAMS_STRUCT *radio_params); + +private: + // Parameters + struct timespec sleep_time; +}; + +class LTE_fdd_enb_radio_usrp_b2x0 +{ +public: + // Constructor/Destructor + LTE_fdd_enb_radio_usrp_b2x0(); + ~LTE_fdd_enb_radio_usrp_b2x0(); + + // Radio functions + LTE_FDD_ENB_ERROR_ENUM setup(uint32 idx, double bw, int16 dl_earfcn, int16 ul_earfcn, std::string *clock_src, uint32 samp_rate, uint32 tx_gain, uint32 rx_gain); + void teardown(void); + void send(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *buf, LTE_FDD_ENB_RADIO_PARAMS_STRUCT *radio_params); + void receive(LTE_FDD_ENB_RADIO_PARAMS_STRUCT *radio_params); + +private: + // Parameters + uhd::usrp::multi_usrp::sptr usrp; + uhd::tx_streamer::sptr tx_stream; + uhd::rx_streamer::sptr rx_stream; + uhd::rx_metadata_t metadata; + uhd::time_spec_t next_tx_ts; + uhd::time_spec_t next_rx_ts; + uhd::time_spec_t next_rx_subfr_ts; + uhd::time_spec_t check_ts; + gr_complex tx_buf[LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ]; + gr_complex rx_buf[LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ]; + int64 next_rx_ts_ticks; + int64 metadata_ts_ticks; + uint32 N_tx_samps; + uint32 N_rx_samps; + uint32 recv_size; + uint16 next_tx_current_tti; +}; + +class LTE_fdd_enb_radio_bladerf +{ +public: + // Constructor/Destructor + LTE_fdd_enb_radio_bladerf(); + ~LTE_fdd_enb_radio_bladerf(); + + // Radio functions + LTE_FDD_ENB_ERROR_ENUM setup(uint32 idx, double bandwidth, int16 dl_earfcn, int16 ul_earfcn, uint8 N_ant, uint32 samp_rate, uint32 N_samps_per_subfr); + void teardown(void); + void send(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *buf, LTE_FDD_ENB_RADIO_PARAMS_STRUCT *radio_params); + void receive(LTE_FDD_ENB_RADIO_PARAMS_STRUCT *radio_params); + +private: + // Parameters + struct bladerf *bladerf; + bladerf_metadata metadata_tx; + bladerf_metadata metadata_rx; + uint64 next_tx_ts; + uint64 rx_ts; + uint16 next_tx_current_tti; + int16 tx_buf[LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ*2]; + int16 rx_buf[LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ*2]; + bool first_tx_sample; +}; + class LTE_fdd_enb_radio { public: @@ -100,13 +206,17 @@ class LTE_fdd_enb_radio LTE_FDD_ENB_RADIO_STRUCT get_selected_radio(void); uint32 get_selected_radio_idx(void); LTE_FDD_ENB_ERROR_ENUM set_selected_radio_idx(uint32 idx); + LTE_FDD_ENB_RADIO_TYPE_ENUM get_selected_radio_type(void); uint32 get_tx_gain(void); LTE_FDD_ENB_ERROR_ENUM set_tx_gain(uint32 gain); uint32 get_rx_gain(void); LTE_FDD_ENB_ERROR_ENUM set_rx_gain(uint32 gain); - uint32 get_sample_rate(void); - void set_earfcns(int64 dl_earfcn, int64 ul_earfcn); + std::string get_clock_source(void); + LTE_FDD_ENB_ERROR_ENUM set_clock_source(std::string source); + uint32 get_phy_sample_rate(void); + uint32 get_radio_sample_rate(void); void send(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *buf); + pthread_t get_radio_thread(void); private: // Singleton @@ -115,30 +225,24 @@ class LTE_fdd_enb_radio ~LTE_fdd_enb_radio(); // Start/Stop - boost::mutex start_mutex; - bool started; - - // Radios - uhd::usrp::multi_usrp::sptr usrp; - uhd::tx_streamer::sptr tx_stream; - uhd::rx_streamer::sptr rx_stream; + sem_t start_sem; + bool started; + + // Generic radios + static void* radio_thread_func(void *inputs); + pthread_t radio_thread; + std::string clock_source; + LTE_FDD_ENB_RADIO_PARAMS_STRUCT radio_params; LTE_FDD_ENB_AVAILABLE_RADIOS_STRUCT available_radios; + LTE_FDD_ENB_RADIO_TYPE_ENUM selected_radio_type; uint32 selected_radio_idx; + uint32 tx_gain; + uint32 rx_gain; - // Radio thread - static void* radio_thread_func(void *inputs); - pthread_t radio_thread; - gr_complex tx_buf[LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ]; - gr_complex rx_buf[LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ]; - uhd::time_spec_t next_tx_ts; - int64 N_ant; - uint32 N_tx_samps; - uint32 N_rx_samps; - uint32 N_samps_per_subfr; - uint32 fs; - uint32 tx_gain; - uint32 rx_gain; - uint16 next_tx_current_tti; + // Specific radios + LTE_fdd_enb_radio_no_rf no_rf; + LTE_fdd_enb_radio_usrp_b2x0 usrp_b2x0; + LTE_fdd_enb_radio_bladerf bladerf; }; #endif /* __LTE_FDD_ENB_RADIO_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rb.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rb.h old mode 100644 new mode 100755 index 24480ab..aae916a --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rb.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rb.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2014 Ben Wojtowicz + Copyright 2014-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +27,29 @@ 05/04/2014 Ben Wojtowicz Created file 06/15/2014 Ben Wojtowicz Added more states and procedures, QoS, MME, RLC, and uplink scheduling functionality. + 08/03/2014 Ben Wojtowicz Added MME procedures/states, RRC NAS support, + RRC transaction id, PDCP sequence numbers, + and RLC transmit variables. + 09/03/2014 Ben Wojtowicz Added more MME states and ability to store + the contention resolution identity. + 11/01/2014 Ben Wojtowicz Added more MME states and PDCP security. + 11/29/2014 Ben Wojtowicz Added more DRB support, MME states, MME + procedures, and PDCP configs, moved almost + everything to byte messages structs, added + IP gateway and RLC UMD support. + 12/16/2014 Ben Wojtowicz Added QoS for default data services. + 12/24/2014 Ben Wojtowicz Added asymmetric QoS support. + 02/15/2015 Ben Wojtowicz Split UL/DL QoS TTI frequency, added reset + user support, and added multiple UMD RLC data + support. + 03/11/2015 Ben Wojtowicz Added detach handling. + 07/25/2015 Ben Wojtowicz Moved QoS structure to the user class and + fixed RLC AM TX and RX buffers. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t. + 02/13/2016 Ben Wojtowicz Added a wait for RRC connection + reestablishment complete RRC state. + 12/18/2016 Ben Wojtowicz Properly handling multiple RLC AMD PDUs. + 07/29/2017 Ben Wojtowicz Remove last TTI storage. *******************************************************************************/ @@ -37,10 +60,12 @@ INCLUDES *******************************************************************************/ -#include "LTE_fdd_enb_interface.h" +#include "LTE_fdd_enb_common.h" #include "liblte_rlc.h" #include "liblte_rrc.h" #include +#include +#include /******************************************************************************* DEFINES @@ -61,11 +86,57 @@ typedef enum{ LTE_FDD_ENB_RB_SRB0 = 0, LTE_FDD_ENB_RB_SRB1, LTE_FDD_ENB_RB_SRB2, + LTE_FDD_ENB_RB_DRB1, + LTE_FDD_ENB_RB_DRB2, LTE_FDD_ENB_RB_N_ITEMS, }LTE_FDD_ENB_RB_ENUM; static const char LTE_fdd_enb_rb_text[LTE_FDD_ENB_RB_N_ITEMS][20] = {"SRB0", "SRB1", - "SRB2"}; + "SRB2", + "DRB1", + "DRB2"}; + +typedef enum{ + LTE_FDD_ENB_MME_PROC_IDLE = 0, + LTE_FDD_ENB_MME_PROC_ATTACH, + LTE_FDD_ENB_MME_PROC_SERVICE_REQUEST, + LTE_FDD_ENB_MME_PROC_DETACH, + LTE_FDD_ENB_MME_PROC_N_ITEMS, +}LTE_FDD_ENB_MME_PROC_ENUM; +static const char LTE_fdd_enb_mme_proc_text[LTE_FDD_ENB_MME_PROC_N_ITEMS][100] = {"IDLE", + "ATTACH", + "SERVICE REQUEST", + "DETACH"}; + +typedef enum{ + LTE_FDD_ENB_MME_STATE_IDLE = 0, + LTE_FDD_ENB_MME_STATE_ID_REQUEST_IMSI, + LTE_FDD_ENB_MME_STATE_REJECT, + LTE_FDD_ENB_MME_STATE_AUTHENTICATE, + LTE_FDD_ENB_MME_STATE_AUTH_REJECTED, + LTE_FDD_ENB_MME_STATE_ENABLE_SECURITY, + LTE_FDD_ENB_MME_STATE_RELEASE, + LTE_FDD_ENB_MME_STATE_RRC_SECURITY, + LTE_FDD_ENB_MME_STATE_ESM_INFO_TRANSFER, + LTE_FDD_ENB_MME_STATE_ATTACH_ACCEPT, + LTE_FDD_ENB_MME_STATE_ATTACHED, + LTE_FDD_ENB_MME_STATE_SETUP_DRB, + LTE_FDD_ENB_MME_STATE_SEND_DETACH_ACCEPT, + LTE_FDD_ENB_MME_STATE_N_ITEMS, +}LTE_FDD_ENB_MME_STATE_ENUM; +static const char LTE_fdd_enb_mme_state_text[LTE_FDD_ENB_MME_STATE_N_ITEMS][100] = {"IDLE", + "ID REQUEST IMSI", + "REJECT", + "AUTHENTICATE", + "AUTH REJECTED", + "ENABLE SECURITY", + "RELEASE", + "RRC SECURITY", + "ESM INFO TRANSFER", + "ATTACH ACCEPT", + "ATTACHED", + "SETUP DRB", + "SEND DETACH ACCEPT"}; typedef enum{ LTE_FDD_ENB_RRC_PROC_IDLE = 0, @@ -82,18 +153,24 @@ typedef enum{ LTE_FDD_ENB_RRC_STATE_SRB1_SETUP, LTE_FDD_ENB_RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE, LTE_FDD_ENB_RRC_STATE_RRC_CONNECTED, + LTE_FDD_ENB_RRC_STATE_WAIT_FOR_CON_REEST_COMPLETE, LTE_FDD_ENB_RRC_STATE_N_ITEMS, }LTE_FDD_ENB_RRC_STATE_ENUM; static const char LTE_fdd_enb_rrc_state_text[LTE_FDD_ENB_RRC_STATE_N_ITEMS][100] = {"IDLE", "SRB1 SETUP", "WAIT FOR CON SETUP COMPLETE", - "RRC CONNECTED"}; + "RRC CONNECTED", + "WAIT FOR CON REEST COMPLETE"}; typedef enum{ LTE_FDD_ENB_PDCP_CONFIG_N_A = 0, + LTE_FDD_ENB_PDCP_CONFIG_SECURITY, + LTE_FDD_ENB_PDCP_CONFIG_LONG_SN, LTE_FDD_ENB_PDCP_CONFIG_N_ITEMS, }LTE_FDD_ENB_PDCP_CONFIG_ENUM; -static const char LTE_fdd_enb_pdcp_config_text[LTE_FDD_ENB_PDCP_CONFIG_N_ITEMS][20] = {"N/A"}; +static const char LTE_fdd_enb_pdcp_config_text[LTE_FDD_ENB_PDCP_CONFIG_N_ITEMS][20] = {"N/A", + "SECURITY", + "LONG SN"}; typedef enum{ LTE_FDD_ENB_RLC_CONFIG_TM = 0, @@ -111,19 +188,6 @@ typedef enum{ }LTE_FDD_ENB_MAC_CONFIG_ENUM; static const char LTE_fdd_enb_mac_config_text[LTE_FDD_ENB_MAC_CONFIG_N_ITEMS][20] = {"TM"}; -typedef enum{ - LTE_FDD_ENB_QOS_NONE = 0, - LTE_FDD_ENB_QOS_SIGNALLING, - LTE_FDD_ENB_QOS_N_ITEMS, -}LTE_FDD_ENB_QOS_ENUM; -static const char LTE_fdd_enb_qos_text[LTE_FDD_ENB_QOS_N_ITEMS][20] = {"None", - "Signalling"}; - -typedef struct{ - uint32 tti_frequency; - uint32 bits_per_subfn; -}LTE_FDD_ENB_QOS_STRUCT; - /******************************************************************************* CLASS DECLARATIONS *******************************************************************************/ @@ -137,112 +201,193 @@ class LTE_fdd_enb_rb // Identity LTE_FDD_ENB_RB_ENUM get_rb_id(void); + LTE_fdd_enb_user* get_user(void); + void reset_user(LTE_fdd_enb_user *_user); + + // GW + void queue_gw_data_msg(LIBLTE_BYTE_MSG_STRUCT *gw_data); + LTE_FDD_ENB_ERROR_ENUM get_next_gw_data_msg(LIBLTE_BYTE_MSG_STRUCT **gw_data); + LTE_FDD_ENB_ERROR_ENUM delete_next_gw_data_msg(void); // MME void queue_mme_nas_msg(LIBLTE_BYTE_MSG_STRUCT *nas_msg); LTE_FDD_ENB_ERROR_ENUM get_next_mme_nas_msg(LIBLTE_BYTE_MSG_STRUCT **nas_msg); LTE_FDD_ENB_ERROR_ENUM delete_next_mme_nas_msg(void); + void set_mme_procedure(LTE_FDD_ENB_MME_PROC_ENUM procedure); + LTE_FDD_ENB_MME_PROC_ENUM get_mme_procedure(void); + void set_mme_state(LTE_FDD_ENB_MME_STATE_ENUM state); + LTE_FDD_ENB_MME_STATE_ENUM get_mme_state(void); // RRC LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg; LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg; + LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg; void queue_rrc_pdu(LIBLTE_BIT_MSG_STRUCT *pdu); LTE_FDD_ENB_ERROR_ENUM get_next_rrc_pdu(LIBLTE_BIT_MSG_STRUCT **pdu); LTE_FDD_ENB_ERROR_ENUM delete_next_rrc_pdu(void); + void queue_rrc_nas_msg(LIBLTE_BYTE_MSG_STRUCT *nas_msg); + LTE_FDD_ENB_ERROR_ENUM get_next_rrc_nas_msg(LIBLTE_BYTE_MSG_STRUCT **nas_msg); + LTE_FDD_ENB_ERROR_ENUM delete_next_rrc_nas_msg(void); void set_rrc_procedure(LTE_FDD_ENB_RRC_PROC_ENUM procedure); LTE_FDD_ENB_RRC_PROC_ENUM get_rrc_procedure(void); void set_rrc_state(LTE_FDD_ENB_RRC_STATE_ENUM state); LTE_FDD_ENB_RRC_STATE_ENUM get_rrc_state(void); + uint8 get_rrc_transaction_id(void); + void set_rrc_transaction_id(uint8 transaction_id); // PDCP - void queue_pdcp_pdu(LIBLTE_BIT_MSG_STRUCT *pdu); - LTE_FDD_ENB_ERROR_ENUM get_next_pdcp_pdu(LIBLTE_BIT_MSG_STRUCT **pdu); + void queue_pdcp_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu); + LTE_FDD_ENB_ERROR_ENUM get_next_pdcp_pdu(LIBLTE_BYTE_MSG_STRUCT **pdu); LTE_FDD_ENB_ERROR_ENUM delete_next_pdcp_pdu(void); void queue_pdcp_sdu(LIBLTE_BIT_MSG_STRUCT *sdu); LTE_FDD_ENB_ERROR_ENUM get_next_pdcp_sdu(LIBLTE_BIT_MSG_STRUCT **sdu); LTE_FDD_ENB_ERROR_ENUM delete_next_pdcp_sdu(void); + void queue_pdcp_data_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu); + LTE_FDD_ENB_ERROR_ENUM get_next_pdcp_data_sdu(LIBLTE_BYTE_MSG_STRUCT **sdu); + LTE_FDD_ENB_ERROR_ENUM delete_next_pdcp_data_sdu(void); + void set_pdcp_config(LTE_FDD_ENB_PDCP_CONFIG_ENUM config); LTE_FDD_ENB_PDCP_CONFIG_ENUM get_pdcp_config(void); + uint32 get_pdcp_rx_count(void); + void set_pdcp_rx_count(uint32 rx_count); + uint32 get_pdcp_tx_count(void); + void set_pdcp_tx_count(uint32 tx_count); // RLC - void queue_rlc_pdu(LIBLTE_BIT_MSG_STRUCT *pdu); - LTE_FDD_ENB_ERROR_ENUM get_next_rlc_pdu(LIBLTE_BIT_MSG_STRUCT **pdu); + void queue_rlc_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu); + LTE_FDD_ENB_ERROR_ENUM get_next_rlc_pdu(LIBLTE_BYTE_MSG_STRUCT **pdu); LTE_FDD_ENB_ERROR_ENUM delete_next_rlc_pdu(void); - void queue_rlc_sdu(LIBLTE_BIT_MSG_STRUCT *sdu); - LTE_FDD_ENB_ERROR_ENUM get_next_rlc_sdu(LIBLTE_BIT_MSG_STRUCT **sdu); + void queue_rlc_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu); + LTE_FDD_ENB_ERROR_ENUM get_next_rlc_sdu(LIBLTE_BYTE_MSG_STRUCT **sdu); LTE_FDD_ENB_ERROR_ENUM delete_next_rlc_sdu(void); LTE_FDD_ENB_RLC_CONFIG_ENUM get_rlc_config(void); uint16 get_rlc_vrr(void); void set_rlc_vrr(uint16 vrr); + void update_rlc_vrr(void); uint16 get_rlc_vrmr(void); uint16 get_rlc_vrh(void); void set_rlc_vrh(uint16 vrh); - void rlc_add_to_reception_buffer(LIBLTE_RLC_AMD_PDU_STRUCT *amd_pdu); - LTE_FDD_ENB_ERROR_ENUM rlc_reassemble(LIBLTE_BIT_MSG_STRUCT *sdu); + void rlc_add_to_am_reception_buffer(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT *amd_pdu); + void rlc_get_am_reception_buffer_status(LIBLTE_RLC_STATUS_PDU_STRUCT *status); + LTE_FDD_ENB_ERROR_ENUM rlc_am_reassemble(LIBLTE_BYTE_MSG_STRUCT *sdu); + uint16 get_rlc_vta(void); + void set_rlc_vta(uint16 vta); + uint16 get_rlc_vtms(void); + uint16 get_rlc_vts(void); + void set_rlc_vts(uint16 vts); + void rlc_add_to_transmission_buffer(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT *amd_pdu); + void rlc_update_transmission_buffer(LIBLTE_RLC_STATUS_PDU_STRUCT *status); + void rlc_start_t_poll_retransmit(void); + void rlc_stop_t_poll_retransmit(void); + void handle_t_poll_retransmit_timer_expiry(uint32 timer_id); + void set_rlc_vruh(uint16 vruh); + uint16 get_rlc_vruh(void); + void set_rlc_vrur(uint16 vrur); + uint16 get_rlc_vrur(void); + uint16 get_rlc_um_window_size(void); + void rlc_add_to_um_reception_buffer(LIBLTE_RLC_UMD_PDU_STRUCT *umd_pdu, uint32 idx); + LTE_FDD_ENB_ERROR_ENUM rlc_um_reassemble(LIBLTE_BYTE_MSG_STRUCT *sdu); + void set_rlc_vtus(uint16 vtus); + uint16 get_rlc_vtus(void); // MAC - void queue_mac_sdu(LIBLTE_BIT_MSG_STRUCT *sdu); - LTE_FDD_ENB_ERROR_ENUM get_next_mac_sdu(LIBLTE_BIT_MSG_STRUCT **sdu); + void queue_mac_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu); + LTE_FDD_ENB_ERROR_ENUM get_next_mac_sdu(LIBLTE_BYTE_MSG_STRUCT **sdu); LTE_FDD_ENB_ERROR_ENUM delete_next_mac_sdu(void); LTE_FDD_ENB_MAC_CONFIG_ENUM get_mac_config(void); - void start_ul_sched_timer(uint32 m_seconds); - void handle_ul_sched_timer_expiry(uint32 timer_id); - - // Generic - void set_qos(LTE_FDD_ENB_QOS_ENUM _qos); - LTE_FDD_ENB_QOS_ENUM get_qos(void); + void set_con_res_id(uint64 con_res_id); + uint64 get_con_res_id(void); + void set_send_con_res_id(bool send_con_res_id); + bool get_send_con_res_id(void); + + // DRB + void set_eps_bearer_id(uint32 ebi); + uint32 get_eps_bearer_id(void); + void set_lc_id(uint32 _lc_id); + uint32 get_lc_id(void); + void set_drb_id(uint8 _drb_id); + uint8 get_drb_id(void); + void set_log_chan_group(uint8 lcg); + uint8 get_log_chan_group(void); private: // Identity LTE_FDD_ENB_RB_ENUM rb; LTE_fdd_enb_user *user; + // GW + sem_t gw_data_msg_queue_sem; + std::list gw_data_msg_queue; + // MME - boost::mutex mme_nas_msg_queue_mutex; + sem_t mme_nas_msg_queue_sem; std::list mme_nas_msg_queue; + LTE_FDD_ENB_MME_PROC_ENUM mme_procedure; + LTE_FDD_ENB_MME_STATE_ENUM mme_state; // RRC - boost::mutex rrc_pdu_queue_mutex; - std::list rrc_pdu_queue; - LTE_FDD_ENB_RRC_PROC_ENUM rrc_procedure; - LTE_FDD_ENB_RRC_STATE_ENUM rrc_state; + sem_t rrc_pdu_queue_sem; + sem_t rrc_nas_msg_queue_sem; + std::list rrc_pdu_queue; + std::list rrc_nas_msg_queue; + LTE_FDD_ENB_RRC_PROC_ENUM rrc_procedure; + LTE_FDD_ENB_RRC_STATE_ENUM rrc_state; + uint8 rrc_transaction_id; // PDCP - boost::mutex pdcp_pdu_queue_mutex; - boost::mutex pdcp_sdu_queue_mutex; - std::list pdcp_pdu_queue; - std::list pdcp_sdu_queue; - LTE_FDD_ENB_PDCP_CONFIG_ENUM pdcp_config; + sem_t pdcp_pdu_queue_sem; + sem_t pdcp_sdu_queue_sem; + sem_t pdcp_data_sdu_queue_sem; + std::list pdcp_pdu_queue; + std::list pdcp_sdu_queue; + std::list pdcp_data_sdu_queue; + LTE_FDD_ENB_PDCP_CONFIG_ENUM pdcp_config; + uint32 pdcp_rx_count; + uint32 pdcp_tx_count; // RLC - boost::mutex rlc_pdu_queue_mutex; - boost::mutex rlc_sdu_queue_mutex; - std::list rlc_pdu_queue; - std::list rlc_sdu_queue; - std::map rlc_reception_buffer; - LTE_FDD_ENB_RLC_CONFIG_ENUM rlc_config; - uint16 rlc_vrr; - uint16 rlc_vrmr; - uint16 rlc_vrh; - uint16 rlc_first_segment_sn; - uint16 rlc_last_segment_sn; + sem_t rlc_pdu_queue_sem; + sem_t rlc_sdu_queue_sem; + std::list rlc_pdu_queue; + std::list rlc_sdu_queue; + std::map rlc_am_reception_buffer; + std::map rlc_am_transmission_buffer; + std::map rlc_um_reception_buffer; + LTE_FDD_ENB_RLC_CONFIG_ENUM rlc_config; + uint32 t_poll_retransmit_timer_id; + uint16 rlc_vrr; + uint16 rlc_vrmr; + uint16 rlc_vrh; + uint16 rlc_vta; + uint16 rlc_vtms; + uint16 rlc_vts; + uint16 rlc_vruh; + uint16 rlc_vrur; + uint16 rlc_um_window_size; + uint16 rlc_first_um_segment_sn; + uint16 rlc_last_um_segment_sn; + uint16 rlc_vtus; // MAC - boost::mutex mac_sdu_queue_mutex; - std::list mac_sdu_queue; - LTE_FDD_ENB_MAC_CONFIG_ENUM mac_config; - uint32 ul_sched_timer_id; - uint32 ul_sched_timer_m_seconds; + sem_t mac_sdu_queue_sem; + std::list mac_sdu_queue; + LTE_FDD_ENB_MAC_CONFIG_ENUM mac_config; + uint64 mac_con_res_id; + bool mac_send_con_res_id; + + // DRB + uint32 eps_bearer_id; + uint32 lc_id; + uint8 drb_id; + uint8 log_chan_group; // Generic - void queue_msg(LIBLTE_BIT_MSG_STRUCT *msg, boost::mutex *mutex, std::list *queue); - void queue_msg(LIBLTE_BYTE_MSG_STRUCT *msg, boost::mutex *mutex, std::list *queue); - LTE_FDD_ENB_ERROR_ENUM get_next_msg(boost::mutex *mutex, std::list *queue, LIBLTE_BIT_MSG_STRUCT **msg); - LTE_FDD_ENB_ERROR_ENUM get_next_msg(boost::mutex *mutex, std::list *queue, LIBLTE_BYTE_MSG_STRUCT **msg); - LTE_FDD_ENB_ERROR_ENUM delete_next_msg(boost::mutex *mutex, std::list *queue); - LTE_FDD_ENB_ERROR_ENUM delete_next_msg(boost::mutex *mutex, std::list *queue); - LTE_FDD_ENB_QOS_STRUCT avail_qos[LTE_FDD_ENB_QOS_N_ITEMS]; - LTE_FDD_ENB_QOS_ENUM qos; + void queue_msg(LIBLTE_BIT_MSG_STRUCT *msg, sem_t *sem, std::list *queue); + void queue_msg(LIBLTE_BYTE_MSG_STRUCT *msg, sem_t *sem, std::list *queue); + LTE_FDD_ENB_ERROR_ENUM get_next_msg(sem_t *sem, std::list *queue, LIBLTE_BIT_MSG_STRUCT **msg); + LTE_FDD_ENB_ERROR_ENUM get_next_msg(sem_t *sem, std::list *queue, LIBLTE_BYTE_MSG_STRUCT **msg); + LTE_FDD_ENB_ERROR_ENUM delete_next_msg(sem_t *sem, std::list *queue); + LTE_FDD_ENB_ERROR_ENUM delete_next_msg(sem_t *sem, std::list *queue); }; #endif /* __LTE_FDD_ENB_RB_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rlc.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rlc.h old mode 100644 new mode 100755 index c823b3a..8a82f92 --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rlc.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rlc.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2016 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +27,13 @@ 11/09/2013 Ben Wojtowicz Created file 05/04/2014 Ben Wojtowicz Added communication to MAC and PDCP. 06/15/2014 Ben Wojtowicz Using the latest LTE library. + 08/03/2014 Ben Wojtowicz Added transmit functionality. + 11/29/2014 Ben Wojtowicz Using the byte message structure. + 12/16/2014 Ben Wojtowicz Added ol extension to message queues. + 02/15/2015 Ben Wojtowicz Moved to new message queue. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t. + 02/13/2016 Ben Wojtowicz Removed boost message queue include. + 12/18/2016 Ben Wojtowicz Properly handling multiple AMD PDUs. *******************************************************************************/ @@ -39,8 +46,6 @@ #include "LTE_fdd_enb_cnfg_db.h" #include "LTE_fdd_enb_msgq.h" -#include -#include /******************************************************************************* DEFINES @@ -69,11 +74,12 @@ class LTE_fdd_enb_rlc static void cleanup(void); // Start/Stop - void start(void); + void start(LTE_fdd_enb_msgq *from_mac, LTE_fdd_enb_msgq *from_pdcp, LTE_fdd_enb_msgq *to_mac, LTE_fdd_enb_msgq *to_pdcp, LTE_fdd_enb_interface *iface); void stop(void); // External interface void update_sys_info(void); + void handle_retransmit(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT *amd, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); private: // Singleton @@ -82,31 +88,37 @@ class LTE_fdd_enb_rlc ~LTE_fdd_enb_rlc(); // Start/Stop - boost::mutex start_mutex; - bool started; + LTE_fdd_enb_interface *interface; + sem_t start_sem; + bool started; // Communication - void handle_mac_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg); - void handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg); - LTE_fdd_enb_msgq *mac_comm_msgq; - LTE_fdd_enb_msgq *pdcp_comm_msgq; - boost::interprocess::message_queue *rlc_mac_mq; - boost::interprocess::message_queue *rlc_pdcp_mq; + void handle_mac_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + void handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + LTE_fdd_enb_msgq *msgq_from_mac; + LTE_fdd_enb_msgq *msgq_from_pdcp; + LTE_fdd_enb_msgq *msgq_to_mac; + LTE_fdd_enb_msgq *msgq_to_pdcp; // MAC Message Handlers void handle_pdu_ready(LTE_FDD_ENB_RLC_PDU_READY_MSG_STRUCT *pdu_ready); - void handle_tm_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); - void handle_um_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); - void handle_am_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void handle_tm_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void handle_um_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void handle_am_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void handle_status_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); // PDCP Message Handlers void handle_sdu_ready(LTE_FDD_ENB_RLC_SDU_READY_MSG_STRUCT *sdu_ready); - void handle_tm_sdu(LIBLTE_BIT_MSG_STRUCT *sdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); - void handle_um_sdu(LIBLTE_BIT_MSG_STRUCT *sdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); - void handle_am_sdu(LIBLTE_BIT_MSG_STRUCT *sdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void handle_tm_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void handle_um_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void handle_am_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + + // Message Constructors + void send_status_pdu(LIBLTE_RLC_STATUS_PDU_STRUCT *status_pdu, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_amd_pdu(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT *amd, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); // Parameters - boost::mutex sys_info_mutex; + sem_t sys_info_sem; LTE_FDD_ENB_SYS_INFO_STRUCT sys_info; }; diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rrc.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rrc.h old mode 100644 new mode 100755 index 8eac74d..6719d73 --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rrc.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_rrc.h @@ -1,6 +1,7 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz + Copyright 2016 Przemek Bereski (send_ue_capability_enquiry) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -29,6 +30,20 @@ machine. 06/15/2014 Ben Wojtowicz Added UL DCCH message handling and MME NAS message handling. + 08/03/2014 Ben Wojtowicz Added downlink NAS message handling and + connection release. + 11/01/2014 Ben Wojtowicz Added RRC connection reconfiguration and + security mode command messages. + 11/29/2014 Ben Wojtowicz Added user and rb update to + parse_ul_ccch_message. + 12/16/2014 Ben Wojtowicz Added ol extension to message queues. + 02/15/2015 Ben Wojtowicz Moved to new message queue. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t. + 02/13/2016 Ben Wojtowicz Removed boost message queue include and + add support for connection reestablishment + and connection reestablishment reject. + 07/03/2016 Przemek Bereski Added send_ue_capability_enquiry. + 07/29/2017 Ben Wojtowicz Added SR support. *******************************************************************************/ @@ -42,8 +57,6 @@ #include "LTE_fdd_enb_cnfg_db.h" #include "LTE_fdd_enb_user.h" #include "LTE_fdd_enb_msgq.h" -#include -#include /******************************************************************************* DEFINES @@ -72,11 +85,12 @@ class LTE_fdd_enb_rrc static void cleanup(void); // Start/Stop - void start(void); + void start(LTE_fdd_enb_msgq *from_pdcp, LTE_fdd_enb_msgq *from_mme, LTE_fdd_enb_msgq *to_pdcp, LTE_fdd_enb_msgq *to_mme, LTE_fdd_enb_interface *iface); void stop(void); // External interface void update_sys_info(void); + void handle_cmd(LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT *cmd); private: // Singleton @@ -85,16 +99,17 @@ class LTE_fdd_enb_rrc ~LTE_fdd_enb_rrc(); // Start/Stop - boost::mutex start_mutex; - bool started; + LTE_fdd_enb_interface *interface; + sem_t start_sem; + bool started; // Communication - void handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg); - void handle_mme_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg); - LTE_fdd_enb_msgq *pdcp_comm_msgq; - LTE_fdd_enb_msgq *mme_comm_msgq; - boost::interprocess::message_queue *rrc_pdcp_mq; - boost::interprocess::message_queue *rrc_mme_mq; + void handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + void handle_mme_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + LTE_fdd_enb_msgq *msgq_from_pdcp; + LTE_fdd_enb_msgq *msgq_from_mme; + LTE_fdd_enb_msgq *msgq_to_pdcp; + LTE_fdd_enb_msgq *msgq_to_mme; // PDCP Message Handlers void handle_pdu_ready(LTE_FDD_ENB_RRC_PDU_READY_MSG_STRUCT *pdu_ready); @@ -107,15 +122,26 @@ class LTE_fdd_enb_rrc void dcch_sm(LIBLTE_BIT_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); // Message Parsers - void parse_ul_ccch_message(LIBLTE_BIT_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void parse_ul_ccch_message(LIBLTE_BIT_MSG_STRUCT *msg, LTE_fdd_enb_user **user, LTE_fdd_enb_rb **rb); void parse_ul_dcch_message(LIBLTE_BIT_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); // Message Senders + void send_dl_info_transfer(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb, LIBLTE_BYTE_MSG_STRUCT *msg); + void send_rrc_con_reconfig(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb, LIBLTE_BYTE_MSG_STRUCT *msg); + void send_rrc_con_reest(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_rrc_con_reest_reject(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_rrc_con_release(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); void send_rrc_con_setup(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_security_mode_command(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + void send_ue_capability_enquiry(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb); + + // Helpers + void increment_i_sr(void); // Parameters - boost::mutex sys_info_mutex; + sem_t sys_info_sem; LTE_FDD_ENB_SYS_INFO_STRUCT sys_info; + uint32 i_sr; }; #endif /* __LTE_FDD_ENB_RRC_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer.h old mode 100644 new mode 100755 index 57c4f5c..36f06e7 --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer.h @@ -27,6 +27,7 @@ 05/04/2014 Ben Wojtowicz Created file 06/15/2014 Ben Wojtowicz Added millisecond resolution and seperated the callback calling functionality. + 11/29/2014 Ben Wojtowicz Added timer reset support. *******************************************************************************/ @@ -84,6 +85,7 @@ class LTE_fdd_enb_timer ~LTE_fdd_enb_timer(); // External interface + void reset(void); void increment(void); bool expired(void); void call_callback(void); diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer_mgr.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer_mgr.h old mode 100644 new mode 100755 index f6b9168..a940886 --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer_mgr.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer_mgr.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2014 Ben Wojtowicz + Copyright 2014-2015 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -26,6 +26,10 @@ ---------- ------------- -------------------------------------------- 05/04/2014 Ben Wojtowicz Created file 06/15/2014 Ben Wojtowicz Added millisecond resolution. + 08/03/2014 Ben Wojtowicz Added an invalid timer id. + 11/29/2014 Ben Wojtowicz Added timer reset support. + 02/15/2015 Ben Wojtowicz Moved to new message queue for timer ticks. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t. *******************************************************************************/ @@ -38,12 +42,13 @@ #include "LTE_fdd_enb_interface.h" #include "LTE_fdd_enb_timer.h" -#include +#include "LTE_fdd_enb_msgq.h" /******************************************************************************* DEFINES *******************************************************************************/ +#define LTE_FDD_ENB_INVALID_TIMER_ID 0xFFFFFFFF /******************************************************************************* FORWARD DECLARATIONS @@ -66,10 +71,14 @@ class LTE_fdd_enb_timer_mgr static LTE_fdd_enb_timer_mgr* get_instance(void); static void cleanup(void); + // Start/Stop + void start(LTE_fdd_enb_msgq *from_mac, LTE_fdd_enb_interface *iface); + void stop(void); + // External Interface LTE_FDD_ENB_ERROR_ENUM start_timer(uint32 m_seconds, LTE_fdd_enb_timer_cb cb, uint32 *timer_id); LTE_FDD_ENB_ERROR_ENUM stop_timer(uint32 timer_id); - void handle_tick(void); + LTE_FDD_ENB_ERROR_ENUM reset_timer(uint32 timer_id); private: // Singleton @@ -77,8 +86,18 @@ class LTE_fdd_enb_timer_mgr LTE_fdd_enb_timer_mgr(); ~LTE_fdd_enb_timer_mgr(); + // Start/Stop + LTE_fdd_enb_interface *interface; + sem_t start_sem; + bool started; + + // Communication + void handle_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg); + void handle_tick(void); + LTE_fdd_enb_msgq *msgq_from_mac; + // Timer Storage - boost::mutex timer_mutex; + sem_t timer_sem; std::map timer_map; uint32 next_timer_id; }; diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_user.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_user.h old mode 100644 new mode 100755 index deb07ae..d4ac3d2 --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_user.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_user.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +27,22 @@ 11/09/2013 Ben Wojtowicz Created file 05/04/2014 Ben Wojtowicz Added radio bearer support. 06/15/2014 Ben Wojtowicz Added initialize routine. + 08/03/2014 Ben Wojtowicz Refactored user identities. + 09/03/2014 Ben Wojtowicz Added ciphering and integrity algorithm + storing. + 11/01/2014 Ben Wojtowicz Added more MME support and RRC key storage. + 11/29/2014 Ben Wojtowicz Added DRB setup/teardown and C-RNTI release + timer support. + 12/16/2014 Ben Wojtowicz Changed the delayed delete functionality. + 02/15/2015 Ben Wojtowicz Added clear_rbs and fixed copy_rbs. + 07/25/2015 Ben Wojtowicz Moved the QoS structure from the RB class to + the user class and got rid of the cached + copy of pusch_mac_pdu. + 12/06/2015 Ben Wojtowicz Changed the deletion and C-RNTI release + procedures. + 02/13/2016 Ben Wojtowicz Added an inactivity timer. + 03/12/2016 Ben Wojtowicz Added H-ARQ support. + 07/29/2017 Ben Wojtowicz Remove QOS support and fixed UL scheduling. *******************************************************************************/ @@ -37,9 +53,10 @@ INCLUDES *******************************************************************************/ -#include "LTE_fdd_enb_interface.h" #include "LTE_fdd_enb_rb.h" +#include "liblte_phy.h" #include "liblte_mac.h" +#include "liblte_mme.h" #include "typedefs.h" #include @@ -47,6 +64,7 @@ DEFINES *******************************************************************************/ +#define LTE_FDD_ENB_USER_INACTIVITY_TIMER_VALUE_MS 10000 /******************************************************************************* FORWARD DECLARATIONS @@ -57,6 +75,29 @@ TYPEDEFS *******************************************************************************/ +typedef struct{ + uint64 imsi; + uint64 imei; +}LTE_FDD_ENB_USER_ID_STRUCT; + +typedef struct{ + uint32 nas_count_ul; + uint32 nas_count_dl; + uint8 rand[16]; + uint8 res[8]; + uint8 ck[16]; + uint8 ik[16]; + uint8 autn[16]; + uint8 k_nas_enc[32]; + uint8 k_nas_int[32]; + uint8 k_rrc_enc[32]; + uint8 k_rrc_int[32]; +}LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT; + +typedef struct{ + LIBLTE_MAC_PDU_STRUCT mac_pdu; + LIBLTE_PHY_ALLOCATION_STRUCT alloc; +}LTE_FDD_ENB_HARQ_INFO_STRUCT; /******************************************************************************* CLASS DECLARATIONS @@ -66,16 +107,54 @@ class LTE_fdd_enb_user { public: // Constructor/Destructor - LTE_fdd_enb_user(std::string _imsi); + LTE_fdd_enb_user(); ~LTE_fdd_enb_user(); // Initialize void init(void); // Identity - std::string get_imsi(void); + void set_id(LTE_FDD_ENB_USER_ID_STRUCT *identity); + LTE_FDD_ENB_USER_ID_STRUCT* get_id(void); + bool is_id_set(void); + void set_guti(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *_guti); + LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT* get_guti(void); + bool is_guti_set(void); + void set_temp_id(uint64 id); + uint64 get_temp_id(void); + std::string get_imsi_str(void); + uint64 get_imsi_num(void); + std::string get_imei_str(void); + uint64 get_imei_num(void); void set_c_rnti(uint16 _c_rnti); uint16 get_c_rnti(void); + bool is_c_rnti_set(void); + void set_ip_addr(uint32 addr); + uint32 get_ip_addr(void); + bool is_ip_addr_set(void); + void prepare_for_deletion(void); + + // Security + void set_auth_vec(LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT *av); + LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT* get_auth_vec(void); + void increment_nas_count_dl(void); + void increment_nas_count_ul(void); + bool is_auth_vec_set(void); + + // Capabilities + void set_eea_support(uint8 eea, bool support); + bool get_eea_support(uint8 eea); + void set_eia_support(uint8 eia, bool support); + bool get_eia_support(uint8 eia); + void set_uea_support(uint8 uea, bool support); + bool get_uea_support(uint8 uea); + bool is_uea_set(void); + void set_uia_support(uint8 uia, bool support); + bool get_uia_support(uint8 uia); + bool is_uia_set(void); + void set_gea_support(uint8 gea, bool support); + bool get_gea_support(uint8 gea); + bool is_gea_set(void); // Radio Bearers void get_srb0(LTE_fdd_enb_rb **rb); @@ -85,20 +164,101 @@ class LTE_fdd_enb_user LTE_FDD_ENB_ERROR_ENUM setup_srb2(LTE_fdd_enb_rb **rb); LTE_FDD_ENB_ERROR_ENUM teardown_srb2(void); LTE_FDD_ENB_ERROR_ENUM get_srb2(LTE_fdd_enb_rb **rb); + LTE_FDD_ENB_ERROR_ENUM setup_drb(LTE_FDD_ENB_RB_ENUM drb_id, LTE_fdd_enb_rb **rb); + LTE_FDD_ENB_ERROR_ENUM teardown_drb(LTE_FDD_ENB_RB_ENUM drb_id); + LTE_FDD_ENB_ERROR_ENUM get_drb(LTE_FDD_ENB_RB_ENUM drb_id, LTE_fdd_enb_rb **rb); + void copy_rbs(LTE_fdd_enb_user *user); + void clear_rbs(void); + + // MME + void set_emm_cause(uint8 cause); + uint8 get_emm_cause(void); + void set_attach_type(uint8 type); + uint8 get_attach_type(void); + void set_pdn_type(uint8 type); + uint8 get_pdn_type(void); + void set_eps_bearer_id(uint8 id); + uint8 get_eps_bearer_id(void); + void set_proc_transaction_id(uint8 id); + uint8 get_proc_transaction_id(void); + void set_esm_info_transfer(bool eit); + bool get_esm_info_transfer(void); + void set_protocol_cnfg_opts(LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT *pco); + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT* get_protocol_cnfg_opts(void); // MAC - LIBLTE_MAC_PDU_STRUCT pusch_mac_pdu; + bool get_dl_ndi(void); + void flip_dl_ndi(void); + bool get_ul_ndi(void); + void flip_ul_ndi(void); + void store_harq_info(uint32 pucch_tti, LIBLTE_MAC_PDU_STRUCT *mac_pdu, LIBLTE_PHY_ALLOCATION_STRUCT *alloc); + void clear_harq_info(uint32 pucch_tti); + LTE_FDD_ENB_ERROR_ENUM get_harq_info(uint32 pucch_tti, LIBLTE_MAC_PDU_STRUCT *mac_pdu, LIBLTE_PHY_ALLOCATION_STRUCT *alloc); + void set_ul_buffer_size(uint32 N_bytes_in_buffer); + void update_ul_buffer_size(uint32 N_bytes_received); + uint32 get_ul_buffer_size(void); + + // Generic + void set_N_del_ticks(uint32 N_ticks); + uint32 get_N_del_ticks(void); + uint32 get_max_ul_bytes_per_subfn(void); + uint32 get_max_dl_bytes_per_subfn(void); + void start_inactivity_timer(uint32 m_seconds); + void reset_inactivity_timer(uint32 m_seconds); + void stop_inactivity_timer(void); private: // Identity - std::string imsi; - uint32 c_rnti; + LTE_FDD_ENB_USER_ID_STRUCT id; + LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; + uint64 temp_id; + uint32 c_rnti; + uint32 ip_addr; + bool id_set; + bool guti_set; + bool c_rnti_set; + bool ip_addr_set; + + // Security + LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT auth_vec; + bool auth_vec_set; + + // Capabilities + bool eea_support[8]; + bool eia_support[8]; + bool uea_support[8]; + bool uea_set; + bool uia_support[8]; + bool uia_set; + bool gea_support[8]; + bool gea_set; // Radio Bearers LTE_fdd_enb_rb *srb0; LTE_fdd_enb_rb *srb1; LTE_fdd_enb_rb *srb2; LTE_fdd_enb_rb *drb[8]; + + // MME + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 emm_cause; + uint8 attach_type; + uint8 pdn_type; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + bool eit_flag; + + // MAC + sem_t harq_buffer_sem; + std::map harq_buffer; + uint32 ul_buffer_size; + bool dl_ndi; + bool ul_ndi; + + // Generic + void handle_timer_expiry(uint32 timer_id); + uint32 N_del_ticks; + uint32 inactivity_timer_id; }; #endif /* __LTE_FDD_ENB_USER_H__ */ diff --git a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_user_mgr.h b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_user_mgr.h old mode 100644 new mode 100755 index aea445b..27bb14e --- a/LTE_fdd_enodeb/hdr/LTE_fdd_enb_user_mgr.h +++ b/LTE_fdd_enodeb/hdr/LTE_fdd_enb_user_mgr.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2016 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -26,6 +26,16 @@ ---------- ------------- -------------------------------------------- 11/09/2013 Ben Wojtowicz Created file 05/04/2014 Ben Wojtowicz Added C-RNTI timeout timers. + 08/03/2014 Ben Wojtowicz Refactored add_user. + 11/01/2014 Ben Wojtowicz Added M-TMSI assignment. + 11/29/2014 Ben Wojtowicz Refactored C-RNTI assign/release, added + C-RNTI transfer, added more ways to add, + delete, and find users. + 12/16/2014 Ben Wojtowicz Added delayed user delete functionality. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to sem_t and changed the + user deletion procedure. + 02/13/2016 Ben Wojtowicz Added ability to retrieve a string of all + registered users. *******************************************************************************/ @@ -38,7 +48,6 @@ #include "LTE_fdd_enb_interface.h" #include "LTE_fdd_enb_user.h" -#include #include /******************************************************************************* @@ -68,15 +77,22 @@ class LTE_fdd_enb_user_mgr static void cleanup(void); // External interface - LTE_FDD_ENB_ERROR_ENUM get_free_c_rnti(uint16 *c_rnti); - void assign_c_rnti(uint16 c_rnti, LTE_fdd_enb_user *user); - LTE_FDD_ENB_ERROR_ENUM free_c_rnti(uint16 c_rnti); - LTE_FDD_ENB_ERROR_ENUM add_user(std::string imsi); - LTE_FDD_ENB_ERROR_ENUM add_user(uint16 c_rnti); + LTE_FDD_ENB_ERROR_ENUM assign_c_rnti(LTE_fdd_enb_user *user, uint16 *c_rnti); + LTE_FDD_ENB_ERROR_ENUM release_c_rnti(uint16 c_rnti); + LTE_FDD_ENB_ERROR_ENUM transfer_c_rnti(LTE_fdd_enb_user *old_user, LTE_fdd_enb_user *new_user); + LTE_FDD_ENB_ERROR_ENUM reset_c_rnti_timer(uint16 c_rnti); + uint32 get_next_m_tmsi(void); + LTE_FDD_ENB_ERROR_ENUM add_user(LTE_fdd_enb_user **user); LTE_FDD_ENB_ERROR_ENUM find_user(std::string imsi, LTE_fdd_enb_user **user); LTE_FDD_ENB_ERROR_ENUM find_user(uint16 c_rnti, LTE_fdd_enb_user **user); + LTE_FDD_ENB_ERROR_ENUM find_user(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *guti, LTE_fdd_enb_user **user); + LTE_FDD_ENB_ERROR_ENUM find_user(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi, LTE_fdd_enb_user **user); + LTE_FDD_ENB_ERROR_ENUM find_user(uint32 ip_addr, LTE_fdd_enb_user **user); + LTE_FDD_ENB_ERROR_ENUM del_user(LTE_fdd_enb_user *user); LTE_FDD_ENB_ERROR_ENUM del_user(std::string imsi); LTE_FDD_ENB_ERROR_ENUM del_user(uint16 c_rnti); + LTE_FDD_ENB_ERROR_ENUM del_user(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *guti); + std::string print_all_users(void); private: // Singleton @@ -88,13 +104,16 @@ class LTE_fdd_enb_user_mgr void handle_c_rnti_timer_expiry(uint32 timer_id); // User storage - std::map user_map; - std::map c_rnti_map; - std::map timer_id_map; - boost::mutex user_mutex; - boost::mutex c_rnti_mutex; - boost::mutex timer_id_mutex; - uint16 next_c_rnti; + std::list user_list; + std::list delayed_del_user_list; + std::map c_rnti_map; + std::map timer_id_map_forward; + std::map timer_id_map_reverse; + sem_t user_sem; + sem_t c_rnti_sem; + sem_t timer_id_sem; + uint32 next_m_tmsi; + uint16 next_c_rnti; }; #endif /* __LTE_FDD_ENB_USER_MGR_H__ */ diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_cnfg_db.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_cnfg_db.cc old mode 100644 new mode 100755 index 241ff02..7d20a80 --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_cnfg_db.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_cnfg_db.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_cnfg_db.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -32,6 +32,26 @@ 03/26/2014 Ben Wojtowicz Using the latest LTE library. 05/04/2014 Ben Wojtowicz Added PCAP support. 06/15/2014 Ben Wojtowicz Omitting path from __FILE__. + 08/03/2014 Ben Wojtowicz Added support for limiting PCAP output. + 09/03/2014 Ben Wojtowicz Added better MCC/MNC support and UL EARFCN, + and DL and UL center frequencies. + 11/01/2014 Ben Wojtowicz Added config file support. + 03/15/2015 Ben Wojtowicz Fixed uninitialized variables. + 07/25/2015 Ben Wojtowicz Added config file support for TX/RX gains + and changed the default time alignment timer + to 10240 subframes. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t, + properly initialized SIB scheduling info, and + properly constructing MNC (thanks to Mikhail + Gudkov). + 02/13/2016 Ben Wojtowicz Actually properly constructing MNC (again, + thanks to Mikhail Gudkov). + 07/03/2016 Ben Wojtowicz Removed the ability to switch EARFCNs while + the radio is running. + 07/29/2017 Ben Wojtowicz Added a routine for filling RRC physical + layer dedicated configuration, added input + parameters for direct IPC to a UE, and using + the latest tools library. *******************************************************************************/ @@ -41,6 +61,7 @@ #include "LTE_fdd_enb_cnfg_db.h" #include "LTE_fdd_enb_interface.h" +#include "LTE_fdd_enb_hss.h" #include "LTE_fdd_enb_phy.h" #include "LTE_fdd_enb_mac.h" #include "LTE_fdd_enb_rlc.h" @@ -49,8 +70,8 @@ #include "LTE_fdd_enb_mme.h" #include "liblte_mac.h" #include "liblte_interface.h" -#include -#include +#include "libtools_scoped_lock.h" +#include "libtools_helpers.h" /******************************************************************************* DEFINES @@ -66,8 +87,8 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_enb_cnfg_db* LTE_fdd_enb_cnfg_db::instance = NULL; -boost::mutex cnfg_db_instance_mutex; +LTE_fdd_enb_cnfg_db* LTE_fdd_enb_cnfg_db::instance = NULL; +static pthread_mutex_t cnfg_db_instance_mutex = PTHREAD_MUTEX_INITIALIZER; /******************************************************************************* CLASS IMPLEMENTATIONS @@ -78,7 +99,7 @@ boost::mutex cnfg_db_instance_mutex; /*******************/ LTE_fdd_enb_cnfg_db* LTE_fdd_enb_cnfg_db::get_instance(void) { - boost::mutex::scoped_lock lock(cnfg_db_instance_mutex); + libtools_scoped_lock lock(cnfg_db_instance_mutex); if(NULL == instance) { @@ -89,7 +110,7 @@ LTE_fdd_enb_cnfg_db* LTE_fdd_enb_cnfg_db::get_instance(void) } void LTE_fdd_enb_cnfg_db::cleanup(void) { - boost::mutex::scoped_lock lock(cnfg_db_instance_mutex); + libtools_scoped_lock lock(cnfg_db_instance_mutex); if(NULL != instance) { @@ -108,6 +129,8 @@ LTE_fdd_enb_cnfg_db::LTE_fdd_enb_cnfg_db() var_map_int64[LTE_FDD_ENB_PARAM_FREQ_BAND] = 0; var_map_int64[LTE_FDD_ENB_PARAM_DL_EARFCN] = liblte_interface_first_dl_earfcn[0]; var_map_int64[LTE_FDD_ENB_PARAM_UL_EARFCN] = liblte_interface_get_corresponding_ul_earfcn(liblte_interface_first_dl_earfcn[0]); + var_map_int64[LTE_FDD_ENB_PARAM_DL_CENTER_FREQ] = liblte_interface_dl_earfcn_to_frequency(liblte_interface_first_dl_earfcn[0]); + var_map_int64[LTE_FDD_ENB_PARAM_UL_CENTER_FREQ] = liblte_interface_ul_earfcn_to_frequency(liblte_interface_get_corresponding_ul_earfcn(liblte_interface_first_dl_earfcn[0])); var_map_int64[LTE_FDD_ENB_PARAM_N_RB_DL] = LIBLTE_PHY_N_RB_DL_10MHZ; var_map_int64[LTE_FDD_ENB_PARAM_N_RB_UL] = LIBLTE_PHY_N_RB_UL_10MHZ; var_map_int64[LTE_FDD_ENB_PARAM_DL_BW] = LIBLTE_RRC_DL_BANDWIDTH_50; @@ -137,9 +160,18 @@ LTE_fdd_enb_cnfg_db::LTE_fdd_enb_cnfg_db() var_map_int64[LTE_FDD_ENB_PARAM_PHICH_RESOURCE] = LIBLTE_RRC_PHICH_RESOURCE_1; var_map_int64[LTE_FDD_ENB_PARAM_N_SCHED_INFO] = 1; var_map_int64[LTE_FDD_ENB_PARAM_SYSTEM_INFO_PERIODICITY] = LIBLTE_RRC_SI_PERIODICITY_RF8; + var_map_int64[LTE_FDD_ENB_PARAM_MAC_DIRECT_TO_UE] = 0; + var_map_int64[LTE_FDD_ENB_PARAM_PHY_DIRECT_TO_UE] = 0; var_map_uint32[LTE_FDD_ENB_PARAM_DEBUG_TYPE] = 0xFFFFFFFF; var_map_uint32[LTE_FDD_ENB_PARAM_DEBUG_LEVEL] = 0xFFFFFFFF; var_map_int64[LTE_FDD_ENB_PARAM_ENABLE_PCAP] = 0; + var_map_uint32[LTE_FDD_ENB_PARAM_IP_ADDR_START] = 0xC0A80102; + var_map_uint32[LTE_FDD_ENB_PARAM_DNS_ADDR] = 0xC0A80101; + var_map_int64[LTE_FDD_ENB_PARAM_USE_CNFG_FILE] = 0; + var_map_int64[LTE_FDD_ENB_PARAM_USE_USER_FILE] = 0; + var_map_int64[LTE_FDD_ENB_PARAM_TX_GAIN] = 0; + var_map_int64[LTE_FDD_ENB_PARAM_RX_GAIN] = 0; + use_cnfg_file = false; } LTE_fdd_enb_cnfg_db::~LTE_fdd_enb_cnfg_db() { @@ -151,6 +183,7 @@ LTE_fdd_enb_cnfg_db::~LTE_fdd_enb_cnfg_db() LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_cnfg_db::set_param(LTE_FDD_ENB_PARAM_ENUM param, int64 value) { + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); LTE_fdd_enb_radio *radio = LTE_fdd_enb_radio::get_instance(); std::map::iterator iter = var_map_int64.find(param); LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_INVALID_PARAM; @@ -167,7 +200,32 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_cnfg_db::set_param(LTE_FDD_ENB_PARAM_ENUM par set_param(LTE_FDD_ENB_PARAM_N_ID_1, (value - (value % 3))/3); }else if(LTE_FDD_ENB_PARAM_DL_EARFCN == param){ set_param(LTE_FDD_ENB_PARAM_UL_EARFCN, (int64)liblte_interface_get_corresponding_ul_earfcn(value)); - radio->set_earfcns(value, (int64)liblte_interface_get_corresponding_ul_earfcn(value)); + set_param(LTE_FDD_ENB_PARAM_DL_CENTER_FREQ, (int64)liblte_interface_dl_earfcn_to_frequency(value)); + set_param(LTE_FDD_ENB_PARAM_UL_CENTER_FREQ, (int64)liblte_interface_ul_earfcn_to_frequency(liblte_interface_get_corresponding_ul_earfcn(value))); + }else if(LTE_FDD_ENB_PARAM_USE_CNFG_FILE == param){ + if(value) + { + use_cnfg_file = true; + }else{ + use_cnfg_file = false; + delete_cnfg_file(); + } + }else if(LTE_FDD_ENB_PARAM_USE_USER_FILE == param){ + if(value) + { + hss->set_use_user_file(true); + }else{ + hss->set_use_user_file(false); + } + }else if(LTE_FDD_ENB_PARAM_TX_GAIN == param){ + radio->set_tx_gain(value); + }else if(LTE_FDD_ENB_PARAM_RX_GAIN == param){ + radio->set_rx_gain(value); + } + + if(use_cnfg_file) + { + write_cnfg_file(); } } @@ -214,6 +272,11 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_cnfg_db::set_param(LTE_FDD_ENB_PARAM_ENUM par set_param(LTE_FDD_ENB_PARAM_DL_BW, (int64)LIBLTE_RRC_DL_BANDWIDTH_6); } } + + if(use_cnfg_file) + { + write_cnfg_file(); + } } return(err); @@ -221,9 +284,10 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_cnfg_db::set_param(LTE_FDD_ENB_PARAM_ENUM par LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_cnfg_db::set_param(LTE_FDD_ENB_PARAM_ENUM param, std::string value) { - std::map::iterator iter = var_map_uint32.find(param); - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_INVALID_PARAM; - uint32 i; + std::map::iterator iter = var_map_uint32.find(param); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_INVALID_PARAM; + uint32 i; + const char *v_str = value.c_str(); if(var_map_uint32.end() != iter) { @@ -231,9 +295,23 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_cnfg_db::set_param(LTE_FDD_ENB_PARAM_ENUM par for(i=0; i= '0' && + v_str[i] <= '9') + { + (*iter).second |= (v_str[i] & 0x0F); + }else if(v_str[i] >= 'A' && + v_str[i] <= 'F'){ + (*iter).second |= ((v_str[i]-'A')+0xA) & 0x0F; + }else{ + (*iter).second |= ((v_str[i]-'a')+0xA) & 0x0F; + } } err = LTE_FDD_ENB_ERROR_NONE; + + if(use_cnfg_file) + { + write_cnfg_file(); + } } return(err); @@ -248,6 +326,11 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_cnfg_db::set_param(LTE_FDD_ENB_PARAM_ENUM par { (*iter).second = value; err = LTE_FDD_ENB_ERROR_NONE; + + if(use_cnfg_file) + { + write_cnfg_file(); + } } return(err); @@ -286,16 +369,32 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_cnfg_db::get_param(LTE_FDD_ENB_PARAM_ENUM pa std::map::iterator iter = var_map_uint32.find(param); LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_INVALID_PARAM; uint32 i; + uint32 hex_val; if(var_map_uint32.end() != iter) { try { - for(i=0; i<8; i++) + if(LTE_FDD_ENB_PARAM_IP_ADDR_START == param || + LTE_FDD_ENB_PARAM_DNS_ADDR == param) { - if((((*iter).second >> (7-i)*4) & 0x0F) != 0xF) + for(i=0; i<8; i++) { - value += boost::lexical_cast(((*iter).second >> (7-i)*4) & 0x0F); + hex_val = ((*iter).second >> (7-i)*4) & 0x0F; + if(hex_val < 0xA) + { + value += (char)(hex_val + '0'); + }else{ + value += (char)((hex_val-0xA) + 'A'); + } + } + }else{ + for(i=0; i<8; i++) + { + if((((*iter).second >> (7-i)*4) & 0x0F) != 0xF) + { + value += to_string(((*iter).second >> (7-i)*4) & 0x0F); + } } } err = LTE_FDD_ENB_ERROR_NONE; @@ -324,14 +423,13 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_cnfg_db::get_param(LTE_FDD_ENB_PARAM_ENUM pa /******************************/ /* MIB/SIB Construction */ /******************************/ -void LTE_fdd_enb_cnfg_db::construct_sys_info(void) +void LTE_fdd_enb_cnfg_db::construct_sys_info(LTE_fdd_enb_pdcp *pdcp, + LTE_fdd_enb_mme *mme) { LTE_fdd_enb_phy *phy = LTE_fdd_enb_phy::get_instance(); LTE_fdd_enb_mac *mac = LTE_fdd_enb_mac::get_instance(); LTE_fdd_enb_rlc *rlc = LTE_fdd_enb_rlc::get_instance(); - LTE_fdd_enb_pdcp *pdcp = LTE_fdd_enb_pdcp::get_instance(); LTE_fdd_enb_rrc *rrc = LTE_fdd_enb_rrc::get_instance(); - LTE_fdd_enb_mme *mme = LTE_fdd_enb_mme::get_instance(); std::map::iterator double_iter; std::map::iterator int64_iter; std::map::iterator uint32_iter; @@ -398,8 +496,12 @@ void LTE_fdd_enb_cnfg_db::construct_sys_info(void) } // Initialize the scheduling info - sys_info.sib1.N_sched_info = 1; - sys_info.sib1.sched_info[0].N_sib_mapping_info = 0; + sys_info.sib1.N_sched_info = 1; + for(i=0; i 0) @@ -449,18 +551,39 @@ void LTE_fdd_enb_cnfg_db::construct_sys_info(void) if(var_map_uint32.end() != uint32_iter) { sys_info.sib1.plmn_id[0].id.mcc = ((*uint32_iter).second) & 0xFFFF; + sys_info.mcc = 0; + for(i=0; i<3; i++) + { + sys_info.mcc *= 10; + sys_info.mcc += (((*uint32_iter).second) >> (2-i)*4) & 0xF; + } } uint32_iter = var_map_uint32.find(LTE_FDD_ENB_PARAM_MNC); if(var_map_uint32.end() != uint32_iter) { sys_info.sib1.plmn_id[0].id.mnc = ((*uint32_iter).second) & 0xFFFF; + sys_info.mnc = 0; + if(((((*uint32_iter).second) >> 8) & 0xF) == 0xF) + { + for(i=0; i<2; i++) + { + sys_info.mnc *= 10; + sys_info.mnc += (((*uint32_iter).second) >> (1-i)*4) & 0xF; + } + }else{ + for(i=0; i<3; i++) + { + sys_info.mnc *= 10; + sys_info.mnc += (((*uint32_iter).second) >> (2-i)*4) & 0xF; + } + } } sys_info.sib1.plmn_id[0].resv_for_oper = LIBLTE_RRC_NOT_RESV_FOR_OPER; sys_info.sib1.cell_barred = LIBLTE_RRC_CELL_NOT_BARRED; sys_info.sib1.intra_freq_reselection = LIBLTE_RRC_INTRA_FREQ_RESELECTION_ALLOWED; sys_info.sib1.si_window_length = LIBLTE_RRC_SI_WINDOW_LENGTH_MS2; - sys_info.sib1.sf_assignment = LIBLTE_RRC_SUBFRAME_ASSIGNMENT_0; - sys_info.sib1.special_sf_patterns = LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_0; + sys_info.sib1.tdd_cnfg.sf_assignment = LIBLTE_RRC_SUBFRAME_ASSIGNMENT_0; + sys_info.sib1.tdd_cnfg.special_sf_patterns = LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_0; int64_iter = var_map_int64.find(LTE_FDD_ENB_PARAM_CELL_ID); if(var_map_int64.end() != int64_iter) { @@ -548,13 +671,13 @@ void LTE_fdd_enb_cnfg_db::construct_sys_info(void) sys_info.sib2.ue_timers_and_constants.t301 = LIBLTE_RRC_T301_MS1000; sys_info.sib2.ue_timers_and_constants.t310 = LIBLTE_RRC_T310_MS1000; sys_info.sib2.ue_timers_and_constants.n310 = LIBLTE_RRC_N310_N20; - sys_info.sib2.ue_timers_and_constants.t311 = LIBLTE_RRC_T311_MS1000; - sys_info.sib2.ue_timers_and_constants.n311 = LIBLTE_RRC_N311_N10; + sys_info.sib2.ue_timers_and_constants.t311 = LIBLTE_RRC_T311_MS30000; + sys_info.sib2.ue_timers_and_constants.n311 = LIBLTE_RRC_N311_N1; sys_info.sib2.arfcn_value_eutra.present = false; sys_info.sib2.ul_bw.present = false; sys_info.sib2.additional_spectrum_emission = 1; sys_info.sib2.mbsfn_subfr_cnfg_list_size = 0; - sys_info.sib2.time_alignment_timer = LIBLTE_RRC_TIME_ALIGNMENT_TIMER_SF500; + sys_info.sib2.time_alignment_timer = LIBLTE_RRC_TIME_ALIGNMENT_TIMER_SF10240; // SIB3 sys_info.sib3_present = false; @@ -653,7 +776,7 @@ void LTE_fdd_enb_cnfg_db::construct_sys_info(void) bcch_dlsch_msg.sibs[0].sib_type = LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1; memcpy(&bcch_dlsch_msg.sibs[0].sib, &sys_info.sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT)); liblte_rrc_pack_bcch_dlsch_msg(&bcch_dlsch_msg, - &sys_info.sib1_alloc.msg); + &sys_info.sib1_alloc.msg[0]); sys_info.sib1_alloc.pre_coder_type = LIBLTE_PHY_PRE_CODER_TYPE_TX_DIVERSITY; sys_info.sib1_alloc.mod_type = LIBLTE_PHY_MODULATION_TYPE_QPSK; sys_info.sib1_alloc.rv_idx = 0; // 36.321 section 5.3.1 @@ -704,7 +827,7 @@ void LTE_fdd_enb_cnfg_db::construct_sys_info(void) } } liblte_rrc_pack_bcch_dlsch_msg(&bcch_dlsch_msg, - &sys_info.sib_alloc[0].msg); + &sys_info.sib_alloc[0].msg[0]); sys_info.sib_alloc[0].pre_coder_type = LIBLTE_PHY_PRE_CODER_TYPE_TX_DIVERSITY; sys_info.sib_alloc[0].mod_type = LIBLTE_PHY_MODULATION_TYPE_QPSK; sys_info.sib_alloc[0].rv_idx = 0; // 36.321 section 5.3.1 @@ -747,7 +870,7 @@ void LTE_fdd_enb_cnfg_db::construct_sys_info(void) } } liblte_rrc_pack_bcch_dlsch_msg(&bcch_dlsch_msg, - &sys_info.sib_alloc[i].msg); + &sys_info.sib_alloc[i].msg[0]); sys_info.sib_alloc[i].pre_coder_type = LIBLTE_PHY_PRE_CODER_TYPE_TX_DIVERSITY; sys_info.sib_alloc[i].mod_type = LIBLTE_PHY_MODULATION_TYPE_QPSK; sys_info.sib_alloc[i].rv_idx = 0; // 36.321 section 5.3.1 @@ -797,8 +920,25 @@ void LTE_fdd_enb_cnfg_db::construct_sys_info(void) { sys_info.N_sc_rb_ul = (*int64_iter).second; } - sys_info.si_periodicity_T = liblte_rrc_si_periodicity_num[sys_info.sib1.sched_info[0].si_periodicity]; - sys_info.si_win_len = liblte_rrc_si_window_length_num[sys_info.sib1.si_window_length]; + int64_iter = var_map_int64.find(LTE_FDD_ENB_PARAM_SYSTEM_INFO_PERIODICITY); + if(var_map_int64.end() != int64_iter) + { + sys_info.si_periodicity_T = liblte_rrc_si_periodicity_num[(*int64_iter).second]; + } + int64_iter = var_map_int64.find(LTE_FDD_ENB_PARAM_SYSTEM_INFO_WINDOW_LENGTH); + if(var_map_int64.end() != int64_iter) + { + sys_info.si_win_len = liblte_rrc_si_window_length_num[(*int64_iter).second]; + } + + // PCAP variables + sys_info.mib_pcap_sent = false; + sys_info.sib1_pcap_sent = false; + sys_info.sib_pcap_sent[0] = false; + sys_info.sib_pcap_sent[1] = false; + sys_info.sib_pcap_sent[2] = false; + sys_info.sib_pcap_sent[3] = false; + sys_info.continuous_sib_pcap = false; // Update all layers phy->update_sys_info(); @@ -812,3 +952,160 @@ void LTE_fdd_enb_cnfg_db::get_sys_info(LTE_FDD_ENB_SYS_INFO_STRUCT &_sys_info) { memcpy(&_sys_info, &sys_info, sizeof(sys_info)); } + +/*********************/ +/* Config File */ +/*********************/ +void LTE_fdd_enb_cnfg_db::read_cnfg_file(void) +{ + LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + std::string line_str; + FILE *cnfg_file = NULL; + int64 ucf = 1; + char str[LTE_FDD_ENB_MAX_LINE_SIZE]; + + cnfg_file = fopen("/tmp/LTE_fdd_enodeb.cnfg_db", "r"); + + if(NULL != cnfg_file) + { + while(NULL != fgets(str, LTE_FDD_ENB_MAX_LINE_SIZE, cnfg_file)) + { + line_str = str; + interface->handle_write(line_str.substr(0, line_str.length()-1)); + } + set_param(LTE_FDD_ENB_PARAM_USE_CNFG_FILE, ucf); + fclose(cnfg_file); + } +} +void LTE_fdd_enb_cnfg_db::write_cnfg_file(void) +{ + std::map::iterator iter_d; + std::map::iterator iter_i64; + std::map::iterator iter_u32; + FILE *cnfg_file = NULL; + uint32 i; + + cnfg_file = fopen("/tmp/LTE_fdd_enodeb.cnfg_db", "w"); + + if(NULL != cnfg_file) + { + iter_d = var_map_double.find(LTE_FDD_ENB_PARAM_BANDWIDTH); + fprintf(cnfg_file, "%s %f\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_BANDWIDTH], (*iter_d).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_FREQ_BAND); + fprintf(cnfg_file, "%s %s\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_FREQ_BAND], liblte_interface_band_text[(*iter_i64).second]); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_DL_EARFCN); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DL_EARFCN], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_N_ANT); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_N_ANT], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_N_ID_CELL); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_N_ID_CELL], (*iter_i64).second); + iter_u32 = var_map_uint32.find(LTE_FDD_ENB_PARAM_MCC); + fprintf(cnfg_file, "%s %03X\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_MCC], (*iter_u32).second & 0xFFF); + iter_u32 = var_map_uint32.find(LTE_FDD_ENB_PARAM_MNC); + if(((*iter_u32).second & 0xF00) == 0xF00) + { + fprintf(cnfg_file, "%s %02X\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_MNC], (*iter_u32).second & 0xFF); + }else{ + fprintf(cnfg_file, "%s %03X\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_MNC], (*iter_u32).second & 0xFFF); + } + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_CELL_ID); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_CELL_ID], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_TRACKING_AREA_CODE); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_TRACKING_AREA_CODE], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_Q_RX_LEV_MIN); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_Q_RX_LEV_MIN], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_P0_NOMINAL_PUSCH); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_P0_NOMINAL_PUSCH], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_P0_NOMINAL_PUCCH); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_P0_NOMINAL_PUCCH], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_SIB3_PRESENT); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB3_PRESENT], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_Q_HYST); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_Q_HYST], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_SIB4_PRESENT); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB4_PRESENT], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_SIB5_PRESENT); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB5_PRESENT], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_SIB6_PRESENT); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB6_PRESENT], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_SIB7_PRESENT); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB7_PRESENT], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_SIB8_PRESENT); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB8_PRESENT], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_SEARCH_WIN_SIZE); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SEARCH_WIN_SIZE], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_MAC_DIRECT_TO_UE); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_MAC_DIRECT_TO_UE], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_PHY_DIRECT_TO_UE); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_PHY_DIRECT_TO_UE], (*iter_i64).second); + iter_u32 = var_map_uint32.find(LTE_FDD_ENB_PARAM_DEBUG_TYPE); + fprintf(cnfg_file, "%s ", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DEBUG_TYPE]); + for(i=0; i<32; i++) + { + if(i < LTE_FDD_ENB_DEBUG_TYPE_N_ITEMS) + { + if((((*iter_u32).second >> i) & 0x01) == 0x01) + { + fprintf(cnfg_file, "%s ", LTE_fdd_enb_debug_type_text[i]); + } + } + } + fprintf(cnfg_file, "\n"); + iter_u32 = var_map_uint32.find(LTE_FDD_ENB_PARAM_DEBUG_LEVEL); + fprintf(cnfg_file, "%s ", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DEBUG_LEVEL]); + for(i=0; i<32; i++) + { + if(i < LTE_FDD_ENB_DEBUG_LEVEL_N_ITEMS) + { + if((((*iter_u32).second >> i) & 0x01) == 0x01) + { + fprintf(cnfg_file, "%s ", LTE_fdd_enb_debug_level_text[i]); + } + } + } + fprintf(cnfg_file, "\n"); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_ENABLE_PCAP); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_ENABLE_PCAP], (*iter_i64).second); + iter_u32 = var_map_uint32.find(LTE_FDD_ENB_PARAM_IP_ADDR_START); + fprintf(cnfg_file, "%s %08X\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_IP_ADDR_START], (*iter_u32).second); + iter_u32 = var_map_uint32.find(LTE_FDD_ENB_PARAM_DNS_ADDR); + fprintf(cnfg_file, "%s %08X\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DNS_ADDR], (*iter_u32).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_USE_USER_FILE); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_USE_USER_FILE], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_TX_GAIN); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_TX_GAIN], (*iter_i64).second); + iter_i64 = var_map_int64.find(LTE_FDD_ENB_PARAM_RX_GAIN); + fprintf(cnfg_file, "%s %lld\n", LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_RX_GAIN], (*iter_i64).second); + + fclose(cnfg_file); + } +} +void LTE_fdd_enb_cnfg_db::delete_cnfg_file(void) +{ + remove("/tmp/LTE_fdd_enodeb.cnfg_db"); +} + +/*****************/ +/* Helpers */ +/*****************/ +void LTE_fdd_enb_cnfg_db::populate_rrc_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *cnfg, + uint32 i_cqi_pmi, + uint32 i_ri, + uint32 i_sr, + uint32 n_1_p_pucch) +{ + cnfg->pdsch_cnfg_ded_present = false; + cnfg->pucch_cnfg_ded_present = false; + cnfg->pusch_cnfg_ded_present = false; + cnfg->ul_pwr_ctrl_ded_present = false; + cnfg->tpc_pdcch_cnfg_pucch_present = false; + cnfg->tpc_pdcch_cnfg_pusch_present = false; + cnfg->cqi_report_cnfg_present = false; + cnfg->srs_ul_cnfg_ded_present = false; + cnfg->antenna_info_present = false; + cnfg->sched_request_cnfg_present = true; + cnfg->sched_request_cnfg.setup_present = true; + cnfg->sched_request_cnfg.sr_pucch_resource_idx = n_1_p_pucch; + cnfg->sched_request_cnfg.sr_cnfg_idx = i_sr; + cnfg->sched_request_cnfg.dsr_trans_max = LIBLTE_RRC_DSR_TRANS_MAX_N16; +} diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_gw.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_gw.cc new file mode 100755 index 0000000..df3d3ca --- /dev/null +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_gw.cc @@ -0,0 +1,323 @@ +#line 2 "LTE_fdd_enb_gw.cc" // Make __FILE__ omit the path +/******************************************************************************* + + Copyright 2014-2017 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: LTE_fdd_enb_gw.cc + + Description: Contains all the implementations for the LTE FDD eNodeB + IP gateway. + + Revision History + ---------- ------------- -------------------------------------------- + 11/29/2014 Ben Wojtowicz Created file + 12/16/2014 Ben Wojtowicz Added ol extension to message queue. + 02/15/2015 Ben Wojtowicz Moved to new message queue. + 03/11/2015 Ben Wojtowicz Closing TUN device on stop. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t. + 02/13/2016 Ben Wojtowicz Using memcpy instead of a typed cast for + parsing the IP packet header (thanks to + Damian Jarek for finding this). + 07/03/2016 Ben Wojtowicz Setting processor affinity. + 07/29/2017 Ben Wojtowicz Moved away from singleton pattern. + +*******************************************************************************/ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "LTE_fdd_enb_gw.h" +#include "LTE_fdd_enb_user_mgr.h" +#include "LTE_fdd_enb_cnfg_db.h" +#include "libtools_scoped_lock.h" +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + GLOBAL VARIABLES +*******************************************************************************/ + + +/******************************************************************************* + CLASS IMPLEMENTATIONS +*******************************************************************************/ + +/********************************/ +/* Constructor/Destructor */ +/********************************/ +LTE_fdd_enb_gw::LTE_fdd_enb_gw() +{ + sem_init(&start_sem, 0, 1); + started = false; +} +LTE_fdd_enb_gw::~LTE_fdd_enb_gw() +{ + stop(); + sem_destroy(&start_sem); +} + +/********************/ +/* Start/Stop */ +/********************/ +bool LTE_fdd_enb_gw::is_started(void) +{ + libtools_scoped_lock lock(start_sem); + + return(started); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_gw::start(LTE_fdd_enb_msgq *from_pdcp, + LTE_fdd_enb_msgq *to_pdcp, + char *err_str, + LTE_fdd_enb_interface *iface) +{ + libtools_scoped_lock lock(start_sem); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + LTE_fdd_enb_msgq_cb pdcp_cb(<E_fdd_enb_msgq_cb_wrapper, this); + struct ifreq ifr; + int32 sock; + char dev[IFNAMSIZ] = "tun_openlte"; + uint32 ip_addr; + + if(!started) + { + interface = iface; + started = true; + + cnfg_db->get_param(LTE_FDD_ENB_PARAM_IP_ADDR_START, ip_addr); + + // Construct the TUN device + tun_fd = open("/dev/net/tun", O_RDWR); + if(0 > tun_fd) + { + err_str = strerror(errno); + started = false; + return(LTE_FDD_ENB_ERROR_CANT_START); + } + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TUN | IFF_NO_PI; + strncpy(ifr.ifr_ifrn.ifrn_name, dev, IFNAMSIZ); + if(0 > ioctl(tun_fd, TUNSETIFF, &ifr)) + { + err_str = strerror(errno); + started = false; + close(tun_fd); + return(LTE_FDD_ENB_ERROR_CANT_START); + } + + // Setup the IP address range + sock = socket(AF_INET, SOCK_DGRAM, 0); + ifr.ifr_addr.sa_family = AF_INET; + ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(ip_addr); + if(0 > ioctl(sock, SIOCSIFADDR, &ifr)) + { + err_str = strerror(errno); + started = false; + close(tun_fd); + return(LTE_FDD_ENB_ERROR_CANT_START); + } + ifr.ifr_netmask.sa_family = AF_INET; + ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); + if(0 > ioctl(sock, SIOCSIFNETMASK, &ifr)) + { + err_str = strerror(errno); + started = false; + close(tun_fd); + return(LTE_FDD_ENB_ERROR_CANT_START); + } + + // Bring up the interface + if(0 > ioctl(sock, SIOCGIFFLAGS, &ifr)) + { + err_str = strerror(errno); + started = false; + close(tun_fd); + return(LTE_FDD_ENB_ERROR_CANT_START); + } + ifr.ifr_flags |= IFF_UP | IFF_RUNNING; + if(0 > ioctl(sock, SIOCSIFFLAGS, &ifr)) + { + err_str = strerror(errno); + started = false; + close(tun_fd); + return(LTE_FDD_ENB_ERROR_CANT_START); + } + + // Setup PDCP communication + msgq_from_pdcp = from_pdcp; + msgq_to_pdcp = to_pdcp; + msgq_from_pdcp->attach_rx(pdcp_cb); + + // Setup a thread to receive packets from the TUN device + pthread_create(&rx_thread, NULL, &receive_thread, this); + } + + return(LTE_FDD_ENB_ERROR_NONE); +} +void LTE_fdd_enb_gw::stop(void) +{ + sem_wait(&start_sem); + if(started) + { + started = false; + sem_post(&start_sem); + pthread_cancel(rx_thread); + pthread_join(rx_thread, NULL); + + close(tun_fd); + }else{ + sem_post(&start_sem); + } +} + +/***********************/ +/* Communication */ +/***********************/ +void LTE_fdd_enb_gw::handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) +{ + switch(msg.type) + { + case LTE_FDD_ENB_MESSAGE_TYPE_GW_DATA_READY: + handle_gw_data(&msg.msg.gw_data_ready); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_GW, + __FILE__, + __LINE__, + "Received invalid PDCP message %s", + LTE_fdd_enb_message_type_text[msg.type]); + break; + } +} + +/*******************************/ +/* PDCP Message Handlers */ +/*******************************/ +void LTE_fdd_enb_gw::handle_gw_data(LTE_FDD_ENB_GW_DATA_READY_MSG_STRUCT *gw_data) +{ + LIBLTE_BYTE_MSG_STRUCT *msg; + + if(LTE_FDD_ENB_ERROR_NONE == gw_data->rb->get_next_gw_data_msg(&msg)) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_GW, + __FILE__, + __LINE__, + msg, + "Received GW data message for RNTI=%u and RB=%s", + gw_data->user->get_c_rnti(), + LTE_fdd_enb_rb_text[gw_data->rb->get_rb_id()]); + interface->send_ip_pcap_msg(msg->msg, msg->N_bytes); + + if(msg->N_bytes != write(tun_fd, msg->msg, msg->N_bytes)) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_GW, + __FILE__, + __LINE__, + "Write failure"); + } + + // Delete the message + gw_data->rb->delete_next_gw_data_msg(); + } +} + +/********************/ +/* GW Receive */ +/********************/ +void* LTE_fdd_enb_gw::receive_thread(void *inputs) +{ + LTE_fdd_enb_gw *gw = (LTE_fdd_enb_gw *)inputs; + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + LTE_FDD_ENB_PDCP_DATA_SDU_READY_MSG_STRUCT pdcp_data_sdu; + LIBLTE_BYTE_MSG_STRUCT msg; + struct iphdr ip_pkt; + cpu_set_t af_mask; + uint32 idx = 0; + int32 N_bytes; + + // Set affinity to not the last core (last core is for PHY/Radio) + pthread_getaffinity_np(gw->rx_thread, sizeof(af_mask), &af_mask); + CPU_CLR(sysconf(_SC_NPROCESSORS_ONLN)-1, &af_mask); + pthread_setaffinity_np(gw->rx_thread, sizeof(af_mask), &af_mask); + + while(gw->is_started()) + { + N_bytes = read(gw->tun_fd, &msg.msg[idx], LIBLTE_MAX_MSG_SIZE); + + if(N_bytes > 0) + { + msg.N_bytes = idx + N_bytes; + memcpy(&ip_pkt, msg.msg, sizeof(iphdr)); + + // Check if entire packet was received + if(ntohs(ip_pkt.tot_len) == msg.N_bytes) + { + // Find user and rb + if(LTE_FDD_ENB_ERROR_NONE == user_mgr->find_user(ntohl(ip_pkt.daddr), &pdcp_data_sdu.user) && + LTE_FDD_ENB_ERROR_NONE == pdcp_data_sdu.user->get_drb(LTE_FDD_ENB_RB_DRB1, &pdcp_data_sdu.rb)) + { + gw->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_GW, + __FILE__, + __LINE__, + &msg, + "Received IP packet for RNTI=%u and RB=%s", + pdcp_data_sdu.user->get_c_rnti(), + LTE_fdd_enb_rb_text[pdcp_data_sdu.rb->get_rb_id()]); + gw->interface->send_ip_pcap_msg(msg.msg, msg.N_bytes); + + // Send message to PDCP + pdcp_data_sdu.rb->queue_pdcp_data_sdu(&msg); + gw->msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_DATA_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_data_sdu, + sizeof(LTE_FDD_ENB_PDCP_DATA_SDU_READY_MSG_STRUCT)); + } + + idx = 0; + }else{ + idx = N_bytes; + } + }else{ + // Something bad has happened + break; + } + } + + return(NULL); +} diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_hss.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_hss.cc old mode 100644 new mode 100755 index 2856320..602fc27 --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_hss.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_hss.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_hss.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2014 Ben Wojtowicz + Copyright 2014-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -26,6 +26,19 @@ Revision History ---------- ------------- -------------------------------------------- 06/15/2014 Ben Wojtowicz Created file + 08/03/2014 Ben Wojtowicz Added authentication vector support. + 09/03/2014 Ben Wojtowicz Added sequence number resynch and key + generation. + 11/01/2014 Ben Wojtowicz Added user file support. + 11/29/2014 Ben Wojtowicz Added support for regenerating eNodeB + security data. + 07/25/2015 Ben Wojtowicz Moved away from using boost::lexical_cast + in del_user. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t. + 07/03/2016 Ben Wojtowicz Fixed a bug in print_all_users. Thanks to + Sultan Qasim Khan for finding this. + 07/29/2017 Ben Wojtowicz Using the latest tools library. *******************************************************************************/ @@ -34,7 +47,10 @@ *******************************************************************************/ #include "LTE_fdd_enb_hss.h" -#include +#include "LTE_fdd_enb_cnfg_db.h" +#include "liblte_security.h" +#include "libtools_scoped_lock.h" +#include "libtools_helpers.h" /******************************************************************************* DEFINES @@ -50,8 +66,8 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_enb_hss* LTE_fdd_enb_hss::instance = NULL; -boost::mutex hss_instance_mutex; +LTE_fdd_enb_hss* LTE_fdd_enb_hss::instance = NULL; +static pthread_mutex_t hss_instance_mutex = PTHREAD_MUTEX_INITIALIZER; /******************************************************************************* CLASS IMPLEMENTATIONS @@ -62,7 +78,7 @@ boost::mutex hss_instance_mutex; /*******************/ LTE_fdd_enb_hss* LTE_fdd_enb_hss::get_instance(void) { - boost::mutex::scoped_lock lock(hss_instance_mutex); + libtools_scoped_lock lock(hss_instance_mutex); if(NULL == instance) { @@ -73,7 +89,7 @@ LTE_fdd_enb_hss* LTE_fdd_enb_hss::get_instance(void) } void LTE_fdd_enb_hss::cleanup(void) { - boost::mutex::scoped_lock lock(hss_instance_mutex); + libtools_scoped_lock lock(hss_instance_mutex); if(NULL != instance) { @@ -87,47 +103,68 @@ void LTE_fdd_enb_hss::cleanup(void) /********************************/ LTE_fdd_enb_hss::LTE_fdd_enb_hss() { + sem_init(&user_sem, 0, 1); user_list.clear(); + use_user_file = false; } LTE_fdd_enb_hss::~LTE_fdd_enb_hss() { + std::list::iterator iter; + + sem_wait(&user_sem); + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + delete (*iter); + } + sem_post(&user_sem); + sem_destroy(&user_sem); } /****************************/ /* External Interface */ /****************************/ -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_hss::add_user(std::string imsi) +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_hss::add_user(std::string imsi, + std::string imei, + std::string k) { - LTE_fdd_enb_user *new_user = NULL; - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_BAD_ALLOC; - - new_user = new LTE_fdd_enb_user(imsi); - - if(NULL != new_user) + std::list::iterator iter; + LTE_FDD_ENB_HSS_USER_STRUCT *new_user = new LTE_FDD_ENB_HSS_USER_STRUCT; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_BAD_ALLOC; + + if(NULL != new_user && + 15 == imsi.length() && + 15 == imei.length() && + 32 == k.length()) { - user_mutex.lock(); - user_list.push_back(new_user); - user_mutex.unlock(); + to_number(imsi, 15, &new_user->id.imsi); + to_number(imei, 15, &new_user->id.imei); + to_number(k, 16, new_user->stored_data.k); - err = LTE_FDD_ENB_ERROR_NONE; - } + new_user->generated_data.sqn_he = 0; + new_user->generated_data.seq_he = 0; + new_user->generated_data.ind_he = 0; - return(err); -} -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_hss::find_user(std::string imsi, - LTE_fdd_enb_user **user) -{ - boost::mutex::scoped_lock lock(user_mutex); - std::list::iterator iter; - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + sem_wait(&user_sem); + err = LTE_FDD_ENB_ERROR_NONE; + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if((*iter)->id.imsi == new_user->id.imsi && + (*iter)->id.imei == new_user->id.imei) + { + err = LTE_FDD_ENB_ERROR_DUPLICATE_ENTRY; + } + } + if(LTE_FDD_ENB_ERROR_NONE == err) + { + user_list.push_back(new_user); + }else{ + delete new_user; + } + sem_post(&user_sem); - for(iter=user_list.begin(); iter!=user_list.end(); iter++) - { - if((*iter)->get_imsi() == imsi) + if(use_user_file) { - *user = (*iter); - err = LTE_FDD_ENB_ERROR_NONE; - break; + write_user_file(); } } @@ -135,14 +172,18 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_hss::find_user(std::string imsi, } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_hss::del_user(std::string imsi) { - boost::mutex::scoped_lock lock(user_mutex); - std::list::iterator iter; - LTE_fdd_enb_user *user = NULL; - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + std::list::iterator iter; + LTE_FDD_ENB_HSS_USER_STRUCT *user = NULL; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + uint64 imsi_num; + bool update_user_file = false; + to_number(imsi, 15, &imsi_num); + + sem_wait(&user_sem); for(iter=user_list.begin(); iter!=user_list.end(); iter++) { - if((*iter)->get_imsi() == imsi) + if(imsi_num == (*iter)->id.imsi) { user = (*iter); user_list.erase(iter); @@ -150,22 +191,365 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_hss::del_user(std::string imsi) err = LTE_FDD_ENB_ERROR_NONE; break; } + + update_user_file = true; + } + sem_post(&user_sem); + + if(update_user_file && + use_user_file) + { + write_user_file(); } return(err); } std::string LTE_fdd_enb_hss::print_all_users(void) { - boost::mutex::scoped_lock lock(user_mutex); - std::list::iterator iter; - std::string output; + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + std::string output; - output = boost::lexical_cast(user_list.size()); + output = to_string((uint32)user_list.size()); for(iter=user_list.begin(); iter!=user_list.end(); iter++) { output += "\n"; - output += (*iter)->get_imsi(); + output += "imsi=" + to_string((*iter)->id.imsi, 15) + " "; + output += "imei=" + to_string((*iter)->id.imei, 15) + " "; + output += "k=" + to_string((*iter)->stored_data.k, 16); } return(output); } +bool LTE_fdd_enb_hss::is_imsi_allowed(uint64 imsi) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + bool ret = false; + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if(imsi == (*iter)->id.imsi) + { + ret = true; + break; + } + } + + return(ret); +} +bool LTE_fdd_enb_hss::is_imei_allowed(uint64 imei) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + bool ret = false; + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if(imei == (*iter)->id.imei) + { + ret = true; + break; + } + } + + return(ret); +} +LTE_FDD_ENB_USER_ID_STRUCT* LTE_fdd_enb_hss::get_user_id_from_imsi(uint64 imsi) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_FDD_ENB_USER_ID_STRUCT *id = NULL; + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if(imsi == (*iter)->id.imsi) + { + id = &(*iter)->id; + } + } + + return(id); +} +LTE_FDD_ENB_USER_ID_STRUCT* LTE_fdd_enb_hss::get_user_id_from_imei(uint64 imei) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_FDD_ENB_USER_ID_STRUCT *id = NULL; + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if(imei == (*iter)->id.imei) + { + id = &(*iter)->id; + } + } + + return(id); +} +void LTE_fdd_enb_hss::generate_security_data(LTE_FDD_ENB_USER_ID_STRUCT *id, + uint16 mcc, + uint16 mnc) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + uint32 i; + uint32 rand_val; + uint8 sqn[6]; + uint8 amf[2] = {0x80, 0x00}; // 3GPP 33.102 v10.0.0 Annex H + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if(id->imei == (*iter)->id.imei && + id->imsi == (*iter)->id.imsi) + { + // Generate sqn + // From 33.102 v10.0.0 section C.3.2 + (*iter)->generated_data.seq_he = ((*iter)->generated_data.seq_he + 1) % LTE_FDD_ENB_SEQ_HE_MAX_VALUE; + (*iter)->generated_data.ind_he = ((*iter)->generated_data.ind_he + 1) % LTE_FDD_ENB_IND_HE_MAX_VALUE; + (*iter)->generated_data.sqn_he = ((*iter)->generated_data.seq_he << LTE_FDD_ENB_IND_HE_N_BITS) | (*iter)->generated_data.ind_he; + for(i=0; i<6; i++) + { + sqn[i] = ((*iter)->generated_data.sqn_he >> (5-i)*8) & 0xFF; + } + + // Generate RAND + for(i=0; i<4; i++) + { + rand_val = rand(); + (*iter)->generated_data.auth_vec.rand[i*4+0] = rand_val & 0xFF; + (*iter)->generated_data.auth_vec.rand[i*4+1] = (rand_val >> 8) & 0xFF; + (*iter)->generated_data.auth_vec.rand[i*4+2] = (rand_val >> 16) & 0xFF; + (*iter)->generated_data.auth_vec.rand[i*4+3] = (rand_val >> 24) & 0xFF; + } + + // Generate MAC, RES, CK, IK, and AK + liblte_security_milenage_f1((*iter)->stored_data.k, + (*iter)->generated_data.auth_vec.rand, + sqn, + amf, + (*iter)->generated_data.mac); + liblte_security_milenage_f2345((*iter)->stored_data.k, + (*iter)->generated_data.auth_vec.rand, + (*iter)->generated_data.auth_vec.res, + (*iter)->generated_data.auth_vec.ck, + (*iter)->generated_data.auth_vec.ik, + (*iter)->generated_data.ak); + + // Construct AUTN + for(i=0; i<6; i++) + { + (*iter)->generated_data.auth_vec.autn[i] = sqn[i] ^ (*iter)->generated_data.ak[i]; + } + for(i=0; i<2; i++) + { + (*iter)->generated_data.auth_vec.autn[6+i] = amf[i]; + } + for(i=0; i<8; i++) + { + (*iter)->generated_data.auth_vec.autn[8+i] = (*iter)->generated_data.mac[i]; + } + + // Reset NAS counts + // 3GPP 33.401 v10.0.0 section 6.5 + (*iter)->generated_data.auth_vec.nas_count_ul = 0; + (*iter)->generated_data.auth_vec.nas_count_dl = 0; + + // Generate Kasme + liblte_security_generate_k_asme((*iter)->generated_data.auth_vec.ck, + (*iter)->generated_data.auth_vec.ik, + (*iter)->generated_data.ak, + sqn, + mcc, + mnc, + (*iter)->generated_data.k_asme); + + // Generate K_nas_enc and K_nas_int + liblte_security_generate_k_nas((*iter)->generated_data.k_asme, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_EEA0, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_128_EIA2, + (*iter)->generated_data.auth_vec.k_nas_enc, + (*iter)->generated_data.auth_vec.k_nas_int); + + // Generate K_enb + liblte_security_generate_k_enb((*iter)->generated_data.k_asme, + (*iter)->generated_data.auth_vec.nas_count_ul, + (*iter)->generated_data.k_enb); + + // Generate K_rrc_enc and K_rrc_int + liblte_security_generate_k_rrc((*iter)->generated_data.k_enb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_EEA0, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_128_EIA2, + (*iter)->generated_data.auth_vec.k_rrc_enc, + (*iter)->generated_data.auth_vec.k_rrc_int); + + // Generate K_up_enc and K_up_int + liblte_security_generate_k_up((*iter)->generated_data.k_enb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_EEA0, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_128_EIA2, + (*iter)->generated_data.k_up_enc, + (*iter)->generated_data.k_up_int); + + break; + } + } +} +void LTE_fdd_enb_hss::security_resynch(LTE_FDD_ENB_USER_ID_STRUCT *id, + uint16 mcc, + uint16 mnc, + uint8 *auts) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + uint32 i; + uint8 sqn[6]; + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if(id->imei == (*iter)->id.imei && + id->imsi == (*iter)->id.imsi) + { + // Decode returned SQN and break into SEQ and IND + liblte_security_milenage_f5_star((*iter)->stored_data.k, + (*iter)->generated_data.auth_vec.rand, + (*iter)->generated_data.ak); + (*iter)->generated_data.sqn_he = 0; + for(i=0; i<6; i++) + { + sqn[i] = auts[i] ^ (*iter)->generated_data.ak[i]; + (*iter)->generated_data.sqn_he |= (uint64)sqn[i] << (5-i)*8; + } + (*iter)->generated_data.seq_he = (*iter)->generated_data.sqn_he >> LTE_FDD_ENB_IND_HE_N_BITS; + (*iter)->generated_data.ind_he = (*iter)->generated_data.sqn_he & LTE_FDD_ENB_IND_HE_MASK; + if((*iter)->generated_data.ind_he > 0) + { + (*iter)->generated_data.ind_he--; + } + + break; + } + } +} +LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT* LTE_fdd_enb_hss::regenerate_enb_security_data(LTE_FDD_ENB_USER_ID_STRUCT *id, + uint32 nas_count_ul) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT *auth_vec = NULL; + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if(id->imei == (*iter)->id.imei && + id->imsi == (*iter)->id.imsi) + { + // Generate K_enb + liblte_security_generate_k_enb((*iter)->generated_data.k_asme, + nas_count_ul, + (*iter)->generated_data.k_enb); + + // Generate K_rrc_enc and K_rrc_int + liblte_security_generate_k_rrc((*iter)->generated_data.k_enb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_EEA0, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_128_EIA2, + (*iter)->generated_data.auth_vec.k_rrc_enc, + (*iter)->generated_data.auth_vec.k_rrc_int); + + // Generate K_up_enc and K_up_int + liblte_security_generate_k_up((*iter)->generated_data.k_enb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_EEA0, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_128_EIA2, + (*iter)->generated_data.k_up_enc, + (*iter)->generated_data.k_up_int); + + auth_vec = &(*iter)->generated_data.auth_vec; + + break; + } + } + + return(auth_vec); +} +LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT* LTE_fdd_enb_hss::get_auth_vec(LTE_FDD_ENB_USER_ID_STRUCT *id) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT *auth_vec = NULL; + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if(id->imei == (*iter)->id.imei && + id->imsi == (*iter)->id.imsi) + { + auth_vec = &(*iter)->generated_data.auth_vec; + + break; + } + } + + return(auth_vec); +} + +/*******************/ +/* User File */ +/*******************/ +void LTE_fdd_enb_hss::set_use_user_file(bool uuf) +{ + use_user_file = uuf; + + if(use_user_file) + { + write_user_file(); + }else{ + delete_user_file(); + } +} +void LTE_fdd_enb_hss::read_user_file(void) +{ + LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + std::string line_str; + FILE *user_file = NULL; + int64 uuf = 1; + char str[LTE_FDD_ENB_MAX_LINE_SIZE]; + + user_file = fopen("/tmp/LTE_fdd_enodeb.user_db", "r"); + + if(NULL != user_file) + { + while(NULL != fgets(str, LTE_FDD_ENB_MAX_LINE_SIZE, user_file)) + { + line_str = str; + interface->handle_add_user(line_str.substr(0, line_str.length()-1)); + } + fclose(user_file); + use_user_file = true; + cnfg_db->set_param(LTE_FDD_ENB_PARAM_USE_USER_FILE, uuf); + } +} +void LTE_fdd_enb_hss::write_user_file(void) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + FILE *user_file = NULL; + uint32 i; + + user_file = fopen("/tmp/LTE_fdd_enodeb.user_db", "w"); + + if(NULL != user_file) + { + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + fprintf(user_file, "imsi=%015llu imei=%015llu k=", (*iter)->id.imsi, (*iter)->id.imei); + for(i=0; i<16; i++) + { + fprintf(user_file, "%02X", (*iter)->stored_data.k[i]); + } + fprintf(user_file, "\n"); + } + fclose(user_file); + } +} +void LTE_fdd_enb_hss::delete_user_file(void) +{ + remove("/tmp/LTE_fdd_enodeb.user_db"); +} diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_interface.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_interface.cc old mode 100644 new mode 100755 index f18ffd4..902732b --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_interface.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_interface.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_interface.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -33,6 +33,25 @@ 05/04/2014 Ben Wojtowicz Added PCAP support. 06/15/2014 Ben Wojtowicz Added ... support for info messages and using the latest LTE library. + 07/22/2014 Ben Wojtowicz Added clock source as a configurable + parameter. + 08/03/2014 Ben Wojtowicz Added HSS support. + 09/03/2014 Ben Wojtowicz Added read only parameters for UL EARFCN, + DL center frequency and UL center frequency. + 11/01/2014 Ben Wojtowicz Added parameters for IP address assignment, + DNS address, config file, and user file. + 11/29/2014 Ben Wojtowicz Added support for the IP gateway. + 12/16/2014 Ben Wojtowicz Added ol extension to message queues. + 02/15/2015 Ben Wojtowicz Moved to new message queue, added IP pcap + support, and added UTC time to the log port. + 03/11/2015 Ben Wojtowicz Made a common routine for formatting time. + 07/25/2015 Ben Wojtowicz Added config file support for TX/RX gains. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t. + 02/13/2016 Ben Wojtowicz Added a command to print all registered + users. + 07/29/2017 Ben Wojtowicz Added input parameters for direct IPC to a UE + and using the latest tools library. *******************************************************************************/ @@ -42,7 +61,9 @@ #include "LTE_fdd_enb_interface.h" #include "LTE_fdd_enb_cnfg_db.h" +#include "LTE_fdd_enb_user_mgr.h" #include "LTE_fdd_enb_hss.h" +#include "LTE_fdd_enb_gw.h" #include "LTE_fdd_enb_mme.h" #include "LTE_fdd_enb_rrc.h" #include "LTE_fdd_enb_pdcp.h" @@ -50,11 +71,14 @@ #include "LTE_fdd_enb_mac.h" #include "LTE_fdd_enb_phy.h" #include "LTE_fdd_enb_radio.h" +#include "LTE_fdd_enb_timer_mgr.h" #include "liblte_interface.h" +#include "libtools_scoped_lock.h" +#include "libtools_helpers.h" #include -#include -#include #include +#include +#include /******************************************************************************* DEFINES @@ -70,10 +94,10 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_enb_interface* LTE_fdd_enb_interface::instance = NULL; -boost::mutex interface_instance_mutex; -boost::mutex ctrl_connect_mutex; -boost::mutex debug_connect_mutex; +LTE_fdd_enb_interface* LTE_fdd_enb_interface::instance = NULL; +static pthread_mutex_t interface_instance_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t ctrl_connect_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t debug_connect_mutex = PTHREAD_MUTEX_INITIALIZER; bool LTE_fdd_enb_interface::ctrl_connected = false; bool LTE_fdd_enb_interface::debug_connected = false; @@ -86,7 +110,7 @@ bool LTE_fdd_enb_interface::debug_connected = false; /*******************/ LTE_fdd_enb_interface* LTE_fdd_enb_interface::get_instance(void) { - boost::mutex::scoped_lock lock(interface_instance_mutex); + libtools_scoped_lock lock(interface_instance_mutex); if(NULL == instance) { @@ -97,7 +121,7 @@ LTE_fdd_enb_interface* LTE_fdd_enb_interface::get_instance(void) } void LTE_fdd_enb_interface::cleanup(void) { - boost::mutex::scoped_lock lock(interface_instance_mutex); + libtools_scoped_lock lock(interface_instance_mutex); if(NULL != instance) { @@ -114,6 +138,8 @@ LTE_fdd_enb_interface::LTE_fdd_enb_interface() uint32 i; // Communication + sem_init(&ctrl_sem, 0, 1); + sem_init(&debug_sem, 0, 1); ctrl_socket = NULL; debug_socket = NULL; ctrl_port = LTE_FDD_ENB_DEFAULT_CTRL_PORT; @@ -122,29 +148,44 @@ LTE_fdd_enb_interface::LTE_fdd_enb_interface() debug_connected = false; // Variables - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_BANDWIDTH]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_DOUBLE, LTE_FDD_ENB_PARAM_BANDWIDTH, 0, 0, 0, 0, true, false}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_FREQ_BAND]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_FREQ_BAND, 0, 0, 0, 0, true, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DL_EARFCN]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_DL_EARFCN, 0, 0, 0, 0, true, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_N_ANT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_N_ANT, 0, 0, 0, 0, true, false}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_N_ID_CELL]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_N_ID_CELL, 0, 0, 0, 503, false, false}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_MCC]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_HEX, LTE_FDD_ENB_PARAM_MCC, 0, 0, 0, 0, true, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_MNC]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_HEX, LTE_FDD_ENB_PARAM_MNC, 0, 0, 0, 0, true, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_CELL_ID]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_CELL_ID, 0, 0, 0, 268435455, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_TRACKING_AREA_CODE]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_TRACKING_AREA_CODE, 0, 0, 0, 65535, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_Q_RX_LEV_MIN]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_Q_RX_LEV_MIN, 0, 0, -140, -44, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_P0_NOMINAL_PUSCH]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_P0_NOMINAL_PUSCH, 0, 0, -126, 24, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_P0_NOMINAL_PUCCH]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_P0_NOMINAL_PUCCH, 0, 0, -127, -96, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB3_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB3_PRESENT, 0, 0, 0, 1, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_Q_HYST]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_Q_HYST, 0, 0, 0, 0, true, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB4_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB4_PRESENT, 0, 0, 0, 1, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB5_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB5_PRESENT, 0, 0, 0, 1, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB6_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB6_PRESENT, 0, 0, 0, 1, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB7_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB7_PRESENT, 0, 0, 0, 1, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB8_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB8_PRESENT, 0, 0, 0, 1, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SEARCH_WIN_SIZE]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SEARCH_WIN_SIZE, 0, 0, 0, 15, false, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DEBUG_TYPE]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_UINT32, LTE_FDD_ENB_PARAM_DEBUG_TYPE, 0, 0, 0, 0, true, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DEBUG_LEVEL]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_UINT32, LTE_FDD_ENB_PARAM_DEBUG_LEVEL, 0, 0, 0, 0, true, true}; - var_map[lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_ENABLE_PCAP]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_ENABLE_PCAP, 0, 0, 0, 1, false, true}; + pdcp = NULL; + mme = NULL; + gw = NULL; + sem_init(&start_sem, 0, 1); + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_BANDWIDTH]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_DOUBLE, LTE_FDD_ENB_PARAM_BANDWIDTH, 0, 0, 0, 0, true, false, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_FREQ_BAND]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_FREQ_BAND, 0, 0, 0, 0, true, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DL_EARFCN]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_DL_EARFCN, 0, 0, 0, 0, true, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_UL_EARFCN]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_UL_EARFCN, 0, 0, 0, 0, false, false, true}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DL_CENTER_FREQ]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_DL_CENTER_FREQ, 0, 0, 0, 0, false, false, true}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_UL_CENTER_FREQ]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_UL_CENTER_FREQ, 0, 0, 0, 0, false, false, true}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_N_ANT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_N_ANT, 0, 0, 0, 0, true, false, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_N_ID_CELL]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_N_ID_CELL, 0, 0, 0, 503, false, false, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_MCC]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_HEX, LTE_FDD_ENB_PARAM_MCC, 0, 0, 0, 0, true, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_MNC]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_HEX, LTE_FDD_ENB_PARAM_MNC, 0, 0, 0, 0, true, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_CELL_ID]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_CELL_ID, 0, 0, 0, 268435455, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_TRACKING_AREA_CODE]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_TRACKING_AREA_CODE, 0, 0, 0, 65535, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_Q_RX_LEV_MIN]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_Q_RX_LEV_MIN, 0, 0, -140, -44, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_P0_NOMINAL_PUSCH]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_P0_NOMINAL_PUSCH, 0, 0, -126, 24, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_P0_NOMINAL_PUCCH]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_P0_NOMINAL_PUCCH, 0, 0, -127, -96, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB3_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB3_PRESENT, 0, 0, 0, 1, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_Q_HYST]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_Q_HYST, 0, 0, 0, 0, true, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB4_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB4_PRESENT, 0, 0, 0, 1, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB5_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB5_PRESENT, 0, 0, 0, 1, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB6_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB6_PRESENT, 0, 0, 0, 1, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB7_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB7_PRESENT, 0, 0, 0, 1, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SIB8_PRESENT]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SIB8_PRESENT, 0, 0, 0, 1, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SEARCH_WIN_SIZE]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_SEARCH_WIN_SIZE, 0, 0, 0, 15, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_MAC_DIRECT_TO_UE]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_MAC_DIRECT_TO_UE, 0, 0, 0, 1, false, false, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_PHY_DIRECT_TO_UE]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_PHY_DIRECT_TO_UE, 0, 0, 0, 1, false, false, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DEBUG_TYPE]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_UINT32, LTE_FDD_ENB_PARAM_DEBUG_TYPE, 0, 0, 0, 0, true, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DEBUG_LEVEL]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_UINT32, LTE_FDD_ENB_PARAM_DEBUG_LEVEL, 0, 0, 0, 0, true, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_ENABLE_PCAP]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_ENABLE_PCAP, 0, 0, 0, 1, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_IP_ADDR_START]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_HEX, LTE_FDD_ENB_PARAM_IP_ADDR_START, 0, 0, 0, 0, true, false, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_DNS_ADDR]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_HEX, LTE_FDD_ENB_PARAM_DNS_ADDR, 0, 0, 0, 0, true, false, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_USE_CNFG_FILE]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_USE_CNFG_FILE, 0, 0, 0, 1, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_USE_USER_FILE]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_USE_USER_FILE, 0, 0, 0, 1, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_TX_GAIN]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_TX_GAIN, 0, 0, 0, 100, false, true, false}; + var_map[LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_RX_GAIN]] = (LTE_FDD_ENB_VAR_STRUCT){LTE_FDD_ENB_VAR_TYPE_INT64, LTE_FDD_ENB_PARAM_RX_GAIN, 0, 0, 0, 100, false, true, false}; debug_type_mask = 0; for(i=0; i(time.tv_sec) + "."; - tmp_ss << std::setw(6) << std::setfill('0') << time.tv_usec; - tmp_msg += tmp_ss.str() + " "; + get_formatted_time(tmp_msg); + tmp_msg += " "; tmp_msg += LTE_fdd_enb_debug_type_text[type]; tmp_msg += " "; tmp_msg += LTE_fdd_enb_debug_level_text[level]; tmp_msg += " "; tmp_msg += file_name.c_str(); tmp_msg += " "; - tmp_msg += boost::lexical_cast(line); + tmp_msg += to_string(line); tmp_msg += " "; va_start(args, msg); if(-1 != vasprintf(&args_msg, msg.c_str(), args)) @@ -355,32 +397,27 @@ void LTE_fdd_enb_interface::send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ENUM type, std::string msg, ...) { - boost::mutex::scoped_lock lock(debug_connect_mutex); - std::string tmp_msg; - std::stringstream tmp_ss; - va_list args; - struct timeval time; - struct timezone time_zone; - uint32 i; - uint32 hex_val; - char *args_msg; + libtools_scoped_lock lock(debug_connect_mutex); + std::string tmp_msg; + va_list args; + uint32 i; + uint32 hex_val; + char *args_msg; if(debug_connected && (debug_type_mask & (1 << type)) && (debug_level_mask & (1 << level))) { // Format the output string - gettimeofday(&time, &time_zone); - tmp_msg = boost::lexical_cast(time.tv_sec) + "."; - tmp_ss << std::setw(6) << std::setfill('0') << time.tv_usec; - tmp_msg += tmp_ss.str() + " "; + get_formatted_time(tmp_msg); + tmp_msg += " "; tmp_msg += LTE_fdd_enb_debug_type_text[type]; tmp_msg += " "; tmp_msg += LTE_fdd_enb_debug_level_text[level]; tmp_msg += " "; tmp_msg += file_name.c_str(); tmp_msg += " "; - tmp_msg += boost::lexical_cast(line); + tmp_msg += to_string(line); tmp_msg += " "; va_start(args, msg); if(-1 != vasprintf(&args_msg, msg.c_str(), args)) @@ -433,57 +470,32 @@ void LTE_fdd_enb_interface::send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ENUM type, std::string msg, ...) { - boost::mutex::scoped_lock lock(debug_connect_mutex); - std::string tmp_msg; - std::stringstream tmp_ss; - va_list args; - struct timeval time; - struct timezone time_zone; - uint32 i; - uint32 hex_val; - char *args_msg; + libtools_scoped_lock lock(debug_connect_mutex); + std::string tmp_msg; + va_list args; + char *args_msg; if(debug_connected && (debug_type_mask & (1 << type)) && (debug_level_mask & (1 << level))) { // Format the output string - gettimeofday(&time, &time_zone); - tmp_msg = boost::lexical_cast(time.tv_sec) + "."; - tmp_ss << std::setw(6) << std::setfill('0') << time.tv_usec; - tmp_msg += tmp_ss.str() + " "; + get_formatted_time(tmp_msg); + tmp_msg += " "; tmp_msg += LTE_fdd_enb_debug_type_text[type]; tmp_msg += " "; tmp_msg += LTE_fdd_enb_debug_level_text[level]; tmp_msg += " "; tmp_msg += file_name.c_str(); tmp_msg += " "; - tmp_msg += boost::lexical_cast(line); + tmp_msg += to_string(line); tmp_msg += " "; va_start(args, msg); if(-1 != vasprintf(&args_msg, msg.c_str(), args)) { tmp_msg += args_msg; } - tmp_msg += " "; - for(i=0; iN_bytes; i++) - { - hex_val = (lte_msg->msg[i] >> 4) & 0xF; - if(hex_val < 0xA) - { - tmp_msg += (char)(hex_val + '0'); - }else{ - tmp_msg += (char)((hex_val-0xA) + 'A'); - } - hex_val = lte_msg->msg[i] & 0xF; - if(hex_val < 0xA) - { - tmp_msg += (char)(hex_val + '0'); - }else{ - tmp_msg += (char)((hex_val-0xA) + 'A'); - } - } - tmp_msg += "\n"; + tmp_msg += " " + to_string(lte_msg->msg, lte_msg->N_bytes) + "\n"; // Cleanup the variable argument string free(args_msg); @@ -491,31 +503,69 @@ void LTE_fdd_enb_interface::send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ENUM type, debug_socket->send(tmp_msg); } } -void LTE_fdd_enb_interface::open_pcap_fd(void) +void LTE_fdd_enb_interface::open_lte_pcap_fd(void) { - uint32 magic_number = 0xa1b2c3d4; - uint32 timezone = 0; - uint32 sigfigs = 0; - uint32 snap_len = (LIBLTE_MAX_MSG_SIZE/4); - uint32 dlt = 147; + uint32 magic_number = 0xa1b2c3d4; + uint32 timezone = 0; + uint32 sigfigs = 0; + uint32 snap_len = 0xFFFF; + uint32 dlt = 147; + uint32 tmp_u32; uint16 major_version = 2; uint16 minor_version = 4; - - pcap_fd = fopen("/tmp/LTE_fdd_enodeb.pcap", "w"); - - fwrite(&magic_number, sizeof(magic_number), 1, pcap_fd); - fwrite(&major_version, sizeof(major_version), 1, pcap_fd); - fwrite(&minor_version, sizeof(minor_version), 1, pcap_fd); - fwrite(&timezone, sizeof(timezone), 1, pcap_fd); - fwrite(&sigfigs, sizeof(sigfigs), 1, pcap_fd); - fwrite(&snap_len, sizeof(snap_len), 1, pcap_fd); - fwrite(&dlt, sizeof(dlt), 1, pcap_fd); + uint16 tmp_u16; + + lte_pcap_fd = fopen("/tmp/LTE_fdd_enodeb.pcap", "w"); + + tmp_u32 = htonl(magic_number); + fwrite(&tmp_u32, sizeof(tmp_u32), 1, lte_pcap_fd); + tmp_u16 = htons(major_version); + fwrite(&tmp_u16, sizeof(tmp_u16), 1, lte_pcap_fd); + tmp_u16 = htons(minor_version); + fwrite(&tmp_u16, sizeof(tmp_u16), 1, lte_pcap_fd); + tmp_u32 = htonl(timezone); + fwrite(&tmp_u32, sizeof(tmp_u32), 1, lte_pcap_fd); + tmp_u32 = htonl(sigfigs); + fwrite(&tmp_u32, sizeof(tmp_u32), 1, lte_pcap_fd); + tmp_u32 = htonl(snap_len); + fwrite(&tmp_u32, sizeof(tmp_u32), 1, lte_pcap_fd); + tmp_u32 = htonl(dlt); + fwrite(&tmp_u32, sizeof(tmp_u32), 1, lte_pcap_fd); +} +void LTE_fdd_enb_interface::open_ip_pcap_fd(void) +{ + uint32 magic_number = 0xa1b2c3d4; + uint32 timezone = 0; + uint32 sigfigs = 0; + uint32 snap_len = 0xFFFF; + uint32 dlt = 228; + uint32 tmp_u32; + uint16 major_version = 2; + uint16 minor_version = 4; + uint16 tmp_u16; + + ip_pcap_fd = fopen("/tmp/LTE_fdd_enodeb_ip.pcap", "w"); + + tmp_u32 = htonl(magic_number); + fwrite(&tmp_u32, sizeof(tmp_u32), 1, ip_pcap_fd); + tmp_u16 = htons(major_version); + fwrite(&tmp_u16, sizeof(tmp_u16), 1, ip_pcap_fd); + tmp_u16 = htons(minor_version); + fwrite(&tmp_u16, sizeof(tmp_u16), 1, ip_pcap_fd); + tmp_u32 = htonl(timezone); + fwrite(&tmp_u32, sizeof(tmp_u32), 1, ip_pcap_fd); + tmp_u32 = htonl(sigfigs); + fwrite(&tmp_u32, sizeof(tmp_u32), 1, ip_pcap_fd); + tmp_u32 = htonl(snap_len); + fwrite(&tmp_u32, sizeof(tmp_u32), 1, ip_pcap_fd); + tmp_u32 = htonl(dlt); + fwrite(&tmp_u32, sizeof(tmp_u32), 1, ip_pcap_fd); } -void LTE_fdd_enb_interface::send_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_ENUM dir, - uint32 rnti, - uint32 current_tti, - uint8 *msg, - uint32 N_bits) +void LTE_fdd_enb_interface::send_lte_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_ENUM dir, + uint32 rnti, + uint32 current_tti, + uint8 *msg, + uint32 N_bits) { LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); struct timeval time; @@ -524,9 +574,10 @@ void LTE_fdd_enb_interface::send_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_ENUM dir, uint32 i; uint32 idx; uint32 length; - uint16 tmp; + uint32 tmp_u32; + uint16 tmp_u16; uint8 pcap_c_hdr[15]; - uint8 pcap_msg[LIBLTE_MAX_MSG_SIZE/8]; + uint8 pcap_msg[LIBLTE_MAX_MSG_SIZE*2]; cnfg_db->get_param(LTE_FDD_ENB_PARAM_ENABLE_PCAP, enable_pcap); @@ -560,18 +611,18 @@ void LTE_fdd_enb_interface::send_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_ENUM dir, // RNTI Tag and RNTI pcap_c_hdr[3] = 2; - tmp = htons((uint16)rnti); - memcpy(&pcap_c_hdr[4], &tmp, sizeof(uint16)); + tmp_u16 = htons((uint16)rnti); + memcpy(&pcap_c_hdr[4], &tmp_u16, sizeof(uint16)); // UEID Tag and UEID pcap_c_hdr[6] = 3; - pcap_c_hdr[7] = 0; - pcap_c_hdr[8] = 0; + tmp_u16 = htons((uint16)rnti); + memcpy(&pcap_c_hdr[7], &tmp_u16, sizeof(uint16)); // SUBFN Tag and SUBFN pcap_c_hdr[9] = 4; - tmp = htons((uint16)(current_tti%10)); - memcpy(&pcap_c_hdr[10], &tmp, sizeof(uint16)); + tmp_u16 = htons((uint16)(current_tti%10)); + memcpy(&pcap_c_hdr[10], &tmp_u16, sizeof(uint16)); // CRC Status Tag and CRC Status pcap_c_hdr[12] = 7; @@ -598,12 +649,42 @@ void LTE_fdd_enb_interface::send_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_ENUM dir, length = 15 + idx; // Write Data - fwrite(&time.tv_sec, sizeof(uint32), 1, pcap_fd); - fwrite(&time.tv_usec, sizeof(uint32), 1, pcap_fd); - fwrite(&length, sizeof(uint32), 1, pcap_fd); - fwrite(&length, sizeof(uint32), 1, pcap_fd); - fwrite(pcap_c_hdr, sizeof(uint8), 15, pcap_fd); - fwrite(pcap_msg, sizeof(uint8), idx, pcap_fd); + tmp_u32 = htonl(time.tv_sec); + fwrite(&tmp_u32, sizeof(uint32), 1, lte_pcap_fd); + tmp_u32 = htonl(time.tv_usec); + fwrite(&tmp_u32, sizeof(uint32), 1, lte_pcap_fd); + tmp_u32 = htonl(length); + fwrite(&tmp_u32, sizeof(uint32), 1, lte_pcap_fd); + fwrite(&tmp_u32, sizeof(uint32), 1, lte_pcap_fd); + fwrite(pcap_c_hdr, sizeof(uint8), 15, lte_pcap_fd); + fwrite(pcap_msg, sizeof(uint8), idx, lte_pcap_fd); + } +} +void LTE_fdd_enb_interface::send_ip_pcap_msg(uint8 *msg, + uint32 N_bytes) +{ + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + struct timeval time; + struct timezone time_zone; + int64 enable_pcap; + uint32 tmp; + + cnfg_db->get_param(LTE_FDD_ENB_PARAM_ENABLE_PCAP, enable_pcap); + + if(enable_pcap) + { + // Get approximate time stamp + gettimeofday(&time, &time_zone); + + // Write Data + tmp = htonl(time.tv_sec); + fwrite(&tmp, sizeof(uint32), 1, ip_pcap_fd); + tmp = htonl(time.tv_usec); + fwrite(&tmp, sizeof(uint32), 1, ip_pcap_fd); + tmp = htonl(N_bytes); + fwrite(&tmp, sizeof(uint32), 1, ip_pcap_fd); + fwrite(&tmp, sizeof(uint32), 1, ip_pcap_fd); + fwrite(msg, sizeof(uint8), N_bytes, ip_pcap_fd); } } void LTE_fdd_enb_interface::handle_ctrl_msg(std::string msg) @@ -616,7 +697,7 @@ void LTE_fdd_enb_interface::handle_ctrl_msg(std::string msg) { interface->handle_read(msg.substr(msg.find("read")+sizeof("read"), std::string::npos)); }else if(std::string::npos != msg.find("write")){ - interface->handle_write(msg.substr(msg.find("write")+sizeof("write"), std::string::npos)); + interface->send_ctrl_error_msg(interface->handle_write(msg.substr(msg.find("write")+sizeof("write"), std::string::npos)), ""); }else if(std::string::npos != msg.find("start")){ interface->handle_start(); }else if(std::string::npos != msg.find("stop")){ @@ -630,19 +711,32 @@ void LTE_fdd_enb_interface::handle_ctrl_msg(std::string msg) interface->send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, ""); } }else if(std::string::npos != msg.find("construct_si")){ - cnfg_db->construct_sys_info(); - interface->send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, ""); + if(interface->app_is_started()) + { + cnfg_db->construct_sys_info(interface->pdcp, interface->mme); + interface->send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, ""); + }else{ + interface->send_ctrl_error_msg(LTE_FDD_ENB_ERROR_ALREADY_STOPPED, ""); + } }else if(std::string::npos != msg.find("help")){ interface->handle_help(); + }else if(std::string::npos != msg.find("add_user")){ + interface->handle_add_user(msg.substr(msg.find("add_user")+sizeof("add_user"), std::string::npos)); + }else if(std::string::npos != msg.find("del_user")){ + interface->handle_del_user(msg.substr(msg.find("del_user")+sizeof("del_user"), std::string::npos)); + }else if(std::string::npos != msg.find("print_users")){ + interface->handle_print_users(); + }else if(std::string::npos != msg.find("print_registered_users")){ + interface->handle_print_registered_users(); }else{ interface->send_ctrl_error_msg(LTE_FDD_ENB_ERROR_INVALID_COMMAND, ""); } } void LTE_fdd_enb_interface::handle_ctrl_connect(void) { - ctrl_connect_mutex.lock(); + pthread_mutex_lock(&ctrl_connect_mutex); LTE_fdd_enb_interface::ctrl_connected = true; - ctrl_connect_mutex.unlock(); + pthread_mutex_unlock(&ctrl_connect_mutex); LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); @@ -651,7 +745,7 @@ void LTE_fdd_enb_interface::handle_ctrl_connect(void) } void LTE_fdd_enb_interface::handle_ctrl_disconnect(void) { - boost::mutex::scoped_lock lock(ctrl_connect_mutex); + libtools_scoped_lock lock(ctrl_connect_mutex); LTE_fdd_enb_interface::ctrl_connected = false; } @@ -673,9 +767,9 @@ void LTE_fdd_enb_interface::handle_debug_msg(std::string msg) } void LTE_fdd_enb_interface::handle_debug_connect(void) { - debug_connect_mutex.lock(); + pthread_mutex_lock(&debug_connect_mutex); LTE_fdd_enb_interface::debug_connected = true; - debug_connect_mutex.unlock(); + pthread_mutex_unlock(&debug_connect_mutex); LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); @@ -687,7 +781,7 @@ void LTE_fdd_enb_interface::handle_debug_connect(void) } void LTE_fdd_enb_interface::handle_debug_disconnect(void) { - boost::mutex::scoped_lock lock(debug_connect_mutex); + libtools_scoped_lock lock(debug_connect_mutex); LTE_fdd_enb_interface::debug_connected = false; } @@ -714,90 +808,83 @@ void LTE_fdd_enb_interface::handle_read(std::string msg) uint32 u_value; uint32 i; - try + if(var_map.end() != iter) { - if(var_map.end() != iter) + // Handle all system parameters + switch((*iter).second.var_type) { - // Handle all system parameters - switch((*iter).second.var_type) + case LTE_FDD_ENB_VAR_TYPE_DOUBLE: + cnfg_db->get_param((*iter).second.param, d_value); + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, to_string(d_value)); + break; + case LTE_FDD_ENB_VAR_TYPE_INT64: + cnfg_db->get_param((*iter).second.param, i_value); + if(LTE_FDD_ENB_PARAM_FREQ_BAND == (*iter).second.param) { - case LTE_FDD_ENB_VAR_TYPE_DOUBLE: - cnfg_db->get_param((*iter).second.param, d_value); - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, boost::lexical_cast(d_value)); - break; - case LTE_FDD_ENB_VAR_TYPE_INT64: - cnfg_db->get_param((*iter).second.param, i_value); - if(LTE_FDD_ENB_PARAM_FREQ_BAND == (*iter).second.param) - { - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, liblte_interface_band_text[i_value]); - }else{ - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, boost::lexical_cast(i_value)); - } - break; - case LTE_FDD_ENB_VAR_TYPE_HEX: - cnfg_db->get_param((*iter).second.param, s_value); - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, s_value); - break; - case LTE_FDD_ENB_VAR_TYPE_UINT32: - cnfg_db->get_param((*iter).second.param, u_value); - if(LTE_FDD_ENB_PARAM_DEBUG_TYPE == (*iter).second.param) + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, liblte_interface_band_text[i_value]); + }else{ + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, to_string(i_value)); + } + break; + case LTE_FDD_ENB_VAR_TYPE_HEX: + cnfg_db->get_param((*iter).second.param, s_value); + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, s_value); + break; + case LTE_FDD_ENB_VAR_TYPE_UINT32: + cnfg_db->get_param((*iter).second.param, u_value); + if(LTE_FDD_ENB_PARAM_DEBUG_TYPE == (*iter).second.param) + { + for(i=0; i(u_value)); } - break; - default: - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_INVALID_PARAM, ""); - break; + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, tmp_str); + }else{ + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, to_string(u_value)); } - }else{ - // Handle all radio parameters - if(std::string::npos != msg.find(lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_AVAILABLE_RADIOS])) + break; + default: + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_INVALID_PARAM, ""); + break; + } + }else{ + // Handle all radio parameters + if(std::string::npos != msg.find(LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_AVAILABLE_RADIOS])) + { + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, to_string(avail_radios.num_radios)); + for(i=0; i(avail_radios.num_radios)); - for(i=0; i(i); - tmp_str += ":"; - tmp_str += avail_radios.radio[i].name; - send_ctrl_msg(tmp_str); - } - }else if(std::string::npos != msg.find(lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SELECTED_RADIO_NAME])){ - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, selected_radio.name); - }else if(std::string::npos != msg.find(lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SELECTED_RADIO_IDX])){ - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, boost::lexical_cast(radio->get_selected_radio_idx())); - }else if(std::string::npos != msg.find(lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_TX_GAIN])){ - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, boost::lexical_cast(radio->get_tx_gain())); - }else if(std::string::npos != msg.find(lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_RX_GAIN])){ - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, boost::lexical_cast(radio->get_rx_gain())); - }else{ - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_INVALID_PARAM, ""); + tmp_str = to_string(i); + tmp_str += ":"; + tmp_str += avail_radios.radio[i].name; + send_ctrl_msg(tmp_str); } + }else if(std::string::npos != msg.find(LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SELECTED_RADIO_NAME])){ + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, selected_radio.name); + }else if(std::string::npos != msg.find(LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SELECTED_RADIO_IDX])){ + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, to_string(radio->get_selected_radio_idx())); + }else if(std::string::npos != msg.find(LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_CLOCK_SOURCE])){ + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, radio->get_clock_source()); + }else{ + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_INVALID_PARAM, ""); } - }catch(...){ - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_EXCEPTION, ""); } } -void LTE_fdd_enb_interface::handle_write(std::string msg) +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_interface::handle_write(std::string msg) { LTE_fdd_enb_radio *radio = LTE_fdd_enb_radio::get_instance(); std::map::iterator iter = var_map.find(msg.substr(0, msg.find(" "))); @@ -811,198 +898,175 @@ void LTE_fdd_enb_interface::handle_write(std::string msg) { if(var_map.end() != iter) { - // Handle all system parameters - switch((*iter).second.var_type) + if(!(*iter).second.read_only) { - case LTE_FDD_ENB_VAR_TYPE_DOUBLE: - d_value = boost::lexical_cast(msg.substr(msg.find(" ")+1, std::string::npos)); - err = write_value(&(*iter).second, d_value); - break; - case LTE_FDD_ENB_VAR_TYPE_INT64: - i_value = boost::lexical_cast(msg.substr(msg.find(" ")+1, std::string::npos)); - err = write_value(&(*iter).second, i_value); - break; - case LTE_FDD_ENB_VAR_TYPE_HEX: - err = write_value(&(*iter).second, msg.substr(msg.find(" ")+1, std::string::npos)); - break; - case LTE_FDD_ENB_VAR_TYPE_UINT32: - if(LTE_FDD_ENB_PARAM_DEBUG_TYPE == (*iter).second.param) + // Handle all system parameters + switch((*iter).second.var_type) { - u_value = 0; - for(i=0; i(msg.substr(msg.find(" ")+1, std::string::npos)); + err = write_value(&(*iter).second, d_value); + break; + case LTE_FDD_ENB_VAR_TYPE_INT64: + i_value = boost::lexical_cast(msg.substr(msg.find(" ")+1, std::string::npos)); + err = write_value(&(*iter).second, i_value); + break; + case LTE_FDD_ENB_VAR_TYPE_HEX: + err = write_value(&(*iter).second, msg.substr(msg.find(" ")+1, std::string::npos)); + break; + case LTE_FDD_ENB_VAR_TYPE_UINT32: + if(LTE_FDD_ENB_PARAM_DEBUG_TYPE == (*iter).second.param) { - if(std::string::npos != msg.substr(msg.find(" ")+1, std::string::npos).find(LTE_fdd_enb_debug_type_text[i])) + u_value = 0; + for(i=0; i(msg.substr(msg.find(" ")+1, std::string::npos)); + err = write_value(&(*iter).second, u_value); } - debug_level_mask = u_value; - err = write_value(&(*iter).second, u_value); - }else{ - u_value = boost::lexical_cast(msg.substr(msg.find(" ")+1, std::string::npos)); - err = write_value(&(*iter).second, u_value); + break; + default: + err = LTE_FDD_ENB_ERROR_INVALID_PARAM; + break; } - break; - default: - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_INVALID_PARAM, ""); - break; - } - - if(LTE_FDD_ENB_ERROR_NONE == err) - { - send_ctrl_error_msg(err, ""); }else{ - send_ctrl_error_msg(err, ""); + err = LTE_FDD_ENB_ERROR_READ_ONLY; } }else{ // Handle all radio parameters - if(std::string::npos != msg.find(lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SELECTED_RADIO_IDX])) + if(std::string::npos != msg.find(LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SELECTED_RADIO_IDX])) { u_value = boost::lexical_cast(msg.substr(msg.find(" ")+1, std::string::npos)); - send_ctrl_error_msg(radio->set_selected_radio_idx(u_value), ""); - }else if(std::string::npos != msg.find(lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_TX_GAIN])){ - u_value = boost::lexical_cast(msg.substr(msg.find(" ")+1, std::string::npos)); - send_ctrl_error_msg(radio->set_tx_gain(u_value), ""); - }else if(std::string::npos != msg.find(lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_RX_GAIN])){ - u_value = boost::lexical_cast(msg.substr(msg.find(" ")+1, std::string::npos)); - send_ctrl_error_msg(radio->set_rx_gain(u_value), ""); + err = radio->set_selected_radio_idx(u_value); + }else if(std::string::npos != msg.find(LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_CLOCK_SOURCE])){ + err = radio->set_clock_source(msg.substr(msg.find(" ")+1, std::string::npos)); }else{ - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_INVALID_PARAM, ""); + err = LTE_FDD_ENB_ERROR_INVALID_PARAM; } } }catch(...){ - send_ctrl_error_msg(LTE_FDD_ENB_ERROR_EXCEPTION, ""); + err = LTE_FDD_ENB_ERROR_EXCEPTION; } + + return(err); } void LTE_fdd_enb_interface::handle_start(void) { - boost::mutex::scoped_lock lock(start_mutex); - LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); - LTE_fdd_enb_mac *mac = LTE_fdd_enb_mac::get_instance(); - LTE_fdd_enb_rlc *rlc = LTE_fdd_enb_rlc::get_instance(); - LTE_fdd_enb_pdcp *pdcp = LTE_fdd_enb_pdcp::get_instance(); - LTE_fdd_enb_rrc *rrc = LTE_fdd_enb_rrc::get_instance(); - LTE_fdd_enb_mme *mme = LTE_fdd_enb_mme::get_instance(); - LTE_fdd_enb_phy *phy = LTE_fdd_enb_phy::get_instance(); - LTE_fdd_enb_radio *radio = LTE_fdd_enb_radio::get_instance(); - LTE_FDD_ENB_ERROR_ENUM err; - + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + LTE_fdd_enb_mac *mac = LTE_fdd_enb_mac::get_instance(); + LTE_fdd_enb_rlc *rlc = LTE_fdd_enb_rlc::get_instance(); + LTE_fdd_enb_rrc *rrc = LTE_fdd_enb_rrc::get_instance(); + LTE_fdd_enb_phy *phy = LTE_fdd_enb_phy::get_instance(); + LTE_fdd_enb_radio *radio = LTE_fdd_enb_radio::get_instance(); + LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + LTE_FDD_ENB_ERROR_ENUM err; + int64 mac_direct_to_ue; + int64 phy_direct_to_ue; + char err_str[LTE_FDD_ENB_MAX_LINE_SIZE]; + + sem_wait(&start_sem); if(!started) { started = true; - start_mutex.unlock(); + sem_post(&start_sem); + + // Initialize inter-stack communication + phy_to_mac_comm = new LTE_fdd_enb_msgq("phy_to_mac"); + mac_to_phy_comm = new LTE_fdd_enb_msgq("mac_to_phy"); + mac_to_rlc_comm = new LTE_fdd_enb_msgq("mac_to_rlc"); + mac_to_timer_comm = new LTE_fdd_enb_msgq("mac_to_timer"); + rlc_to_mac_comm = new LTE_fdd_enb_msgq("rlc_to_mac"); + rlc_to_pdcp_comm = new LTE_fdd_enb_msgq("rlc_to_pdcp"); + pdcp_to_rlc_comm = new LTE_fdd_enb_msgq("pdcp_to_rlc"); + pdcp_to_rrc_comm = new LTE_fdd_enb_msgq("pdcp_to_rrc"); + rrc_to_pdcp_comm = new LTE_fdd_enb_msgq("rrc_to_pdcp"); + rrc_to_mme_comm = new LTE_fdd_enb_msgq("rrc_to_mme"); + mme_to_rrc_comm = new LTE_fdd_enb_msgq("mme_to_rrc"); + pdcp_to_gw_comm = new LTE_fdd_enb_msgq("pdcp_to_gw"); + gw_to_pdcp_comm = new LTE_fdd_enb_msgq("gw_to_pdcp"); + + // Construct layers + pdcp = new LTE_fdd_enb_pdcp(); + mme = new LTE_fdd_enb_mme(); + gw = new LTE_fdd_enb_gw(); // Construct the system information - cnfg_db->construct_sys_info(); - - // Initialize message queues for inter-layer communication - boost::interprocess::message_queue::remove("phy_mac_mq"); - boost::interprocess::message_queue::remove("mac_phy_mq"); - boost::interprocess::message_queue::remove("mac_rlc_mq"); - boost::interprocess::message_queue::remove("rlc_mac_mq"); - boost::interprocess::message_queue::remove("rlc_pdcp_mq"); - boost::interprocess::message_queue::remove("pdcp_rlc_mq"); - boost::interprocess::message_queue::remove("pdcp_rrc_mq"); - boost::interprocess::message_queue::remove("rrc_pdcp_mq"); - boost::interprocess::message_queue::remove("rrc_mme_mq"); - boost::interprocess::message_queue::remove("mme_rrc_mq"); - boost::interprocess::message_queue phy_mac_mq(boost::interprocess::create_only, - "phy_mac_mq", - 100, - sizeof(LTE_FDD_ENB_MESSAGE_STRUCT *)); - boost::interprocess::message_queue mac_phy_mq(boost::interprocess::create_only, - "mac_phy_mq", - 100, - sizeof(LTE_FDD_ENB_MESSAGE_STRUCT *)); - boost::interprocess::message_queue mac_rlc_mq(boost::interprocess::create_only, - "mac_rlc_mq", - 100, - sizeof(LTE_FDD_ENB_MESSAGE_STRUCT *)); - boost::interprocess::message_queue rlc_mac_mq(boost::interprocess::create_only, - "rlc_mac_mq", - 100, - sizeof(LTE_FDD_ENB_MESSAGE_STRUCT *)); - boost::interprocess::message_queue rlc_pdcp_mq(boost::interprocess::create_only, - "rlc_pdcp_mq", - 100, - sizeof(LTE_FDD_ENB_MESSAGE_STRUCT *)); - boost::interprocess::message_queue pdcp_rlc_mq(boost::interprocess::create_only, - "pdcp_rlc_mq", - 100, - sizeof(LTE_FDD_ENB_MESSAGE_STRUCT *)); - boost::interprocess::message_queue pdcp_rrc_mq(boost::interprocess::create_only, - "pdcp_rrc_mq", - 100, - sizeof(LTE_FDD_ENB_MESSAGE_STRUCT *)); - boost::interprocess::message_queue rrc_pdcp_mq(boost::interprocess::create_only, - "rrc_pdcp_mq", - 100, - sizeof(LTE_FDD_ENB_MESSAGE_STRUCT *)); - boost::interprocess::message_queue rrc_mme_mq(boost::interprocess::create_only, - "rrc_mme_mq", - 100, - sizeof(LTE_FDD_ENB_MESSAGE_STRUCT *)); - boost::interprocess::message_queue mme_rrc_mq(boost::interprocess::create_only, - "mme_rrc_mq", - 100, - sizeof(LTE_FDD_ENB_MESSAGE_STRUCT *)); + cnfg_db->construct_sys_info(pdcp, mme); // Start layers - phy->start(this); - mac->start(this); - rlc->start(); - pdcp->start(); - rrc->start(); - mme->start(); - err = radio->start(); + err = gw->start(pdcp_to_gw_comm, gw_to_pdcp_comm, err_str, this); if(LTE_FDD_ENB_ERROR_NONE == err) { - send_ctrl_error_msg(err, ""); - }else{ - start_mutex.lock(); - started = false; - start_mutex.unlock(); - - phy->stop(); - mac->stop(); - rlc->stop(); - pdcp->stop(); - rrc->stop(); - mme->stop(); + cnfg_db->get_param(LTE_FDD_ENB_PARAM_MAC_DIRECT_TO_UE, mac_direct_to_ue); + cnfg_db->get_param(LTE_FDD_ENB_PARAM_PHY_DIRECT_TO_UE, phy_direct_to_ue); + + phy->start(mac_to_phy_comm, phy_to_mac_comm, phy_direct_to_ue, this); + mac->start(phy_to_mac_comm, rlc_to_mac_comm, mac_to_phy_comm, mac_to_rlc_comm, mac_to_timer_comm, mac_direct_to_ue, this); + timer_mgr->start(mac_to_timer_comm, this); + rlc->start(mac_to_rlc_comm, pdcp_to_rlc_comm, rlc_to_mac_comm, rlc_to_pdcp_comm, this); + pdcp->start(rlc_to_pdcp_comm, rrc_to_pdcp_comm, gw_to_pdcp_comm, pdcp_to_rlc_comm, pdcp_to_rrc_comm, pdcp_to_gw_comm, this); + rrc->start(pdcp_to_rrc_comm, mme_to_rrc_comm, rrc_to_pdcp_comm, rrc_to_mme_comm, this); + mme->start(rrc_to_mme_comm, mme_to_rrc_comm, this); + err = radio->start(); + if(LTE_FDD_ENB_ERROR_NONE == err) + { + send_ctrl_error_msg(err, ""); + }else{ + sem_wait(&start_sem); + started = false; + sem_post(&start_sem); + + phy->stop(); + mac->stop(); + timer_mgr->stop(); + rlc->stop(); + pdcp->stop(); + rrc->stop(); + mme->stop(); - send_ctrl_error_msg(err, ""); + send_ctrl_error_msg(err, ""); + } + }else{ + send_ctrl_error_msg(err, err_str); } }else{ + sem_post(&start_sem); send_ctrl_error_msg(LTE_FDD_ENB_ERROR_ALREADY_STARTED, ""); } } void LTE_fdd_enb_interface::handle_stop(void) { - boost::mutex::scoped_lock lock(start_mutex); - LTE_fdd_enb_radio *radio = LTE_fdd_enb_radio::get_instance(); - LTE_fdd_enb_phy *phy = LTE_fdd_enb_phy::get_instance(); - LTE_fdd_enb_mac *mac = LTE_fdd_enb_mac::get_instance(); - LTE_fdd_enb_rlc *rlc = LTE_fdd_enb_rlc::get_instance(); - LTE_fdd_enb_pdcp *pdcp = LTE_fdd_enb_pdcp::get_instance(); - LTE_fdd_enb_rrc *rrc = LTE_fdd_enb_rrc::get_instance(); - LTE_fdd_enb_mme *mme = LTE_fdd_enb_mme::get_instance(); - LTE_FDD_ENB_ERROR_ENUM err; - + LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + LTE_fdd_enb_radio *radio = LTE_fdd_enb_radio::get_instance(); + LTE_fdd_enb_phy *phy = LTE_fdd_enb_phy::get_instance(); + LTE_fdd_enb_mac *mac = LTE_fdd_enb_mac::get_instance(); + LTE_fdd_enb_rlc *rlc = LTE_fdd_enb_rlc::get_instance(); + LTE_fdd_enb_rrc *rrc = LTE_fdd_enb_rrc::get_instance(); + LTE_FDD_ENB_ERROR_ENUM err; + + sem_wait(&start_sem); if(started) { started = false; - start_mutex.unlock(); + sem_post(&start_sem); // Stop all layers err = radio->stop(); @@ -1010,89 +1074,99 @@ void LTE_fdd_enb_interface::handle_stop(void) { phy->stop(); mac->stop(); + timer_mgr->stop(); rlc->stop(); pdcp->stop(); rrc->stop(); mme->stop(); - - // Send a message to all inter-layer message_queues to unblock receive - LTE_fdd_enb_msgq::send("phy_mac_mq", - LTE_FDD_ENB_MESSAGE_TYPE_KILL, - LTE_FDD_ENB_DEST_LAYER_ANY, - NULL, - 0); - LTE_fdd_enb_msgq::send("mac_phy_mq", - LTE_FDD_ENB_MESSAGE_TYPE_KILL, - LTE_FDD_ENB_DEST_LAYER_ANY, - NULL, - 0); - LTE_fdd_enb_msgq::send("mac_rlc_mq", - LTE_FDD_ENB_MESSAGE_TYPE_KILL, - LTE_FDD_ENB_DEST_LAYER_ANY, - NULL, - 0); - LTE_fdd_enb_msgq::send("rlc_mac_mq", - LTE_FDD_ENB_MESSAGE_TYPE_KILL, - LTE_FDD_ENB_DEST_LAYER_ANY, - NULL, - 0); - LTE_fdd_enb_msgq::send("rlc_pdcp_mq", - LTE_FDD_ENB_MESSAGE_TYPE_KILL, + gw->stop(); + + // Send a message to all inter-stack communication message queues and cleanup + phy_to_mac_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, + LTE_FDD_ENB_DEST_LAYER_ANY, + NULL, + 0); + mac_to_phy_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, + LTE_FDD_ENB_DEST_LAYER_ANY, + NULL, + 0); + mac_to_rlc_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, + LTE_FDD_ENB_DEST_LAYER_ANY, + NULL, + 0); + mac_to_timer_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, + LTE_FDD_ENB_DEST_LAYER_ANY, + NULL, + 0); + rlc_to_mac_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, + LTE_FDD_ENB_DEST_LAYER_ANY, + NULL, + 0); + rlc_to_pdcp_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, LTE_FDD_ENB_DEST_LAYER_ANY, NULL, 0); - LTE_fdd_enb_msgq::send("pdcp_rlc_mq", - LTE_FDD_ENB_MESSAGE_TYPE_KILL, + pdcp_to_rlc_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, LTE_FDD_ENB_DEST_LAYER_ANY, NULL, 0); - LTE_fdd_enb_msgq::send("pdcp_rrc_mq", - LTE_FDD_ENB_MESSAGE_TYPE_KILL, + pdcp_to_rrc_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, LTE_FDD_ENB_DEST_LAYER_ANY, NULL, 0); - LTE_fdd_enb_msgq::send("rrc_pdcp_mq", - LTE_FDD_ENB_MESSAGE_TYPE_KILL, + rrc_to_pdcp_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, LTE_FDD_ENB_DEST_LAYER_ANY, NULL, 0); - LTE_fdd_enb_msgq::send("rrc_mme_mq", - LTE_FDD_ENB_MESSAGE_TYPE_KILL, - LTE_FDD_ENB_DEST_LAYER_ANY, - NULL, - 0); - LTE_fdd_enb_msgq::send("mme_rrc_mq", - LTE_FDD_ENB_MESSAGE_TYPE_KILL, - LTE_FDD_ENB_DEST_LAYER_ANY, - NULL, - 0); - sleep(1); - - boost::interprocess::message_queue::remove("phy_mac_mq"); - boost::interprocess::message_queue::remove("mac_phy_mq"); - boost::interprocess::message_queue::remove("mac_rlc_mq"); - boost::interprocess::message_queue::remove("rlc_mac_mq"); - boost::interprocess::message_queue::remove("rlc_pdcp_mq"); - boost::interprocess::message_queue::remove("pdcp_rlc_mq"); - boost::interprocess::message_queue::remove("pdcp_rrc_mq"); - boost::interprocess::message_queue::remove("rrc_pdcp_mq"); - boost::interprocess::message_queue::remove("rrc_mme_mq"); - boost::interprocess::message_queue::remove("mme_rrc_mq"); + rrc_to_mme_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, + LTE_FDD_ENB_DEST_LAYER_ANY, + NULL, + 0); + mme_to_rrc_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, + LTE_FDD_ENB_DEST_LAYER_ANY, + NULL, + 0); + pdcp_to_gw_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, + LTE_FDD_ENB_DEST_LAYER_ANY, + NULL, + 0); + gw_to_pdcp_comm->send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, + LTE_FDD_ENB_DEST_LAYER_ANY, + NULL, + 0); + delete phy_to_mac_comm; + delete mac_to_phy_comm; + delete mac_to_rlc_comm; + delete mac_to_timer_comm; + delete rlc_to_mac_comm; + delete rlc_to_pdcp_comm; + delete pdcp_to_rlc_comm; + delete pdcp_to_rrc_comm; + delete rrc_to_pdcp_comm; + delete rrc_to_mme_comm; + delete mme_to_rrc_comm; + delete pdcp_to_gw_comm; + delete gw_to_pdcp_comm; // Cleanup all layers LTE_fdd_enb_radio::cleanup(); LTE_fdd_enb_phy::cleanup(); LTE_fdd_enb_mac::cleanup(); + LTE_fdd_enb_timer_mgr::cleanup(); LTE_fdd_enb_rlc::cleanup(); - LTE_fdd_enb_pdcp::cleanup(); LTE_fdd_enb_rrc::cleanup(); - LTE_fdd_enb_mme::cleanup(); + + // Delete layers + delete pdcp; + delete mme; + delete gw; send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, ""); }else{ send_ctrl_error_msg(err, ""); } }else{ + sem_post(&start_sem); send_ctrl_error_msg(LTE_FDD_ENB_ERROR_ALREADY_STOPPED, ""); } } @@ -1115,65 +1189,44 @@ void LTE_fdd_enb_interface::handle_help(void) send_ctrl_msg("\tSet parameters using write format"); // Commands send_ctrl_msg("\tCommands:"); - send_ctrl_msg("\t\tstart - Constructs the system information and starts the eNB"); - send_ctrl_msg("\t\tstop - Stops the eNB"); - send_ctrl_msg("\t\tshutdown - Stops the eNB and exits"); - send_ctrl_msg("\t\tconstruct_si - Constructs the new system information"); - send_ctrl_msg("\t\thelp - Prints this screen"); + send_ctrl_msg("\t\tstart - Constructs the system information and starts the eNB"); + send_ctrl_msg("\t\tstop - Stops the eNB"); + send_ctrl_msg("\t\tshutdown - Stops the eNB and exits"); + send_ctrl_msg("\t\tconstruct_si - Constructs the new system information"); + send_ctrl_msg("\t\thelp - Prints this screen"); + send_ctrl_msg("\t\tadd_user imsi= imei= k= - Adds a user to the HSS ( and are 15 decimal digits, and is 32 hex digits)"); + send_ctrl_msg("\t\tdel_user imsi= - Deletes a user from the HSS"); + send_ctrl_msg("\t\tprint_users - Prints all the users in the HSS"); + send_ctrl_msg("\t\tprint_registered_users - Prints all the users currently registered"); // Radio Parameters send_ctrl_msg("\tRadio Parameters:"); tmp_str = "\t\t"; - tmp_str += lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_AVAILABLE_RADIOS]; + tmp_str += LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_AVAILABLE_RADIOS]; tmp_str += ": (read-only)"; send_ctrl_msg(tmp_str); for(i=0; i(i); - tmp_str += ": "; - tmp_str += avail_radios.radio[i].name; - }catch(...){ - // Intentionally do nothing - } + tmp_str = "\t\t\t"; + tmp_str += to_string(i); + tmp_str += ": "; + tmp_str += avail_radios.radio[i].name; send_ctrl_msg(tmp_str); } tmp_str = "\t\t"; - tmp_str += lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SELECTED_RADIO_NAME]; + tmp_str += LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SELECTED_RADIO_NAME]; tmp_str += " (read-only) = "; tmp_str += selected_radio.name; send_ctrl_msg(tmp_str); tmp_str = "\t\t"; - tmp_str += lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SELECTED_RADIO_IDX]; - tmp_str += " = "; - try - { - tmp_str += boost::lexical_cast(radio->get_selected_radio_idx()); - }catch(...){ - // Intentionally do nothing - } - send_ctrl_msg(tmp_str); - tmp_str = "\t\t"; - tmp_str += lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_TX_GAIN]; + tmp_str += LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_SELECTED_RADIO_IDX]; tmp_str += " = "; - try - { - tmp_str += boost::lexical_cast(radio->get_tx_gain()); - }catch(...){ - // Intentionally do nothing - } + tmp_str += to_string(radio->get_selected_radio_idx()); send_ctrl_msg(tmp_str); tmp_str = "\t\t"; - tmp_str += lte_fdd_enb_param_text[LTE_FDD_ENB_PARAM_RX_GAIN]; + tmp_str += LTE_fdd_enb_param_text[LTE_FDD_ENB_PARAM_CLOCK_SOURCE]; tmp_str += " = "; - try - { - tmp_str += boost::lexical_cast(radio->get_rx_gain()); - }catch(...){ - // Intentionally do nothing - } + tmp_str += radio->get_clock_source(); send_ctrl_msg(tmp_str); // System Parameters @@ -1181,62 +1234,117 @@ void LTE_fdd_enb_interface::handle_help(void) for(iter=var_map.begin(); iter!=var_map.end(); iter++) { tmp_str = "\t\t"; - tmp_str += lte_fdd_enb_param_text[(*iter).second.param]; + tmp_str += LTE_fdd_enb_param_text[(*iter).second.param]; tmp_str += " = "; - try + switch((*iter).second.var_type) { - switch((*iter).second.var_type) + case LTE_FDD_ENB_VAR_TYPE_DOUBLE: + cnfg_db->get_param((*iter).second.param, d_value); + tmp_str += to_string(d_value); + break; + case LTE_FDD_ENB_VAR_TYPE_INT64: + cnfg_db->get_param((*iter).second.param, i_value); + if(LTE_FDD_ENB_PARAM_FREQ_BAND == (*iter).second.param) { - case LTE_FDD_ENB_VAR_TYPE_DOUBLE: - cnfg_db->get_param((*iter).second.param, d_value); - tmp_str += boost::lexical_cast(d_value); - break; - case LTE_FDD_ENB_VAR_TYPE_INT64: - cnfg_db->get_param((*iter).second.param, i_value); - if(LTE_FDD_ENB_PARAM_FREQ_BAND == (*iter).second.param) - { - tmp_str += liblte_interface_band_text[i_value]; - }else{ - tmp_str += boost::lexical_cast(i_value); - } - break; - case LTE_FDD_ENB_VAR_TYPE_HEX: - s_value.clear(); - cnfg_db->get_param((*iter).second.param, s_value); - tmp_str += s_value; - break; - case LTE_FDD_ENB_VAR_TYPE_UINT32: - cnfg_db->get_param((*iter).second.param, u_value); - if(LTE_FDD_ENB_PARAM_DEBUG_TYPE == (*iter).second.param) + tmp_str += liblte_interface_band_text[i_value]; + }else{ + tmp_str += to_string(i_value); + } + break; + case LTE_FDD_ENB_VAR_TYPE_HEX: + s_value.clear(); + cnfg_db->get_param((*iter).second.param, s_value); + tmp_str += s_value; + break; + case LTE_FDD_ENB_VAR_TYPE_UINT32: + cnfg_db->get_param((*iter).second.param, u_value); + if(LTE_FDD_ENB_PARAM_DEBUG_TYPE == (*iter).second.param) + { + for(i=0; i(u_value); } - break; + }else{ + tmp_str += to_string(u_value); } - }catch(...){ - // Intentionally do nothing + break; } send_ctrl_msg(tmp_str); } } +void LTE_fdd_enb_interface::handle_add_user(std::string msg) +{ + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); + std::string imsi_str; + std::string imei_str; + std::string k_str; + bool imsi_valid = true; + bool imei_valid = true; + bool k_valid = true; + + // Extract IMSI and check + imsi_str = msg.substr(msg.find("imsi")+sizeof("imsi"), std::string::npos); + imsi_str = imsi_str.substr(0, imsi_str.find(" ")); + imsi_valid = is_string_valid_as_number(imsi_str, 15, 10); + + // Extract IMEI and check + imei_str = msg.substr(msg.find("imei")+sizeof("imei"), std::string::npos); + imei_str = imei_str.substr(0, imei_str.find(" ")); + imei_valid = is_string_valid_as_number(imei_str, 15, 10); + + // Extract K and check + k_str = msg.substr(msg.find("k")+sizeof("k"), std::string::npos); + k_str = k_str.substr(0, k_str.find(" ")); + k_valid = is_string_valid_as_number(k_str, 32, 16); + + if(imsi_valid && imei_valid && k_valid) + { + send_ctrl_error_msg(hss->add_user(imsi_str, imei_str, k_str), ""); + }else{ + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_INVALID_PARAM, ""); + } +} +void LTE_fdd_enb_interface::handle_del_user(std::string msg) +{ + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); + std::string imsi_str; + + // Extract IMSI + imsi_str = msg.substr(msg.find("imsi")+sizeof("imsi"), std::string::npos); + imsi_str = imsi_str.substr(0, imsi_str.find(" ")); + + if(is_string_valid_as_number(imsi_str, 15, 10)) + { + send_ctrl_error_msg(hss->del_user(imsi_str), ""); + }else{ + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_INVALID_PARAM, ""); + } +} +void LTE_fdd_enb_interface::handle_print_users(void) +{ + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); + + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, hss->print_all_users()); +} +void LTE_fdd_enb_interface::handle_print_registered_users(void) +{ + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + + send_ctrl_error_msg(LTE_FDD_ENB_ERROR_NONE, user_mgr->print_all_users()); +} /*******************/ /* Gets/Sets */ @@ -1247,7 +1355,7 @@ bool LTE_fdd_enb_interface::get_shutdown(void) } bool LTE_fdd_enb_interface::app_is_started(void) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_sem); return(started); } @@ -1331,7 +1439,10 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_interface::write_value(LTE_FDD_ENB_VAR_STRUCT { err = cnfg_db->set_param(var->param, (int64)i); err = cnfg_db->set_param(LTE_FDD_ENB_PARAM_DL_EARFCN, (int64)liblte_interface_first_dl_earfcn[i]); - cnfg_db->construct_sys_info(); + if(app_is_started()) + { + cnfg_db->construct_sys_info(pdcp, mme); + } break; } } @@ -1356,6 +1467,7 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_interface::write_value(LTE_FDD_ENB_VAR_STRUCT LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_OUT_OF_BOUNDS; uint32 i; + const char *v_str = value.c_str(); if(started && !var->dynamic) { @@ -1369,7 +1481,7 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_interface::write_value(LTE_FDD_ENB_VAR_STRUCT { for(i=0; i= 0x0A) + if((v_str[i] & 0x0F) >= 0x0A) { break; } @@ -1378,6 +1490,10 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_interface::write_value(LTE_FDD_ENB_VAR_STRUCT { err = cnfg_db->set_param(var->param, value); } + }else if((LTE_FDD_ENB_PARAM_IP_ADDR_START == var->param || + LTE_FDD_ENB_PARAM_DNS_ADDR == var->param) && + value.length() == 8){ + err = cnfg_db->set_param(var->param, value); }else{ err = LTE_FDD_ENB_ERROR_INVALID_PARAM; } diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_mac.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_mac.cc old mode 100644 new mode 100755 index f3393f0..6bf0c1e --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_mac.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_mac.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_mac.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -36,6 +36,37 @@ DL CCCH message processing. 06/15/2014 Ben Wojtowicz Added uplink scheduling and changed fn_combo to current_tti. + 08/03/2014 Ben Wojtowicz Removed debug message. + 09/03/2014 Ben Wojtowicz Combined the contention resolution ID and + the first downlink RLC message. + 11/01/2014 Ben Wojtowicz Added NDI toggling. + 11/29/2014 Ben Wojtowicz Using the byte message struct for SDUs. + 12/16/2014 Ben Wojtowicz Added ol extension to message queues. + 12/24/2014 Ben Wojtowicz Dynamically determining MCS for downlink + data. + 02/15/2015 Ben Wojtowicz Moved to new message queue, added support + for higher order modulation schemes, fixed + C-RNTI release, changed RTS timing, and + added DL QoS TTI frequency. + 03/15/2015 Ben Wojtowicz Fixed RTS issues. + 07/25/2015 Ben Wojtowicz Combined the DL and UL schedule messages into + a single PHY schedule message and using a + local copy of LIBLTE_MAC_PDU_STRUCT. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t, added and used some helper functions, + fixed an issue with RTS response on late + subframes, and properly initialize allocation + structure (thanks to Markus Grab for finding + this). + 02/13/2016 Ben Wojtowicz Added a user inactivity timer. + 03/12/2016 Ben Wojtowicz Added PUCCH and H-ARQ support. + 07/03/2016 Ben Wojtowicz Fixed memcpy lengths. + 07/31/2016 Ben Wojtowicz Reworked the RTS logic and limited the number + of HARQ retransmissions. + 07/29/2017 Ben Wojtowicz Added SR support, added IPC direct to a UE + MAC, using the latest LTE library, and + refactored the UL scheduler from fixed + scheduling to using SR and BSR. *******************************************************************************/ @@ -47,11 +78,13 @@ #include "LTE_fdd_enb_timer_mgr.h" #include "LTE_fdd_enb_mac.h" #include "LTE_fdd_enb_phy.h" +#include "libtools_scoped_lock.h" /******************************************************************************* DEFINES *******************************************************************************/ +#define BSR_GRANT_SIZE_BYTES 10 /******************************************************************************* TYPEDEFS @@ -62,8 +95,8 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_enb_mac* LTE_fdd_enb_mac::instance = NULL; -boost::mutex mac_instance_mutex; +LTE_fdd_enb_mac* LTE_fdd_enb_mac::instance = NULL; +static pthread_mutex_t mac_instance_mutex = PTHREAD_MUTEX_INITIALIZER; /******************************************************************************* CLASS IMPLEMENTATIONS @@ -74,7 +107,7 @@ boost::mutex mac_instance_mutex; /*******************/ LTE_fdd_enb_mac* LTE_fdd_enb_mac::get_instance(void) { - boost::mutex::scoped_lock lock(mac_instance_mutex); + libtools_scoped_lock lock(mac_instance_mutex); if(NULL == instance) { @@ -85,7 +118,7 @@ LTE_fdd_enb_mac* LTE_fdd_enb_mac::get_instance(void) } void LTE_fdd_enb_mac::cleanup(void) { - boost::mutex::scoped_lock lock(mac_instance_mutex); + libtools_scoped_lock lock(mac_instance_mutex); if(NULL != instance) { @@ -99,38 +132,62 @@ void LTE_fdd_enb_mac::cleanup(void) /********************************/ LTE_fdd_enb_mac::LTE_fdd_enb_mac() { + sem_init(&start_sem, 0, 1); + sem_init(&rar_sched_queue_sem, 0, 1); + sem_init(&dl_sched_queue_sem, 0, 1); + sem_init(&ul_sched_queue_sem, 0, 1); + sem_init(&ul_sr_sched_queue_sem, 0, 1); + sem_init(&sys_info_sem, 0, 1); interface = NULL; started = false; } LTE_fdd_enb_mac::~LTE_fdd_enb_mac() { stop(); + sem_destroy(&sys_info_sem); + sem_destroy(&ul_sr_sched_queue_sem); + sem_destroy(&ul_sched_queue_sem); + sem_destroy(&dl_sched_queue_sem); + sem_destroy(&rar_sched_queue_sem); + sem_destroy(&start_sem); } /********************/ /* Start/Stop */ /********************/ -void LTE_fdd_enb_mac::start(LTE_fdd_enb_interface *iface) +void LTE_fdd_enb_mac::start(LTE_fdd_enb_msgq *from_phy, + LTE_fdd_enb_msgq *from_rlc, + LTE_fdd_enb_msgq *to_phy, + LTE_fdd_enb_msgq *to_rlc, + LTE_fdd_enb_msgq *to_timer, + bool direct_to_ue, + LTE_fdd_enb_interface *iface) { - boost::mutex::scoped_lock lock(start_mutex); - LTE_fdd_enb_msgq_cb phy_cb(<E_fdd_enb_msgq_cb_wrapper, this); - LTE_fdd_enb_msgq_cb rlc_cb(<E_fdd_enb_msgq_cb_wrapper, this); - LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); - uint32 i; + libtools_scoped_lock lock(start_sem); + LTE_fdd_enb_msgq_cb phy_cb(<E_fdd_enb_msgq_cb_wrapper, this); + LTE_fdd_enb_msgq_cb rlc_cb(<E_fdd_enb_msgq_cb_wrapper, this); + libtools_ipc_msgq_cb ue_cb(&libtools_ipc_msgq_cb_wrapper, this); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + uint32 i; if(!started) { interface = iface; started = true; - phy_comm_msgq = new LTE_fdd_enb_msgq("phy_mac_mq", - phy_cb, - 90); - rlc_comm_msgq = new LTE_fdd_enb_msgq("rlc_mac_mq", - rlc_cb); - mac_phy_mq = new boost::interprocess::message_queue(boost::interprocess::open_only, - "mac_phy_mq"); - mac_rlc_mq = new boost::interprocess::message_queue(boost::interprocess::open_only, - "mac_rlc_mq"); + msgq_from_phy = from_phy; + msgq_from_rlc = from_rlc; + msgq_to_phy = to_phy; + msgq_to_rlc = to_rlc; + msgq_to_timer = to_timer; + msgq_from_phy->attach_rx(phy_cb, 90); + msgq_from_rlc->attach_rx(rlc_cb); + + if(direct_to_ue) + { + msgq_to_ue = new libtools_ipc_msgq("enb_ue", ue_cb); + }else{ + msgq_to_ue = NULL; + } // Scheduler cnfg_db->get_sys_info(sys_info); @@ -146,6 +203,7 @@ void LTE_fdd_enb_mac::start(LTE_fdd_enb_interface *iface) sched_ul_subfr[i].N_avail_prbs = sys_info.N_rb_ul; sched_ul_subfr[i].N_sched_prbs = 0; sched_ul_subfr[i].current_tti = i; + sched_ul_subfr[i].N_pucch = 0; sched_ul_subfr[i].next_prb = 0; } sched_dl_subfr[0].current_tti = 10; @@ -157,41 +215,40 @@ void LTE_fdd_enb_mac::start(LTE_fdd_enb_interface *iface) } void LTE_fdd_enb_mac::stop(void) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_sem); if(started) { started = false; - delete phy_comm_msgq; - delete rlc_comm_msgq; + + if(NULL != msgq_to_ue) + { + delete msgq_to_ue; + } } } /***********************/ /* Communication */ /***********************/ -void LTE_fdd_enb_mac::handle_phy_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) +void LTE_fdd_enb_mac::handle_phy_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) { - if(LTE_FDD_ENB_DEST_LAYER_MAC == msg->dest_layer || - LTE_FDD_ENB_DEST_LAYER_ANY == msg->dest_layer) + if(LTE_FDD_ENB_DEST_LAYER_MAC == msg.dest_layer || + LTE_FDD_ENB_DEST_LAYER_ANY == msg.dest_layer) { - switch(msg->type) + switch(msg.type) { case LTE_FDD_ENB_MESSAGE_TYPE_READY_TO_SEND: - handle_ready_to_send(&msg->msg.ready_to_send); - delete msg; + handle_ready_to_send(&msg.msg.ready_to_send); break; case LTE_FDD_ENB_MESSAGE_TYPE_PRACH_DECODE: - handle_prach_decode(&msg->msg.prach_decode); - delete msg; + handle_prach_decode(&msg.msg.prach_decode); break; case LTE_FDD_ENB_MESSAGE_TYPE_PUCCH_DECODE: - handle_pucch_decode(&msg->msg.pucch_decode); - delete msg; + handle_pucch_decode(&msg.msg.pucch_decode); break; case LTE_FDD_ENB_MESSAGE_TYPE_PUSCH_DECODE: - handle_pusch_decode(&msg->msg.pusch_decode); - delete msg; + handle_pusch_decode(&msg.msg.pusch_decode); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_WARNING, @@ -199,25 +256,23 @@ void LTE_fdd_enb_mac::handle_phy_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) __FILE__, __LINE__, "Received invalid PHY message %s", - LTE_fdd_enb_message_type_text[msg->type]); - delete msg; + LTE_fdd_enb_message_type_text[msg.type]); break; } }else{ // Forward message to RLC - mac_rlc_mq->send(&msg, sizeof(msg), 0); + msgq_to_rlc->send(msg); } } -void LTE_fdd_enb_mac::handle_rlc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) +void LTE_fdd_enb_mac::handle_rlc_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) { - if(LTE_FDD_ENB_DEST_LAYER_MAC == msg->dest_layer || - LTE_FDD_ENB_DEST_LAYER_ANY == msg->dest_layer) + if(LTE_FDD_ENB_DEST_LAYER_MAC == msg.dest_layer || + LTE_FDD_ENB_DEST_LAYER_ANY == msg.dest_layer) { - switch(msg->type) + switch(msg.type) { case LTE_FDD_ENB_MESSAGE_TYPE_MAC_SDU_READY: - handle_sdu_ready(&msg->msg.mac_sdu_ready); - delete msg; + handle_sdu_ready(&msg.msg.mac_sdu_ready); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, @@ -225,13 +280,45 @@ void LTE_fdd_enb_mac::handle_rlc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) __FILE__, __LINE__, "Received invalid RLC message %s", - LTE_fdd_enb_message_type_text[msg->type]); - delete msg; + LTE_fdd_enb_message_type_text[msg.type]); break; } }else{ // Forward message to PHY - mac_phy_mq->send(&msg, sizeof(msg), 0); + msgq_to_phy->send(msg); + } +} +void LTE_fdd_enb_mac::handle_ue_msg(LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT *msg) +{ + LTE_FDD_ENB_PRACH_DECODE_MSG_STRUCT prach_decode; + LTE_FDD_ENB_PUSCH_DECODE_MSG_STRUCT pusch_decode; + + switch(msg->type) + { + case LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_KILL: + msgq_to_ue = NULL; + break; + case LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_RACH: + prach_decode.num_preambles = 1; + prach_decode.current_tti = sched_ul_subfr[sched_cur_ul_subfn].current_tti; + prach_decode.timing_adv[0] = 0; + prach_decode.preamble[0] = msg->msg.rach.preamble; + handle_prach_decode(&prach_decode); + break; + case LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_MAC_PDU: + memcpy(&pusch_decode.msg, &msg->msg.mac_pdu_msg.msg, sizeof(pusch_decode.msg)); + pusch_decode.current_tti = sched_ul_subfr[sched_cur_ul_subfn].current_tti; + pusch_decode.rnti = msg->msg.mac_pdu_msg.rnti; + handle_pusch_decode(&pusch_decode); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MAC, + __FILE__, + __LINE__, + "Received invalid UE message %s", + libtools_ipc_msgq_message_type_text[msg->type]); + break; } } @@ -240,53 +327,47 @@ void LTE_fdd_enb_mac::handle_rlc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) /****************************/ void LTE_fdd_enb_mac::update_sys_info(void) { - LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + libtools_scoped_lock lock(sys_info_sem); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); - sys_info_mutex.lock(); cnfg_db->get_sys_info(sys_info); - sys_info_mutex.unlock(); } -void LTE_fdd_enb_mac::sched_ul(LTE_fdd_enb_user *user, - uint32 requested_tbs) +void LTE_fdd_enb_mac::add_periodic_sr_pucch(uint16 rnti, + uint32 i_sr, + uint32 n_1_p_pucch) { - LIBLTE_PHY_ALLOCATION_STRUCT alloc; + LTE_FDD_ENB_UL_SR_SCHED_QUEUE_STRUCT *sr = NULL; + + sr = new LTE_FDD_ENB_UL_SR_SCHED_QUEUE_STRUCT; - alloc.pre_coder_type = LIBLTE_PHY_PRE_CODER_TYPE_TX_DIVERSITY; - alloc.mod_type = LIBLTE_PHY_MODULATION_TYPE_QPSK; - alloc.chan_type = LIBLTE_PHY_CHAN_TYPE_ULSCH; - alloc.rv_idx = 0; - alloc.N_codewords = 1; - alloc.N_layers = 1; - alloc.tx_mode = 1; - alloc.rnti = user->get_c_rnti(); - alloc.tpc = LIBLTE_PHY_TPC_COMMAND_DCI_0_3_4_DB_NEG_1; - alloc.ndi = false; // FIXME - sys_info_mutex.lock(); - liblte_phy_get_tbs_mcs_and_n_prb_for_ul(requested_tbs, - sys_info.N_rb_ul, - &alloc.tbs, - &alloc.mcs, - &alloc.N_prb); - sys_info_mutex.unlock(); - - // Add the allocation to the scheduling queue - if(LTE_FDD_ENB_ERROR_NONE != add_to_ul_sched_queue((sched_ul_subfr[sched_cur_ul_subfn].current_tti + 4) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1), - &alloc)) + if(NULL != sr) { - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, - LTE_FDD_ENB_DEBUG_LEVEL_MAC, - __FILE__, - __LINE__, - "Can't schedule UL"); - }else{ - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, - LTE_FDD_ENB_DEBUG_LEVEL_MAC, - __FILE__, - __LINE__, - "UL scheduled for RNTI=%u, UL_QUEUE_SIZE=%u", - alloc.rnti, - ul_sched_queue.size()); + sr->i_sr = i_sr; + sr->n_1_p_pucch = n_1_p_pucch - 1; + sr->rnti = rnti; + + sem_wait(&ul_sr_sched_queue_sem); + ul_sr_sched_queue.push_back(sr); + sem_post(&ul_sr_sched_queue_sem); + } +} +void LTE_fdd_enb_mac::remove_periodic_sr_pucch(uint16 rnti) +{ + std::list::iterator iter; + LTE_FDD_ENB_UL_SR_SCHED_QUEUE_STRUCT *sr; + + sem_wait(&ul_sr_sched_queue_sem); + for(iter=ul_sr_sched_queue.begin(); iter!=ul_sr_sched_queue.end(); iter++) + { + if(rnti == (*iter)->rnti) + { + sr = (*iter); + ul_sr_sched_queue.erase(iter); + delete sr; + break; + } } + sem_post(&ul_sr_sched_queue_sem); } /**********************/ @@ -294,103 +375,99 @@ void LTE_fdd_enb_mac::sched_ul(LTE_fdd_enb_user *user, /**********************/ void LTE_fdd_enb_mac::handle_ready_to_send(LTE_FDD_ENB_READY_TO_SEND_MSG_STRUCT *rts) { - LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + LTE_fdd_enb_phy *phy = LTE_fdd_enb_phy::get_instance(); + LTE_FDD_ENB_TIMER_TICK_MSG_STRUCT timer_tick; + uint32 i; + uint32 dl_tti; + uint32 ul_tti; + int32 num_subfrs_to_skip; // Send tick to timer manager - // FIXME: Send this through msgq - timer_mgr->handle_tick(); - - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, - LTE_FDD_ENB_DEBUG_LEVEL_MAC, - __FILE__, - __LINE__, - "RTS DL_CURRENT_TTI:PHY=%u,MAC=%u UL_CURRENT_TTI:PHY=%u,MAC=%u", - rts->dl_current_tti, - sched_dl_subfr[sched_cur_dl_subfn].current_tti, - rts->ul_current_tti, - sched_ul_subfr[sched_cur_ul_subfn].current_tti); + msgq_to_timer->send(LTE_FDD_ENB_MESSAGE_TYPE_TIMER_TICK, + LTE_FDD_ENB_DEST_LAYER_TIMER_MGR, + (LTE_FDD_ENB_MESSAGE_UNION *)&timer_tick, + sizeof(LTE_FDD_ENB_TIMER_TICK_MSG_STRUCT)); - if(rts->dl_current_tti != sched_dl_subfr[sched_cur_dl_subfn].current_tti) + phy->get_current_ttis(&dl_tti, &ul_tti); + if(2 != ((int32)(sched_dl_subfr[sched_cur_dl_subfn].current_tti) - (int32)(dl_tti))) { - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + num_subfrs_to_skip = (int32)(sched_dl_subfr[sched_cur_dl_subfn].current_tti) - (int32)(dl_tti); + if(1000 < fabs(num_subfrs_to_skip)) + { + num_subfrs_to_skip = 0; + }else if(0 > num_subfrs_to_skip){ + num_subfrs_to_skip = -num_subfrs_to_skip; + num_subfrs_to_skip += 3; + }else{ + num_subfrs_to_skip = 0; + } + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, __LINE__, - "RTS dl_current_tti incorrect: RTS %u but currently on %u", - rts->dl_current_tti, - sched_dl_subfr[sched_cur_dl_subfn].current_tti); - while(rts->dl_current_tti != sched_dl_subfr[sched_cur_dl_subfn].current_tti) + "MAC_dl_tti - PHY_dl_tti != 2 (%d), skipping %d subframes", + (int32)(sched_dl_subfr[sched_cur_dl_subfn].current_tti) - (int32)(dl_tti), + num_subfrs_to_skip); + sem_wait(&sys_info_sem); + for(i=0; iul_current_tti != sched_ul_subfr[sched_cur_ul_subfn].current_tti) - { + sem_post(&sys_info_sem); + }else if(rts->dl_current_tti == sched_dl_subfr[sched_cur_dl_subfn].current_tti && + rts->ul_current_tti == sched_ul_subfr[sched_cur_ul_subfn].current_tti){ + msgq_to_phy->send(LTE_FDD_ENB_MESSAGE_TYPE_PHY_SCHEDULE, + &sched_dl_subfr[sched_cur_dl_subfn], + &sched_ul_subfr[sched_cur_ul_subfn]); + + // Advance the frame number combination + sched_dl_subfr[sched_cur_dl_subfn].current_tti = add_to_tti(sched_dl_subfr[sched_cur_dl_subfn].current_tti, 10); + sched_ul_subfr[sched_cur_ul_subfn].current_tti = add_to_tti(sched_ul_subfr[sched_cur_ul_subfn].current_tti, 10); + + // Clear the subframes + sem_wait(&sys_info_sem); + sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.N_alloc = 0; + sched_dl_subfr[sched_cur_dl_subfn].ul_allocations.N_alloc = 0; + sched_dl_subfr[sched_cur_dl_subfn].N_avail_prbs = sys_info.N_rb_dl - get_n_reserved_prbs(sched_dl_subfr[sched_cur_dl_subfn].current_tti); + sched_dl_subfr[sched_cur_dl_subfn].N_sched_prbs = 0; + sched_ul_subfr[sched_cur_ul_subfn].decodes.N_alloc = 0; + sched_ul_subfr[sched_cur_ul_subfn].N_sched_prbs = 0; + sched_ul_subfr[sched_cur_ul_subfn].N_pucch = 0; + sched_ul_subfr[sched_cur_ul_subfn].next_prb = 0; + sem_post(&sys_info_sem); + + // Advance the subframe numbers + sched_cur_dl_subfn = (sched_cur_dl_subfn + 1) % 10; + sched_cur_ul_subfn = (sched_cur_ul_subfn + 1) % 10; + + scheduler(); + }else{ interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, __LINE__, - "RTS ul_current_tti incorrect: RTS %u but currently on %u", - rts->ul_current_tti, - sched_ul_subfr[sched_cur_ul_subfn].current_tti); - while(rts->ul_current_tti != sched_ul_subfr[sched_cur_ul_subfn].current_tti) - { - // Advance the frame number combination - sched_ul_subfr[sched_cur_ul_subfn].current_tti = (sched_ul_subfr[sched_cur_ul_subfn].current_tti + 10) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - - // Clear the subframe - sched_ul_subfr[sched_cur_ul_subfn].decodes.N_alloc = 0; - sched_ul_subfr[sched_cur_ul_subfn].N_sched_prbs = 0; - sched_ul_subfr[sched_cur_ul_subfn].next_prb = 0; - - // Advance the subframe number - sched_cur_ul_subfn = (sched_cur_ul_subfn + 1) % 10; - } + "RTS issue DL %u:%u, UL %u:%u", + sched_dl_subfr[sched_cur_dl_subfn].current_tti, + dl_tti, + sched_ul_subfr[sched_cur_ul_subfn].current_tti, + ul_tti); } - - LTE_fdd_enb_msgq::send(mac_phy_mq, - LTE_FDD_ENB_MESSAGE_TYPE_DL_SCHEDULE, - LTE_FDD_ENB_DEST_LAYER_PHY, - (LTE_FDD_ENB_MESSAGE_UNION *)&sched_dl_subfr[sched_cur_dl_subfn], - sizeof(LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT)); - LTE_fdd_enb_msgq::send(mac_phy_mq, - LTE_FDD_ENB_MESSAGE_TYPE_UL_SCHEDULE, - LTE_FDD_ENB_DEST_LAYER_PHY, - (LTE_FDD_ENB_MESSAGE_UNION *)&sched_ul_subfr[sched_cur_ul_subfn], - sizeof(LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT)); - - // Advance the frame number combination - sched_dl_subfr[sched_cur_dl_subfn].current_tti = (sched_dl_subfr[sched_cur_dl_subfn].current_tti + 10) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - sched_ul_subfr[sched_cur_ul_subfn].current_tti = (sched_ul_subfr[sched_cur_ul_subfn].current_tti + 10) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - - // Clear the subframes - sys_info_mutex.lock(); - sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.N_alloc = 0; - sched_dl_subfr[sched_cur_dl_subfn].ul_allocations.N_alloc = 0; - sched_dl_subfr[sched_cur_dl_subfn].N_avail_prbs = sys_info.N_rb_dl - get_n_reserved_prbs(sched_dl_subfr[sched_cur_dl_subfn].current_tti); - sched_dl_subfr[sched_cur_dl_subfn].N_sched_prbs = 0; - sched_ul_subfr[sched_cur_ul_subfn].decodes.N_alloc = 0; - sched_ul_subfr[sched_cur_ul_subfn].N_sched_prbs = 0; - sched_ul_subfr[sched_cur_ul_subfn].next_prb = 0; - sys_info_mutex.unlock(); - - // Advance the subframe numbers - sched_cur_dl_subfn = (sched_cur_dl_subfn + 1) % 10; - sched_cur_ul_subfn = (sched_cur_ul_subfn + 1) % 10; - - scheduler(); } void LTE_fdd_enb_mac::handle_prach_decode(LTE_FDD_ENB_PRACH_DECODE_MSG_STRUCT *prach_decode) { @@ -406,21 +483,141 @@ void LTE_fdd_enb_mac::handle_prach_decode(LTE_FDD_ENB_PRACH_DECODE_MSG_STRUCT *p } void LTE_fdd_enb_mac::handle_pucch_decode(LTE_FDD_ENB_PUCCH_DECODE_MSG_STRUCT *pucch_decode) { - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + LTE_fdd_enb_user *user; + + if(LTE_FDD_ENB_ERROR_NONE == user_mgr->find_user(pucch_decode->rnti, &user)) + { + if(LTE_FDD_ENB_PUCCH_TYPE_ACK_NACK == pucch_decode->type) + { + handle_pucch_ack_nack(user, + pucch_decode->current_tti, + &pucch_decode->msg); + }else{ + handle_pucch_sr(user, + pucch_decode->current_tti, + &pucch_decode->msg); + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MAC, + __FILE__, + __LINE__, + "Failed to find PUCCH user RNTI=%u TTI=%u", + pucch_decode->rnti, + pucch_decode->current_tti); + } +} +void LTE_fdd_enb_mac::handle_pucch_ack_nack(LTE_fdd_enb_user *user, + uint32 current_tti, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_MAC_PDU_STRUCT mac_pdu; + LIBLTE_PHY_ALLOCATION_STRUCT alloc; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, __LINE__, - "Not handling PUCCH_DECODE"); + "PUCCH ACK/NACK received for %u RNTI=%u", + current_tti, + user->get_c_rnti()); + + if(msg->msg[0]) + { + user->clear_harq_info(current_tti); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MAC, + __FILE__, + __LINE__, + "Clearing HARQ info RNTI=%u TTI=%u", + user->get_c_rnti(), + current_tti); + }else{ + if(LTE_FDD_ENB_ERROR_NONE == user->get_harq_info(current_tti, + &mac_pdu, + &alloc)) + { + if(LTE_FDD_ENB_MAX_HARQ_RETX <= alloc.harq_retx_count) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MAC, + __FILE__, + __LINE__, + "Not resending HARQ due to max retx RNTI=%u TTI=%u", + user->get_c_rnti(), + current_tti); + }else{ + alloc.harq_retx_count++; + alloc.ndi = user->get_dl_ndi(); + if(LTE_FDD_ENB_ERROR_NONE == add_to_dl_sched_queue(add_to_tti(sched_dl_subfr[sched_cur_dl_subfn].current_tti, + 4), + &mac_pdu, + &alloc)) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MAC, + __FILE__, + __LINE__, + "Resending HARQ info RNTI=%u TTI=%u (%u)", + user->get_c_rnti(), + current_tti, + alloc.harq_retx_count); + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MAC, + __FILE__, + __LINE__, + "Failed to resend HARQ info RNTI=%u TTI=%u", + user->get_c_rnti(), + current_tti); + } + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MAC, + __FILE__, + __LINE__, + "Failed to find HARQ info RNTI=%u TTI=%u", + user->get_c_rnti(), + current_tti); + } + } +} +void LTE_fdd_enb_mac::handle_pucch_sr(LTE_fdd_enb_user *user, + uint32 current_tti, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + if(msg->msg[0]) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MAC, + __FILE__, + __LINE__, + "PUCCH SR received for %u RNTI=%u", + current_tti, + user->get_c_rnti()); + + // Schedule a grant big enough to at least hold long BSR + sched_ul(user, BSR_GRANT_SIZE_BYTES*8); + } } void LTE_fdd_enb_mac::handle_pusch_decode(LTE_FDD_ENB_PUSCH_DECODE_MSG_STRUCT *pusch_decode) { - LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); - LTE_fdd_enb_user *user = NULL; - uint32 i; + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + LTE_fdd_enb_user *user = NULL; + LIBLTE_MAC_PDU_STRUCT mac_pdu; + uint32 i; // Find the user if(LTE_FDD_ENB_ERROR_NONE == user_mgr->find_user(pusch_decode->rnti, &user)) { + // Reset the C-RNTI release timer + user_mgr->reset_c_rnti_timer(pusch_decode->rnti); + + // Reset the inactivity timer + user->reset_inactivity_timer(LTE_FDD_ENB_USER_INACTIVITY_TIMER_VALUE_MS); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, @@ -429,39 +626,40 @@ void LTE_fdd_enb_mac::handle_pusch_decode(LTE_FDD_ENB_PUSCH_DECODE_MSG_STRUCT *p "PUSCH decode for RNTI=%u CURRENT_TTI=%u", pusch_decode->rnti, pusch_decode->current_tti); - interface->send_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_UL, - pusch_decode->rnti, - pusch_decode->current_tti, - pusch_decode->msg.msg, - pusch_decode->msg.N_bits); + interface->send_lte_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_UL, + pusch_decode->rnti, + pusch_decode->current_tti, + pusch_decode->msg.msg, + pusch_decode->msg.N_bits); // Set the correct channel type - user->pusch_mac_pdu.chan_type = LIBLTE_MAC_CHAN_TYPE_ULSCH; + mac_pdu.chan_type = LIBLTE_MAC_CHAN_TYPE_ULSCH; // Unpack MAC PDU liblte_mac_unpack_mac_pdu(&pusch_decode->msg, - &user->pusch_mac_pdu); + false, // Simultaneous PUCCH/PUSCH + &mac_pdu); - for(i=0; ipusch_mac_pdu.N_subheaders; i++) + for(i=0; ipusch_mac_pdu.subheader[i].lcid) + if(LIBLTE_MAC_ULSCH_CCCH_LCID == mac_pdu.subheader[i].lcid) { - handle_ulsch_ccch_sdu(user, user->pusch_mac_pdu.subheader[i].lcid, &user->pusch_mac_pdu.subheader[i].payload.sdu); - }else if(LIBLTE_MAC_ULSCH_DCCH_LCID_BEGIN <= user->pusch_mac_pdu.subheader[i].lcid && - LIBLTE_MAC_ULSCH_DCCH_LCID_END >= user->pusch_mac_pdu.subheader[i].lcid){ - handle_ulsch_dcch_sdu(user, user->pusch_mac_pdu.subheader[i].lcid, &user->pusch_mac_pdu.subheader[i].payload.sdu); - }else if(LIBLTE_MAC_ULSCH_EXT_POWER_HEADROOM_REPORT_LCID == user->pusch_mac_pdu.subheader[i].lcid){ - handle_ulsch_ext_power_headroom_report(user, &user->pusch_mac_pdu.subheader[i].payload.ext_power_headroom); - }else if(LIBLTE_MAC_ULSCH_POWER_HEADROOM_REPORT_LCID == user->pusch_mac_pdu.subheader[i].lcid){ - handle_ulsch_power_headroom_report(user, &user->pusch_mac_pdu.subheader[i].payload.power_headroom); - }else if(LIBLTE_MAC_ULSCH_C_RNTI_LCID == user->pusch_mac_pdu.subheader[i].lcid){ - handle_ulsch_c_rnti(&user, &user->pusch_mac_pdu.subheader[i].payload.c_rnti); - }else if(LIBLTE_MAC_ULSCH_TRUNCATED_BSR_LCID == user->pusch_mac_pdu.subheader[i].lcid){ - handle_ulsch_truncated_bsr(user, &user->pusch_mac_pdu.subheader[i].payload.truncated_bsr); - }else if(LIBLTE_MAC_ULSCH_SHORT_BSR_LCID == user->pusch_mac_pdu.subheader[i].lcid){ - handle_ulsch_short_bsr(user, &user->pusch_mac_pdu.subheader[i].payload.short_bsr); - }else if(LIBLTE_MAC_ULSCH_LONG_BSR_LCID == user->pusch_mac_pdu.subheader[i].lcid){ - handle_ulsch_long_bsr(user, &user->pusch_mac_pdu.subheader[i].payload.long_bsr); + handle_ulsch_ccch_sdu(user, mac_pdu.subheader[i].lcid, &mac_pdu.subheader[i].payload.sdu); + }else if(LIBLTE_MAC_ULSCH_DCCH_LCID_BEGIN <= mac_pdu.subheader[i].lcid && + LIBLTE_MAC_ULSCH_DCCH_LCID_END >= mac_pdu.subheader[i].lcid){ + handle_ulsch_dcch_sdu(user, mac_pdu.subheader[i].lcid, &mac_pdu.subheader[i].payload.sdu); + }else if(LIBLTE_MAC_ULSCH_EXT_POWER_HEADROOM_REPORT_LCID == mac_pdu.subheader[i].lcid){ + handle_ulsch_ext_power_headroom_report(user, &mac_pdu.subheader[i].payload.ext_power_headroom); + }else if(LIBLTE_MAC_ULSCH_POWER_HEADROOM_REPORT_LCID == mac_pdu.subheader[i].lcid){ + handle_ulsch_power_headroom_report(user, &mac_pdu.subheader[i].payload.power_headroom); + }else if(LIBLTE_MAC_ULSCH_C_RNTI_LCID == mac_pdu.subheader[i].lcid){ + handle_ulsch_c_rnti(&user, &mac_pdu.subheader[i].payload.c_rnti); + }else if(LIBLTE_MAC_ULSCH_TRUNCATED_BSR_LCID == mac_pdu.subheader[i].lcid){ + handle_ulsch_truncated_bsr(user, &mac_pdu.subheader[i].payload.truncated_bsr); + }else if(LIBLTE_MAC_ULSCH_SHORT_BSR_LCID == mac_pdu.subheader[i].lcid){ + handle_ulsch_short_bsr(user, &mac_pdu.subheader[i].payload.short_bsr); + }else if(LIBLTE_MAC_ULSCH_LONG_BSR_LCID == mac_pdu.subheader[i].lcid){ + handle_ulsch_long_bsr(user, &mac_pdu.subheader[i].payload.long_bsr); } } }else{ @@ -482,9 +680,8 @@ void LTE_fdd_enb_mac::handle_sdu_ready(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT *sdu { LTE_fdd_enb_user *user; LIBLTE_MAC_PDU_STRUCT mac_pdu; - LIBLTE_PHY_ALLOCATION_STRUCT alloc; - LIBLTE_BIT_MSG_STRUCT *sdu; - uint32 current_tti; + LIBLTE_PHY_ALLOCATION_STRUCT alloc = {0}; + LIBLTE_BYTE_MSG_STRUCT *sdu; if(LTE_FDD_ENB_ERROR_NONE == sdu_ready->rb->get_next_mac_sdu(&sdu)) { @@ -505,30 +702,39 @@ void LTE_fdd_enb_mac::handle_sdu_ready(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT *sdu alloc.chan_type = LIBLTE_PHY_CHAN_TYPE_DLSCH; alloc.rv_idx = 0; alloc.N_codewords = 1; - sys_info_mutex.lock(); + sem_wait(&sys_info_sem); if(1 == sys_info.N_ant) { alloc.tx_mode = 1; }else{ alloc.tx_mode = 2; } - sys_info_mutex.unlock(); + sem_post(&sys_info_sem); alloc.rnti = user->get_c_rnti(); - alloc.mcs = 0; alloc.tpc = LIBLTE_PHY_TPC_COMMAND_DCI_1_1A_1B_1D_2_3_DB_ZERO; - alloc.ndi = false; - - // Pack the SDU - mac_pdu.chan_type = LIBLTE_MAC_CHAN_TYPE_DLSCH; - mac_pdu.N_subheaders = 1; - mac_pdu.subheader[0].lcid = sdu_ready->rb->get_rb_id(); - memcpy(&mac_pdu.subheader[0].payload.sdu, sdu, sizeof(LIBLTE_BIT_MSG_STRUCT)); + alloc.ndi = user->get_dl_ndi(); + user->flip_dl_ndi(); + alloc.harq_retx_count = 0; - // Determine the current_tti - current_tti = (sched_dl_subfr[sched_cur_dl_subfn].current_tti + 4) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + // Pack the PDU + mac_pdu.chan_type = LIBLTE_MAC_CHAN_TYPE_DLSCH; + if(sdu_ready->rb->get_send_con_res_id()) + { + mac_pdu.N_subheaders = 2; + mac_pdu.subheader[0].lcid = LIBLTE_MAC_DLSCH_UE_CONTENTION_RESOLUTION_ID_LCID; + mac_pdu.subheader[0].payload.ue_con_res_id.id = sdu_ready->rb->get_con_res_id(); + mac_pdu.subheader[1].lcid = sdu_ready->rb->get_rb_id(); + memcpy(&mac_pdu.subheader[1].payload.sdu, sdu, sizeof(LIBLTE_BYTE_MSG_STRUCT)); + sdu_ready->rb->set_send_con_res_id(false); + }else{ + mac_pdu.N_subheaders = 1; + mac_pdu.subheader[0].lcid = sdu_ready->rb->get_rb_id(); + memcpy(&mac_pdu.subheader[0].payload.sdu, sdu, sizeof(LIBLTE_BYTE_MSG_STRUCT)); + } - // Add the SDU to the scheduling queue - if(LTE_FDD_ENB_ERROR_NONE != add_to_dl_sched_queue(current_tti, + // Add the PDU to the scheduling queue + if(LTE_FDD_ENB_ERROR_NONE != add_to_dl_sched_queue(add_to_tti(sched_dl_subfr[sched_cur_dl_subfn].current_tti, + 4), &mac_pdu, &alloc)) { @@ -536,14 +742,14 @@ void LTE_fdd_enb_mac::handle_sdu_ready(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT *sdu LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, __LINE__, - "Can't schedule SDU"); + "Can't schedule PDU"); }else{ interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, __LINE__, - &alloc.msg, - "SDU scheduled for RNTI=%u, DL_QUEUE_SIZE=%u", + &alloc.msg[0], + "PDU scheduled for RNTI=%u, DL_QUEUE_SIZE=%u", alloc.rnti, dl_sched_queue.size()); } @@ -562,15 +768,13 @@ void LTE_fdd_enb_mac::handle_sdu_ready(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT *sdu /**************************/ /* MAC PDU Handlers */ /**************************/ -void LTE_fdd_enb_mac::handle_ulsch_ccch_sdu(LTE_fdd_enb_user *user, - uint32 lcid, - LIBLTE_BIT_MSG_STRUCT *sdu) +void LTE_fdd_enb_mac::handle_ulsch_ccch_sdu(LTE_fdd_enb_user *user, + uint32 lcid, + LIBLTE_BYTE_MSG_STRUCT *sdu) { LTE_fdd_enb_rb *rb = NULL; LTE_FDD_ENB_RLC_PDU_READY_MSG_STRUCT rlc_pdu_ready; - LIBLTE_MAC_PDU_STRUCT mac_pdu; - LIBLTE_PHY_ALLOCATION_STRUCT alloc; - uint32 current_tti; + uint64 con_res_id; uint32 i; if(LIBLTE_MAC_ULSCH_CCCH_LCID == lcid) @@ -587,71 +791,32 @@ void LTE_fdd_enb_mac::handle_ulsch_ccch_sdu(LTE_fdd_enb_user *user, // Get SRB0 user->get_srb0(&rb); - // Fill in the contention resolution allocation - alloc.pre_coder_type = LIBLTE_PHY_PRE_CODER_TYPE_TX_DIVERSITY; - alloc.mod_type = LIBLTE_PHY_MODULATION_TYPE_QPSK; - alloc.chan_type = LIBLTE_PHY_CHAN_TYPE_DLSCH; - alloc.rv_idx = 0; - alloc.N_codewords = 1; - sys_info_mutex.lock(); - if(1 == sys_info.N_ant) - { - alloc.tx_mode = 1; - }else{ - alloc.tx_mode = 2; - } - sys_info_mutex.unlock(); - alloc.rnti = user->get_c_rnti(); - alloc.mcs = 0; - alloc.tpc = LIBLTE_PHY_TPC_COMMAND_DCI_1_1A_1B_1D_2_3_DB_ZERO; - alloc.ndi = false; - - // Pack the contention resolution PDU - mac_pdu.chan_type = LIBLTE_MAC_CHAN_TYPE_DLSCH; - mac_pdu.N_subheaders = 1; - mac_pdu.subheader[0].lcid = LIBLTE_MAC_DLSCH_UE_CONTENTION_RESOLUTION_ID_LCID; - mac_pdu.subheader[0].payload.ue_con_res_id.id = 0; - for(i=0; iN_bits; i++) + // Save the contention resolution ID + con_res_id = 0; + for(i=0; iN_bytes; i++) { - mac_pdu.subheader[0].payload.ue_con_res_id.id <<= 1; - mac_pdu.subheader[0].payload.ue_con_res_id.id |= sdu->msg[i]; - } - - // Determine the contention resolution current_tti - current_tti = (sched_dl_subfr[sched_cur_dl_subfn].current_tti + 4) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - - // Add the contention resolution PDU to the scheduling queue - if(LTE_FDD_ENB_ERROR_NONE != add_to_dl_sched_queue(current_tti, - &mac_pdu, - &alloc)) - { - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, - LTE_FDD_ENB_DEBUG_LEVEL_MAC, - __FILE__, - __LINE__, - "Can't schedule PDU"); - }else{ - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, - LTE_FDD_ENB_DEBUG_LEVEL_MAC, - __FILE__, - __LINE__, - &alloc.msg, - "PDU scheduled for RNTI=%u, DL_QUEUE_SIZE=%u", - alloc.rnti, - dl_sched_queue.size()); + con_res_id <<= 8; + con_res_id |= sdu->msg[i]; } + rb->set_con_res_id(con_res_id); + rb->set_send_con_res_id(true); - // Queue the SDU for RLC + // Queue the PDU for RLC rb->queue_rlc_pdu(sdu); // Signal RLC rlc_pdu_ready.user = user; rlc_pdu_ready.rb = rb; - LTE_fdd_enb_msgq::send(mac_rlc_mq, - LTE_FDD_ENB_MESSAGE_TYPE_RLC_PDU_READY, - LTE_FDD_ENB_DEST_LAYER_RLC, - (LTE_FDD_ENB_MESSAGE_UNION *)&rlc_pdu_ready, - sizeof(LTE_FDD_ENB_RLC_PDU_READY_MSG_STRUCT)); + msgq_to_rlc->send(LTE_FDD_ENB_MESSAGE_TYPE_RLC_PDU_READY, + LTE_FDD_ENB_DEST_LAYER_RLC, + (LTE_FDD_ENB_MESSAGE_UNION *)&rlc_pdu_ready, + sizeof(LTE_FDD_ENB_RLC_PDU_READY_MSG_STRUCT)); + + // Update the uplink buffer size + user->update_ul_buffer_size(sdu->N_bytes); + + // Schedule uplink + sched_ul(user, user->get_ul_buffer_size()*8); }else{ interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_MAC, @@ -663,9 +828,9 @@ void LTE_fdd_enb_mac::handle_ulsch_ccch_sdu(LTE_fdd_enb_user *user, lcid); } } -void LTE_fdd_enb_mac::handle_ulsch_dcch_sdu(LTE_fdd_enb_user *user, - uint32 lcid, - LIBLTE_BIT_MSG_STRUCT *sdu) +void LTE_fdd_enb_mac::handle_ulsch_dcch_sdu(LTE_fdd_enb_user *user, + uint32 lcid, + LIBLTE_BYTE_MSG_STRUCT *sdu) { LTE_fdd_enb_rb *rb = NULL; LTE_FDD_ENB_RLC_PDU_READY_MSG_STRUCT rlc_pdu_ready; @@ -688,7 +853,7 @@ void LTE_fdd_enb_mac::handle_ulsch_dcch_sdu(LTE_fdd_enb_user *user, user->get_srb1(&rb); }else if(LTE_FDD_ENB_RB_SRB2 == lcid){ user->get_srb2(&rb); - }else{ + }else if(LTE_FDD_ENB_ERROR_NONE != user->get_drb((LTE_FDD_ENB_RB_ENUM)lcid, &rb)){ interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, @@ -706,12 +871,17 @@ void LTE_fdd_enb_mac::handle_ulsch_dcch_sdu(LTE_fdd_enb_user *user, // Signal RLC rlc_pdu_ready.user = user; rlc_pdu_ready.rb = rb; - LTE_fdd_enb_msgq::send(mac_rlc_mq, - LTE_FDD_ENB_MESSAGE_TYPE_RLC_PDU_READY, - LTE_FDD_ENB_DEST_LAYER_RLC, - (LTE_FDD_ENB_MESSAGE_UNION *)&rlc_pdu_ready, - sizeof(LTE_FDD_ENB_RLC_PDU_READY_MSG_STRUCT)); + msgq_to_rlc->send(LTE_FDD_ENB_MESSAGE_TYPE_RLC_PDU_READY, + LTE_FDD_ENB_DEST_LAYER_RLC, + (LTE_FDD_ENB_MESSAGE_UNION *)&rlc_pdu_ready, + sizeof(LTE_FDD_ENB_RLC_PDU_READY_MSG_STRUCT)); } + + // Update the uplink buffer size + user->update_ul_buffer_size(sdu->N_bytes); + + // Schedule uplink + sched_ul(user, user->get_ul_buffer_size()*8); }else{ interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_MAC, @@ -755,42 +925,73 @@ void LTE_fdd_enb_mac::handle_ulsch_c_rnti(LTE_fdd_enb_user **user, c_rnti->c_rnti, (*user)->get_c_rnti()); - if(c_rnti->c_rnti != (*user)->get_c_rnti()) + if(c_rnti->c_rnti != (*user)->get_c_rnti() && + LTE_FDD_ENB_ERROR_NONE == user_mgr->find_user(c_rnti->c_rnti, user)) { - user_mgr->find_user(c_rnti->c_rnti, user); - user_mgr->del_user(old_c_rnti); + user_mgr->release_c_rnti(old_c_rnti); } } void LTE_fdd_enb_mac::handle_ulsch_truncated_bsr(LTE_fdd_enb_user *user, LIBLTE_MAC_TRUNCATED_BSR_CE_STRUCT *truncated_bsr) { - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, __LINE__, - "Not handling ULSCH TRUNCATED_BSR"); + "Received truncated BSR for LCG_ID=%u (%u < Buffer Size <= %u), C_RNTI=%u", + truncated_bsr->lcg_id, + truncated_bsr->min_buffer_size, + truncated_bsr->max_buffer_size, + user->get_c_rnti()); + + user->set_ul_buffer_size(truncated_bsr->max_buffer_size); + + sched_ul(user, truncated_bsr->max_buffer_size*8); } void LTE_fdd_enb_mac::handle_ulsch_short_bsr(LTE_fdd_enb_user *user, LIBLTE_MAC_SHORT_BSR_CE_STRUCT *short_bsr) { - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, __LINE__, - "Not handling ULSCH SHORT_BSR"); + "Received short BSR for LCG_ID=%u (%u < Buffer Size <= %u), C_RNTI=%u", + short_bsr->lcg_id, + short_bsr->min_buffer_size, + short_bsr->max_buffer_size, + user->get_c_rnti()); + + user->set_ul_buffer_size(short_bsr->max_buffer_size); + + sched_ul(user, short_bsr->max_buffer_size*8); } void LTE_fdd_enb_mac::handle_ulsch_long_bsr(LTE_fdd_enb_user *user, LIBLTE_MAC_LONG_BSR_CE_STRUCT *long_bsr) { - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, __LINE__, - "Not handling ULSCH LONG_BSR %u %u %u %u", - long_bsr->buffer_size_0, - long_bsr->buffer_size_1, - long_bsr->buffer_size_2, - long_bsr->buffer_size_3); + "Received long BSR (%u < Buffer Size 0 <= %u), (%u < Buffer Size 1 <= %u), (%u < Buffer Size 2 <= %u), (%u < Buffer Size 3 <= %u), C_RNTI=%u", + long_bsr->min_buffer_size_0, + long_bsr->max_buffer_size_0, + long_bsr->min_buffer_size_1, + long_bsr->max_buffer_size_1, + long_bsr->min_buffer_size_2, + long_bsr->max_buffer_size_2, + long_bsr->min_buffer_size_3, + long_bsr->max_buffer_size_3, + user->get_c_rnti()); + + user->set_ul_buffer_size(long_bsr->max_buffer_size_0 + + long_bsr->max_buffer_size_1 + + long_bsr->max_buffer_size_2 + + long_bsr->max_buffer_size_3); + + sched_ul(user, (long_bsr->max_buffer_size_0 + + long_bsr->max_buffer_size_1 + + long_bsr->max_buffer_size_2 + + long_bsr->max_buffer_size_3)*8); } /***************************/ @@ -800,15 +1001,18 @@ void LTE_fdd_enb_mac::construct_random_access_response(uint8 preamble, uint16 timing_adv, uint32 current_tti) { - LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + LTE_fdd_enb_user *user = NULL; LIBLTE_MAC_RAR_STRUCT rar; LIBLTE_PHY_ALLOCATION_STRUCT dl_alloc; LIBLTE_PHY_ALLOCATION_STRUCT ul_alloc; - // Allocate a C-RNTI and a user - if(LTE_FDD_ENB_ERROR_NONE == user_mgr->get_free_c_rnti(&rar.temp_c_rnti) && - LTE_FDD_ENB_ERROR_NONE == user_mgr->add_user(rar.temp_c_rnti)) + // Allocate a user + if(LTE_FDD_ENB_ERROR_NONE == user_mgr->add_user(&user)) { + // Save C-RNTI + rar.temp_c_rnti = user->get_c_rnti(); + // Fill in the DL allocation dl_alloc.pre_coder_type = LIBLTE_PHY_PRE_CODER_TYPE_TX_DIVERSITY; dl_alloc.mod_type = LIBLTE_PHY_MODULATION_TYPE_QPSK; @@ -827,13 +1031,13 @@ void LTE_fdd_enb_mac::construct_random_access_response(uint8 preamble, ul_alloc.N_layers = 1; ul_alloc.tx_mode = 1; // From 36.213 v10.3.0 section 7.1 ul_alloc.rnti = rar.temp_c_rnti; - sys_info_mutex.lock(); + sem_wait(&sys_info_sem); liblte_phy_get_tbs_mcs_and_n_prb_for_ul(56, sys_info.N_rb_ul, &ul_alloc.tbs, &ul_alloc.mcs, &ul_alloc.N_prb); - sys_info_mutex.unlock(); + sem_post(&sys_info_sem); // Fill in the RAR rar.hdr_type = LIBLTE_MAC_RAR_HEADER_TYPE_RAPID; @@ -847,7 +1051,7 @@ void LTE_fdd_enb_mac::construct_random_access_response(uint8 preamble, // Temporarily pack the RAR to determine the number of bits needed liblte_mac_pack_random_access_response_pdu(&rar, - &dl_alloc.msg); + &dl_alloc.msg[0]); // Add the RAR to the scheduling queue if(LTE_FDD_ENB_ERROR_NONE != add_to_rar_sched_queue(current_tti, @@ -880,30 +1084,103 @@ void LTE_fdd_enb_mac::construct_random_access_response(uint8 preamble, /*******************/ /* Scheduler */ /*******************/ +void LTE_fdd_enb_mac::sched_ul(LTE_fdd_enb_user *user, + uint32 requested_tbs) +{ + LIBLTE_PHY_ALLOCATION_STRUCT alloc; + uint32 bits_req = requested_tbs; + + if(requested_tbs != 0) + { + alloc.pre_coder_type = LIBLTE_PHY_PRE_CODER_TYPE_TX_DIVERSITY; + alloc.mod_type = LIBLTE_PHY_MODULATION_TYPE_QPSK; + alloc.chan_type = LIBLTE_PHY_CHAN_TYPE_ULSCH; + alloc.rv_idx = 0; + alloc.N_codewords = 1; + alloc.N_layers = 1; + alloc.tx_mode = 1; + alloc.rnti = user->get_c_rnti(); + alloc.tpc = LIBLTE_PHY_TPC_COMMAND_DCI_0_3_4_DB_NEG_1; + alloc.ndi = user->get_ul_ndi(); + user->flip_ul_ndi(); + if(bits_req > (user->get_max_ul_bytes_per_subfn()*8)) + { + bits_req = user->get_max_ul_bytes_per_subfn()*8; + } + sem_wait(&sys_info_sem); + liblte_phy_get_tbs_mcs_and_n_prb_for_ul(bits_req, + sys_info.N_rb_ul, + &alloc.tbs, + &alloc.mcs, + &alloc.N_prb); + sem_post(&sys_info_sem); + if(11 > alloc.mcs) + { + alloc.mod_type = LIBLTE_PHY_MODULATION_TYPE_QPSK; + }else if(21 > alloc.mcs){ + alloc.mod_type = LIBLTE_PHY_MODULATION_TYPE_16QAM; + }else{ + alloc.mod_type = LIBLTE_PHY_MODULATION_TYPE_64QAM; + } + + // Add the allocation to the scheduling queue + if(LTE_FDD_ENB_ERROR_NONE != add_to_ul_sched_queue(add_to_tti(sched_ul_subfr[sched_cur_ul_subfn].current_tti, + 4), + &alloc)) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MAC, + __FILE__, + __LINE__, + "Can't schedule UL"); + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MAC, + __FILE__, + __LINE__, + "UL scheduled (mcs=%u, tbs=%u, N_prb=%u) for RNTI=%u, UL_QUEUE_SIZE=%u", + alloc.mcs, + alloc.tbs, + alloc.N_prb, + alloc.rnti, + ul_sched_queue.size()); + } + } +} void LTE_fdd_enb_mac::scheduler(void) { - boost::mutex::scoped_lock lock(sys_info_mutex); - LTE_fdd_enb_phy *phy = LTE_fdd_enb_phy::get_instance(); - LTE_FDD_ENB_RAR_SCHED_QUEUE_STRUCT *rar_sched; - LTE_FDD_ENB_DL_SCHED_QUEUE_STRUCT *dl_sched; - LTE_FDD_ENB_UL_SCHED_QUEUE_STRUCT *ul_sched; - uint32 N_cce; - uint32 N_pad; - uint32 resp_win_start; - uint32 resp_win_stop; - uint32 i; - uint32 rb_start; - uint32 riv; - int32 N_avail_dl_prbs; - int32 N_avail_ul_prbs; - int32 N_avail_dcis; - bool sched_out_of_headroom; + libtools_scoped_lock lock(sys_info_sem); + LTE_fdd_enb_phy *phy = LTE_fdd_enb_phy::get_instance(); + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + LTE_fdd_enb_user *user; + std::list::iterator iter; + LTE_FDD_ENB_RAR_SCHED_QUEUE_STRUCT *rar_sched; + LTE_FDD_ENB_DL_SCHED_QUEUE_STRUCT *dl_sched; + LTE_FDD_ENB_UL_SCHED_QUEUE_STRUCT *ul_sched; + LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT *dl_subfr; + LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT *ul_subfr; + LIBTOOLS_IPC_MSGQ_RAR_PDU_MSG_STRUCT rar_pdu_msg; + LIBTOOLS_IPC_MSGQ_UL_ALLOC_MSG_STRUCT ul_alloc_msg; + uint32 N_cce; + uint32 N_pad; + uint32 resp_win_start; + uint32 resp_win_stop; + uint32 i; + uint32 rb_start; + uint32 riv; + uint32 mask; + uint32 sr_periodicity; + uint32 N_offset_sr; + int32 N_avail_dl_prbs; + int32 N_avail_ul_prbs; + int32 N_avail_dcis; + bool sched_out_of_headroom; // Get the number of CCEs for the next subframe N_cce = phy->get_n_cce(); // Schedule RAR for the next subframe - rar_sched_queue_mutex.lock(); + sem_wait(&rar_sched_queue_sem); sched_out_of_headroom = false; while(0 != rar_sched_queue.size() && false == sched_out_of_headroom) @@ -911,10 +1188,11 @@ void LTE_fdd_enb_mac::scheduler(void) rar_sched = rar_sched_queue.front(); // Determine when the response window starts - resp_win_start = (rar_sched->current_tti + 3) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + resp_win_start = add_to_tti(rar_sched->current_tti, 3); // Determine when the response window stops - resp_win_stop = (resp_win_start + liblte_rrc_ra_response_window_size_num[sys_info.sib2.rr_config_common_sib.rach_cnfg.ra_resp_win_size]) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + resp_win_stop = add_to_tti(resp_win_start, + liblte_rrc_ra_response_window_size_num[sys_info.sib2.rr_config_common_sib.rach_cnfg.ra_resp_win_size]); // Take into account the SFN wrap // FIXME: Test this @@ -933,13 +1211,16 @@ void LTE_fdd_enb_mac::scheduler(void) if(resp_win_start <= sched_dl_subfr[sched_cur_dl_subfn].current_tti && resp_win_stop >= sched_dl_subfr[sched_cur_dl_subfn].current_tti) { + dl_subfr = &sched_dl_subfr[sched_cur_dl_subfn]; + ul_subfr = &sched_ul_subfr[(sched_cur_dl_subfn+6)%10]; + // Determine how many PRBs are needed for the DL allocation, if using this subframe - interface->send_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, - rar_sched->dl_alloc.rnti, - sched_dl_subfr[sched_cur_dl_subfn].current_tti, - rar_sched->dl_alloc.msg.msg, - rar_sched->dl_alloc.msg.N_bits); - liblte_phy_get_tbs_mcs_and_n_prb_for_dl(rar_sched->dl_alloc.msg.N_bits, + interface->send_lte_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, + rar_sched->dl_alloc.rnti, + dl_subfr->current_tti, + rar_sched->dl_alloc.msg[0].msg, + rar_sched->dl_alloc.msg[0].N_bits); + liblte_phy_get_tbs_mcs_and_n_prb_for_dl(rar_sched->dl_alloc.msg[0].N_bits, sched_cur_dl_subfn, sys_info.N_rb_dl, rar_sched->dl_alloc.rnti, @@ -948,17 +1229,17 @@ void LTE_fdd_enb_mac::scheduler(void) &rar_sched->dl_alloc.N_prb); // Determine how many PRBs and DCIs are available in this subframe - N_avail_dl_prbs = sched_dl_subfr[sched_cur_dl_subfn].N_avail_prbs - sched_dl_subfr[sched_cur_dl_subfn].N_sched_prbs; - N_avail_ul_prbs = sched_ul_subfr[(sched_cur_ul_subfn+6)%10].N_avail_prbs - sched_ul_subfr[(sched_cur_ul_subfn+6)%10].N_sched_prbs; - N_avail_dcis = N_cce - (sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.N_alloc + sched_dl_subfr[sched_cur_dl_subfn].ul_allocations.N_alloc); + N_avail_dl_prbs = dl_subfr->N_avail_prbs - dl_subfr->N_sched_prbs; + N_avail_ul_prbs = ul_subfr->N_avail_prbs - ul_subfr->N_sched_prbs; + N_avail_dcis = N_cce - (dl_subfr->dl_allocations.N_alloc + dl_subfr->ul_allocations.N_alloc); if(rar_sched->dl_alloc.N_prb <= N_avail_dl_prbs && rar_sched->ul_alloc.N_prb <= N_avail_ul_prbs && 1 <= N_avail_dcis) { // Determine the RB start for the UL allocation - rb_start = sched_ul_subfr[(sched_cur_ul_subfn+6)%10].next_prb; - sched_ul_subfr[(sched_cur_ul_subfn+6)%10].next_prb += rar_sched->ul_alloc.N_prb; + rb_start = ul_subfr->next_prb; + ul_subfr->next_prb += rar_sched->ul_alloc.N_prb; // Fill in the PRBs for the UL allocation for(i=0; iul_alloc.N_prb; i++) @@ -976,34 +1257,47 @@ void LTE_fdd_enb_mac::scheduler(void) } // Fill in the RBA for the UL allocation - // FIXME: implement 36.213 v10.3.0 section 6.2 - rar_sched->rar.rba = riv & 0x3FF; + mask = 0; + for(i=0; i<(uint32)ceilf(logf(sys_info.N_rb_ul*(sys_info.N_rb_ul+1)/2)/logf(2)); i++) + { + mask = (mask << 1) | 1; + } + rar_sched->rar.rba = riv & mask; // Re-pack the RAR liblte_mac_pack_random_access_response_pdu(&rar_sched->rar, - &rar_sched->dl_alloc.msg); + &rar_sched->dl_alloc.msg[0]); interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, __LINE__, - &rar_sched->dl_alloc.msg, + &rar_sched->dl_alloc.msg[0], "RAR sent %u %u %u %u", resp_win_start, resp_win_stop, - sched_dl_subfr[sched_cur_dl_subfn].current_tti, - sched_ul_subfr[(sched_cur_dl_subfn+6)%10].current_tti); + dl_subfr->current_tti, + ul_subfr->current_tti); - // Schedule DL - memcpy(&sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.alloc[sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.N_alloc], - &rar_sched->dl_alloc, - sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); - sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.N_alloc++; - // Schedule UL decode 6 subframes from now - memcpy(&sched_ul_subfr[(sched_cur_dl_subfn+6)%10].decodes.alloc[sched_ul_subfr[(sched_cur_dl_subfn+6)%10].decodes.N_alloc], - &rar_sched->ul_alloc, - sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); - sched_ul_subfr[(sched_cur_dl_subfn+6)%10].decodes.N_alloc++; + if(NULL == msgq_to_ue) + { + // Schedule DL + memcpy(&dl_subfr->dl_allocations.alloc[dl_subfr->dl_allocations.N_alloc], + &rar_sched->dl_alloc, + sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); + dl_subfr->dl_allocations.N_alloc++; + // Schedule UL decode 6 subframes from now + memcpy(&ul_subfr->decodes.alloc[ul_subfr->decodes.N_alloc], + &rar_sched->ul_alloc, + sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); + ul_subfr->decodes.N_alloc++; + }else{ + memcpy(&rar_pdu_msg.msg, &rar_sched->dl_alloc.msg, sizeof(rar_pdu_msg.msg)); + rar_pdu_msg.tti = ul_subfr->current_tti; + msgq_to_ue->send(LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_RAR_PDU, + (LIBTOOLS_IPC_MSGQ_MESSAGE_UNION *)&rar_pdu_msg, + sizeof(rar_pdu_msg)); + } // Remove RAR from queue rar_sched_queue.pop_front(); @@ -1026,31 +1320,47 @@ void LTE_fdd_enb_mac::scheduler(void) break; } } - rar_sched_queue_mutex.unlock(); + sem_post(&rar_sched_queue_sem); // Schedule DL for the next subframe - dl_sched_queue_mutex.lock(); + sem_wait(&dl_sched_queue_sem); sched_out_of_headroom = false; while(0 != dl_sched_queue.size() && false == sched_out_of_headroom) { dl_sched = dl_sched_queue.front(); - if(dl_sched->current_tti == sched_dl_subfr[sched_cur_dl_subfn].current_tti) + if(dl_sched->current_tti >= sched_dl_subfr[sched_cur_dl_subfn].current_tti) { + dl_subfr = &sched_dl_subfr[sched_cur_dl_subfn]; + + // Determine how many PRBs and DCIs are available in this subframe + N_avail_dl_prbs = dl_subfr->N_avail_prbs - dl_subfr->N_sched_prbs; + N_avail_dcis = N_cce - (dl_subfr->dl_allocations.N_alloc + dl_subfr->ul_allocations.N_alloc); + // Pack the message and determine TBS liblte_mac_pack_mac_pdu(&dl_sched->mac_pdu, - &dl_sched->alloc.msg); - liblte_phy_get_tbs_and_n_prb_for_dl(dl_sched->alloc.msg.N_bits, - sys_info.N_rb_dl, - dl_sched->alloc.mcs, - &dl_sched->alloc.tbs, - &dl_sched->alloc.N_prb); + &dl_sched->alloc.msg[0]); + liblte_phy_get_tbs_mcs_and_n_prb_for_dl(dl_sched->alloc.msg[0].N_bits, + dl_subfr->current_tti % 10, + N_avail_dl_prbs, + dl_sched->alloc.rnti, + &dl_sched->alloc.tbs, + &dl_sched->alloc.mcs, + &dl_sched->alloc.N_prb); + if(10 > dl_sched->alloc.mcs) + { + dl_sched->alloc.mod_type = LIBLTE_PHY_MODULATION_TYPE_QPSK; + }else if(17 > dl_sched->alloc.mcs){ + dl_sched->alloc.mod_type = LIBLTE_PHY_MODULATION_TYPE_16QAM; + }else{ + dl_sched->alloc.mod_type = LIBLTE_PHY_MODULATION_TYPE_64QAM; + } // Pad and repack if needed - if(dl_sched->alloc.tbs > dl_sched->alloc.msg.N_bits) + if(dl_sched->alloc.tbs > dl_sched->alloc.msg[0].N_bits) { - N_pad = (dl_sched->alloc.tbs - dl_sched->alloc.msg.N_bits)/8; + N_pad = (dl_sched->alloc.tbs - dl_sched->alloc.msg[0].N_bits)/8; if(1 == N_pad) { @@ -1074,19 +1384,19 @@ void LTE_fdd_enb_mac::scheduler(void) } liblte_mac_pack_mac_pdu(&dl_sched->mac_pdu, - &dl_sched->alloc.msg); + &dl_sched->alloc.msg[0]); } // Send a PCAP message - interface->send_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, - dl_sched->alloc.rnti, - sched_dl_subfr[sched_cur_dl_subfn].current_tti, - dl_sched->alloc.msg.msg, - dl_sched->alloc.tbs); + interface->send_lte_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, + dl_sched->alloc.rnti, + dl_subfr->current_tti, + dl_sched->alloc.msg[0].msg, + dl_sched->alloc.tbs); // Determine how many PRBs and DCIs are available in this subframe - N_avail_dl_prbs = sched_dl_subfr[sched_cur_dl_subfn].N_avail_prbs - sched_dl_subfr[sched_cur_dl_subfn].N_sched_prbs; - N_avail_dcis = N_cce - (sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.N_alloc + sched_dl_subfr[sched_cur_dl_subfn].ul_allocations.N_alloc); + N_avail_dl_prbs = dl_subfr->N_avail_prbs - dl_subfr->N_sched_prbs; + N_avail_dcis = N_cce - (dl_subfr->dl_allocations.N_alloc + dl_subfr->ul_allocations.N_alloc); if(dl_sched->alloc.N_prb <= N_avail_dl_prbs && 1 <= N_avail_dcis) @@ -1095,45 +1405,87 @@ void LTE_fdd_enb_mac::scheduler(void) LTE_FDD_ENB_DEBUG_LEVEL_MAC, __FILE__, __LINE__, - &dl_sched->alloc.msg, - "DL allocation sent for RNTI=%u CURRENT_TTI=%u", + &dl_sched->alloc.msg[0], + "DL allocation (mcs=%u, tbs=%u, N_prb=%u) sent for RNTI=%u CURRENT_TTI=%u", + dl_sched->alloc.mcs, + dl_sched->alloc.tbs, + dl_sched->alloc.N_prb, dl_sched->alloc.rnti, - sched_dl_subfr[sched_cur_dl_subfn].current_tti); + dl_subfr->current_tti); - // Schedule DL - memcpy(&sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.alloc[sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.N_alloc], - &dl_sched->alloc, - sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); - sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.N_alloc++; + if(NULL == msgq_to_ue) + { + // Schedule DL + memcpy(&dl_subfr->dl_allocations.alloc[dl_subfr->dl_allocations.N_alloc], + &dl_sched->alloc, + sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); + dl_subfr->dl_allocations.N_alloc++; + + // Schedule ACK/NACK PUCCH 4 subframes from now and store the DL allocation for potential H-ARQ retransmission + ul_subfr = &sched_ul_subfr[(sched_cur_dl_subfn+4)%10]; + ul_subfr->pucch[ul_subfr->N_pucch].type = LTE_FDD_ENB_PUCCH_TYPE_ACK_NACK; + ul_subfr->pucch[ul_subfr->N_pucch].rnti = dl_sched->alloc.rnti; + ul_subfr->pucch[ul_subfr->N_pucch].n_1_p_pucch = sys_info.sib2.rr_config_common_sib.pucch_cnfg.n1_pucch_an; + ul_subfr->pucch[ul_subfr->N_pucch].decode = true; + ul_subfr->N_pucch++; + if(LTE_FDD_ENB_ERROR_NONE == user_mgr->find_user(dl_sched->alloc.rnti, &user)) + { + user->store_harq_info(ul_subfr->current_tti, &dl_sched->mac_pdu, &dl_sched->alloc); + } + }else{ + msgq_to_ue->send(LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_MAC_PDU, + (LIBTOOLS_IPC_MSGQ_MESSAGE_UNION *)&dl_sched->alloc.msg, + sizeof(dl_sched->alloc.msg)); + } + + // Remove DL schedule from queue + dl_sched_queue.pop_front(); + delete dl_sched; + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MAC, + __FILE__, + __LINE__, + "DISCARDING DL MESSAGE %u %u %u %u", + dl_sched->alloc.N_prb, + N_avail_dl_prbs, + 1, + N_avail_dcis); // Remove DL schedule from queue dl_sched_queue.pop_front(); delete dl_sched; } + }else if(dl_sched->current_tti < sched_dl_subfr[sched_cur_dl_subfn].current_tti){ + // Remove DL schedule from queue + dl_sched_queue.pop_front(); + delete dl_sched; }else{ sched_out_of_headroom = true; } } - dl_sched_queue_mutex.unlock(); + sem_post(&dl_sched_queue_sem); // Schedule UL for the next subframe - ul_sched_queue_mutex.lock(); + sem_wait(&ul_sched_queue_sem); sched_out_of_headroom = false; while(0 != ul_sched_queue.size() && false == sched_out_of_headroom) { ul_sched = ul_sched_queue.front(); + dl_subfr = &sched_dl_subfr[sched_cur_dl_subfn]; + ul_subfr = &sched_ul_subfr[(sched_cur_dl_subfn+4)%10]; // Determine how many PRBs and DCIs are available in this subframe - N_avail_ul_prbs = sched_ul_subfr[(sched_cur_dl_subfn+4)%10].N_avail_prbs - sched_ul_subfr[(sched_cur_dl_subfn+4)%10].N_sched_prbs; - N_avail_dcis = N_cce - (sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.N_alloc + sched_dl_subfr[sched_cur_dl_subfn].ul_allocations.N_alloc); + N_avail_ul_prbs = ul_subfr->N_avail_prbs - ul_subfr->N_sched_prbs; + N_avail_dcis = N_cce - (dl_subfr->dl_allocations.N_alloc + dl_subfr->ul_allocations.N_alloc); if(ul_sched->alloc.N_prb <= N_avail_ul_prbs && 1 <= N_avail_dcis) { // Determine the RB start - rb_start = sched_ul_subfr[(sched_cur_dl_subfn+4)%10].next_prb; - sched_ul_subfr[(sched_cur_dl_subfn+4)%10].next_prb += ul_sched->alloc.N_prb; + rb_start = ul_subfr->next_prb; + ul_subfr->next_prb += ul_sched->alloc.N_prb; // Fill in the PRBs for(i=0; ialloc.N_prb; i++) @@ -1148,18 +1500,27 @@ void LTE_fdd_enb_mac::scheduler(void) __LINE__, "UL allocation sent for RNTI=%u CURRENT_TTI=%u", ul_sched->alloc.rnti, - sched_ul_subfr[(sched_cur_dl_subfn+4)%10].current_tti); - - // Schedule UL decode 4 subframes from now - memcpy(&sched_ul_subfr[(sched_cur_dl_subfn+4)%10].decodes.alloc[sched_ul_subfr[(sched_cur_dl_subfn+4)%10].decodes.N_alloc], - &ul_sched->alloc, - sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); - sched_ul_subfr[(sched_cur_dl_subfn+4)%10].decodes.N_alloc++; - // Schedule UL allocation - memcpy(&sched_dl_subfr[sched_cur_dl_subfn].ul_allocations.alloc[sched_dl_subfr[sched_cur_dl_subfn].ul_allocations.N_alloc], - &ul_sched->alloc, - sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); - sched_dl_subfr[sched_cur_dl_subfn].ul_allocations.N_alloc++; + ul_subfr->current_tti); + + if(NULL == msgq_to_ue) + { + // Schedule UL decode 4 subframes from now + memcpy(&ul_subfr->decodes.alloc[ul_subfr->decodes.N_alloc], + &ul_sched->alloc, + sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); + ul_subfr->decodes.N_alloc++; + // Schedule UL allocation + memcpy(&dl_subfr->ul_allocations.alloc[dl_subfr->ul_allocations.N_alloc], + &ul_sched->alloc, + sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); + dl_subfr->ul_allocations.N_alloc++; + }else{ + ul_alloc_msg.size = ul_sched->alloc.tbs; + ul_alloc_msg.tti = ul_subfr->current_tti; + msgq_to_ue->send(LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_UL_ALLOC, + (LIBTOOLS_IPC_MSGQ_MESSAGE_UNION *)&ul_alloc_msg, + sizeof(ul_alloc_msg)); + } // Remove UL schedule from queue ul_sched_queue.pop_front(); @@ -1168,7 +1529,24 @@ void LTE_fdd_enb_mac::scheduler(void) sched_out_of_headroom = true; } } - ul_sched_queue_mutex.unlock(); + sem_post(&ul_sched_queue_sem); + + // Schedule UL SR for the next subframe + sem_wait(&ul_sr_sched_queue_sem); + ul_subfr = &sched_ul_subfr[sched_cur_ul_subfn]; + for(iter=ul_sr_sched_queue.begin(); iter!=ul_sr_sched_queue.end(); iter++) + { + liblte_phy_pucch_map_sr_config_idx((*iter)->i_sr, &sr_periodicity, &N_offset_sr); + if(((ul_subfr->current_tti - N_offset_sr) % sr_periodicity) == 0) + { + ul_subfr->pucch[ul_subfr->N_pucch].type = LTE_FDD_ENB_PUCCH_TYPE_SR; + ul_subfr->pucch[ul_subfr->N_pucch].rnti = (*iter)->rnti; + ul_subfr->pucch[ul_subfr->N_pucch].n_1_p_pucch = (*iter)->n_1_p_pucch; + ul_subfr->pucch[ul_subfr->N_pucch].decode = true; + ul_subfr->N_pucch++; + } + } + sem_post(&ul_sr_sched_queue_sem); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_mac::add_to_rar_sched_queue(uint32 current_tti, LIBLTE_PHY_ALLOCATION_STRUCT *dl_alloc, @@ -1187,9 +1565,9 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_mac::add_to_rar_sched_queue(uint32 memcpy(&rar_sched->ul_alloc, ul_alloc, sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); memcpy(&rar_sched->rar, rar, sizeof(LIBLTE_MAC_RAR_STRUCT)); - rar_sched_queue_mutex.lock(); + sem_wait(&rar_sched_queue_sem); rar_sched_queue.push_back(rar_sched); - rar_sched_queue_mutex.unlock(); + sem_post(&rar_sched_queue_sem); err = LTE_FDD_ENB_ERROR_NONE; } @@ -1212,17 +1590,17 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_mac::add_to_dl_sched_queue(uint32 memcpy(&dl_sched->mac_pdu, mac_pdu, sizeof(LIBLTE_MAC_PDU_STRUCT)); memcpy(&dl_sched->alloc, alloc, sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); - dl_sched_queue_mutex.lock(); + sem_wait(&dl_sched_queue_sem); for(iter=dl_sched_queue.begin(); iter!=dl_sched_queue.end(); iter++) { if((*iter)->alloc.rnti == alloc->rnti && (*iter)->current_tti == dl_sched->current_tti) { - dl_sched->current_tti = (dl_sched->current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + dl_sched->current_tti = add_to_tti(dl_sched->current_tti, 1); } } dl_sched_queue.push_back(dl_sched); - dl_sched_queue_mutex.unlock(); + sem_post(&dl_sched_queue_sem); err = LTE_FDD_ENB_ERROR_NONE; } @@ -1235,6 +1613,7 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_mac::add_to_ul_sched_queue(uint32 std::list::iterator iter; LTE_FDD_ENB_UL_SCHED_QUEUE_STRUCT *ul_sched = NULL; LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_CANT_SCHEDULE; + bool sched = true; ul_sched = new LTE_FDD_ENB_UL_SCHED_QUEUE_STRUCT; @@ -1243,19 +1622,21 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_mac::add_to_ul_sched_queue(uint32 ul_sched->current_tti = current_tti; memcpy(&ul_sched->alloc, alloc, sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); - ul_sched_queue_mutex.lock(); + sem_wait(&ul_sched_queue_sem); for(iter=ul_sched_queue.begin(); iter!=ul_sched_queue.end(); iter++) { if((*iter)->alloc.rnti == alloc->rnti && (*iter)->current_tti == ul_sched->current_tti) { - ul_sched->current_tti = (ul_sched->current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + sched = false; } } - ul_sched_queue.push_back(ul_sched); - ul_sched_queue_mutex.unlock(); - - err = LTE_FDD_ENB_ERROR_NONE; + if(sched) + { + ul_sched_queue.push_back(ul_sched); + err = LTE_FDD_ENB_ERROR_NONE; + } + sem_post(&ul_sched_queue_sem); } return(err); @@ -1285,8 +1666,8 @@ uint32 LTE_fdd_enb_mac::get_n_reserved_prbs(uint32 current_tti) // Reserve PRBs for all other SIBs for(i=0; i current_tti && + tti_to_check < max_future_tti) + { + tti_in_future = true; + } + + return(tti_in_future); +} diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_main.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_main.cc old mode 100644 new mode 100755 index 072d50c..14a5750 --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_main.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_main.cc @@ -27,6 +27,7 @@ ---------- ------------- -------------------------------------------- 11/09/2013 Ben Wojtowicz Created file 06/15/2014 Ben Wojtowicz Omitting path from __FILE__. + 11/01/2014 Ben Wojtowicz Added config and user file support. *******************************************************************************/ @@ -35,6 +36,8 @@ *******************************************************************************/ #include "LTE_fdd_enb_interface.h" +#include "LTE_fdd_enb_cnfg_db.h" +#include "LTE_fdd_enb_hss.h" /******************************************************************************* DEFINES @@ -58,10 +61,16 @@ int main(int argc, char *argv[]) { LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); interface->set_ctrl_port(LTE_FDD_ENB_DEFAULT_CTRL_PORT); interface->start_ports(); + // Read configuration + hss->read_user_file(); + cnfg_db->read_cnfg_file(); + printf("*** LTE FDD ENB ***\n"); printf("Please connect to control port %u\n", LTE_FDD_ENB_DEFAULT_CTRL_PORT); diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_mme.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_mme.cc old mode 100644 new mode 100755 index dc1fdac..d1b1d0b --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_mme.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_mme.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_mme.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -28,6 +28,33 @@ 11/10/2013 Ben Wojtowicz Created file 01/18/2014 Ben Wojtowicz Added level to debug prints. 06/15/2014 Ben Wojtowicz Added RRC NAS message handler. + 08/03/2014 Ben Wojtowicz Added message parsers, state machines, and + message senders. + 09/03/2014 Ben Wojtowicz Added authentication and security support. + 11/01/2014 Ben Wojtowicz Added attach accept/complete, ESM info + transfer, and default bearer setup support. + 11/29/2014 Ben Wojtowicz Added service request, service reject, and + activate dedicated EPS bearer context + request support. + 12/16/2014 Ben Wojtowicz Added ol extension to message queue and + sending of EMM information message. + 12/24/2014 Ben Wojtowicz Actually sending EMM information message. + 02/15/2015 Ben Wojtowicz Moved to new message queue, added more debug + log points, and using the fixed user switch. + 03/11/2015 Ben Wojtowicz Added detach handling. + 07/25/2015 Ben Wojtowicz Using the latest liblte and changed the + dedicated bearer QoS to 9. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t and changed the user deletion and + C-RNTI release procedures. + 02/13/2016 Ben Wojtowicz Properly initialize present flags and change + the packet filter evaluation precedence in + activate dedicated EPS bearer context (thanks + to Pedro Batista for reporting this). + 07/03/2016 Ben Wojtowicz Fixed a bug when receiving a service request + message for a non-existent user. Thanks to + Peter Nguyen for finding this. + 07/29/2017 Ben Wojtowicz Moved away from singleton pattern. *******************************************************************************/ @@ -36,8 +63,12 @@ *******************************************************************************/ #include "LTE_fdd_enb_mme.h" -#include "LTE_fdd_enb_interface.h" +#include "LTE_fdd_enb_hss.h" +#include "LTE_fdd_enb_user_mgr.h" #include "liblte_mme.h" +#include "liblte_security.h" +#include "libtools_scoped_lock.h" +#include /******************************************************************************* DEFINES @@ -53,90 +84,73 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_enb_mme* LTE_fdd_enb_mme::instance = NULL; -boost::mutex mme_instance_mutex; /******************************************************************************* CLASS IMPLEMENTATIONS *******************************************************************************/ -/*******************/ -/* Singleton */ -/*******************/ -LTE_fdd_enb_mme* LTE_fdd_enb_mme::get_instance(void) -{ - boost::mutex::scoped_lock lock(mme_instance_mutex); - - if(NULL == instance) - { - instance = new LTE_fdd_enb_mme(); - } - - return(instance); -} -void LTE_fdd_enb_mme::cleanup(void) -{ - boost::mutex::scoped_lock lock(mme_instance_mutex); - - if(NULL != instance) - { - delete instance; - instance = NULL; - } -} - /********************************/ /* Constructor/Destructor */ /********************************/ LTE_fdd_enb_mme::LTE_fdd_enb_mme() { + sem_init(&start_sem, 0, 1); + sem_init(&sys_info_sem, 0, 1); started = false; } LTE_fdd_enb_mme::~LTE_fdd_enb_mme() { stop(); + sem_destroy(&sys_info_sem); + sem_destroy(&start_sem); } /********************/ /* Start/Stop */ /********************/ -void LTE_fdd_enb_mme::start(void) +void LTE_fdd_enb_mme::start(LTE_fdd_enb_msgq *from_rrc, + LTE_fdd_enb_msgq *to_rrc, + LTE_fdd_enb_interface *iface) { - boost::mutex::scoped_lock lock(start_mutex); - LTE_fdd_enb_msgq_cb rrc_cb(<E_fdd_enb_msgq_cb_wrapper, this); + libtools_scoped_lock lock(start_sem); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + LTE_fdd_enb_msgq_cb rrc_cb(<E_fdd_enb_msgq_cb_wrapper, this); if(!started) { + interface = iface; started = true; - rrc_comm_msgq = new LTE_fdd_enb_msgq("rrc_mme_mq", - rrc_cb); - mme_rrc_mq = new boost::interprocess::message_queue(boost::interprocess::open_only, - "mme_rrc_mq"); + msgq_from_rrc = from_rrc; + msgq_to_rrc = to_rrc; + msgq_from_rrc->attach_rx(rrc_cb); + + cnfg_db->get_param(LTE_FDD_ENB_PARAM_IP_ADDR_START, next_ip_addr); + cnfg_db->get_param(LTE_FDD_ENB_PARAM_DNS_ADDR, dns_addr); + next_ip_addr++; } } void LTE_fdd_enb_mme::stop(void) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_sem); if(started) { started = false; - delete rrc_comm_msgq; } } /***********************/ /* Communication */ /***********************/ -void LTE_fdd_enb_mme::handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) +void LTE_fdd_enb_mme::handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - - switch(msg->type) + switch(msg.type) { case LTE_FDD_ENB_MESSAGE_TYPE_MME_NAS_MSG_READY: - handle_nas_msg(&msg->msg.mme_nas_msg_ready); - delete msg; + handle_nas_msg(&msg.msg.mme_nas_msg_ready); + break; + case LTE_FDD_ENB_MESSAGE_TYPE_MME_RRC_CMD_RESP: + handle_rrc_cmd_resp(&msg.msg.mme_rrc_cmd_resp); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, @@ -144,8 +158,7 @@ void LTE_fdd_enb_mme::handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) __FILE__, __LINE__, "Received invalid RRC message %s", - LTE_fdd_enb_message_type_text[msg->type]); - delete msg; + LTE_fdd_enb_message_type_text[msg.type]); break; } } @@ -155,11 +168,10 @@ void LTE_fdd_enb_mme::handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) /****************************/ void LTE_fdd_enb_mme::update_sys_info(void) { - LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + libtools_scoped_lock lock(sys_info_sem); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); - sys_info_mutex.lock(); cnfg_db->get_sys_info(sys_info); - sys_info_mutex.unlock(); } /******************************/ @@ -167,15 +179,10 @@ void LTE_fdd_enb_mme::update_sys_info(void) /******************************/ void LTE_fdd_enb_mme::handle_nas_msg(LTE_FDD_ENB_MME_NAS_MSG_READY_MSG_STRUCT *nas_msg) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); LIBLTE_BYTE_MSG_STRUCT *msg; uint8 pd; uint8 msg_type; - // FIXME - LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; - LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; - if(LTE_FDD_ENB_ERROR_NONE == nas_msg->rb->get_next_mme_nas_msg(&msg)) { interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, @@ -187,65 +194,1707 @@ void LTE_fdd_enb_mme::handle_nas_msg(LTE_FDD_ENB_MME_NAS_MSG_READY_MSG_STRUCT *n nas_msg->user->get_c_rnti(), LTE_fdd_enb_rb_text[nas_msg->rb->get_rb_id()]); + // Parse the message liblte_mme_parse_msg_header(msg, &pd, &msg_type); + switch(msg_type) + { + case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: + parse_attach_complete(msg, nas_msg->user, nas_msg->rb); + break; + case LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST: + parse_attach_request(msg, &nas_msg->user, &nas_msg->rb); + break; + case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE: + parse_authentication_failure(msg, nas_msg->user, nas_msg->rb); + break; + case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: + parse_authentication_response(msg, nas_msg->user, nas_msg->rb); + break; + case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST: + parse_detach_request(msg, nas_msg->user, nas_msg->rb); + break; + case LIBLTE_MME_MSG_TYPE_EMM_STATUS: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling EMM Status"); + break; + case LIBLTE_MME_MSG_TYPE_EXTENDED_SERVICE_REQUEST: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Extended Service Request"); + break; + case LIBLTE_MME_MSG_TYPE_GUTI_REALLOCATION_COMPLETE: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling GUTI Reallocation Complete"); + break; + case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: + parse_identity_response(msg, nas_msg->user, nas_msg->rb); + break; + case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: + parse_security_mode_complete(msg, nas_msg->user, nas_msg->rb); + break; + case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_REJECT: + parse_security_mode_reject(msg, nas_msg->user, nas_msg->rb); + break; + case LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST: + parse_service_request(msg, nas_msg->user, nas_msg->rb); + break; + case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_COMPLETE: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Tracking Area Update Complete"); + break; + case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Tracking Area Update Request"); + break; + case LIBLTE_MME_MSG_TYPE_UPLINK_NAS_TRANSPORT: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Uplink NAS Transport"); + break; + case LIBLTE_MME_MSG_TYPE_UPLINK_GENERIC_NAS_TRANSPORT: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Uplink Generic NAS Transport"); + break; + case LIBLTE_MME_MSG_TYPE_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Activate Dedicated EPS Bearer Context Accept"); + break; + case LIBLTE_MME_MSG_TYPE_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Activate Dedicated EPS Bearer Context Reject"); + break; + case LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Activate Default EPS Bearer Context Accept"); + break; + case LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Activate Default EPS Bearer Context Reject"); + break; + case LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_ALLOCATION_REQUEST: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Bearer Resource Allocation Request"); + break; + case LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_MODIFICATION_REQUEST: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Bearer Resource Modification Request"); + break; + case LIBLTE_MME_MSG_TYPE_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Deactivate EPS Bearer Context Accept"); + break; + case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: + parse_esm_information_response(msg, nas_msg->user, nas_msg->rb); + break; + case LIBLTE_MME_MSG_TYPE_MODIFY_EPS_BEARER_CONTEXT_ACCEPT: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Modify EPS Bearer Context Accept"); + break; + case LIBLTE_MME_MSG_TYPE_MODIFY_EPS_BEARER_CONTEXT_REJECT: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling Modify EPS Bearer Context Reject"); + break; + case LIBLTE_MME_MSG_TYPE_PDN_CONNECTIVITY_REQUEST: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling PDN Connectivity Request"); + break; + case LIBLTE_MME_MSG_TYPE_PDN_DISCONNECT_REQUEST: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling PDN Disconnect Request"); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling NAS message with MSG_TYPE=%02X", + msg_type); + break; + } + + // Increment the uplink NAS count + nas_msg->user->increment_nas_count_ul(); - if(LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST == msg_type) + // Delete the NAS message + nas_msg->rb->delete_next_mme_nas_msg(); + + // Call the appropriate state machine + switch(nas_msg->rb->get_mme_procedure()) { - liblte_mme_unpack_attach_request_msg(msg, &attach_req); - liblte_mme_parse_msg_header(&attach_req.esm_msg, &pd, &msg_type); - if(LIBLTE_MME_MSG_TYPE_PDN_CONNECTIVITY_REQUEST == msg_type) + case LTE_FDD_ENB_MME_PROC_ATTACH: + attach_sm(nas_msg->user, nas_msg->rb); + break; + case LTE_FDD_ENB_MME_PROC_SERVICE_REQUEST: + service_req_sm(nas_msg->user, nas_msg->rb); + break; + case LTE_FDD_ENB_MME_PROC_DETACH: + detach_sm(nas_msg->user, nas_msg->rb); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "MME in invalid procedure %s", + LTE_fdd_enb_mme_proc_text[nas_msg->rb->get_mme_procedure()]); + break; + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received NAS message with no message queued"); + } +} +void LTE_fdd_enb_mme::handle_rrc_cmd_resp(LTE_FDD_ENB_MME_RRC_CMD_RESP_MSG_STRUCT *rrc_cmd_resp) +{ + switch(rrc_cmd_resp->cmd_resp) + { + case LTE_FDD_ENB_MME_RRC_CMD_RESP_SECURITY: + switch(rrc_cmd_resp->rb->get_mme_procedure()) + { + case LTE_FDD_ENB_MME_PROC_ATTACH: + if(rrc_cmd_resp->user->get_esm_info_transfer()) { - liblte_mme_unpack_pdn_connectivity_request_msg(&attach_req.esm_msg, &pdn_con_req); + rrc_cmd_resp->rb->set_mme_state(LTE_FDD_ENB_MME_STATE_ESM_INFO_TRANSFER); + attach_sm(rrc_cmd_resp->user, rrc_cmd_resp->rb); + }else{ + rrc_cmd_resp->rb->set_mme_state(LTE_FDD_ENB_MME_STATE_ATTACH_ACCEPT); + attach_sm(rrc_cmd_resp->user, rrc_cmd_resp->rb); + } + break; + case LTE_FDD_ENB_MME_PROC_SERVICE_REQUEST: + rrc_cmd_resp->rb->set_mme_state(LTE_FDD_ENB_MME_STATE_SETUP_DRB); + service_req_sm(rrc_cmd_resp->user, rrc_cmd_resp->rb); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "MME in invalid procedure %s", + LTE_fdd_enb_mme_proc_text[rrc_cmd_resp->rb->get_mme_procedure()]); + break; + } + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received invalid RRC command response %s", + LTE_fdd_enb_mme_rrc_cmd_resp_text[rrc_cmd_resp->cmd_resp]); + break; + } +} + +/*************************/ +/* Message Parsers */ +/*************************/ +void LTE_fdd_enb_mme::parse_attach_complete(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_comp; + uint8 pd; + uint8 msg_type; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received Attach Complete for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_attach_complete_msg(msg, &attach_comp); + + interface->send_ctrl_info_msg("user fully attached imsi=%s imei=%s", + user->get_imsi_str().c_str(), + user->get_imei_str().c_str()); + + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_ATTACHED); - if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI == attach_req.eps_mobile_id.type_of_id) + // Parse the ESM message + liblte_mme_parse_msg_header(&attach_comp.esm_msg, &pd, &msg_type); + switch(msg_type) + { + case LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT: + parse_activate_default_eps_bearer_context_accept(&attach_comp.esm_msg, user, rb); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling NAS message with MSG_TYPE=%02X", + msg_type); + break; + } +} +void LTE_fdd_enb_mme::parse_attach_request(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user **user, + LTE_fdd_enb_rb **rb) +{ + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + LTE_fdd_enb_user *act_user; + LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; + uint64 imsi_num = 0; + uint64 imei_num = 0; + uint32 i; + uint8 pd; + uint8 msg_type; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received Attach Request for RNTI=%u and RB=%s", + (*user)->get_c_rnti(), + LTE_fdd_enb_rb_text[(*rb)->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_attach_request_msg(msg, &attach_req); + + // Parse the ESM message + liblte_mme_parse_msg_header(&attach_req.esm_msg, &pd, &msg_type); + switch(msg_type) + { + case LIBLTE_MME_MSG_TYPE_PDN_CONNECTIVITY_REQUEST: + parse_pdn_connectivity_request(&attach_req.esm_msg, (*user), (*rb)); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Not handling NAS message with MSG_TYPE=%02X", + msg_type); + break; + } + + // Set the procedure + (*rb)->set_mme_procedure(LTE_FDD_ENB_MME_PROC_ATTACH); + + // Store the attach type + (*user)->set_attach_type(attach_req.eps_attach_type); + + // Store UE capabilities + for(i=0; i<8; i++) + { + (*user)->set_eea_support(i, attach_req.ue_network_cap.eea[i]); + (*user)->set_eia_support(i, attach_req.ue_network_cap.eia[i]); + } + if(attach_req.ue_network_cap.uea_present) + { + for(i=0; i<8; i++) + { + (*user)->set_uea_support(i, attach_req.ue_network_cap.uea[i]); + } + } + if(attach_req.ue_network_cap.uia_present) + { + for(i=1; i<8; i++) + { + (*user)->set_uia_support(i, attach_req.ue_network_cap.uia[i]); + } + } + if(attach_req.ms_network_cap_present) + { + for(i=1; i<8; i++) + { + (*user)->set_gea_support(i, attach_req.ms_network_cap.gea[i]); + } + } + + // Send an info message + if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI == attach_req.eps_mobile_id.type_of_id) + { + if(LTE_FDD_ENB_ERROR_NONE == user_mgr->find_user(&attach_req.eps_mobile_id.guti, &act_user)) + { + if(act_user != (*user)) + { + act_user->copy_rbs((*user)); + (*user)->clear_rbs(); + user_mgr->transfer_c_rnti(*user, act_user); + *user = act_user; + } + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "IMSI=%015llu is associated with RNTI=%u, RB=%s", + (*user)->get_id()->imsi, + (*user)->get_c_rnti(), + LTE_fdd_enb_rb_text[(*rb)->get_rb_id()]); + (*rb)->set_mme_state(LTE_FDD_ENB_MME_STATE_AUTHENTICATE); + }else{ + if((*user)->is_id_set()) + { + if((*user)->get_eea_support(0) && (*user)->get_eia_support(2)) { - interface->send_ctrl_info_msg("attach_request m_tmsi=%08X", - attach_req.eps_mobile_id.guti.m_tmsi); - }else if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI == attach_req.eps_mobile_id.type_of_id){ - interface->send_ctrl_info_msg("attach_request imsi=%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u", - attach_req.eps_mobile_id.imsi[0], - attach_req.eps_mobile_id.imsi[1], - attach_req.eps_mobile_id.imsi[2], - attach_req.eps_mobile_id.imsi[3], - attach_req.eps_mobile_id.imsi[4], - attach_req.eps_mobile_id.imsi[5], - attach_req.eps_mobile_id.imsi[6], - attach_req.eps_mobile_id.imsi[7], - attach_req.eps_mobile_id.imsi[8], - attach_req.eps_mobile_id.imsi[9], - attach_req.eps_mobile_id.imsi[10], - attach_req.eps_mobile_id.imsi[11], - attach_req.eps_mobile_id.imsi[12], - attach_req.eps_mobile_id.imsi[13], - attach_req.eps_mobile_id.imsi[14]); + (*rb)->set_mme_state(LTE_FDD_ENB_MME_STATE_AUTHENTICATE); }else{ - interface->send_ctrl_info_msg("attach_request imei=%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u", - attach_req.eps_mobile_id.imei[0], - attach_req.eps_mobile_id.imei[1], - attach_req.eps_mobile_id.imei[2], - attach_req.eps_mobile_id.imei[3], - attach_req.eps_mobile_id.imei[4], - attach_req.eps_mobile_id.imei[5], - attach_req.eps_mobile_id.imei[6], - attach_req.eps_mobile_id.imei[7], - attach_req.eps_mobile_id.imei[8], - attach_req.eps_mobile_id.imei[9], - attach_req.eps_mobile_id.imei[10], - attach_req.eps_mobile_id.imei[11], - attach_req.eps_mobile_id.imei[12], - attach_req.eps_mobile_id.imei[13], - attach_req.eps_mobile_id.imei[14]); + (*user)->set_emm_cause(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH); + (*rb)->set_mme_state(LTE_FDD_ENB_MME_STATE_REJECT); } + }else{ + (*rb)->set_mme_state(LTE_FDD_ENB_MME_STATE_ID_REQUEST_IMSI); } } + }else if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI == attach_req.eps_mobile_id.type_of_id){ + for(i=0; i<15; i++) + { + imsi_num *= 10; + imsi_num += attach_req.eps_mobile_id.imsi[i]; + } + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "IMSI=%015llu is associated with RNTI=%u, RB=%s", + imsi_num, + (*user)->get_c_rnti(), + LTE_fdd_enb_rb_text[(*rb)->get_rb_id()]); + if(hss->is_imsi_allowed(imsi_num)) + { + if((*user)->get_eea_support(0) && (*user)->get_eia_support(2)) + { + (*rb)->set_mme_state(LTE_FDD_ENB_MME_STATE_AUTHENTICATE); + (*user)->set_id(hss->get_user_id_from_imsi(imsi_num)); + }else{ + (*user)->set_emm_cause(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH); + (*rb)->set_mme_state(LTE_FDD_ENB_MME_STATE_REJECT); + } + }else{ + (*user)->set_temp_id(imsi_num); + (*rb)->set_mme_state(LTE_FDD_ENB_MME_STATE_REJECT); + } + }else{ + for(i=0; i<15; i++) + { + imei_num *= 10; + imei_num += attach_req.eps_mobile_id.imei[i]; + } + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "IMEI=%015llu is associated with RNTI=%u, RB=%s", + imei_num, + (*user)->get_c_rnti(), + LTE_fdd_enb_rb_text[(*rb)->get_rb_id()]); + if(hss->is_imei_allowed(imei_num)) + { + if((*user)->get_eea_support(0) && (*user)->get_eia_support(2)) + { + (*rb)->set_mme_state(LTE_FDD_ENB_MME_STATE_AUTHENTICATE); + (*user)->set_id(hss->get_user_id_from_imei(imei_num)); + }else{ + (*user)->set_emm_cause(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH); + (*rb)->set_mme_state(LTE_FDD_ENB_MME_STATE_REJECT); + } + }else{ + (*user)->set_temp_id(imei_num); + (*rb)->set_mme_state(LTE_FDD_ENB_MME_STATE_REJECT); + } + } +} +void LTE_fdd_enb_mme::parse_authentication_failure(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); + LIBLTE_MME_AUTHENTICATION_FAILURE_MSG_STRUCT auth_fail; - // Delete the NAS message - nas_msg->rb->delete_next_mme_nas_msg(); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received Authentication Failure for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_authentication_failure_msg(msg, &auth_fail); + + if(LIBLTE_MME_EMM_CAUSE_SYNCH_FAILURE == auth_fail.emm_cause && + auth_fail.auth_fail_param_present) + { + sem_wait(&sys_info_sem); + hss->security_resynch(user->get_id(), sys_info.mcc, sys_info.mnc, auth_fail.auth_fail_param); + sem_post(&sys_info_sem); }else{ interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, LTE_FDD_ENB_DEBUG_LEVEL_MME, __FILE__, __LINE__, - "Received NAS message with no message queued"); + "Authentication failure cause=%02X, RNTI=%u, RB=%s", + auth_fail.emm_cause, + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_RELEASE); + } +} +void LTE_fdd_enb_mme::parse_authentication_response(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); + LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT *auth_vec = NULL; + LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; + uint32 i; + bool res_match = true; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received Authentication Response for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_authentication_response_msg(msg, &auth_resp); + + // Check RES + auth_vec = hss->get_auth_vec(user->get_id()); + if(NULL != auth_vec) + { + res_match = true; + for(i=0; i<8; i++) + { + if(auth_vec->res[i] != auth_resp.res[i]) + { + res_match = false; + break; + } + } + + if(res_match) + { + interface->send_ctrl_info_msg("user authentication successful imsi=%s imei=%s", + user->get_imsi_str().c_str(), + user->get_imei_str().c_str()); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Authentication successful for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + user->set_auth_vec(auth_vec); + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_ENABLE_SECURITY); + }else{ + interface->send_ctrl_info_msg("user authentication rejected (RES MISMATCH) imsi=%s imei=%s", + user->get_imsi_str().c_str(), + user->get_imei_str().c_str()); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Authentication rejected (RES MISMATCH) for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_AUTH_REJECTED); + } + }else{ + interface->send_ctrl_info_msg("user authentication rejected (NO AUTH VEC) imsi=%s imei=%s", + user->get_imsi_str().c_str(), + user->get_imei_str().c_str()); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Authentication rejected (NO AUTH VEC) for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_AUTH_REJECTED); + } +} +void LTE_fdd_enb_mme::parse_detach_request(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT detach_req; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received Detach Request for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_detach_request_msg(msg, &detach_req); + + // Set the procedure + rb->set_mme_procedure(LTE_FDD_ENB_MME_PROC_DETACH); + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_SEND_DETACH_ACCEPT); + + // Delete the user + user->prepare_for_deletion(); +} +void LTE_fdd_enb_mme::parse_identity_response(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); + LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp; + uint64 imsi_num = 0; + uint64 imei_num = 0; + uint32 i; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received Identity Response for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_identity_response_msg(msg, &id_resp); + + // Store the ID + if(LIBLTE_MME_MOBILE_ID_TYPE_IMSI == id_resp.mobile_id.type_of_id) + { + for(i=0; i<15; i++) + { + imsi_num *= 10; + imsi_num += id_resp.mobile_id.imsi[i]; + } + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "IMSI=%015llu is associated with RNTI=%u, RB=%s", + imsi_num, + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + if(hss->is_imsi_allowed(imsi_num)) + { + if(user->get_eea_support(0) && user->get_eia_support(2)) + { + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_AUTHENTICATE); + user->set_id(hss->get_user_id_from_imsi(imsi_num)); + }else{ + user->set_emm_cause(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH); + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_REJECT); + } + }else{ + user->set_temp_id(imsi_num); + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_REJECT); + } + }else if(LIBLTE_MME_MOBILE_ID_TYPE_IMEI == id_resp.mobile_id.type_of_id){ + for(i=0; i<15; i++) + { + imei_num *= 10; + imei_num += id_resp.mobile_id.imei[i]; + } + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "IMEI=%015llu is associated with RNTI=%u, RB=%s", + imei_num, + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + if(hss->is_imei_allowed(imei_num)) + { + if(user->get_eea_support(0) && user->get_eia_support(2)) + { + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_AUTHENTICATE); + user->set_id(hss->get_user_id_from_imei(imei_num)); + }else{ + user->set_emm_cause(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH); + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_REJECT); + } + }else{ + user->set_temp_id(imei_num); + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_REJECT); + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Invalid ID_TYPE=%u", + id_resp.mobile_id.type_of_id); + } +} +void LTE_fdd_enb_mme::parse_security_mode_complete(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sec_mode_comp; + uint64 imei_num = 0; + uint32 i; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received Security Mode Complete for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_security_mode_complete_msg(msg, &sec_mode_comp); + + if(sec_mode_comp.imeisv_present) + { + if(LIBLTE_MME_MOBILE_ID_TYPE_IMEISV == sec_mode_comp.imeisv.type_of_id) + { + for(i=0; i<14; i++) + { + imei_num *= 10; + imei_num += sec_mode_comp.imeisv.imeisv[i]; + } + if((user->get_id()->imei/10) != imei_num) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received IMEI (%015llu) does not match stored IMEI (%015llu), RNTI=%u, RB=%s", + imei_num*10, + (user->get_id()->imei/10)*10, + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Security Mode Complete received with invalid ID type (%u), RNTI=%u, RB=%s", + sec_mode_comp.imeisv.type_of_id, + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + } + } + + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_RRC_SECURITY); +} +void LTE_fdd_enb_mme::parse_security_mode_reject(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT sec_mode_rej; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received Security Mode Reject for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_security_mode_reject_msg(msg, &sec_mode_rej); + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Security Mode Rejected cause=%02X, RNTI=%u, RB=%s", + sec_mode_rej.emm_cause, + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_RELEASE); +} +void LTE_fdd_enb_mme::parse_service_request(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); + LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT *auth_vec = user->get_auth_vec(); + LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT *hss_auth_vec; + LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT cmd_ready; + LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT service_req; + uint32 i; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received Service Request for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_service_request_msg(msg, &service_req); + + // Set the procedure + rb->set_mme_procedure(LTE_FDD_ENB_MME_PROC_SERVICE_REQUEST); + + // Verify KSI and sequence number + if(0 != service_req.ksi_and_seq_num.ksi) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Invalid KSI (%u) for RNTI=%u, RB=%s", + service_req.ksi_and_seq_num.ksi, + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + send_service_reject(user, rb, LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED); + + // Set the state + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_RELEASE); + }else{ + if(auth_vec->nas_count_ul != service_req.ksi_and_seq_num.seq_num) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Sequence number mismatch (rx=%u, stored=%u) for RNTI=%u, RB=%s", + service_req.ksi_and_seq_num.seq_num, + user->get_auth_vec()->nas_count_ul, + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Resolve sequence number mismatch + auth_vec->nas_count_ul = service_req.ksi_and_seq_num.seq_num; + hss_auth_vec = hss->regenerate_enb_security_data(user->get_id(), auth_vec->nas_count_ul); + if(NULL != hss_auth_vec) + { + for(i=0; i<32; i++) + { + auth_vec->k_rrc_enc[i] = hss_auth_vec->k_rrc_enc[i]; + auth_vec->k_rrc_int[i] = hss_auth_vec->k_rrc_int[i]; + } + } + } + + // Set the state + if(NULL != hss_auth_vec) + { + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_RRC_SECURITY); + }else{ + send_service_reject(user, rb, LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED); + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_RELEASE); + } + } +} +void LTE_fdd_enb_mme::parse_activate_default_eps_bearer_context_accept(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_def_eps_bearer_context_accept; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received Activate Default EPS Bearer Context Accept for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_activate_default_eps_bearer_context_accept_msg(msg, &act_def_eps_bearer_context_accept); + + interface->send_ctrl_info_msg("default bearer setup for imsi=%s imei=%s", + user->get_imsi_str().c_str(), + user->get_imei_str().c_str()); +} +void LTE_fdd_enb_mme::parse_esm_information_response(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT esm_info_resp; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received ESM Information Response for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_esm_information_response_msg(msg, &esm_info_resp); + + // FIXME + + rb->set_mme_state(LTE_FDD_ENB_MME_STATE_ATTACH_ACCEPT); +} +void LTE_fdd_enb_mme::parse_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT pco_resp; + uint32 i; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Received PDN Connectivity Request for RNTI=%u and RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Unpack the message + liblte_mme_unpack_pdn_connectivity_request_msg(msg, &pdn_con_req); + + // Store the EPS Bearer ID + user->set_eps_bearer_id(pdn_con_req.eps_bearer_id); + + // Store the Procedure Transaction ID + user->set_proc_transaction_id(pdn_con_req.proc_transaction_id); + + // Store the PDN Type + user->set_pdn_type(pdn_con_req.pdn_type); + + // Store the ESM Information Transfer Flag +// if(pdn_con_req.esm_info_transfer_flag_present && +// LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_REQUIRED == pdn_con_req.esm_info_transfer_flag) +// { +// user->set_esm_info_transfer(true); +// }else{ + user->set_esm_info_transfer(false); +// } + + if(pdn_con_req.protocol_cnfg_opts_present) + { + pco_resp.N_opts = 0; + for(i=0; i> 24) & 0xFF; + pco_resp.opt[pco_resp.N_opts].contents[7] = (dns_addr >> 16) & 0xFF; + pco_resp.opt[pco_resp.N_opts].contents[8] = (dns_addr >> 8) & 0xFF; + pco_resp.opt[pco_resp.N_opts].contents[9] = dns_addr & 0xFF; + pco_resp.opt[pco_resp.N_opts].contents[10] = 0x83; + pco_resp.opt[pco_resp.N_opts].contents[11] = 0x06; + pco_resp.opt[pco_resp.N_opts].contents[12] = (dns_addr >> 24) & 0xFF; + pco_resp.opt[pco_resp.N_opts].contents[13] = (dns_addr >> 16) & 0xFF; + pco_resp.opt[pco_resp.N_opts].contents[14] = (dns_addr >> 8) & 0xFF; + pco_resp.opt[pco_resp.N_opts].contents[15] = dns_addr & 0xFF; + pco_resp.N_opts++; + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Unknown PCO"); + } + }else if(LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_DNS_SERVER_IPV4_ADDRESS_REQUEST == pdn_con_req.protocol_cnfg_opts.opt[i].id){ + pco_resp.opt[pco_resp.N_opts].id = LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_DNS_SERVER_IPV4_ADDRESS; + pco_resp.opt[pco_resp.N_opts].len = 4; + pco_resp.opt[pco_resp.N_opts].contents[0] = (dns_addr >> 24) & 0xFF; + pco_resp.opt[pco_resp.N_opts].contents[1] = (dns_addr >> 16) & 0xFF; + pco_resp.opt[pco_resp.N_opts].contents[2] = (dns_addr >> 8) & 0xFF; + pco_resp.opt[pco_resp.N_opts].contents[3] = dns_addr & 0xFF; + pco_resp.N_opts++; + }else if(LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_IP_ADDRESS_ALLOCATION_VIA_NAS_SIGNALLING == pdn_con_req.protocol_cnfg_opts.opt[i].id){ + // Nothing to do + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "Invalid PCO ID (%04X)", + pdn_con_req.protocol_cnfg_opts.opt[i].id); + } + } + user->set_protocol_cnfg_opts(&pco_resp); + } +} + +/************************/ +/* State Machines */ +/************************/ +void LTE_fdd_enb_mme::attach_sm(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + + switch(rb->get_mme_state()) + { + case LTE_FDD_ENB_MME_STATE_ID_REQUEST_IMSI: + send_identity_request(user, rb, LIBLTE_MME_ID_TYPE_2_IMSI); + break; + case LTE_FDD_ENB_MME_STATE_REJECT: + user->prepare_for_deletion(); + send_attach_reject(user, rb); + break; + case LTE_FDD_ENB_MME_STATE_AUTHENTICATE: + send_authentication_request(user, rb); + break; + case LTE_FDD_ENB_MME_STATE_AUTH_REJECTED: + send_authentication_reject(user, rb); + break; + case LTE_FDD_ENB_MME_STATE_ENABLE_SECURITY: + send_security_mode_command(user, rb); + break; + case LTE_FDD_ENB_MME_STATE_RELEASE: + send_rrc_command(user, rb, LTE_FDD_ENB_RRC_CMD_RELEASE); + break; + case LTE_FDD_ENB_MME_STATE_RRC_SECURITY: + send_rrc_command(user, rb, LTE_FDD_ENB_RRC_CMD_SECURITY); + break; + case LTE_FDD_ENB_MME_STATE_ESM_INFO_TRANSFER: + send_esm_information_request(user, rb); + break; + case LTE_FDD_ENB_MME_STATE_ATTACH_ACCEPT: + send_attach_accept(user, rb); + break; + case LTE_FDD_ENB_MME_STATE_ATTACHED: + send_emm_information(user, rb); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "ATTACH state machine invalid state %s, RNTI=%u and RB=%s", + LTE_fdd_enb_mme_state_text[rb->get_mme_state()], + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + break; } } +void LTE_fdd_enb_mme::service_req_sm(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + switch(rb->get_mme_state()) + { + case LTE_FDD_ENB_MME_STATE_RELEASE: + send_rrc_command(user, rb, LTE_FDD_ENB_RRC_CMD_RELEASE); + break; + case LTE_FDD_ENB_MME_STATE_RRC_SECURITY: + send_rrc_command(user, rb, LTE_FDD_ENB_RRC_CMD_SECURITY); + break; + case LTE_FDD_ENB_MME_STATE_SETUP_DRB: + send_activate_dedicated_eps_bearer_context_request(user, rb); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "SERVICE REQUEST state machine invalid state %s, RNTI=%u and RB=%s", + LTE_fdd_enb_mme_state_text[rb->get_mme_state()], + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + break; + } +} +void LTE_fdd_enb_mme::detach_sm(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + switch(rb->get_mme_state()) + { + case LTE_FDD_ENB_MME_STATE_SEND_DETACH_ACCEPT: + send_detach_accept(user, rb); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + "DETACH state machine invalid state %s, RNTI=%u and RB=%s", + LTE_fdd_enb_mme_state_text[rb->get_mme_state()], + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + break; + } +} + +/*************************/ +/* Message Senders */ +/*************************/ +void LTE_fdd_enb_mme::send_attach_accept(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT cmd_ready; + LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept; + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req; + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT *pco = user->get_protocol_cnfg_opts(); + LIBLTE_BYTE_MSG_STRUCT msg; + uint32 ip_addr; + + // Assign IP address to user + user->set_ip_addr(get_next_ip_addr()); + ip_addr = user->get_ip_addr(); + + if(0 == user->get_eps_bearer_id()) + { + act_def_eps_bearer_context_req.eps_bearer_id = 5; + user->set_eps_bearer_id(5); + }else{ + act_def_eps_bearer_context_req.eps_bearer_id = user->get_eps_bearer_id(); + } + if(0 == user->get_proc_transaction_id()) + { + act_def_eps_bearer_context_req.proc_transaction_id = 1; + user->set_proc_transaction_id(1); + }else{ + act_def_eps_bearer_context_req.proc_transaction_id = user->get_proc_transaction_id(); + } + act_def_eps_bearer_context_req.eps_qos.qci = 9; + act_def_eps_bearer_context_req.eps_qos.br_present = false; + act_def_eps_bearer_context_req.eps_qos.br_ext_present = false; + act_def_eps_bearer_context_req.apn.apn = "www.openLTE.com"; + act_def_eps_bearer_context_req.pdn_addr.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; + act_def_eps_bearer_context_req.pdn_addr.addr[0] = (ip_addr >> 24) & 0xFF; + act_def_eps_bearer_context_req.pdn_addr.addr[1] = (ip_addr >> 16) & 0xFF; + act_def_eps_bearer_context_req.pdn_addr.addr[2] = (ip_addr >> 8) & 0xFF; + act_def_eps_bearer_context_req.pdn_addr.addr[3] = ip_addr & 0xFF; + act_def_eps_bearer_context_req.transaction_id_present = false; + act_def_eps_bearer_context_req.negotiated_qos_present = false; + act_def_eps_bearer_context_req.llc_sapi_present = false; + act_def_eps_bearer_context_req.radio_prio_present = false; + act_def_eps_bearer_context_req.packet_flow_id_present = false; + act_def_eps_bearer_context_req.apn_ambr_present = false; + if(LIBLTE_MME_PDN_TYPE_IPV4 == user->get_pdn_type()) + { + act_def_eps_bearer_context_req.esm_cause_present = false; + }else{ + act_def_eps_bearer_context_req.esm_cause_present = true; + act_def_eps_bearer_context_req.esm_cause = LIBLTE_MME_ESM_CAUSE_PDN_TYPE_IPV4_ONLY_ALLOWED; + } + if(0 != pco->N_opts) + { + act_def_eps_bearer_context_req.protocol_cnfg_opts_present = true; + memcpy(&act_def_eps_bearer_context_req.protocol_cnfg_opts, pco, sizeof(LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT)); + }else{ + act_def_eps_bearer_context_req.protocol_cnfg_opts_present = false; + } + act_def_eps_bearer_context_req.connectivity_type_present = false; + liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, + &attach_accept.esm_msg); + + sem_wait(&sys_info_sem); + attach_accept.eps_attach_result = user->get_attach_type(); + attach_accept.t3412.unit = LIBLTE_MME_GPRS_TIMER_DEACTIVATED; + attach_accept.tai_list.N_tais = 1; + attach_accept.tai_list.tai[0].mcc = sys_info.mcc; + attach_accept.tai_list.tai[0].mnc = sys_info.mnc; + attach_accept.tai_list.tai[0].tac = sys_info.sib1.tracking_area_code; + attach_accept.guti_present = true; + attach_accept.guti.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI; + attach_accept.guti.guti.mcc = sys_info.mcc; + attach_accept.guti.guti.mnc = sys_info.mnc; + attach_accept.guti.guti.mme_group_id = 0; + attach_accept.guti.guti.mme_code = 0; + attach_accept.guti.guti.m_tmsi = user_mgr->get_next_m_tmsi(); + attach_accept.lai_present = false; + attach_accept.ms_id_present = false; + attach_accept.emm_cause_present = false; + attach_accept.t3402_present = false; + attach_accept.t3423_present = false; + attach_accept.equivalent_plmns_present = false; + attach_accept.emerg_num_list_present = false; + attach_accept.eps_network_feature_support_present = false; + attach_accept.additional_update_result_present = false; + attach_accept.t3412_ext_present = false; + sem_post(&sys_info_sem); + user->set_guti(&attach_accept.guti.guti); + liblte_mme_pack_attach_accept_msg(&attach_accept, + LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED, + user->get_auth_vec()->k_nas_int, + user->get_auth_vec()->nas_count_dl, + LIBLTE_SECURITY_DIRECTION_DOWNLINK, + &msg); + user->increment_nas_count_dl(); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + &msg, + "Sending Attach Accept for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the NAS message for RRC + rb->queue_rrc_nas_msg(&msg); + + // Signal RRC for NAS message + cmd_ready.user = user; + cmd_ready.rb = rb; + cmd_ready.cmd = LTE_FDD_ENB_RRC_CMD_SETUP_DEF_DRB; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_CMD_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&cmd_ready, + sizeof(LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_mme::send_attach_reject(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT nas_msg_ready; + LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT attach_rej; + LIBLTE_BYTE_MSG_STRUCT msg; + uint64 imsi_num; + + if(user->is_id_set()) + { + imsi_num = user->get_id()->imsi; + }else{ + imsi_num = user->get_temp_id(); + } + + attach_rej.emm_cause = user->get_emm_cause(); + attach_rej.esm_msg_present = false; + attach_rej.t3446_value_present = false; + liblte_mme_pack_attach_reject_msg(&attach_rej, &msg); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + &msg, + "Sending Attach Reject for IMSI=%015llu, RNTI=%u, RB=%s", + imsi_num, + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the NAS message for RRC + rb->queue_rrc_nas_msg(&msg); + + // Signal RRC for NAS message + nas_msg_ready.user = user; + nas_msg_ready.rb = rb; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_NAS_MSG_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, + sizeof(LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT)); + + send_rrc_command(user, rb, LTE_FDD_ENB_RRC_CMD_RELEASE); +} +void LTE_fdd_enb_mme::send_authentication_reject(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT nas_msg_ready; + LIBLTE_MME_AUTHENTICATION_REJECT_MSG_STRUCT auth_rej; + LIBLTE_BYTE_MSG_STRUCT msg; + + liblte_mme_pack_authentication_reject_msg(&auth_rej, &msg); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + &msg, + "Sending Authentication Reject for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the NAS message for RRC + rb->queue_rrc_nas_msg(&msg); + + // Signal RRC for NAS message + nas_msg_ready.user = user; + nas_msg_ready.rb = rb; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_NAS_MSG_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, + sizeof(LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT)); + + send_rrc_command(user, rb, LTE_FDD_ENB_RRC_CMD_RELEASE); +} +void LTE_fdd_enb_mme::send_authentication_request(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_fdd_enb_hss *hss = LTE_fdd_enb_hss::get_instance(); + LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT *auth_vec = NULL; + LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT nas_msg_ready; + LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req; + LIBLTE_BYTE_MSG_STRUCT msg; + uint32 i; + + sem_wait(&sys_info_sem); + hss->generate_security_data(user->get_id(), sys_info.mcc, sys_info.mnc); + sem_post(&sys_info_sem); + auth_vec = hss->get_auth_vec(user->get_id()); + if(NULL != auth_vec) + { + for(i=0; i<16; i++) + { + auth_req.autn[i] = auth_vec->autn[i]; + auth_req.rand[i] = auth_vec->rand[i]; + } + auth_req.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; + auth_req.nas_ksi.nas_ksi = 0; + liblte_mme_pack_authentication_request_msg(&auth_req, &msg); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + &msg, + "Sending Authentication Request for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the NAS message for RRC + rb->queue_rrc_nas_msg(&msg); + + // Signal RRC + nas_msg_ready.user = user; + nas_msg_ready.rb = rb; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_NAS_MSG_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, + sizeof(LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT)); + } +} +void LTE_fdd_enb_mme::send_detach_accept(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT nas_msg_ready; + LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT detach_accept; + LIBLTE_BYTE_MSG_STRUCT msg; + + if(user->is_auth_vec_set()) + { + liblte_mme_pack_detach_accept_msg(&detach_accept, + LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED, + user->get_auth_vec()->k_nas_int, + user->get_auth_vec()->nas_count_dl, + LIBLTE_SECURITY_DIRECTION_DOWNLINK, + &msg); + user->increment_nas_count_dl(); + }else{ + liblte_mme_pack_detach_accept_msg(&detach_accept, + LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS, + NULL, + 0, + 0, + &msg); + } + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + &msg, + "Sending Detach Accept for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the NAS message for RRC + rb->queue_rrc_nas_msg(&msg); + + // Signal RRC + nas_msg_ready.user = user; + nas_msg_ready.rb = rb; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_NAS_MSG_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, + sizeof(LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_mme::send_emm_information(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT nas_msg_ready; + LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info; + LIBLTE_BYTE_MSG_STRUCT msg; + struct tm *local_time; + time_t tmp_time; + + tmp_time = time(NULL); + local_time = localtime(&tmp_time); + + emm_info.full_net_name_present = true; + emm_info.full_net_name.name = "openLTE"; + emm_info.full_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; + emm_info.short_net_name_present = true; + emm_info.short_net_name.name = "oLTE"; + emm_info.short_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; + emm_info.local_time_zone_present = false; + emm_info.utc_and_local_time_zone_present = true; + emm_info.utc_and_local_time_zone.year = local_time->tm_year; + emm_info.utc_and_local_time_zone.month = local_time->tm_mon + 1; + emm_info.utc_and_local_time_zone.day = local_time->tm_mday; + emm_info.utc_and_local_time_zone.hour = local_time->tm_hour; + emm_info.utc_and_local_time_zone.minute = local_time->tm_min; + emm_info.utc_and_local_time_zone.second = local_time->tm_sec; + emm_info.utc_and_local_time_zone.tz = 0; // FIXME + emm_info.net_dst_present = false; + liblte_mme_pack_emm_information_msg(&emm_info, + LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED, + user->get_auth_vec()->k_nas_int, + user->get_auth_vec()->nas_count_dl, + LIBLTE_SECURITY_DIRECTION_DOWNLINK, + &msg); + user->increment_nas_count_dl(); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + &msg, + "Sending EMM Information for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the NAS message for RRC + rb->queue_rrc_nas_msg(&msg); + + // Signal RRC + nas_msg_ready.user = user; + nas_msg_ready.rb = rb; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_NAS_MSG_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, + sizeof(LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_mme::send_identity_request(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb, + uint8 id_type) +{ + LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT nas_msg_ready; + LIBLTE_MME_ID_REQUEST_MSG_STRUCT id_req; + LIBLTE_BYTE_MSG_STRUCT msg; + + id_req.id_type = id_type; + liblte_mme_pack_identity_request_msg(&id_req, &msg); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + &msg, + "Sending ID Request for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the NAS message for RRC + rb->queue_rrc_nas_msg(&msg); + + // Signal RRC + nas_msg_ready.user = user; + nas_msg_ready.rb = rb; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_NAS_MSG_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, + sizeof(LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_mme::send_security_mode_command(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT nas_msg_ready; + LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sec_mode_cmd; + LIBLTE_BYTE_MSG_STRUCT msg; + uint32 i; + + sec_mode_cmd.selected_nas_sec_algs.type_of_eea = LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_EEA0; + sec_mode_cmd.selected_nas_sec_algs.type_of_eia = LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_128_EIA2; + sec_mode_cmd.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; + sec_mode_cmd.nas_ksi.nas_ksi = 0; + for(i=0; i<8; i++) + { + sec_mode_cmd.ue_security_cap.eea[i] = user->get_eea_support(i); + sec_mode_cmd.ue_security_cap.eia[i] = user->get_eia_support(i); + sec_mode_cmd.ue_security_cap.uea[i] = user->get_uea_support(i); + sec_mode_cmd.ue_security_cap.uia[i] = user->get_uia_support(i); + sec_mode_cmd.ue_security_cap.gea[i] = user->get_gea_support(i); + } + if(user->is_uea_set()) + { + sec_mode_cmd.ue_security_cap.uea_present = true; + }else{ + sec_mode_cmd.ue_security_cap.uea_present = false; + } + if(user->is_uia_set()) + { + sec_mode_cmd.ue_security_cap.uia_present = true; + }else{ + sec_mode_cmd.ue_security_cap.uia_present = false; + } + if(user->is_gea_set()) + { + sec_mode_cmd.ue_security_cap.gea_present = true; + }else{ + sec_mode_cmd.ue_security_cap.gea_present = false; + } + sec_mode_cmd.imeisv_req = LIBLTE_MME_IMEISV_REQUESTED; + sec_mode_cmd.imeisv_req_present = true; + sec_mode_cmd.nonce_ue_present = false; + sec_mode_cmd.nonce_mme_present = false; + liblte_mme_pack_security_mode_command_msg(&sec_mode_cmd, + LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT, + user->get_auth_vec()->k_nas_int, + user->get_auth_vec()->nas_count_dl, + LIBLTE_SECURITY_DIRECTION_DOWNLINK, + &msg); + user->increment_nas_count_dl(); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + &msg, + "Sending Security Mode Command for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the message for RRC + rb->queue_rrc_nas_msg(&msg); + + // Signal RRC + nas_msg_ready.user = user; + nas_msg_ready.rb = rb; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_NAS_MSG_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, + sizeof(LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_mme::send_service_reject(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb, + uint8 cause) +{ + LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT nas_msg_ready; + LIBLTE_MME_SERVICE_REJECT_MSG_STRUCT service_rej; + LIBLTE_BYTE_MSG_STRUCT msg; + + service_rej.emm_cause = cause; + service_rej.t3442_present = false; + service_rej.t3446_present = false; + liblte_mme_pack_service_reject_msg(&service_rej, + LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS, + NULL, + 0, + 0, + &msg); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + &msg, + "Sending Service Reject for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the NAS message for RRC + rb->queue_rrc_nas_msg(&msg); + + nas_msg_ready.user = user; + nas_msg_ready.rb = rb; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_NAS_MSG_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, + sizeof(LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_mme::send_activate_dedicated_eps_bearer_context_request(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT cmd_ready; + LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_ded_eps_bearer_context_req; + LIBLTE_BYTE_MSG_STRUCT msg; + LIBLTE_BYTE_MSG_STRUCT sec_msg; + + if(0 == user->get_eps_bearer_id()) + { + act_ded_eps_bearer_context_req.eps_bearer_id = 6; + user->set_eps_bearer_id(5); + }else{ + act_ded_eps_bearer_context_req.eps_bearer_id = user->get_eps_bearer_id()+1; + } + act_ded_eps_bearer_context_req.proc_transaction_id = 0; + act_ded_eps_bearer_context_req.linked_eps_bearer_id = user->get_eps_bearer_id(); + act_ded_eps_bearer_context_req.eps_qos.qci = 9; + act_ded_eps_bearer_context_req.eps_qos.br_present = false; + act_ded_eps_bearer_context_req.eps_qos.br_ext_present = false; + act_ded_eps_bearer_context_req.tft.tft_op_code = LIBLTE_MME_TFT_OPERATION_CODE_CREATE_NEW_TFT; + act_ded_eps_bearer_context_req.tft.parameter_list_size = 0; + act_ded_eps_bearer_context_req.tft.packet_filter_list_size = 3; + act_ded_eps_bearer_context_req.tft.packet_filter_list[0].id = 1; + act_ded_eps_bearer_context_req.tft.packet_filter_list[0].dir = LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_BIDIRECTIONAL; + act_ded_eps_bearer_context_req.tft.packet_filter_list[0].eval_precedence = 1; + act_ded_eps_bearer_context_req.tft.packet_filter_list[0].filter_size = 2; + act_ded_eps_bearer_context_req.tft.packet_filter_list[0].filter[0] = LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_PROTOCOL_ID_NEXT_HEADER_TYPE; + act_ded_eps_bearer_context_req.tft.packet_filter_list[0].filter[1] = IPPROTO_UDP; + act_ded_eps_bearer_context_req.tft.packet_filter_list[1].id = 2; + act_ded_eps_bearer_context_req.tft.packet_filter_list[1].dir = LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_BIDIRECTIONAL; + act_ded_eps_bearer_context_req.tft.packet_filter_list[1].eval_precedence = 2; + act_ded_eps_bearer_context_req.tft.packet_filter_list[1].filter_size = 2; + act_ded_eps_bearer_context_req.tft.packet_filter_list[1].filter[0] = LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_PROTOCOL_ID_NEXT_HEADER_TYPE; + act_ded_eps_bearer_context_req.tft.packet_filter_list[1].filter[1] = IPPROTO_TCP; + act_ded_eps_bearer_context_req.tft.packet_filter_list[2].id = 3; + act_ded_eps_bearer_context_req.tft.packet_filter_list[2].dir = LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_BIDIRECTIONAL; + act_ded_eps_bearer_context_req.tft.packet_filter_list[2].eval_precedence = 3; + act_ded_eps_bearer_context_req.tft.packet_filter_list[2].filter_size = 2; + act_ded_eps_bearer_context_req.tft.packet_filter_list[2].filter[0] = LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_PROTOCOL_ID_NEXT_HEADER_TYPE; + act_ded_eps_bearer_context_req.tft.packet_filter_list[2].filter[1] = IPPROTO_ICMP; + act_ded_eps_bearer_context_req.transaction_id_present = false; + act_ded_eps_bearer_context_req.negotiated_qos_present = false; + act_ded_eps_bearer_context_req.llc_sapi_present = false; + act_ded_eps_bearer_context_req.radio_prio_present = false; + act_ded_eps_bearer_context_req.packet_flow_id_present = false; + act_ded_eps_bearer_context_req.protocol_cnfg_opts_present = false; + liblte_mme_pack_activate_dedicated_eps_bearer_context_request_msg(&act_ded_eps_bearer_context_req, + &msg); + liblte_mme_pack_security_protected_nas_msg(&msg, + LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED, + user->get_auth_vec()->k_nas_int, + user->get_auth_vec()->nas_count_dl, + LIBLTE_SECURITY_DIRECTION_DOWNLINK, + &sec_msg); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + &sec_msg, + "Sending Activate Dedicated EPS Bearer Context Request for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the NAS message for RRC + rb->queue_rrc_nas_msg(&sec_msg); + + // Signal RRC for NAS message + cmd_ready.user = user; + cmd_ready.rb = rb; + cmd_ready.cmd = LTE_FDD_ENB_RRC_CMD_SETUP_DED_DRB; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_CMD_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&cmd_ready, + sizeof(LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_mme::send_esm_information_request(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT nas_msg_ready; + LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT esm_info_req; + LIBLTE_BYTE_MSG_STRUCT msg; + LIBLTE_BYTE_MSG_STRUCT sec_msg; + + esm_info_req.eps_bearer_id = 0; + if(0 == user->get_proc_transaction_id()) + { + esm_info_req.proc_transaction_id = 1; + user->set_proc_transaction_id(1); + }else{ + esm_info_req.proc_transaction_id = user->get_proc_transaction_id(); + } + liblte_mme_pack_esm_information_request_msg(&esm_info_req, &msg); + liblte_mme_pack_security_protected_nas_msg(&msg, + LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED, + user->get_auth_vec()->k_nas_int, + user->get_auth_vec()->nas_count_dl, + LIBLTE_SECURITY_DIRECTION_DOWNLINK, + &sec_msg); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_MME, + __FILE__, + __LINE__, + &sec_msg, + "Sending ESM Info Request for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the NAS message for RRC + rb->queue_rrc_nas_msg(&sec_msg); + + // Signal RRC + nas_msg_ready.user = user; + nas_msg_ready.rb = rb; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_NAS_MSG_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, + sizeof(LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_mme::send_rrc_command(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb, + LTE_FDD_ENB_RRC_CMD_ENUM cmd) +{ + LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT cmd_ready; + + // Signal RRC for command + cmd_ready.user = user; + cmd_ready.rb = rb; + cmd_ready.cmd = cmd; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_CMD_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&cmd_ready, + sizeof(LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT)); +} + +/*****************/ +/* Helpers */ +/*****************/ +uint32 LTE_fdd_enb_mme::get_next_ip_addr(void) +{ + uint32 ip_addr = next_ip_addr; + + next_ip_addr++; + if((next_ip_addr & 0xFF) == 0xFF) + { + next_ip_addr++; + } + + return(ip_addr); +} diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_msgq.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_msgq.cc old mode 100644 new mode 100755 index 576fc25..435f32a --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_msgq.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_msgq.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_msgq.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2016 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -29,6 +29,17 @@ 11/23/2013 Ben Wojtowicz Fixed a bug with receive size. 01/18/2014 Ben Wojtowicz Added ability to set priorities. 06/15/2014 Ben Wojtowicz Omitting path from __FILE__. + 02/15/2015 Ben Wojtowicz Moving to new message queue with semaphores + and circular buffers. + 03/15/2015 Ben Wojtowicz Added a mutex to the circular buffer. + 07/25/2015 Ben Wojtowicz Combined the DL and UL schedule messages into + a single PHY schedule message. + 12/06/2015 Ben Wojtowicz Changed boost::mutex and + boost::interprocess::interprocess_semaphore + to sem_t and properly initializing priority. + 02/13/2016 Ben Wojtowicz Moved the buffer empty log from ERROR to + WARNING. + 07/03/2016 Ben Wojtowicz Setting processor affinity. *******************************************************************************/ @@ -69,7 +80,7 @@ LTE_fdd_enb_msgq_cb::LTE_fdd_enb_msgq_cb(FuncType f, void* o) func = f; obj = o; } -void LTE_fdd_enb_msgq_cb::operator()(LTE_FDD_ENB_MESSAGE_STRUCT *msg) +void LTE_fdd_enb_msgq_cb::operator()(LTE_FDD_ENB_MESSAGE_STRUCT &msg) { return (*func)(obj, msg); } @@ -77,119 +88,154 @@ void LTE_fdd_enb_msgq_cb::operator()(LTE_FDD_ENB_MESSAGE_STRUCT *msg) /********************************/ /* Constructor/Destructor */ /********************************/ -LTE_fdd_enb_msgq::LTE_fdd_enb_msgq(std::string _msgq_name, - LTE_fdd_enb_msgq_cb cb) +LTE_fdd_enb_msgq::LTE_fdd_enb_msgq(std::string _msgq_name) { + sem_init(&sync_sem, 0, 1); + sem_init(&msg_sem, 0, 1); + circ_buf = new boost::circular_buffer(100); msgq_name = _msgq_name; - callback = cb; - prio = 0; - pthread_create(&rx_thread, NULL, &receive_thread, this); -} -LTE_fdd_enb_msgq::LTE_fdd_enb_msgq(std::string _msgq_name, - LTE_fdd_enb_msgq_cb cb, - uint32 _prio) -{ - msgq_name = _msgq_name; - callback = cb; - prio = _prio; - pthread_create(&rx_thread, NULL, &receive_thread, this); + rx_setup = false; } LTE_fdd_enb_msgq::~LTE_fdd_enb_msgq() { - try + if(rx_setup) { - LTE_fdd_enb_msgq::send(msgq_name.c_str(), - LTE_FDD_ENB_MESSAGE_TYPE_KILL, - LTE_FDD_ENB_DEST_LAYER_ANY, - NULL, - 0); - sleep(1); - }catch(boost::interprocess::interprocess_exception &){ - // Intentionally do nothing + send(LTE_FDD_ENB_MESSAGE_TYPE_KILL, + LTE_FDD_ENB_DEST_LAYER_ANY, + NULL, + 0); + + // Cleanup thread + pthread_cancel(rx_thread); + pthread_join(rx_thread, NULL); + rx_setup = false; } + sem_destroy(&msg_sem); + sem_destroy(&sync_sem); + delete circ_buf; +} - // Cleanup thread - pthread_cancel(rx_thread); - pthread_join(rx_thread, NULL); +/***************/ +/* Setup */ +/***************/ +void LTE_fdd_enb_msgq::attach_rx(LTE_fdd_enb_msgq_cb cb) +{ + callback = cb; + prio = 0; + pthread_create(&rx_thread, NULL, &receive_thread, this); + rx_setup = true; +} +void LTE_fdd_enb_msgq::attach_rx(LTE_fdd_enb_msgq_cb cb, + uint32 _prio) +{ + callback = cb; + prio = _prio; + pthread_create(&rx_thread, NULL, &receive_thread, this); + rx_setup = true; } /**********************/ /* Send/Receive */ /**********************/ -void LTE_fdd_enb_msgq::send(const char *mq_name, - LTE_FDD_ENB_MESSAGE_TYPE_ENUM type, +void LTE_fdd_enb_msgq::send(LTE_FDD_ENB_MESSAGE_TYPE_ENUM type, LTE_FDD_ENB_DEST_LAYER_ENUM dest_layer, LTE_FDD_ENB_MESSAGE_UNION *msg_content, uint32 msg_content_size) { - boost::interprocess::message_queue mq(boost::interprocess::open_only, mq_name); + LTE_FDD_ENB_MESSAGE_STRUCT msg; - LTE_fdd_enb_msgq::send(&mq, type, dest_layer, msg_content, msg_content_size); -} -void LTE_fdd_enb_msgq::send(boost::interprocess::message_queue *mq, - LTE_FDD_ENB_MESSAGE_TYPE_ENUM type, - LTE_FDD_ENB_DEST_LAYER_ENUM dest_layer, - LTE_FDD_ENB_MESSAGE_UNION *msg_content, - uint32 msg_content_size) -{ - LTE_FDD_ENB_MESSAGE_STRUCT *msg = NULL; - - msg = new LTE_FDD_ENB_MESSAGE_STRUCT; - - msg->type = type; - msg->dest_layer = dest_layer; + msg.type = type; + msg.dest_layer = dest_layer; if(msg_content != NULL) { - memcpy(&msg->msg, msg_content, msg_content_size); + memcpy(&msg.msg, msg_content, msg_content_size); } - mq->send(&msg, sizeof(msg), 0); + sem_wait(&sync_sem); + circ_buf->push_back(msg); + sem_post(&sync_sem); + sem_post(&msg_sem); +} +void LTE_fdd_enb_msgq::send(LTE_FDD_ENB_MESSAGE_TYPE_ENUM type, + LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT *dl_sched, + LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT *ul_sched) +{ + LTE_FDD_ENB_MESSAGE_STRUCT msg; + + msg.type = type; + msg.dest_layer = LTE_FDD_ENB_DEST_LAYER_PHY; + memcpy(&msg.msg.phy_schedule.dl_sched, dl_sched, sizeof(LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT)); + memcpy(&msg.msg.phy_schedule.ul_sched, ul_sched, sizeof(LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT)); + + sem_wait(&sync_sem); + circ_buf->push_back(msg); + sem_post(&sync_sem); + sem_post(&msg_sem); +} +void LTE_fdd_enb_msgq::send(LTE_FDD_ENB_MESSAGE_STRUCT &msg) +{ + sem_wait(&sync_sem); + circ_buf->push_back(msg); + sem_post(&sync_sem); + sem_post(&msg_sem); } void* LTE_fdd_enb_msgq::receive_thread(void *inputs) { - LTE_fdd_enb_msgq *msgq = (LTE_fdd_enb_msgq *)inputs; - LTE_FDD_ENB_MESSAGE_STRUCT *msg = NULL; + LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + LTE_fdd_enb_msgq *msgq = (LTE_fdd_enb_msgq *)inputs; + LTE_FDD_ENB_MESSAGE_STRUCT msg; struct sched_param priority; - std::size_t rx_size; - uint32 prio; + cpu_set_t af_mask; bool not_done = true; // Set priority if(msgq->prio != 0) { // FIXME: verify - priority.sched_priority = prio; + priority.sched_priority = msgq->prio; pthread_setschedparam(msgq->rx_thread, SCHED_FIFO, &priority); } - // Open the message_queue - boost::interprocess::message_queue mq(boost::interprocess::open_only, - msgq->msgq_name.c_str()); + // Set affinity to not the last core (last core is for PHY/Radio) + pthread_getaffinity_np(msgq->rx_thread, sizeof(af_mask), &af_mask); + CPU_CLR(sysconf(_SC_NPROCESSORS_ONLN)-1, &af_mask); + pthread_setaffinity_np(msgq->rx_thread, sizeof(af_mask), &af_mask); while(not_done) { // Wait for a message - mq.receive(&msg, sizeof(msg), rx_size, prio); - - // Process message - if(sizeof(msg) == rx_size) + sem_wait(&msgq->msg_sem); + sem_wait(&msgq->sync_sem); + if(msgq->circ_buf->size() != 0) { - switch(msg->type) + while(msgq->circ_buf->size() != 0) { - case LTE_FDD_ENB_MESSAGE_TYPE_KILL: - not_done = false; - delete msg; - break; - default: - msgq->callback(msg); - break; + msg = msgq->circ_buf->front(); + msgq->circ_buf->pop_front(); + sem_post(&msgq->sync_sem); + + // Process message + switch(msg.type) + { + case LTE_FDD_ENB_MESSAGE_TYPE_KILL: + not_done = false; + break; + default: + msgq->callback(msg); + break; + } + + sem_wait(&msgq->sync_sem); } }else{ - // FIXME: Use print_debug_msg - printf("ERROR %s Invalid message size received: %u\n", - msgq->msgq_name.c_str(), - rx_size); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_WARNING, + LTE_FDD_ENB_DEBUG_LEVEL_MSGQ, + __FILE__, + __LINE__, + "%s circular buffer empty on receive", + msgq->msgq_name.c_str()); } + sem_post(&msgq->sync_sem); } return(NULL); diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_pdcp.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_pdcp.cc old mode 100644 new mode 100755 index ae11c73..e642a5e --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_pdcp.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_pdcp.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_pdcp.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2015, 2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -29,6 +29,14 @@ 01/18/2014 Ben Wojtowicz Added level to debug prints. 05/04/2014 Ben Wojtowicz Added communication to RLC and RRC. 06/15/2014 Ben Wojtowicz Added simple header parsing. + 08/03/2014 Ben Wojtowicz Added transmit functionality. + 11/01/2014 Ben Wojtowicz Added SRB2 and security support. + 11/29/2014 Ben Wojtowicz Added communication to IP gateway. + 12/16/2014 Ben Wojtowicz Added ol extension to message queues. + 02/15/2015 Ben Wojtowicz Moved to new message queue. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t. + 07/29/2017 Ben Wojtowicz Moved away from singleton pattern. *******************************************************************************/ @@ -38,7 +46,9 @@ #include "LTE_fdd_enb_pdcp.h" #include "LTE_fdd_enb_rlc.h" -#include "LTE_fdd_enb_interface.h" +#include "liblte_pdcp.h" +#include "liblte_security.h" +#include "libtools_scoped_lock.h" /******************************************************************************* DEFINES @@ -54,99 +64,80 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_enb_pdcp* LTE_fdd_enb_pdcp::instance = NULL; -boost::mutex pdcp_instance_mutex; /******************************************************************************* CLASS IMPLEMENTATIONS *******************************************************************************/ -/*******************/ -/* Singleton */ -/*******************/ -LTE_fdd_enb_pdcp* LTE_fdd_enb_pdcp::get_instance(void) -{ - boost::mutex::scoped_lock lock(pdcp_instance_mutex); - - if(NULL == instance) - { - instance = new LTE_fdd_enb_pdcp(); - } - - return(instance); -} -void LTE_fdd_enb_pdcp::cleanup(void) -{ - boost::mutex::scoped_lock lock(pdcp_instance_mutex); - - if(NULL != instance) - { - delete instance; - instance = NULL; - } -} - /********************************/ /* Constructor/Destructor */ /********************************/ LTE_fdd_enb_pdcp::LTE_fdd_enb_pdcp() { + sem_init(&start_sem, 0, 1); + sem_init(&sys_info_sem, 0, 1); started = false; } LTE_fdd_enb_pdcp::~LTE_fdd_enb_pdcp() { stop(); + sem_destroy(&sys_info_sem); + sem_destroy(&start_sem); } /********************/ /* Start/Stop */ /********************/ -void LTE_fdd_enb_pdcp::start(void) +void LTE_fdd_enb_pdcp::start(LTE_fdd_enb_msgq *from_rlc, + LTE_fdd_enb_msgq *from_rrc, + LTE_fdd_enb_msgq *from_gw, + LTE_fdd_enb_msgq *to_rlc, + LTE_fdd_enb_msgq *to_rrc, + LTE_fdd_enb_msgq *to_gw, + LTE_fdd_enb_interface *iface) { - boost::mutex::scoped_lock lock(start_mutex); - LTE_fdd_enb_msgq_cb rlc_cb(<E_fdd_enb_msgq_cb_wrapper, this); - LTE_fdd_enb_msgq_cb rrc_cb(<E_fdd_enb_msgq_cb_wrapper, this); + libtools_scoped_lock lock(start_sem); + LTE_fdd_enb_msgq_cb rlc_cb(<E_fdd_enb_msgq_cb_wrapper, this); + LTE_fdd_enb_msgq_cb rrc_cb(<E_fdd_enb_msgq_cb_wrapper, this); + LTE_fdd_enb_msgq_cb gw_cb(<E_fdd_enb_msgq_cb_wrapper, this); if(!started) { + interface = iface; started = true; - rlc_comm_msgq = new LTE_fdd_enb_msgq("rlc_pdcp_mq", - rlc_cb); - rrc_comm_msgq = new LTE_fdd_enb_msgq("rrc_pdcp_mq", - rrc_cb); - pdcp_rlc_mq = new boost::interprocess::message_queue(boost::interprocess::open_only, - "pdcp_rlc_mq"); - pdcp_rrc_mq = new boost::interprocess::message_queue(boost::interprocess::open_only, - "pdcp_rrc_mq"); + msgq_from_rlc = from_rlc; + msgq_from_rrc = from_rrc; + msgq_from_gw = from_gw; + msgq_to_rlc = to_rlc; + msgq_to_rrc = to_rrc; + msgq_to_gw = to_gw; + msgq_from_rlc->attach_rx(rlc_cb); + msgq_from_rrc->attach_rx(rrc_cb); + msgq_from_gw->attach_rx(gw_cb); } } void LTE_fdd_enb_pdcp::stop(void) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_sem); if(started) { started = false; - delete rlc_comm_msgq; - delete rrc_comm_msgq; } } /***********************/ /* Communication */ /***********************/ -void LTE_fdd_enb_pdcp::handle_rlc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) +void LTE_fdd_enb_pdcp::handle_rlc_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - - if(LTE_FDD_ENB_DEST_LAYER_PDCP == msg->dest_layer || - LTE_FDD_ENB_DEST_LAYER_ANY == msg->dest_layer) + if(LTE_FDD_ENB_DEST_LAYER_PDCP == msg.dest_layer || + LTE_FDD_ENB_DEST_LAYER_ANY == msg.dest_layer) { - switch(msg->type) + switch(msg.type) { case LTE_FDD_ENB_MESSAGE_TYPE_PDCP_PDU_READY: - handle_pdu_ready(&msg->msg.pdcp_pdu_ready); - delete msg; + handle_pdu_ready(&msg.msg.pdcp_pdu_ready); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, @@ -154,27 +145,23 @@ void LTE_fdd_enb_pdcp::handle_rlc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) __FILE__, __LINE__, "Received invalid RLC message %s", - LTE_fdd_enb_message_type_text[msg->type]); - delete msg; + LTE_fdd_enb_message_type_text[msg.type]); break; } }else{ // Forward message to RRC - pdcp_rrc_mq->send(&msg, sizeof(msg), 0); + msgq_to_rrc->send(msg); } } -void LTE_fdd_enb_pdcp::handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) +void LTE_fdd_enb_pdcp::handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - - if(LTE_FDD_ENB_DEST_LAYER_PDCP == msg->dest_layer || - LTE_FDD_ENB_DEST_LAYER_ANY == msg->dest_layer) + if(LTE_FDD_ENB_DEST_LAYER_PDCP == msg.dest_layer || + LTE_FDD_ENB_DEST_LAYER_ANY == msg.dest_layer) { - switch(msg->type) + switch(msg.type) { case LTE_FDD_ENB_MESSAGE_TYPE_PDCP_SDU_READY: - handle_sdu_ready(&msg->msg.pdcp_sdu_ready); - delete msg; + handle_sdu_ready(&msg.msg.pdcp_sdu_ready); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, @@ -182,13 +169,40 @@ void LTE_fdd_enb_pdcp::handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) __FILE__, __LINE__, "Received invalid RRC message %s", - LTE_fdd_enb_message_type_text[msg->type]); - delete msg; + LTE_fdd_enb_message_type_text[msg.type]); break; } }else{ // Forward message to RLC - pdcp_rlc_mq->send(&msg, sizeof(msg), 0); + msgq_to_rlc->send(msg); + } +} +void LTE_fdd_enb_pdcp::handle_gw_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) +{ + if(LTE_FDD_ENB_DEST_LAYER_PDCP == msg.dest_layer || + LTE_FDD_ENB_DEST_LAYER_ANY == msg.dest_layer) + { + switch(msg.type) + { + case LTE_FDD_ENB_MESSAGE_TYPE_PDCP_DATA_SDU_READY: + handle_data_sdu_ready(&msg.msg.pdcp_data_sdu_ready); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_PDCP, + __FILE__, + __LINE__, + "Received invalid GW message %s", + LTE_fdd_enb_message_type_text[msg.type]); + break; + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_PDCP, + __FILE__, + __LINE__, + "Received GW message for invalid layer %s", + LTE_fdd_enb_dest_layer_text[msg.dest_layer]); } } @@ -197,11 +211,10 @@ void LTE_fdd_enb_pdcp::handle_rrc_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) /****************************/ void LTE_fdd_enb_pdcp::update_sys_info(void) { - LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + libtools_scoped_lock lock(sys_info_sem); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); - sys_info_mutex.lock(); cnfg_db->get_sys_info(sys_info); - sys_info_mutex.unlock(); } /******************************/ @@ -209,9 +222,14 @@ void LTE_fdd_enb_pdcp::update_sys_info(void) /******************************/ void LTE_fdd_enb_pdcp::handle_pdu_ready(LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT *pdu_ready) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - LTE_FDD_ENB_RRC_PDU_READY_MSG_STRUCT rrc_pdu_ready; - LIBLTE_BIT_MSG_STRUCT *pdu; + LTE_FDD_ENB_RRC_PDU_READY_MSG_STRUCT rrc_pdu_ready; + LTE_FDD_ENB_GW_DATA_READY_MSG_STRUCT gw_data_ready; + LIBLTE_PDCP_CONTROL_PDU_STRUCT contents; + LIBLTE_PDCP_DATA_PDU_WITH_LONG_SN_STRUCT data_contents; + LIBLTE_BYTE_MSG_STRUCT *pdu; + LIBLTE_BIT_MSG_STRUCT rrc_pdu; + uint8 *pdu_ptr; + uint32 i; if(LTE_FDD_ENB_ERROR_NONE == pdu_ready->rb->get_next_pdcp_pdu(&pdu)) { @@ -224,39 +242,67 @@ void LTE_fdd_enb_pdcp::handle_pdu_ready(LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT *p pdu_ready->user->get_c_rnti(), LTE_fdd_enb_rb_text[pdu_ready->rb->get_rb_id()]); + // FIXME: Add SN and integrity verification + if(LTE_FDD_ENB_RB_SRB0 == pdu_ready->rb->get_rb_id()) { + // Convert to bit struct for RRC + pdu_ptr = rrc_pdu.msg; + for(i=0; iN_bytes; i++) + { + liblte_value_2_bits(pdu->msg[i], &pdu_ptr, 8); + } + rrc_pdu.N_bits = pdu_ptr - rrc_pdu.msg; + // Queue the SDU for RRC - pdu_ready->rb->queue_rrc_pdu(pdu); + pdu_ready->rb->queue_rrc_pdu(&rrc_pdu); // Signal RRC rrc_pdu_ready.user = pdu_ready->user; rrc_pdu_ready.rb = pdu_ready->rb; - LTE_fdd_enb_msgq::send(pdcp_rrc_mq, - LTE_FDD_ENB_MESSAGE_TYPE_RRC_PDU_READY, - LTE_FDD_ENB_DEST_LAYER_RRC, - (LTE_FDD_ENB_MESSAGE_UNION *)&rrc_pdu_ready, - sizeof(LTE_FDD_ENB_RRC_PDU_READY_MSG_STRUCT)); - - // Delete the PDU - pdu_ready->rb->delete_next_pdcp_pdu(); + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_PDU_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&rrc_pdu_ready, + sizeof(LTE_FDD_ENB_RRC_PDU_READY_MSG_STRUCT)); }else if(LTE_FDD_ENB_RB_SRB1 == pdu_ready->rb->get_rb_id()){ - // Parse the header - // FIXME - memmove(&pdu->msg[0], &pdu->msg[8], pdu->N_bits-8); - pdu->N_bits -= 8; + liblte_pdcp_unpack_control_pdu(pdu, &contents); // Queue the SDU for RRC - pdu_ready->rb->queue_rrc_pdu(pdu); + pdu_ready->rb->queue_rrc_pdu(&contents.data); // Signal RRC rrc_pdu_ready.user = pdu_ready->user; rrc_pdu_ready.rb = pdu_ready->rb; - LTE_fdd_enb_msgq::send(pdcp_rrc_mq, - LTE_FDD_ENB_MESSAGE_TYPE_RRC_PDU_READY, - LTE_FDD_ENB_DEST_LAYER_RRC, - (LTE_FDD_ENB_MESSAGE_UNION *)&rrc_pdu_ready, - sizeof(LTE_FDD_ENB_RRC_PDU_READY_MSG_STRUCT)); + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_PDU_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&rrc_pdu_ready, + sizeof(LTE_FDD_ENB_RRC_PDU_READY_MSG_STRUCT)); + }else if(LTE_FDD_ENB_RB_SRB2 == pdu_ready->rb->get_rb_id()){ + liblte_pdcp_unpack_control_pdu(pdu, &contents); + + // Queue the SDU for RRC + pdu_ready->rb->queue_rrc_pdu(&contents.data); + + // Signal RRC + rrc_pdu_ready.user = pdu_ready->user; + rrc_pdu_ready.rb = pdu_ready->rb; + msgq_to_rrc->send(LTE_FDD_ENB_MESSAGE_TYPE_RRC_PDU_READY, + LTE_FDD_ENB_DEST_LAYER_RRC, + (LTE_FDD_ENB_MESSAGE_UNION *)&rrc_pdu_ready, + sizeof(LTE_FDD_ENB_RRC_PDU_READY_MSG_STRUCT)); + }else if(LTE_FDD_ENB_RB_DRB1 == pdu_ready->rb->get_rb_id()){ + liblte_pdcp_unpack_data_pdu_with_long_sn(pdu, &data_contents); + + // Queue the SDU for GW + pdu_ready->rb->queue_gw_data_msg(&data_contents.data); + + // Signal GW + gw_data_ready.user = pdu_ready->user; + gw_data_ready.rb = pdu_ready->rb; + msgq_to_gw->send(LTE_FDD_ENB_MESSAGE_TYPE_GW_DATA_READY, + LTE_FDD_ENB_DEST_LAYER_GW, + (LTE_FDD_ENB_MESSAGE_UNION *)&gw_data_ready, + sizeof(LTE_FDD_ENB_GW_DATA_READY_MSG_STRUCT)); }else{ interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, LTE_FDD_ENB_DEBUG_LEVEL_PDCP, @@ -267,6 +313,9 @@ void LTE_fdd_enb_pdcp::handle_pdu_ready(LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT *p pdu_ready->user->get_c_rnti(), LTE_fdd_enb_rb_text[pdu_ready->rb->get_rb_id()]); } + + // Delete the PDU + pdu_ready->rb->delete_next_pdcp_pdu(); } } @@ -275,9 +324,11 @@ void LTE_fdd_enb_pdcp::handle_pdu_ready(LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT *p /******************************/ void LTE_fdd_enb_pdcp::handle_sdu_ready(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT *sdu_ready) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); LTE_FDD_ENB_RLC_SDU_READY_MSG_STRUCT rlc_sdu_ready; + LIBLTE_PDCP_CONTROL_PDU_STRUCT contents; + LIBLTE_BYTE_MSG_STRUCT pdu; LIBLTE_BIT_MSG_STRUCT *sdu; + uint8 *sdu_ptr; uint32 i; if(LTE_FDD_ENB_ERROR_NONE == sdu_ready->rb->get_next_pdcp_sdu(&sdu)) @@ -303,17 +354,76 @@ void LTE_fdd_enb_pdcp::handle_sdu_ready(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT *s sdu->N_bits += 8 - (sdu->N_bits % 8); } + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_PDCP, + __FILE__, + __LINE__, + sdu, + "Sending PDU for RNTI=%u and RB=%s", + sdu_ready->user->get_c_rnti(), + LTE_fdd_enb_rb_text[sdu_ready->rb->get_rb_id()]); + + // Convert from bit to byte struct + sdu_ptr = sdu->msg; + for(i=0; iN_bits/8; i++) + { + pdu.msg[i] = liblte_bits_2_value(&sdu_ptr, 8); + } + pdu.N_bytes = sdu->N_bits/8; + + // Queue the PDU for RLC + sdu_ready->rb->queue_rlc_sdu(&pdu); + + // Signal RLC + rlc_sdu_ready.user = sdu_ready->user; + rlc_sdu_ready.rb = sdu_ready->rb; + msgq_to_rlc->send(LTE_FDD_ENB_MESSAGE_TYPE_RLC_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_RLC, + (LTE_FDD_ENB_MESSAGE_UNION *)&rlc_sdu_ready, + sizeof(LTE_FDD_ENB_RLC_SDU_READY_MSG_STRUCT)); + + // Delete the SDU + sdu_ready->rb->delete_next_pdcp_sdu(); + }else if(LTE_FDD_ENB_RB_SRB1 == sdu_ready->rb->get_rb_id() || + LTE_FDD_ENB_RB_SRB2 == sdu_ready->rb->get_rb_id()){ + // Pack the control PDU + contents.count = sdu_ready->rb->get_pdcp_tx_count(); + if(LTE_FDD_ENB_PDCP_CONFIG_SECURITY == sdu_ready->rb->get_pdcp_config()) + { + liblte_pdcp_pack_control_pdu(&contents, + sdu, + sdu_ready->user->get_auth_vec()->k_rrc_int, + LIBLTE_SECURITY_DIRECTION_DOWNLINK, + sdu_ready->rb->get_rb_id()-1, + &pdu); + }else{ + liblte_pdcp_pack_control_pdu(&contents, + sdu, + &pdu); + } + + // Increment the SN + sdu_ready->rb->set_pdcp_tx_count(contents.count + 1); + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_PDCP, + __FILE__, + __LINE__, + &pdu, + "Sending PDU for RNTI=%u and RB=%s", + sdu_ready->user->get_c_rnti(), + LTE_fdd_enb_rb_text[sdu_ready->rb->get_rb_id()]); + // Queue the PDU for RLC - sdu_ready->rb->queue_rlc_sdu(sdu); + sdu_ready->rb->queue_rlc_sdu(&pdu); // Signal RLC rlc_sdu_ready.user = sdu_ready->user; rlc_sdu_ready.rb = sdu_ready->rb; - LTE_fdd_enb_msgq::send(pdcp_rlc_mq, - LTE_FDD_ENB_MESSAGE_TYPE_RLC_SDU_READY, - LTE_FDD_ENB_DEST_LAYER_RLC, - (LTE_FDD_ENB_MESSAGE_UNION *)&rlc_sdu_ready, - sizeof(LTE_FDD_ENB_RLC_SDU_READY_MSG_STRUCT)); + msgq_to_rlc->send(LTE_FDD_ENB_MESSAGE_TYPE_RLC_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_RLC, + (LTE_FDD_ENB_MESSAGE_UNION *)&rlc_sdu_ready, + sizeof(LTE_FDD_ENB_RLC_SDU_READY_MSG_STRUCT)); // Delete the SDU sdu_ready->rb->delete_next_pdcp_sdu(); @@ -327,5 +437,88 @@ void LTE_fdd_enb_pdcp::handle_sdu_ready(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT *s sdu_ready->user->get_c_rnti(), LTE_fdd_enb_rb_text[sdu_ready->rb->get_rb_id()]); } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_PDCP, + __FILE__, + __LINE__, + "Received SDU ready with no data, RNTI=%u, RB=%s", + sdu_ready->user->get_c_rnti(), + LTE_fdd_enb_rb_text[sdu_ready->rb->get_rb_id()]); + } +} + +/*****************************/ +/* GW Message Handlers */ +/*****************************/ +void LTE_fdd_enb_pdcp::handle_data_sdu_ready(LTE_FDD_ENB_PDCP_DATA_SDU_READY_MSG_STRUCT *data_sdu_ready) +{ + LTE_FDD_ENB_RLC_SDU_READY_MSG_STRUCT rlc_sdu_ready; + LIBLTE_PDCP_DATA_PDU_WITH_LONG_SN_STRUCT contents; + LIBLTE_BYTE_MSG_STRUCT pdu; + LIBLTE_BYTE_MSG_STRUCT *sdu; + + if(LTE_FDD_ENB_ERROR_NONE == data_sdu_ready->rb->get_next_pdcp_data_sdu(&sdu)) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_PDCP, + __FILE__, + __LINE__, + sdu, + "Received data SDU from GW for RNTI=%u and RB=%s", + data_sdu_ready->user->get_c_rnti(), + LTE_fdd_enb_rb_text[data_sdu_ready->rb->get_rb_id()]); + + if(data_sdu_ready->rb->get_rb_id() >= LTE_FDD_ENB_RB_DRB1 && + data_sdu_ready->rb->get_pdcp_config() == LTE_FDD_ENB_PDCP_CONFIG_LONG_SN) + { + // Pack the data PDU + contents.count = data_sdu_ready->rb->get_pdcp_tx_count(); + liblte_pdcp_pack_data_pdu_with_long_sn(&contents, + sdu, + &pdu); + + // Increment the SN + data_sdu_ready->rb->set_pdcp_tx_count(contents.count + 1); + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_PDCP, + __FILE__, + __LINE__, + &pdu, + "Sending PDU for RNTI=%u and RB=%s", + data_sdu_ready->user->get_c_rnti(), + LTE_fdd_enb_rb_text[data_sdu_ready->rb->get_rb_id()]); + + // Queue the PDU for RLC + data_sdu_ready->rb->queue_rlc_sdu(&pdu); + + // Signal RLC + rlc_sdu_ready.user = data_sdu_ready->user; + rlc_sdu_ready.rb = data_sdu_ready->rb; + msgq_to_rlc->send(LTE_FDD_ENB_MESSAGE_TYPE_RLC_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_RLC, + (LTE_FDD_ENB_MESSAGE_UNION *)&rlc_sdu_ready, + sizeof(LTE_FDD_ENB_RLC_SDU_READY_MSG_STRUCT)); + + // Delete the SDU + data_sdu_ready->rb->delete_next_pdcp_data_sdu(); + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_PDCP, + __FILE__, + __LINE__, + "Received data SDU from GW for invalid RB=%s, RNTI=%u", + LTE_fdd_enb_rb_text[data_sdu_ready->rb->get_rb_id()], + data_sdu_ready->user->get_c_rnti()); + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_PDCP, + __FILE__, + __LINE__, + "Received data SDU ready from GW with no data, RNTI=%u, RB=%s", + data_sdu_ready->user->get_c_rnti(), + LTE_fdd_enb_rb_text[data_sdu_ready->rb->get_rb_id()]); } } diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_phy.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_phy.cc old mode 100644 new mode 100755 index 6d8572e..2f5abe9 --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_phy.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_phy.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_phy.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -37,6 +37,23 @@ 05/04/2014 Ben Wojtowicz Added PCAP support, PHICH support, and timer support. 06/15/2014 Ben Wojtowicz Changed fn_combo to current_tti. + 08/03/2014 Ben Wojtowicz Added support for limiting PCAP output. + 12/16/2014 Ben Wojtowicz Added ol extension to message queue. + 02/15/2015 Ben Wojtowicz Moved to new message queue and changed the + RTS timing. + 03/11/2015 Ben Wojtowicz Changed the RTS timing. + 07/25/2015 Ben Wojtowicz Combined the DL and UL schedule messages into + a single PHY schedule message and using the + new radio interface. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t. + 03/12/2016 Ben Wojtowicz Added PUCCH support. + 07/03/2016 Ben Wojtowicz Not including UL PDCCH allocations in a check + of how many DL PRBs are being used. + 07/31/2016 Ben Wojtowicz Added an external interface for getting the + current TTIs. + 07/29/2017 Ben Wojtowicz Added IPC direct to a UE PHY, added SR + support, and using the latest LTE library. *******************************************************************************/ @@ -46,6 +63,7 @@ #include "LTE_fdd_enb_phy.h" #include "LTE_fdd_enb_radio.h" +#include "libtools_scoped_lock.h" /******************************************************************************* DEFINES @@ -61,8 +79,8 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_enb_phy* LTE_fdd_enb_phy::instance = NULL; -boost::mutex phy_instance_mutex; +LTE_fdd_enb_phy* LTE_fdd_enb_phy::instance = NULL; +static pthread_mutex_t phy_instance_mutex = PTHREAD_MUTEX_INITIALIZER; /******************************************************************************* CLASS IMPLEMENTATIONS @@ -73,7 +91,7 @@ boost::mutex phy_instance_mutex; /*******************/ LTE_fdd_enb_phy* LTE_fdd_enb_phy::get_instance(void) { - boost::mutex::scoped_lock lock(phy_instance_mutex); + libtools_scoped_lock lock(phy_instance_mutex); if(NULL == instance) { @@ -84,7 +102,7 @@ LTE_fdd_enb_phy* LTE_fdd_enb_phy::get_instance(void) } void LTE_fdd_enb_phy::cleanup(void) { - boost::mutex::scoped_lock lock(phy_instance_mutex); + libtools_scoped_lock lock(phy_instance_mutex); if(NULL != instance) { @@ -98,27 +116,37 @@ void LTE_fdd_enb_phy::cleanup(void) /********************************/ LTE_fdd_enb_phy::LTE_fdd_enb_phy() { + sem_init(&sys_info_sem, 0, 1); + sem_init(&dl_sched_sem, 0, 1); + sem_init(&ul_sched_sem, 0, 1); interface = NULL; started = false; } LTE_fdd_enb_phy::~LTE_fdd_enb_phy() { stop(); + sem_destroy(&ul_sched_sem); + sem_destroy(&dl_sched_sem); + sem_destroy(&sys_info_sem); } /********************/ /* Start/Stop */ /********************/ -void LTE_fdd_enb_phy::start(LTE_fdd_enb_interface *iface) +void LTE_fdd_enb_phy::start(LTE_fdd_enb_msgq *from_mac, + LTE_fdd_enb_msgq *to_mac, + bool direct_to_ue, + LTE_fdd_enb_interface *iface) { - LTE_fdd_enb_radio *radio = LTE_fdd_enb_radio::get_instance(); - LTE_fdd_enb_msgq_cb cb(<E_fdd_enb_msgq_cb_wrapper, this); - LIBLTE_PHY_FS_ENUM fs; - uint32 i; - uint32 j; - uint32 k; - uint32 samp_rate; - uint8 prach_cnfg_idx; + LTE_fdd_enb_radio *radio = LTE_fdd_enb_radio::get_instance(); + LTE_fdd_enb_msgq_cb mac_cb(<E_fdd_enb_msgq_cb_wrapper, this); + libtools_ipc_msgq_cb ue_cb(&libtools_ipc_msgq_cb_wrapper, this); + LIBLTE_PHY_FS_ENUM fs; + uint32 i; + uint32 j; + uint32 k; + uint32 samp_rate; + uint8 prach_cnfg_idx; if(!started) { @@ -126,7 +154,7 @@ void LTE_fdd_enb_phy::start(LTE_fdd_enb_interface *iface) update_sys_info(); // Initialize phy - samp_rate = radio->get_sample_rate(); + samp_rate = radio->get_phy_sample_rate(); if(30720000 == samp_rate) { fs = LIBLTE_PHY_FS_30_72MHZ; @@ -163,7 +191,9 @@ void LTE_fdd_enb_phy::start(LTE_fdd_enb_interface *iface) sys_info.sib2.rr_config_common_sib.pusch_cnfg.ul_rs.group_hopping_enabled, sys_info.sib2.rr_config_common_sib.pusch_cnfg.ul_rs.sequence_hopping_enabled, sys_info.sib2.rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift, - 0); + 0, + sys_info.sib2.rr_config_common_sib.pucch_cnfg.n_cs_an, + sys_info.sib2.rr_config_common_sib.pucch_cnfg.delta_pucch_shift); // Downlink for(i=0; i<10; i++) @@ -173,6 +203,7 @@ void LTE_fdd_enb_phy::start(LTE_fdd_enb_interface *iface) dl_schedule[i].ul_allocations.N_alloc = 0; ul_schedule[i].current_tti = i; ul_schedule[i].decodes.N_alloc = 0; + ul_schedule[i].N_pucch = 0; } pcfich.cfi = 2; // FIXME: Make this dynamic every subfr for(i=0; i<10; i++) @@ -280,11 +311,18 @@ void LTE_fdd_enb_phy::start(LTE_fdd_enb_interface *iface) break; } - // Communication - mac_comm_msgq = new LTE_fdd_enb_msgq("mac_phy_mq", - cb); - phy_mac_mq = new boost::interprocess::message_queue(boost::interprocess::open_only, - "phy_mac_mq"); + // eNodeB communication + msgq_from_mac = from_mac; + msgq_to_mac = to_mac; + msgq_from_mac->attach_rx(mac_cb); + + // UE communication + if(direct_to_ue) + { + msgq_to_ue = new libtools_ipc_msgq("enb_ue", ue_cb); + }else{ + msgq_to_ue = NULL; + } interface = iface; started = true; @@ -296,10 +334,13 @@ void LTE_fdd_enb_phy::stop(void) { started = false; + if(NULL != msgq_to_ue) + { + delete msgq_to_ue; + } + liblte_phy_ul_cleanup(phy_struct); liblte_phy_cleanup(phy_struct); - - delete mac_comm_msgq; } } @@ -308,16 +349,15 @@ void LTE_fdd_enb_phy::stop(void) /****************************/ void LTE_fdd_enb_phy::update_sys_info(void) { - LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + libtools_scoped_lock lock(sys_info_sem); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); - sys_info_mutex.lock(); cnfg_db->get_sys_info(sys_info); - sys_info_mutex.unlock(); } uint32 LTE_fdd_enb_phy::get_n_cce(void) { - boost::mutex::scoped_lock lock(sys_info_mutex); - uint32 N_cce; + libtools_scoped_lock lock(sys_info_sem); + uint32 N_cce; liblte_phy_get_n_cce(phy_struct, liblte_rrc_phich_resource_num[sys_info.mib.phich_config.res], @@ -327,24 +367,25 @@ uint32 LTE_fdd_enb_phy::get_n_cce(void) return(N_cce); } +void LTE_fdd_enb_phy::get_current_ttis(uint32 *dl_tti, + uint32 *ul_tti) +{ + *dl_tti = dl_current_tti; + *ul_tti = ul_current_tti; +} /***********************/ /* Communication */ /***********************/ -void LTE_fdd_enb_phy::handle_mac_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) +void LTE_fdd_enb_phy::handle_mac_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) { - if(LTE_FDD_ENB_DEST_LAYER_PHY == msg->dest_layer || - LTE_FDD_ENB_DEST_LAYER_ANY == msg->dest_layer) + if(LTE_FDD_ENB_DEST_LAYER_PHY == msg.dest_layer || + LTE_FDD_ENB_DEST_LAYER_ANY == msg.dest_layer) { - switch(msg->type) + switch(msg.type) { - case LTE_FDD_ENB_MESSAGE_TYPE_DL_SCHEDULE: - handle_dl_schedule(&msg->msg.dl_schedule); - delete msg; - break; - case LTE_FDD_ENB_MESSAGE_TYPE_UL_SCHEDULE: - handle_ul_schedule(&msg->msg.ul_schedule); - delete msg; + case LTE_FDD_ENB_MESSAGE_TYPE_PHY_SCHEDULE: + handle_phy_schedule(&msg.msg.phy_schedule); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_WARNING, @@ -352,8 +393,7 @@ void LTE_fdd_enb_phy::handle_mac_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) __FILE__, __LINE__, "Received invalid message %s", - LTE_fdd_enb_message_type_text[msg->type]); - delete msg; + LTE_fdd_enb_message_type_text[msg.type]); break; } }else{ @@ -362,8 +402,24 @@ void LTE_fdd_enb_phy::handle_mac_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) __FILE__, __LINE__, "Received message for invalid layer %s", - LTE_fdd_enb_dest_layer_text[msg->dest_layer]); - delete msg; + LTE_fdd_enb_dest_layer_text[msg.dest_layer]); + } +} +void LTE_fdd_enb_phy::handle_ue_msg(LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT *msg) +{ + switch(msg->type) + { + case LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_KILL: + msgq_to_ue = NULL; + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_PHY, + __FILE__, + __LINE__, + "Received invalid UE message %s", + libtools_ipc_msgq_message_type_text[msg->type]); + break; } } @@ -380,6 +436,13 @@ void LTE_fdd_enb_phy::radio_interface(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf, // 2) generate the next downlink subframe process_ul(rx_buf); process_dl(tx_buf); + + if(NULL != msgq_to_ue) + { + msgq_to_ue->send(LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_PHY_SAMPS, + (LIBTOOLS_IPC_MSGQ_MESSAGE_UNION *)tx_buf, + sizeof(LIBTOOLS_IPC_MSGQ_PHY_SAMPS_MSG_STRUCT)); + } } } void LTE_fdd_enb_phy::radio_interface(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf) @@ -391,73 +454,79 @@ void LTE_fdd_enb_phy::radio_interface(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf) /******************/ /* Downlink */ /******************/ -void LTE_fdd_enb_phy::handle_dl_schedule(LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT *dl_sched) +void LTE_fdd_enb_phy::handle_phy_schedule(LTE_FDD_ENB_PHY_SCHEDULE_MSG_STRUCT *phy_sched) { - boost::mutex::scoped_lock lock(dl_sched_mutex); + sem_wait(&dl_sched_sem); + sem_wait(&ul_sched_sem); - if(dl_sched->current_tti < dl_current_tti && - (dl_current_tti - dl_sched->current_tti) < (LTE_FDD_ENB_CURRENT_TTI_MAX/2)) + if(phy_sched->dl_sched.current_tti < dl_current_tti && + (dl_current_tti - phy_sched->dl_sched.current_tti) < (LTE_FDD_ENB_CURRENT_TTI_MAX/2)) { interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, LTE_FDD_ENB_DEBUG_LEVEL_PHY, __FILE__, __LINE__, "Late DL subframe from MAC:%u, PHY is currently on %u", - dl_sched->current_tti, + phy_sched->dl_sched.current_tti, dl_current_tti); late_subfr = true; - if(dl_sched->current_tti == last_rts_current_tti) + if(phy_sched->dl_sched.current_tti == last_rts_current_tti) { late_subfr = false; } }else{ - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, - LTE_FDD_ENB_DEBUG_LEVEL_PHY, - __FILE__, - __LINE__, - "Received PDSCH schedule from MAC CURRENT_TTI:MAC=%u,PHY=%u N_dl_allocs=%u N_ul_allocs=%u", - dl_sched->current_tti, - dl_current_tti, - dl_sched->dl_allocations.N_alloc, - dl_sched->ul_allocations.N_alloc); + if(phy_sched->dl_sched.dl_allocations.N_alloc || + phy_sched->dl_sched.ul_allocations.N_alloc) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_PHY, + __FILE__, + __LINE__, + "Received PDSCH schedule from MAC CURRENT_TTI:MAC=%u,PHY=%u N_dl_allocs=%u N_ul_allocs=%u", + phy_sched->dl_sched.current_tti, + dl_current_tti, + phy_sched->dl_sched.dl_allocations.N_alloc, + phy_sched->dl_sched.ul_allocations.N_alloc); + } - memcpy(&dl_schedule[dl_sched->current_tti%10], dl_sched, sizeof(LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT)); + memcpy(&dl_schedule[phy_sched->dl_sched.current_tti%10], &phy_sched->dl_sched, sizeof(LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT)); late_subfr = false; } -} -void LTE_fdd_enb_phy::handle_ul_schedule(LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT *ul_sched) -{ - boost::mutex::scoped_lock lock(ul_sched_mutex); - - if(ul_sched->current_tti < ul_current_tti && - (ul_current_tti - ul_sched->current_tti) < (LTE_FDD_ENB_CURRENT_TTI_MAX/2)) + if(phy_sched->ul_sched.current_tti < ul_current_tti && + (ul_current_tti - phy_sched->ul_sched.current_tti) < (LTE_FDD_ENB_CURRENT_TTI_MAX/2)) { interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, LTE_FDD_ENB_DEBUG_LEVEL_PHY, __FILE__, __LINE__, "Late UL subframe from MAC:%u, PHY is currently on %u", - ul_sched->current_tti, + phy_sched->ul_sched.current_tti, ul_current_tti); }else{ - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, - LTE_FDD_ENB_DEBUG_LEVEL_PHY, - __FILE__, - __LINE__, - "Received PUSCH schedule from MAC CURRENT_TTI:MAC=%u,PHY=%u N_ul_decodes=%u", - ul_sched->current_tti, - ul_current_tti, - ul_sched->decodes.N_alloc); + if(phy_sched->ul_sched.decodes.N_alloc) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_PHY, + __FILE__, + __LINE__, + "Received PUSCH schedule from MAC CURRENT_TTI:MAC=%u,PHY=%u N_ul_decodes=%u", + phy_sched->ul_sched.current_tti, + ul_current_tti, + phy_sched->ul_sched.decodes.N_alloc); + } - memcpy(&ul_schedule[ul_sched->current_tti%10], ul_sched, sizeof(LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT)); + memcpy(&ul_schedule[phy_sched->ul_sched.current_tti%10], &phy_sched->ul_sched, sizeof(LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT)); } + + sem_post(&ul_sched_sem); + sem_post(&dl_sched_sem); } void LTE_fdd_enb_phy::process_dl(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf) { LTE_fdd_enb_radio *radio = LTE_fdd_enb_radio::get_instance(); - boost::mutex::scoped_lock lock(sys_info_mutex); + libtools_scoped_lock lock(sys_info_sem); LTE_FDD_ENB_READY_TO_SEND_MSG_STRUCT rts; uint32 p; uint32 i; @@ -508,11 +577,18 @@ void LTE_fdd_enb_phy::process_dl(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf) sys_info.mib.sfn_div_4 = sfn/4; liblte_rrc_pack_bcch_bch_msg(&sys_info.mib, &dl_rrc_msg); - interface->send_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, - 0xFFFFFFFF, - dl_current_tti, - dl_rrc_msg.msg, - dl_rrc_msg.N_bits); + if(!sys_info.mib_pcap_sent) + { + interface->send_lte_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, + 0xFFFFFFFF, + dl_current_tti, + dl_rrc_msg.msg, + dl_rrc_msg.N_bits); + if(!sys_info.continuous_sib_pcap) + { + sys_info.mib_pcap_sent = true; + } + } liblte_phy_bch_channel_encode(phy_struct, dl_rrc_msg.msg, dl_rrc_msg.N_bits, @@ -528,35 +604,49 @@ void LTE_fdd_enb_phy::process_dl(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf) 0 == (sfn % 2)) { // SIB1 - interface->send_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, - LIBLTE_MAC_SI_RNTI, - dl_current_tti, - sys_info.sib1_alloc.msg.msg, - sys_info.sib1_alloc.msg.N_bits); + if(!sys_info.sib1_pcap_sent) + { + interface->send_lte_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, + LIBLTE_MAC_SI_RNTI, + dl_current_tti, + sys_info.sib1_alloc.msg[0].msg, + sys_info.sib1_alloc.msg[0].N_bits); + if(!sys_info.continuous_sib_pcap) + { + sys_info.sib1_pcap_sent = true; + } + } memcpy(&pdcch.alloc[pdcch.N_alloc], &sys_info.sib1_alloc, sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); - liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg.N_bits, + liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg[0].N_bits, dl_subframe.num, sys_info.N_rb_dl, pdcch.alloc[pdcch.N_alloc].rnti, &pdcch.alloc[pdcch.N_alloc].tbs, &pdcch.alloc[pdcch.N_alloc].mcs, &pdcch.alloc[pdcch.N_alloc].N_prb); - pdcch.alloc[pdcch.N_alloc].rv_idx = (uint32)ceilf(1.5 * ((sfn / 2) % 4)) % 4; //36.321 section 5.3.1 - pdcch.N_alloc++; + pdcch.alloc[pdcch.N_alloc].rv_idx = (uint32)ceilf(1.5 * ((sfn / 2) % 4)) % 4; //36.321 section 5.3.1 + pdcch.alloc[pdcch.N_alloc++].dl_alloc = true; } if((0 * sys_info.si_win_len)%10 <= dl_subframe.num && (1 * sys_info.si_win_len)%10 > dl_subframe.num && ((0 * sys_info.si_win_len)/10) == (sfn % sys_info.si_periodicity_T)) { // SIs in 1st scheduling info list entry - interface->send_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, - LIBLTE_MAC_SI_RNTI, - dl_current_tti, - sys_info.sib_alloc[0].msg.msg, - sys_info.sib_alloc[0].msg.N_bits); + if(!sys_info.sib_pcap_sent[0]) + { + interface->send_lte_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, + LIBLTE_MAC_SI_RNTI, + dl_current_tti, + sys_info.sib_alloc[0].msg[0].msg, + sys_info.sib_alloc[0].msg[0].N_bits); + if(!sys_info.continuous_sib_pcap) + { + sys_info.sib_pcap_sent[0] = true; + } + } memcpy(&pdcch.alloc[pdcch.N_alloc], &sys_info.sib_alloc[0], sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); // FIXME: This was a hack to allow SIB2 decoding with 1.4MHz BW due to overlap with MIB - if(LIBLTE_SUCCESS == liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg.N_bits, + if(LIBLTE_SUCCESS == liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg[0].N_bits, dl_subframe.num, sys_info.N_rb_dl, pdcch.alloc[pdcch.N_alloc].rnti, @@ -564,47 +654,55 @@ void LTE_fdd_enb_phy::process_dl(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf) &pdcch.alloc[pdcch.N_alloc].mcs, &pdcch.alloc[pdcch.N_alloc].N_prb)) { - pdcch.N_alloc++; + pdcch.alloc[pdcch.N_alloc++].dl_alloc = true; } } for(i=1; isend_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, - LIBLTE_MAC_SI_RNTI, - dl_current_tti, - sys_info.sib_alloc[i].msg.msg, - sys_info.sib_alloc[i].msg.N_bits); + if(!sys_info.sib_pcap_sent[i]) + { + interface->send_lte_pcap_msg(LTE_FDD_ENB_PCAP_DIRECTION_DL, + LIBLTE_MAC_SI_RNTI, + dl_current_tti, + sys_info.sib_alloc[i].msg[0].msg, + sys_info.sib_alloc[i].msg[0].N_bits); + if(!sys_info.continuous_sib_pcap) + { + sys_info.sib_pcap_sent[i] = true; + } + } memcpy(&pdcch.alloc[pdcch.N_alloc], &sys_info.sib_alloc[i], sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); - liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg.N_bits, + liblte_phy_get_tbs_mcs_and_n_prb_for_dl(pdcch.alloc[pdcch.N_alloc].msg[0].N_bits, dl_subframe.num, sys_info.N_rb_dl, pdcch.alloc[pdcch.N_alloc].rnti, &pdcch.alloc[pdcch.N_alloc].tbs, &pdcch.alloc[pdcch.N_alloc].mcs, &pdcch.alloc[pdcch.N_alloc].N_prb); - pdcch.N_alloc++; + pdcch.alloc[pdcch.N_alloc++].dl_alloc = true; } } // Handle user data - dl_sched_mutex.lock(); + sem_wait(&dl_sched_sem); if(dl_schedule[dl_current_tti%10].current_tti == dl_current_tti) { for(i=0; isend_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, LTE_FDD_ENB_DEBUG_LEVEL_PHY, __FILE__, @@ -613,15 +711,18 @@ void LTE_fdd_enb_phy::process_dl(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf) dl_schedule[subfn].current_tti, dl_current_tti); } - dl_sched_mutex.unlock(); + sem_post(&dl_sched_sem); // Handle PDCCH and PDSCH for(i=0; i phy_struct->N_rb_dl) @@ -667,23 +768,22 @@ void LTE_fdd_enb_phy::process_dl(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf) &tx_buf->i_buf[p][0], &tx_buf->q_buf[p][0]); } - tx_buf->current_tti = dl_current_tti; + tx_buf->N_samps_per_ant = phy_struct->N_samps_per_subfr; + tx_buf->current_tti = dl_current_tti; + tx_buf->N_ant = sys_info.N_ant; // Update current TTI dl_current_tti = (dl_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); // Send READY TO SEND message to MAC - if(!late_subfr) - { - rts.dl_current_tti = (dl_current_tti + 2) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - rts.ul_current_tti = (ul_current_tti + 2) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - last_rts_current_tti = rts.dl_current_tti; - LTE_fdd_enb_msgq::send(phy_mac_mq, - LTE_FDD_ENB_MESSAGE_TYPE_READY_TO_SEND, - LTE_FDD_ENB_DEST_LAYER_MAC, - (LTE_FDD_ENB_MESSAGE_UNION *)&rts, - sizeof(rts)); - } + rts.dl_current_tti = (dl_current_tti + 2) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + rts.ul_current_tti = (ul_current_tti + 2) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + rts.late = late_subfr; + last_rts_current_tti = rts.dl_current_tti; + msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_READY_TO_SEND, + LTE_FDD_ENB_DEST_LAYER_MAC, + (LTE_FDD_ENB_MESSAGE_UNION *)&rts, + sizeof(rts)); // Send samples to radio radio->send(tx_buf); @@ -694,12 +794,14 @@ void LTE_fdd_enb_phy::process_dl(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf) /****************/ void LTE_fdd_enb_phy::process_ul(LTE_FDD_ENB_RADIO_RX_BUF_STRUCT *rx_buf) { - uint32 N_skipped_subfrs = 0; - uint32 sfn; - uint32 i; - uint32 I_prb_ra; - uint32 n_group_phich; - uint32 n_seq_phich; + LIBLTE_ERROR_ENUM subfr_err; + LIBLTE_ERROR_ENUM pucch_err; + uint32 N_skipped_subfrs = 0; + uint32 sfn; + uint32 i; + uint32 I_prb_ra; + uint32 n_group_phich; + uint32 n_seq_phich; // Check the received current_tti if(rx_buf->current_tti != ul_current_tti) @@ -728,72 +830,112 @@ void LTE_fdd_enb_phy::process_ul(LTE_FDD_ENB_RADIO_RX_BUF_STRUCT *rx_buf) { prach_decode.current_tti = ul_current_tti; liblte_phy_detect_prach(phy_struct, - rx_buf->i_buf, - rx_buf->q_buf, + rx_buf->i_buf[0], + rx_buf->q_buf[0], sys_info.sib2.rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset, &prach_decode.num_preambles, prach_decode.preamble, prach_decode.timing_adv); - LTE_fdd_enb_msgq::send(phy_mac_mq, - LTE_FDD_ENB_MESSAGE_TYPE_PRACH_DECODE, - LTE_FDD_ENB_DEST_LAYER_MAC, - (LTE_FDD_ENB_MESSAGE_UNION *)&prach_decode, - sizeof(LTE_FDD_ENB_PRACH_DECODE_MSG_STRUCT)); + msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_PRACH_DECODE, + LTE_FDD_ENB_DEST_LAYER_MAC, + (LTE_FDD_ENB_MESSAGE_UNION *)&prach_decode, + sizeof(LTE_FDD_ENB_PRACH_DECODE_MSG_STRUCT)); } } } - // Handle PUCCH - // FIXME + sem_wait(&ul_sched_sem); + if(0 != ul_schedule[ul_subframe.num].N_pucch || + 0 != ul_schedule[ul_subframe.num].decodes.N_alloc) + { + subfr_err = liblte_phy_get_ul_subframe(phy_struct, + rx_buf->i_buf[0], + rx_buf->q_buf[0], + &ul_subframe); + } - // Handle PUSCH - ul_sched_mutex.lock(); - if(0 != ul_schedule[ul_subframe.num].decodes.N_alloc) + // Handle PUCCH + if(LIBLTE_SUCCESS == subfr_err && + 0 != ul_schedule[ul_subframe.num].N_pucch) { - if(LIBLTE_SUCCESS == liblte_phy_get_ul_subframe(phy_struct, - rx_buf->i_buf, - rx_buf->q_buf, - &ul_subframe)) + pucch_decode.current_tti = ul_current_tti; + for(i=0; iN_group_phich; - n_seq_phich = (I_prb_ra/phy_struct->N_group_phich) % (2*phy_struct->N_sf_phich); - - // Attempt decode - if(LIBLTE_SUCCESS == liblte_phy_pusch_channel_decode(phy_struct, - &ul_subframe, - &ul_schedule[ul_subframe.num].decodes.alloc[i], - sys_info.N_id_cell, - 1, - pusch_decode.msg.msg, - &pusch_decode.msg.N_bits)) + if(LIBLTE_SUCCESS == pucch_err) { - pusch_decode.current_tti = ul_current_tti; - pusch_decode.rnti = ul_schedule[ul_subframe.num].decodes.alloc[i].rnti; - - LTE_fdd_enb_msgq::send(phy_mac_mq, - LTE_FDD_ENB_MESSAGE_TYPE_PUSCH_DECODE, - LTE_FDD_ENB_DEST_LAYER_MAC, - (LTE_FDD_ENB_MESSAGE_UNION *)&pusch_decode, - sizeof(LTE_FDD_ENB_PUSCH_DECODE_MSG_STRUCT)); - - // Add ACK to PHICH - phich[(ul_subframe.num + 4) % 10].present[n_group_phich][n_seq_phich] = true; - phich[(ul_subframe.num + 4) % 10].b[n_group_phich][n_seq_phich] = 1; + pucch_decode.msg.msg[0] = 1; + pucch_decode.msg.N_bits = 1; }else{ - // Add NACK to PHICH - phich[(ul_subframe.num + 4) % 10].present[n_group_phich][n_seq_phich] = true; - phich[(ul_subframe.num + 4) % 10].b[n_group_phich][n_seq_phich] = 0; + pucch_decode.msg.msg[0] = 0; + pucch_decode.msg.N_bits = 1; } + msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_PUCCH_DECODE, + LTE_FDD_ENB_DEST_LAYER_MAC, + (LTE_FDD_ENB_MESSAGE_UNION *)&pucch_decode, + sizeof(LTE_FDD_ENB_PUCCH_DECODE_MSG_STRUCT)); + }else if(LIBLTE_SUCCESS == pucch_err){ + msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_PUCCH_DECODE, + LTE_FDD_ENB_DEST_LAYER_MAC, + (LTE_FDD_ENB_MESSAGE_UNION *)&pucch_decode, + sizeof(LTE_FDD_ENB_PUCCH_DECODE_MSG_STRUCT)); + } + } + } + ul_schedule[ul_subframe.num].N_pucch = 0; + + // Handle PUSCH + if(LIBLTE_SUCCESS == subfr_err && + 0 != ul_schedule[ul_subframe.num].decodes.N_alloc) + { + for(i=0; iN_group_phich; + n_seq_phich = (I_prb_ra/phy_struct->N_group_phich) % (2*phy_struct->N_sf_phich); + + // Attempt decode + if(LIBLTE_SUCCESS == liblte_phy_pusch_channel_decode(phy_struct, + &ul_subframe, + &ul_schedule[ul_subframe.num].decodes.alloc[i], + sys_info.N_id_cell, + 1, + pusch_decode.msg.msg, + &pusch_decode.msg.N_bits)) + { + pusch_decode.current_tti = ul_current_tti; + pusch_decode.rnti = ul_schedule[ul_subframe.num].decodes.alloc[i].rnti; + + msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_PUSCH_DECODE, + LTE_FDD_ENB_DEST_LAYER_MAC, + (LTE_FDD_ENB_MESSAGE_UNION *)&pusch_decode, + sizeof(LTE_FDD_ENB_PUSCH_DECODE_MSG_STRUCT)); + + // Add ACK to PHICH + phich[(ul_subframe.num + 4) % 10].present[n_group_phich][n_seq_phich] = true; + phich[(ul_subframe.num + 4) % 10].b[n_group_phich][n_seq_phich] = 1; + }else{ + // Add NACK to PHICH + phich[(ul_subframe.num + 4) % 10].present[n_group_phich][n_seq_phich] = true; + phich[(ul_subframe.num + 4) % 10].b[n_group_phich][n_seq_phich] = 0; } } } ul_schedule[ul_subframe.num].decodes.N_alloc = 0; - ul_sched_mutex.unlock(); + sem_post(&ul_sched_sem); // Update counters ul_current_tti = (ul_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_radio.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_radio.cc old mode 100644 new mode 100755 index 8282b59..abb2fe2 --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_radio.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_radio.cc @@ -1,7 +1,8 @@ #line 2 "LTE_fdd_enb_radio.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz + Copyright 2016 Przemek Bereski (bladeRF support) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -35,6 +36,23 @@ 04/12/2014 Ben Wojtowicz Pulled in a patch from Max Suraev for more descriptive start failures. 06/15/2014 Ben Wojtowicz Changed fn_combo to current_tti. + 07/22/2014 Ben Wojtowicz Added clock source as a configurable + parameter. + 08/03/2014 Ben Wojtowicz Fixed clock_source bug. + 09/03/2014 Ben Wojtowicz Fixed stop issue. + 12/16/2014 Ben Wojtowicz Pulled in a patch from Ruben Merz to add + USRP X300 support. + 12/24/2014 Ben Wojtowicz Added more time spec information in debug. + 07/25/2015 Ben Wojtowicz Added parameters to abstract PHY sample rate + from radio sample rate. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t. + 07/03/2016 Ben Wojtowicz Massive restructuring to support the addition + of bladeRF as a radio choice and setting + processor affinity. + 07/03/2016 Przemek Bereski Addition of bladeRF as a radio choice. + 10/09/2016 Ben Wojtowicz Added typecast for bladerf_get_timestamp(). + 07/29/2017 Ben Wojtowicz Using the latest tools library. *******************************************************************************/ @@ -45,6 +63,7 @@ #include "LTE_fdd_enb_radio.h" #include "LTE_fdd_enb_phy.h" #include "liblte_interface.h" +#include "libtools_scoped_lock.h" #include #include #include @@ -57,6 +76,11 @@ // Change this to 1 to turn on RADIO DEBUG #define EXTRA_RADIO_DEBUG 0 +// bladeRF defines +#define BLADERF_NUM_BUFFERS 256 +#define BLADERF_NUM_TRANSFERS 32 +#define BLADERF_TIMEOUT_MS 4000 + /******************************************************************************* TYPEDEFS *******************************************************************************/ @@ -66,19 +90,949 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_enb_radio* LTE_fdd_enb_radio::instance = NULL; -boost::mutex radio_instance_mutex; +LTE_fdd_enb_radio* LTE_fdd_enb_radio::instance = NULL; +static pthread_mutex_t radio_instance_mutex = PTHREAD_MUTEX_INITIALIZER; + +/******************************************************************************* + LOCAL FUNCTIONS +*******************************************************************************/ + +static uint32 find_usrps(LTE_FDD_ENB_AVAILABLE_RADIOS_STRUCT *radios) +{ + uhd::device_addr_t hint; + uhd::device_addrs_t devs = uhd::device::find(hint); + size_t i; + + if(NULL != radios) + { + for(i=0; iradio[radios->num_radios].name = devs[i].to_string(); + radios->radio[radios->num_radios++].type = LTE_FDD_ENB_RADIO_TYPE_USRP_B2X0; + } + } + + return(devs.size()); +} + +static uint32 find_usrps(void) +{ + return(find_usrps(NULL)); +} + +static uint32 find_bladerfs(LTE_FDD_ENB_AVAILABLE_RADIOS_STRUCT *radios) +{ + struct bladerf_devinfo *devs; + size_t i; + int N_devs; + + N_devs = bladerf_get_device_list(&devs); + if(N_devs < 0) + { + return(0); + } + if(NULL != radios) + { + for(i=0; iradio[radios->num_radios].name = "bladerf-"; + radios->radio[radios->num_radios].name += devs[i].serial; + radios->radio[radios->num_radios++].type = LTE_FDD_ENB_RADIO_TYPE_BLADERF; + } + } + bladerf_free_device_list(devs); + + return(N_devs); +} + +static uint32 find_bladerfs(void) +{ + return(find_bladerfs(NULL)); +} /******************************************************************************* CLASS IMPLEMENTATIONS *******************************************************************************/ +/**************************************/ +/* No-RF Constructor/Destructor */ +/**************************************/ +LTE_fdd_enb_radio_no_rf::LTE_fdd_enb_radio_no_rf() +{ + // Sleep time between subframes + sleep_time.tv_sec = 0; + sleep_time.tv_nsec = 1000000; +} +LTE_fdd_enb_radio_no_rf::~LTE_fdd_enb_radio_no_rf() +{ +} + +/*******************************/ +/* No-RF Radio Functions */ +/*******************************/ +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_radio_no_rf::setup(void) +{ + return(LTE_FDD_ENB_ERROR_NONE); +} +void LTE_fdd_enb_radio_no_rf::teardown(void) +{ +} +void LTE_fdd_enb_radio_no_rf::send(void) +{ +} +void LTE_fdd_enb_radio_no_rf::receive(LTE_FDD_ENB_RADIO_PARAMS_STRUCT *radio_params) +{ + struct timespec time_rem; + + if(radio_params->init_needed) + { + // Signal PHY to generate first subframe + radio_params->phy->radio_interface(&radio_params->tx_radio_buf[1]); + radio_params->init_needed = false; + } + radio_params->rx_radio_buf[radio_params->buf_idx].current_tti = radio_params->rx_current_tti; + radio_params->phy->radio_interface(&radio_params->tx_radio_buf[radio_params->buf_idx], + &radio_params->rx_radio_buf[radio_params->buf_idx]); + radio_params->buf_idx = (radio_params->buf_idx + 1) % 2; + radio_params->rx_current_tti = (radio_params->rx_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + nanosleep(&sleep_time, &time_rem); +} + +/******************************************/ +/* USRP-B2X0 Constructor/Destructor */ +/******************************************/ +LTE_fdd_enb_radio_usrp_b2x0::LTE_fdd_enb_radio_usrp_b2x0() +{ +} +LTE_fdd_enb_radio_usrp_b2x0::~LTE_fdd_enb_radio_usrp_b2x0() +{ +} + +/***********************************/ +/* USRP-B2X0 Radio Functions */ +/***********************************/ +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_radio_usrp_b2x0::setup(uint32 idx, + double bw, + int16 dl_earfcn, + int16 ul_earfcn, + std::string *clock_src, + uint32 samp_rate, + uint32 tx_gain, + uint32 rx_gain) +{ + uhd::device_addr_t hint; + uhd::device_addrs_t devs = uhd::device::find(hint); + uhd::stream_args_t stream_args("fc32"); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_CANT_START; + bool master_clock_set = false; + + try + { + // Setup the USRP + if(devs[idx-1]["type"] == "x300") + { + devs[idx-1]["master_clock_rate"] = "184320000"; + master_clock_set = true; + } + usrp = uhd::usrp::multi_usrp::make(devs[idx-1]); + usrp->set_clock_source(*clock_src); + if(!master_clock_set) + { + usrp->set_master_clock_rate(30720000); + if(2.0 >= fabs(usrp->get_master_clock_rate() - 30720000.0)) + { + master_clock_set = true; + } + } + if(master_clock_set) + { + usrp->set_tx_rate(samp_rate); + usrp->set_rx_rate(samp_rate); + usrp->set_tx_freq((double)liblte_interface_dl_earfcn_to_frequency(dl_earfcn)); + usrp->set_rx_freq((double)liblte_interface_ul_earfcn_to_frequency(ul_earfcn)); + usrp->set_tx_gain(tx_gain); + usrp->set_rx_gain(rx_gain); + + // Setup the TX and RX streams + tx_stream = usrp->get_tx_stream(stream_args); + rx_stream = usrp->get_rx_stream(stream_args); + N_tx_samps = tx_stream->get_max_num_samps(); + N_rx_samps = rx_stream->get_max_num_samps(); + if(N_rx_samps > LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ && + N_tx_samps > LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ) + { + N_rx_samps = LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ; + N_tx_samps = LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ; + + err = LTE_FDD_ENB_ERROR_NONE; + } + recv_size = N_rx_samps; + }else{ + err = LTE_FDD_ENB_ERROR_MASTER_CLOCK_FAIL; + } + }catch(...){ + // Nothing to do here + } + + return(err); +} +void LTE_fdd_enb_radio_usrp_b2x0::teardown(void) +{ + uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; + + usrp->issue_stream_cmd(cmd); +} +void LTE_fdd_enb_radio_usrp_b2x0::send(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *buf, + LTE_FDD_ENB_RADIO_PARAMS_STRUCT *radio_params) +{ + uhd::tx_metadata_t metadata; + uint32 samps_to_send = radio_params->N_samps_per_subfr; + uint32 idx = 0; + uint32 i; + uint32 p; + uint16 N_skipped_subfrs; + + // Setup metadata + metadata.has_time_spec = true; + metadata.start_of_burst = false; + metadata.end_of_burst = false; + + // Check current_tti + if(buf->current_tti != next_tx_current_tti) + { + if(buf->current_tti > next_tx_current_tti) + { + N_skipped_subfrs = buf->current_tti - next_tx_current_tti; + }else{ + N_skipped_subfrs = (buf->current_tti + LTE_FDD_ENB_CURRENT_TTI_MAX + 1) - next_tx_current_tti; + } + + next_tx_ts += uhd::time_spec_t::from_ticks(N_skipped_subfrs*radio_params->N_samps_per_subfr, + radio_params->fs); + next_tx_current_tti = (buf->current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + }else{ + next_tx_current_tti = (next_tx_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + } + + while(samps_to_send > N_tx_samps) + { + metadata.time_spec = next_tx_ts; + for(i=0; ii_buf[0][idx+i]/50.0, buf->q_buf[0][idx+i]/50.0); + for(p=1; pN_ant; p++) + { + tx_buf[i] += gr_complex(buf->i_buf[p][idx+i]/50.0, buf->q_buf[p][idx+i]/50.0); + } + tx_buf[i] /= radio_params->N_ant; + } +#if EXTRA_RADIO_DEBUG + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Sending subfr %lld %u", + metadata.time_spec.to_ticks(fs), + buf->current_tti); +#endif + tx_stream->send(tx_buf, N_tx_samps, metadata); + idx += N_tx_samps; + samps_to_send -= N_tx_samps; + next_tx_ts += uhd::time_spec_t::from_ticks(N_tx_samps, + radio_params->fs); + } + if(0 != samps_to_send) + { + metadata.time_spec = next_tx_ts; + for(i=0; ii_buf[0][idx+i]/50.0, buf->q_buf[0][idx+i]/50.0); + for(p=1; pN_ant; p++) + { + tx_buf[i] += gr_complex(buf->i_buf[p][idx+i]/50.0, buf->q_buf[p][idx+i]/50.0); + } + tx_buf[i] /= radio_params->N_ant; + } +#if EXTRA_RADIO_DEBUG + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Sending subfr %lld %u", + metadata.time_spec.to_ticks(fs), + buf->current_tti); +#endif + tx_stream->send(tx_buf, samps_to_send, metadata); + next_tx_ts += uhd::time_spec_t::from_ticks(samps_to_send, + radio_params->fs); + } +} +void LTE_fdd_enb_radio_usrp_b2x0::receive(LTE_FDD_ENB_RADIO_PARAMS_STRUCT *radio_params) +{ + uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS; + uint32 i; + + if(radio_params->init_needed) + { + // Setup time specs + next_tx_ts = uhd::time_spec_t::from_ticks(radio_params->samp_rate, + radio_params->samp_rate); // 1 second to make sure everything is setup + next_rx_ts = next_tx_ts; + next_rx_ts -= uhd::time_spec_t::from_ticks(radio_params->N_samps_per_subfr*2, + radio_params->samp_rate); // Retard RX by 2 subframes + next_rx_subfr_ts = next_rx_ts; + + // Reset USRP time + usrp->set_time_now(uhd::time_spec_t::from_ticks(0, radio_params->samp_rate)); + + // Signal PHY to generate first subframe + radio_params->phy->radio_interface(&radio_params->tx_radio_buf[1]); + + // Start streaming + cmd.stream_now = true; + usrp->issue_stream_cmd(cmd); + + radio_params->init_needed = false; + } + + if(!radio_params->rx_synced) + { + radio_params->num_samps = rx_stream->recv(rx_buf, recv_size, metadata); + check_ts = metadata.time_spec; + check_ts += uhd::time_spec_t::from_ticks(radio_params->num_samps, + radio_params->samp_rate); + + if(check_ts.to_ticks(radio_params->samp_rate) == next_rx_ts.to_ticks(radio_params->samp_rate)) + { + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "RX synced %lld %lld", + check_ts.to_ticks(radio_params->samp_rate), + next_rx_ts.to_ticks(radio_params->samp_rate)); + radio_params->samp_idx = 0; + radio_params->rx_synced = true; + }else{ + check_ts += uhd::time_spec_t::from_ticks(N_rx_samps, + radio_params->samp_rate); + if(check_ts.to_ticks(radio_params->samp_rate) > next_rx_ts.to_ticks(radio_params->samp_rate)) + { + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "RX modifying recv_size to sync %lld %lld", + check_ts.to_ticks(radio_params->samp_rate), + next_rx_ts.to_ticks(radio_params->samp_rate)); + check_ts -= uhd::time_spec_t::from_ticks(N_rx_samps, radio_params->samp_rate); + recv_size = (uint32)(next_rx_ts.to_ticks(radio_params->samp_rate) - check_ts.to_ticks(radio_params->samp_rate)); + } + } + }else{ + radio_params->num_samps = rx_stream->recv(rx_buf, N_rx_samps, metadata); + if(0 != radio_params->num_samps) + { + next_rx_ts_ticks = next_rx_ts.to_ticks(radio_params->samp_rate); + metadata_ts_ticks = metadata.time_spec.to_ticks(radio_params->samp_rate); + if(radio_params->num_samps != N_rx_samps) + { + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "RX packet size issue %u %u %lld %lld", + radio_params->num_samps, + N_rx_samps, + metadata_ts_ticks, + next_rx_ts_ticks); + } + if((next_rx_ts_ticks - metadata_ts_ticks) > 1) + { + // FIXME: Not sure this will ever happen + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "RX old time spec %lld %lld", + metadata_ts_ticks, + next_rx_ts_ticks); + }else if((metadata_ts_ticks - next_rx_ts_ticks) > 1){ + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "RX overrun %lld %lld", + metadata_ts_ticks, + next_rx_ts_ticks); + + // Determine how many subframes we are going to drop + radio_params->N_subfrs_dropped = ((metadata_ts_ticks - next_rx_ts_ticks)/radio_params->N_samps_per_subfr) + 2; + + // Jump the rx_current_tti + radio_params->rx_current_tti = (radio_params->rx_current_tti + radio_params->N_subfrs_dropped) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + + // Align the samples coming from the radio + radio_params->rx_synced = false; + next_rx_subfr_ts += uhd::time_spec_t::from_ticks(radio_params->N_subfrs_dropped*radio_params->N_samps_per_subfr, + radio_params->samp_rate); + next_rx_ts = next_rx_subfr_ts; + check_ts = metadata.time_spec; + check_ts += uhd::time_spec_t::from_ticks(radio_params->num_samps + N_rx_samps, + radio_params->samp_rate); + + if(check_ts.to_ticks(radio_params->samp_rate) > next_rx_ts.to_ticks(radio_params->samp_rate)) + { + check_ts -= uhd::time_spec_t::from_ticks(N_rx_samps, radio_params->samp_rate); + recv_size = (uint32)(next_rx_ts.to_ticks(radio_params->samp_rate) - check_ts.to_ticks(radio_params->samp_rate)); + }else{ + recv_size = N_rx_samps; + } + }else{ + // FIXME: May need to realign to 1920 sample boundries + radio_params->recv_idx = 0; + next_rx_ts += uhd::time_spec_t::from_ticks(radio_params->num_samps, + radio_params->samp_rate); + while(radio_params->num_samps > 0) + { + if((radio_params->samp_idx + radio_params->num_samps) <= radio_params->N_samps_per_subfr) + { + for(i=0; inum_samps; i++) + { + radio_params->rx_radio_buf[radio_params->buf_idx].i_buf[0][radio_params->samp_idx+i] = rx_buf[radio_params->recv_idx+i].real(); + radio_params->rx_radio_buf[radio_params->buf_idx].q_buf[0][radio_params->samp_idx+i] = rx_buf[radio_params->recv_idx+i].imag(); + } + radio_params->samp_idx += radio_params->num_samps; + + if(radio_params->samp_idx == radio_params->N_samps_per_subfr) + { +#if EXTRA_RADIO_DEBUG + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Receiving subfr %lld %u", + next_rx_subfr_ts.to_ticks(radio_params->samp_rate), + radio_params->rx_current_tti); +#endif + radio_params->rx_radio_buf[radio_params->buf_idx].current_tti = radio_params->rx_current_tti; + radio_params->phy->radio_interface(&radio_params->tx_radio_buf[radio_params->buf_idx], + &radio_params->rx_radio_buf[radio_params->buf_idx]); + radio_params->buf_idx = (radio_params->buf_idx + 1) % 2; + radio_params->rx_current_tti = (radio_params->rx_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + radio_params->samp_idx = 0; + next_rx_subfr_ts += uhd::time_spec_t::from_ticks(radio_params->N_samps_per_subfr, + radio_params->samp_rate); + } + radio_params->num_samps = 0; + }else{ + for(i=0; i<(radio_params->N_samps_per_subfr - radio_params->samp_idx); i++) + { + radio_params->rx_radio_buf[radio_params->buf_idx].i_buf[0][radio_params->samp_idx+i] = rx_buf[radio_params->recv_idx+i].real(); + radio_params->rx_radio_buf[radio_params->buf_idx].q_buf[0][radio_params->samp_idx+i] = rx_buf[radio_params->recv_idx+i].imag(); + } +#if EXTRA_RADIO_DEBUG + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Receiving subfr %lld %u", + next_rx_subfr_ts.to_ticks(radio_params->samp_rate), + radio_params->rx_current_tti); +#endif + radio_params->rx_radio_buf[radio_params->buf_idx].current_tti = radio_params->rx_current_tti; + radio_params->phy->radio_interface(&radio_params->tx_radio_buf[radio_params->buf_idx], + &radio_params->rx_radio_buf[radio_params->buf_idx]); + radio_params->buf_idx = (radio_params->buf_idx + 1) % 2; + radio_params->rx_current_tti = (radio_params->rx_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + radio_params->num_samps -= (radio_params->N_samps_per_subfr - radio_params->samp_idx); + radio_params->recv_idx = (radio_params->N_samps_per_subfr - radio_params->samp_idx); + radio_params->samp_idx = 0; + next_rx_subfr_ts += uhd::time_spec_t::from_ticks(radio_params->N_samps_per_subfr, + radio_params->samp_rate); + } + } + } + }else{ + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "RX error %u", + (uint32)metadata.error_code); + } + } +} + +/****************************************/ +/* BladeRF Constructor/Destructor */ +/****************************************/ +LTE_fdd_enb_radio_bladerf::LTE_fdd_enb_radio_bladerf() +{ + bladerf = NULL; + first_tx_sample = true; + memset(&metadata_tx, 0, sizeof(metadata_tx)); +} +LTE_fdd_enb_radio_bladerf::~LTE_fdd_enb_radio_bladerf() +{ +} + +/*********************************/ +/* BladeRF Radio Functions */ +/*********************************/ +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_radio_bladerf::setup(uint32 idx, + double bandwidth, + int16 dl_earfcn, + int16 ul_earfcn, + uint8 N_ant, + uint32 samp_rate, + uint32 N_samps_per_subfr) +{ + LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + struct bladerf_devinfo *devs; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_CANT_START; + uint32 bladerf_idx; + uint32 buffer_size; + int status; + + // Only supporting N_ant=1 + if(1 != N_ant) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Not supported N_ant=%u", + N_ant); + return(err); + } + + // Determine the bladerf index + bladerf_idx = idx - find_usrps() - 1; + if(bladerf_idx >= find_bladerfs()) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Incorrect bladerf index %u", + bladerf_idx); + return(err); + } + + // Open bladerf device + bladerf_get_device_list(&devs); + status = bladerf_open_with_devinfo(&bladerf, &devs[bladerf_idx]); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to open device: %s", + bladerf_strerror(status)); + return(err); + } + + // Set RX frequency + status = bladerf_set_frequency(bladerf, + BLADERF_MODULE_RX, + liblte_interface_ul_earfcn_to_frequency(ul_earfcn)); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set RX frequency: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Set RX sample rate + status = bladerf_set_sample_rate(bladerf, + BLADERF_MODULE_RX, + samp_rate, + NULL); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set RX sample rate: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Set RX bandwidth + status = bladerf_set_bandwidth(bladerf, + BLADERF_MODULE_RX, + (uint32)(bandwidth * 1000000), + NULL); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set RX bandwidth: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Set LNA gain + // FIXME: rx_gain + status = bladerf_set_lna_gain(bladerf, + BLADERF_LNA_GAIN_MID); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set LNA gain: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Set RX VGA1 gain + // FIXME: rx_gain + status = bladerf_set_rxvga1(bladerf, + BLADERF_RXVGA1_GAIN_MIN); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set RX VGA1 gain: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Set RX VGA2 gain + // FIXME: rx_gain + status = bladerf_set_rxvga2(bladerf, + BLADERF_RXVGA2_GAIN_MIN); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set RX VGA2 gain: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Set TX frequency + status = bladerf_set_frequency(bladerf, + BLADERF_MODULE_TX, + liblte_interface_dl_earfcn_to_frequency(dl_earfcn)); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set TX frequency: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Set TX sample rate + status = bladerf_set_sample_rate(bladerf, + BLADERF_MODULE_TX, + samp_rate, + NULL); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set TX sample rate: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Set TX bandwidth + status = bladerf_set_bandwidth(bladerf, + BLADERF_MODULE_TX, + (uint32)(bandwidth * 1000000), + NULL); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set TX bandwidth: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Set TX VGA1 gain + // FIXME: tx_gain + status = bladerf_set_txvga1(bladerf, + BLADERF_TXVGA1_GAIN_MAX); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set TX VGA1 gain: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Set TX VGA2 gain + // FIXME: tx_gain + status = bladerf_set_txvga2(bladerf, + BLADERF_TXVGA2_GAIN_MAX - 1); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set TX VGA2 gain: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Setup sync TX + if(0 == (N_samps_per_subfr % 1024)) + { + buffer_size = N_samps_per_subfr; + }else{ + buffer_size = 1024; + } + status = bladerf_sync_config(bladerf, + BLADERF_MODULE_TX, + BLADERF_FORMAT_SC16_Q11_META, + BLADERF_NUM_BUFFERS, + buffer_size, + BLADERF_NUM_TRANSFERS, + BLADERF_TIMEOUT_MS); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set TX sync config: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Setup sync RX + status = bladerf_sync_config(bladerf, + BLADERF_MODULE_RX, + BLADERF_FORMAT_SC16_Q11_META, + BLADERF_NUM_BUFFERS, + buffer_size, + BLADERF_NUM_TRANSFERS, + BLADERF_TIMEOUT_MS); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to set RX sync config: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Enable TX + status = bladerf_enable_module(bladerf, BLADERF_MODULE_TX, true); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to enable TX module: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + // Enable RX + status = bladerf_enable_module(bladerf, BLADERF_MODULE_RX, true); + if(0 != status) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Failed to enable RX module: %s", + bladerf_strerror(status)); + bladerf_close(bladerf); + return(err); + } + + return(LTE_FDD_ENB_ERROR_NONE); +} +void LTE_fdd_enb_radio_bladerf::teardown(void) +{ + if(NULL != bladerf) + { + bladerf_close(bladerf); + } +} +void LTE_fdd_enb_radio_bladerf::send(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *buf, + LTE_FDD_ENB_RADIO_PARAMS_STRUCT *radio_params) +{ + uint32 i; + uint32 samps_to_send = radio_params->N_samps_per_subfr; + int status; + uint16 N_skipped_subfrs; + + // Check current_tti + if(buf->current_tti != next_tx_current_tti) + { + if(buf->current_tti > next_tx_current_tti) + { + N_skipped_subfrs = buf->current_tti - next_tx_current_tti; + }else{ + N_skipped_subfrs = (buf->current_tti + LTE_FDD_ENB_CURRENT_TTI_MAX + 1) - next_tx_current_tti; + } + + next_tx_ts += N_skipped_subfrs * radio_params->N_samps_per_subfr; + next_tx_current_tti = (buf->current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + metadata_tx.flags = BLADERF_META_FLAG_TX_UPDATE_TIMESTAMP; + metadata_tx.timestamp = next_tx_ts; + }else{ + next_tx_current_tti = (next_tx_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + metadata_tx.flags = 0; + } + + for(i=0; ii_buf[0][i] * 40.0); + tx_buf[(i*2)+1] = (int16_t)(buf->q_buf[0][i] * 40.0); + } + + if(first_tx_sample) + { + metadata_tx.flags = BLADERF_META_FLAG_TX_BURST_START; + metadata_tx.timestamp = next_tx_ts; + first_tx_sample = false; + } + + // TX samples + status = bladerf_sync_tx(bladerf, tx_buf, samps_to_send, &metadata_tx, 1000); + if(BLADERF_ERR_TIME_PAST == status) + { + LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "TX failed: BLADERF_ERR_TIME_PAST"); + }else if(0 != status){ + LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "TX failed: %s", + bladerf_strerror(status)); + }else if(BLADERF_META_STATUS_UNDERRUN & metadata_tx.status){ + LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "TX failed: BLADERF_META_STATUS_UNDERRUN"); + } + + next_tx_ts += samps_to_send; +} +void LTE_fdd_enb_radio_bladerf::receive(LTE_FDD_ENB_RADIO_PARAMS_STRUCT *radio_params) +{ + uint32 i; + int status; + + if(radio_params->init_needed) + { + // Assume RX_timestamp and TX_timestamp difference is 0 + bladerf_get_timestamp(bladerf, BLADERF_MODULE_RX, (uint64_t*)&rx_ts); + next_tx_ts = rx_ts + radio_params->samp_rate; // 1 second to make sure everything is setup + metadata_rx.flags = 0; + metadata_rx.timestamp = next_tx_ts - (radio_params->N_samps_per_subfr*2); // Retard RX by 2 subframes + + // Signal PHY to generate first subframe + radio_params->phy->radio_interface(&radio_params->tx_radio_buf[1]); + + radio_params->init_needed = false; + }else{ + metadata_rx.flags = 0; // Use timestamps + } + + // RX + status = bladerf_sync_rx(bladerf, rx_buf, radio_params->N_samps_per_subfr, &metadata_rx, 1000); + if(0 != status) + { + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "RX failed: %s", + bladerf_strerror(status)); + }else if(BLADERF_META_STATUS_OVERRUN & metadata_rx.status){ + radio_params->interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "RX failed: BLADERF_META_STATUS_OVERRUN"); + + // Determine how many subframes we are going to drop + radio_params->N_subfrs_dropped = 10; + + // Jump the rx_current_tti and timestamp + radio_params->rx_current_tti = (radio_params->rx_current_tti + radio_params->N_subfrs_dropped) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + metadata_rx.timestamp += radio_params->N_subfrs_dropped * radio_params->N_samps_per_subfr; + + // FIXME: This doesn't recover from the overrun + }else{ + for(i=0; iN_samps_per_subfr; i++) + { + radio_params->rx_radio_buf[radio_params->buf_idx].i_buf[0][i] = rx_buf[(i*2) ] / 40.0; + radio_params->rx_radio_buf[radio_params->buf_idx].q_buf[0][i] = rx_buf[(i*2)+1] / 40.0; + } + metadata_rx.timestamp += radio_params->N_samps_per_subfr; + radio_params->rx_radio_buf[radio_params->buf_idx].current_tti = radio_params->rx_current_tti; + radio_params->phy->radio_interface(&radio_params->tx_radio_buf[radio_params->buf_idx], + &radio_params->rx_radio_buf[radio_params->buf_idx]); + radio_params->buf_idx = (radio_params->buf_idx + 1) % 2; + radio_params->rx_current_tti = (radio_params->rx_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); + } +} + /*******************/ /* Singleton */ /*******************/ LTE_fdd_enb_radio* LTE_fdd_enb_radio::get_instance(void) { - boost::mutex::scoped_lock lock(radio_instance_mutex); + libtools_scoped_lock lock(radio_instance_mutex); if(NULL == instance) { @@ -89,7 +1043,7 @@ LTE_fdd_enb_radio* LTE_fdd_enb_radio::get_instance(void) } void LTE_fdd_enb_radio::cleanup(void) { - boost::mutex::scoped_lock lock(radio_instance_mutex); + libtools_scoped_lock lock(radio_instance_mutex); if(NULL != instance) { @@ -103,23 +1057,24 @@ void LTE_fdd_enb_radio::cleanup(void) /********************************/ LTE_fdd_enb_radio::LTE_fdd_enb_radio() { - // Setup radios + // Start/Stop + sem_init(&start_sem, 0, 1); + started = false; + + // Setup generic radios available_radios.num_radios = 0; get_available_radios(); + tx_gain = 0; + rx_gain = 0; + clock_source = "internal"; // Setup radio thread - get_sample_rate(); - N_tx_samps = 0; - N_rx_samps = 0; - tx_gain = 0; - rx_gain = 0; - - // Start/Stop - started = false; + get_radio_sample_rate(); } LTE_fdd_enb_radio::~LTE_fdd_enb_radio() { stop(); + sem_destroy(&start_sem); } /********************/ @@ -127,102 +1082,120 @@ LTE_fdd_enb_radio::~LTE_fdd_enb_radio() /********************/ bool LTE_fdd_enb_radio::is_started(void) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_sem); return(started); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_radio::start(void) { - boost::mutex::scoped_lock lock(start_mutex); - LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); - uhd::device_addr_t hint; - uhd::device_addrs_t devs = uhd::device::find(hint); - uhd::stream_args_t stream_args("fc32"); - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_CANT_START; - int64 dl_earfcn; - int64 ul_earfcn; - + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_CANT_START; + double bandwidth; + int64 dl_earfcn; + int64 ul_earfcn; + int64 N_ant; + + sem_wait(&start_sem); if(false == started) { - if(0 != selected_radio_idx) - { - started = true; - start_mutex.unlock(); - try - { - // Get the DL and UL EARFCNs - cnfg_db->get_param(LTE_FDD_ENB_PARAM_DL_EARFCN, dl_earfcn); - cnfg_db->get_param(LTE_FDD_ENB_PARAM_UL_EARFCN, ul_earfcn); + // Get the DL and UL EARFCNs + cnfg_db->get_param(LTE_FDD_ENB_PARAM_DL_EARFCN, dl_earfcn); + cnfg_db->get_param(LTE_FDD_ENB_PARAM_UL_EARFCN, ul_earfcn); - // Get the number of TX antennas - cnfg_db->get_param(LTE_FDD_ENB_PARAM_N_ANT, N_ant); + // Get the number of TX antennas + cnfg_db->get_param(LTE_FDD_ENB_PARAM_N_ANT, N_ant); + radio_params.N_ant = N_ant; - // Setup the USRP - usrp = uhd::usrp::multi_usrp::make(devs[selected_radio_idx-1]); - usrp->set_master_clock_rate(30720000); - if(2.0 >= fabs(usrp->get_master_clock_rate() - 30720000.0)) - { - usrp->set_tx_rate(get_sample_rate()); - usrp->set_rx_rate(get_sample_rate()); - usrp->set_tx_freq((double)liblte_interface_dl_earfcn_to_frequency(dl_earfcn)); - usrp->set_rx_freq((double)liblte_interface_ul_earfcn_to_frequency(ul_earfcn)); - usrp->set_tx_gain(tx_gain); - usrp->set_rx_gain(rx_gain); - - // Setup the TX and RX streams - tx_stream = usrp->get_tx_stream(stream_args); - rx_stream = usrp->get_rx_stream(stream_args); - N_tx_samps = tx_stream->get_max_num_samps(); - N_rx_samps = rx_stream->get_max_num_samps(); - if(N_rx_samps > LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ && - N_tx_samps > LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ) - { - N_rx_samps = LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ; - N_tx_samps = LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ; + // Get the bandwidth + cnfg_db->get_param(LTE_FDD_ENB_PARAM_BANDWIDTH, bandwidth); - // Kick off the receiving thread - pthread_create(&radio_thread, NULL, &radio_thread_func, NULL); - - err = LTE_FDD_ENB_ERROR_NONE; - }else{ - started = false; - } - }else{ - started = false; - err = LTE_FDD_ENB_ERROR_MASTER_CLOCK_FAIL; - } - }catch(...){ + // Setup the appropriate radio + started = true; + sem_post(&start_sem); + switch(get_selected_radio_type()) + { + case LTE_FDD_ENB_RADIO_TYPE_NO_RF: + err = no_rf.setup(); + if(LTE_FDD_ENB_ERROR_NONE != err) + { started = false; return(err); } - }else{ - // Kick off the receiving thread - pthread_create(&radio_thread, NULL, &radio_thread_func, NULL); - - err = LTE_FDD_ENB_ERROR_NONE; - started = true; + break; + case LTE_FDD_ENB_RADIO_TYPE_USRP_B2X0: + err = usrp_b2x0.setup(selected_radio_idx, + bandwidth, + dl_earfcn, + ul_earfcn, + &clock_source, + get_radio_sample_rate(), + tx_gain, + rx_gain); + if(LTE_FDD_ENB_ERROR_NONE != err) + { + started = false; + return(err); + } + break; + case LTE_FDD_ENB_RADIO_TYPE_BLADERF: + err = bladerf.setup(selected_radio_idx, + bandwidth, + dl_earfcn, + ul_earfcn, + N_ant, + get_radio_sample_rate(), + radio_params.N_samps_per_subfr); + if(LTE_FDD_ENB_ERROR_NONE != err) + { + started = false; + return(err); + } + break; + default: + started = false; + return(LTE_FDD_ENB_ERROR_OUT_OF_BOUNDS); + break; } + + // Kick off the receiving thread + pthread_create(&radio_thread, NULL, &radio_thread_func, NULL); + }else{ + sem_post(&start_sem); } return(err); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_radio::stop(void) { - boost::mutex::scoped_lock lock(start_mutex); - uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_CANT_STOP; + uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_CANT_STOP; + sem_wait(&start_sem); if(started) { started = false; - if(0 != selected_radio_idx) + sem_post(&start_sem); + switch(get_selected_radio_type()) { - usrp->issue_stream_cmd(cmd); + case LTE_FDD_ENB_RADIO_TYPE_NO_RF: + no_rf.teardown(); + break; + case LTE_FDD_ENB_RADIO_TYPE_USRP_B2X0: + usrp_b2x0.teardown(); + break; + case LTE_FDD_ENB_RADIO_TYPE_BLADERF: + bladerf.teardown(); + break; + default: + err = LTE_FDD_ENB_ERROR_OUT_OF_BOUNDS; + break; } sleep(1); pthread_cancel(radio_thread); pthread_join(radio_thread, NULL); err = LTE_FDD_ENB_ERROR_NONE; + }else{ + sem_post(&start_sem); } return(err); @@ -233,18 +1206,21 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_radio::stop(void) /****************************/ LTE_FDD_ENB_AVAILABLE_RADIOS_STRUCT LTE_fdd_enb_radio::get_available_radios(void) { - uhd::device_addr_t hint; - uhd::device_addrs_t devs = uhd::device::find(hint); - size_t i; - uint32 orig_num_radios = available_radios.num_radios; + uint32 orig_num_radios = available_radios.num_radios; available_radios.num_radios = 0; - available_radios.radio[available_radios.num_radios++].name = "no_rf"; - for(i=0; iget_tx_gain(); - } + get_available_radios(); } - return(gain); + return(available_radios.radio[selected_radio_idx].type); +} +uint32 LTE_fdd_enb_radio::get_tx_gain(void) +{ + return(tx_gain); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_radio::set_tx_gain(uint32 gain) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_sem); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_OUT_OF_BOUNDS; - tx_gain = gain; - if(started) + if(!started) { - if(0 != selected_radio_idx) - { - usrp->set_tx_gain(gain); - } + tx_gain = gain; + err = LTE_FDD_ENB_ERROR_NONE; } - return(LTE_FDD_ENB_ERROR_NONE); + return(err); } uint32 LTE_fdd_enb_radio::get_rx_gain(void) { - boost::mutex::scoped_lock lock(start_mutex); - uint32 gain; + return(rx_gain); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_radio::set_rx_gain(uint32 gain) +{ + libtools_scoped_lock lock(start_sem); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_OUT_OF_BOUNDS; if(!started) { - gain = rx_gain; - }else{ - if(0 == selected_radio_idx) - { - gain = rx_gain; - }else{ - gain = (uint32)usrp->get_rx_gain(); - } + rx_gain = gain; + err = LTE_FDD_ENB_ERROR_NONE; } - return(gain); + return(err); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_radio::set_rx_gain(uint32 gain) +std::string LTE_fdd_enb_radio::get_clock_source(void) +{ + return(clock_source); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_radio::set_clock_source(std::string source) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_sem); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_OUT_OF_BOUNDS; - rx_gain = gain; - if(started) + if("internal" == source || + "external" == source) { - if(0 != selected_radio_idx) + if(!started) { - usrp->set_rx_gain(gain); + clock_source = source; + err = LTE_FDD_ENB_ERROR_NONE; } } - return(LTE_FDD_ENB_ERROR_NONE); + return(err); } -uint32 LTE_fdd_enb_radio::get_sample_rate(void) +uint32 LTE_fdd_enb_radio::get_phy_sample_rate(void) { - boost::mutex::scoped_lock lock(start_mutex); - LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); - int64 dl_bw; + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + int64 dl_bw; if(!started) { @@ -382,367 +1358,125 @@ uint32 LTE_fdd_enb_radio::get_sample_rate(void) case LIBLTE_RRC_DL_BANDWIDTH_100: // Intentional fall-thru case LIBLTE_RRC_DL_BANDWIDTH_75: - fs = 30720000; - N_samps_per_subfr = LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ; + radio_params.fs = 30720000; + radio_params.N_samps_per_subfr = LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ; break; case LIBLTE_RRC_DL_BANDWIDTH_50: - fs = 15360000; - N_samps_per_subfr = LIBLTE_PHY_N_SAMPS_PER_SUBFR_15_36MHZ; + radio_params.fs = 15360000; + radio_params.N_samps_per_subfr = LIBLTE_PHY_N_SAMPS_PER_SUBFR_15_36MHZ; break; case LIBLTE_RRC_DL_BANDWIDTH_25: - fs = 7680000; - N_samps_per_subfr = LIBLTE_PHY_N_SAMPS_PER_SUBFR_7_68MHZ; + radio_params.fs = 7680000; + radio_params.N_samps_per_subfr = LIBLTE_PHY_N_SAMPS_PER_SUBFR_7_68MHZ; break; case LIBLTE_RRC_DL_BANDWIDTH_15: - fs = 3840000; - N_samps_per_subfr = LIBLTE_PHY_N_SAMPS_PER_SUBFR_3_84MHZ; + radio_params.fs = 3840000; + radio_params.N_samps_per_subfr = LIBLTE_PHY_N_SAMPS_PER_SUBFR_3_84MHZ; break; case LIBLTE_RRC_DL_BANDWIDTH_6: // Intentional fall-thru default: - fs = 1920000; - N_samps_per_subfr = LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ; + radio_params.fs = 1920000; + radio_params.N_samps_per_subfr = LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ; break; } } - return(fs); + return(radio_params.fs); } -void LTE_fdd_enb_radio::set_earfcns(int64 dl_earfcn, - int64 ul_earfcn) +uint32 LTE_fdd_enb_radio::get_radio_sample_rate(void) { - if(started && - 0 != selected_radio_idx) + libtools_scoped_lock lock(start_sem); + + if(!started) { - usrp->set_tx_freq((double)liblte_interface_dl_earfcn_to_frequency(dl_earfcn)); - usrp->set_rx_freq((double)liblte_interface_ul_earfcn_to_frequency(ul_earfcn)); + radio_params.fs = get_phy_sample_rate(); } + + return(radio_params.fs); } void LTE_fdd_enb_radio::send(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *buf) { -#if EXTRA_RADIO_DEBUG - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); -#endif - uhd::tx_metadata_t metadata; - uint32 samps_to_send = N_samps_per_subfr; - uint32 idx = 0; - uint32 i; - uint32 p; - uint16 N_skipped_subfrs; - - if(0 != selected_radio_idx) - { - // Setup metadata - metadata.has_time_spec = true; - metadata.start_of_burst = false; - metadata.end_of_burst = false; - - // Check current_tti - if(buf->current_tti != next_tx_current_tti) - { - if(buf->current_tti > next_tx_current_tti) - { - N_skipped_subfrs = buf->current_tti - next_tx_current_tti; - }else{ - N_skipped_subfrs = (buf->current_tti + LTE_FDD_ENB_CURRENT_TTI_MAX + 1) - next_tx_current_tti; - } - - next_tx_ts += uhd::time_spec_t::from_ticks(N_skipped_subfrs*N_samps_per_subfr, fs); - next_tx_current_tti = (buf->current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - }else{ - next_tx_current_tti = (next_tx_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - } - - while(samps_to_send > N_tx_samps) - { - metadata.time_spec = next_tx_ts; - for(i=0; ii_buf[0][idx+i]/50.0, buf->q_buf[0][idx+i]/50.0); - for(p=1; pi_buf[p][idx+i]/50.0, buf->q_buf[p][idx+i]/50.0); - } - tx_buf[i] /= N_ant; - } -#if EXTRA_RADIO_DEBUG - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, - LTE_FDD_ENB_DEBUG_LEVEL_RADIO, - __FILE__, - __LINE__, - "Sending subfr %lld %u", - metadata.time_spec.to_ticks(fs), - buf->current_tti); -#endif - tx_stream->send(tx_buf, N_tx_samps, metadata); - idx += N_tx_samps; - samps_to_send -= N_tx_samps; - next_tx_ts += uhd::time_spec_t::from_ticks(N_tx_samps, fs); - } - if(0 != samps_to_send) - { - metadata.time_spec = next_tx_ts; - for(i=0; ii_buf[0][idx+i]/50.0, buf->q_buf[0][idx+i]/50.0); - for(p=1; pi_buf[p][idx+i]/50.0, buf->q_buf[p][idx+i]/50.0); - } - tx_buf[i] /= N_ant; - } -#if EXTRA_RADIO_DEBUG - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, - LTE_FDD_ENB_DEBUG_LEVEL_RADIO, - __FILE__, - __LINE__, - "Sending subfr %lld %u", - metadata.time_spec.to_ticks(fs), - buf->current_tti); -#endif - tx_stream->send(tx_buf, samps_to_send, metadata); - next_tx_ts += uhd::time_spec_t::from_ticks(samps_to_send, fs); - } + switch(selected_radio_type) + { + case LTE_FDD_ENB_RADIO_TYPE_NO_RF: + no_rf.send(); + break; + case LTE_FDD_ENB_RADIO_TYPE_USRP_B2X0: + usrp_b2x0.send(buf, &radio_params); + break; + case LTE_FDD_ENB_RADIO_TYPE_BLADERF: + bladerf.send(buf, &radio_params); + break; + default: + radio_params.interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RADIO, + __FILE__, + __LINE__, + "Invalid radio type %u", + selected_radio_type); + break; } } +pthread_t LTE_fdd_enb_radio::get_radio_thread(void) +{ + return(radio_thread); +} -/**********************/ -/* Radio Thread */ -/**********************/ +/************************/ +/* Generic Radios */ +/************************/ void* LTE_fdd_enb_radio::radio_thread_func(void *inputs) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - LTE_fdd_enb_phy *phy = LTE_fdd_enb_phy::get_instance(); - LTE_fdd_enb_radio *radio = LTE_fdd_enb_radio::get_instance(); - LTE_FDD_ENB_RADIO_TX_BUF_STRUCT tx_radio_buf[2]; - LTE_FDD_ENB_RADIO_RX_BUF_STRUCT rx_radio_buf[2]; - struct timespec sleep_time; - struct timespec time_rem; - struct sched_param priority; - uhd::rx_metadata_t metadata; - uhd::time_spec_t next_rx_ts; - uhd::time_spec_t next_rx_subfr_ts; - uhd::time_spec_t check_ts; - uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS; - int64 next_rx_ts_ticks; - int64 metadata_ts_ticks; - uint32 i; - uint32 N_subfrs_dropped; - uint32 recv_size = radio->N_rx_samps; - uint32 samp_rate = radio->fs; - uint32 buf_idx = 0; - uint32 recv_idx = 0; - uint32 samp_idx = 0; - uint32 num_samps = 0; - uint32 radio_idx = radio->get_selected_radio_idx(); - uint16 rx_current_tti = (LTE_FDD_ENB_CURRENT_TTI_MAX + 1) - 2; - bool not_done = true; - bool init_needed = true; - bool rx_synced = false; + LTE_fdd_enb_radio *radio = LTE_fdd_enb_radio::get_instance(); + struct sched_param priority; + cpu_set_t af_mask; + LTE_FDD_ENB_RADIO_TYPE_ENUM radio_type = radio->get_selected_radio_type(); + + // Setup radio params + radio->radio_params.interface = LTE_fdd_enb_interface::get_instance(); + radio->radio_params.phy = LTE_fdd_enb_phy::get_instance(); + radio->radio_params.samp_rate = radio->radio_params.fs; + radio->radio_params.buf_idx = 0; + radio->radio_params.recv_idx = 0; + radio->radio_params.samp_idx = 0; + radio->radio_params.num_samps = 0; + radio->radio_params.rx_current_tti = (LTE_FDD_ENB_CURRENT_TTI_MAX + 1) - 2; + radio->radio_params.init_needed = true; + radio->radio_params.rx_synced = false; // Set highest priority priority.sched_priority = 99; pthread_setschedparam(radio->radio_thread, SCHED_FIFO, &priority); - // Setup sleep time for no_rf device - sleep_time.tv_sec = 0; - sleep_time.tv_nsec = 1000000; + // Set affinity to the last core for PHY/Radio + CPU_ZERO(&af_mask); + CPU_SET(sysconf(_SC_NPROCESSORS_ONLN)-1, &af_mask); + pthread_setaffinity_np(radio->get_radio_thread(), sizeof(af_mask), &af_mask); - while(not_done && - radio->is_started()) + while(radio->is_started()) { - if(0 == radio_idx) + switch(radio_type) { - if(init_needed) - { - // Signal PHY to generate first subframe - phy->radio_interface(&tx_radio_buf[1]); - init_needed = false; - } - rx_radio_buf[buf_idx].current_tti = rx_current_tti; - phy->radio_interface(&tx_radio_buf[buf_idx], &rx_radio_buf[buf_idx]); - buf_idx = (buf_idx + 1) % 2; - rx_current_tti = (rx_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - nanosleep(&sleep_time, &time_rem); - }else{ - if(init_needed) - { - // Setup time specs - radio->next_tx_ts = uhd::time_spec_t::from_ticks(samp_rate, samp_rate); // 1 second to make sure everything is setup - next_rx_ts = radio->next_tx_ts; - next_rx_ts -= uhd::time_spec_t::from_ticks(radio->N_samps_per_subfr*2, samp_rate); // Retard RX by 2 subframes - next_rx_subfr_ts = next_rx_ts; - - // Reset USRP time - radio->usrp->set_time_now(uhd::time_spec_t::from_ticks(0, samp_rate)); - - // Signal PHY to generate first subframe - phy->radio_interface(&tx_radio_buf[1]); - - // Start streaming - cmd.stream_now = true; - radio->usrp->issue_stream_cmd(cmd); - - init_needed = false; - } - - if(!rx_synced) - { - num_samps = radio->rx_stream->recv(radio->rx_buf, recv_size, metadata); - check_ts = metadata.time_spec; - check_ts += uhd::time_spec_t::from_ticks(num_samps, samp_rate); - - if(check_ts.to_ticks(samp_rate) == next_rx_ts.to_ticks(samp_rate)) - { - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, - LTE_FDD_ENB_DEBUG_LEVEL_RADIO, - __FILE__, - __LINE__, - "RX synced %lld %lld", - check_ts.to_ticks(samp_rate), - next_rx_ts.to_ticks(samp_rate)); - samp_idx = 0; - rx_synced = true; - }else{ - check_ts += uhd::time_spec_t::from_ticks(radio->N_rx_samps, samp_rate); - if(check_ts.to_ticks(samp_rate) > next_rx_ts.to_ticks(samp_rate)) - { - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, - LTE_FDD_ENB_DEBUG_LEVEL_RADIO, - __FILE__, - __LINE__, - "RX modifying recv_size to sync %lld %lld", - check_ts.to_ticks(samp_rate), - next_rx_ts.to_ticks(samp_rate)); - check_ts -= uhd::time_spec_t::from_ticks(radio->N_rx_samps, samp_rate); - recv_size = (uint32)(next_rx_ts.to_ticks(samp_rate) - check_ts.to_ticks(samp_rate)); - } - } - }else{ - num_samps = radio->rx_stream->recv(radio->rx_buf, radio->N_rx_samps, metadata); - if(0 != num_samps) - { - if(num_samps != radio->N_rx_samps) - { - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, - LTE_FDD_ENB_DEBUG_LEVEL_RADIO, - __FILE__, - __LINE__, - "RX packet size issue %u %u", - num_samps, - radio->N_rx_samps); - } - next_rx_ts_ticks = next_rx_ts.to_ticks(samp_rate); - metadata_ts_ticks = metadata.time_spec.to_ticks(samp_rate); - if((next_rx_ts_ticks - metadata_ts_ticks) > 1) - { - // FIXME: Not sure this will ever happen - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, - LTE_FDD_ENB_DEBUG_LEVEL_RADIO, - __FILE__, - __LINE__, - "RX old time spec %lld %lld", - metadata_ts_ticks, - next_rx_ts_ticks); - }else if((metadata_ts_ticks - next_rx_ts_ticks) > 1){ - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, - LTE_FDD_ENB_DEBUG_LEVEL_RADIO, - __FILE__, - __LINE__, - "RX overrun %lld %lld", - metadata_ts_ticks, - next_rx_ts_ticks); - - // Determine how many subframes we are going to drop - N_subfrs_dropped = ((metadata_ts_ticks - next_rx_ts_ticks)/radio->N_samps_per_subfr) + 2; - - // Jump the rx_current_tti - rx_current_tti = (rx_current_tti + N_subfrs_dropped) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - - // Align the samples coming from the radio - rx_synced = false; - next_rx_subfr_ts += uhd::time_spec_t::from_ticks(N_subfrs_dropped*radio->N_samps_per_subfr, samp_rate); - next_rx_ts = next_rx_subfr_ts; - check_ts = metadata.time_spec; - check_ts += uhd::time_spec_t::from_ticks(num_samps + radio->N_rx_samps, samp_rate); - - if(check_ts.to_ticks(samp_rate) > next_rx_ts.to_ticks(samp_rate)) - { - check_ts -= uhd::time_spec_t::from_ticks(radio->N_rx_samps, samp_rate); - recv_size = (uint32)(next_rx_ts.to_ticks(samp_rate) - check_ts.to_ticks(samp_rate)); - }else{ - recv_size = radio->N_rx_samps; - } - }else{ - // FIXME: May need to realign to 1920 sample boundries - recv_idx = 0; - next_rx_ts += uhd::time_spec_t::from_ticks(num_samps, samp_rate); - while(num_samps > 0) - { - if((samp_idx + num_samps) <= radio->N_samps_per_subfr) - { - for(i=0; irx_buf[recv_idx+i].real(); - rx_radio_buf[buf_idx].q_buf[samp_idx+i] = radio->rx_buf[recv_idx+i].imag(); - } - samp_idx += num_samps; - - if(samp_idx == radio->N_samps_per_subfr) - { -#if EXTRA_RADIO_DEBUG - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, - LTE_FDD_ENB_DEBUG_LEVEL_RADIO, - __FILE__, - __LINE__, - "Receiving subfr %lld %u", - next_rx_subfr_ts.to_ticks(samp_rate), - rx_current_tti); -#endif - rx_radio_buf[buf_idx].current_tti = rx_current_tti; - phy->radio_interface(&tx_radio_buf[buf_idx], &rx_radio_buf[buf_idx]); - buf_idx = (buf_idx + 1) % 2; - rx_current_tti = (rx_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - samp_idx = 0; - next_rx_subfr_ts += uhd::time_spec_t::from_ticks(radio->N_samps_per_subfr, samp_rate); - } - num_samps = 0; - }else{ - for(i=0; i<(radio->N_samps_per_subfr - samp_idx); i++) - { - rx_radio_buf[buf_idx].i_buf[samp_idx+i] = radio->rx_buf[recv_idx+i].real(); - rx_radio_buf[buf_idx].q_buf[samp_idx+i] = radio->rx_buf[recv_idx+i].imag(); - } - -#if EXTRA_RADIO_DEBUG - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + case LTE_FDD_ENB_RADIO_TYPE_NO_RF: + radio->no_rf.receive(&radio->radio_params); + break; + case LTE_FDD_ENB_RADIO_TYPE_USRP_B2X0: + radio->usrp_b2x0.receive(&radio->radio_params); + break; + case LTE_FDD_ENB_RADIO_TYPE_BLADERF: + radio->bladerf.receive(&radio->radio_params); + break; + default: + radio->radio_params.interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, LTE_FDD_ENB_DEBUG_LEVEL_RADIO, __FILE__, __LINE__, - "Receiving subfr %lld %u", - next_rx_subfr_ts.to_ticks(samp_rate), - rx_current_tti); -#endif - rx_radio_buf[buf_idx].current_tti = rx_current_tti; - phy->radio_interface(&tx_radio_buf[buf_idx], &rx_radio_buf[buf_idx]); - buf_idx = (buf_idx + 1) % 2; - rx_current_tti = (rx_current_tti + 1) % (LTE_FDD_ENB_CURRENT_TTI_MAX + 1); - num_samps -= (radio->N_samps_per_subfr - samp_idx); - recv_idx = (radio->N_samps_per_subfr - samp_idx); - samp_idx = 0; - next_rx_subfr_ts += uhd::time_spec_t::from_ticks(radio->N_samps_per_subfr, samp_rate); - } - } - } - }else{ - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, - LTE_FDD_ENB_DEBUG_LEVEL_RADIO, - __FILE__, - __LINE__, - "RX error %u", - (uint32)metadata.error_code); - } - } + "Invalid radio type %u", + radio_type); + return(NULL); } } + + return(NULL); } diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_rb.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_rb.cc old mode 100644 new mode 100755 index 0b059ff..dd53c7d --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_rb.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_rb.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_rb.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2014 Ben Wojtowicz + Copyright 2014-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -28,6 +28,32 @@ 05/04/2014 Ben Wojtowicz Created file 06/15/2014 Ben Wojtowicz Added more states and procedures, QoS, MME, RLC, and uplink scheduling functionality. + 08/03/2014 Ben Wojtowicz Added MME procedures/states, RRC NAS support, + RRC transaction id, PDCP sequence numbers, + and RLC transmit variables. + 09/03/2014 Ben Wojtowicz Added ability to store the contetion + resolution identity and fixed an issue with + t_poll_retransmit. + 11/01/2014 Ben Wojtowicz Added SRB2 support and PDCP security. + 11/29/2014 Ben Wojtowicz Added more DRB support, moved almost + everything to byte messages structs, added + IP gateway and RLC UMD support. + 12/16/2014 Ben Wojtowicz Added QoS for default data services. + 12/24/2014 Ben Wojtowicz Added asymmetric QoS support and fixed a + UMD reassembly bug. + 02/15/2015 Ben Wojtowicz Split UL/DL QoS TTI frequency, added reset + user support, and added multiple UMD RLC data + support. + 07/25/2015 Ben Wojtowicz Moved QoS structure to the user class, fixed + RLC AM TX and RX buffers, and moved DRBs to + RLC AM. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t and fixed the updating of VT(A) in the + retransmission buffer. + 12/18/2016 Ben Wojtowicz Properly handling multiple RLC AMD PDUs. + 07/29/2017 Ben Wojtowicz Remove last TTI storage and refactored AMD + reception buffer handling to support more + than one PDU with the same SN. *******************************************************************************/ @@ -38,7 +64,10 @@ #include "LTE_fdd_enb_rb.h" #include "LTE_fdd_enb_timer_mgr.h" #include "LTE_fdd_enb_user.h" +#include "LTE_fdd_enb_rlc.h" #include "LTE_fdd_enb_mac.h" +#include "libtools_scoped_lock.h" +#include "libtools_helpers.h" /******************************************************************************* DEFINES @@ -65,43 +94,183 @@ LTE_fdd_enb_rb::LTE_fdd_enb_rb(LTE_FDD_ENB_RB_ENUM _rb, LTE_fdd_enb_user *_user) { - LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); - rb = _rb; user = _user; - timer_mgr->stop_timer(ul_sched_timer_id); + t_poll_retransmit_timer_id = LTE_FDD_ENB_INVALID_TIMER_ID; if(LTE_FDD_ENB_RB_SRB0 == rb) { + mme_procedure = LTE_FDD_ENB_MME_PROC_IDLE; + mme_state = LTE_FDD_ENB_MME_STATE_IDLE; rrc_procedure = LTE_FDD_ENB_RRC_PROC_IDLE; rrc_state = LTE_FDD_ENB_RRC_STATE_IDLE; pdcp_config = LTE_FDD_ENB_PDCP_CONFIG_N_A; rlc_config = LTE_FDD_ENB_RLC_CONFIG_TM; mac_config = LTE_FDD_ENB_MAC_CONFIG_TM; }else if(LTE_FDD_ENB_RB_SRB1 == rb){ + mme_procedure = LTE_FDD_ENB_MME_PROC_IDLE; + mme_state = LTE_FDD_ENB_MME_STATE_IDLE; + rrc_procedure = LTE_FDD_ENB_RRC_PROC_IDLE; + rrc_state = LTE_FDD_ENB_RRC_STATE_IDLE; + pdcp_config = LTE_FDD_ENB_PDCP_CONFIG_N_A; + rlc_config = LTE_FDD_ENB_RLC_CONFIG_AM; + mac_config = LTE_FDD_ENB_MAC_CONFIG_TM; + }else if(LTE_FDD_ENB_RB_SRB2 == rb){ + mme_procedure = LTE_FDD_ENB_MME_PROC_IDLE; + mme_state = LTE_FDD_ENB_MME_STATE_IDLE; rrc_procedure = LTE_FDD_ENB_RRC_PROC_IDLE; rrc_state = LTE_FDD_ENB_RRC_STATE_IDLE; pdcp_config = LTE_FDD_ENB_PDCP_CONFIG_N_A; rlc_config = LTE_FDD_ENB_RLC_CONFIG_AM; mac_config = LTE_FDD_ENB_MAC_CONFIG_TM; + }else if(LTE_FDD_ENB_RB_DRB1 == rb){ + pdcp_config = LTE_FDD_ENB_PDCP_CONFIG_LONG_SN; + rlc_config = LTE_FDD_ENB_RLC_CONFIG_AM; + mac_config = LTE_FDD_ENB_MAC_CONFIG_TM; + }else if(LTE_FDD_ENB_RB_DRB2 == rb){ + pdcp_config = LTE_FDD_ENB_PDCP_CONFIG_LONG_SN; + rlc_config = LTE_FDD_ENB_RLC_CONFIG_AM; + mac_config = LTE_FDD_ENB_MAC_CONFIG_TM; } + // GW + sem_init(&gw_data_msg_queue_sem, 0, 1); + + // MME + sem_init(&mme_nas_msg_queue_sem, 0, 1); + + // RRC + sem_init(&rrc_pdu_queue_sem, 0, 1); + sem_init(&rrc_nas_msg_queue_sem, 0, 1); + rrc_transaction_id = 0; + + // PDCP + sem_init(&pdcp_pdu_queue_sem, 0, 1); + sem_init(&pdcp_sdu_queue_sem, 0, 1); + sem_init(&pdcp_data_sdu_queue_sem, 0, 1); + pdcp_rx_count = 0; + pdcp_tx_count = 0; + // RLC - rlc_reception_buffer.clear(); - rlc_vrr = 0; - rlc_vrmr = rlc_vrr + LIBLTE_RLC_AM_WINDOW_SIZE; - rlc_vrh = 0; - rlc_first_segment_sn = 0xFFFF; - rlc_last_segment_sn = 0xFFFF; - - // Setup the QoS - avail_qos[0] = (LTE_FDD_ENB_QOS_STRUCT){ 0, 0}; - avail_qos[1] = (LTE_FDD_ENB_QOS_STRUCT){20, 176}; - qos = LTE_FDD_ENB_QOS_NONE; + sem_init(&rlc_pdu_queue_sem, 0, 1); + sem_init(&rlc_sdu_queue_sem, 0, 1); + rlc_am_reception_buffer.clear(); + rlc_am_transmission_buffer.clear(); + rlc_um_reception_buffer.clear(); + t_poll_retransmit_timer_id = LTE_FDD_ENB_INVALID_TIMER_ID; + rlc_vrr = 0; + rlc_vrmr = rlc_vrr + LIBLTE_RLC_AM_WINDOW_SIZE; + rlc_vrh = 0; + rlc_vta = 0; + rlc_vtms = rlc_vta + LIBLTE_RLC_AM_WINDOW_SIZE; + rlc_vts = 0; + rlc_vruh = 0; + rlc_vrur = 0; + rlc_um_window_size = 512; + rlc_first_um_segment_sn = 0xFFFF; + rlc_last_um_segment_sn = 0xFFFF; + rlc_vtus = 0; + + // MAC + sem_init(&mac_sdu_queue_sem, 0, 1); + mac_con_res_id = 0; } LTE_fdd_enb_rb::~LTE_fdd_enb_rb() { + LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + std::list::iterator byte_iter; + std::list::iterator bit_iter; + std::map::iterator rlc_am_iter; + std::map::iterator rlc_um_iter; + + // MAC + sem_wait(&mac_sdu_queue_sem); + for(byte_iter=mac_sdu_queue.begin(); byte_iter!=mac_sdu_queue.end(); byte_iter++) + { + delete (*byte_iter); + } + sem_destroy(&mac_sdu_queue_sem); + + // RLC + sem_wait(&rlc_pdu_queue_sem); + for(byte_iter=rlc_pdu_queue.begin(); byte_iter!=rlc_pdu_queue.end(); byte_iter++) + { + delete (*byte_iter); + } + sem_destroy(&rlc_pdu_queue_sem); + sem_wait(&rlc_sdu_queue_sem); + for(byte_iter=rlc_sdu_queue.begin(); byte_iter!=rlc_sdu_queue.end(); byte_iter++) + { + delete (*byte_iter); + } + sem_destroy(&rlc_sdu_queue_sem); + for(rlc_am_iter=rlc_am_reception_buffer.begin(); rlc_am_iter!=rlc_am_reception_buffer.end(); rlc_am_iter++) + { + delete (*rlc_am_iter).second; + } + for(rlc_am_iter=rlc_am_transmission_buffer.begin(); rlc_am_iter!=rlc_am_transmission_buffer.end(); rlc_am_iter++) + { + delete (*rlc_am_iter).second; + } + for(rlc_um_iter=rlc_um_reception_buffer.begin(); rlc_um_iter!=rlc_um_reception_buffer.end(); rlc_um_iter++) + { + delete (*rlc_um_iter).second; + } + if(LTE_FDD_ENB_INVALID_TIMER_ID != t_poll_retransmit_timer_id) + { + timer_mgr->stop_timer(t_poll_retransmit_timer_id); + } + + // PDCP + sem_wait(&pdcp_pdu_queue_sem); + for(byte_iter=pdcp_pdu_queue.begin(); byte_iter!=pdcp_pdu_queue.end(); byte_iter++) + { + delete (*byte_iter); + } + sem_destroy(&pdcp_pdu_queue_sem); + sem_wait(&pdcp_sdu_queue_sem); + for(bit_iter=pdcp_sdu_queue.begin(); bit_iter!=pdcp_sdu_queue.end(); bit_iter++) + { + delete (*bit_iter); + } + sem_destroy(&pdcp_sdu_queue_sem); + sem_wait(&pdcp_data_sdu_queue_sem); + for(byte_iter=pdcp_data_sdu_queue.begin(); byte_iter!=pdcp_data_sdu_queue.end(); byte_iter++) + { + delete (*byte_iter); + } + sem_destroy(&pdcp_data_sdu_queue_sem); + + // RRC + sem_wait(&rrc_pdu_queue_sem); + for(bit_iter=rrc_pdu_queue.begin(); bit_iter!=rrc_pdu_queue.end(); bit_iter++) + { + delete (*bit_iter); + } + sem_destroy(&rrc_pdu_queue_sem); + sem_wait(&rrc_nas_msg_queue_sem); + for(byte_iter=rrc_nas_msg_queue.begin(); byte_iter!=rrc_nas_msg_queue.end(); byte_iter++) + { + delete (*byte_iter); + } + sem_destroy(&rrc_nas_msg_queue_sem); + + // MME + sem_wait(&mme_nas_msg_queue_sem); + for(byte_iter=mme_nas_msg_queue.begin(); byte_iter!=mme_nas_msg_queue.end(); byte_iter++) + { + delete (*byte_iter); + } + sem_destroy(&mme_nas_msg_queue_sem); + + // GW + sem_wait(&gw_data_msg_queue_sem); + for(byte_iter=gw_data_msg_queue.begin(); byte_iter!=gw_data_msg_queue.end(); byte_iter++) + { + delete (*byte_iter); + } + sem_destroy(&gw_data_msg_queue_sem); } /******************/ @@ -111,21 +280,81 @@ LTE_FDD_ENB_RB_ENUM LTE_fdd_enb_rb::get_rb_id(void) { return(rb); } +void LTE_fdd_enb_rb::reset_user(LTE_fdd_enb_user *_user) +{ + user = _user; +} + +/************/ +/* GW */ +/************/ +void LTE_fdd_enb_rb::queue_gw_data_msg(LIBLTE_BYTE_MSG_STRUCT *gw_data) +{ + queue_msg(gw_data, &gw_data_msg_queue_sem, &gw_data_msg_queue); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_gw_data_msg(LIBLTE_BYTE_MSG_STRUCT **gw_data) +{ + return(get_next_msg(&gw_data_msg_queue_sem, &gw_data_msg_queue, gw_data)); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_gw_data_msg(void) +{ + return(delete_next_msg(&gw_data_msg_queue_sem, &gw_data_msg_queue)); +} /*************/ /* MME */ /*************/ void LTE_fdd_enb_rb::queue_mme_nas_msg(LIBLTE_BYTE_MSG_STRUCT *nas_msg) { - queue_msg(nas_msg, &mme_nas_msg_queue_mutex, &mme_nas_msg_queue); + queue_msg(nas_msg, &mme_nas_msg_queue_sem, &mme_nas_msg_queue); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_mme_nas_msg(LIBLTE_BYTE_MSG_STRUCT **nas_msg) { - return(get_next_msg(&mme_nas_msg_queue_mutex, &mme_nas_msg_queue, nas_msg)); + return(get_next_msg(&mme_nas_msg_queue_sem, &mme_nas_msg_queue, nas_msg)); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_mme_nas_msg(void) { - return(delete_next_msg(&mme_nas_msg_queue_mutex, &mme_nas_msg_queue)); + return(delete_next_msg(&mme_nas_msg_queue_sem, &mme_nas_msg_queue)); +} +void LTE_fdd_enb_rb::set_mme_procedure(LTE_FDD_ENB_MME_PROC_ENUM procedure) +{ + LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RB, + __FILE__, + __LINE__, + "%s MME procedure moving from %s to %s for RNTI=%u", + LTE_fdd_enb_rb_text[rb], + LTE_fdd_enb_mme_proc_text[mme_procedure], + LTE_fdd_enb_mme_proc_text[procedure], + user->get_c_rnti()); + + mme_procedure = procedure; +} +LTE_FDD_ENB_MME_PROC_ENUM LTE_fdd_enb_rb::get_mme_procedure(void) +{ + return(mme_procedure); +} +void LTE_fdd_enb_rb::set_mme_state(LTE_FDD_ENB_MME_STATE_ENUM state) +{ + LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RB, + __FILE__, + __LINE__, + "%s MME state moving from %s to %s for RNTI=%u", + LTE_fdd_enb_rb_text[rb], + LTE_fdd_enb_mme_state_text[mme_state], + LTE_fdd_enb_mme_state_text[state], + user->get_c_rnti()); + + mme_state = state; +} +LTE_FDD_ENB_MME_STATE_ENUM LTE_fdd_enb_rb::get_mme_state(void) +{ + return(mme_state); } /*************/ @@ -133,15 +362,27 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_mme_nas_msg(void) /*************/ void LTE_fdd_enb_rb::queue_rrc_pdu(LIBLTE_BIT_MSG_STRUCT *pdu) { - queue_msg(pdu, &rrc_pdu_queue_mutex, &rrc_pdu_queue); + queue_msg(pdu, &rrc_pdu_queue_sem, &rrc_pdu_queue); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_rrc_pdu(LIBLTE_BIT_MSG_STRUCT **pdu) { - return(get_next_msg(&rrc_pdu_queue_mutex, &rrc_pdu_queue, pdu)); + return(get_next_msg(&rrc_pdu_queue_sem, &rrc_pdu_queue, pdu)); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_rrc_pdu(void) { - return(delete_next_msg(&rrc_pdu_queue_mutex, &rrc_pdu_queue)); + return(delete_next_msg(&rrc_pdu_queue_sem, &rrc_pdu_queue)); +} +void LTE_fdd_enb_rb::queue_rrc_nas_msg(LIBLTE_BYTE_MSG_STRUCT *nas_msg) +{ + queue_msg(nas_msg, &rrc_nas_msg_queue_sem, &rrc_nas_msg_queue); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_rrc_nas_msg(LIBLTE_BYTE_MSG_STRUCT **nas_msg) +{ + return(get_next_msg(&rrc_nas_msg_queue_sem, &rrc_nas_msg_queue, nas_msg)); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_rrc_nas_msg(void) +{ + return(delete_next_msg(&rrc_nas_msg_queue_sem, &rrc_nas_msg_queue)); } void LTE_fdd_enb_rb::set_rrc_procedure(LTE_FDD_ENB_RRC_PROC_ENUM procedure) { @@ -181,65 +422,105 @@ LTE_FDD_ENB_RRC_STATE_ENUM LTE_fdd_enb_rb::get_rrc_state(void) { return(rrc_state); } +uint8 LTE_fdd_enb_rb::get_rrc_transaction_id(void) +{ + return(rrc_transaction_id); +} +void LTE_fdd_enb_rb::set_rrc_transaction_id(uint8 transaction_id) +{ + rrc_transaction_id = transaction_id; +} /**************/ /* PDCP */ /**************/ -void LTE_fdd_enb_rb::queue_pdcp_pdu(LIBLTE_BIT_MSG_STRUCT *pdu) +void LTE_fdd_enb_rb::queue_pdcp_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu) { - queue_msg(pdu, &pdcp_pdu_queue_mutex, &pdcp_pdu_queue); + queue_msg(pdu, &pdcp_pdu_queue_sem, &pdcp_pdu_queue); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_pdcp_pdu(LIBLTE_BIT_MSG_STRUCT **pdu) +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_pdcp_pdu(LIBLTE_BYTE_MSG_STRUCT **pdu) { - return(get_next_msg(&pdcp_pdu_queue_mutex, &pdcp_pdu_queue, pdu)); + return(get_next_msg(&pdcp_pdu_queue_sem, &pdcp_pdu_queue, pdu)); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_pdcp_pdu(void) { - return(delete_next_msg(&pdcp_pdu_queue_mutex, &pdcp_pdu_queue)); + return(delete_next_msg(&pdcp_pdu_queue_sem, &pdcp_pdu_queue)); } void LTE_fdd_enb_rb::queue_pdcp_sdu(LIBLTE_BIT_MSG_STRUCT *sdu) { - queue_msg(sdu, &pdcp_sdu_queue_mutex, &pdcp_sdu_queue); + queue_msg(sdu, &pdcp_sdu_queue_sem, &pdcp_sdu_queue); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_pdcp_sdu(LIBLTE_BIT_MSG_STRUCT **sdu) { - return(get_next_msg(&pdcp_sdu_queue_mutex, &pdcp_sdu_queue, sdu)); + return(get_next_msg(&pdcp_sdu_queue_sem, &pdcp_sdu_queue, sdu)); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_pdcp_sdu(void) { - return(delete_next_msg(&pdcp_sdu_queue_mutex, &pdcp_sdu_queue)); + return(delete_next_msg(&pdcp_sdu_queue_sem, &pdcp_sdu_queue)); +} +void LTE_fdd_enb_rb::queue_pdcp_data_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu) +{ + queue_msg(sdu, &pdcp_data_sdu_queue_sem, &pdcp_data_sdu_queue); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_pdcp_data_sdu(LIBLTE_BYTE_MSG_STRUCT **sdu) +{ + return(get_next_msg(&pdcp_data_sdu_queue_sem, &pdcp_data_sdu_queue, sdu)); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_pdcp_data_sdu(void) +{ + return(delete_next_msg(&pdcp_data_sdu_queue_sem, &pdcp_data_sdu_queue)); +} +void LTE_fdd_enb_rb::set_pdcp_config(LTE_FDD_ENB_PDCP_CONFIG_ENUM config) +{ + pdcp_config = config; } LTE_FDD_ENB_PDCP_CONFIG_ENUM LTE_fdd_enb_rb::get_pdcp_config(void) { return(pdcp_config); } +uint32 LTE_fdd_enb_rb::get_pdcp_rx_count(void) +{ + return(pdcp_rx_count); +} +void LTE_fdd_enb_rb::set_pdcp_rx_count(uint32 rx_count) +{ + pdcp_rx_count = rx_count; +} +uint32 LTE_fdd_enb_rb::get_pdcp_tx_count(void) +{ + return(pdcp_tx_count); +} +void LTE_fdd_enb_rb::set_pdcp_tx_count(uint32 tx_count) +{ + pdcp_tx_count = tx_count; +} /*************/ /* RLC */ /*************/ -void LTE_fdd_enb_rb::queue_rlc_pdu(LIBLTE_BIT_MSG_STRUCT *pdu) +void LTE_fdd_enb_rb::queue_rlc_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu) { - queue_msg(pdu, &rlc_pdu_queue_mutex, &rlc_pdu_queue); + queue_msg(pdu, &rlc_pdu_queue_sem, &rlc_pdu_queue); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_rlc_pdu(LIBLTE_BIT_MSG_STRUCT **pdu) +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_rlc_pdu(LIBLTE_BYTE_MSG_STRUCT **pdu) { - return(get_next_msg(&rlc_pdu_queue_mutex, &rlc_pdu_queue, pdu)); + return(get_next_msg(&rlc_pdu_queue_sem, &rlc_pdu_queue, pdu)); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_rlc_pdu(void) { - return(delete_next_msg(&rlc_pdu_queue_mutex, &rlc_pdu_queue)); + return(delete_next_msg(&rlc_pdu_queue_sem, &rlc_pdu_queue)); } -void LTE_fdd_enb_rb::queue_rlc_sdu(LIBLTE_BIT_MSG_STRUCT *sdu) +void LTE_fdd_enb_rb::queue_rlc_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu) { - queue_msg(sdu, &rlc_sdu_queue_mutex, &rlc_sdu_queue); + queue_msg(sdu, &rlc_sdu_queue_sem, &rlc_sdu_queue); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_rlc_sdu(LIBLTE_BIT_MSG_STRUCT **sdu) +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_rlc_sdu(LIBLTE_BYTE_MSG_STRUCT **sdu) { - return(get_next_msg(&rlc_sdu_queue_mutex, &rlc_sdu_queue, sdu)); + return(get_next_msg(&rlc_sdu_queue_sem, &rlc_sdu_queue, sdu)); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_rlc_sdu(void) { - return(delete_next_msg(&rlc_sdu_queue_mutex, &rlc_sdu_queue)); + return(delete_next_msg(&rlc_sdu_queue_sem, &rlc_sdu_queue)); } LTE_FDD_ENB_RLC_CONFIG_ENUM LTE_fdd_enb_rb::get_rlc_config(void) { @@ -254,6 +535,29 @@ void LTE_fdd_enb_rb::set_rlc_vrr(uint16 vrr) rlc_vrr = vrr; rlc_vrmr = rlc_vrr + LIBLTE_RLC_AM_WINDOW_SIZE; } +void LTE_fdd_enb_rb::update_rlc_vrr(void) +{ + std::map::iterator iter; + uint32 i; + uint16 vrr = rlc_vrr; + + for(i=vrr; i::iterator iter; + LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT *new_pdu = NULL; + + new_pdu = new LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT; + + if(NULL != new_pdu) + { + iter = rlc_am_reception_buffer.find(amd_pdu->hdr.sn * 10); + if(rlc_am_reception_buffer.end() == iter) + { + memcpy(new_pdu, amd_pdu, sizeof(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT)); + rlc_am_reception_buffer[amd_pdu->hdr.sn * 10] = new_pdu; + }else{ + iter = rlc_am_reception_buffer.find(amd_pdu->hdr.sn * 10 + 1); + if(rlc_am_reception_buffer.end() == iter) + { + memcpy(new_pdu, amd_pdu, sizeof(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT)); + rlc_am_reception_buffer[amd_pdu->hdr.sn * 10 + 1] = new_pdu; + }else{ + delete new_pdu; + } + } + } +} +void LTE_fdd_enb_rb::rlc_get_am_reception_buffer_status(LIBLTE_RLC_STATUS_PDU_STRUCT *status) { - LIBLTE_BIT_MSG_STRUCT *new_pdu = NULL; + std::map::iterator iter; + uint32 i; - new_pdu = new LIBLTE_BIT_MSG_STRUCT; + // Fill in the ACK_SN + status->ack_sn = rlc_vrh; + + // Determine if any NACK_SNs are needed + status->N_nack = 0; + if(rlc_vrh != rlc_vrr) + { + for(i=rlc_vrr; i 0x3FFFF) + { + i -= 0x3FFFF; + } + + iter = rlc_am_reception_buffer.find(i * 10); + if(rlc_am_reception_buffer.end() == iter) + { + status->nack_sn[status->N_nack++] = i; + } + } + + // Update VR(R) if there are no missing frames + if(0 == status->N_nack) + { + set_rlc_vrr(rlc_vrh); + } + } +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::rlc_am_reassemble(LIBLTE_BYTE_MSG_STRUCT *sdu) +{ + std::map::iterator iter; + std::list first; + std::list last; + std::list::iterator first_iter; + std::list::iterator last_iter; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_CANT_REASSEMBLE_SDU; + uint32 i; + bool reassemble; + + // Find all first and last SDUs + for(iter=rlc_am_reception_buffer.begin(); iter!=rlc_am_reception_buffer.end(); iter++) + { + if(LIBLTE_RLC_FI_FIELD_FULL_SDU == (*iter).second->hdr.fi) + { + first.push_back((*iter).second->hdr.sn); + last.push_back((*iter).second->hdr.sn); + }else if(LIBLTE_RLC_FI_FIELD_FIRST_SDU_SEGMENT == (*iter).second->hdr.fi){ + first.push_back((*iter).second->hdr.sn); + }else if(LIBLTE_RLC_FI_FIELD_LAST_SDU_SEGMENT == (*iter).second->hdr.fi){ + last.push_back((*iter).second->hdr.sn); + } + } + + // Check all first segments to see if the complete SDU is present + for(first_iter=first.begin(); first_iter!=first.end(); first_iter++) + { + for(last_iter=last.begin(); last_iter!=last.end(); last_iter++) + { + if((*last_iter) >= (*first_iter)) + { + break; + } + } + + if(last_iter != last.end()) + { + reassemble = true; + // Check that the whole SDU is present + for(i=(*first_iter); i<=(*last_iter); i++) + { + iter = rlc_am_reception_buffer.find(i * 10); + if(rlc_am_reception_buffer.end() == iter) + { + iter = rlc_am_reception_buffer.find(i * 10 + 1); + if(rlc_am_reception_buffer.end() == iter) + { + reassemble = false; + break; + } + } + } + + if(reassemble) + { + // Reorder and reassemble the SDU + sdu->N_bytes = 0; + for(i=(*first_iter); i<=(*last_iter); i++) + { + iter = rlc_am_reception_buffer.find(i * 10); + if(rlc_am_reception_buffer.end() == iter) + { + iter = rlc_am_reception_buffer.find(i * 10 + 1); + } + memcpy(&sdu->msg[sdu->N_bytes], (*iter).second->data.msg, (*iter).second->data.N_bytes); + sdu->N_bytes += (*iter).second->data.N_bytes; + delete (*iter).second; + rlc_am_reception_buffer.erase(iter); + } + err = LTE_FDD_ENB_ERROR_NONE; + break; + } + } + } + + return(err); +} +uint16 LTE_fdd_enb_rb::get_rlc_vta(void) +{ + return(rlc_vta); +} +void LTE_fdd_enb_rb::set_rlc_vta(uint16 vta) +{ + rlc_vta = vta; + rlc_vtms = rlc_vta + LIBLTE_RLC_AM_WINDOW_SIZE; +} +uint16 LTE_fdd_enb_rb::get_rlc_vtms(void) +{ + return(rlc_vtms); +} +uint16 LTE_fdd_enb_rb::get_rlc_vts(void) +{ + return(rlc_vts); +} +void LTE_fdd_enb_rb::set_rlc_vts(uint16 vts) +{ + rlc_vts = vts; +} +void LTE_fdd_enb_rb::rlc_add_to_transmission_buffer(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT *amd_pdu) +{ + LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT *new_pdu = NULL; + + new_pdu = new LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT; if(NULL != new_pdu) { - memcpy(new_pdu, &amd_pdu->data, sizeof(LIBLTE_BIT_MSG_STRUCT)); - rlc_reception_buffer[amd_pdu->hdr.sn] = new_pdu; + memcpy(new_pdu, amd_pdu, sizeof(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT)); + rlc_am_transmission_buffer[amd_pdu->hdr.sn] = new_pdu; + } +} +void LTE_fdd_enb_rb::rlc_update_transmission_buffer(LIBLTE_RLC_STATUS_PDU_STRUCT *status) +{ + std::map::iterator iter; + uint32 i = rlc_vta; + uint32 j; + bool update_vta = true; + bool remove_sn; - if(LIBLTE_RLC_FI_FIELD_FULL_SDU == amd_pdu->hdr.fi) + while(i != status->ack_sn) + { + remove_sn = true; + for(j=0; jN_nack; j++) { - rlc_first_segment_sn = amd_pdu->hdr.sn; - rlc_last_segment_sn = amd_pdu->hdr.sn; - }else if(LIBLTE_RLC_FI_FIELD_FIRST_SDU_SEGMENT == amd_pdu->hdr.fi){ - rlc_first_segment_sn = amd_pdu->hdr.sn; - }else if(LIBLTE_RLC_FI_FIELD_LAST_SDU_SEGMENT == amd_pdu->hdr.fi){ - rlc_last_segment_sn = amd_pdu->hdr.sn; + if(i == status->nack_sn[j]) + { + remove_sn = false; + update_vta = false; + break; + } } + if(remove_sn) + { + iter = rlc_am_transmission_buffer.find(i); + if(rlc_am_transmission_buffer.end() != iter) + { + delete (*iter).second; + rlc_am_transmission_buffer.erase(iter); + } + if(update_vta) + { + set_rlc_vta(i+1); + } + } + i = (i+1) % 1024; + } + + if(rlc_am_transmission_buffer.size() == 0) + { + rlc_stop_t_poll_retransmit(); } } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::rlc_reassemble(LIBLTE_BIT_MSG_STRUCT *sdu) +void LTE_fdd_enb_rb::rlc_start_t_poll_retransmit(void) { - std::map::iterator iter; - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_CANT_REASSEMBLE_SDU; - uint32 i; + LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + LTE_fdd_enb_timer_cb timer_expiry_cb(<E_fdd_enb_timer_cb_wrapper, this); - if(0xFFFF != rlc_first_segment_sn && - 0xFFFF != rlc_last_segment_sn) + if(LTE_FDD_ENB_INVALID_TIMER_ID == t_poll_retransmit_timer_id) { - // Reorder and reassemble the SDU - for(i=rlc_first_segment_sn; i<=rlc_last_segment_sn; i++) + timer_mgr->start_timer(100, timer_expiry_cb, &t_poll_retransmit_timer_id); + } +} +void LTE_fdd_enb_rb::rlc_stop_t_poll_retransmit(void) +{ + LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + + timer_mgr->stop_timer(t_poll_retransmit_timer_id); + t_poll_retransmit_timer_id = LTE_FDD_ENB_INVALID_TIMER_ID; +} +void LTE_fdd_enb_rb::handle_t_poll_retransmit_timer_expiry(uint32 timer_id) +{ + LTE_fdd_enb_rlc *rlc = LTE_fdd_enb_rlc::get_instance(); + std::map::iterator iter = rlc_am_transmission_buffer.find(rlc_vta); + + t_poll_retransmit_timer_id = LTE_FDD_ENB_INVALID_TIMER_ID; + + if(rlc_am_transmission_buffer.end() != iter) + { + rlc->handle_retransmit((*iter).second, user, this); + } +} +void LTE_fdd_enb_rb::set_rlc_vruh(uint16 vruh) +{ + rlc_vruh = vruh; +} +uint16 LTE_fdd_enb_rb::get_rlc_vruh(void) +{ + return(rlc_vruh); +} +void LTE_fdd_enb_rb::set_rlc_vrur(uint16 vrur) +{ + rlc_vrur = vrur; +} +uint16 LTE_fdd_enb_rb::get_rlc_vrur(void) +{ + return(rlc_vrur); +} +uint16 LTE_fdd_enb_rb::get_rlc_um_window_size(void) +{ + return(rlc_um_window_size); +} +void LTE_fdd_enb_rb::rlc_add_to_um_reception_buffer(LIBLTE_RLC_UMD_PDU_STRUCT *umd_pdu, + uint32 idx) +{ + std::map::iterator iter; + LIBLTE_BYTE_MSG_STRUCT *new_pdu = NULL; + + new_pdu = new LIBLTE_BYTE_MSG_STRUCT; + + if(NULL != new_pdu) + { + iter = rlc_um_reception_buffer.find(umd_pdu->hdr.sn); + if(rlc_um_reception_buffer.end() == iter) { - // FIXME: Error handling - iter = rlc_reception_buffer.find(i); - memcpy(&sdu->msg[sdu->N_bits], (*iter).second->msg, (*iter).second->N_bits); - sdu->N_bits += (*iter).second->N_bits; - delete (*iter).second; - rlc_reception_buffer.erase(iter); + memcpy(new_pdu, &umd_pdu->data[idx], sizeof(LIBLTE_BYTE_MSG_STRUCT)); + rlc_um_reception_buffer[umd_pdu->hdr.sn] = new_pdu; + + if(LIBLTE_RLC_FI_FIELD_FULL_SDU == umd_pdu->hdr.fi) + { + rlc_first_um_segment_sn = umd_pdu->hdr.sn; + rlc_last_um_segment_sn = umd_pdu->hdr.sn; + }else if(LIBLTE_RLC_FI_FIELD_FIRST_SDU_SEGMENT == umd_pdu->hdr.fi){ + rlc_first_um_segment_sn = umd_pdu->hdr.sn; + }else if(LIBLTE_RLC_FI_FIELD_LAST_SDU_SEGMENT == umd_pdu->hdr.fi){ + rlc_last_um_segment_sn = umd_pdu->hdr.sn; + } + if(rlc_last_um_segment_sn < rlc_first_um_segment_sn) + { + rlc_last_um_segment_sn = 0xFFFF; + } + }else{ + delete new_pdu; + } + } +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::rlc_um_reassemble(LIBLTE_BYTE_MSG_STRUCT *sdu) +{ + std::map::iterator iter; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_CANT_REASSEMBLE_SDU; + uint32 i; + bool reassemble = true; + + if(0xFFFF != rlc_first_um_segment_sn && + 0xFFFF != rlc_last_um_segment_sn) + { + // Make sure all segments are available + for(i=rlc_first_um_segment_sn; i<=rlc_last_um_segment_sn; i++) + { + iter = rlc_um_reception_buffer.find(i); + if(rlc_um_reception_buffer.end() == iter) + { + reassemble = false; + } } - // Clear the first/last segment SNs - rlc_first_segment_sn = 0xFFFF; - rlc_last_segment_sn = 0xFFFF; + if(reassemble) + { + // Reorder and reassemble the SDU + sdu->N_bytes = 0; + for(i=rlc_first_um_segment_sn; i<=rlc_last_um_segment_sn; i++) + { + iter = rlc_um_reception_buffer.find(i); + memcpy(&sdu->msg[sdu->N_bytes], (*iter).second->msg, (*iter).second->N_bytes); + sdu->N_bytes += (*iter).second->N_bytes; + delete (*iter).second; + rlc_um_reception_buffer.erase(iter); + } - err = LTE_FDD_ENB_ERROR_NONE; + // Clear the first/last segment SNs + rlc_first_um_segment_sn = 0xFFFF; + rlc_last_um_segment_sn = 0xFFFF; + + err = LTE_FDD_ENB_ERROR_NONE; + } } return(err); } +void LTE_fdd_enb_rb::set_rlc_vtus(uint16 vtus) +{ + rlc_vtus = vtus; +} +uint16 LTE_fdd_enb_rb::get_rlc_vtus(void) +{ + return(rlc_vtus); +} /*************/ /* MAC */ /*************/ -void LTE_fdd_enb_rb::queue_mac_sdu(LIBLTE_BIT_MSG_STRUCT *sdu) +void LTE_fdd_enb_rb::queue_mac_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu) { - queue_msg(sdu, &mac_sdu_queue_mutex, &mac_sdu_queue); + queue_msg(sdu, &mac_sdu_queue_sem, &mac_sdu_queue); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_mac_sdu(LIBLTE_BIT_MSG_STRUCT **sdu) +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_mac_sdu(LIBLTE_BYTE_MSG_STRUCT **sdu) { - return(get_next_msg(&mac_sdu_queue_mutex, &mac_sdu_queue, sdu)); + return(get_next_msg(&mac_sdu_queue_sem, &mac_sdu_queue, sdu)); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_mac_sdu(void) { - return(delete_next_msg(&mac_sdu_queue_mutex, &mac_sdu_queue)); + return(delete_next_msg(&mac_sdu_queue_sem, &mac_sdu_queue)); } LTE_FDD_ENB_MAC_CONFIG_ENUM LTE_fdd_enb_rb::get_mac_config(void) { return(mac_config); } -void LTE_fdd_enb_rb::start_ul_sched_timer(uint32 m_seconds) +void LTE_fdd_enb_rb::set_con_res_id(uint64 con_res_id) { - LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); - LTE_fdd_enb_timer_cb timer_expiry_cb(<E_fdd_enb_timer_cb_wrapper, this); - - ul_sched_timer_m_seconds = m_seconds; - timer_mgr->start_timer(ul_sched_timer_m_seconds, timer_expiry_cb, &ul_sched_timer_id); + mac_con_res_id = con_res_id; +} +uint64 LTE_fdd_enb_rb::get_con_res_id(void) +{ + return(mac_con_res_id); +} +void LTE_fdd_enb_rb::set_send_con_res_id(bool send_con_res_id) +{ + mac_send_con_res_id = send_con_res_id; } -void LTE_fdd_enb_rb::handle_ul_sched_timer_expiry(uint32 timer_id) +bool LTE_fdd_enb_rb::get_send_con_res_id(void) { - LTE_fdd_enb_mac *mac = LTE_fdd_enb_mac::get_instance(); + return(mac_send_con_res_id); +} - mac->sched_ul(user, avail_qos[qos].bits_per_subfn); - if(LTE_FDD_ENB_RRC_PROC_IDLE != rrc_procedure && - LTE_FDD_ENB_RRC_STATE_IDLE != rrc_state) - { - start_ul_sched_timer(ul_sched_timer_m_seconds); - } +/*************/ +/* DRB */ +/*************/ +void LTE_fdd_enb_rb::set_eps_bearer_id(uint32 ebi) +{ + eps_bearer_id = ebi; +} +uint32 LTE_fdd_enb_rb::get_eps_bearer_id(void) +{ + return(eps_bearer_id); +} +void LTE_fdd_enb_rb::set_lc_id(uint32 _lc_id) +{ + lc_id = _lc_id; +} +uint32 LTE_fdd_enb_rb::get_lc_id(void) +{ + return(lc_id); +} +void LTE_fdd_enb_rb::set_drb_id(uint8 _drb_id) +{ + drb_id = _drb_id; +} +uint8 LTE_fdd_enb_rb::get_drb_id(void) +{ + return(drb_id); +} +void LTE_fdd_enb_rb::set_log_chan_group(uint8 lcg) +{ + log_chan_group = lcg; +} +uint8 LTE_fdd_enb_rb::get_log_chan_group(void) +{ + return(log_chan_group); } /*****************/ /* Generic */ /*****************/ void LTE_fdd_enb_rb::queue_msg(LIBLTE_BIT_MSG_STRUCT *msg, - boost::mutex *mutex, + sem_t *sem, std::list *queue) { - boost::mutex::scoped_lock lock(*mutex); - LIBLTE_BIT_MSG_STRUCT *loc_msg; + libtools_scoped_lock lock(*sem); + LIBLTE_BIT_MSG_STRUCT *loc_msg; loc_msg = new LIBLTE_BIT_MSG_STRUCT; memcpy(loc_msg, msg, sizeof(LIBLTE_BIT_MSG_STRUCT)); @@ -373,23 +1004,23 @@ void LTE_fdd_enb_rb::queue_msg(LIBLTE_BIT_MSG_STRUCT *msg, queue->push_back(loc_msg); } void LTE_fdd_enb_rb::queue_msg(LIBLTE_BYTE_MSG_STRUCT *msg, - boost::mutex *mutex, + sem_t *sem, std::list *queue) { - boost::mutex::scoped_lock lock(*mutex); - LIBLTE_BYTE_MSG_STRUCT *loc_msg; + libtools_scoped_lock lock(*sem); + LIBLTE_BYTE_MSG_STRUCT *loc_msg; loc_msg = new LIBLTE_BYTE_MSG_STRUCT; memcpy(loc_msg, msg, sizeof(LIBLTE_BYTE_MSG_STRUCT)); queue->push_back(loc_msg); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_msg(boost::mutex *mutex, +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_msg(sem_t *sem, std::list *queue, LIBLTE_BIT_MSG_STRUCT **msg) { - boost::mutex::scoped_lock lock(*mutex); - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NO_MSG_IN_QUEUE; + libtools_scoped_lock lock(*sem); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NO_MSG_IN_QUEUE; if(0 != queue->size()) { @@ -399,12 +1030,12 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_msg(boost::mutex return(err); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_msg(boost::mutex *mutex, +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_msg(sem_t *sem, std::list *queue, LIBLTE_BYTE_MSG_STRUCT **msg) { - boost::mutex::scoped_lock lock(*mutex); - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NO_MSG_IN_QUEUE; + libtools_scoped_lock lock(*sem); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NO_MSG_IN_QUEUE; if(0 != queue->size()) { @@ -414,12 +1045,12 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::get_next_msg(boost::mutex return(err); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_msg(boost::mutex *mutex, +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_msg(sem_t *sem, std::list *queue) { - boost::mutex::scoped_lock lock(*mutex); - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NO_MSG_IN_QUEUE; - LIBLTE_BIT_MSG_STRUCT *msg; + libtools_scoped_lock lock(*sem); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NO_MSG_IN_QUEUE; + LIBLTE_BIT_MSG_STRUCT *msg; if(0 != queue->size()) { @@ -431,12 +1062,12 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_msg(boost::mutex return(err); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_msg(boost::mutex *mutex, +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_msg(sem_t *sem, std::list *queue) { - boost::mutex::scoped_lock lock(*mutex); - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NO_MSG_IN_QUEUE; - LIBLTE_BYTE_MSG_STRUCT *msg; + libtools_scoped_lock lock(*sem); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NO_MSG_IN_QUEUE; + LIBLTE_BYTE_MSG_STRUCT *msg; if(0 != queue->size()) { @@ -448,15 +1079,3 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_rb::delete_next_msg(boost::mutex return(err); } -void LTE_fdd_enb_rb::set_qos(LTE_FDD_ENB_QOS_ENUM _qos) -{ - qos = _qos; - if(qos != LTE_FDD_ENB_QOS_NONE) - { - start_ul_sched_timer(avail_qos[qos].tti_frequency-1); - } -} -LTE_FDD_ENB_QOS_ENUM LTE_fdd_enb_rb::get_qos(void) -{ - return(qos); -} diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_rlc.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_rlc.cc old mode 100644 new mode 100755 index 8250935..f9a57e1 --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_rlc.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_rlc.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_rlc.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -29,6 +29,24 @@ 01/18/2014 Ben Wojtowicz Added level to debug prints. 05/04/2014 Ben Wojtowicz Added communication to MAC and PDCP. 06/15/2014 Ben Wojtowicz Added basic AM receive functionality. + 08/03/2014 Ben Wojtowicz Added transmit functionality. + 09/03/2014 Ben Wojtowicz Added debug print and status request. + 11/01/2014 Ben Wojtowicz Fixed VRR updating and added debug. + 11/29/2014 Ben Wojtowicz Using the byte message structure and added + UMD support. + 12/16/2014 Ben Wojtowicz Added ol extension to message queues. + 12/24/2014 Ben Wojtowicz Using asymmetric QoS. + 02/15/2015 Ben Wojtowicz Moved to new message queue and added header + extension/multiple data support to UMD. + 03/11/2015 Ben Wojtowicz Added header extension/multiple data support + to AMD. + 07/25/2015 Ben Wojtowicz Using the new user QoS structure. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t. + 07/03/2016 Ben Wojtowicz Added error log for AMD PDU segments. + 12/18/2016 Ben Wojtowicz Properly handling multiple AMD PDUs. + 07/29/2017 Ben Wojtowicz Try more than one reassembly and always send + poll frames. *******************************************************************************/ @@ -37,8 +55,8 @@ *******************************************************************************/ #include "LTE_fdd_enb_rlc.h" -#include "LTE_fdd_enb_interface.h" #include "liblte_rlc.h" +#include "libtools_scoped_lock.h" /******************************************************************************* DEFINES @@ -54,8 +72,8 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_enb_rlc* LTE_fdd_enb_rlc::instance = NULL; -boost::mutex rlc_instance_mutex; +LTE_fdd_enb_rlc* LTE_fdd_enb_rlc::instance = NULL; +static pthread_mutex_t rlc_instance_mutex = PTHREAD_MUTEX_INITIALIZER; /******************************************************************************* CLASS IMPLEMENTATIONS @@ -66,7 +84,7 @@ boost::mutex rlc_instance_mutex; /*******************/ LTE_fdd_enb_rlc* LTE_fdd_enb_rlc::get_instance(void) { - boost::mutex::scoped_lock lock(rlc_instance_mutex); + libtools_scoped_lock lock(rlc_instance_mutex); if(NULL == instance) { @@ -77,7 +95,7 @@ LTE_fdd_enb_rlc* LTE_fdd_enb_rlc::get_instance(void) } void LTE_fdd_enb_rlc::cleanup(void) { - boost::mutex::scoped_lock lock(rlc_instance_mutex); + libtools_scoped_lock lock(rlc_instance_mutex); if(NULL != instance) { @@ -91,62 +109,64 @@ void LTE_fdd_enb_rlc::cleanup(void) /********************************/ LTE_fdd_enb_rlc::LTE_fdd_enb_rlc() { + sem_init(&start_sem, 0, 1); + sem_init(&sys_info_sem, 0, 1); started = false; } LTE_fdd_enb_rlc::~LTE_fdd_enb_rlc() { stop(); + sem_destroy(&sys_info_sem); + sem_destroy(&start_sem); } /********************/ /* Start/Stop */ /********************/ -void LTE_fdd_enb_rlc::start(void) +void LTE_fdd_enb_rlc::start(LTE_fdd_enb_msgq *from_mac, + LTE_fdd_enb_msgq *from_pdcp, + LTE_fdd_enb_msgq *to_mac, + LTE_fdd_enb_msgq *to_pdcp, + LTE_fdd_enb_interface *iface) { - boost::mutex::scoped_lock lock(start_mutex); - LTE_fdd_enb_msgq_cb mac_cb(<E_fdd_enb_msgq_cb_wrapper, this); - LTE_fdd_enb_msgq_cb pdcp_cb(<E_fdd_enb_msgq_cb_wrapper, this); + libtools_scoped_lock lock(start_sem); + LTE_fdd_enb_msgq_cb mac_cb(<E_fdd_enb_msgq_cb_wrapper, this); + LTE_fdd_enb_msgq_cb pdcp_cb(<E_fdd_enb_msgq_cb_wrapper, this); if(!started) { + interface = iface; started = true; - mac_comm_msgq = new LTE_fdd_enb_msgq("mac_rlc_mq", - mac_cb); - pdcp_comm_msgq = new LTE_fdd_enb_msgq("pdcp_rlc_mq", - pdcp_cb); - rlc_mac_mq = new boost::interprocess::message_queue(boost::interprocess::open_only, - "rlc_mac_mq"); - rlc_pdcp_mq = new boost::interprocess::message_queue(boost::interprocess::open_only, - "rlc_pdcp_mq"); + msgq_from_mac = from_mac; + msgq_from_pdcp = from_pdcp; + msgq_to_mac = to_mac; + msgq_to_pdcp = to_pdcp; + msgq_from_mac->attach_rx(mac_cb); + msgq_from_pdcp->attach_rx(pdcp_cb); } } void LTE_fdd_enb_rlc::stop(void) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_sem); if(started) { started = false; - delete mac_comm_msgq; - delete pdcp_comm_msgq; } } /***********************/ /* Communication */ /***********************/ -void LTE_fdd_enb_rlc::handle_mac_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) +void LTE_fdd_enb_rlc::handle_mac_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - - if(LTE_FDD_ENB_DEST_LAYER_RLC == msg->dest_layer || - LTE_FDD_ENB_DEST_LAYER_ANY == msg->dest_layer) + if(LTE_FDD_ENB_DEST_LAYER_RLC == msg.dest_layer || + LTE_FDD_ENB_DEST_LAYER_ANY == msg.dest_layer) { - switch(msg->type) + switch(msg.type) { case LTE_FDD_ENB_MESSAGE_TYPE_RLC_PDU_READY: - handle_pdu_ready(&msg->msg.rlc_pdu_ready); - delete msg; + handle_pdu_ready(&msg.msg.rlc_pdu_ready); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, @@ -154,27 +174,23 @@ void LTE_fdd_enb_rlc::handle_mac_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) __FILE__, __LINE__, "Received invalid MAC message %s", - LTE_fdd_enb_message_type_text[msg->type]); - delete msg; + LTE_fdd_enb_message_type_text[msg.type]); break; } }else{ // Forward message to PDCP - rlc_pdcp_mq->send(&msg, sizeof(msg), 0); + msgq_to_pdcp->send(msg); } } -void LTE_fdd_enb_rlc::handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) +void LTE_fdd_enb_rlc::handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - - if(LTE_FDD_ENB_DEST_LAYER_RLC == msg->dest_layer || - LTE_FDD_ENB_DEST_LAYER_ANY == msg->dest_layer) + if(LTE_FDD_ENB_DEST_LAYER_RLC == msg.dest_layer || + LTE_FDD_ENB_DEST_LAYER_ANY == msg.dest_layer) { - switch(msg->type) + switch(msg.type) { case LTE_FDD_ENB_MESSAGE_TYPE_RLC_SDU_READY: - handle_sdu_ready(&msg->msg.rlc_sdu_ready); - delete msg; + handle_sdu_ready(&msg.msg.rlc_sdu_ready); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, @@ -182,13 +198,12 @@ void LTE_fdd_enb_rlc::handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) __FILE__, __LINE__, "Received invalid PDCP message %s", - LTE_fdd_enb_message_type_text[msg->type]); - delete msg; + LTE_fdd_enb_message_type_text[msg.type]); break; } }else{ // Forward message to MAC - rlc_mac_mq->send(&msg, sizeof(msg), 0); + msgq_to_mac->send(msg); } } @@ -197,11 +212,50 @@ void LTE_fdd_enb_rlc::handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) /****************************/ void LTE_fdd_enb_rlc::update_sys_info(void) { - LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + libtools_scoped_lock lock(sys_info_sem); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); - sys_info_mutex.lock(); cnfg_db->get_sys_info(sys_info); - sys_info_mutex.unlock(); +} +void LTE_fdd_enb_rlc::handle_retransmit(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT *amd, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT mac_sdu_ready; + LIBLTE_BYTE_MSG_STRUCT pdu; + + // Pack the PDU + amd->hdr.p = LIBLTE_RLC_P_FIELD_STATUS_REPORT_REQUESTED; + liblte_rlc_pack_amd_pdu(amd, &amd->data, &pdu); + + // Start t-pollretransmit + rb->rlc_start_t_poll_retransmit(); + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + &pdu, + "Re-sending AMD PDU for RNTI=%u, RB=%s, VT(A)=%u, SN=%u, VT(MS)=%u, RF=%s, P=%s, FI=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()], + rb->get_rlc_vta(), + amd->hdr.sn, + rb->get_rlc_vtms(), + liblte_rlc_rf_field_text[amd->hdr.rf], + liblte_rlc_p_field_text[amd->hdr.p], + liblte_rlc_fi_field_text[amd->hdr.fi]); + + // Queue the SDU for MAC + rb->queue_mac_sdu(&pdu); + + // Signal MAC + mac_sdu_ready.user = user; + mac_sdu_ready.rb = rb; + msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_MAC_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_MAC, + (LTE_FDD_ENB_MESSAGE_UNION *)&mac_sdu_ready, + sizeof(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT)); } /******************************/ @@ -209,8 +263,7 @@ void LTE_fdd_enb_rlc::update_sys_info(void) /******************************/ void LTE_fdd_enb_rlc::handle_pdu_ready(LTE_FDD_ENB_RLC_PDU_READY_MSG_STRUCT *pdu_ready) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - LIBLTE_BIT_MSG_STRUCT *pdu; + LIBLTE_BYTE_MSG_STRUCT *pdu; if(LTE_FDD_ENB_ERROR_NONE == pdu_ready->rb->get_next_rlc_pdu(&pdu)) { @@ -257,9 +310,9 @@ void LTE_fdd_enb_rlc::handle_pdu_ready(LTE_FDD_ENB_RLC_PDU_READY_MSG_STRUCT *pdu "Received pdu_ready message with no PDU queued"); } } -void LTE_fdd_enb_rlc::handle_tm_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, - LTE_fdd_enb_user *user, - LTE_fdd_enb_rb *rb) +void LTE_fdd_enb_rlc::handle_tm_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) { LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT pdcp_pdu_ready; @@ -269,131 +322,277 @@ void LTE_fdd_enb_rlc::handle_tm_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, // Signal PDCP pdcp_pdu_ready.user = user; pdcp_pdu_ready.rb = rb; - LTE_fdd_enb_msgq::send(rlc_pdcp_mq, - LTE_FDD_ENB_MESSAGE_TYPE_PDCP_PDU_READY, - LTE_FDD_ENB_DEST_LAYER_PDCP, - (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_pdu_ready, - sizeof(LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT)); -} -void LTE_fdd_enb_rlc::handle_um_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, - LTE_fdd_enb_user *user, - LTE_fdd_enb_rb *rb) -{ - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, - LTE_FDD_ENB_DEBUG_LEVEL_RLC, - __FILE__, - __LINE__, - "Not handling PDUs for RLC UM config"); + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_PDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_pdu_ready, + sizeof(LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT)); } -void LTE_fdd_enb_rlc::handle_am_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, - LTE_fdd_enb_user *user, - LTE_fdd_enb_rb *rb) +void LTE_fdd_enb_rlc::handle_um_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT pdcp_pdu_ready; - LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT mac_sdu_ready; - LIBLTE_BIT_MSG_STRUCT pdcp_pdu; - LIBLTE_BIT_MSG_STRUCT mac_sdu; - LIBLTE_RLC_AMD_PDU_STRUCT amd; - LIBLTE_RLC_STATUS_PDU_STRUCT status; - uint16 vrr = rb->get_rlc_vrr(); - uint16 vrmr = rb->get_rlc_vrmr(); - uint16 vrh = rb->get_rlc_vrh(); - - liblte_rlc_unpack_amd_pdu(pdu, &amd); - - if(vrr <= amd.hdr.sn && - amd.hdr.sn < vrmr) + LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT pdcp_pdu_ready; + LIBLTE_BYTE_MSG_STRUCT pdcp_pdu; + LIBLTE_RLC_UMD_PDU_STRUCT umd; + LIBLTE_RLC_FI_FIELD_ENUM orig_fi; + int32 vrul = (int32)rb->get_rlc_vruh() - (int32)rb->get_rlc_um_window_size(); + uint16 vrur = rb->get_rlc_vrur(); + + umd.hdr.sn_size = LIBLTE_RLC_UMD_SN_SIZE_10_BITS; + if(LIBLTE_SUCCESS == liblte_rlc_unpack_umd_pdu(pdu, &umd)) { - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, - LTE_FDD_ENB_DEBUG_LEVEL_RLC, - __FILE__, - __LINE__, - &amd.data, - "Received AMD PDU for RNTI=%u, RB=%s, VR(R)=%u, SN=%u, VR(MR)=%u, VR(H)=%u, RF=%s, P=%s, FI=%s", - user->get_c_rnti(), - LTE_fdd_enb_rb_text[rb->get_rb_id()], - vrr, - amd.hdr.sn, - vrmr, - vrh, - liblte_rlc_rf_field_text[amd.hdr.rf], - liblte_rlc_p_field_text[amd.hdr.p], - liblte_rlc_fi_field_text[amd.hdr.fi]); - - // Place RLC data PDU in reception buffer - rb->rlc_add_to_reception_buffer(&amd); - - // Update VR(H) - if(amd.hdr.sn >= vrh) + if(!(vrul <= umd.hdr.sn && + umd.hdr.sn < vrur)) { - rb->set_rlc_vrh(amd.hdr.sn + 1); - } - - // Update VR(MS) - // FIXME - - // Update VR(R)/VR(MR) and reassemble - if(amd.hdr.sn == vrr) - { - // FIXME: Handle AMD PDU Segments - rb->set_rlc_vrr(amd.hdr.sn + 1); - - if(LTE_FDD_ENB_ERROR_NONE == rb->rlc_reassemble(&pdcp_pdu)) + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + &umd.data[0], + "Received UMD PDU for RNTI=%u, RB=%s, VR(UL)=%d, SN=%u, VR(UR)=%u, FI=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()], + vrul, + umd.hdr.sn, + vrur, + liblte_rlc_fi_field_text[umd.hdr.fi]); + + if(1 == umd.N_data) { - // Queue the SDU for PDCP - rb->queue_pdcp_pdu(&pdcp_pdu); - - // Signal PDCP - pdcp_pdu_ready.user = user; - pdcp_pdu_ready.rb = rb; - LTE_fdd_enb_msgq::send(rlc_pdcp_mq, - LTE_FDD_ENB_MESSAGE_TYPE_PDCP_PDU_READY, + // Place RLC data PDU in reception buffer + rb->rlc_add_to_um_reception_buffer(&umd, 0); + + if(LTE_FDD_ENB_ERROR_NONE == rb->rlc_um_reassemble(&pdcp_pdu)) + { + // Queue the SDU for PDCP + rb->queue_pdcp_pdu(&pdcp_pdu); + + // Signal PDCP + pdcp_pdu_ready.user = user; + pdcp_pdu_ready.rb = rb; + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_PDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_pdu_ready, + sizeof(LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT)); + } + }else if(2 == umd.N_data){ + // Place first RLC data PDU in reception buffer + orig_fi = umd.hdr.fi; + if(LIBLTE_RLC_FI_FIELD_FULL_SDU != umd.hdr.fi) + { + umd.hdr.fi = LIBLTE_RLC_FI_FIELD_LAST_SDU_SEGMENT; + } + rb->rlc_add_to_um_reception_buffer(&umd, 0); + + if(LTE_FDD_ENB_ERROR_NONE == rb->rlc_um_reassemble(&pdcp_pdu)) + { + // Queue the SDU for PDCP + rb->queue_pdcp_pdu(&pdcp_pdu); + + // Signal PDCP + pdcp_pdu_ready.user = user; + pdcp_pdu_ready.rb = rb; + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_PDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_pdu_ready, + sizeof(LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT)); + } + + // Place the second RLC data PDU in reception buffer + if(LIBLTE_RLC_FI_FIELD_MIDDLE_SDU_SEGMENT == orig_fi) + { + umd.hdr.fi = LIBLTE_RLC_FI_FIELD_FIRST_SDU_SEGMENT; + }else{ + umd.hdr.fi = orig_fi; + } + rb->rlc_add_to_um_reception_buffer(&umd, 1); + + if(LTE_FDD_ENB_ERROR_NONE == rb->rlc_um_reassemble(&pdcp_pdu)) + { + // Queue the SDU for PDCP + rb->queue_pdcp_pdu(&pdcp_pdu); + + // Signal PDCP + pdcp_pdu_ready.user = user; + pdcp_pdu_ready.rb = rb; + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_PDU_READY, LTE_FDD_ENB_DEST_LAYER_PDCP, (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_pdu_ready, sizeof(LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT)); + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + "Multiple data segments (%u) in one RLC PDU", + umd.N_data); } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + &umd.data[0], + "Received UMD PDU for RNTI=%u, RB=%s, that is outside of the receiving window (%d <= %u < %u)", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()], + vrul, + umd.hdr.sn, + vrur); } - - // Send a STATUS PDU to acknowledge the PDU - status.ack_sn = amd.hdr.sn + 1; - liblte_rlc_pack_status_pdu(&status, &mac_sdu); - - // Queue the PDU for MAC - rb->queue_mac_sdu(&mac_sdu); - - // Signal MAC - mac_sdu_ready.user = user; - mac_sdu_ready.rb = rb; - LTE_fdd_enb_msgq::send(rlc_mac_mq, - LTE_FDD_ENB_MESSAGE_TYPE_MAC_SDU_READY, - LTE_FDD_ENB_DEST_LAYER_MAC, - (LTE_FDD_ENB_MESSAGE_UNION *)&mac_sdu_ready, - sizeof(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT)); }else{ - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, LTE_FDD_ENB_DEBUG_LEVEL_RLC, __FILE__, __LINE__, - &amd.data, - "Received AMD PDU for RNTI=%u, RB=%s, that is outside of the receiving window (%u <= %u < %u)", - user->get_c_rnti(), - LTE_fdd_enb_rb_text[rb->get_rb_id()], - vrr, - amd.hdr.sn, - vrmr); + "Can't unpack UMD PDU"); + } +} +void LTE_fdd_enb_rlc::handle_am_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT pdcp_pdu_ready; + LIBLTE_BYTE_MSG_STRUCT pdcp_pdu; + LIBLTE_RLC_AMD_PDUS_STRUCT amd_pdus; + LIBLTE_RLC_STATUS_PDU_STRUCT status; + uint32 i; + uint16 vrr = rb->get_rlc_vrr(); + uint16 vrmr = rb->get_rlc_vrmr(); + uint16 vrh = rb->get_rlc_vrh(); + + if(LIBLTE_SUCCESS == liblte_rlc_unpack_amd_pdu(pdu, &amd_pdus)) + { + if(LIBLTE_RLC_DC_FIELD_CONTROL_PDU == amd_pdus.pdu[0].hdr.dc) + { + handle_status_pdu(pdu, user, rb); + }else{ + if(LIBLTE_RLC_RF_FIELD_AMD_PDU_SEGMENT == amd_pdus.pdu[0].hdr.rf) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + &amd_pdus.pdu[0].data, + "Not handling AMD PDU segments"); + }else{ + for(i=0; isend_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + &amd_pdus.pdu[i].data, + "Received AMD PDU for RNTI=%u, RB=%s, VR(R)=%u, SN=%u, VR(MR)=%u, VR(H)=%u, RF=%s, P=%s, FI=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()], + vrr, + amd_pdus.pdu[i].hdr.sn, + vrmr, + vrh, + liblte_rlc_rf_field_text[amd_pdus.pdu[i].hdr.rf], + liblte_rlc_p_field_text[amd_pdus.pdu[i].hdr.p], + liblte_rlc_fi_field_text[amd_pdus.pdu[i].hdr.fi]); + + // Place RLC data PDU in reception buffer + rb->rlc_add_to_am_reception_buffer(&amd_pdus.pdu[i]); + + // Update VR(H) + if(amd_pdus.pdu[i].hdr.sn >= vrh) + { + rb->set_rlc_vrh(amd_pdus.pdu[i].hdr.sn + 1); + } + + // Update VR(MS) + // FIXME + + // Update VR(R)/VR(MR) and reassemble + if(amd_pdus.pdu[i].hdr.sn == vrr) + { + rb->update_rlc_vrr(); + // FIXME: Handle AMD PDU Segments + + while(LTE_FDD_ENB_ERROR_NONE == rb->rlc_am_reassemble(&pdcp_pdu)) + { + // Queue the SDU for PDCP + rb->queue_pdcp_pdu(&pdcp_pdu); + + // Signal PDCP + pdcp_pdu_ready.user = user; + pdcp_pdu_ready.rb = rb; + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_PDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_pdu_ready, + sizeof(LTE_FDD_ENB_PDCP_PDU_READY_MSG_STRUCT)); + } + } + +// if(amd_pdus.pdu[i].hdr.p) + { + // Send a STATUS PDU to ACK/NACK SNs + rb->rlc_get_am_reception_buffer_status(&status); + send_status_pdu(&status, user, rb); + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + &amd_pdus.pdu[i].data, + "Received AMD PDU for RNTI=%u, RB=%s, that is outside of the receiving window (%u <= %u < %u), P=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()], + vrr, + amd_pdus.pdu[i].hdr.sn, + vrmr, + liblte_rlc_p_field_text[amd_pdus.pdu[i].hdr.p]); + +// if(amd_pdus.pdu[i].hdr.p) + { + // Send a STATUS PDU to ACK/NACK SNs + rb->rlc_get_am_reception_buffer_status(&status); + send_status_pdu(&status, user, rb); + } + } + } + } + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + "Can't unpack AMD PDU"); } } +void LTE_fdd_enb_rlc::handle_status_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LIBLTE_RLC_STATUS_PDU_STRUCT status; + + liblte_rlc_unpack_status_pdu(pdu, &status); + + rb->rlc_update_transmission_buffer(&status); + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + pdu, + "Received STATUS PDU"); +} /*******************************/ /* PDCP Message Handlers */ /*******************************/ void LTE_fdd_enb_rlc::handle_sdu_ready(LTE_FDD_ENB_RLC_SDU_READY_MSG_STRUCT *sdu_ready) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - LIBLTE_BIT_MSG_STRUCT *sdu; + LIBLTE_BYTE_MSG_STRUCT *sdu; if(LTE_FDD_ENB_ERROR_NONE == sdu_ready->rb->get_next_rlc_sdu(&sdu)) { @@ -439,45 +638,274 @@ void LTE_fdd_enb_rlc::handle_sdu_ready(LTE_FDD_ENB_RLC_SDU_READY_MSG_STRUCT *sdu "Received sdu_ready message with no SDU queued"); } } -void LTE_fdd_enb_rlc::handle_tm_sdu(LIBLTE_BIT_MSG_STRUCT *sdu, - LTE_fdd_enb_user *user, - LTE_fdd_enb_rb *rb) +void LTE_fdd_enb_rlc::handle_tm_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) { LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT mac_sdu_ready; + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + sdu, + "Sending TMD PDU for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + // Queue the SDU for MAC rb->queue_mac_sdu(sdu); // Signal MAC mac_sdu_ready.user = user; mac_sdu_ready.rb = rb; - LTE_fdd_enb_msgq::send(rlc_mac_mq, - LTE_FDD_ENB_MESSAGE_TYPE_MAC_SDU_READY, - LTE_FDD_ENB_DEST_LAYER_MAC, - (LTE_FDD_ENB_MESSAGE_UNION *)&mac_sdu_ready, - sizeof(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT)); + msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_MAC_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_MAC, + (LTE_FDD_ENB_MESSAGE_UNION *)&mac_sdu_ready, + sizeof(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT)); } -void LTE_fdd_enb_rlc::handle_um_sdu(LIBLTE_BIT_MSG_STRUCT *sdu, - LTE_fdd_enb_user *user, - LTE_fdd_enb_rb *rb) +void LTE_fdd_enb_rlc::handle_um_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT mac_sdu_ready; + LIBLTE_RLC_UMD_PDU_STRUCT umd; + LIBLTE_BYTE_MSG_STRUCT pdu; + uint32 byte_idx = 0; + uint32 bytes_per_subfn = user->get_max_dl_bytes_per_subfn(); + uint16 vtus = rb->get_rlc_vtus(); - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, - LTE_FDD_ENB_DEBUG_LEVEL_RLC, - __FILE__, - __LINE__, - "Not handling SDUs for RLC UM config"); + if(sdu->N_bytes <= bytes_per_subfn) + { + // Pack the PDU + umd.hdr.fi = LIBLTE_RLC_FI_FIELD_FULL_SDU; + umd.hdr.sn = vtus; + umd.hdr.sn_size = LIBLTE_RLC_UMD_SN_SIZE_10_BITS; + umd.N_data = 1; + memcpy(&umd.data, sdu, sizeof(LIBLTE_BYTE_MSG_STRUCT)); + rb->set_rlc_vtus(vtus+1); + liblte_rlc_pack_umd_pdu(&umd, &pdu); + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + &pdu, + "Sending UMD PDU for RNTI=%u, RB=%s, SN=%u, FI=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()], + umd.hdr.sn, + liblte_rlc_fi_field_text[umd.hdr.fi]); + + // Queue the PDU for MAC + rb->queue_mac_sdu(&pdu); + + // Signal MAC + mac_sdu_ready.user = user; + mac_sdu_ready.rb = rb; + msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_MAC_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_MAC, + (LTE_FDD_ENB_MESSAGE_UNION *)&mac_sdu_ready, + sizeof(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT)); + }else{ + // Segment the message + while(byte_idx < sdu->N_bytes) + { + umd.hdr.fi = LIBLTE_RLC_FI_FIELD_MIDDLE_SDU_SEGMENT; + umd.hdr.sn = vtus; + if(byte_idx == 0) + { + umd.hdr.fi = LIBLTE_RLC_FI_FIELD_FIRST_SDU_SEGMENT; + } + if((sdu->N_bytes - byte_idx) >= bytes_per_subfn) + { + memcpy(&umd.data[0].msg[0], &sdu->msg[byte_idx], bytes_per_subfn); + umd.data[0].N_bytes = bytes_per_subfn; + byte_idx += bytes_per_subfn; + }else{ + memcpy(&umd.data[0].msg[0], &sdu->msg[byte_idx], bytes_per_subfn); + umd.data[0].N_bytes = sdu->N_bytes - byte_idx; + byte_idx = sdu->N_bytes; + } + umd.N_data = 1; + if(byte_idx == sdu->N_bytes) + { + umd.hdr.fi = LIBLTE_RLC_FI_FIELD_LAST_SDU_SEGMENT; + } + rb->set_rlc_vtus(vtus+1); + vtus = rb->get_rlc_vtus(); + liblte_rlc_pack_umd_pdu(&umd, &pdu); + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + &pdu, + "Sending UMD PDU for RNTI=%u, RB=%s, SN=%u, FI=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()], + umd.hdr.sn, + liblte_rlc_fi_field_text[umd.hdr.fi]); + + // Queue the PDU for MAC + rb->queue_mac_sdu(&pdu); + + // Signal MAC + mac_sdu_ready.user = user; + mac_sdu_ready.rb = rb; + msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_MAC_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_MAC, + (LTE_FDD_ENB_MESSAGE_UNION *)&mac_sdu_ready, + sizeof(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT)); + } + } +} +void LTE_fdd_enb_rlc::handle_am_sdu(LIBLTE_BYTE_MSG_STRUCT *sdu, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT amd; + uint32 byte_idx = 0; + uint32 bytes_per_subfn = user->get_max_dl_bytes_per_subfn(); + uint16 vts = rb->get_rlc_vts(); + + if(sdu->N_bytes <= bytes_per_subfn) + { + amd.hdr.dc = LIBLTE_RLC_DC_FIELD_DATA_PDU; + amd.hdr.rf = LIBLTE_RLC_RF_FIELD_AMD_PDU; + amd.hdr.sn = vts; + amd.hdr.p = LIBLTE_RLC_P_FIELD_STATUS_REPORT_REQUESTED; + amd.hdr.fi = LIBLTE_RLC_FI_FIELD_FULL_SDU; + memcpy(&amd.data, sdu, sizeof(LIBLTE_BYTE_MSG_STRUCT)); + rb->set_rlc_vts(vts+1); + + send_amd_pdu(&amd, user, rb); + }else{ + // Segment the message + while(byte_idx < sdu->N_bytes) + { + amd.hdr.dc = LIBLTE_RLC_DC_FIELD_DATA_PDU; + amd.hdr.rf = LIBLTE_RLC_RF_FIELD_AMD_PDU; + amd.hdr.sn = vts; + amd.hdr.p = LIBLTE_RLC_P_FIELD_STATUS_REPORT_NOT_REQUESTED; + amd.hdr.fi = LIBLTE_RLC_FI_FIELD_MIDDLE_SDU_SEGMENT; + if(byte_idx == 0) + { + amd.hdr.fi = LIBLTE_RLC_FI_FIELD_FIRST_SDU_SEGMENT; + } + if((sdu->N_bytes - byte_idx) >= bytes_per_subfn) + { + memcpy(&amd.data.msg[0], &sdu->msg[byte_idx], bytes_per_subfn); + amd.data.N_bytes = bytes_per_subfn; + byte_idx += bytes_per_subfn; + }else{ + memcpy(&amd.data.msg[0], &sdu->msg[byte_idx], sdu->N_bytes - byte_idx); + amd.data.N_bytes = sdu->N_bytes - byte_idx; + byte_idx = sdu->N_bytes; + } + if(byte_idx == sdu->N_bytes) + { + amd.hdr.fi = LIBLTE_RLC_FI_FIELD_LAST_SDU_SEGMENT; + amd.hdr.p = LIBLTE_RLC_P_FIELD_STATUS_REPORT_REQUESTED; + } + rb->set_rlc_vts(vts+1); + vts = rb->get_rlc_vts(); + + send_amd_pdu(&amd, user, rb); + } + } } -void LTE_fdd_enb_rlc::handle_am_sdu(LIBLTE_BIT_MSG_STRUCT *sdu, - LTE_fdd_enb_user *user, - LTE_fdd_enb_rb *rb) + +/******************************/ +/* Message Constructors */ +/******************************/ +void LTE_fdd_enb_rlc::send_status_pdu(LIBLTE_RLC_STATUS_PDU_STRUCT *status_pdu, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + LIBLTE_BYTE_MSG_STRUCT mac_sdu; + LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT mac_sdu_ready; - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + // Pack the PDU + liblte_rlc_pack_status_pdu(status_pdu, &mac_sdu); + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_RLC, __FILE__, __LINE__, - "Not handling SDUs for RLC AM config"); + &mac_sdu, + "Sending STATUS PDU for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the PDU for MAC + rb->queue_mac_sdu(&mac_sdu); + + // Signal MAC + mac_sdu_ready.user = user; + mac_sdu_ready.rb = rb; + msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_MAC_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_MAC, + (LTE_FDD_ENB_MESSAGE_UNION *)&mac_sdu_ready, + sizeof(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_rlc::send_amd_pdu(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT *amd, + LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT mac_sdu_ready; + LIBLTE_BYTE_MSG_STRUCT pdu; + uint16 vta = rb->get_rlc_vta(); + uint16 vtms = rb->get_rlc_vtms(); + + // Pack the PDU + liblte_rlc_pack_amd_pdu(amd, &amd->data, &pdu); + + // Store + rb->rlc_add_to_transmission_buffer(amd); + + // Start t-pollretransmit + rb->rlc_start_t_poll_retransmit(); + + if(vta <= amd->hdr.sn && + amd->hdr.sn < vtms) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + &pdu, + "Sending AMD PDU for RNTI=%u, RB=%s, VT(A)=%u, SN=%u, VT(MS)=%u, RF=%s, P=%s, FI=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()], + vta, + amd->hdr.sn, + vtms, + liblte_rlc_rf_field_text[amd->hdr.rf], + liblte_rlc_p_field_text[amd->hdr.p], + liblte_rlc_fi_field_text[amd->hdr.fi]); + + // Queue the SDU for MAC + rb->queue_mac_sdu(&pdu); + + // Signal MAC + mac_sdu_ready.user = user; + mac_sdu_ready.rb = rb; + msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_MAC_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_MAC, + (LTE_FDD_ENB_MESSAGE_UNION *)&mac_sdu_ready, + sizeof(LTE_FDD_ENB_MAC_SDU_READY_MSG_STRUCT)); + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RLC, + __FILE__, + __LINE__, + &pdu, + "Can't send AMD PDU for RNTI=%u, RB=%s, outside of transmit window (%u <= %u < %u)", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()], + vta, + amd->hdr.sn, + vtms); + } } diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_rrc.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_rrc.cc old mode 100644 new mode 100755 index 78673c4..eb2f022 --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_rrc.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_rrc.cc @@ -1,7 +1,9 @@ #line 2 "LTE_fdd_enb_rrc.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz + Copyright 2016 Przemek Bereski (UE capability information and UE capability + enquiry support) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -31,6 +33,29 @@ machine. 06/15/2014 Ben Wojtowicz Added UL DCCH message handling and MME NAS message handling. + 08/03/2014 Ben Wojtowicz Added downlink NAS message handling and + connection release. + 11/01/2014 Ben Wojtowicz Added RRC connection reconfiguration and + security mode command messages. + 11/29/2014 Ben Wojtowicz Added DRB1 and DRB2 support and user + recovery on RRC connection request. + 12/16/2014 Ben Wojtowicz Added ol extension to message queues. + 12/24/2014 Ben Wojtowicz Using default data QoS and copying SRB1 + PDCP config to SRB2. + 02/15/2015 Ben Wojtowicz Moved to new message queue and using the + fixed user switch. + 07/25/2015 Ben Wojtowicz Using the new user QoS structure, moved DRBs + to RLC AM, and changed the default time + alignment timer to 10240 subframes. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t. + 02/13/2016 Ben Wojtowicz Added RRC connection reestablishment state + machine. + 07/03/2016 Przemek Bereski Added UE capability information and UE + capability enquiry support. + 07/29/2017 Ben Wojtowicz Add SR support, populate physical layer + dedicated configurations, remove QOS and + fixed UL scheduling. *******************************************************************************/ @@ -40,12 +65,18 @@ #include "LTE_fdd_enb_rrc.h" #include "LTE_fdd_enb_pdcp.h" -#include "LTE_fdd_enb_interface.h" +#include "LTE_fdd_enb_mac.h" +#include "LTE_fdd_enb_user_mgr.h" +#include "libtools_scoped_lock.h" /******************************************************************************* DEFINES *******************************************************************************/ +// SR configuration +#define I_SR_MIN 15 +#define I_SR_MAX 34 +#define N_1_P_PUCCH_SR 1 /******************************************************************************* TYPEDEFS @@ -56,8 +87,8 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_enb_rrc* LTE_fdd_enb_rrc::instance = NULL; -boost::mutex rrc_instance_mutex; +LTE_fdd_enb_rrc* LTE_fdd_enb_rrc::instance = NULL; +static pthread_mutex_t rrc_instance_mutex = PTHREAD_MUTEX_INITIALIZER; /******************************************************************************* CLASS IMPLEMENTATIONS @@ -68,7 +99,7 @@ boost::mutex rrc_instance_mutex; /*******************/ LTE_fdd_enb_rrc* LTE_fdd_enb_rrc::get_instance(void) { - boost::mutex::scoped_lock lock(rrc_instance_mutex); + libtools_scoped_lock lock(rrc_instance_mutex); if(NULL == instance) { @@ -79,7 +110,7 @@ LTE_fdd_enb_rrc* LTE_fdd_enb_rrc::get_instance(void) } void LTE_fdd_enb_rrc::cleanup(void) { - boost::mutex::scoped_lock lock(rrc_instance_mutex); + libtools_scoped_lock lock(rrc_instance_mutex); if(NULL != instance) { @@ -93,62 +124,65 @@ void LTE_fdd_enb_rrc::cleanup(void) /********************************/ LTE_fdd_enb_rrc::LTE_fdd_enb_rrc() { + sem_init(&start_sem, 0, 1); + sem_init(&sys_info_sem, 0, 1); started = false; } LTE_fdd_enb_rrc::~LTE_fdd_enb_rrc() { stop(); + sem_destroy(&sys_info_sem); + sem_destroy(&start_sem); } /********************/ /* Start/Stop */ /********************/ -void LTE_fdd_enb_rrc::start(void) +void LTE_fdd_enb_rrc::start(LTE_fdd_enb_msgq *from_pdcp, + LTE_fdd_enb_msgq *from_mme, + LTE_fdd_enb_msgq *to_pdcp, + LTE_fdd_enb_msgq *to_mme, + LTE_fdd_enb_interface *iface) { - boost::mutex::scoped_lock lock(start_mutex); - LTE_fdd_enb_msgq_cb pdcp_cb(<E_fdd_enb_msgq_cb_wrapper, this); - LTE_fdd_enb_msgq_cb mme_cb(<E_fdd_enb_msgq_cb_wrapper, this); + libtools_scoped_lock lock(start_sem); + LTE_fdd_enb_msgq_cb pdcp_cb(<E_fdd_enb_msgq_cb_wrapper, this); + LTE_fdd_enb_msgq_cb mme_cb(<E_fdd_enb_msgq_cb_wrapper, this); if(!started) { + interface = iface; started = true; - pdcp_comm_msgq = new LTE_fdd_enb_msgq("pdcp_rrc_mq", - pdcp_cb); - mme_comm_msgq = new LTE_fdd_enb_msgq("mme_rrc_mq", - mme_cb); - rrc_pdcp_mq = new boost::interprocess::message_queue(boost::interprocess::open_only, - "rrc_pdcp_mq"); - rrc_mme_mq = new boost::interprocess::message_queue(boost::interprocess::open_only, - "rrc_mme_mq"); + i_sr = I_SR_MIN; + msgq_from_pdcp = from_pdcp; + msgq_from_mme = from_mme; + msgq_to_pdcp = to_pdcp; + msgq_to_mme = to_mme; + msgq_from_pdcp->attach_rx(pdcp_cb); + msgq_from_mme->attach_rx(mme_cb); } } void LTE_fdd_enb_rrc::stop(void) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_sem); if(started) { started = false; - delete pdcp_comm_msgq; - delete mme_comm_msgq; } } /***********************/ /* Communication */ /***********************/ -void LTE_fdd_enb_rrc::handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) +void LTE_fdd_enb_rrc::handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - - if(LTE_FDD_ENB_DEST_LAYER_RRC == msg->dest_layer || - LTE_FDD_ENB_DEST_LAYER_ANY == msg->dest_layer) + if(LTE_FDD_ENB_DEST_LAYER_RRC == msg.dest_layer || + LTE_FDD_ENB_DEST_LAYER_ANY == msg.dest_layer) { - switch(msg->type) + switch(msg.type) { case LTE_FDD_ENB_MESSAGE_TYPE_RRC_PDU_READY: - handle_pdu_ready(&msg->msg.rrc_pdu_ready); - delete msg; + handle_pdu_ready(&msg.msg.rrc_pdu_ready); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, @@ -156,27 +190,26 @@ void LTE_fdd_enb_rrc::handle_pdcp_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) __FILE__, __LINE__, "Received invalid PDCP message %s", - LTE_fdd_enb_message_type_text[msg->type]); - delete msg; + LTE_fdd_enb_message_type_text[msg.type]); break; } }else{ // Forward message to MME - rrc_mme_mq->send(&msg, sizeof(msg), 0); + msgq_to_mme->send(msg); } } -void LTE_fdd_enb_rrc::handle_mme_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) +void LTE_fdd_enb_rrc::handle_mme_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - - if(LTE_FDD_ENB_DEST_LAYER_RRC == msg->dest_layer || - LTE_FDD_ENB_DEST_LAYER_ANY == msg->dest_layer) + if(LTE_FDD_ENB_DEST_LAYER_RRC == msg.dest_layer || + LTE_FDD_ENB_DEST_LAYER_ANY == msg.dest_layer) { - switch(msg->type) + switch(msg.type) { case LTE_FDD_ENB_MESSAGE_TYPE_RRC_NAS_MSG_READY: - handle_nas_msg(&msg->msg.rrc_nas_msg_ready); - delete msg; + handle_nas_msg(&msg.msg.rrc_nas_msg_ready); + break; + case LTE_FDD_ENB_MESSAGE_TYPE_RRC_CMD_READY: + handle_cmd(&msg.msg.rrc_cmd_ready); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, @@ -184,13 +217,12 @@ void LTE_fdd_enb_rrc::handle_mme_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) __FILE__, __LINE__, "Received invalid MME message %s", - LTE_fdd_enb_message_type_text[msg->type]); - delete msg; + LTE_fdd_enb_message_type_text[msg.type]); break; } }else{ // Forward message to PDCP - rrc_pdcp_mq->send(&msg, sizeof(msg), 0); + msgq_to_pdcp->send(msg); } } @@ -199,11 +231,10 @@ void LTE_fdd_enb_rrc::handle_mme_msg(LTE_FDD_ENB_MESSAGE_STRUCT *msg) /****************************/ void LTE_fdd_enb_rrc::update_sys_info(void) { - LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + libtools_scoped_lock lock(sys_info_sem); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); - sys_info_mutex.lock(); cnfg_db->get_sys_info(sys_info); - sys_info_mutex.unlock(); } /*******************************/ @@ -211,7 +242,6 @@ void LTE_fdd_enb_rrc::update_sys_info(void) /*******************************/ void LTE_fdd_enb_rrc::handle_pdu_ready(LTE_FDD_ENB_RRC_PDU_READY_MSG_STRUCT *pdu_ready) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); LIBLTE_BIT_MSG_STRUCT *pdu; if(LTE_FDD_ENB_ERROR_NONE == pdu_ready->rb->get_next_rrc_pdu(&pdu)) @@ -263,7 +293,139 @@ void LTE_fdd_enb_rrc::handle_pdu_ready(LTE_FDD_ENB_RRC_PDU_READY_MSG_STRUCT *pdu /******************************/ void LTE_fdd_enb_rrc::handle_nas_msg(LTE_FDD_ENB_RRC_NAS_MSG_READY_MSG_STRUCT *nas_msg) { - // FIXME + LIBLTE_BYTE_MSG_STRUCT *msg; + + if(LTE_FDD_ENB_ERROR_NONE == nas_msg->rb->get_next_rrc_nas_msg(&msg)) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + msg, + "Received NAS message for RNTI=%u and RB=%s", + nas_msg->user->get_c_rnti(), + LTE_fdd_enb_rb_text[nas_msg->rb->get_rb_id()]); + + // Send the NAS message + send_dl_info_transfer(nas_msg->user, nas_msg->rb, msg); + + // Delete the NAS message + nas_msg->rb->delete_next_rrc_nas_msg(); + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + "Received NAS message with no message queued"); + } +} +void LTE_fdd_enb_rrc::handle_cmd(LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT *cmd) +{ + LIBLTE_BYTE_MSG_STRUCT *msg; + LTE_fdd_enb_rb *srb2 = NULL; + LTE_fdd_enb_rb *drb1 = NULL; + LTE_fdd_enb_rb *drb2 = NULL; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + "Received MME command %s for RNTI=%u and RB=%s", + LTE_fdd_enb_rrc_cmd_text[cmd->cmd], + cmd->user->get_c_rnti(), + LTE_fdd_enb_rb_text[cmd->rb->get_rb_id()]); + + switch(cmd->cmd) + { + case LTE_FDD_ENB_RRC_CMD_RELEASE: + send_rrc_con_release(cmd->user, cmd->rb); + break; + case LTE_FDD_ENB_RRC_CMD_SECURITY: + send_ue_capability_enquiry(cmd->user, cmd->rb); + send_security_mode_command(cmd->user, cmd->rb); + break; + case LTE_FDD_ENB_RRC_CMD_SETUP_DEF_DRB: + if(LTE_FDD_ENB_ERROR_NONE == cmd->user->setup_srb2(&srb2) && + LTE_FDD_ENB_ERROR_NONE == cmd->user->setup_drb(LTE_FDD_ENB_RB_DRB1, &drb1)) + { + // Configure SRB2 + srb2->set_rrc_procedure(cmd->rb->get_rrc_procedure()); + srb2->set_rrc_state(cmd->rb->get_rrc_state()); + srb2->set_mme_procedure(cmd->rb->get_mme_procedure()); + srb2->set_mme_state(cmd->rb->get_mme_state()); + srb2->set_pdcp_config(cmd->rb->get_pdcp_config()); + + // Configure DRB1 + drb1->set_eps_bearer_id(cmd->user->get_eps_bearer_id()); + drb1->set_drb_id(1); + drb1->set_lc_id(3); + drb1->set_log_chan_group(2); + + if(LTE_FDD_ENB_ERROR_NONE == cmd->rb->get_next_rrc_nas_msg(&msg)) + { + send_rrc_con_reconfig(cmd->user, cmd->rb, msg); + cmd->rb->delete_next_rrc_nas_msg(); + }else{ + send_rrc_con_reconfig(cmd->user, cmd->rb, NULL); + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + "Handle CMD can't setup default DRB"); + } + break; + case LTE_FDD_ENB_RRC_CMD_SETUP_DED_DRB: + if(LTE_FDD_ENB_ERROR_NONE == cmd->user->setup_srb2(&srb2) && + LTE_FDD_ENB_ERROR_NONE == cmd->user->setup_drb(LTE_FDD_ENB_RB_DRB1, &drb1) && + LTE_FDD_ENB_ERROR_NONE == cmd->user->setup_drb(LTE_FDD_ENB_RB_DRB2, &drb2)) + { + // Configure SRB2 + srb2->set_rrc_procedure(cmd->rb->get_rrc_procedure()); + srb2->set_rrc_state(cmd->rb->get_rrc_state()); + srb2->set_mme_procedure(cmd->rb->get_mme_procedure()); + srb2->set_mme_state(cmd->rb->get_mme_state()); + srb2->set_pdcp_config(cmd->rb->get_pdcp_config()); + + // Configure DRB1 + drb1->set_eps_bearer_id(cmd->user->get_eps_bearer_id()); + drb1->set_drb_id(1); + drb1->set_lc_id(3); + drb1->set_log_chan_group(2); + + // Configure DRB2 + drb2->set_eps_bearer_id(cmd->user->get_eps_bearer_id()+1); + drb2->set_drb_id(2); + drb2->set_lc_id(4); + drb2->set_log_chan_group(3); + + if(LTE_FDD_ENB_ERROR_NONE == cmd->rb->get_next_rrc_nas_msg(&msg)) + { + send_rrc_con_reconfig(cmd->user, cmd->rb, msg); + cmd->rb->delete_next_rrc_nas_msg(); + }else{ + send_rrc_con_reconfig(cmd->user, cmd->rb, NULL); + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + "Handle CMD can't setup dedicated DRB"); + } + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + "Received MME command %s for RNTI=%u and RB=%s", + LTE_fdd_enb_rrc_cmd_text[cmd->cmd], + cmd->user->get_c_rnti(), + LTE_fdd_enb_rb_text[cmd->rb->get_rb_id()]); + break; + } } /************************/ @@ -273,27 +435,26 @@ void LTE_fdd_enb_rrc::ccch_sm(LIBLTE_BIT_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - LTE_fdd_enb_rb *srb1 = NULL; + LTE_fdd_enb_user *loc_user = user; + LTE_fdd_enb_rb *loc_rb = rb; + LTE_fdd_enb_rb *srb1 = NULL; // Parse the message - parse_ul_ccch_message(msg, user, rb); + parse_ul_ccch_message(msg, &loc_user, &loc_rb); - switch(rb->get_rrc_procedure()) + switch(loc_rb->get_rrc_procedure()) { case LTE_FDD_ENB_RRC_PROC_RRC_CON_REQ: - switch(rb->get_rrc_state()) + switch(loc_rb->get_rrc_state()) { case LTE_FDD_ENB_RRC_STATE_IDLE: - if(LTE_FDD_ENB_ERROR_NONE == user->setup_srb1(&srb1)) + loc_user->setup_srb1(&srb1); + if(NULL != srb1) { - rb->set_rrc_state(LTE_FDD_ENB_RRC_STATE_SRB1_SETUP); - send_rrc_con_setup(user, rb); - - // Setup uplink scheduling + loc_rb->set_rrc_state(LTE_FDD_ENB_RRC_STATE_SRB1_SETUP); + send_rrc_con_setup(loc_user, loc_rb); srb1->set_rrc_procedure(LTE_FDD_ENB_RRC_PROC_RRC_CON_REQ); srb1->set_rrc_state(LTE_FDD_ENB_RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE); - srb1->set_qos(LTE_FDD_ENB_QOS_SIGNALLING); }else{ interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, LTE_FDD_ENB_DEBUG_LEVEL_RRC, @@ -308,19 +469,42 @@ void LTE_fdd_enb_rrc::ccch_sm(LIBLTE_BIT_MSG_STRUCT *msg, __FILE__, __LINE__, "UL-CCCH-Message RRC CON REQ state machine invalid state %s", - LTE_fdd_enb_rrc_state_text[rb->get_rrc_state()]); + LTE_fdd_enb_rrc_state_text[loc_rb->get_rrc_state()]); break; } break; case LTE_FDD_ENB_RRC_PROC_RRC_CON_REEST_REQ: - // FIXME: Not handling RRC Connection Reestablishment Request + switch(loc_rb->get_rrc_state()) + { + case LTE_FDD_ENB_RRC_STATE_IDLE: + loc_user->setup_srb1(&srb1); + if(NULL != srb1) + { + loc_rb->set_rrc_state(LTE_FDD_ENB_RRC_STATE_SRB1_SETUP); + send_rrc_con_reest(loc_user, loc_rb); + srb1->set_rrc_procedure(LTE_FDD_ENB_RRC_PROC_RRC_CON_REEST_REQ); + srb1->set_rrc_state(LTE_FDD_ENB_RRC_STATE_WAIT_FOR_CON_REEST_COMPLETE); + }else{ + send_rrc_con_reest_reject(loc_user, loc_rb); + } + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + "UL-CCCH-Message RRC CON REEST REQ state machine invalid state %s", + LTE_fdd_enb_rrc_state_text[loc_rb->get_rrc_state()]); + break; + } + break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, LTE_FDD_ENB_DEBUG_LEVEL_RRC, __FILE__, __LINE__, "CCCH state machine invalid procedure %s", - LTE_fdd_enb_rrc_proc_text[rb->get_rrc_procedure()]); + LTE_fdd_enb_rrc_proc_text[loc_rb->get_rrc_procedure()]); break; } } @@ -328,14 +512,15 @@ void LTE_fdd_enb_rrc::dcch_sm(LIBLTE_BIT_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - switch(rb->get_rrc_procedure()) { + case LTE_FDD_ENB_RRC_PROC_RRC_CON_REEST_REQ: case LTE_FDD_ENB_RRC_PROC_RRC_CON_REQ: switch(rb->get_rrc_state()) { case LTE_FDD_ENB_RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE: + case LTE_FDD_ENB_RRC_STATE_WAIT_FOR_CON_REEST_COMPLETE: + case LTE_FDD_ENB_RRC_STATE_RRC_CONNECTED: // Parse the message parse_ul_dcch_message(msg, user, rb); break; @@ -363,37 +548,74 @@ void LTE_fdd_enb_rrc::dcch_sm(LIBLTE_BIT_MSG_STRUCT *msg, /*************************/ /* Message Parsers */ /*************************/ -void LTE_fdd_enb_rrc::parse_ul_ccch_message(LIBLTE_BIT_MSG_STRUCT *msg, - LTE_fdd_enb_user *user, - LTE_fdd_enb_rb *rb) +void LTE_fdd_enb_rrc::parse_ul_ccch_message(LIBLTE_BIT_MSG_STRUCT *msg, + LTE_fdd_enb_user **user, + LTE_fdd_enb_rb **rb) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + LTE_fdd_enb_user *act_user = NULL; + LTE_fdd_enb_rb *tmp_rb; // Parse the message liblte_rrc_unpack_ul_ccch_msg(msg, - &rb->ul_ccch_msg); + &(*rb)->ul_ccch_msg); interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_RRC, __FILE__, __LINE__, "Received %s for RNTI=%u, RB=%s", - liblte_rrc_ul_ccch_msg_type_text[rb->ul_ccch_msg.msg_type], - user->get_c_rnti(), - LTE_fdd_enb_rb_text[rb->get_rb_id()]); + liblte_rrc_ul_ccch_msg_type_text[(*rb)->ul_ccch_msg.msg_type], + (*user)->get_c_rnti(), + LTE_fdd_enb_rb_text[(*rb)->get_rb_id()]); - switch(rb->ul_ccch_msg.msg_type) + switch((*rb)->ul_ccch_msg.msg_type) { case LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ: - rb->set_rrc_procedure(LTE_FDD_ENB_RRC_PROC_RRC_CON_REQ); + if(LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI == (*rb)->ul_ccch_msg.msg.rrc_con_req.ue_id_type) + { + if(LTE_FDD_ENB_ERROR_NONE == user_mgr->find_user(&(*rb)->ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi, &act_user)) + { + if(act_user != (*user)) + { + act_user->copy_rbs((*user)); + (*user)->clear_rbs(); + user_mgr->transfer_c_rnti(*user, act_user); + *user = act_user; + } + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + "IMSI=%s is associated with RNTI=%u, RB=%s", + (*user)->get_imsi_str().c_str(), + (*user)->get_c_rnti(), + LTE_fdd_enb_rb_text[(*rb)->get_rb_id()]); + } + } + (*rb)->set_rrc_procedure(LTE_FDD_ENB_RRC_PROC_RRC_CON_REQ); break; case LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REEST_REQ: - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, - LTE_FDD_ENB_DEBUG_LEVEL_RRC, - __FILE__, - __LINE__, - "Not handling UL-CCCH-Message with msg_type=%s", - liblte_rrc_ul_ccch_msg_type_text[rb->ul_ccch_msg.msg_type]); + if(LTE_FDD_ENB_ERROR_NONE == user_mgr->find_user((*rb)->ul_ccch_msg.msg.rrc_con_reest_req.ue_id.c_rnti, &act_user)) + { + if(act_user != (*user)) + { + act_user->copy_rbs((*user)); + (*user)->clear_rbs(); + user_mgr->transfer_c_rnti(*user, act_user); + *user = act_user; + } + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + "IMSI=%s is associated with RNTI=%u, RB=%s", + (*user)->get_imsi_str().c_str(), + (*user)->get_c_rnti(), + LTE_fdd_enb_rb_text[(*rb)->get_rb_id()]); + } + (*rb)->set_rrc_procedure(LTE_FDD_ENB_RRC_PROC_RRC_CON_REEST_REQ); + (*rb)->set_rrc_state(LTE_FDD_ENB_RRC_STATE_IDLE); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, @@ -402,7 +624,7 @@ void LTE_fdd_enb_rrc::parse_ul_ccch_message(LIBLTE_BIT_MSG_STRUCT *msg, __LINE__, msg, "UL-CCCH-Message received with invalid msg_type=%s", - liblte_rrc_ul_ccch_msg_type_text[rb->ul_ccch_msg.msg_type]); + liblte_rrc_ul_ccch_msg_type_text[(*rb)->ul_ccch_msg.msg_type]); break; } } @@ -410,8 +632,8 @@ void LTE_fdd_enb_rrc::parse_ul_dcch_message(LIBLTE_BIT_MSG_STRUCT *msg, LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - LTE_FDD_ENB_MME_NAS_MSG_READY_MSG_STRUCT nas_msg_ready; + LTE_FDD_ENB_MME_NAS_MSG_READY_MSG_STRUCT nas_msg_ready; + LTE_FDD_ENB_MME_RRC_CMD_RESP_MSG_STRUCT cmd_resp; // Parse the message liblte_rrc_unpack_ul_dcch_msg(msg, @@ -428,6 +650,9 @@ void LTE_fdd_enb_rrc::parse_ul_dcch_message(LIBLTE_BIT_MSG_STRUCT *msg, switch(rb->ul_dcch_msg.msg_type) { + case LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_REEST_COMPLETE: + rb->set_rrc_state(LTE_FDD_ENB_RRC_STATE_RRC_CONNECTED); + break; case LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_SETUP_COMPLETE: rb->set_rrc_state(LTE_FDD_ENB_RRC_STATE_RRC_CONNECTED); @@ -437,11 +662,54 @@ void LTE_fdd_enb_rrc::parse_ul_dcch_message(LIBLTE_BIT_MSG_STRUCT *msg, // Signal MME nas_msg_ready.user = user; nas_msg_ready.rb = rb; - LTE_fdd_enb_msgq::send(rrc_mme_mq, - LTE_FDD_ENB_MESSAGE_TYPE_MME_NAS_MSG_READY, - LTE_FDD_ENB_DEST_LAYER_MME, - (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, - sizeof(LTE_FDD_ENB_MME_NAS_MSG_READY_MSG_STRUCT)); + msgq_to_mme->send(LTE_FDD_ENB_MESSAGE_TYPE_MME_NAS_MSG_READY, + LTE_FDD_ENB_DEST_LAYER_MME, + (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, + sizeof(LTE_FDD_ENB_MME_NAS_MSG_READY_MSG_STRUCT)); + break; + case LIBLTE_RRC_UL_DCCH_MSG_TYPE_UL_INFO_TRANSFER: + if(LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_NAS == rb->ul_dcch_msg.msg.ul_info_transfer.dedicated_info_type) + { + // Queue the NAS message for MME + rb->queue_mme_nas_msg(&rb->ul_dcch_msg.msg.ul_info_transfer.dedicated_info); + + // Signal MME + nas_msg_ready.user = user; + nas_msg_ready.rb = rb; + msgq_to_mme->send(LTE_FDD_ENB_MESSAGE_TYPE_MME_NAS_MSG_READY, + LTE_FDD_ENB_DEST_LAYER_MME, + (LTE_FDD_ENB_MESSAGE_UNION *)&nas_msg_ready, + sizeof(LTE_FDD_ENB_MME_NAS_MSG_READY_MSG_STRUCT)); + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + msg, + "UL-DCCH-Message UL Information Transfer received with invalid dedicated info %s", + liblte_rrc_ul_information_transfer_type_text[rb->ul_dcch_msg.msg.ul_info_transfer.dedicated_info_type]); + } + break; + case LIBLTE_RRC_UL_DCCH_MSG_TYPE_SECURITY_MODE_COMPLETE: + // Signal MME + cmd_resp.user = user; + cmd_resp.rb = rb; + cmd_resp.cmd_resp = LTE_FDD_ENB_MME_RRC_CMD_RESP_SECURITY; + msgq_to_mme->send(LTE_FDD_ENB_MESSAGE_TYPE_MME_RRC_CMD_RESP, + LTE_FDD_ENB_DEST_LAYER_MME, + (LTE_FDD_ENB_MESSAGE_UNION *)&cmd_resp, + sizeof(LTE_FDD_ENB_MME_RRC_CMD_RESP_MSG_STRUCT)); + break; + case LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE: + break; + case LIBLTE_RRC_UL_DCCH_MSG_TYPE_UE_CAPABILITY_INFO: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + msg, + "UE Capability Information for RNTI=%u", + user->get_c_rnti()); break; default: interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, @@ -458,18 +726,299 @@ void LTE_fdd_enb_rrc::parse_ul_dcch_message(LIBLTE_BIT_MSG_STRUCT *msg, /*************************/ /* Message Senders */ /*************************/ +void LTE_fdd_enb_rrc::send_dl_info_transfer(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT pdcp_sdu_ready; + LIBLTE_BIT_MSG_STRUCT pdcp_sdu; + + rb->dl_dcch_msg.msg_type = LIBLTE_RRC_DL_DCCH_MSG_TYPE_DL_INFO_TRANSFER; + rb->dl_dcch_msg.msg.dl_info_transfer.rrc_transaction_id = rb->get_rrc_transaction_id(); + rb->dl_dcch_msg.msg.dl_info_transfer.dedicated_info_type = LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_NAS; + memcpy(&rb->dl_dcch_msg.msg.dl_info_transfer.dedicated_info, msg, sizeof(LIBLTE_BYTE_MSG_STRUCT)); + liblte_rrc_pack_dl_dcch_msg(&rb->dl_dcch_msg, &pdcp_sdu); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + &pdcp_sdu, + "Sending DL Info Transfer for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the PDU for PDCP + rb->queue_pdcp_sdu(&pdcp_sdu); + + // Signal PDCP + pdcp_sdu_ready.user = user; + pdcp_sdu_ready.rb = rb; + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_sdu_ready, + sizeof(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_rrc::send_rrc_con_reconfig(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LTE_fdd_enb_rb *drb1 = NULL; + LTE_fdd_enb_rb *drb2 = NULL; + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + LTE_fdd_enb_mac *mac = LTE_fdd_enb_mac::get_instance(); + LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT pdcp_sdu_ready; + LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *rrc_con_recnfg; + LIBLTE_BIT_MSG_STRUCT pdcp_sdu; + uint32 idx; + + user->get_drb(LTE_FDD_ENB_RB_DRB1, &drb1); + user->get_drb(LTE_FDD_ENB_RB_DRB2, &drb2); + + rb->dl_dcch_msg.msg_type = LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RECONFIG; + rrc_con_recnfg = (LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *)&rb->dl_dcch_msg.msg.rrc_con_reconfig; + rrc_con_recnfg->meas_cnfg_present = false; + rrc_con_recnfg->mob_ctrl_info_present = false; + if(NULL == msg) + { + rrc_con_recnfg->N_ded_info_nas = 0; + }else{ + rrc_con_recnfg->N_ded_info_nas = 1; + memcpy(&rrc_con_recnfg->ded_info_nas_list[0], msg, sizeof(LIBLTE_BYTE_MSG_STRUCT)); + } + rrc_con_recnfg->rr_cnfg_ded_present = true; + rrc_con_recnfg->rr_cnfg_ded.srb_to_add_mod_list_size = 1; + rrc_con_recnfg->rr_cnfg_ded.srb_to_add_mod_list[0].srb_id = 2; + rrc_con_recnfg->rr_cnfg_ded.srb_to_add_mod_list[0].rlc_cnfg_present = true; + rrc_con_recnfg->rr_cnfg_ded.srb_to_add_mod_list[0].rlc_default_cnfg_present = true; + rrc_con_recnfg->rr_cnfg_ded.srb_to_add_mod_list[0].lc_cnfg_present = true; + rrc_con_recnfg->rr_cnfg_ded.srb_to_add_mod_list[0].lc_default_cnfg_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list_size = 0; + if(NULL != drb1) + { + idx = rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list_size; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].eps_bearer_id_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].eps_bearer_id = drb1->get_eps_bearer_id(); + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].drb_id = drb1->get_drb_id(); + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.discard_timer_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.discard_timer = LIBLTE_RRC_DISCARD_TIMER_INFINITY; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.rlc_am_status_report_required_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.rlc_am_status_report_required = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.rlc_um_pdcp_sn_size_present = false; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.hdr_compression_rohc = false; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS45; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_INFINITY; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_INFINITY; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS35; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS0; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_id_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_id = drb1->get_lc_id(); + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params.priority = 13; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params.prioritized_bit_rate = LIBLTE_RRC_PRIORITIZED_BIT_RATE_INFINITY; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params.bucket_size_duration = LIBLTE_RRC_BUCKET_SIZE_DURATION_MS100; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params.log_chan_group_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params.log_chan_group = drb1->get_log_chan_group(); + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.log_chan_sr_mask_present = false; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list_size++; + } + if(NULL != drb2) + { + idx = rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list_size; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].eps_bearer_id_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].eps_bearer_id = drb2->get_eps_bearer_id(); + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].drb_id = drb2->get_drb_id(); + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.discard_timer_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.discard_timer = LIBLTE_RRC_DISCARD_TIMER_INFINITY; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.rlc_am_status_report_required_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.rlc_am_status_report_required = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.rlc_um_pdcp_sn_size_present = false; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].pdcp_cnfg.hdr_compression_rohc = false; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS45; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_INFINITY; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_INFINITY; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS35; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].rlc_cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS0; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_id_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_id = drb2->get_lc_id(); + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params.priority = 13; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params.prioritized_bit_rate = LIBLTE_RRC_PRIORITIZED_BIT_RATE_INFINITY; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params.bucket_size_duration = LIBLTE_RRC_BUCKET_SIZE_DURATION_MS100; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params.log_chan_group_present = true; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.ul_specific_params.log_chan_group = drb2->get_log_chan_group(); + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list[idx].lc_cnfg.log_chan_sr_mask_present = false; + rrc_con_recnfg->rr_cnfg_ded.drb_to_add_mod_list_size++; + } + rrc_con_recnfg->rr_cnfg_ded.drb_to_release_list_size = 0; + rrc_con_recnfg->rr_cnfg_ded.mac_main_cnfg_present = false; + rrc_con_recnfg->rr_cnfg_ded.sps_cnfg_present = false; + rrc_con_recnfg->rr_cnfg_ded.phy_cnfg_ded_present = true; + cnfg_db->populate_rrc_phy_config_dedicated(&rrc_con_recnfg->rr_cnfg_ded.phy_cnfg_ded, 0, 0, i_sr, N_1_P_PUCCH_SR); + mac->add_periodic_sr_pucch(user->get_c_rnti(), i_sr, N_1_P_PUCCH_SR); + increment_i_sr(); + rrc_con_recnfg->rr_cnfg_ded.rlf_timers_and_constants_present = false; + rrc_con_recnfg->sec_cnfg_ho_present = false; + liblte_rrc_pack_dl_dcch_msg(&rb->dl_dcch_msg, &pdcp_sdu); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + &pdcp_sdu, + "Sending RRC Connection Reconfiguration for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the PDU for PDCP + rb->queue_pdcp_sdu(&pdcp_sdu); + + // Signal PDCP + pdcp_sdu_ready.user = user; + pdcp_sdu_ready.rb = rb; + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_sdu_ready, + sizeof(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_rrc::send_rrc_con_reest(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + LTE_fdd_enb_mac *mac = LTE_fdd_enb_mac::get_instance(); + LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT pdcp_sdu_ready; + LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *rrc_con_reest; + LIBLTE_BIT_MSG_STRUCT pdcp_sdu; + + rb->dl_ccch_msg.msg_type = LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST; + rrc_con_reest = (LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *)&rb->dl_ccch_msg.msg.rrc_con_reest; + rrc_con_reest->rrc_transaction_id = rb->get_rrc_transaction_id(); + rrc_con_reest->rr_cnfg.srb_to_add_mod_list_size = 1; + rrc_con_reest->rr_cnfg.srb_to_add_mod_list[0].srb_id = 1; + rrc_con_reest->rr_cnfg.srb_to_add_mod_list[0].rlc_cnfg_present = true; + rrc_con_reest->rr_cnfg.srb_to_add_mod_list[0].rlc_default_cnfg_present = true; + rrc_con_reest->rr_cnfg.srb_to_add_mod_list[0].lc_cnfg_present = true; + rrc_con_reest->rr_cnfg.srb_to_add_mod_list[0].lc_default_cnfg_present = true; + rrc_con_reest->rr_cnfg.drb_to_add_mod_list_size = 0; + rrc_con_reest->rr_cnfg.drb_to_release_list_size = 0; + rrc_con_reest->rr_cnfg.mac_main_cnfg_present = true; + rrc_con_reest->rr_cnfg.mac_main_cnfg.default_value = false; + rrc_con_reest->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg_present = true; + rrc_con_reest->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.max_harq_tx_present = true; + rrc_con_reest->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.max_harq_tx = LIBLTE_RRC_MAX_HARQ_TX_N1; + rrc_con_reest->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.periodic_bsr_timer_present = false; + rrc_con_reest->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.retx_bsr_timer = LIBLTE_RRC_RETRANSMISSION_BSR_TIMER_SF1280; + rrc_con_reest->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.tti_bundling = false; + rrc_con_reest->rr_cnfg.mac_main_cnfg.explicit_value.drx_cnfg_present = false; + rrc_con_reest->rr_cnfg.mac_main_cnfg.explicit_value.phr_cnfg_present = false; + rrc_con_reest->rr_cnfg.mac_main_cnfg.explicit_value.time_alignment_timer = LIBLTE_RRC_TIME_ALIGNMENT_TIMER_SF10240; + rrc_con_reest->rr_cnfg.sps_cnfg_present = false; + rrc_con_reest->rr_cnfg.phy_cnfg_ded_present = true; + cnfg_db->populate_rrc_phy_config_dedicated(&rrc_con_reest->rr_cnfg.phy_cnfg_ded, 0, 0, i_sr, N_1_P_PUCCH_SR); + mac->add_periodic_sr_pucch(user->get_c_rnti(), i_sr, N_1_P_PUCCH_SR); + increment_i_sr(); + rrc_con_reest->rr_cnfg.rlf_timers_and_constants_present = false; + liblte_rrc_pack_dl_ccch_msg(&rb->dl_ccch_msg, &pdcp_sdu); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + "Sending RRC Connection Reestablishment for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the PDU for PDCP + rb->queue_pdcp_sdu(&pdcp_sdu); + + // Signal PDCP + pdcp_sdu_ready.user = user; + pdcp_sdu_ready.rb = rb; + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_sdu_ready, + sizeof(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_rrc::send_rrc_con_reest_reject(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT pdcp_sdu_ready; + LIBLTE_BIT_MSG_STRUCT pdcp_sdu; + + rb->dl_ccch_msg.msg_type = LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST_REJ; + liblte_rrc_pack_dl_ccch_msg(&rb->dl_ccch_msg, &pdcp_sdu); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + &pdcp_sdu, + "Sending RRC Connection Reestablishment Reject for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the PDU for PDCP + rb->queue_pdcp_sdu(&pdcp_sdu); + + // Signal PDCP + pdcp_sdu_ready.user = user; + pdcp_sdu_ready.rb = rb; + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_sdu_ready, + sizeof(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_rrc::send_rrc_con_release(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_fdd_enb_mac *mac = LTE_fdd_enb_mac::get_instance(); + LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT pdcp_sdu_ready; + LIBLTE_BIT_MSG_STRUCT pdcp_sdu; + + rb->dl_dcch_msg.msg_type = LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RELEASE; + rb->dl_dcch_msg.msg.rrc_con_release.rrc_transaction_id = rb->get_rrc_transaction_id(); + rb->dl_dcch_msg.msg.rrc_con_release.release_cause = LIBLTE_RRC_RELEASE_CAUSE_OTHER; + liblte_rrc_pack_dl_dcch_msg(&rb->dl_dcch_msg, &pdcp_sdu); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + &pdcp_sdu, + "Sending RRC Connection Release for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + mac->remove_periodic_sr_pucch(user->get_c_rnti()); + + // Queue the PDU for PDCP + rb->queue_pdcp_sdu(&pdcp_sdu); + + // Signal PDCP + pdcp_sdu_ready.user = user; + pdcp_sdu_ready.rb = rb; + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_sdu_ready, + sizeof(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT)); +} void LTE_fdd_enb_rrc::send_rrc_con_setup(LTE_fdd_enb_user *user, LTE_fdd_enb_rb *rb) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + LTE_fdd_enb_cnfg_db *cnfg_db = LTE_fdd_enb_cnfg_db::get_instance(); + LTE_fdd_enb_mac *mac = LTE_fdd_enb_mac::get_instance(); LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT pdcp_sdu_ready; LIBLTE_RRC_CONNECTION_SETUP_STRUCT *rrc_con_setup; - LIBLTE_BIT_MSG_STRUCT msg; + LIBLTE_BIT_MSG_STRUCT pdcp_sdu; - // RRC Connection Setup rb->dl_ccch_msg.msg_type = LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP; rrc_con_setup = (LIBLTE_RRC_CONNECTION_SETUP_STRUCT *)&rb->dl_ccch_msg.msg.rrc_con_setup; - rrc_con_setup->transaction_id = 0; + rrc_con_setup->rrc_transaction_id = rb->get_rrc_transaction_id(); rrc_con_setup->rr_cnfg.srb_to_add_mod_list_size = 1; rrc_con_setup->rr_cnfg.srb_to_add_mod_list[0].srb_id = 1; rrc_con_setup->rr_cnfg.srb_to_add_mod_list[0].rlc_cnfg_present = true; @@ -488,29 +1037,113 @@ void LTE_fdd_enb_rrc::send_rrc_con_setup(LTE_fdd_enb_user *user, rrc_con_setup->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.tti_bundling = false; rrc_con_setup->rr_cnfg.mac_main_cnfg.explicit_value.drx_cnfg_present = false; rrc_con_setup->rr_cnfg.mac_main_cnfg.explicit_value.phr_cnfg_present = false; - rrc_con_setup->rr_cnfg.mac_main_cnfg.explicit_value.time_alignment_timer = LIBLTE_RRC_TIME_ALIGNMENT_TIMER_SF500; + rrc_con_setup->rr_cnfg.mac_main_cnfg.explicit_value.time_alignment_timer = LIBLTE_RRC_TIME_ALIGNMENT_TIMER_SF10240; rrc_con_setup->rr_cnfg.sps_cnfg_present = false; - rrc_con_setup->rr_cnfg.phy_cnfg_ded_present = false; - rrc_con_setup->rr_cnfg.rlf_timers_and_constants_present = false; - liblte_rrc_pack_dl_ccch_msg(&rb->dl_ccch_msg, &msg); + rrc_con_setup->rr_cnfg.phy_cnfg_ded_present = true; + cnfg_db->populate_rrc_phy_config_dedicated(&rrc_con_setup->rr_cnfg.phy_cnfg_ded, 0, 0, i_sr, N_1_P_PUCCH_SR); + mac->add_periodic_sr_pucch(user->get_c_rnti(), i_sr, N_1_P_PUCCH_SR); + increment_i_sr(); + rrc_con_setup->rr_cnfg.rlf_timers_and_constants_present = false; + liblte_rrc_pack_dl_ccch_msg(&rb->dl_ccch_msg, &pdcp_sdu); interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_RRC, __FILE__, __LINE__, - &msg, + &pdcp_sdu, "Sending RRC Connection Setup for RNTI=%u, RB=%s", user->get_c_rnti(), LTE_fdd_enb_rb_text[rb->get_rb_id()]); // Queue the PDU for PDCP - rb->queue_pdcp_sdu(&msg); + rb->queue_pdcp_sdu(&pdcp_sdu); // Signal PDCP pdcp_sdu_ready.user = user; pdcp_sdu_ready.rb = rb; - LTE_fdd_enb_msgq::send(rrc_pdcp_mq, - LTE_FDD_ENB_MESSAGE_TYPE_PDCP_SDU_READY, - LTE_FDD_ENB_DEST_LAYER_PDCP, - (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_sdu_ready, - sizeof(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT)); + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_sdu_ready, + sizeof(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_rrc::send_security_mode_command(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT pdcp_sdu_ready; + LIBLTE_BIT_MSG_STRUCT pdcp_sdu; + + rb->dl_dcch_msg.msg_type = LIBLTE_RRC_DL_DCCH_MSG_TYPE_SECURITY_MODE_COMMAND; + rb->dl_dcch_msg.msg.security_mode_cmd.rrc_transaction_id = rb->get_rrc_transaction_id(); + rb->dl_dcch_msg.msg.security_mode_cmd.sec_algs.cipher_alg = LIBLTE_RRC_CIPHERING_ALGORITHM_EEA0; + rb->dl_dcch_msg.msg.security_mode_cmd.sec_algs.int_alg = LIBLTE_RRC_INTEGRITY_PROT_ALGORITHM_EIA2; + liblte_rrc_pack_dl_dcch_msg(&rb->dl_dcch_msg, &pdcp_sdu); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + &pdcp_sdu, + "Sending Security Mode Command for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Configure PDCP for security + rb->set_pdcp_config(LTE_FDD_ENB_PDCP_CONFIG_SECURITY); + + // Queue the PDU for PDCP + rb->queue_pdcp_sdu(&pdcp_sdu); + + // Signal PDCP + pdcp_sdu_ready.user = user; + pdcp_sdu_ready.rb = rb; + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_sdu_ready, + sizeof(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT)); +} +void LTE_fdd_enb_rrc::send_ue_capability_enquiry(LTE_fdd_enb_user *user, + LTE_fdd_enb_rb *rb) +{ + LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT pdcp_sdu_ready; + LIBLTE_BIT_MSG_STRUCT pdcp_sdu; + LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT *ue_cap_enquiry = &rb->dl_dcch_msg.msg.ue_cap_enquiry; + + rb->dl_dcch_msg.msg_type = LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_CAPABILITY_ENQUIRY; + ue_cap_enquiry->rrc_transaction_id = (rb->get_rrc_transaction_id() + 1) % 4; + ue_cap_enquiry->rat_type_list_size = 0; + ue_cap_enquiry->rat_type_list[ue_cap_enquiry->rat_type_list_size++] = LIBLTE_RRC_RAT_TYPE_EUTRA; + ue_cap_enquiry->rat_type_list[ue_cap_enquiry->rat_type_list_size++] = LIBLTE_RRC_RAT_TYPE_UTRA; + ue_cap_enquiry->rat_type_list[ue_cap_enquiry->rat_type_list_size++] = LIBLTE_RRC_RAT_TYPE_GERAN_CS; + ue_cap_enquiry->rat_type_list[ue_cap_enquiry->rat_type_list_size++] = LIBLTE_RRC_RAT_TYPE_GERAN_PS; + ue_cap_enquiry->rat_type_list[ue_cap_enquiry->rat_type_list_size++] = LIBLTE_RRC_RAT_TYPE_CDMA2000_1XRTT; + liblte_rrc_pack_dl_dcch_msg(&rb->dl_dcch_msg, &pdcp_sdu); + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_RRC, + __FILE__, + __LINE__, + &pdcp_sdu, + "Sending UE Capability Enquiry for RNTI=%u, RB=%s", + user->get_c_rnti(), + LTE_fdd_enb_rb_text[rb->get_rb_id()]); + + // Queue the PDU for PDCP + rb->queue_pdcp_sdu(&pdcp_sdu); + + // Signal PDCP + pdcp_sdu_ready.user = user; + pdcp_sdu_ready.rb = rb; + msgq_to_pdcp->send(LTE_FDD_ENB_MESSAGE_TYPE_PDCP_SDU_READY, + LTE_FDD_ENB_DEST_LAYER_PDCP, + (LTE_FDD_ENB_MESSAGE_UNION *)&pdcp_sdu_ready, + sizeof(LTE_FDD_ENB_PDCP_SDU_READY_MSG_STRUCT)); +} + +/*****************/ +/* Helpers */ +/*****************/ +void LTE_fdd_enb_rrc::increment_i_sr(void) +{ + i_sr++; + if(i_sr > I_SR_MAX) + { + i_sr = I_SR_MIN; + } } diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_timer.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_timer.cc old mode 100644 new mode 100755 index 8c0063e..fdd72c6 --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_timer.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_timer.cc @@ -28,6 +28,7 @@ 05/04/2014 Ben Wojtowicz Created file 06/15/2014 Ben Wojtowicz Added millisecond resolution and seperated the callback calling functionality. + 11/29/2014 Ben Wojtowicz Added timer reset support. *******************************************************************************/ @@ -91,6 +92,10 @@ LTE_fdd_enb_timer::~LTE_fdd_enb_timer() /****************************/ /* External Interface */ /****************************/ +void LTE_fdd_enb_timer::reset(void) +{ + current_m_seconds = 0; +} void LTE_fdd_enb_timer::increment(void) { current_m_seconds++; diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_timer_mgr.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_timer_mgr.cc old mode 100644 new mode 100755 index ca57176..48aa8b5 --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_timer_mgr.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_timer_mgr.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_timer_mgr.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2014 Ben Wojtowicz + Copyright 2014-2015 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +27,12 @@ ---------- ------------- -------------------------------------------- 05/04/2014 Ben Wojtowicz Created file 06/15/2014 Ben Wojtowicz Added millisecond resolution. + 08/03/2014 Ben Wojtowicz Added an invalid timer id. + 11/29/2014 Ben Wojtowicz Added timer reset support. + 12/16/2014 Ben Wojtowicz Passing timer tick to user_mgr. + 02/15/2015 Ben Wojtowicz Moved to new message queue for timer ticks. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t. *******************************************************************************/ @@ -35,6 +41,8 @@ *******************************************************************************/ #include "LTE_fdd_enb_timer_mgr.h" +#include "LTE_fdd_enb_user_mgr.h" +#include "libtools_scoped_lock.h" #include /******************************************************************************* @@ -52,7 +60,7 @@ *******************************************************************************/ LTE_fdd_enb_timer_mgr* LTE_fdd_enb_timer_mgr::instance = NULL; -boost::mutex timer_mgr_instance_mutex; +static pthread_mutex_t timer_mgr_instance_mutex = PTHREAD_MUTEX_INITIALIZER; /******************************************************************************* CLASS IMPLEMENTATIONS @@ -63,7 +71,7 @@ boost::mutex timer_mgr_instance_mutex; /*******************/ LTE_fdd_enb_timer_mgr* LTE_fdd_enb_timer_mgr::get_instance(void) { - boost::mutex::scoped_lock lock(timer_mgr_instance_mutex); + libtools_scoped_lock lock(timer_mgr_instance_mutex); if(NULL == instance) { @@ -74,7 +82,7 @@ LTE_fdd_enb_timer_mgr* LTE_fdd_enb_timer_mgr::get_instance(void) } void LTE_fdd_enb_timer_mgr::cleanup(void) { - boost::mutex::scoped_lock lock(timer_mgr_instance_mutex); + libtools_scoped_lock lock(timer_mgr_instance_mutex); if(NULL != instance) { @@ -88,10 +96,51 @@ void LTE_fdd_enb_timer_mgr::cleanup(void) /********************************/ LTE_fdd_enb_timer_mgr::LTE_fdd_enb_timer_mgr() { - next_timer_id = 0; + sem_init(&start_sem, 0, 1); + sem_init(&timer_sem, 0, 1); + interface = NULL; + started = false; } LTE_fdd_enb_timer_mgr::~LTE_fdd_enb_timer_mgr() { + std::map::iterator iter; + + sem_wait(&timer_sem); + for(iter=timer_map.begin(); iter!=timer_map.end(); iter++) + { + delete (*iter).second; + } + sem_post(&timer_sem); + sem_destroy(&timer_sem); + sem_destroy(&start_sem); +} + +/********************/ +/* Start/Stop */ +/********************/ +void LTE_fdd_enb_timer_mgr::start(LTE_fdd_enb_msgq *from_mac, + LTE_fdd_enb_interface *iface) +{ + libtools_scoped_lock lock(start_sem); + LTE_fdd_enb_msgq_cb timer_cb(<E_fdd_enb_msgq_cb_wrapper, this); + + if(!started) + { + interface = iface; + started = true; + next_timer_id = 0; + msgq_from_mac = from_mac; + msgq_from_mac->attach_rx(timer_cb); + } +} +void LTE_fdd_enb_timer_mgr::stop(void) +{ + libtools_scoped_lock lock(start_sem); + + if(started) + { + started = false; + } } /****************************/ @@ -101,12 +150,13 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_timer_mgr::start_timer(uint32 LTE_fdd_enb_timer_cb cb, uint32 *timer_id) { - boost::mutex::scoped_lock lock(timer_mutex); + libtools_scoped_lock lock(timer_sem); std::map::iterator iter = timer_map.find(next_timer_id); LTE_fdd_enb_timer *new_timer = NULL; LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_BAD_ALLOC; - while(timer_map.end() != iter) + while(timer_map.end() != iter && + LTE_FDD_ENB_INVALID_TIMER_ID != next_timer_id) { next_timer_id++; iter = timer_map.find(next_timer_id); @@ -124,7 +174,7 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_timer_mgr::start_timer(uint32 } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_timer_mgr::stop_timer(uint32 timer_id) { - boost::mutex::scoped_lock lock(timer_mutex); + libtools_scoped_lock lock(timer_sem); std::map::iterator iter = timer_map.find(timer_id); LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_TIMER_NOT_FOUND; @@ -137,12 +187,59 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_timer_mgr::stop_timer(uint32 timer_id) return(err); } +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_timer_mgr::reset_timer(uint32 timer_id) +{ + libtools_scoped_lock lock(timer_sem); + std::map::iterator iter = timer_map.find(timer_id); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_TIMER_NOT_FOUND; + + if(timer_map.end() != iter) + { + (*iter).second->reset(); + err = LTE_FDD_ENB_ERROR_NONE; + } + + return(err); +} + +/***********************/ +/* Communication */ +/***********************/ +void LTE_fdd_enb_timer_mgr::handle_msg(LTE_FDD_ENB_MESSAGE_STRUCT &msg) +{ + if(LTE_FDD_ENB_DEST_LAYER_TIMER_MGR == msg.dest_layer || + LTE_FDD_ENB_DEST_LAYER_ANY == msg.dest_layer) + { + switch(msg.type) + { + case LTE_FDD_ENB_MESSAGE_TYPE_TIMER_TICK: + handle_tick(); + break; + default: + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_WARNING, + LTE_FDD_ENB_DEBUG_LEVEL_TIMER, + __FILE__, + __LINE__, + "Received invalid TIMER message %s", + LTE_fdd_enb_message_type_text[msg.type]); + break; + } + }else{ + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_WARNING, + LTE_FDD_ENB_DEBUG_LEVEL_TIMER, + __FILE__, + __LINE__, + "Received message for invalid layer (%s)", + LTE_fdd_enb_dest_layer_text[msg.dest_layer]); + } +} void LTE_fdd_enb_timer_mgr::handle_tick(void) { - std::map::iterator iter; - std::list expired_list; + LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance(); + std::map::iterator iter; + std::list expired_list; - timer_mutex.lock(); + sem_wait(&timer_sem); for(iter=timer_map.begin(); iter!=timer_map.end(); iter++) { (*iter).second->increment(); @@ -152,7 +249,7 @@ void LTE_fdd_enb_timer_mgr::handle_tick(void) expired_list.push_back((*iter).first); } } - timer_mutex.unlock(); + sem_post(&timer_sem); // Delete expired timers while(0 != expired_list.size()) diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_user.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_user.cc old mode 100644 new mode 100755 index 4459707..11cf92f --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_user.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_user.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_user.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -28,6 +28,28 @@ 11/10/2013 Ben Wojtowicz Created file 05/04/2014 Ben Wojtowicz Added radio bearer support. 06/15/2014 Ben Wojtowicz Added initialize routine. + 08/03/2014 Ben Wojtowicz Refactored user identities. + 09/03/2014 Ben Wojtowicz Added ciphering and integrity algorithm + storing. + 11/01/2014 Ben Wojtowicz Added more MME support. + 11/29/2014 Ben Wojtowicz Added DRB setup/teardown and C-RNTI release + timer support. + 12/16/2014 Ben Wojtowicz Changed the delayed delete functionality. + 02/15/2015 Ben Wojtowicz Added clear_rbs and fixed copy_rbs. + 07/25/2015 Ben Wojtowicz Moved the QoS structure from the RB class to + the user class. + 12/06/2015 Ben Wojtowicz Changed the deletion and C-RNTI release + procedures and changed the QoS parameters + for default data. + 02/13/2016 Ben Wojtowicz Added an inactivity timer. + 03/12/2016 Ben Wojtowicz Added H-ARQ support and properly cleaning + up inactivity timer. + 07/03/2016 Ben Wojtowicz Changed the DL bytes per subframe QoS + parameter for default data. + 08/14/2016 Ben Wojtowicz Changed the QoS DL bytes per subframe for + default data to ensure QPSK only for 5MHz. + 07/29/2017 Ben Wojtowicz Remove QOS support and fixed UL scheduling + and using the latest tools library. *******************************************************************************/ @@ -36,6 +58,13 @@ *******************************************************************************/ #include "LTE_fdd_enb_user.h" +#include "LTE_fdd_enb_user_mgr.h" +#include "LTE_fdd_enb_timer_mgr.h" +#include "LTE_fdd_enb_mac.h" +#include "LTE_fdd_enb_rrc.h" +#include "liblte_mme.h" +#include "libtools_scoped_lock.h" +#include "libtools_helpers.h" /******************************************************************************* DEFINES @@ -59,13 +88,32 @@ /********************************/ /* Constructor/Destructor */ /********************************/ -LTE_fdd_enb_user::LTE_fdd_enb_user(std::string _imsi) +LTE_fdd_enb_user::LTE_fdd_enb_user() { uint32 i; // Identity - imsi = _imsi; - c_rnti = LIBLTE_MAC_INVALID_RNTI; + id_set = false; + guti_set = false; + temp_id = 0; + c_rnti_set = false; + ip_addr_set = false; + + // Security + auth_vec_set = false; + + // Capabilities + for(i=0; i<8; i++) + { + eea_support[i] = false; + eia_support[i] = false; + uea_support[i] = false; + uia_support[i] = false; + gea_support[i] = false; + } + uea_set = false; + uia_set = false; + gea_set = false; // Radio Bearers srb0 = new LTE_fdd_enb_rb(LTE_FDD_ENB_RB_SRB0, this); @@ -75,10 +123,40 @@ LTE_fdd_enb_user::LTE_fdd_enb_user(std::string _imsi) { drb[i] = NULL; } + + // MME + emm_cause = LIBLTE_MME_EMM_CAUSE_IMSI_UNKNOWN_IN_HSS; + attach_type = 0; + pdn_type = 0; + eps_bearer_id = 0; + proc_transaction_id = 0; + eit_flag = false; + protocol_cnfg_opts.N_opts = 0; + + // MAC + sem_init(&harq_buffer_sem, 0, 1); + harq_buffer.clear(); + dl_ndi = false; + ul_ndi = false; + ul_buffer_size = 0; + + // Generic + N_del_ticks = 0; + inactivity_timer_id = LTE_FDD_ENB_INVALID_TIMER_ID; } LTE_fdd_enb_user::~LTE_fdd_enb_user() { - uint32 i; + LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + std::map::iterator iter; + uint32 i; + + // MAC + sem_wait(&harq_buffer_sem); + for(iter=harq_buffer.begin(); iter!=harq_buffer.end(); iter++) + { + delete (*iter).second; + } + sem_destroy(&harq_buffer_sem); // Radio Bearers for(i=0; i<8; i++) @@ -88,6 +166,11 @@ LTE_fdd_enb_user::~LTE_fdd_enb_user() delete srb2; delete srb1; delete srb0; + + if(LTE_FDD_ENB_INVALID_TIMER_ID != inactivity_timer_id) + { + timer_mgr->stop_timer(inactivity_timer_id); + } } /********************/ @@ -101,28 +184,213 @@ void LTE_fdd_enb_user::init(void) for(i=0; i<8; i++) { delete drb[i]; + drb[i] = NULL; } delete srb2; + srb2 = NULL; delete srb1; + srb1 = NULL; + srb0->set_mme_procedure(LTE_FDD_ENB_MME_PROC_IDLE); + srb0->set_mme_state(LTE_FDD_ENB_MME_STATE_IDLE); srb0->set_rrc_procedure(LTE_FDD_ENB_RRC_PROC_IDLE); srb0->set_rrc_state(LTE_FDD_ENB_RRC_STATE_IDLE); + + // MME + emm_cause = LIBLTE_MME_EMM_CAUSE_ROAMING_NOT_ALLOWED_IN_THIS_TRACKING_AREA; + attach_type = 0; + pdn_type = 0; + eps_bearer_id = 0; + proc_transaction_id = 0; + protocol_cnfg_opts.N_opts = 0; + + // MAC + dl_ndi = false; + ul_ndi = false; + + // Identity + c_rnti = 0xFFFF; + c_rnti_set = false; } /******************/ /* Identity */ /******************/ -std::string LTE_fdd_enb_user::get_imsi(void) +void LTE_fdd_enb_user::set_id(LTE_FDD_ENB_USER_ID_STRUCT *identity) +{ + memcpy(&id, identity, sizeof(LTE_FDD_ENB_USER_ID_STRUCT)); + id_set = true; +} +LTE_FDD_ENB_USER_ID_STRUCT* LTE_fdd_enb_user::get_id(void) +{ + return(&id); +} +bool LTE_fdd_enb_user::is_id_set(void) +{ + return(id_set); +} +void LTE_fdd_enb_user::set_guti(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *_guti) +{ + memcpy(&guti, _guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT)); + guti_set = true; +} +LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT* LTE_fdd_enb_user::get_guti(void) +{ + return(&guti); +} +bool LTE_fdd_enb_user::is_guti_set(void) { - return(imsi); + return(guti_set); +} +void LTE_fdd_enb_user::set_temp_id(uint64 id) +{ + temp_id = id; +} +uint64 LTE_fdd_enb_user::get_temp_id(void) +{ + return(temp_id); +} +std::string LTE_fdd_enb_user::get_imsi_str(void) +{ + return(to_string(id.imsi, 15)); +} +uint64 LTE_fdd_enb_user::get_imsi_num(void) +{ + return(id.imsi); +} +std::string LTE_fdd_enb_user::get_imei_str(void) +{ + return(to_string(id.imei, 15)); +} +uint64 LTE_fdd_enb_user::get_imei_num(void) +{ + return(id.imei); } void LTE_fdd_enb_user::set_c_rnti(uint16 _c_rnti) { - c_rnti = _c_rnti; + c_rnti = _c_rnti; + c_rnti_set = true; } uint16 LTE_fdd_enb_user::get_c_rnti(void) { return(c_rnti); } +bool LTE_fdd_enb_user::is_c_rnti_set(void) +{ + return(c_rnti_set); +} +void LTE_fdd_enb_user::set_ip_addr(uint32 addr) +{ + ip_addr = addr; + ip_addr_set = true; +} +uint32 LTE_fdd_enb_user::get_ip_addr(void) +{ + return(ip_addr); +} +bool LTE_fdd_enb_user::is_ip_addr_set(void) +{ + return(ip_addr_set); +} +void LTE_fdd_enb_user::prepare_for_deletion(void) +{ + // Let the C-RNTI timer cleanup the user + id_set = false; +} + +/******************/ +/* Security */ +/******************/ +void LTE_fdd_enb_user::set_auth_vec(LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT *av) +{ + memcpy(&auth_vec, av, sizeof(LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT)); + auth_vec_set = true; +} +LTE_FDD_ENB_AUTHENTICATION_VECTOR_STRUCT* LTE_fdd_enb_user::get_auth_vec(void) +{ + return(&auth_vec); +} +void LTE_fdd_enb_user::increment_nas_count_dl(void) +{ + if(auth_vec_set) + { + auth_vec.nas_count_dl++; + } +} +void LTE_fdd_enb_user::increment_nas_count_ul(void) +{ + if(auth_vec_set) + { + auth_vec.nas_count_ul++; + } +} +bool LTE_fdd_enb_user::is_auth_vec_set(void) +{ + return(auth_vec_set); +} + +/**********************/ +/* Capabilities */ +/**********************/ +void LTE_fdd_enb_user::set_eea_support(uint8 eea, + bool support) +{ + eea_support[eea] = support; +} +bool LTE_fdd_enb_user::get_eea_support(uint8 eea) +{ + return(eea_support[eea]); +} +void LTE_fdd_enb_user::set_eia_support(uint8 eia, + bool support) +{ + eia_support[eia] = support; +} +bool LTE_fdd_enb_user::get_eia_support(uint8 eia) +{ + return(eia_support[eia]); +} +void LTE_fdd_enb_user::set_uea_support(uint8 uea, + bool support) +{ + uea_support[uea] = support; + uea_set = true; +} +bool LTE_fdd_enb_user::get_uea_support(uint8 uea) +{ + return(uea_support[uea]); +} +bool LTE_fdd_enb_user::is_uea_set(void) +{ + return(uea_set); +} +void LTE_fdd_enb_user::set_uia_support(uint8 uia, + bool support) +{ + uia_support[uia] = support; + uia_set = true; +} +bool LTE_fdd_enb_user::get_uia_support(uint8 uia) +{ + return(uia_support[uia]); +} +bool LTE_fdd_enb_user::is_uia_set(void) +{ + return(uia_set); +} +void LTE_fdd_enb_user::set_gea_support(uint8 gea, + bool support) +{ + gea_support[gea] = support; + gea_set = true; +} +bool LTE_fdd_enb_user::get_gea_support(uint8 gea) +{ + return(gea_support[gea]); +} +bool LTE_fdd_enb_user::is_gea_set(void) +{ + return(gea_set); +} /***********************/ /* Radio Bearers */ @@ -205,3 +473,306 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user::get_srb2(LTE_fdd_enb_rb **rb) return(err); } +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user::setup_drb(LTE_FDD_ENB_RB_ENUM drb_id, + LTE_fdd_enb_rb **rb) +{ + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_RB_ALREADY_SETUP; + + if(LTE_FDD_ENB_RB_DRB1 <= drb_id && + LTE_FDD_ENB_RB_N_ITEMS > drb_id) + { + if(NULL == drb[drb_id-LTE_FDD_ENB_RB_DRB1]) + { + drb[drb_id-LTE_FDD_ENB_RB_DRB1] = new LTE_fdd_enb_rb(LTE_FDD_ENB_RB_DRB1, this); + err = LTE_FDD_ENB_ERROR_NONE; + } + *rb = drb[drb_id-LTE_FDD_ENB_RB_DRB1]; + } + + return(err); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user::teardown_drb(LTE_FDD_ENB_RB_ENUM drb_id) +{ + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_RB_NOT_SETUP; + + if(LTE_FDD_ENB_RB_DRB1 <= drb_id && + LTE_FDD_ENB_RB_N_ITEMS > drb_id) + { + if(NULL != drb[drb_id-LTE_FDD_ENB_RB_DRB1]) + { + delete drb[drb_id-LTE_FDD_ENB_RB_DRB1]; + err = LTE_FDD_ENB_ERROR_NONE; + } + } + + return(err); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user::get_drb(LTE_FDD_ENB_RB_ENUM drb_id, + LTE_fdd_enb_rb **rb) +{ + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_RB_NOT_SETUP; + + if(LTE_FDD_ENB_RB_DRB1 <= drb_id && + LTE_FDD_ENB_RB_N_ITEMS > drb_id) + { + if(NULL != drb[drb_id-LTE_FDD_ENB_RB_DRB1]) + { + err = LTE_FDD_ENB_ERROR_NONE; + } + *rb = drb[drb_id-LTE_FDD_ENB_RB_DRB1]; + } + + return(err); +} +void LTE_fdd_enb_user::copy_rbs(LTE_fdd_enb_user *user) +{ + uint32 i; + + delete srb0; + user->get_srb0(&srb0); + srb0->reset_user(this); + delete srb1; + user->get_srb1(&srb1); + if(NULL != srb1) + { + srb1->reset_user(this); + } + delete srb2; + user->get_srb2(&srb2); + if(NULL != srb2) + { + srb2->reset_user(this); + } + for(i=0; i<8; i++) + { + delete drb[i]; + user->get_drb((LTE_FDD_ENB_RB_ENUM)(LTE_FDD_ENB_RB_DRB1+i), &drb[i]); + if(NULL != drb[i]) + { + drb[i]->reset_user(this); + } + } +} +void LTE_fdd_enb_user::clear_rbs(void) +{ + uint32 i; + + srb0 = new LTE_fdd_enb_rb(LTE_FDD_ENB_RB_SRB0, this); + srb1 = NULL; + srb2 = NULL; + for(i=0; i<8; i++) + { + drb[i] = NULL; + } +} + +/*************/ +/* MME */ +/*************/ +void LTE_fdd_enb_user::set_emm_cause(uint8 cause) +{ + emm_cause = cause; +} +uint8 LTE_fdd_enb_user::get_emm_cause(void) +{ + return(emm_cause); +} +void LTE_fdd_enb_user::set_attach_type(uint8 type) +{ + attach_type = type; +} +uint8 LTE_fdd_enb_user::get_attach_type(void) +{ + return(attach_type); +} +void LTE_fdd_enb_user::set_pdn_type(uint8 type) +{ + pdn_type = type; +} +uint8 LTE_fdd_enb_user::get_pdn_type(void) +{ + return(pdn_type); +} +void LTE_fdd_enb_user::set_eps_bearer_id(uint8 id) +{ + eps_bearer_id = id; +} +uint8 LTE_fdd_enb_user::get_eps_bearer_id(void) +{ + return(eps_bearer_id); +} +void LTE_fdd_enb_user::set_proc_transaction_id(uint8 id) +{ + proc_transaction_id = id; +} +uint8 LTE_fdd_enb_user::get_proc_transaction_id(void) +{ + return(proc_transaction_id); +} +void LTE_fdd_enb_user::set_esm_info_transfer(bool eit) +{ + eit_flag = eit; +} +bool LTE_fdd_enb_user::get_esm_info_transfer(void) +{ + return(eit_flag); +} +void LTE_fdd_enb_user::set_protocol_cnfg_opts(LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT *pco) +{ + memcpy(&protocol_cnfg_opts, pco, sizeof(LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT)); +} +LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT* LTE_fdd_enb_user::get_protocol_cnfg_opts(void) +{ + return(&protocol_cnfg_opts); +} + +/*************/ +/* MAC */ +/*************/ +bool LTE_fdd_enb_user::get_dl_ndi(void) +{ + return(dl_ndi); +} +void LTE_fdd_enb_user::flip_dl_ndi(void) +{ + dl_ndi ^= 1; +} +bool LTE_fdd_enb_user::get_ul_ndi(void) +{ + return(ul_ndi); +} +void LTE_fdd_enb_user::flip_ul_ndi(void) +{ + ul_ndi ^= 1; +} +void LTE_fdd_enb_user::store_harq_info(uint32 pucch_tti, + LIBLTE_MAC_PDU_STRUCT *mac_pdu, + LIBLTE_PHY_ALLOCATION_STRUCT *alloc) +{ + LTE_FDD_ENB_HARQ_INFO_STRUCT *harq_info = NULL; + + harq_info = new LTE_FDD_ENB_HARQ_INFO_STRUCT; + + if(NULL != harq_info) + { + memcpy(&harq_info->mac_pdu, mac_pdu, sizeof(LIBLTE_MAC_PDU_STRUCT)); + memcpy(&harq_info->alloc, alloc, sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); + sem_wait(&harq_buffer_sem); + harq_buffer[pucch_tti] = harq_info; + sem_post(&harq_buffer_sem); + } +} +void LTE_fdd_enb_user::clear_harq_info(uint32 pucch_tti) +{ + libtools_scoped_lock lock(harq_buffer_sem); + std::map::iterator iter; + + iter = harq_buffer.find(pucch_tti); + if(harq_buffer.end() != iter) + { + delete (*iter).second; + harq_buffer.erase(iter); + } +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user::get_harq_info(uint32 pucch_tti, + LIBLTE_MAC_PDU_STRUCT *mac_pdu, + LIBLTE_PHY_ALLOCATION_STRUCT *alloc) +{ + libtools_scoped_lock lock(harq_buffer_sem); + std::map::iterator iter; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_HARQ_INFO_NOT_FOUND; + + iter = harq_buffer.find(pucch_tti); + if(harq_buffer.end() != iter) + { + memcpy(mac_pdu, &(*iter).second->mac_pdu, sizeof(LIBLTE_MAC_PDU_STRUCT)); + memcpy(alloc, &(*iter).second->alloc, sizeof(LIBLTE_PHY_ALLOCATION_STRUCT)); + delete (*iter).second; + harq_buffer.erase(iter); + err = LTE_FDD_ENB_ERROR_NONE; + } + + return(err); +} +void LTE_fdd_enb_user::set_ul_buffer_size(uint32 N_bytes_in_buffer) +{ + ul_buffer_size = N_bytes_in_buffer; +} +void LTE_fdd_enb_user::update_ul_buffer_size(uint32 N_bytes_received) +{ + if(N_bytes_received > ul_buffer_size) + { + ul_buffer_size = 0; + }else{ + ul_buffer_size -= N_bytes_received; + } +} +uint32 LTE_fdd_enb_user::get_ul_buffer_size(void) +{ + return(ul_buffer_size); +} + +/*****************/ +/* Generic */ +/*****************/ +void LTE_fdd_enb_user::set_N_del_ticks(uint32 N_ticks) +{ + N_del_ticks = N_ticks; +} +uint32 LTE_fdd_enb_user::get_N_del_ticks(void) +{ + return(N_del_ticks); +} +void LTE_fdd_enb_user::handle_timer_expiry(uint32 timer_id) +{ + LTE_fdd_enb_mac *mac = LTE_fdd_enb_mac::get_instance(); + LTE_fdd_enb_rrc *rrc = LTE_fdd_enb_rrc::get_instance(); + LTE_FDD_ENB_RRC_CMD_READY_MSG_STRUCT cmd; + + if(timer_id == inactivity_timer_id) + { + if(NULL != srb1) + { + cmd.cmd = LTE_FDD_ENB_RRC_CMD_RELEASE; + cmd.user = this; + cmd.rb = srb1; + rrc->handle_cmd(&cmd); + } + } +} +uint32 LTE_fdd_enb_user::get_max_ul_bytes_per_subfn(void) +{ + // FIXME: Make this dynamic based on channel conditions + return(50); +} +uint32 LTE_fdd_enb_user::get_max_dl_bytes_per_subfn(void) +{ + // FIXME: Make this dynamic based on channel conditions + return(325); +} +void LTE_fdd_enb_user::start_inactivity_timer(uint32 m_seconds) +{ + LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + LTE_fdd_enb_timer_cb timer_expiry_cb(<E_fdd_enb_timer_cb_wrapper, this); + + timer_mgr->start_timer(m_seconds, timer_expiry_cb, &inactivity_timer_id); +} +void LTE_fdd_enb_user::reset_inactivity_timer(uint32 m_seconds) +{ + LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + LTE_fdd_enb_timer_cb timer_expiry_cb(<E_fdd_enb_timer_cb_wrapper, this); + + if(LTE_FDD_ENB_INVALID_TIMER_ID != inactivity_timer_id) + { + timer_mgr->reset_timer(inactivity_timer_id); + }else{ + timer_mgr->start_timer(m_seconds, timer_expiry_cb, &inactivity_timer_id); + } +} +void LTE_fdd_enb_user::stop_inactivity_timer(void) +{ + LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + + timer_mgr->stop_timer(inactivity_timer_id); + inactivity_timer_id = LTE_FDD_ENB_INVALID_TIMER_ID; +} diff --git a/LTE_fdd_enodeb/src/LTE_fdd_enb_user_mgr.cc b/LTE_fdd_enodeb/src/LTE_fdd_enb_user_mgr.cc old mode 100644 new mode 100755 index bb45b78..5f2f7c8 --- a/LTE_fdd_enodeb/src/LTE_fdd_enb_user_mgr.cc +++ b/LTE_fdd_enodeb/src/LTE_fdd_enb_user_mgr.cc @@ -1,7 +1,7 @@ #line 2 "LTE_fdd_enb_user_mgr.cc" // Make __FILE__ omit the path /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -29,6 +29,27 @@ 01/18/2014 Ben Wojtowicz Added level to debug prints. 05/04/2014 Ben Wojtowicz Added C-RNTI timeout timers. 06/15/2014 Ben Wojtowicz Deleting user on C-RNTI expiration. + 08/03/2014 Ben Wojtowicz Refactored add_user. + 11/01/2014 Ben Wojtowicz Added M-TMSI assignment. + 11/29/2014 Ben Wojtowicz Refactored C-RNTI assign/release, added + C-RNTI transfer, added more ways to add, + delete, and find users. + 12/16/2014 Ben Wojtowicz Added delayed user delete functionality. + 12/24/2014 Ben Wojtowicz Hack to get around a crash when releasing a + C-RNTI. + 02/15/2015 Ben Wojtowicz Fixed C-RNTI assign/release list management. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and + sem_t and changed the user deletion + procedure. + 02/13/2016 Ben Wojtowicz Added ability to retrieve a string of all + registered users, added a user inactivity + timer, and properly updating the iterator + after erasing a user from the user list + (thanks to Damian Jarek for reporting this). + 07/03/2016 Ben Wojtowicz Added logic to use the C-RNTI instead of + IMSI/IMEI when printing a user that doesn't + have IMSI/IMEI set. + 07/29/2017 Ben Wojtowicz Using the latest tools library. *******************************************************************************/ @@ -39,7 +60,8 @@ #include "LTE_fdd_enb_user_mgr.h" #include "LTE_fdd_enb_timer_mgr.h" #include "liblte_mac.h" -#include +#include "libtools_scoped_lock.h" +#include "libtools_helpers.h" /******************************************************************************* DEFINES @@ -55,8 +77,8 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_fdd_enb_user_mgr* LTE_fdd_enb_user_mgr::instance = NULL; -boost::mutex user_mgr_instance_mutex; +LTE_fdd_enb_user_mgr* LTE_fdd_enb_user_mgr::instance = NULL; +static pthread_mutex_t user_mgr_instance_mutex = PTHREAD_MUTEX_INITIALIZER; /******************************************************************************* CLASS IMPLEMENTATIONS @@ -67,7 +89,7 @@ boost::mutex user_mgr_instance_mutex; /*******************/ LTE_fdd_enb_user_mgr* LTE_fdd_enb_user_mgr::get_instance(void) { - boost::mutex::scoped_lock lock(user_mgr_instance_mutex); + libtools_scoped_lock lock(user_mgr_instance_mutex); if(NULL == instance) { @@ -78,7 +100,7 @@ LTE_fdd_enb_user_mgr* LTE_fdd_enb_user_mgr::get_instance(void) } void LTE_fdd_enb_user_mgr::cleanup(void) { - boost::mutex::scoped_lock lock(user_mgr_instance_mutex); + libtools_scoped_lock lock(user_mgr_instance_mutex); if(NULL != instance) { @@ -92,135 +114,212 @@ void LTE_fdd_enb_user_mgr::cleanup(void) /********************************/ LTE_fdd_enb_user_mgr::LTE_fdd_enb_user_mgr() { + sem_init(&user_sem, 0, 1); + sem_init(&c_rnti_sem, 0, 1); + sem_init(&timer_id_sem, 0, 1); + next_m_tmsi = 1; next_c_rnti = LIBLTE_MAC_C_RNTI_START; } LTE_fdd_enb_user_mgr::~LTE_fdd_enb_user_mgr() { + sem_destroy(&user_sem); + sem_destroy(&c_rnti_sem); + sem_destroy(&timer_id_sem); } /****************************/ /* External Interface */ /****************************/ -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::get_free_c_rnti(uint16 *c_rnti) +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::assign_c_rnti(LTE_fdd_enb_user *user, + uint16 *c_rnti) { - boost::mutex::scoped_lock lock(c_rnti_mutex); - std::map::iterator iter; - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NO_FREE_C_RNTI; - uint16 start_c_rnti = next_c_rnti; + libtools_scoped_lock lock(c_rnti_sem); + LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + std::map::iterator iter = c_rnti_map.find(next_c_rnti); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NONE; + uint16 start_c_rnti = next_c_rnti; while(c_rnti_map.end() != iter) { - iter = c_rnti_map.find(next_c_rnti++); - + next_c_rnti++; if(LIBLTE_MAC_C_RNTI_END < next_c_rnti) { next_c_rnti = LIBLTE_MAC_C_RNTI_START; } if(next_c_rnti == start_c_rnti) { + err = LTE_FDD_ENB_ERROR_NO_FREE_C_RNTI; break; } + + iter = c_rnti_map.find(next_c_rnti); } - if(next_c_rnti != start_c_rnti) + if(LTE_FDD_ENB_ERROR_NONE == err) { - *c_rnti = next_c_rnti-1; - err = LTE_FDD_ENB_ERROR_NONE; + c_rnti_map[next_c_rnti] = user; + *c_rnti = next_c_rnti++; + + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_USER, + __FILE__, + __LINE__, + "C-RNTI=%u assigned", + *c_rnti); + + if(LIBLTE_MAC_C_RNTI_END < next_c_rnti) + { + next_c_rnti = LIBLTE_MAC_C_RNTI_START; + } } return(err); } -void LTE_fdd_enb_user_mgr::assign_c_rnti(uint16 c_rnti, - LTE_fdd_enb_user *user) +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::release_c_rnti(uint16 c_rnti) { - boost::mutex::scoped_lock lock(c_rnti_mutex); + libtools_scoped_lock c_lock(c_rnti_sem); + libtools_scoped_lock t_lock(timer_id_sem); + LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); + LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + std::map::iterator iter = c_rnti_map.find(c_rnti); + std::map::iterator tr_iter; + std::map::iterator tf_iter; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_C_RNTI_NOT_FOUND; - c_rnti_map[c_rnti] = user; + if(c_rnti_map.end() != iter) + { + interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, + LTE_FDD_ENB_DEBUG_LEVEL_USER, + __FILE__, + __LINE__, + "C-RNTI=%u released", + c_rnti); + + // Initialize or delete the user + if((*iter).second->is_id_set()) + { + (*iter).second->init(); + }else{ + del_user((*iter).second); + } + + // Release the C-RNTI + c_rnti_map.erase(iter); + + // Stop the C-RNTI timer + tr_iter = timer_id_map_reverse.find(c_rnti); + if(timer_id_map_reverse.end() != tr_iter) + { + timer_mgr->stop_timer((*tr_iter).second); + tf_iter = timer_id_map_forward.find((*tr_iter).second); + if(timer_id_map_forward.end() != tf_iter) + { + timer_id_map_forward.erase(tf_iter); + } + timer_id_map_reverse.erase(tr_iter); + } + + err = LTE_FDD_ENB_ERROR_NONE; + } + + return(err); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::free_c_rnti(uint16 c_rnti) +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::transfer_c_rnti(LTE_fdd_enb_user *old_user, + LTE_fdd_enb_user *new_user) { - boost::mutex::scoped_lock lock(c_rnti_mutex); - std::map::iterator iter = c_rnti_map.find(c_rnti); - std::string fake_imsi; - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_C_RNTI_NOT_FOUND; + libtools_scoped_lock lock(c_rnti_sem); + std::map::iterator iter = c_rnti_map.find(old_user->get_c_rnti()); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_C_RNTI_NOT_FOUND; + uint16 c_rnti; if(c_rnti_map.end() != iter) { - fake_imsi = "F"; - fake_imsi += boost::lexical_cast(c_rnti); - if((*iter).second->get_imsi() == fake_imsi) + c_rnti = old_user->get_c_rnti(); + + // Cleanup the old user + if(old_user->is_id_set()) { - del_user(c_rnti); + old_user->init(); }else{ - (*iter).second->init(); + old_user->prepare_for_deletion(); } + + // Update the C-RNTI map c_rnti_map.erase(iter); + c_rnti_map[c_rnti] = new_user; + iter = c_rnti_map.find(new_user->get_c_rnti()); + if(c_rnti_map.end() != iter) + { + c_rnti_map.erase(iter); + } + new_user->set_c_rnti(c_rnti); + err = LTE_FDD_ENB_ERROR_NONE; } return(err); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::add_user(std::string imsi) +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::reset_c_rnti_timer(uint16 c_rnti) { - LTE_fdd_enb_user *new_user = NULL; - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NONE; - - new_user = new LTE_fdd_enb_user(imsi); + libtools_scoped_lock lock(timer_id_sem); + std::map::iterator iter = timer_id_map_reverse.find(c_rnti); + LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_C_RNTI_NOT_FOUND; - if(NULL != new_user) + if(timer_id_map_reverse.end() != iter) { - user_mutex.lock(); - user_map[imsi] = new_user; - user_mutex.unlock(); - }else{ - err = LTE_FDD_ENB_ERROR_BAD_ALLOC; + timer_mgr->reset_timer((*iter).second); + + err = LTE_FDD_ENB_ERROR_NONE; } return(err); } -LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::add_user(uint16 c_rnti) +uint32 LTE_fdd_enb_user_mgr::get_next_m_tmsi(void) +{ + return(next_m_tmsi++); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::add_user(LTE_fdd_enb_user **user) { LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance(); LTE_fdd_enb_user *new_user = NULL; LTE_fdd_enb_timer_cb timer_expiry_cb(<E_fdd_enb_timer_cb_wrapper, this); - std::string fake_imsi; - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NONE; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_NONE; uint32 timer_id; + uint16 c_rnti; - try - { - fake_imsi = "F"; - fake_imsi += boost::lexical_cast(c_rnti); - - new_user = new LTE_fdd_enb_user(fake_imsi); + new_user = new LTE_fdd_enb_user(); - if(NULL != new_user) + if(NULL != new_user) + { + // Assign C-RNTI + if(LTE_FDD_ENB_ERROR_NONE == assign_c_rnti(new_user, &c_rnti)) { - // Allocate new user + // Start C-RNTI reservation timer + timer_mgr->start_timer(5000, timer_expiry_cb, &timer_id); + sem_wait(&timer_id_sem); + timer_id_map_forward[timer_id] = c_rnti; + timer_id_map_reverse[c_rnti] = timer_id; + sem_post(&timer_id_sem); + + // Setup user new_user->set_c_rnti(c_rnti); - user_mutex.lock(); - user_map[fake_imsi] = new_user; - user_mutex.unlock(); + new_user->start_inactivity_timer(LTE_FDD_ENB_USER_INACTIVITY_TIMER_VALUE_MS); - // Start a C-RNTI reservation timer - timer_mgr->start_timer(5000, timer_expiry_cb, &timer_id); - timer_id_mutex.lock(); - timer_id_map[timer_id] = c_rnti; - timer_id_mutex.unlock(); + // Store user + sem_wait(&user_sem); + user_list.push_back(new_user); + sem_post(&user_sem); - // Assign C-RNTI - assign_c_rnti(c_rnti, new_user); + // Return user + *user = new_user; }else{ - err = LTE_FDD_ENB_ERROR_BAD_ALLOC; + err = LTE_FDD_ENB_ERROR_NO_FREE_C_RNTI; + delete new_user; } - }catch(...){ - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, - LTE_FDD_ENB_DEBUG_LEVEL_USER, - __FILE__, - __LINE__, - "Exception to fake imsi"); - err = LTE_FDD_ENB_ERROR_EXCEPTION; + }else{ + err = LTE_FDD_ENB_ERROR_BAD_ALLOC; } return(err); @@ -228,14 +327,25 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::add_user(uint16 c_rnti) LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::find_user(std::string imsi, LTE_fdd_enb_user **user) { - boost::mutex::scoped_lock lock(user_mutex); - std::map::iterator iter = user_map.find(imsi); - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + uint64 imsi_num = 0; - if(user_map.end() != iter) + if(imsi.length() == 15) { - *user = (*iter).second; - err = LTE_FDD_ENB_ERROR_NONE; + to_number(imsi, 15, &imsi_num); + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if((*iter)->is_id_set() && + (*iter)->get_id()->imsi == imsi_num) + { + *user = (*iter); + err = LTE_FDD_ENB_ERROR_NONE; + break; + } + } } return(err); @@ -243,66 +353,256 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::find_user(std::string imsi, LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::find_user(uint16 c_rnti, LTE_fdd_enb_user **user) { - boost::mutex::scoped_lock lock(c_rnti_mutex); - std::map::iterator iter = c_rnti_map.find(c_rnti); - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if((*iter)->is_c_rnti_set() && + (*iter)->get_c_rnti() == c_rnti) + { + *user = (*iter); + err = LTE_FDD_ENB_ERROR_NONE; + break; + } + } + + return(err); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::find_user(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *guti, + LTE_fdd_enb_user **user) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if((*iter)->is_guti_set() && + (*iter)->get_guti()->m_tmsi == guti->m_tmsi && + (*iter)->get_guti()->mcc == guti->mcc && + (*iter)->get_guti()->mnc == guti->mnc && + (*iter)->get_guti()->mme_group_id == guti->mme_group_id && + (*iter)->get_guti()->mme_code == guti->mme_code) + { + *user = (*iter); + err = LTE_FDD_ENB_ERROR_NONE; + break; + } + } + + return(err); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::find_user(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi, + LTE_fdd_enb_user **user) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if((*iter)->is_guti_set() && + (*iter)->get_guti()->m_tmsi == s_tmsi->m_tmsi && + (*iter)->get_guti()->mme_code == s_tmsi->mmec) + { + *user = (*iter); + err = LTE_FDD_ENB_ERROR_NONE; + break; + } + } + + return(err); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::find_user(uint32 ip_addr, + LTE_fdd_enb_user **user) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; - if(c_rnti_map.end() != iter && - NULL != (*iter).second) + for(iter=user_list.begin(); iter!=user_list.end(); iter++) { - *user = (*iter).second; - err = LTE_FDD_ENB_ERROR_NONE; + if((*iter)->is_ip_addr_set() && + (*iter)->get_ip_addr() == ip_addr) + { + *user = (*iter); + err = LTE_FDD_ENB_ERROR_NONE; + break; + } + } + + return(err); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::del_user(LTE_fdd_enb_user *user) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_fdd_enb_user *tmp_user = NULL; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + + if(user->is_id_set()) + { + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if(user->get_id()->imsi == (*iter)->get_id()->imsi && + user->get_id()->imei == (*iter)->get_id()->imei) + { + tmp_user = (*iter); + iter = user_list.erase(iter); + delete tmp_user; + err = LTE_FDD_ENB_ERROR_NONE; + break; + } + } + }else if(user->is_guti_set()){ + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if(user->get_guti()->m_tmsi == (*iter)->get_guti()->m_tmsi && + user->get_guti()->mcc == (*iter)->get_guti()->mcc && + user->get_guti()->mnc == (*iter)->get_guti()->mnc && + user->get_guti()->mme_group_id == (*iter)->get_guti()->mme_group_id && + user->get_guti()->mme_code == (*iter)->get_guti()->mme_code) + { + tmp_user = (*iter); + iter = user_list.erase(iter); + delete tmp_user; + err = LTE_FDD_ENB_ERROR_NONE; + break; + } + } + }else if(user->is_c_rnti_set()){ + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if(user->get_c_rnti() == (*iter)->get_c_rnti()) + { + tmp_user = (*iter); + iter = user_list.erase(iter); + delete tmp_user; + err = LTE_FDD_ENB_ERROR_NONE; + break; + } + } } return(err); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::del_user(std::string imsi) { - boost::mutex::scoped_lock lock(user_mutex); - std::map::iterator iter = user_map.find(imsi); - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_fdd_enb_user *tmp_user = NULL; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + uint64 imsi_num = 0; - if(user_map.end() != iter) + if(imsi.length() == 15) { - delete (*iter).second; - user_map.erase(iter); - err = LTE_FDD_ENB_ERROR_NONE; + to_number(imsi, 15, &imsi_num); + + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if((*iter)->is_id_set() && + (*iter)->get_id()->imsi == imsi_num) + { + tmp_user = (*iter); + iter = user_list.erase(iter); + delete tmp_user; + err = LTE_FDD_ENB_ERROR_NONE; + break; + } + } } return(err); } LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::del_user(uint16 c_rnti) { - LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - boost::mutex::scoped_lock lock(user_mutex); - std::map::iterator iter; - std::string fake_imsi; - LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_fdd_enb_user *tmp_user = NULL; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; - try + for(iter=user_list.begin(); iter!=user_list.end(); iter++) { - fake_imsi = "F"; - fake_imsi += boost::lexical_cast(c_rnti); + if((*iter)->is_c_rnti_set() && + (*iter)->get_c_rnti() == c_rnti) + { + tmp_user = (*iter); + iter = user_list.erase(iter); + delete tmp_user; + err = LTE_FDD_ENB_ERROR_NONE; + break; + } + } - iter = user_map.find(fake_imsi); + return(err); +} +LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::del_user(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *guti) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + LTE_fdd_enb_user *tmp_user = NULL; + LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_USER_NOT_FOUND; - if(user_map.end() != iter) + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + if((*iter)->is_guti_set() && + (*iter)->get_guti()->m_tmsi == guti->m_tmsi && + (*iter)->get_guti()->mcc == guti->mcc && + (*iter)->get_guti()->mnc == guti->mnc && + (*iter)->get_guti()->mme_group_id == guti->mme_group_id && + (*iter)->get_guti()->mme_code == guti->mme_code) { - delete (*iter).second; - user_map.erase(iter); + tmp_user = (*iter); + iter = user_list.erase(iter); + delete tmp_user; err = LTE_FDD_ENB_ERROR_NONE; + break; } - }catch(...){ - interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR, - LTE_FDD_ENB_DEBUG_LEVEL_USER, - __FILE__, - __LINE__, - "Exception to fake imsi"); - err = LTE_FDD_ENB_ERROR_EXCEPTION; } return(err); } +std::string LTE_fdd_enb_user_mgr::print_all_users(void) +{ + libtools_scoped_lock lock(user_sem); + std::list::iterator iter; + std::string output; + LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *guti; + uint32 i; + uint32 hex_val; + + output = to_string((uint32)user_list.size()); + for(iter=user_list.begin(); iter!=user_list.end(); iter++) + { + output += "\n"; + if((*iter)->is_id_set()) + { + output += "imsi=" + to_string((*iter)->get_imsi_num(), 15) + " "; + output += "imei=" + to_string((*iter)->get_imei_num(), 15) + " "; + }else{ + output += "c-rnti=" + to_string((*iter)->get_c_rnti()) + " "; + } + if((*iter)->is_guti_set()) + { + guti = (*iter)->get_guti(); + output += " m-tmsi="; + for(i=0; i<8; i++) + { + hex_val = (guti->m_tmsi >> (28 - (i*4))) & 0xF; + if(hex_val < 0xA) + { + output += (char)(hex_val + '0'); + }else{ + output += (char)((hex_val-0xA) + 'A'); + } + } + } + } + + return(output); +} /**********************/ /* C-RNTI Timer */ @@ -310,18 +610,30 @@ LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user_mgr::del_user(uint16 c_rnti) void LTE_fdd_enb_user_mgr::handle_c_rnti_timer_expiry(uint32 timer_id) { LTE_fdd_enb_interface *interface = LTE_fdd_enb_interface::get_instance(); - boost::mutex::scoped_lock lock(timer_id_mutex); - std::map::iterator iter = timer_id_map.find(timer_id); + std::map::iterator forward_iter = timer_id_map_forward.find(timer_id); + std::map::iterator reverse_iter; + uint16 c_rnti; - if(timer_id_map.end() != iter) + sem_wait(&timer_id_sem); + if(timer_id_map_forward.end() != forward_iter) { interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO, LTE_FDD_ENB_DEBUG_LEVEL_USER, __FILE__, __LINE__, "C-RNTI allocation timer expiry C-RNTI=%u", - (*iter).second); - free_c_rnti((*iter).second); - timer_id_map.erase(iter); + (*forward_iter).second); + c_rnti = (*forward_iter).second; + reverse_iter = timer_id_map_reverse.find((*forward_iter).second); + if(timer_id_map_reverse.end() != reverse_iter) + { + timer_id_map_reverse.erase(reverse_iter); + } + timer_id_map_forward.erase(forward_iter); + + sem_post(&timer_id_sem); + release_c_rnti(c_rnti); + }else{ + sem_post(&timer_id_sem); } } diff --git a/LTE_file_recorder/CMakeLists.txt b/LTE_file_recorder/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/LTE_file_recorder/hdr/LTE_file_recorder_flowgraph.h b/LTE_file_recorder/hdr/LTE_file_recorder_flowgraph.h old mode 100644 new mode 100755 index da449df..f5f84ed --- a/LTE_file_recorder/hdr/LTE_file_recorder_flowgraph.h +++ b/LTE_file_recorder/hdr/LTE_file_recorder_flowgraph.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013 Ben Wojtowicz + Copyright 2013,2015 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +27,7 @@ 08/26/2013 Ben Wojtowicz Created file 11/13/2013 Ben Wojtowicz Added support for USRP B2X0. 11/30/2013 Ben Wojtowicz Added support for bladeRF. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t. *******************************************************************************/ @@ -38,7 +39,6 @@ *******************************************************************************/ #include "LTE_file_recorder_interface.h" -#include #include #include #include @@ -95,9 +95,9 @@ class LTE_file_recorder_flowgraph osmosdr::source::sptr samp_src; gr::blocks::file_sink::sptr file_sink; - pthread_t start_thread; - boost::mutex start_mutex; - bool started; + pthread_t start_thread; + pthread_mutex_t start_mutex; + bool started; }; #endif /* __LTE_FILE_RECORDER_FLOWGRAPH_H__ */ diff --git a/LTE_file_recorder/hdr/LTE_file_recorder_interface.h b/LTE_file_recorder/hdr/LTE_file_recorder_interface.h old mode 100644 new mode 100755 index 6fb9db8..eaa9bca --- a/LTE_file_recorder/hdr/LTE_file_recorder_interface.h +++ b/LTE_file_recorder/hdr/LTE_file_recorder_interface.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013 Ben Wojtowicz + Copyright 2013,2015 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -25,6 +25,7 @@ Revision History ---------- ------------- -------------------------------------------- 08/26/2013 Ben Wojtowicz Created file + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t. *******************************************************************************/ @@ -37,7 +38,6 @@ #include "liblte_interface.h" #include "libtools_socket_wrap.h" -#include #include /******************************************************************************* @@ -82,7 +82,7 @@ class LTE_file_recorder_interface static void handle_ctrl_connect(void); static void handle_ctrl_disconnect(void); static void handle_ctrl_error(LIBTOOLS_SOCKET_WRAP_ERROR_ENUM err); - boost::mutex ctrl_mutex; + pthread_mutex_t ctrl_mutex; libtools_socket_wrap *ctrl_socket; int16 ctrl_port; static bool ctrl_connected; diff --git a/LTE_file_recorder/src/LTE_file_recorder_flowgraph.cc b/LTE_file_recorder/src/LTE_file_recorder_flowgraph.cc old mode 100644 new mode 100755 index 139ca59..e77f16c --- a/LTE_file_recorder/src/LTE_file_recorder_flowgraph.cc +++ b/LTE_file_recorder/src/LTE_file_recorder_flowgraph.cc @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013 Ben Wojtowicz + Copyright 2013,2015 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +27,7 @@ 08/26/2013 Ben Wojtowicz Created file 11/13/2013 Ben Wojtowicz Added support for USRP B2X0. 11/30/2013 Ben Wojtowicz Added support for bladeRF. + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t. *******************************************************************************/ @@ -35,6 +36,7 @@ *******************************************************************************/ #include "LTE_file_recorder_flowgraph.h" +#include "libtools_scoped_lock.h" #include "uhd/usrp/multi_usrp.hpp" /******************************************************************************* @@ -52,7 +54,7 @@ *******************************************************************************/ LTE_file_recorder_flowgraph* LTE_file_recorder_flowgraph::instance = NULL; -boost::mutex flowgraph_instance_mutex; +static pthread_mutex_t flowgraph_instance_mutex = PTHREAD_MUTEX_INITIALIZER; /******************************************************************************* CLASS IMPLEMENTATIONS @@ -61,7 +63,7 @@ boost::mutex flowgraph_instance_mutex; // Singleton LTE_file_recorder_flowgraph* LTE_file_recorder_flowgraph::get_instance(void) { - boost::mutex::scoped_lock lock(flowgraph_instance_mutex); + libtools_scoped_lock lock(flowgraph_instance_mutex); if(NULL == instance) { @@ -72,7 +74,7 @@ LTE_file_recorder_flowgraph* LTE_file_recorder_flowgraph::get_instance(void) } void LTE_file_recorder_flowgraph::cleanup(void) { - boost::mutex::scoped_lock lock(flowgraph_instance_mutex); + libtools_scoped_lock lock(flowgraph_instance_mutex); if(NULL != instance) { @@ -84,30 +86,32 @@ void LTE_file_recorder_flowgraph::cleanup(void) // Constructor/Destructor LTE_file_recorder_flowgraph::LTE_file_recorder_flowgraph() { + pthread_mutex_init(&start_mutex, NULL); started = false; } LTE_file_recorder_flowgraph::~LTE_file_recorder_flowgraph() { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_mutex); if(started) { - start_mutex.unlock(); + pthread_mutex_unlock(&start_mutex); stop(); } + pthread_mutex_destroy(&start_mutex); } // Flowgraph bool LTE_file_recorder_flowgraph::is_started(void) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_mutex); return(started); } LTE_FILE_RECORDER_STATUS_ENUM LTE_file_recorder_flowgraph::start(uint16 earfcn, std::string file_name) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_mutex); LTE_file_recorder_interface *interface = LTE_file_recorder_interface::get_instance(); uhd::device_addr_t hint; LTE_FILE_RECORDER_STATUS_ENUM err = LTE_FILE_RECORDER_STATUS_FAIL; @@ -225,13 +229,13 @@ LTE_FILE_RECORDER_STATUS_ENUM LTE_file_recorder_flowgraph::start(uint16 ear } LTE_FILE_RECORDER_STATUS_ENUM LTE_file_recorder_flowgraph::stop(void) { - boost::mutex::scoped_lock lock(start_mutex); + libtools_scoped_lock lock(start_mutex); LTE_FILE_RECORDER_STATUS_ENUM err = LTE_FILE_RECORDER_STATUS_FAIL; if(started) { started = false; - start_mutex.unlock(); + pthread_mutex_unlock(&start_mutex); top_block->stop(); sleep(1); // Wait for state_machine to exit pthread_cancel(start_thread); diff --git a/LTE_file_recorder/src/LTE_file_recorder_interface.cc b/LTE_file_recorder/src/LTE_file_recorder_interface.cc old mode 100644 new mode 100755 index a7e12ff..897249c --- a/LTE_file_recorder/src/LTE_file_recorder_interface.cc +++ b/LTE_file_recorder/src/LTE_file_recorder_interface.cc @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013 Ben Wojtowicz + Copyright 2013,2015,2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -25,6 +25,8 @@ Revision History ---------- ------------- -------------------------------------------- 08/26/2013 Ben Wojtowicz Created file + 12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t. + 07/29/2017 Ben Wojtowicz Using the latest tools library. *******************************************************************************/ @@ -34,7 +36,8 @@ #include "LTE_file_recorder_interface.h" #include "LTE_file_recorder_flowgraph.h" -#include +#include "libtools_scoped_lock.h" +#include "libtools_helpers.h" /******************************************************************************* DEFINES @@ -52,9 +55,9 @@ GLOBAL VARIABLES *******************************************************************************/ -LTE_file_recorder_interface* LTE_file_recorder_interface::instance = NULL; -boost::mutex interface_instance_mutex; -boost::mutex connect_mutex; +LTE_file_recorder_interface* LTE_file_recorder_interface::instance = NULL; +static pthread_mutex_t interface_instance_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t connect_mutex = PTHREAD_MUTEX_INITIALIZER; bool LTE_file_recorder_interface::ctrl_connected = false; /******************************************************************************* @@ -64,7 +67,7 @@ bool LTE_file_recorder_interface::ctrl_connected = false // Singleton LTE_file_recorder_interface* LTE_file_recorder_interface::get_instance(void) { - boost::mutex::scoped_lock lock(interface_instance_mutex); + libtools_scoped_lock lock(interface_instance_mutex); if(NULL == instance) { @@ -75,7 +78,7 @@ LTE_file_recorder_interface* LTE_file_recorder_interface::get_instance(void) } void LTE_file_recorder_interface::cleanup(void) { - boost::mutex::scoped_lock lock(interface_instance_mutex); + libtools_scoped_lock lock(interface_instance_mutex); if(NULL != instance) { @@ -90,6 +93,7 @@ LTE_file_recorder_interface::LTE_file_recorder_interface() uint32 i; // Communication + pthread_mutex_init(&ctrl_mutex, NULL); ctrl_socket = NULL; ctrl_port = LTE_FILE_RECORDER_DEFAULT_CTRL_PORT; ctrl_connected = false; @@ -102,12 +106,13 @@ LTE_file_recorder_interface::LTE_file_recorder_interface() LTE_file_recorder_interface::~LTE_file_recorder_interface() { stop_ctrl_port(); + pthread_mutex_destroy(&ctrl_mutex); } // Communication void LTE_file_recorder_interface::set_ctrl_port(int16 port) { - boost::mutex::scoped_lock lock(connect_mutex); + libtools_scoped_lock lock(connect_mutex); if(!ctrl_connected) { @@ -116,7 +121,7 @@ void LTE_file_recorder_interface::set_ctrl_port(int16 port) } void LTE_file_recorder_interface::start_ctrl_port(void) { - boost::mutex::scoped_lock lock(ctrl_mutex); + libtools_scoped_lock lock(ctrl_mutex); LIBTOOLS_SOCKET_WRAP_ERROR_ENUM error; if(NULL == ctrl_socket) @@ -138,7 +143,7 @@ void LTE_file_recorder_interface::start_ctrl_port(void) } void LTE_file_recorder_interface::stop_ctrl_port(void) { - boost::mutex::scoped_lock lock(ctrl_mutex); + libtools_scoped_lock lock(ctrl_mutex); if(NULL != ctrl_socket) { @@ -148,8 +153,8 @@ void LTE_file_recorder_interface::stop_ctrl_port(void) } void LTE_file_recorder_interface::send_ctrl_msg(std::string msg) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; if(ctrl_connected) { @@ -160,8 +165,8 @@ void LTE_file_recorder_interface::send_ctrl_msg(std::string msg) } void LTE_file_recorder_interface::send_ctrl_info_msg(std::string msg) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; if(ctrl_connected) { @@ -174,8 +179,8 @@ void LTE_file_recorder_interface::send_ctrl_info_msg(std::string msg) void LTE_file_recorder_interface::send_ctrl_status_msg(LTE_FILE_RECORDER_STATUS_ENUM status, std::string msg) { - boost::mutex::scoped_lock lock(connect_mutex); - std::string tmp_msg; + libtools_scoped_lock lock(connect_mutex); + std::string tmp_msg; if(ctrl_connected) { @@ -217,16 +222,16 @@ void LTE_file_recorder_interface::handle_ctrl_connect(void) { LTE_file_recorder_interface *interface = LTE_file_recorder_interface::get_instance(); - connect_mutex.lock(); + pthread_mutex_lock(&connect_mutex); LTE_file_recorder_interface::ctrl_connected = true; - connect_mutex.unlock(); + pthread_mutex_unlock(&connect_mutex); interface->send_ctrl_msg("*** LTE File Recorder ***"); interface->send_ctrl_msg("Type help to see a list of commands"); } void LTE_file_recorder_interface::handle_ctrl_disconnect(void) { - boost::mutex::scoped_lock lock(connect_mutex); + libtools_scoped_lock lock(connect_mutex); LTE_file_recorder_interface::ctrl_connected = false; } @@ -306,15 +311,10 @@ void LTE_file_recorder_interface::handle_help(void) send_ctrl_msg("\tParameters:"); // EARFCN - try - { - tmp_str = "\t\t"; - tmp_str += EARFCN_PARAM; - tmp_str += " = "; - tmp_str += boost::lexical_cast(earfcn); - }catch(boost::bad_lexical_cast &){ - // Intentionally do nothing - } + tmp_str = "\t\t"; + tmp_str += EARFCN_PARAM; + tmp_str += " = "; + tmp_str += to_string(earfcn); send_ctrl_msg(tmp_str); // FILE_NAME @@ -333,23 +333,13 @@ bool LTE_file_recorder_interface::get_shutdown(void) // Reads/Writes void LTE_file_recorder_interface::read_earfcn(void) { - try - { - send_ctrl_status_msg(LTE_FILE_RECORDER_STATUS_OK, boost::lexical_cast(earfcn).c_str()); - }catch(boost::bad_lexical_cast &){ - send_ctrl_status_msg(LTE_FILE_RECORDER_STATUS_FAIL, "bad earfcn"); - } + send_ctrl_status_msg(LTE_FILE_RECORDER_STATUS_OK, to_string(earfcn).c_str()); } void LTE_file_recorder_interface::write_earfcn(std::string earfcn_str) { uint16 tmp_earfcn = LIBLTE_INTERFACE_DL_EARFCN_INVALID; - try - { - tmp_earfcn = boost::lexical_cast(earfcn_str); - }catch(boost::bad_lexical_cast &){ - // Intentionally do nothing - } + to_number(earfcn_str, &tmp_earfcn); if(0 != liblte_interface_dl_earfcn_to_frequency(tmp_earfcn) || 0 != liblte_interface_ul_earfcn_to_frequency(tmp_earfcn)) diff --git a/LTE_file_recorder/src/LTE_file_recorder_main.cc b/LTE_file_recorder/src/LTE_file_recorder_main.cc old mode 100644 new mode 100755 diff --git a/NEWS b/NEWS old mode 100644 new mode 100755 diff --git a/README b/README old mode 100644 new mode 100755 index 5e05cb1..81ff3d3 --- a/README +++ b/README @@ -25,6 +25,8 @@ openLTE is dependant on the following: 4) UHD 5) HackRF 6) bladeRF +7) mbedtls +8) iptables To build the C++ and python code use the following: @@ -144,9 +146,17 @@ USRP B2X0 hardware, run LTE_fdd_enodeb, and connect (via telnet, nc, etc) to the control port at port number 30000. eNodeB parameters can be changed on the control port. For a list of parameters simply type help on the control port. A MAC and above level PCAP trace is -output to /tmp/LTE_fdd_enodeb.pcap. -NOTES: This application has been tested at 1.4, 3, and 5MHz -bandwidths. Higher bandwidths are supported and performance may +output to /tmp/LTE_fdd_enodeb.pcap. Data packets are routed through +a tun device named tun_openlte. Wireshark can be used to observe +IP packets on tun_openlte to inspect the IP traffic to/from UEs. In +order to configure properly, set the ip_addr_start parameter to the +begining of a non-conflicting private address range (i.e. 10.0.0.1) +and set the dns_addr parameter to the primary DNS address listed by +your modem. All UEs will be assigned IP addresses in the range +of ip_addr_start to ip_addr_start+254 and all traffic will be tunneled +through the tun device to the internet using NAT/iptables. +NOTES: This application has been tested exclusively at 5MHz +bandwidth. Higher bandwidths are supported and performance may vary based on processing hardware. WARNINGS: By using this application you risk disruption of service in a public network, even if you are not directly interfering with the diff --git a/cmake/Modules/CMakeParseArgumentsCopy.cmake b/cmake/Modules/CMakeParseArgumentsCopy.cmake old mode 100644 new mode 100755 diff --git a/cmake/Modules/FindFFTW3F.cmake b/cmake/Modules/FindFFTW3F.cmake old mode 100644 new mode 100755 diff --git a/cmake/Modules/FindGnuradioOsmosdr.cmake b/cmake/Modules/FindGnuradioOsmosdr.cmake old mode 100644 new mode 100755 diff --git a/cmake/Modules/FindLibbladeRF.cmake b/cmake/Modules/FindLibbladeRF.cmake new file mode 100755 index 0000000..0971344 --- /dev/null +++ b/cmake/Modules/FindLibbladeRF.cmake @@ -0,0 +1,27 @@ +if(NOT LIBBLADERF_FOUND) + pkg_check_modules (LIBBLADERF_PKG libbladeRF) + find_path(LIBBLADERF_INCLUDE_DIRS NAMES libbladeRF.h + PATHS + ${LIBBLADERF_PKG_INCLUDE_DIRS} + /usr/include + /usr/local/include + ) + + find_library(LIBBLADERF_LIBRARIES NAMES bladeRF + PATHS + ${LIBBLADERF_PKG_LIBRARY_DIRS} + /usr/lib + /usr/local/lib + ) + +if(LIBBLADERF_INCLUDE_DIRS AND LIBBLADERF_LIBRARIES) + set(LIBBLADERF_FOUND TRUE CACHE INTERNAL "libbladeRF found") + message(STATUS "Found libbladeRF: ${LIBBLADERF_INCLUDE_DIRS}, ${LIBBLADERF_LIBRARIES}") +else(LIBBLADERF_INCLUDE_DIRS AND LIBBLADERF_LIBRARIES) + set(LIBBLADERF_FOUND FALSE CACHE INTERNAL "libbladeRF found") + message(STATUS "libbladeRF not found.") +endif(LIBBLADERF_INCLUDE_DIRS AND LIBBLADERF_LIBRARIES) + +mark_as_advanced(LIBBLADERF_LIBRARIES LIBBLADERF_INCLUDE_DIRS) + +endif(NOT LIBBLADERF_FOUND) diff --git a/cmake/Modules/FindMbedTLS.cmake b/cmake/Modules/FindMbedTLS.cmake new file mode 100755 index 0000000..5f9ab86 --- /dev/null +++ b/cmake/Modules/FindMbedTLS.cmake @@ -0,0 +1,47 @@ +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_MBEDTLS mbedtls) + +FIND_PATH( + MBEDTLS_INCLUDE_DIRS + NAMES mbedtls/version.h + HINTS $ENV{MBEDTLS_DIR}/include + ${PC_MBEDTLS_INCLUDEDIR} + ${CMAKE_INSTALL_PREFIX}/include + PATHS /usr/local/include + /usr/include +) + +FIND_LIBRARY( + MBEDTLS_LIBRARY + NAMES mbedtls + HINTS $ENV{MBEDTLS_DIR}/lib + ${PC_MBEDTLS_LIBDIR} + ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib64 + PATHS /usr/local/lib + /usr/local/lib64 + /usr/lib + /usr/lib64 +) + +FIND_LIBRARY( + MBEDCRYPTO_LIBRARY + NAMES mbedcrypto + HINTS $ENV{MBEDTLS_DIR}/lib + ${PC_MBEDTLS_LIBDIR} + ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib64 + PATHS /usr/local/lib + /usr/local/lib64 + /usr/lib + /usr/lib64 +) + +set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDCRYPTO_LIBRARY}) + +message(STATUS "MBEDTLS LIBRARIES " ${MBEDTLS_LIBRARIES}) +message(STATUS "MBEDTLS INCLUDE DIRS " ${MBEDTLS_INCLUDE_DIRS}) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(MBEDTLS DEFAULT_MSG MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) +MARK_AS_ADVANCED(MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) diff --git a/cmake/Modules/FindUhd.cmake b/cmake/Modules/FindUhd.cmake old mode 100644 new mode 100755 diff --git a/cmake/Modules/GrMiscUtils.cmake b/cmake/Modules/GrMiscUtils.cmake old mode 100644 new mode 100755 diff --git a/cmake/Modules/GrPlatform.cmake b/cmake/Modules/GrPlatform.cmake old mode 100644 new mode 100755 diff --git a/cmake/Modules/GrPython.cmake b/cmake/Modules/GrPython.cmake old mode 100644 new mode 100755 diff --git a/cmake/Modules/GrSwig.cmake b/cmake/Modules/GrSwig.cmake old mode 100644 new mode 100755 diff --git a/cmake/cmake_uninstall.cmake.in b/cmake/cmake_uninstall.cmake.in old mode 100644 new mode 100755 diff --git a/enodeb_nat_script.sh b/enodeb_nat_script.sh new file mode 100755 index 0000000..b12a68b --- /dev/null +++ b/enodeb_nat_script.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# Determine which interface to use +iface=$(ifconfig | grep Ethernet | head -n1 | awk '{print $1}') +echo Using interface : $iface + +# Enable IPTABLES +tmp_ipt_en=$(cat /etc/sysctl.conf | grep -c -x net.ipv4.ip_forward=1) +if [ $tmp_ipt_en -eq 0 ]; then + printf "net.ipv4.ip_forward=1\n" >> /etc/sysctl.conf + sysctl -p /etc/sysctl.conf +fi +modprobe ip_tables +modprobe ip_conntrack + +# Setup IPTABLES +iptables -C FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +if [ $? -eq 1 ]; then + iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +fi +iptables -C FORWARD -i tun_openlte -o $iface -m conntrack --ctstate NEW -j ACCEPT +if [ $? -eq 1 ]; then + iptables -I FORWARD -i tun_openlte -o $iface -m conntrack --ctstate NEW -j ACCEPT +fi +iptables -t nat -C POSTROUTING -o $iface -j MASQUERADE +if [ $? -eq 1 ]; then + iptables -t nat -I POSTROUTING -o $iface -j MASQUERADE +fi +iptables-save > /etc/iptables_openlte.rules +printf "#!/bin/sh\niptables-restore < /etc/iptables_openlte.rules\nexit 0\n" > /etc/network/if-up.d/iptablesload +chmod +x /etc/network/if-up.d/iptablesload + +# Give cap_net_admin capabilities to LTE_fdd_enodeb +tmp_loc=$(which LTE_fdd_enodeb) +setcap cap_net_admin=eip $tmp_loc + +# Give global read/write permissions to /dev/net/tun +chmod 666 /dev/net/tun + +# Remove all shared memories for message queues +rm -f /dev/shm/*_olmq diff --git a/liblte/CMakeLists.txt b/liblte/CMakeLists.txt old mode 100644 new mode 100755 index ba25b4a..78600e4 --- a/liblte/CMakeLists.txt +++ b/liblte/CMakeLists.txt @@ -1,10 +1,19 @@ include(GrPlatform) add_library(lte + src/liblte_common.cc src/liblte_interface.cc src/liblte_phy.cc src/liblte_mac.cc src/liblte_rlc.cc + src/liblte_pdcp.cc src/liblte_rrc.cc src/liblte_mme.cc + src/liblte_security.cc ) include_directories(hdr ${CMAKE_SOURCE_DIR}/cmn_hdr) + +add_executable(liblte_common_test + tests/liblte_common_tests.cc + src/liblte_common.cc +) +add_test(liblte_common_test liblte_common_test) diff --git a/liblte/hdr/liblte_common.h b/liblte/hdr/liblte_common.h old mode 100644 new mode 100755 index 20bbade..cf5abf3 --- a/liblte/hdr/liblte_common.h +++ b/liblte/hdr/liblte_common.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2012-2014 Ben Wojtowicz + Copyright 2012-2016 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +27,12 @@ 07/21/2013 Ben Wojtowicz Added a common message structure. 06/15/2014 Ben Wojtowicz Split LIBLTE_MSG_STRUCT into bit and byte aligned messages. + 08/03/2014 Ben Wojtowicz Commonized value_2_bits and bits_2_value. + 11/29/2014 Ben Wojtowicz Added liblte prefix to value_2_bits and + bits_2_value. + 07/14/2015 Ben Wojtowicz Added an error code for DCIs with invalid + contents. + 07/03/2016 Ben Wojtowicz Increased the maximum message size. *******************************************************************************/ @@ -45,7 +51,7 @@ *******************************************************************************/ // FIXME: This was chosen arbitrarily -#define LIBLTE_MAX_MSG_SIZE 4096 +#define LIBLTE_MAX_MSG_SIZE 5512 /******************************************************************************* TYPEDEFS @@ -56,6 +62,7 @@ typedef enum{ LIBLTE_ERROR_INVALID_INPUTS, LIBLTE_ERROR_DECODE_FAIL, LIBLTE_ERROR_INVALID_CRC, + LIBLTE_ERROR_INVALID_CONTENTS, }LIBLTE_ERROR_ENUM; typedef struct{ @@ -72,4 +79,21 @@ typedef struct{ DECLARATIONS *******************************************************************************/ +/********************************************************************* + Name: liblte_value_2_bits + + Description: Converts a value to a bit string +*********************************************************************/ +void liblte_value_2_bits(uint32 value, + uint8 **bits, + uint32 N_bits); + +/********************************************************************* + Name: liblte_bits_2_value + + Description: Converts a bit string to a value +*********************************************************************/ +uint32 liblte_bits_2_value(uint8 **bits, + uint32 N_bits); + #endif /* __LIBLTE_COMMON_H__ */ diff --git a/liblte/hdr/liblte_interface.h b/liblte/hdr/liblte_interface.h old mode 100644 new mode 100755 index d3c8948..aa6be22 --- a/liblte/hdr/liblte_interface.h +++ b/liblte/hdr/liblte_interface.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013 Ben Wojtowicz + Copyright 2013, 2016 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -26,6 +26,8 @@ 02/23/2013 Ben Wojtowicz Created file 11/13/2013 Ben Wojtowicz Added functions for getting corresponding EARFCNs for FDD configuration + 12/18/2016 Ben Wojtowicz Added support for band 26, 26, and 28 (thanks + to Jeremy Quirke). *******************************************************************************/ @@ -57,7 +59,7 @@ Description: Defines the operating frequency bands. - Document Reference: 36.101 v10.4.0 Section 5.5 + Document Reference: 36.101 v11.2.0 Section 5.5 *********************************************************************/ // Defines // Enums @@ -85,6 +87,9 @@ typedef enum{ LIBLTE_INTERFACE_BAND_23, LIBLTE_INTERFACE_BAND_24, LIBLTE_INTERFACE_BAND_25, + LIBLTE_INTERFACE_BAND_26, + LIBLTE_INTERFACE_BAND_27, + LIBLTE_INTERFACE_BAND_28, LIBLTE_INTERFACE_BAND_33, LIBLTE_INTERFACE_BAND_34, LIBLTE_INTERFACE_BAND_35, @@ -103,12 +108,14 @@ static const char liblte_interface_band_text[LIBLTE_INTERFACE_BAND_N_ITEMS][20] "9", "10", "11", "12", "13", "14", "17", "18", "19", "20", "21", "22", - "23", "24", "25", "33", - "34", "35", "36", "37", - "38", "39", "40", "41", - "42", "43"}; + "23", "24", "25", "26", + "27", "28", "33", "34", + "35", "36", "37", "38", + "39", "40", "41", "42", + "43"}; static const uint8 liblte_interface_band_num[LIBLTE_INTERFACE_BAND_N_ITEMS] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43}; + 20, 21, 22, 23, 24, 25, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43}; // Structs // Functions @@ -118,20 +125,30 @@ static const uint8 liblte_interface_band_num[LIBLTE_INTERFACE_BAND_N_ITEMS] = { Description: Defines the downlink E-UTRA Absolute Radio Frequency Channel Number. - Document Reference: 36.101 v10.4.0 Section 5.7.3 + Document Reference: 36.101 v11.2.0 Section 5.7.3 *********************************************************************/ // Defines #define LIBLTE_INTERFACE_DL_EARFCN_INVALID 65535 -static const uint16 liblte_interface_first_dl_earfcn[LIBLTE_INTERFACE_BAND_N_ITEMS] = { 25, 607, 1207, 1957, 2407, 2675, 2775, 3457, - 3825, 4175, 4775, 5017, 5205, 5305, 5755, 5875, - 6025, 6175, 6475, 6625, 7507, 7725, 8047, 36025, - 36225, 36357, 36957, 37575, 37775, 38275, 38675, 39675, - 41615, 43615}; -static const uint16 liblte_interface_last_dl_earfcn[LIBLTE_INTERFACE_BAND_N_ITEMS] = { 575, 1193, 1943, 2393, 2643, 2725, 3425, 3793, - 4125, 4725, 4925, 5173, 5255, 5355, 5825, 5975, - 6125, 6425, 6575, 7375, 7693, 8015, 8683, 36175, - 36325, 36943, 37543, 37725, 38225, 38625, 39625, 41565, - 43565, 45565}; +static const uint16 liblte_interface_first_dl_earfcn[LIBLTE_INTERFACE_BAND_N_ITEMS] = { 0 + 25, 600 + 7, 1200 + 7, 1950 + 7, + 2400 + 7, 2650 + 25, 2750 + 25, 3450 + 7, + 3800 + 25, 4150 + 25, 4750 + 25, 5010 + 7, + 5180 + 25, 5280 + 25, 5730 + 25, 5850 + 25, + 6000 + 25, 6150 + 25, 6450 + 25, 6600 + 25, + 7500 + 7, 7700 + 25, 8040 + 7, 8690 + 7, + 9040 + 7, 9210 + 15, 36000 + 25, 36200 + 25, + 36350 + 7, 36950 + 7, 37550 + 25, 37750 + 25, + 38250 + 25, 38650 + 25, 39650 + 25, 41590 + 25, + 43590 + 25}; +static const uint16 liblte_interface_last_dl_earfcn[LIBLTE_INTERFACE_BAND_N_ITEMS] = { 600 - 25, 1200 - 7, 1950 - 7, 2400 - 7, + 2650 - 7, 2750 - 25, 3450 - 25, 3800 - 7, + 4150 - 25, 4750 - 25, 4950 - 25, 5180 - 7, + 5280 - 25, 5380 - 25, 5850 - 25, 6000 - 25, + 6150 - 25, 6450 - 25, 6600 - 25, 7400 - 25, + 7700 - 7, 8040 - 25, 8690 - 7, 9040 - 7, + 9210 - 7, 9660 - 15, 36200 - 25, 36350 - 25, + 36950 - 7, 37550 - 7, 37750 - 25, 38250 - 25, + 38650 - 25, 39650 - 25, 41590 - 25, 43590 - 25, + 45590 - 25}; // Enums // Structs // Functions @@ -144,20 +161,30 @@ uint16 liblte_interface_get_corresponding_dl_earfcn(uint16 ul_earfcn); Description: Defines the uplink E-UTRA Absolute Radio Frequency Channel Number. - Document Reference: 36.101 v10.4.0 Section 5.7.3 + Document Reference: 36.101 v11.2.0 Section 5.7.3 *********************************************************************/ // Defines #define LIBLTE_INTERFACE_UL_EARFCN_INVALID 65535 -static const uint16 liblte_interface_first_ul_earfcn[LIBLTE_INTERFACE_BAND_N_ITEMS] = {18025, 18607, 19207, 19957, 20407, 20675, 20775, 21457, - 21825, 22175, 22775, 23017, 23205, 23305, 23755, 23875, - 24025, 24175, 24475, 24625, 25507, 25725, 26047, 36025, - 36225, 36357, 36957, 37575, 37775, 38275, 38675, 39675, - 41615, 43615}; -static const uint16 liblte_interface_last_ul_earfcn[LIBLTE_INTERFACE_BAND_N_ITEMS] = {18575, 19193, 19943, 20393, 20643, 20725, 21425, 21793, - 22125, 22725, 22925, 23173, 23255, 23355, 23825, 23975, - 24125, 24425, 24575, 25375, 25693, 26015, 26683, 36175, - 36325, 36943, 37543, 37725, 38225, 38625, 39625, 41565, - 43565, 45565}; +static const uint16 liblte_interface_first_ul_earfcn[LIBLTE_INTERFACE_BAND_N_ITEMS] = {18000 + 25, 18600 + 7, 19200 + 7, 19950 + 7, + 20400 + 7, 20650 + 25, 20750 + 25, 21450 + 7, + 21800 + 25, 22150 + 25, 22750 + 25, 23010 + 7, + 23180 + 25, 23280 + 25, 23730 + 25, 23850 + 25, + 24000 + 25, 24150 + 25, 24450 + 25, 24600 + 25, + 25500 + 7, 25700 + 25, 26040 + 7, 26690 + 7, + 27040 + 7, 27210 + 7, 36000 + 25, 36200 + 25, + 36350 + 7, 36950 + 7, 37550 + 25, 37750 + 25, + 38250 + 25, 38650 + 25, 39650 + 25, 41590 + 25, + 43590 + 25}; +static const uint16 liblte_interface_last_ul_earfcn[LIBLTE_INTERFACE_BAND_N_ITEMS] = {18600 - 25, 19200 - 7, 19950 - 7, 20400 - 7, + 20650 - 7, 20750 - 25, 21450 - 25, 21800 - 7, + 22150 - 25, 22750 - 25, 22950 - 25, 23180 - 7, + 23280 - 25, 23380 - 25, 23850 - 25, 24000 - 25, + 24150 - 25, 24450 - 25, 24600 - 25, 25400 - 25, + 25700 - 7, 26040 - 25, 26690 - 7, 27040 - 7, + 27210 - 7, 27660 - 15, 36200 - 25, 36350 - 25, + 36950 - 7, 37550 - 7, 37750 - 25, 38250 - 25, + 38650 - 25, 39650 - 25, 41590 - 25, 43590 - 25, + 45590 - 25}; // Enums // Structs // Functions diff --git a/liblte/hdr/liblte_mac.h b/liblte/hdr/liblte_mac.h old mode 100644 new mode 100755 index bb9e157..2d01f57 --- a/liblte/hdr/liblte_mac.h +++ b/liblte/hdr/liblte_mac.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2016 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -29,6 +29,11 @@ 05/04/2014 Ben Wojtowicz Added control element handling. 06/15/2014 Ben Wojtowicz Added support for padding LCIDs and breaking out max and min buffer sizes for BSRs. + 11/29/2014 Ben Wojtowicz Using byte message struct for SDUs. + 02/15/2015 Ben Wojtowicz Removed FIXME for transparent mode. + 03/11/2015 Ben Wojtowicz Fixed long BSR CE and added extended power + headroom CE support. + 07/03/2016 Ben Wojtowicz Fixed extended power headroom CE. *******************************************************************************/ @@ -118,10 +123,14 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_short_bsr_ce(uint8 // Enums // Structs typedef struct{ - uint8 buffer_size_0; - uint8 buffer_size_1; - uint8 buffer_size_2; - uint8 buffer_size_3; + uint8 max_buffer_size_0; + uint8 min_buffer_size_0; + uint8 max_buffer_size_1; + uint8 min_buffer_size_1; + uint8 max_buffer_size_2; + uint8 min_buffer_size_2; + uint8 max_buffer_size_3; + uint8 min_buffer_size_3; }LIBLTE_MAC_LONG_BSR_CE_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mac_pack_long_bsr_ce(LIBLTE_MAC_LONG_BSR_CE_STRUCT *long_bsr, @@ -229,12 +238,23 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_power_headroom_ce(uint8 // Enums // Structs typedef struct{ - // FIXME + uint8 ph; + uint8 p_cmax; + bool p; + bool v; +}LIBLTE_MAC_EPH_CELL_STRUCT; +typedef struct{ + LIBLTE_MAC_EPH_CELL_STRUCT pcell_type_1; + LIBLTE_MAC_EPH_CELL_STRUCT pcell_type_2; + LIBLTE_MAC_EPH_CELL_STRUCT scell[7]; + bool pcell_type_2_present; + bool scell_present[7]; }LIBLTE_MAC_EXT_POWER_HEADROOM_CE_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mac_pack_ext_power_headroom_ce(LIBLTE_MAC_EXT_POWER_HEADROOM_CE_STRUCT *ext_power_headroom, uint8 **ce_ptr); LIBLTE_ERROR_ENUM liblte_mac_unpack_ext_power_headroom_ce(uint8 **ce_ptr, + bool simultaneous_pucch_pusch, LIBLTE_MAC_EXT_POWER_HEADROOM_CE_STRUCT *ext_power_headroom); /********************************************************************* @@ -339,7 +359,7 @@ typedef union{ LIBLTE_MAC_EXT_POWER_HEADROOM_CE_STRUCT ext_power_headroom; LIBLTE_MAC_MCH_SCHEDULING_INFORMATION_CE_STRUCT mch_sched_info; LIBLTE_MAC_ACTIVATION_DEACTIVATION_CE_STRUCT act_deact; - LIBLTE_BIT_MSG_STRUCT sdu; + LIBLTE_BYTE_MSG_STRUCT sdu; }LIBLTE_MAC_SUBHEADER_PAYLOAD_UNION; typedef struct{ LIBLTE_MAC_SUBHEADER_PAYLOAD_UNION payload; @@ -354,6 +374,7 @@ typedef struct{ LIBLTE_ERROR_ENUM liblte_mac_pack_mac_pdu(LIBLTE_MAC_PDU_STRUCT *mac_pdu, LIBLTE_BIT_MSG_STRUCT *pdu); LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, + bool simultaneous_pucch_pusch, LIBLTE_MAC_PDU_STRUCT *mac_pdu); /********************************************************************* @@ -367,7 +388,6 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, // Enums // Structs // Functions -// FIXME /********************************************************************* PDU Name: Random Access Response @@ -424,10 +444,10 @@ typedef struct{ LIBLTE_MAC_RAR_TPC_COMMAND_ENUM tpc_command; LIBLTE_MAC_RAR_UL_DELAY_ENUM ul_delay; LIBLTE_MAC_RAR_CSI_REQ_ENUM csi_req; - uint16 rba; // FIXME + uint16 rba; uint16 timing_adv_cmd; uint16 temp_c_rnti; - uint8 mcs; // FIXME + uint8 mcs; uint8 RAPID; uint8 BI; }LIBLTE_MAC_RAR_STRUCT; diff --git a/liblte/hdr/liblte_mcc_mnc_list.h b/liblte/hdr/liblte_mcc_mnc_list.h old mode 100644 new mode 100755 diff --git a/liblte/hdr/liblte_mme.h b/liblte/hdr/liblte_mme.h old mode 100644 new mode 100755 index 39a8fcd..5482bfe --- a/liblte/hdr/liblte_mme.h +++ b/liblte/hdr/liblte_mme.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2014 Ben Wojtowicz + Copyright 2014-2016 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -25,6 +25,20 @@ Revision History ---------- ------------- -------------------------------------------- 06/15/2014 Ben Wojtowicz Created file. + 08/03/2014 Ben Wojtowicz Added more decoding/encoding. + 09/03/2014 Ben Wojtowicz Added more decoding/encoding. + 11/01/2014 Ben Wojtowicz Added more decoding/encoding. + 11/29/2014 Ben Wojtowicz Added more decoding/encoding. + 12/16/2014 Ben Wojtowicz Added more decoding/encoding. + 12/24/2014 Ben Wojtowicz Cleaned up the Time Zone and Time IE. + 02/15/2015 Ben Wojtowicz Added more decoding/encoding. + 07/25/2015 Ben Wojtowicz Removed rb_id from pack routines as + 33.401 section 8.1.1 specifies 0 as the + input to the security routines (credit goes + to Przemek Bereski for finding this). + 12/06/2015 Ben Wojtowicz Added all ID types for Mobile Identity IE. + 07/03/2016 Ben Wojtowicz Added classmark 3 IE and tracking area + update request message parsing. *******************************************************************************/ @@ -36,6 +50,7 @@ *******************************************************************************/ #include "liblte_common.h" +#include /******************************************************************************* DEFINES @@ -61,10 +76,18 @@ Document Reference: 24.301 v10.2.0 Section 9.9.2.0 *********************************************************************/ // Defines +#define LIBLTE_MME_ADDITIONAL_INFORMATION_MAX_N_OCTETS (LIBLTE_MAX_MSG_SIZE/2) // Enums // Structs +typedef struct{ + uint8 info[LIBLTE_MME_ADDITIONAL_INFORMATION_MAX_N_OCTETS]; + uint32 N_octets; +}LIBLTE_MME_ADDITIONAL_INFORMATION_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_additional_information_ie(LIBLTE_MME_ADDITIONAL_INFORMATION_STRUCT *add_info, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_information_ie(uint8 **ie_ptr, + LIBLTE_MME_ADDITIONAL_INFORMATION_STRUCT *add_info); /********************************************************************* IE Name: Device Properties @@ -104,8 +127,14 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_device_properties_ie(uint8 // Defines // Enums // Structs +typedef struct{ + bool ebi[16]; +}LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_bearer_context_status_ie(LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_STRUCT *ebcs, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_bearer_context_status_ie(uint8 **ie_ptr, + LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_STRUCT *ebcs); /********************************************************************* IE Name: Location Area Identification @@ -141,10 +170,34 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_location_area_id_ie(uint8 24.008 v10.2.0 Section 10.5.1.4 *********************************************************************/ // Defines +#define LIBLTE_MME_MOBILE_ID_TYPE_IMSI 0x1 +#define LIBLTE_MME_MOBILE_ID_TYPE_IMEI 0x2 +#define LIBLTE_MME_MOBILE_ID_TYPE_IMEISV 0x3 +#define LIBLTE_MME_MOBILE_ID_TYPE_TMSI 0x4 +#define LIBLTE_MME_MOBILE_ID_TYPE_TMGI 0x5 // Enums // Structs +typedef struct{ + uint32 mbms_service_id; + uint16 mcc; + uint16 mnc; + uint8 mbms_session_id; + bool mbms_session_id_ind; + bool mcc_mnc_ind; +}LIBLTE_MME_MOBILE_ID_TMGI_STRUCT; +typedef struct{ + LIBLTE_MME_MOBILE_ID_TMGI_STRUCT tmgi; + uint32 tmsi; + uint8 type_of_id; + uint8 imsi[15]; + uint8 imei[15]; + uint8 imeisv[16]; +}LIBLTE_MME_MOBILE_ID_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_mobile_id_ie(LIBLTE_MME_MOBILE_ID_STRUCT *mobile_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_id_ie(uint8 **ie_ptr, + LIBLTE_MME_MOBILE_ID_STRUCT *mobile_id); /********************************************************************* IE Name: Mobile Station Classmark 2 @@ -157,9 +210,60 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_location_area_id_ie(uint8 *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_MME_REVISION_LEVEL_GSM_PHASE_1 = 0, + LIBLTE_MME_REVISION_LEVEL_GSM_PHASE_2, + LIBLTE_MME_REVISION_LEVEL_R99, + LIBLTE_MME_REVISION_LEVEL_RESERVED, + LIBLTE_MME_REVISION_LEVEL_N_ITEMS, +}LIBLTE_MME_REVISION_LEVEL_ENUM; +static const char liblte_mme_revision_level_text[LIBLTE_MME_REVISION_LEVEL_N_ITEMS][20] = {"GSM Phase 1", + "GSM Phase 2", + "R99", + "RESERVED"}; +typedef enum{ + LIBLTE_MME_RF_POWER_CAPABILITY_CLASS_1 = 0, + LIBLTE_MME_RF_POWER_CAPABILITY_CLASS_2, + LIBLTE_MME_RF_POWER_CAPABILITY_CLASS_3, + LIBLTE_MME_RF_POWER_CAPABILITY_CLASS_4, + LIBLTE_MME_RF_POWER_CAPABILITY_CLASS_5, + LIBLTE_MME_RF_POWER_CAPABILITY_N_ITEMS, +}LIBLTE_MME_RF_POWER_CAPABILITY_ENUM; +static const char liblte_mme_rf_power_capability_text[LIBLTE_MME_RF_POWER_CAPABILITY_N_ITEMS][20] = {"Class 1", + "Class 2", + "Class 3", + "Class 4", + "Class 5"}; +typedef enum{ + LIBLTE_MME_SS_SCREEN_INDICATOR_0 = 0, + LIBLTE_MME_SS_SCREEN_INDICATOR_1, + LIBLTE_MME_SS_SCREEN_INDICATOR_2, + LIBLTE_MME_SS_SCREEN_INDICATOR_3, + LIBLTE_MME_SS_SCREEN_INDICATOR_N_ITEMS, +}LIBLTE_MME_SS_SCREEN_INDICATOR_ENUM; +static const char liblte_mme_ss_screen_indicator_text[LIBLTE_MME_SS_SCREEN_INDICATOR_N_ITEMS][100] = {"Default Phase 1", + "Ellipsis Notation Phase 2", + "RESERVED", + "RESERVED"}; // Structs typedef struct{ - // FIXME + LIBLTE_MME_REVISION_LEVEL_ENUM rev_lev; + LIBLTE_MME_RF_POWER_CAPABILITY_ENUM rf_power_cap; + LIBLTE_MME_SS_SCREEN_INDICATOR_ENUM ss_screen_ind; + bool es_ind; + bool a5_1; + bool ps_cap; + bool sm_cap; + bool vbs; + bool vgcs; + bool fc; + bool cm3; + bool lcsva_cap; + bool ucs2; + bool solsa; + bool cmsp; + bool a5_3; + bool a5_2; }LIBLTE_MME_MOBILE_STATION_CLASSMARK_2_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_mobile_station_classmark_2_ie(LIBLTE_MME_MOBILE_STATION_CLASSMARK_2_STRUCT *ms_cm2, @@ -180,7 +284,117 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_station_classmark_2_ie(uint8 // Enums // Structs typedef struct{ - // FIXME + uint8 assoc_radio_cap_2; + uint8 assoc_radio_cap_1; + bool pgsm_support; + bool e_rgsm_support; + bool gsm_1800_support; + bool a5_7; + bool a5_6; + bool a5_5; + bool a5_4; +}LIBLTE_MME_MULTI_BAND_SUPPORT_STRUCT; +typedef struct{ + uint8 sms_value; + uint8 sm_value; +}LIBLTE_MME_MS_MEASUREMENT_CAPABILITY_STRUCT; +typedef struct{ + uint8 eight_psk_rf_power_cap_1; + uint8 eight_psk_rf_power_cap_2; + bool modulation_cap; + bool eight_psk_rf_power_cap_1_present; + bool eight_psk_rf_power_cap_2_present; +}LIBLTE_MME_8PSK_STRUCT; +typedef struct{ + uint8 assoc_radio_cap; + bool gsm450_support; + bool gsm480_support; +}LIBLTE_MME_GSM400_SUPPORT_STRUCT; +typedef struct{ + uint8 dtm_gprs_multi_slot_class; + uint8 dtm_egprs_multi_slot_class; + bool single_slot_dtm; + bool dtm_egprs_multi_slot_class_present; +}LIBLTE_MME_DUAL_TRANSFER_MODE_STRUCT; +typedef struct{ + uint8 extended_dtm_gprs_multi_slot_class; + uint8 extended_dtm_egprs_multi_slot_class; +}LIBLTE_MME_EXTENDED_DUAL_TRANSFER_MODE_STRUCT; +typedef struct{ + bool flo_iu_cap; +}LIBLTE_MME_GERAN_IU_MODE_CAPABILITIES_STRUCT; +typedef struct{ + uint8 assoc_radio_cap; + bool tgsm_410_support; + bool tgsm_380_support; +}LIBLTE_MME_TGSM400_SUPPORT_STRUCT; +typedef struct{ + uint8 dtm_gprs_high_multi_slot_class; + uint8 dtm_egprs_high_multi_slot_class; + bool offset_required; + bool dtm_egprs_high_multi_slot_class_present; +}LIBLTE_MME_DUAL_TRANSFER_MODE_HIGH_MULTI_SLOT_STRUCT; +typedef struct{ + LIBLTE_MME_MULTI_BAND_SUPPORT_STRUCT multi_band_support; + LIBLTE_MME_MS_MEASUREMENT_CAPABILITY_STRUCT ms_meas_cap; + LIBLTE_MME_8PSK_STRUCT eight_psk; + LIBLTE_MME_GSM400_SUPPORT_STRUCT gsm400_support; + LIBLTE_MME_DUAL_TRANSFER_MODE_STRUCT dtm; + LIBLTE_MME_EXTENDED_DUAL_TRANSFER_MODE_STRUCT ext_dtm; + LIBLTE_MME_GERAN_IU_MODE_CAPABILITIES_STRUCT geran_iu_mode_cap; + LIBLTE_MME_TGSM400_SUPPORT_STRUCT tgsm400_support; + LIBLTE_MME_DUAL_TRANSFER_MODE_HIGH_MULTI_SLOT_STRUCT dtm_high_multi_slot; + uint8 r_support; + uint8 hscsd_multi_slot_cap; + uint8 ms_pos_method_cap; + uint8 ecsd_multi_slot_cap; + uint8 gsm850_assoc_radio_cap; + uint8 gsm1900_assoc_radio_cap; + uint8 single_band_support; + uint8 gsm750_assoc_radio_cap; + uint8 high_multi_slot_cap; + uint8 gmsk_multi_slot_power_profile; + uint8 eight_psk_multi_slot_power_profile; + uint8 darp; + uint8 gsm710_assoc_radio_cap; + uint8 tgsm810_assoc_radio_cap; + uint8 vamos_level; + bool r_support_present; + bool hscsd_multi_slot_cap_present; + bool ucs2_treatment; + bool ext_meas_cap; + bool ms_meas_cap_present; + bool ms_pos_method_cap_present; + bool ecsd_multi_slot_cap_present; + bool eight_psk_present; + bool gsm400_support_present; + bool gsm850_assoc_radio_cap_present; + bool gsm1900_assoc_radio_cap_present; + bool umts_fdd_rat_cap; + bool umts_3_84_mcps_tdd_rat_cap; + bool cdma2000_rat_cap; + bool dtm_present; + bool single_band_support_present; + bool gsm750_assoc_radio_cap_present; + bool umts_1_28_mcps_tdd_rat_cap; + bool geran_feature_package; + bool ext_dtm_present; + bool high_multi_slot_cap_present; + bool geran_iu_mode_cap_present; + bool geran_feature_package_2; + bool tgsm400_support_present; + bool dtm_enhancements_cap; + bool dtm_high_multi_slot_present; + bool repeated_acch_cap; + bool gsm710_assoc_radio_cap_present; + bool tgsm810_assoc_radio_cap_present; + bool ciphering_mode_setting_cap; + bool additional_pos_cap; + bool eutra_fdd_support; + bool eutra_tdd_support; + bool eutra_meas_and_reporting_support; + bool prio_based_reselection_support; + bool utra_csg_cells_reporting; }LIBLTE_MME_MOBILE_STATION_CLASSMARK_3_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_mobile_station_classmark_3_ie(LIBLTE_MME_MOBILE_STATION_CLASSMARK_3_STRUCT *ms_cm3, @@ -200,7 +414,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_station_classmark_3_ie(uint8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_nas_security_parameters_from_eutra_ie(uint8 dl_nas_count, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_security_parameters_from_eutra_ie(uint8 **ie_ptr, + uint8 *dl_nas_count); /********************************************************************* IE Name: NAS Security Parameters To E-UTRA @@ -214,9 +431,64 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_station_classmark_3_ie(uint8 *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_EIA0 = 0, + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_128_EIA1, + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_128_EIA2, + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_EIA3, + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_EIA4, + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_EIA5, + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_EIA6, + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_EIA7, + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_N_ITEMS, +}LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM; +static const char liblte_mme_type_of_integrity_algorithm_text[LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_N_ITEMS][20] = {"EIA0", + "128-EIA1", + "128-EIA2", + "EIA3", + "EIA4", + "EIA5", + "EIA6", + "EIA7"}; +typedef enum{ + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_EEA0 = 0, + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_128_EEA1, + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_128_EEA2, + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_EEA3, + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_EEA4, + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_EEA5, + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_EEA6, + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_EEA7, + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_N_ITEMS, +}LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM; +static const char liblte_mme_type_of_ciphering_algorithm_text[LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_N_ITEMS][20] = {"EEA0", + "128-EEA1", + "128-EEA2", + "EEA3", + "EEA4", + "EEA5", + "EEA6", + "EEA7"}; +typedef enum{ + LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE = 0, + LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_MAPPED, + LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_N_ITEMS, +}LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM; +static const char liblte_mme_type_of_security_context_flag_text[LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_N_ITEMS][20] = {"Native", + "Mapped"}; // Structs +typedef struct{ + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM eea; + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM eia; + LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM tsc_flag; + uint32 nonce_mme; + uint8 nas_ksi; +}LIBLTE_MME_NAS_SECURITY_PARAMETERS_TO_EUTRA_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_nas_security_parameters_to_eutra_ie(LIBLTE_MME_NAS_SECURITY_PARAMETERS_TO_EUTRA_STRUCT *sec_params, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_security_parameters_to_eutra_ie(uint8 **ie_ptr, + LIBLTE_MME_NAS_SECURITY_PARAMETERS_TO_EUTRA_STRUCT *sec_params); /********************************************************************* IE Name: PLMN List @@ -227,10 +499,19 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_station_classmark_3_ie(uint8 24.008 v10.2.0 Section 10.5.1.13 *********************************************************************/ // Defines +#define LIBLTE_MME_PLMN_LIST_MAX_SIZE 15 // Enums // Structs +typedef struct{ + uint32 N_plmns; + uint16 mcc[LIBLTE_MME_PLMN_LIST_MAX_SIZE]; + uint16 mnc[LIBLTE_MME_PLMN_LIST_MAX_SIZE]; +}LIBLTE_MME_PLMN_LIST_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_plmn_list_ie(LIBLTE_MME_PLMN_LIST_STRUCT *plmn_list, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_plmn_list_ie(uint8 **ie_ptr, + LIBLTE_MME_PLMN_LIST_STRUCT *plmn_list); /********************************************************************* IE Name: Spare Half Octet @@ -245,7 +526,6 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_station_classmark_3_ie(uint8 // Enums // Structs // Functions -// FIXME /********************************************************************* IE Name: Supported Codec List @@ -257,10 +537,16 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_station_classmark_3_ie(uint8 24.008 v10.2.0 Section 10.5.4.32 *********************************************************************/ // Defines +#define LIBLTE_MME_MAX_N_SUPPORTED_CODECS (LIBLTE_MAX_MSG_SIZE/16) // Enums // Structs typedef struct{ - // FIXME + uint8 sys_id; + uint16 codec_bitmap; +}LIBLTE_MME_SUPPORTED_CODEC_STRUCT; +typedef struct{ + LIBLTE_MME_SUPPORTED_CODEC_STRUCT supported_codec[LIBLTE_MME_MAX_N_SUPPORTED_CODECS]; + uint32 N_supported_codecs; }LIBLTE_MME_SUPPORTED_CODEC_LIST_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_supported_codec_list_ie(LIBLTE_MME_SUPPORTED_CODEC_LIST_STRUCT *supported_codec_list, @@ -279,9 +565,25 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_supported_codec_list_ie(uint8 *********************************************************************/ // Defines // Enums -// Structs -// Functions -// FIXME +typedef enum{ + LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_NO_ADDITIONAL_INFO = 0, + LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_CS_FALLBACK_NOT_PREFERRED, + LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_SMS_ONLY, + LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_RESERVED, + LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_N_ITEMS, +}LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM; +static const char liblte_mme_additional_update_result_text[LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_N_ITEMS][100] = {"No Additional Information", + "CS Fallback Not Preferred", + "SMS Only", + "RESERVED"}; +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_additional_update_result_ie(LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM result, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_result_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM *result); /********************************************************************* IE Name: Additional Update Type @@ -325,7 +627,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_type_ie(uint8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_failure_parameter_ie(uint8 *auth_fail_param, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_failure_parameter_ie(uint8 **ie_ptr, + uint8 *auth_fail_param); /********************************************************************* IE Name: Authentication Parameter AUTN @@ -340,7 +645,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_type_ie(uint8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_parameter_autn_ie(uint8 *autn, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_parameter_autn_ie(uint8 **ie_ptr, + uint8 *autn); /********************************************************************* IE Name: Authentication Parameter RAND @@ -359,7 +667,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_type_ie(uint8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_parameter_rand_ie(uint8 *rand_val, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_parameter_rand_ie(uint8 **ie_ptr, + uint8 *rand_val); /********************************************************************* IE Name: Authentication Response Parameter @@ -373,7 +684,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_type_ie(uint8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_response_parameter_ie(uint8 *res, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_response_parameter_ie(uint8 **ie_ptr, + uint8 *res); /********************************************************************* IE Name: Ciphering Key Sequence Number @@ -389,7 +703,12 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_type_ie(uint8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_ciphering_key_sequence_number_ie(uint8 key_seq, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_ciphering_key_sequence_number_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *key_seq); /********************************************************************* IE Name: CSFB Response @@ -400,24 +719,45 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_type_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.3.5 *********************************************************************/ // Defines +#define LIBLTE_MME_CSFB_REJECTED_BY_THE_UE 0x0 +#define LIBLTE_MME_CSFB_ACCEPTED_BY_THE_UE 0x1 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_csfb_response_ie(uint8 csfb_resp, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_csfb_response_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *csfb_resp); /********************************************************************* - IE Name: Daylight Savings Time + IE Name: Daylight Saving Time - Description: Encodes the daylight savings time in steps of 1 hour. + Description: Encodes the daylight saving time in steps of 1 hour. Document Reference: 24.301 v10.2.0 Section 9.9.3.6 24.008 v10.2.0 Section 10.5.3.12 *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_MME_DAYLIGHT_SAVING_TIME_NO_ADJUSTMENT = 0, + LIBLTE_MME_DAYLIGHT_SAVING_TIME_PLUS_ONE_HOUR, + LIBLTE_MME_DAYLIGHT_SAVING_TIME_PLUS_TWO_HOURS, + LIBLTE_MME_DAYLIGHT_SAVING_TIME_RESERVED, + LIBLTE_MME_DAYLIGHT_SAVING_TIME_N_ITEMS, +}LIBLTE_MME_DAYLIGHT_SAVING_TIME_ENUM; +static const char liblte_mme_daylight_saving_time_text[LIBLTE_MME_DAYLIGHT_SAVING_TIME_N_ITEMS][20] = {"No Adjustment", + "+1 Hour", + "+2 Hours", + "RESERVED"}; // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_daylight_saving_time_ie(LIBLTE_MME_DAYLIGHT_SAVING_TIME_ENUM dst, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_daylight_saving_time_ie(uint8 **ie_ptr, + LIBLTE_MME_DAYLIGHT_SAVING_TIME_ENUM *dst); /********************************************************************* IE Name: Detach Type @@ -427,10 +767,27 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_type_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.3.7 *********************************************************************/ // Defines +#define LIBLTE_MME_SO_FLAG_NORMAL_DETACH 0 +#define LIBLTE_MME_SO_FLAG_SWITCH_OFF 1 +#define LIBLTE_MME_TOD_UL_EPS_DETACH 0x1 +#define LIBLTE_MME_TOD_UL_IMSI_DETACH 0x2 +#define LIBLTE_MME_TOD_UL_COMBINED_DETACH 0x3 +#define LIBLTE_MME_TOD_DL_REATTACH_REQUIRED 0x1 +#define LIBLTE_MME_TOD_DL_REATTACH_NOT_REQUIRED 0x2 +#define LIBLTE_MME_TOD_DL_IMSI_DETACH 0x3 // Enums // Structs +typedef struct{ + uint8 switch_off; + uint8 type_of_detach; +}LIBLTE_MME_DETACH_TYPE_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_detach_type_ie(LIBLTE_MME_DETACH_TYPE_STRUCT *detach_type, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_detach_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_DETACH_TYPE_STRUCT *detach_type); /********************************************************************* IE Name: DRX Parameter @@ -442,9 +799,31 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_type_ie(uint8 *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_MME_NON_DRX_TIMER_NO_NON_DRX_MODE = 0, + LIBLTE_MME_NON_DRX_TIMER_MAX_1S_NON_DRX_MODE, + LIBLTE_MME_NON_DRX_TIMER_MAX_2S_NON_DRX_MODE, + LIBLTE_MME_NON_DRX_TIMER_MAX_4S_NON_DRX_MODE, + LIBLTE_MME_NON_DRX_TIMER_MAX_8S_NON_DRX_MODE, + LIBLTE_MME_NON_DRX_TIMER_MAX_16S_NON_DRX_MODE, + LIBLTE_MME_NON_DRX_TIMER_MAX_32S_NON_DRX_MODE, + LIBLTE_MME_NON_DRX_TIMER_MAX_64S_NON_DRX_MODE, + LIBLTE_MME_NON_DRX_TIMER_N_ITEMS, +}LIBLTE_MME_NON_DRX_TIMER_ENUM; +static const char liblte_mme_non_drx_timer_text[LIBLTE_MME_NON_DRX_TIMER_N_ITEMS][100] = {"No Non-DRX Mode", + "Max 1s Non-DRX Mode", + "Max 2s Non-DRX Mode", + "Max 4s Non-DRX Mode", + "Max 8s Non-DRX Mode", + "Max 16s Non-DRX Mode", + "Max 32s Non-DRX Mode", + "Max 64s Non-DRX Mode"}; // Structs typedef struct{ - // FIXME + LIBLTE_MME_NON_DRX_TIMER_ENUM non_drx_timer; + uint8 split_pg_cycle_code; + uint8 drx_cycle_len_coeff_and_value; + bool split_on_ccch; }LIBLTE_MME_DRX_PARAMETER_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_drx_parameter_ie(LIBLTE_MME_DRX_PARAMETER_STRUCT *drx_param, @@ -461,10 +840,47 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_drx_parameter_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.3.9 *********************************************************************/ // Defines -// Enums -// Structs -// Functions -// FIXME +#define LIBLTE_MME_EMM_CAUSE_IMSI_UNKNOWN_IN_HSS 0x02 +#define LIBLTE_MME_EMM_CAUSE_ILLEGAL_UE 0x03 +#define LIBLTE_MME_EMM_CAUSE_IMEI_NOT_ACCEPTED 0x05 +#define LIBLTE_MME_EMM_CAUSE_ILLEGAL_ME 0x06 +#define LIBLTE_MME_EMM_CAUSE_EPS_SERVICES_NOT_ALLOWED 0x07 +#define LIBLTE_MME_EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED 0x08 +#define LIBLTE_MME_EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK 0x09 +#define LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED 0x0A +#define LIBLTE_MME_EMM_CAUSE_PLMN_NOT_ALLOWED 0x0B +#define LIBLTE_MME_EMM_CAUSE_TRACKING_AREA_NOT_ALLOWED 0x0C +#define LIBLTE_MME_EMM_CAUSE_ROAMING_NOT_ALLOWED_IN_THIS_TRACKING_AREA 0x0D +#define LIBLTE_MME_EMM_CAUSE_EPS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN 0x0E +#define LIBLTE_MME_EMM_CAUSE_NO_SUITABLE_CELLS_IN_TRACKING_AREA 0x0F +#define LIBLTE_MME_EMM_CAUSE_MSC_TEMPORARILY_NOT_REACHABLE 0x10 +#define LIBLTE_MME_EMM_CAUSE_NETWORK_FAILURE 0x11 +#define LIBLTE_MME_EMM_CAUSE_CS_DOMAIN_NOT_AVAILABLE 0x12 +#define LIBLTE_MME_EMM_CAUSE_ESM_FAILURE 0x13 +#define LIBLTE_MME_EMM_CAUSE_MAC_FAILURE 0x14 +#define LIBLTE_MME_EMM_CAUSE_SYNCH_FAILURE 0x15 +#define LIBLTE_MME_EMM_CAUSE_CONGESTION 0x16 +#define LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH 0x17 +#define LIBLTE_MME_EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED 0x18 +#define LIBLTE_MME_EMM_CAUSE_NOT_AUTHORIZED_FOR_THIS_CSG 0x19 +#define LIBLTE_MME_EMM_CAUSE_NON_EPS_AUTHENTICATION_UNACCEPTABLE 0x1A +#define LIBLTE_MME_EMM_CAUSE_CS_SERVICE_TEMPORARILY_NOT_AVAILABLE 0x27 +#define LIBLTE_MME_EMM_CAUSE_NO_EPS_BEARER_CONTEXT_ACTIVATED 0x28 +#define LIBLTE_MME_EMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE 0x5F +#define LIBLTE_MME_EMM_CAUSE_INVALID_MANDATORY_INFORMATION 0x60 +#define LIBLTE_MME_EMM_CAUSE_MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED 0x61 +#define LIBLTE_MME_EMM_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE 0x62 +#define LIBLTE_MME_EMM_CAUSE_INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT_IMPLEMENTED 0x63 +#define LIBLTE_MME_EMM_CAUSE_CONDITIONAL_IE_ERROR 0x64 +#define LIBLTE_MME_EMM_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE 0x65 +#define LIBLTE_MME_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED 0x6F +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_emm_cause_ie(uint8 emm_cause, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_emm_cause_ie(uint8 **ie_ptr, + uint8 *emm_cause); /********************************************************************* IE Name: EPS Attach Result @@ -474,10 +890,17 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_drx_parameter_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.3.10 *********************************************************************/ // Defines +#define LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY 0x1 +#define LIBLTE_MME_EPS_ATTACH_RESULT_COMBINED_EPS_IMSI_ATTACH 0x2 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_attach_result_ie(uint8 result, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_attach_result_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *result); /********************************************************************* IE Name: EPS Attach Type @@ -541,10 +964,33 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_mobile_id_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.3.12A *********************************************************************/ // Defines +#define LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_NOT_SUPPORTED 0 +#define LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_SUPPORTED 1 // Enums +typedef enum{ + LIBLTE_MME_CS_LCS_NO_INFORMATION_AVAILABLE = 0, + LIBLTE_MME_CS_LCS_NOT_SUPPORTED, + LIBLTE_MME_CS_LCS_SUPPORTED, + LIBLTE_MME_CS_LCS_RESERVED, + LIBLTE_MME_CS_LCS_N_ITEMS, +}LIBLTE_MME_CS_LCS_ENUM; +static const char liblte_mme_cs_lcs_text[LIBLTE_MME_CS_LCS_N_ITEMS][100] = {"No Information Available", + "Not Supported", + "Supported", + "RESERVED"}; // Structs +typedef struct{ + LIBLTE_MME_CS_LCS_ENUM cs_lcs; + bool esrps; + bool epc_lcs; + bool emc_bs; + bool ims_vops; +}LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_network_feature_support_ie(LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_STRUCT *eps_nfs, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_network_feature_support_ie(uint8 **ie_ptr, + LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_STRUCT *eps_nfs); /********************************************************************* IE Name: EPS Update Result @@ -555,10 +1001,19 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_mobile_id_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.3.13 *********************************************************************/ // Defines +#define LIBLTE_MME_EPS_UPDATE_RESULT_TA_UPDATED 0x0 +#define LIBLTE_MME_EPS_UPDATE_RESULT_COMBINED_TA_LA_UPDATED 0x1 +#define LIBLTE_MME_EPS_UPDATE_RESULT_TA_UPDATED_AND_ISR_ACTIVATED 0x4 +#define LIBLTE_MME_EPS_UPDATE_RESULT_COMBINED_TA_LA_UPDATED_AND_ISR_ACTIVATED 0x5 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_update_result_ie(uint8 eps_update_res, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_update_result_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *eps_update_res); /********************************************************************* IE Name: EPS Update Type @@ -570,9 +1025,29 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_mobile_id_ie(uint8 *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_MME_EPS_UPDATE_TYPE_TA_UPDATING = 0, + LIBLTE_MME_EPS_UPDATE_TYPE_COMBINED_TA_LA_UPDATING, + LIBLTE_MME_EPS_UPDATE_TYPE_COMBINED_TA_LA_UPDATING_WITH_IMSI_ATTACH, + LIBLTE_MME_EPS_UPDATE_TYPE_PERIODIC_UPDATING, + LIBLTE_MME_EPS_UPDATE_TYPE_N_ITEMS, +}LIBLTE_MME_EPS_UPDATE_TYPE_ENUM; +static const char liblte_mme_eps_update_type_text[LIBLTE_MME_EPS_UPDATE_TYPE_N_ITEMS][100] = {"TA Updating", + "Combined TA/LA Updating", + "Combined TA/LA Updating With IMSI Attach", + "Periodic Updating"}; // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_EPS_UPDATE_TYPE_ENUM type; + bool active_flag; +}LIBLTE_MME_EPS_UPDATE_TYPE_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_update_type_ie(LIBLTE_MME_EPS_UPDATE_TYPE_STRUCT *eps_update_type, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_update_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_EPS_UPDATE_TYPE_STRUCT *eps_update_type); /********************************************************************* IE Name: ESM Message Container @@ -600,10 +1075,21 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8 24.008 v10.2.0 Section 10.5.7.3 *********************************************************************/ // Defines +#define LIBLTE_MME_GPRS_TIMER_UNIT_2_SECONDS 0x0 +#define LIBLTE_MME_GPRS_TIMER_UNIT_1_MINUTE 0x1 +#define LIBLTE_MME_GPRS_TIMER_UNIT_6_MINUTES 0x2 +#define LIBLTE_MME_GPRS_TIMER_DEACTIVATED 0x7 // Enums // Structs +typedef struct{ + uint8 unit; + uint8 value; +}LIBLTE_MME_GPRS_TIMER_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_gprs_timer_ie(LIBLTE_MME_GPRS_TIMER_STRUCT *timer, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_gprs_timer_ie(uint8 **ie_ptr, + LIBLTE_MME_GPRS_TIMER_STRUCT *timer); /********************************************************************* IE Name: GPRS Timer 2 @@ -617,7 +1103,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_gprs_timer_2_ie(uint8 value, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_gprs_timer_2_ie(uint8 **ie_ptr, + uint8 *value); /********************************************************************* IE Name: GPRS Timer 3 @@ -628,10 +1117,21 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8 24.008 v10.2.0 Section 10.5.7.4A *********************************************************************/ // Defines +#define LIBLTE_MME_GPRS_TIMER_3_UNIT_10_MINUTES 0x0 +#define LIBLTE_MME_GPRS_TIMER_3_UNIT_1_HOUR 0x1 +#define LIBLTE_MME_GPRS_TIMER_3_UNIT_10_HOURS 0x2 +#define LIBLTE_MME_GPRS_TIMER_3_DEACTIVATED 0x7 // Enums // Structs +typedef struct{ + uint8 unit; + uint8 value; +}LIBLTE_MME_GPRS_TIMER_3_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_gprs_timer_3_ie(LIBLTE_MME_GPRS_TIMER_3_STRUCT *timer, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_gprs_timer_3_ie(uint8 **ie_ptr, + LIBLTE_MME_GPRS_TIMER_3_STRUCT *timer); /********************************************************************* IE Name: Identity Type 2 @@ -642,10 +1142,19 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8 24.008 v10.2.0 Section 10.5.5.9 *********************************************************************/ // Defines +#define LIBLTE_MME_ID_TYPE_2_IMSI 0x1 +#define LIBLTE_MME_ID_TYPE_2_IMEI 0x2 +#define LIBLTE_MME_ID_TYPE_2_IMEISV 0x3 +#define LIBLTE_MME_ID_TYPE_2_TMSI 0x4 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_identity_type_2_ie(uint8 id_type, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_type_2_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *id_type); /********************************************************************* IE Name: IMEISV Request @@ -659,9 +1168,21 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8 *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_MME_IMEISV_NOT_REQUESTED = 0, + LIBLTE_MME_IMEISV_REQUESTED, + LIBLTE_MME_IMEISV_REQUEST_N_ITEMS, +}LIBLTE_MME_IMEISV_REQUEST_ENUM; +static const char liblte_mme_imeisv_request_text[LIBLTE_MME_IMEISV_REQUEST_N_ITEMS][20] = {"Not Requested", + "Requested"}; // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_imeisv_request_ie(LIBLTE_MME_IMEISV_REQUEST_ENUM imeisv_req, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_imeisv_request_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_IMEISV_REQUEST_ENUM *imeisv_req); /********************************************************************* IE Name: KSI And Sequence Number @@ -677,8 +1198,15 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8 // Defines // Enums // Structs +typedef struct{ + uint8 ksi; + uint8 seq_num; +}LIBLTE_MME_KSI_AND_SEQUENCE_NUMBER_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_ksi_and_sequence_number_ie(LIBLTE_MME_KSI_AND_SEQUENCE_NUMBER_STRUCT *ksi_and_seq_num, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_ksi_and_sequence_number_ie(uint8 **ie_ptr, + LIBLTE_MME_KSI_AND_SEQUENCE_NUMBER_STRUCT *ksi_and_seq_num); /********************************************************************* IE Name: MS Network Capability @@ -691,9 +1219,35 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8 *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_MME_SS_SCREENING_INDICATOR_PHASE_1 = 0, + LIBLTE_MME_SS_SCREENING_INDICATOR_PHASE_2, + LIBLTE_MME_SS_SCREENING_INDICATOR_RESERVED_1, + LIBLTE_MME_SS_SCREENING_INDICATOR_RESERVED_2, + LIBLTE_MME_SS_SCREENING_INDICATOR_N_ITEMS, +}LIBLTE_MME_SS_SCREENING_INDICATOR_ENUM; +static const char liblte_mme_ss_screening_indicator_text[LIBLTE_MME_SS_SCREENING_INDICATOR_N_ITEMS][20] = {"Phase 1", + "Phase 2", + "Reserved 1", + "Reserved 2"}; // Structs typedef struct{ - // FIXME + LIBLTE_MME_SS_SCREENING_INDICATOR_ENUM ss_screening; + bool gea[8]; + bool sm_cap_ded; + bool sm_cap_gprs; + bool ucs2; + bool solsa; + bool revision; + bool pfc; + bool lcsva; + bool ho_g2u_via_iu; + bool ho_g2e_via_s1; + bool emm_comb; + bool isr; + bool srvcc; + bool epc; + bool nf; }LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_ms_network_capability_ie(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT *ms_network_cap, @@ -711,13 +1265,6 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_ms_network_capability_ie(uint8 *********************************************************************/ // Defines // Enums -typedef enum{ - LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE = 0, - LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_MAPPED, - LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_N_ITEMS, -}LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM; -static const char liblte_mme_type_of_security_context_flag_text[LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_N_ITEMS][20] = {"Native", - "Mapped"}; // Structs typedef struct{ LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM tsc_flag; @@ -743,7 +1290,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_key_set_id_ie(uint8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_nas_message_container_ie(LIBLTE_BYTE_MSG_STRUCT *nas_msg, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_message_container_ie(uint8 **ie_ptr, + LIBLTE_BYTE_MSG_STRUCT *nas_msg); /********************************************************************* IE Name: NAS Security Algorithms @@ -756,8 +1306,15 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_key_set_id_ie(uint8 // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM type_of_eea; + LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM type_of_eia; +}LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_nas_security_algorithms_ie(LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT *nas_sec_algs, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_security_algorithms_ie(uint8 **ie_ptr, + LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT *nas_sec_algs); /********************************************************************* IE Name: Network Name @@ -769,9 +1326,23 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_key_set_id_ie(uint8 *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_MME_ADD_CI_DONT_ADD = 0, + LIBLTE_MME_ADD_CI_ADD, + LIBLTE_MME_ADD_CI_N_ITEMS, +}LIBLTE_MME_ADD_CI_ENUM; +static const char liblte_mme_add_ci_text[LIBLTE_MME_ADD_CI_N_ITEMS][20] = {"Don't add", + "Add"}; // Structs +typedef struct{ + std::string name; + LIBLTE_MME_ADD_CI_ENUM add_ci; +}LIBLTE_MME_NETWORK_NAME_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_network_name_ie(LIBLTE_MME_NETWORK_NAME_STRUCT *net_name, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_network_name_ie(uint8 **ie_ptr, + LIBLTE_MME_NETWORK_NAME_STRUCT *net_name); /********************************************************************* IE Name: Nonce @@ -785,7 +1356,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_key_set_id_ie(uint8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_nonce_ie(uint32 nonce, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_nonce_ie(uint8 **ie_ptr, + uint32 *nonce); /********************************************************************* IE Name: Paging Identity @@ -796,10 +1370,15 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_key_set_id_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.3.25A *********************************************************************/ // Defines +#define LIBLTE_MME_PAGING_IDENTITY_IMSI 0 +#define LIBLTE_MME_PAGING_IDENTITY_TMSI 1 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_paging_identity_ie(uint8 paging_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_paging_identity_ie(uint8 **ie_ptr, + uint8 *paging_id); /********************************************************************* IE Name: P-TMSI Signature @@ -827,10 +1406,19 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_p_tmsi_signature_ie(uint8 **ie_ptr, Document Reference: 24.301 v10.2.0 Section 9.9.3.27 *********************************************************************/ // Defines +#define LIBLTE_MME_SERVICE_TYPE_MO_CSFB 0x0 +#define LIBLTE_MME_SERVICE_TYPE_MT_CSFB 0x1 +#define LIBLTE_MME_SERVICE_TYPE_MO_CSFB_EMERGENCY 0x2 +#define LIBLTE_MME_SERVICE_TYPE_PACKET_SERVICES 0x8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_service_type_ie(uint8 value, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_service_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *value); /********************************************************************* IE Name: Short MAC @@ -843,7 +1431,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_p_tmsi_signature_ie(uint8 **ie_ptr, // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_short_mac_ie(uint16 short_mac, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_short_mac_ie(uint8 **ie_ptr, + uint16 *short_mac); /********************************************************************* IE Name: Time Zone @@ -858,7 +1449,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_p_tmsi_signature_ie(uint8 **ie_ptr, // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_time_zone_ie(uint8 tz, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_time_zone_ie(uint8 **ie_ptr, + uint8 *tz); /********************************************************************* IE Name: Time Zone And Time @@ -874,8 +1468,20 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_p_tmsi_signature_ie(uint8 **ie_ptr, // Defines // Enums // Structs +typedef struct{ + uint16 year; + uint8 month; + uint8 day; + uint8 hour; + uint8 minute; + uint8 second; + uint8 tz; +}LIBLTE_MME_TIME_ZONE_AND_TIME_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_time_zone_and_time_ie(LIBLTE_MME_TIME_ZONE_AND_TIME_STRUCT *ttz, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_time_zone_and_time_ie(uint8 **ie_ptr, + LIBLTE_MME_TIME_ZONE_AND_TIME_STRUCT *ttz); /********************************************************************* IE Name: TMSI Status @@ -935,10 +1541,27 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_id_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.3.33 *********************************************************************/ // Defines +#define LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_MAX_SIZE 16 // Enums +typedef enum{ + LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ONE_PLMN_NON_CONSECUTIVE_TACS = 0, + LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ONE_PLMN_CONSECUTIVE_TACS, + LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_DIFFERENT_PLMNS, + LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_N_ITEMS, +}LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ENUM; +static const char liblte_mme_tracking_area_identity_list_type_text[LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_N_ITEMS][100] = {"One PLMN, Non-Consecutive TACs", + "One PLMN, Consecutive TACs", + "Different PLMNs"}; // Structs +typedef struct{ + LIBLTE_MME_TRACKING_AREA_ID_STRUCT tai[LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_MAX_SIZE]; + uint32 N_tais; +}LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_identity_list_ie(LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_STRUCT *tai_list, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_identity_list_ie(uint8 **ie_ptr, + LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_STRUCT *tai_list); /********************************************************************* IE Name: UE Network Capability @@ -953,42 +1576,22 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_id_ie(uint8 // Enums // Structs typedef struct{ - bool eea0; - bool eea1; - bool eea2; - bool eea3; - bool eea4; - bool eea5; - bool eea6; - bool eea7; - bool eia0; - bool eia1; - bool eia2; - bool eia3; - bool eia4; - bool eia5; - bool eia6; - bool eia7; - bool uea0; - bool uea1; - bool uea2; - bool uea3; - bool uea4; - bool uea5; - bool uea6; - bool uea7; + bool eea[8]; + bool eia[8]; + bool uea[8]; + bool uea_present; bool ucs2; - bool uia1; - bool uia2; - bool uia3; - bool uia4; - bool uia5; - bool uia6; - bool uia7; + bool ucs2_present; + bool uia[8]; + bool uia_present; bool lpp; + bool lpp_present; bool lcs; + bool lcs_present; bool onexsrvcc; + bool onexsrvcc_present; bool nf; + bool nf_present; }LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_ue_network_capability_ie(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT *ue_network_cap, @@ -1005,10 +1608,17 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_network_capability_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.3.35 *********************************************************************/ // Defines +#define LIBLTE_MME_URC_UPDATE_NOT_NEEDED 0 +#define LIBLTE_MME_URC_UPDATE_NEEDED 1 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_ue_radio_capability_update_needed_ie(uint8 urc_update, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_radio_capability_update_needed_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *urc_update); /********************************************************************* IE Name: UE Security Capability @@ -1021,8 +1631,21 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_network_capability_ie(uint8 // Defines // Enums // Structs -// Functions -// FIXME +typedef struct{ + bool eea[8]; + bool eia[8]; + bool uea[8]; + bool uea_present; + bool uia[8]; + bool uia_present; + bool gea[8]; + bool gea_present; +}LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_ue_security_capabilities_ie(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *ue_sec_cap, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_security_capabilities_ie(uint8 **ie_ptr, + LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *ue_sec_cap); /********************************************************************* IE Name: Emergency Number List @@ -1035,10 +1658,41 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_network_capability_ie(uint8 24.008 v10.2.0 Section 10.5.3.13 *********************************************************************/ // Defines +#define LIBLTE_MME_EMERGENCY_NUMBER_LIST_MAX_SIZE 12 +#define LIBLTE_MME_EMERGENCY_NUMBER_MAX_NUM_DIGITS 92 // Enums +typedef enum{ + LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_POLICE = 0, + LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_AMBULANCE, + LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_FIRE, + LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD, + LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE, + LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_MANUALLY_INITIATED_ECALL, + LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_AUTOMATICALLY_INITIATED_ECALL, + LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_N_ITEMS, +}LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_ENUM; +static const char liblte_mme_emergency_service_category_text[LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_N_ITEMS][100] = {"Police", + "Ambulance", + "Fire", + "Marine Guard", + "Mountain Rescue", + "Manually Initiated ECall", + "Automatically Initiated ECall"}; // Structs +typedef struct{ + LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_ENUM emerg_service_cat; + uint32 N_emerg_num_digits; + uint8 emerg_num[LIBLTE_MME_EMERGENCY_NUMBER_MAX_NUM_DIGITS]; +}LIBLTE_MME_EMERGENCY_NUMBER_STRUCT; +typedef struct{ + LIBLTE_MME_EMERGENCY_NUMBER_STRUCT emerg_num[LIBLTE_MME_EMERGENCY_NUMBER_LIST_MAX_SIZE]; + uint32 N_emerg_nums; +}LIBLTE_MME_EMERGENCY_NUMBER_LIST_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_emergency_number_list_ie(LIBLTE_MME_EMERGENCY_NUMBER_LIST_STRUCT *emerg_num_list, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_emergency_number_list_ie(uint8 **ie_ptr, + LIBLTE_MME_EMERGENCY_NUMBER_LIST_STRUCT *emerg_num_list); /********************************************************************* IE Name: CLI @@ -1067,7 +1721,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_network_capability_ie(uint8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_ss_code_ie(uint8 code, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_ss_code_ie(uint8 **ie_ptr, + uint8 *code); /********************************************************************* IE Name: LCS Indicator @@ -1079,10 +1736,14 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_network_capability_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.3.40 *********************************************************************/ // Defines +#define LIBLTE_MME_LCS_INDICATOR_MT_LR 0x01 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_lcs_indicator_ie(uint8 lcs_ind, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_lcs_indicator_ie(uint8 **ie_ptr, + uint8 *lcs_ind); /********************************************************************* IE Name: LCS Client Identity @@ -1107,10 +1768,15 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_network_capability_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.3.42 *********************************************************************/ // Defines +#define LIBLTE_MME_GENERIC_MESSAGE_CONTAINER_TYPE_LPP 0x01 +#define LIBLTE_MME_GENERIC_MESSAGE_CONTAINER_TYPE_LOCATION_SERVICES 0x02 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_generic_message_container_type_ie(uint8 msg_cont_type, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_generic_message_container_type_ie(uint8 **ie_ptr, + uint8 *msg_cont_type); /********************************************************************* IE Name: Generic Message Container @@ -1124,7 +1790,10 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_network_capability_ie(uint8 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_generic_message_container_ie(LIBLTE_BYTE_MSG_STRUCT *msg, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_generic_message_container_ie(uint8 **ie_ptr, + LIBLTE_BYTE_MSG_STRUCT *msg); /********************************************************************* IE Name: Voice Domain Preference and UE's Usage Setting @@ -1209,7 +1878,7 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_type_ie(uint8 **ie_ // Enums // Structs typedef struct{ - // FIXME + std::string apn; }LIBLTE_MME_ACCESS_POINT_NAME_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_access_point_name_ie(LIBLTE_MME_ACCESS_POINT_NAME_STRUCT *apn, @@ -1229,8 +1898,21 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_access_point_name_ie(uint8 // Defines // Enums // Structs -// Functions -// FIXME +typedef struct{ + uint8 apn_ambr_dl; + uint8 apn_ambr_ul; + uint8 apn_ambr_dl_ext; + uint8 apn_ambr_ul_ext; + uint8 apn_ambr_dl_ext2; + uint8 apn_ambr_ul_ext2; + bool ext_present; + bool ext2_present; +}LIBLTE_MME_APN_AGGREGATE_MAXIMUM_BIT_RATE_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_apn_aggregate_maximum_bit_rate_ie(LIBLTE_MME_APN_AGGREGATE_MAXIMUM_BIT_RATE_STRUCT *apn_ambr, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_apn_aggregate_maximum_bit_rate_ie(uint8 **ie_ptr, + LIBLTE_MME_APN_AGGREGATE_MAXIMUM_BIT_RATE_STRUCT *apn_ambr); /********************************************************************* IE Name: Connectivity Type @@ -1242,10 +1924,17 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_access_point_name_ie(uint8 24.008 v10.2.0 Section 10.5.6.19 *********************************************************************/ // Defines +#define LIBLTE_MME_CONNECTIVITY_TYPE_NOT_INDICATED 0x0 +#define LIBLTE_MME_CONNECTIVITY_TYPE_LIPA_PDN 0x1 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_connectivity_type_ie(uint8 con_type, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_connectivity_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *con_type); /********************************************************************* IE Name: EPS Quality Of Service @@ -1258,8 +1947,24 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_access_point_name_ie(uint8 // Defines // Enums // Structs -// Functions -// FIXME +typedef struct{ + uint8 qci; + uint8 mbr_ul; + uint8 mbr_dl; + uint8 gbr_ul; + uint8 gbr_dl; + uint8 mbr_ul_ext; + uint8 mbr_dl_ext; + uint8 gbr_ul_ext; + uint8 gbr_dl_ext; + bool br_present; + bool br_ext_present; +}LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_quality_of_service_ie(LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT *qos, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_quality_of_service_ie(uint8 **ie_ptr, + LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT *qos); /********************************************************************* IE Name: ESM Cause @@ -1270,10 +1975,55 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_access_point_name_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.4.4 *********************************************************************/ // Defines -// Enums -// Structs -// Functions -// FIXME +#define LIBLTE_MME_ESM_CAUSE_OPERATOR_DETERMINED_BARRING 0x08 +#define LIBLTE_MME_ESM_CAUSE_INSUFFICIENT_RESOURCES 0x1A +#define LIBLTE_MME_ESM_CAUSE_UNKNOWN_OR_MISSING_APN 0x1B +#define LIBLTE_MME_ESM_CAUSE_UNKNOWN_PDN_TYPE 0x1C +#define LIBLTE_MME_ESM_CAUSE_USER_AUTHENTICATION_FAILED 0x1D +#define LIBLTE_MME_ESM_CAUSE_REQUEST_REJECTED_BY_SERVING_OR_PDN_GW 0x1E +#define LIBLTE_MME_ESM_CAUSE_REQUEST_REJECTED_UNSPECIFIED 0x1F +#define LIBLTE_MME_ESM_CAUSE_SERVICE_OPTION_NOT_SUPPORTED 0x20 +#define LIBLTE_MME_ESM_CAUSE_REQUESTED_SERVICE_OPTION_NOT_SUBSCRIBED 0x21 +#define LIBLTE_MME_ESM_CAUSE_SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER 0x22 +#define LIBLTE_MME_ESM_CAUSE_PTI_ALREADY_IN_USE 0x23 +#define LIBLTE_MME_ESM_CAUSE_REGULAR_DEACTIVATION 0x24 +#define LIBLTE_MME_ESM_CAUSE_EPS_QOS_NOT_ACCEPTED 0x25 +#define LIBLTE_MME_ESM_CAUSE_NETWORK_FAILURE 0x26 +#define LIBLTE_MME_ESM_CAUSE_REACTIVATION_REQUESTED 0x27 +#define LIBLTE_MME_ESM_CAUSE_SEMANTIC_ERROR_IN_THE_TFT_OPERATION 0x29 +#define LIBLTE_MME_ESM_CAUSE_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION 0x2A +#define LIBLTE_MME_ESM_CAUSE_INVALID_EPS_BEARER_IDENTITY 0x2B +#define LIBLTE_MME_ESM_CAUSE_SEMANTIC_ERRORS_IN_PACKET_FILTERS 0x2C +#define LIBLTE_MME_ESM_CAUSE_SYNTACTICAL_ERRORS_IN_PACKET_FILTERS 0x2D +#define LIBLTE_MME_ESM_CAUSE_UNUSED 0x2E +#define LIBLTE_MME_ESM_CAUSE_PTI_MISMATCH 0x2F +#define LIBLTE_MME_ESM_CAUSE_LAST_PDN_DISCONNECTION_NOT_ALLOWED 0x31 +#define LIBLTE_MME_ESM_CAUSE_PDN_TYPE_IPV4_ONLY_ALLOWED 0x32 +#define LIBLTE_MME_ESM_CAUSE_PDN_TYPE_IPV6_ONLY_ALLOWED 0x33 +#define LIBLTE_MME_ESM_CAUSE_SINGLE_ADDRESS_BEARERS_ONLY_ALLOWED 0x34 +#define LIBLTE_MME_ESM_CAUSE_ESM_INFORMATION_NOT_RECEIVED 0x35 +#define LIBLTE_MME_ESM_CAUSE_PDN_CONNECTION_DOES_NOT_EXIST 0x36 +#define LIBLTE_MME_ESM_CAUSE_MULTIPLE_PDN_CONNECTIONS_FOR_A_GIVEN_APN_NOT_ALLOWED 0x37 +#define LIBLTE_MME_ESM_CAUSE_COLLISION_WITH_NETWORK_INITIATED_REQUEST 0x38 +#define LIBLTE_MME_ESM_CAUSE_UNSUPPORTED_QCI_VALUE 0x3B +#define LIBLTE_MME_ESM_CAUSE_BEARER_HANDLING_NOT_SUPPORTED 0x3C +#define LIBLTE_MME_ESM_CAUSE_INVALID_PTI_VALUE 0x51 +#define LIBLTE_MME_ESM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE 0x5F +#define LIBLTE_MME_ESM_CAUSE_INVALID_MANDATORY_INFORMATION 0x60 +#define LIBLTE_MME_ESM_CAUSE_MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED 0x61 +#define LIBLTE_MME_ESM_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE 0x62 +#define LIBLTE_MME_ESM_CAUSE_INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT_IMPLEMENTED 0x63 +#define LIBLTE_MME_ESM_CAUSE_CONDITIONAL_IE_ERROR 0x64 +#define LIBLTE_MME_ESM_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE 0x65 +#define LIBLTE_MME_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED 0x6F +#define LIBLTE_MME_ESM_CAUSE_APN_RESTRICTION_VALUE_INCOMPATIBLE_WITH_ACTIVE_EPS_BEARER_CONTEXT 0x70 +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_esm_cause_ie(uint8 cause, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_cause_ie(uint8 **ie_ptr, + uint8 *cause); /********************************************************************* IE Name: ESM Information Transfer Flag @@ -1314,10 +2064,26 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_info_transfer_flag_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.4.6 *********************************************************************/ // Defines +#define LIBLTE_MME_LINKED_EPS_BEARER_IDENTITY_5 0x5 +#define LIBLTE_MME_LINKED_EPS_BEARER_IDENTITY_6 0x6 +#define LIBLTE_MME_LINKED_EPS_BEARER_IDENTITY_7 0x7 +#define LIBLTE_MME_LINKED_EPS_BEARER_IDENTITY_8 0x8 +#define LIBLTE_MME_LINKED_EPS_BEARER_IDENTITY_9 0x9 +#define LIBLTE_MME_LINKED_EPS_BEARER_IDENTITY_10 0xA +#define LIBLTE_MME_LINKED_EPS_BEARER_IDENTITY_11 0xB +#define LIBLTE_MME_LINKED_EPS_BEARER_IDENTITY_12 0xC +#define LIBLTE_MME_LINKED_EPS_BEARER_IDENTITY_13 0xD +#define LIBLTE_MME_LINKED_EPS_BEARER_IDENTITY_14 0xE +#define LIBLTE_MME_LINKED_EPS_BEARER_IDENTITY_15 0xF // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_linked_eps_bearer_identity_ie(uint8 bearer_id, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_linked_eps_bearer_identity_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *bearer_id); /********************************************************************* IE Name: LLC Service Access Point Identifier @@ -1329,10 +2095,18 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_info_transfer_flag_ie(uint8 24.008 v10.2.0 Section 10.5.6.9 *********************************************************************/ // Defines +#define LIBLTE_MME_LLC_SAPI_NOT_ASSIGNED 0x0 +#define LIBLTE_MME_LLC_SAPI_3 0x3 +#define LIBLTE_MME_LLC_SAPI_5 0x5 +#define LIBLTE_MME_LLC_SAPI_9 0x9 +#define LIBLTE_MME_LLC_SAPI_11 0xB // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_llc_service_access_point_identifier_ie(uint8 llc_sapi, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_llc_service_access_point_identifier_ie(uint8 **ie_ptr, + uint8 *llc_sapi); /********************************************************************* IE Name: Notification Indicator @@ -1344,10 +2118,14 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_info_transfer_flag_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.4.7A *********************************************************************/ // Defines +#define LIBLTE_MME_NOTIFICATION_INDICATOR_SRVCC_HO_CANCELLED_IMS_SESSION_REEST_REQ 0x01 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_notification_indicator_ie(uint8 notification_ind, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_notification_indicator_ie(uint8 **ie_ptr, + uint8 *notification_ind); /********************************************************************* IE Name: Packet Flow Identifier @@ -1359,10 +2137,17 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_info_transfer_flag_ie(uint8 24.008 v10.2.0 Section 10.5.6.11 *********************************************************************/ // Defines +#define LIBLTE_MME_PACKET_FLOW_ID_BEST_EFFORT 0x00 +#define LIBLTE_MME_PACKET_FLOW_ID_SIGNALLING 0x01 +#define LIBLTE_MME_PACKET_FLOW_ID_SMS 0x02 +#define LIBLTE_MME_PACKET_FLOW_ID_TOM8 0x03 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_packet_flow_identifier_ie(uint8 packet_flow_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_packet_flow_identifier_ie(uint8 **ie_ptr, + uint8 *packet_flow_id); /********************************************************************* IE Name: PDN Address @@ -1375,10 +2160,20 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_info_transfer_flag_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.4.9 *********************************************************************/ // Defines +#define LIBLTE_MME_PDN_TYPE_IPV4 0x1 +#define LIBLTE_MME_PDN_TYPE_IPV6 0x2 +#define LIBLTE_MME_PDN_TYPE_IPV4V6 0x3 // Enums // Structs +typedef struct{ + uint8 pdn_type; + uint8 addr[12]; +}LIBLTE_MME_PDN_ADDRESS_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_address_ie(LIBLTE_MME_PDN_ADDRESS_STRUCT *pdn_addr, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_address_ie(uint8 **ie_ptr, + LIBLTE_MME_PDN_ADDRESS_STRUCT *pdn_addr); /********************************************************************* IE Name: PDN Type @@ -1417,10 +2212,49 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_type_ie(uint8 **ie_ptr, 24.008 v10.2.0 Section 10.5.6.3 *********************************************************************/ // Defines +#define LIBLTE_MME_MAX_PROTOCOL_CONFIG_OPTIONS 83 +#define LIBLTE_MME_MAX_PROTOCOL_CONFIG_LEN 248 +#define LIBLTE_MME_CONFIGURATION_PROTOCOL_OPTIONS_LCP 0xC021 +#define LIBLTE_MME_CONFIGURATION_PROTOCOL_OPTIONS_PAP 0xC023 +#define LIBLTE_MME_CONFIGURATION_PROTOCOL_OPTIONS_CHAP 0xC223 +#define LIBLTE_MME_CONFIGURATION_PROTOCOL_OPTIONS_IPCP 0x8021 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_P_CSCF_IPV6_ADDRESS_REQUEST 0x0001 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_IM_CN_SUBSYSTEM_SIGNALLING_FLAG 0x0002 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_DNS_SERVER_IPV6_ADDRESS_REQUEST 0x0003 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_MS_SUPPORT_OF_NETWORK_REQUESTED_BEARER_CONTROL_INDICATOR 0x0005 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_DSMIPV6_HOME_AGENT_ADDRESS_REQUEST 0x0007 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_DSMIPV6_HOME_NETWORK_PREFIX_REQUEST 0x0008 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_DSMIPV6_IPV4_HOME_AGENT_ADDRESS_REQUEST 0x0009 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_IP_ADDRESS_ALLOCATION_VIA_NAS_SIGNALLING 0x000A +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_IPV4_ADDRESS_ALLOCATION_VIA_DHCPV4 0x000B +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_P_CSCF_IPV4_ADDRESS_REQUEST 0x000C +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_DNS_SERVER_IPV4_ADDRESS_REQUEST 0x000D +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_MSISDN_REQUEST 0x000E +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_IFOM_SUPPORT_REQUEST 0x000F +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_IPV4_LINK_MTU_REQUEST 0x0010 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_P_CSCF_IPV6_ADDRESS 0x0001 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_IM_CN_SUBSYSTEM_SIGNALLING_FLAG 0x0002 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_DNS_SERVER_IPV6_ADDRESS 0x0003 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_POLICY_CONTROL_REJECTION_CODE 0x0004 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_SELECTED_BEARER_CONTROL_MODE 0x0005 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_DSMIPV6_HOME_AGENT_ADDRESS 0x0007 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_DSMIPV6_HOME_NETWORK_PREFIX 0x0008 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_DSMIPV6_IPV4_HOME_AGENT_ADDRESS 0x0009 +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_P_CSCF_IPV4_ADDRESS 0x000C +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_DNS_SERVER_IPV4_ADDRESS 0x000D +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_MSISDN 0x000E +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_IFOM_SUPPORT 0x000F +#define LIBLTE_MME_ADDITIONAL_PARAMETERS_DL_IPV4_LINK_MTU 0x0010 // Enums // Structs typedef struct{ - // FIXME + uint16 id; + uint8 len; + uint8 contents[LIBLTE_MME_MAX_PROTOCOL_CONFIG_LEN]; +}LIBLTE_MME_PROTOCOL_CONFIG_STRUCT; +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_STRUCT opt[LIBLTE_MME_MAX_PROTOCOL_CONFIG_OPTIONS]; + uint32 N_opts; }LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_protocol_config_options_ie(LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT *protocol_cnfg_opts, @@ -1437,10 +2271,150 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_protocol_config_options_ie(uint8 24.008 v10.2.0 Section 10.5.6.5 *********************************************************************/ // Defines +#define LIBLTE_MME_QOS_DELAY_CLASS_UL_SUBSCRIBED 0x0 +#define LIBLTE_MME_QOS_DELAY_CLASS_DL_RESERVED 0x0 +#define LIBLTE_MME_QOS_DELAY_CLASS_1 0x1 +#define LIBLTE_MME_QOS_DELAY_CLASS_2 0x2 +#define LIBLTE_MME_QOS_DELAY_CLASS_3 0x3 +#define LIBLTE_MME_QOS_DELAY_CLASS_4 0x4 +#define LIBLTE_MME_QOS_DELAY_CLASS_RESERVED 0x7 +#define LIBLTE_MME_QOS_RELIABILITY_CLASS_UL_SUBSCRIBED 0x0 +#define LIBLTE_MME_QOS_RELIABILITY_CLASS_DL_RESERVED 0x0 +#define LIBLTE_MME_QOS_RELIABILITY_CLASS_UNUSED 0x1 +#define LIBLTE_MME_QOS_RELIABILITY_CLASS_UNACK_GTP_ACK_LLC_RLC_PROTECTED 0x2 +#define LIBLTE_MME_QOS_RELIABILITY_CLASS_UNACK_GTP_LLC_ACK_RLC_PROTECTED 0x3 +#define LIBLTE_MME_QOS_RELIABILITY_CLASS_UNACK_GTP_LLC_RLC_PROTECTED 0x4 +#define LIBLTE_MME_QOS_RELIABILITY_CLASS_UNACK_GTP_LLC_RLC_UNPROTECTED 0x5 +#define LIBLTE_MME_QOS_RELIABILITY_CLASS_RESERVED 0x7 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_UL_SUBSCRIBED 0x0 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_DL_RESERVED 0x0 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_UP_TO_1000BPS 0x1 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_UP_TO_2000BPS 0x2 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_UP_TO_4000BPS 0x3 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_UP_TO_8000BPS 0x4 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_UP_TO_16000BPS 0x5 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_UP_TO_32000BPS 0x6 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_UP_TO_64000BPS 0x7 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_UP_TO_128000BPS 0x8 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_UP_TO_256000BPS 0x9 +#define LIBLTE_MME_QOS_PEAK_THROUGHPUT_RESERVED 0xF +#define LIBLTE_MME_QOS_PRECEDENCE_CLASS_UL_SUBSCRIBED 0x0 +#define LIBLTE_MME_QOS_PRECEDENCE_CLASS_DL_RESERVED 0x0 +#define LIBLTE_MME_QOS_PRECEDENCE_CLASS_HIGH_PRIORITY 0x1 +#define LIBLTE_MME_QOS_PRECEDENCE_CLASS_NORMAL_PRIORITY 0x2 +#define LIBLTE_MME_QOS_PRECEDENCE_CLASS_LOW_PRIORITY 0x3 +#define LIBLTE_MME_QOS_PRECEDENCE_CLASS_RESERVED 0x7 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_UL_SUBSCRIBED 0x00 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_DL_RESERVED 0x00 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_100BPH 0x01 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_200BPH 0x02 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_500BPH 0x03 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_1000BPH 0x04 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_2000BPH 0x05 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_5000BPH 0x06 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_10000BPH 0x07 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_20000BPH 0x08 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_50000BPH 0x09 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_100000BPH 0x0A +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_200000BPH 0x0B +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_500000BPH 0x0C +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_1000000BPH 0x0D +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_2000000BPH 0x0E +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_5000000BPH 0x0F +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_10000000BPH 0x10 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_20000000BPH 0x11 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_50000000BPH 0x12 +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_RESERVED 0x1E +#define LIBLTE_MME_QOS_MEAN_THROUGHPUT_BEST_EFFORT 0x1F +#define LIBLTE_MME_QOS_TRAFFIC_CLASS_UL_SUBSCRIBED 0x0 +#define LIBLTE_MME_QOS_TRAFFIC_CLASS_DL_RESERVED 0x0 +#define LIBLTE_MME_QOS_TRAFFIC_CLASS_CONVERSATIONAL 0x1 +#define LIBLTE_MME_QOS_TRAFFIC_CLASS_STREAMING 0x2 +#define LIBLTE_MME_QOS_TRAFFIC_CLASS_INTERACTIVE 0x3 +#define LIBLTE_MME_QOS_TRAFFIC_CLASS_BACKGROUND 0x4 +#define LIBLTE_MME_QOS_TRAFFIC_CLASS_RESERVED 0x7 +#define LIBLTE_MME_QOS_DELIVERY_ORDER_UL_SUBSCRIBED 0x0 +#define LIBLTE_MME_QOS_DELIVERY_ORDER_DL_RESERVED 0x0 +#define LIBLTE_MME_QOS_DELIVERY_ORDER_WITH_DELIVERY_ORDER_YES 0x1 +#define LIBLTE_MME_QOS_DELIVERY_ORDER_WITHOUT_DELIVERY_ORDER_NO 0x2 +#define LIBLTE_MME_QOS_DELIVERY_ORDER_RESERVED 0x3 +#define LIBLTE_MME_QOS_DELIVERY_OF_ERRONEOUS_SDU_UL_SUBSCRIBED 0x0 +#define LIBLTE_MME_QOS_DELIVERY_OF_ERRONEOUS_SDU_DL_RESERVED 0x0 +#define LIBLTE_MME_QOS_DELIVERY_OF_ERRONEOUS_SDU_NO_DETECT 0x1 +#define LIBLTE_MME_QOS_DELIVERY_OF_ERRONEOUS_SDU_DELIVERED 0x2 +#define LIBLTE_MME_QOS_DELIVERY_OF_ERRONEOUS_SDU_NOT_DELIVERED 0x3 +#define LIBLTE_MME_QOS_DELIVERY_OF_ERRONEOUS_SDU_RESERVED 0x7 +#define LIBLTE_MME_QOS_MAX_SDU_SIZE_UL_SUBSCRIBED 0x00 +#define LIBLTE_MME_QOS_MAX_SDU_SIZE_DL_RESERVED 0x00 +#define LIBLTE_MME_QOS_MAX_SDU_SIZE_RESERVED 0xFF +#define LIBLTE_MME_QOS_RESIDUAL_BER_UL_SUBSCRIBED 0x0 +#define LIBLTE_MME_QOS_RESIDUAL_BER_DL_RESERVED 0x0 +#define LIBLTE_MME_QOS_RESIDUAL_BER_5_E_NEG_2 0x1 +#define LIBLTE_MME_QOS_RESIDUAL_BER_1_E_NEG_2 0x2 +#define LIBLTE_MME_QOS_RESIDUAL_BER_5_E_NEG_3 0x3 +#define LIBLTE_MME_QOS_RESIDUAL_BER_4_E_NEG_3 0x4 +#define LIBLTE_MME_QOS_RESIDUAL_BER_1_E_NEG_3 0x5 +#define LIBLTE_MME_QOS_RESIDUAL_BER_1_E_NEG_4 0x6 +#define LIBLTE_MME_QOS_RESIDUAL_BER_1_E_NEG_5 0x7 +#define LIBLTE_MME_QOS_RESIDUAL_BER_1_E_NEG_6 0x8 +#define LIBLTE_MME_QOS_RESIDUAL_BER_6_E_NEG_8 0x9 +#define LIBLTE_MME_QOS_RESIDUAL_BER_RESERVED 0xF +#define LIBLTE_MME_QOS_SDU_ERROR_RATIO_UL_SUBSCRIBED 0x0 +#define LIBLTE_MME_QOS_SDU_ERROR_RATIO_DL_RESERVED 0x0 +#define LIBLTE_MME_QOS_SDU_ERROR_RATIO_1_E_NEG_2 0x1 +#define LIBLTE_MME_QOS_SDU_ERROR_RATIO_7_E_NEG_3 0x2 +#define LIBLTE_MME_QOS_SDU_ERROR_RATIO_1_E_NEG_3 0x3 +#define LIBLTE_MME_QOS_SDU_ERROR_RATIO_1_E_NEG_4 0x4 +#define LIBLTE_MME_QOS_SDU_ERROR_RATIO_1_E_NEG_5 0x5 +#define LIBLTE_MME_QOS_SDU_ERROR_RATIO_1_E_NEG_6 0x6 +#define LIBLTE_MME_QOS_SDU_ERROR_RATIO_1_E_NEG_1 0x7 +#define LIBLTE_MME_QOS_SDU_ERROR_RATIO_RESERVED 0xF +#define LIBLTE_MME_QOS_TRANSFER_DELAY_UL_SUBSCRIBED 0x00 +#define LIBLTE_MME_QOS_TRANSFER_DELAY_DL_RESERVED 0x00 +#define LIBLTE_MME_QOS_TRANSFER_DELAY_RESERVED 0x3F +#define LIBLTE_MME_QOS_TRAFFIC_HANDLING_PRIORITY_UL_SUBSCRIBED 0x0 +#define LIBLTE_MME_QOS_TRAFFIC_HANDLING_PRIORITY_DL_RESERVED 0x0 +#define LIBLTE_MME_QOS_TRAFFIC_HANDLING_PRIORITY_LEVEL_1 0x1 +#define LIBLTE_MME_QOS_TRAFFIC_HANDLING_PRIORITY_LEVEL_2 0x2 +#define LIBLTE_MME_QOS_TRAFFIC_HANDLING_PRIORITY_LEVEL_3 0x3 +#define LIBLTE_MME_QOS_SIGNALLING_INDICATOR_NOT_OPTIMIZED_FOR_SIGNALLING 0x0 +#define LIBLTE_MME_QOS_SIGNALLING_INDICATOR_OPTIMIZED_FOR_SIGNALLING 0x1 +#define LIBLTE_MME_QOS_SOURCE_STATISTICS_DESCRIPTOR_UNKNOWN 0x0 +#define LIBLTE_MME_QOS_SOURCE_STATISTICS_DESCRIPTOR_SPEECH 0x1 // Enums // Structs -// Functions -// FIXME +typedef struct{ + uint8 delay_class; + uint8 reliability_class; + uint8 peak_throughput; + uint8 precedence_class; + uint8 mean_throughput; + uint8 traffic_class; + uint8 delivery_order; + uint8 delivery_of_erroneous_sdu; + uint8 max_sdu_size; + uint8 mbr_ul; + uint8 mbr_dl; + uint8 residual_ber; + uint8 sdu_error_ratio; + uint8 transfer_delay; + uint8 traffic_handling_prio; + uint8 gbr_ul; + uint8 gbr_dl; + uint8 signalling_ind; + uint8 source_stats_descriptor; + uint8 mbr_dl_ext; + uint8 gbr_dl_ext; + uint8 mbr_ul_ext; + uint8 gbr_ul_ext; + bool dl_ext_present; + bool ul_ext_present; +}LIBLTE_MME_QUALITY_OF_SERVICE_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_quality_of_service_ie(LIBLTE_MME_QUALITY_OF_SERVICE_STRUCT *qos, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_quality_of_service_ie(uint8 **ie_ptr, + LIBLTE_MME_QUALITY_OF_SERVICE_STRUCT *qos); /********************************************************************* IE Name: Radio Priority @@ -1454,10 +2428,19 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_protocol_config_options_ie(uint8 24.008 v10.2.0 Section 10.5.7.2 *********************************************************************/ // Defines +#define LIBLTE_MME_RADIO_PRIORITY_LEVEL_1 0x1 +#define LIBLTE_MME_RADIO_PRIORITY_LEVEL_2 0x2 +#define LIBLTE_MME_RADIO_PRIORITY_LEVEL_3 0x3 +#define LIBLTE_MME_RADIO_PRIORITY_LEVEL_4 0x4 // Enums // Structs // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_radio_priority_ie(uint8 radio_prio, + uint8 bit_offset, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_radio_priority_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *radio_prio); /********************************************************************* IE Name: Request Type @@ -1493,10 +2476,77 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_request_type_ie(uint8 **ie_ptr, Document Reference: 24.301 v10.2.0 Section 9.9.4.15 *********************************************************************/ // Defines +#define LIBLTE_MME_PACKET_FILTER_LIST_MAX_SIZE 15 +#define LIBLTE_MME_PACKET_FILTER_MAX_SIZE 20 +#define LIBLTE_MME_PARAMETER_LIST_MAX_SIZE 15 +#define LIBLTE_MME_PARAMETER_MAX_SIZE 20 +#define LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_IPV4_REMOTE_ADDRESS_TYPE 0x10 +#define LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_IPV6_REMOTE_ADDRESS_TYPE 0x20 +#define LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_PROTOCOL_ID_NEXT_HEADER_TYPE 0x30 +#define LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_SINGLE_LOCAL_PORT_TYPE 0x40 +#define LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_LOCAL_PORT_RANGE_TYPE 0x41 +#define LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_SINGLE_REMOTE_PORT_TYPE 0x50 +#define LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_REMOTE_PORT_RANGE_TYPE 0x51 +#define LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_SECURITY_PARAMETER_INDEX_TYPE 0x60 +#define LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_TYPE_OF_SERVICE_TRAFFIC_CLASS_TYPE 0x70 +#define LIBLTE_MME_TFT_PACKET_FILTER_COMPONENT_TYPE_ID_FLOW_LABEL_TYPE 0x80 // Enums +typedef enum{ + LIBLTE_MME_TFT_OPERATION_CODE_SPARE = 0, + LIBLTE_MME_TFT_OPERATION_CODE_CREATE_NEW_TFT, + LIBLTE_MME_TFT_OPERATION_CODE_DELETE_EXISTING_TFT, + LIBLTE_MME_TFT_OPERATION_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT, + LIBLTE_MME_TFT_OPERATION_CODE_REPLACE_PACKET_FILTERS_IN_EXISTING_TFT, + LIBLTE_MME_TFT_OPERATION_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING_TFT, + LIBLTE_MME_TFT_OPERATION_CODE_NO_TFT_OPERATION, + LIBLTE_MME_TFT_OPERATION_CODE_RESERVED, + LIBLTE_MME_TFT_OPERATION_CODE_N_ITEMS, +}LIBLTE_MME_TFT_OPERATION_CODE_ENUM; +static const char liblte_mme_tft_operation_code_text[LIBLTE_MME_TFT_OPERATION_CODE_N_ITEMS][100] = {"SPARE", + "Create New TFT", + "Delete Existing TFT", + "Add Packet Filters to Existing TFT", + "Replace Packet Filters in Existing TFT", + "Delete Packet Filters from Existing TFT", + "No TFT Operation", + "RESERVED"}; +typedef enum{ + LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_PRE_REL_7_TFT_FILTER = 0, + LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_DOWNLINK_ONLY, + LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_UPLINK_ONLY, + LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_BIDIRECTIONAL, + LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_N_ITEMS, +}LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_ENUM; +static const char liblte_mme_tft_packet_filter_direction_text[LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_N_ITEMS][100] = {"Pre Rel-7 TFT Filter", + "Downlink Only", + "Uplink Only", + "Bidirectional"}; // Structs +typedef struct{ + LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_ENUM dir; + uint8 id; + uint8 eval_precedence; + uint8 filter[LIBLTE_MME_PACKET_FILTER_MAX_SIZE]; + uint8 filter_size; +}LIBLTE_MME_PACKET_FILTER_STRUCT; +typedef struct{ + uint8 id; + uint8 parameter[LIBLTE_MME_PARAMETER_MAX_SIZE]; + uint8 parameter_size; +}LIBLTE_MME_PARAMETER_STRUCT; +typedef struct{ + LIBLTE_MME_PACKET_FILTER_STRUCT packet_filter_list[LIBLTE_MME_PACKET_FILTER_LIST_MAX_SIZE]; + LIBLTE_MME_PARAMETER_STRUCT parameter_list[LIBLTE_MME_PARAMETER_LIST_MAX_SIZE]; + LIBLTE_MME_TFT_OPERATION_CODE_ENUM tft_op_code; + uint8 packet_filter_list_size; + uint8 parameter_list_size; +}LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT; +typedef LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT LIBLTE_MME_TRAFFIC_FLOW_AGGREGATE_DESCRIPTION_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_traffic_flow_aggregate_description_ie(LIBLTE_MME_TRAFFIC_FLOW_AGGREGATE_DESCRIPTION_STRUCT *tfad, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_traffic_flow_aggregate_description_ie(uint8 **ie_ptr, + LIBLTE_MME_TRAFFIC_FLOW_AGGREGATE_DESCRIPTION_STRUCT *tfad); /********************************************************************* IE Name: Traffic Flow Template @@ -1508,10 +2558,16 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_request_type_ie(uint8 **ie_ptr, 24.008 v10.2.0 Section 10.5.6.12 *********************************************************************/ // Defines +// Traffic Flow Template defines defined above // Enums +// Traffic Flow Template enums defined above // Structs +// Traffic Flow Template structs defined above // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_traffic_flow_template_ie(LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT *tft, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_traffic_flow_template_ie(uint8 **ie_ptr, + LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT *tft); /********************************************************************* IE Name: Transaction Identifier @@ -1524,10 +2580,21 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_request_type_ie(uint8 **ie_ptr, 24.008 v10.2.0 Section 10.5.6.7 *********************************************************************/ // Defines +#define LIBLTE_MME_TI_FLAG_SENT_FROM_ORIGINATOR 0 +#define LIBLTE_MME_TI_FLAG_SENT_TO_ORIGINATOR 1 +#define LIBLTE_MME_TI_VALUE_IS_GIVEN_BY_TIE 0x7 // Enums // Structs +typedef struct{ + uint8 ti_flag; + uint8 tio; + uint8 tie; +}LIBLTE_MME_TRANSACTION_IDENTIFIER_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_transaction_identifier_ie(LIBLTE_MME_TRANSACTION_IDENTIFIER_STRUCT *trans_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_mme_unpack_transaction_identifier_ie(uint8 **ie_ptr, + LIBLTE_MME_TRANSACTION_IDENTIFIER_STRUCT *trans_id); /******************************************************************************* MESSAGE DECLARATIONS @@ -1608,6 +2675,12 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_request_type_ie(uint8 **ie_ptr, LIBLTE_ERROR_ENUM liblte_mme_parse_msg_header(LIBLTE_BYTE_MSG_STRUCT *msg, uint8 *pd, uint8 *msg_type); +LIBLTE_ERROR_ENUM liblte_mme_pack_security_protected_nas_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *sec_msg); /********************************************************************* Message Name: Attach Accept @@ -1618,10 +2691,56 @@ LIBLTE_ERROR_ENUM liblte_mme_parse_msg_header(LIBLTE_BYTE_MSG_STRUCT *msg, Document Reference: 24.301 v10.2.0 Section 8.2.1 *********************************************************************/ // Defines +#define LIBLTE_MME_GUTI_IEI 0x50 +#define LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI 0x13 +#define LIBLTE_MME_MS_IDENTITY_IEI 0x23 +#define LIBLTE_MME_EMM_CAUSE_IEI 0x53 +#define LIBLTE_MME_T3402_VALUE_IEI 0x17 +#define LIBLTE_MME_T3423_VALUE_IEI 0x59 +#define LIBLTE_MME_EQUIVALENT_PLMNS_IEI 0x4A +#define LIBLTE_MME_EMERGENCY_NUMBER_LIST_IEI 0x34 +#define LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_IEI 0x64 +#define LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_IEI 0xF +#define LIBLTE_MME_T3412_EXTENDED_VALUE_IEI 0x5E // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_GPRS_TIMER_STRUCT t3412; + LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_STRUCT tai_list; + LIBLTE_BYTE_MSG_STRUCT esm_msg; + LIBLTE_MME_EPS_MOBILE_ID_STRUCT guti; + LIBLTE_MME_LOCATION_AREA_ID_STRUCT lai; + LIBLTE_MME_MOBILE_ID_STRUCT ms_id; + LIBLTE_MME_GPRS_TIMER_STRUCT t3402; + LIBLTE_MME_GPRS_TIMER_STRUCT t3423; + LIBLTE_MME_PLMN_LIST_STRUCT equivalent_plmns; + LIBLTE_MME_EMERGENCY_NUMBER_LIST_STRUCT emerg_num_list; + LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_STRUCT eps_network_feature_support; + LIBLTE_MME_GPRS_TIMER_3_STRUCT t3412_ext; + LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM additional_update_result; + uint8 eps_attach_result; + uint8 emm_cause; + bool guti_present; + bool lai_present; + bool ms_id_present; + bool emm_cause_present; + bool t3402_present; + bool t3423_present; + bool equivalent_plmns_present; + bool emerg_num_list_present; + bool eps_network_feature_support_present; + bool additional_update_result_present; + bool t3412_ext_present; +}LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_attach_accept_msg(LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT *attach_accept, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT *attach_accept); /********************************************************************* Message Name: Attach Complete @@ -1634,8 +2753,18 @@ LIBLTE_ERROR_ENUM liblte_mme_parse_msg_header(LIBLTE_BYTE_MSG_STRUCT *msg, // Defines // Enums // Structs +typedef struct{ + LIBLTE_BYTE_MSG_STRUCT esm_msg; +}LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_attach_complete_msg(LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT *attach_comp, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_complete_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT *attach_comp); /********************************************************************* Message Name: Attach Reject @@ -1646,10 +2775,22 @@ LIBLTE_ERROR_ENUM liblte_mme_parse_msg_header(LIBLTE_BYTE_MSG_STRUCT *msg, Document Reference: 24.301 v10.2.0 Section 8.2.3 *********************************************************************/ // Defines +#define LIBLTE_MME_ESM_MSG_CONTAINER_IEI 0x78 +#define LIBLTE_MME_T3446_VALUE_IEI 0x5F // Enums // Structs +typedef struct{ + LIBLTE_BYTE_MSG_STRUCT esm_msg; + uint8 emm_cause; + uint8 t3446_value; + bool esm_msg_present; + bool t3446_value_present; +}LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_attach_reject_msg(LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT *attach_rej, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT *attach_rej); /********************************************************************* Message Name: Attach Request @@ -1665,7 +2806,6 @@ LIBLTE_ERROR_ENUM liblte_mme_parse_msg_header(LIBLTE_BYTE_MSG_STRUCT *msg, #define LIBLTE_MME_LAST_VISITED_REGISTERED_TAI_IEI 0x52 #define LIBLTE_MME_DRX_PARAMETER_IEI 0x5C #define LIBLTE_MME_MS_NETWORK_CAPABILITY_IEI 0x31 -#define LIBLTE_MME_LOCATION_AREA_ID_IEI 0x13 #define LIBLTE_MME_TMSI_STATUS_IEI 0x9 #define LIBLTE_MME_MS_CLASSMARK_2_IEI 0x11 #define LIBLTE_MME_MS_CLASSMARK_3_IEI 0x20 @@ -1695,7 +2835,7 @@ typedef struct{ LIBLTE_MME_DEVICE_PROPERTIES_ENUM device_properties; LIBLTE_MME_GUTI_TYPE_ENUM old_guti_type; uint32 old_p_tmsi_signature; - uint8 eps_type_result; + uint8 eps_attach_type; bool old_p_tmsi_signature_present; bool additional_guti_present; bool last_visited_registered_tai_present; @@ -1726,10 +2866,19 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.2.5 *********************************************************************/ // Defines +#define LIBLTE_MME_AUTHENTICATION_FAILURE_PARAMETER_IEI 0x30 // Enums // Structs +typedef struct{ + uint8 emm_cause; + uint8 auth_fail_param[16]; + bool auth_fail_param_present; +}LIBLTE_MME_AUTHENTICATION_FAILURE_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_failure_msg(LIBLTE_MME_AUTHENTICATION_FAILURE_MSG_STRUCT *auth_fail, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_failure_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_AUTHENTICATION_FAILURE_MSG_STRUCT *auth_fail); /********************************************************************* Message Name: Authentication Reject @@ -1743,8 +2892,13 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ +}LIBLTE_MME_AUTHENTICATION_REJECT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_reject_msg(LIBLTE_MME_AUTHENTICATION_REJECT_MSG_STRUCT *auth_reject, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_AUTHENTICATION_REJECT_MSG_STRUCT *auth_reject); /********************************************************************* Message Name: Authentication Request @@ -1757,8 +2911,16 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; + uint8 autn[16]; + uint8 rand[16]; +}LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_request_msg(LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT *auth_req, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT *auth_req); /********************************************************************* Message Name: Authentication Response @@ -1771,8 +2933,14 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + uint8 res[16]; +}LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_response_msg(LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp); /********************************************************************* Message Name: CS Service Notification @@ -1801,8 +2969,17 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ +}LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_detach_accept_msg(LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT *detach_accept, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_detach_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT *detach_accept); /********************************************************************* Message Name: Detach Request @@ -1815,8 +2992,20 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_DETACH_TYPE_STRUCT detach_type; + LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; + LIBLTE_MME_EPS_MOBILE_ID_STRUCT eps_mobile_id; +}LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_detach_request_msg(LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT *detach_req, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_detach_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT *detach_req); /********************************************************************* Message Name: Downlink NAS Transport @@ -1829,8 +3018,18 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_BYTE_MSG_STRUCT nas_msg; +}LIBLTE_MME_DOWNLINK_NAS_TRANSPORT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_downlink_nas_transport_msg(LIBLTE_MME_DOWNLINK_NAS_TRANSPORT_MSG_STRUCT *dl_nas_transport, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_downlink_nas_transport_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DOWNLINK_NAS_TRANSPORT_MSG_STRUCT *dl_nas_transport); /********************************************************************* Message Name: EMM Information @@ -1841,10 +3040,34 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.2.13 *********************************************************************/ // Defines +#define LIBLTE_MME_FULL_NAME_FOR_NETWORK_IEI 0x43 +#define LIBLTE_MME_SHORT_NAME_FOR_NETWORK_IEI 0x45 +#define LIBLTE_MME_LOCAL_TIME_ZONE_IEI 0x46 +#define LIBLTE_MME_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_IEI 0x47 +#define LIBLTE_MME_NETWORK_DAYLIGHT_SAVING_TIME_IEI 0x49 // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_NETWORK_NAME_STRUCT full_net_name; + LIBLTE_MME_NETWORK_NAME_STRUCT short_net_name; + LIBLTE_MME_TIME_ZONE_AND_TIME_STRUCT utc_and_local_time_zone; + LIBLTE_MME_DAYLIGHT_SAVING_TIME_ENUM net_dst; + uint8 local_time_zone; + bool full_net_name_present; + bool short_net_name_present; + bool local_time_zone_present; + bool utc_and_local_time_zone_present; + bool net_dst_present; +}LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_emm_information_msg(LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT *emm_info, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_emm_information_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT *emm_info); /********************************************************************* Message Name: EMM Status @@ -1857,8 +3080,18 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + uint8 emm_cause; +}LIBLTE_MME_EMM_STATUS_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_emm_status_msg(LIBLTE_MME_EMM_STATUS_MSG_STRUCT *emm_status, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_emm_status_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_EMM_STATUS_MSG_STRUCT *emm_status); /********************************************************************* Message Name: Extended Service Request @@ -1875,10 +3108,31 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.2.15 *********************************************************************/ // Defines +#define LIBLTE_MME_CSFB_RESPONSE_IEI 0xB +#define LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_IEI 0x57 +#define LIBLTE_MME_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_IEI 0xD // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; + LIBLTE_MME_MOBILE_ID_STRUCT m_tmsi; + LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_STRUCT eps_bearer_context_status; + LIBLTE_MME_DEVICE_PROPERTIES_ENUM device_props; + uint8 service_type; + uint8 csfb_resp; + bool csfb_resp_present; + bool eps_bearer_context_status_present; + bool device_props_present; +}LIBLTE_MME_EXTENDED_SERVICE_REQUEST_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_extended_service_request_msg(LIBLTE_MME_EXTENDED_SERVICE_REQUEST_MSG_STRUCT *ext_service_req, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_extended_service_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_EXTENDED_SERVICE_REQUEST_MSG_STRUCT *ext_service_req); /********************************************************************* Message Name: GUTI Reallocation Command @@ -1889,10 +3143,23 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.2.16 *********************************************************************/ // Defines +#define LIBLTE_MME_TAI_LIST_IEI 0x54 // Enums // Structs +typedef struct{ + LIBLTE_MME_EPS_MOBILE_ID_STRUCT guti; + LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_STRUCT tai_list; + bool tai_list_present; +}LIBLTE_MME_GUTI_REALLOCATION_COMMAND_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_guti_reallocation_command_msg(LIBLTE_MME_GUTI_REALLOCATION_COMMAND_MSG_STRUCT *guti_realloc_cmd, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_reallocation_command_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_GUTI_REALLOCATION_COMMAND_MSG_STRUCT *guti_realloc_cmd); /********************************************************************* Message Name: GUTI Reallocation Complete @@ -1905,8 +3172,17 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ +}LIBLTE_MME_GUTI_REALLOCATION_COMPLETE_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_guti_reallocation_complete_msg(LIBLTE_MME_GUTI_REALLOCATION_COMPLETE_MSG_STRUCT *guti_realloc_complete, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_reallocation_complete_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_GUTI_REALLOCATION_COMPLETE_MSG_STRUCT *guti_realloc_complete); /********************************************************************* Message Name: Identity Request @@ -1919,8 +3195,14 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + uint8 id_type; +}LIBLTE_MME_ID_REQUEST_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_identity_request_msg(LIBLTE_MME_ID_REQUEST_MSG_STRUCT *id_req, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ID_REQUEST_MSG_STRUCT *id_req); /********************************************************************* Message Name: Identity Response @@ -1934,8 +3216,14 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_MOBILE_ID_STRUCT mobile_id; +}LIBLTE_MME_ID_RESPONSE_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_identity_response_msg(LIBLTE_MME_ID_RESPONSE_MSG_STRUCT *id_resp, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ID_RESPONSE_MSG_STRUCT *id_resp); /********************************************************************* Message Name: Security Mode Command @@ -1946,10 +3234,31 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.2.20 *********************************************************************/ // Defines +#define LIBLTE_MME_IMEISV_REQUEST_IEI 0xC +#define LIBLTE_MME_REPLAYED_NONCE_UE_IEI 0x55 +#define LIBLTE_MME_NONCE_MME_IEI 0x56 // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT selected_nas_sec_algs; + LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; + LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT ue_security_cap; + LIBLTE_MME_IMEISV_REQUEST_ENUM imeisv_req; + uint32 nonce_ue; + uint32 nonce_mme; + bool imeisv_req_present; + bool nonce_ue_present; + bool nonce_mme_present; +}LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_security_mode_command_msg(LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT *sec_mode_cmd, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_security_mode_command_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT *sec_mode_cmd); /********************************************************************* Message Name: Security Mode Complete @@ -1960,10 +3269,22 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.2.21 *********************************************************************/ // Defines +#define LIBLTE_MME_IMEISV_IEI 0x23 // Enums // Structs +typedef struct{ + LIBLTE_MME_MOBILE_ID_STRUCT imeisv; + bool imeisv_present; +}LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_security_mode_complete_msg(LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT *sec_mode_comp, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_security_mode_complete_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT *sec_mode_comp); /********************************************************************* Message Name: Security Mode Reject @@ -1977,23 +3298,14 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + uint8 emm_cause; +}LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT; // Functions -// FIXME - -/********************************************************************* - Message Name: Security Protected NAS Message - - Description: Sent by the UE or the network to transfer a NAS - message together with the sequence number and the - message authentication code protecting the message. - - Document Reference: 24.301 v10.2.0 Section 8.2.23 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_security_mode_reject_msg(LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT *sec_mode_rej, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_security_mode_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT *sec_mode_rej); /********************************************************************* Message Name: Service Reject @@ -2004,10 +3316,25 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.2.24 *********************************************************************/ // Defines +#define LIBLTE_MME_T3442_VALUE_IEI 0x5B // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_GPRS_TIMER_STRUCT t3442; + uint8 emm_cause; + uint8 t3446; + bool t3442_present; + bool t3446_present; +}LIBLTE_MME_SERVICE_REJECT_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_service_reject_msg(LIBLTE_MME_SERVICE_REJECT_MSG_STRUCT *service_rej, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_service_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_SERVICE_REJECT_MSG_STRUCT *service_rej); /********************************************************************* Message Name: Service Request @@ -2021,8 +3348,15 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_KSI_AND_SEQUENCE_NUMBER_STRUCT ksi_and_seq_num; + uint16 short_mac; +}LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_service_request_msg(LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT *service_req, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_service_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT *service_req); /********************************************************************* Message Name: Tracking Area Update Accept @@ -2034,10 +3368,49 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.2.26 *********************************************************************/ // Defines +#define LIBLTE_MME_T3412_VALUE_IEI 0x5A // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_GPRS_TIMER_STRUCT t3412; + LIBLTE_MME_EPS_MOBILE_ID_STRUCT guti; + LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_STRUCT tai_list; + LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_STRUCT eps_bearer_context_status; + LIBLTE_MME_LOCATION_AREA_ID_STRUCT lai; + LIBLTE_MME_MOBILE_ID_STRUCT ms_id; + LIBLTE_MME_GPRS_TIMER_STRUCT t3402; + LIBLTE_MME_GPRS_TIMER_STRUCT t3423; + LIBLTE_MME_PLMN_LIST_STRUCT equivalent_plmns; + LIBLTE_MME_EMERGENCY_NUMBER_LIST_STRUCT emerg_num_list; + LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_STRUCT eps_network_feature_support; + LIBLTE_MME_GPRS_TIMER_3_STRUCT t3412_ext; + LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM additional_update_result; + uint8 eps_update_result; + uint8 emm_cause; + bool t3412_present; + bool guti_present; + bool tai_list_present; + bool eps_bearer_context_status_present; + bool lai_present; + bool ms_id_present; + bool emm_cause_present; + bool t3402_present; + bool t3423_present; + bool equivalent_plmns_present; + bool emerg_num_list_present; + bool eps_network_feature_support_present; + bool additional_update_result_present; + bool t3412_ext_present; +}LIBLTE_MME_TRACKING_AREA_UPDATE_ACCEPT_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_update_accept_msg(LIBLTE_MME_TRACKING_AREA_UPDATE_ACCEPT_MSG_STRUCT *ta_update_accept, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_update_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_TRACKING_AREA_UPDATE_ACCEPT_MSG_STRUCT *ta_update_accept); /********************************************************************* Message Name: Tracking Area Update Complete @@ -2051,8 +3424,17 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ +}LIBLTE_MME_TRACKING_AREA_UPDATE_COMPLETE_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_update_complete_msg(LIBLTE_MME_TRACKING_AREA_UPDATE_COMPLETE_MSG_STRUCT *ta_update_complete, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_update_complete_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_TRACKING_AREA_UPDATE_COMPLETE_MSG_STRUCT *ta_update_complete); /********************************************************************* Message Name: Tracking Area Update Reject @@ -2065,8 +3447,20 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + uint8 emm_cause; + uint8 t3446; + bool t3446_present; +}LIBLTE_MME_TRACKING_AREA_UPDATE_REJECT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_update_reject_msg(LIBLTE_MME_TRACKING_AREA_UPDATE_REJECT_MSG_STRUCT *ta_update_rej, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_update_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_TRACKING_AREA_UPDATE_REJECT_MSG_STRUCT *ta_update_rej); /********************************************************************* Message Name: Tracking Area Update Request @@ -2077,10 +3471,68 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.2.29 *********************************************************************/ // Defines +#define LIBLTE_MME_NAS_KEY_SET_IDENTIFIER_IEI 0xB +#define LIBLTE_MME_CIPHERING_KEY_SEQUENCE_NUMBER_IEI 0x8 +#define LIBLTE_MME_NONCE_UE_IEI 0x55 +#define LIBLTE_MME_UE_NETWORK_CAPABILITY_IEI 0x58 +#define LIBLTE_MME_UE_RADIO_CAPABILITY_INFORMATION_UPDATE_NEEDED_IEI 0xA +#define LIBLTE_MME_TRACKING_AREA_UPDATE_REQUEST_DEVICE_PROPERTIES_IEI 0xD // Enums // Structs +typedef struct{ + LIBLTE_MME_EPS_UPDATE_TYPE_STRUCT eps_update_type; + LIBLTE_MME_NAS_KEY_SET_ID_STRUCT nas_ksi; + LIBLTE_MME_EPS_MOBILE_ID_STRUCT old_guti; + LIBLTE_MME_NAS_KEY_SET_ID_STRUCT non_current_native_nas_ksi; + LIBLTE_MME_EPS_MOBILE_ID_STRUCT additional_guti; + LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT ue_network_cap; + LIBLTE_MME_TRACKING_AREA_ID_STRUCT last_visited_registered_tai; + LIBLTE_MME_DRX_PARAMETER_STRUCT drx_param; + LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_STRUCT eps_bearer_context_status; + LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT ms_network_cap; + LIBLTE_MME_LOCATION_AREA_ID_STRUCT old_lai; + LIBLTE_MME_MOBILE_STATION_CLASSMARK_2_STRUCT ms_cm2; + LIBLTE_MME_MOBILE_STATION_CLASSMARK_3_STRUCT ms_cm3; + LIBLTE_MME_SUPPORTED_CODEC_LIST_STRUCT supported_codecs; + LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_STRUCT voice_domain_pref_and_ue_usage_setting; + LIBLTE_MME_TMSI_STATUS_ENUM tmsi_status; + LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_ENUM additional_update_type; + LIBLTE_MME_GUTI_TYPE_ENUM old_guti_type; + LIBLTE_MME_DEVICE_PROPERTIES_ENUM device_properties; + uint32 old_p_tmsi_signature; + uint32 nonce_ue; + uint8 gprs_ciphering_ksn; + uint8 ue_radio_cap_update_needed; + bool non_current_native_nas_ksi_present; + bool gprs_ciphering_ksn_present; + bool old_p_tmsi_signature_present; + bool additional_guti_present; + bool nonce_ue_present; + bool ue_network_cap_present; + bool last_visited_registered_tai_present; + bool drx_param_present; + bool ue_radio_cap_update_needed_present; + bool eps_bearer_context_status_present; + bool ms_network_cap_present; + bool old_lai_present; + bool tmsi_status_present; + bool ms_cm2_present; + bool ms_cm3_present; + bool supported_codecs_present; + bool additional_update_type_present; + bool voice_domain_pref_and_ue_usage_setting_present; + bool old_guti_type_present; + bool device_properties_present; +}LIBLTE_MME_TRACKING_AREA_UPDATE_REQUEST_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_update_request_msg(LIBLTE_MME_TRACKING_AREA_UPDATE_REQUEST_MSG_STRUCT *ta_update_req, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_update_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_TRACKING_AREA_UPDATE_REQUEST_MSG_STRUCT *ta_update_req); /********************************************************************* Message Name: Uplink NAS Transport @@ -2093,8 +3545,18 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_BYTE_MSG_STRUCT nas_msg; +}LIBLTE_MME_UPLINK_NAS_TRANSPORT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_uplink_nas_transport_msg(LIBLTE_MME_UPLINK_NAS_TRANSPORT_MSG_STRUCT *ul_nas_transport, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_uplink_nas_transport_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_UPLINK_NAS_TRANSPORT_MSG_STRUCT *ul_nas_transport); /********************************************************************* Message Name: Downlink Generic NAS Transport @@ -2107,8 +3569,21 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_BYTE_MSG_STRUCT generic_msg_cont; + LIBLTE_MME_ADDITIONAL_INFORMATION_STRUCT add_info; + uint8 generic_msg_cont_type; + bool add_info_present; +}LIBLTE_MME_DOWNLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_downlink_generic_nas_transport_msg(LIBLTE_MME_DOWNLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT *dl_generic_nas_transport, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_downlink_generic_nas_transport_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DOWNLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT *dl_generic_nas_transport); /********************************************************************* Message Name: Uplink Generic NAS Transport @@ -2121,8 +3596,21 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_BYTE_MSG_STRUCT generic_msg_cont; + LIBLTE_MME_ADDITIONAL_INFORMATION_STRUCT add_info; + uint8 generic_msg_cont_type; + bool add_info_present; +}LIBLTE_MME_UPLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_uplink_generic_nas_transport_msg(LIBLTE_MME_UPLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT *ul_generic_nas_transport, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_uplink_generic_nas_transport_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_UPLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT *ul_generic_nas_transport); /********************************************************************* Message Name: Activate Dedicated EPS Bearer Context Accept @@ -2135,10 +3623,20 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.3.1 *********************************************************************/ // Defines +#define LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI 0x27 // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_dedicated_eps_bearer_context_accept_msg(LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *act_ded_eps_bearer_context_accept, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_dedicated_eps_bearer_context_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *act_ded_eps_bearer_context_accept); /********************************************************************* Message Name: Activate Dedicated EPS Bearer Context Reject @@ -2151,8 +3649,18 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 esm_cause; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_dedicated_eps_bearer_context_reject_msg(LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *act_ded_eps_bearer_context_rej, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_dedicated_eps_bearer_context_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *act_ded_eps_bearer_context_rej); /********************************************************************* Message Name: Activate Dedicated EPS Bearer Context Request @@ -2167,8 +3675,30 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT eps_qos; + LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT tft; + LIBLTE_MME_TRANSACTION_IDENTIFIER_STRUCT transaction_id; + LIBLTE_MME_QUALITY_OF_SERVICE_STRUCT negotiated_qos; + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 linked_eps_bearer_id; + uint8 llc_sapi; + uint8 radio_prio; + uint8 packet_flow_id; + bool transaction_id_present; + bool negotiated_qos_present; + bool llc_sapi_present; + bool radio_prio_present; + bool packet_flow_id_present; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_dedicated_eps_bearer_context_request_msg(LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *act_ded_eps_bearer_context_req, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_dedicated_eps_bearer_context_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *act_ded_eps_bearer_context_req); /********************************************************************* Message Name: Activate Default EPS Bearer Context Accept @@ -2181,8 +3711,17 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_default_eps_bearer_context_accept_msg(LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *act_def_eps_bearer_context_accept, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_default_eps_bearer_context_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *act_def_eps_bearer_context_accept); /********************************************************************* Message Name: Activate Default EPS Bearer Context Reject @@ -2195,8 +3734,18 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 esm_cause; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_default_eps_bearer_context_reject_msg(LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *act_def_eps_bearer_context_rej, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_default_eps_bearer_context_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *act_def_eps_bearer_context_rej); /********************************************************************* Message Name: Activate Default EPS Bearer Context Request @@ -2207,10 +3756,46 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.3.6 *********************************************************************/ // Defines +#define LIBLTE_MME_TRANSACTION_IDENTIFIER_IEI 0x5D +#define LIBLTE_MME_QUALITY_OF_SERVICE_IEI 0x30 +#define LIBLTE_MME_LLC_SAPI_IEI 0x32 +#define LIBLTE_MME_RADIO_PRIORITY_IEI 0x8 +#define LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI 0x34 +#define LIBLTE_MME_APN_AMBR_IEI 0x5E +#define LIBLTE_MME_ESM_CAUSE_IEI 0x58 +#define LIBLTE_MME_CONNECTIVITY_TYPE_IEI 0xB // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT eps_qos; + LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn; + LIBLTE_MME_PDN_ADDRESS_STRUCT pdn_addr; + LIBLTE_MME_TRANSACTION_IDENTIFIER_STRUCT transaction_id; + LIBLTE_MME_QUALITY_OF_SERVICE_STRUCT negotiated_qos; + LIBLTE_MME_APN_AGGREGATE_MAXIMUM_BIT_RATE_STRUCT apn_ambr; + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 llc_sapi; + uint8 radio_prio; + uint8 packet_flow_id; + uint8 esm_cause; + uint8 connectivity_type; + bool transaction_id_present; + bool negotiated_qos_present; + bool llc_sapi_present; + bool radio_prio_present; + bool packet_flow_id_present; + bool apn_ambr_present; + bool esm_cause_present; + bool protocol_cnfg_opts_present; + bool connectivity_type_present; +}LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_default_eps_bearer_context_request_msg(LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *act_def_eps_bearer_context_req, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_default_eps_bearer_context_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *act_def_eps_bearer_context_req); /********************************************************************* Message Name: Bearer Resource Allocation Reject @@ -2221,10 +3806,23 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.3.7 *********************************************************************/ // Defines +#define LIBLTE_MME_T3496_VALUE_IEI 0x37 // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + LIBLTE_MME_GPRS_TIMER_3_STRUCT t3496; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 esm_cause; + bool protocol_cnfg_opts_present; + bool t3496_present; +}LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REJECT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_allocation_reject_msg(LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REJECT_MSG_STRUCT *bearer_res_alloc_rej, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_allocation_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REJECT_MSG_STRUCT *bearer_res_alloc_rej); /********************************************************************* Message Name: Bearer Resource Allocation Request @@ -2235,10 +3833,25 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.3.8 *********************************************************************/ // Defines +#define LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_IEI 0xC // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_TRAFFIC_FLOW_AGGREGATE_DESCRIPTION_STRUCT tfa; + LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT req_tf_qos; + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + LIBLTE_MME_DEVICE_PROPERTIES_ENUM device_properties; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 linked_eps_bearer_id; + bool protocol_cnfg_opts_present; + bool device_properties_present; +}LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_allocation_request_msg(LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_MSG_STRUCT *bearer_res_alloc_req, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_allocation_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_MSG_STRUCT *bearer_res_alloc_req); /********************************************************************* Message Name: Bearer Resource Modification Reject @@ -2251,8 +3864,20 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + LIBLTE_MME_GPRS_TIMER_3_STRUCT t3496; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 esm_cause; + bool protocol_cnfg_opts_present; + bool t3496_present; +}LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REJECT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_modification_reject_msg(LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REJECT_MSG_STRUCT *bearer_res_mod_rej, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_modification_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REJECT_MSG_STRUCT *bearer_res_mod_rej); /********************************************************************* Message Name: Bearer Resource Modification Request @@ -2263,10 +3888,29 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.3.10 *********************************************************************/ // Defines +#define LIBLTE_MME_EPS_QUALITY_OF_SERVICE_IEI 0x5B +#define LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_IEI 0xC // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_TRAFFIC_FLOW_AGGREGATE_DESCRIPTION_STRUCT tfa; + LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT req_tf_qos; + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + LIBLTE_MME_DEVICE_PROPERTIES_ENUM device_properties; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 eps_bearer_id_for_packet_filter; + uint8 esm_cause; + bool req_tf_qos_present; + bool esm_cause_present; + bool protocol_cnfg_opts_present; + bool device_properties_present; +}LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_modification_request_msg(LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_MSG_STRUCT *bearer_res_mod_req, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_modification_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_MSG_STRUCT *bearer_res_mod_req); /********************************************************************* Message Name: Deactivate EPS Bearer Context Accept @@ -2280,8 +3924,17 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_deactivate_eps_bearer_context_accept_msg(LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *deact_eps_bearer_context_accept, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_deactivate_eps_bearer_context_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *deact_eps_bearer_context_accept); /********************************************************************* Message Name: Deactivate EPS Bearer Context Request @@ -2294,8 +3947,18 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 esm_cause; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_deactivate_eps_bearer_context_request_msg(LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *deact_eps_bearer_context_req, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_deactivate_eps_bearer_context_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *deact_eps_bearer_context_req); /********************************************************************* Message Name: ESM Information Request @@ -2309,8 +3972,15 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + uint8 eps_bearer_id; + uint8 proc_transaction_id; +}LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req); /********************************************************************* Message Name: ESM Information Response @@ -2324,8 +3994,19 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn; + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + bool apn_present; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_response_msg(LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp); /********************************************************************* Message Name: ESM Status @@ -2339,8 +4020,16 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 esm_cause; +}LIBLTE_MME_ESM_STATUS_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_esm_status_msg(LIBLTE_MME_ESM_STATUS_MSG_STRUCT *esm_status, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_status_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ESM_STATUS_MSG_STRUCT *esm_status); /********************************************************************* Message Name: Modify EPS Bearer Context Accept @@ -2353,8 +4042,17 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_modify_eps_bearer_context_accept_msg(LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *mod_eps_bearer_context_accept, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_modify_eps_bearer_context_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *mod_eps_bearer_context_accept); /********************************************************************* Message Name: Modify EPS Bearer Context Reject @@ -2367,8 +4065,18 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 esm_cause; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_modify_eps_bearer_context_reject_msg(LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *mod_eps_bearer_context_rej, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_modify_eps_bearer_context_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *mod_eps_bearer_context_rej); /********************************************************************* Message Name: Modify EPS Bearer Context Request @@ -2379,10 +4087,35 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT Document Reference: 24.301 v10.2.0 Section 8.3.18 *********************************************************************/ // Defines +#define LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_IEI 0x36 +#define LIBLTE_MME_QUALITY_OF_SERVICE_IEI 0x30 // Enums // Structs -// Functions -// FIXME +typedef struct{ + LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT new_eps_qos; + LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT tft; + LIBLTE_MME_QUALITY_OF_SERVICE_STRUCT new_qos; + LIBLTE_MME_APN_AGGREGATE_MAXIMUM_BIT_RATE_STRUCT apn_ambr; + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 negotiated_llc_sapi; + uint8 radio_prio; + uint8 packet_flow_id; + bool new_eps_qos_present; + bool tft_present; + bool new_qos_present; + bool negotiated_llc_sapi_present; + bool radio_prio_present; + bool packet_flow_id_present; + bool apn_ambr_present; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_mme_pack_modify_eps_bearer_context_request_msg(LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *mod_eps_bearer_context_req, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_modify_eps_bearer_context_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *mod_eps_bearer_context_req); /********************************************************************* Message Name: Notification @@ -2397,8 +4130,16 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 notification_ind; +}LIBLTE_MME_NOTIFICATION_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_notification_msg(LIBLTE_MME_NOTIFICATION_MSG_STRUCT *notification, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_notification_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_NOTIFICATION_MSG_STRUCT *notification); /********************************************************************* Message Name: PDN Connectivity Reject @@ -2411,8 +4152,20 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + LIBLTE_MME_GPRS_TIMER_3_STRUCT t3496; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 esm_cause; + bool protocol_cnfg_opts_present; + bool t3496_present; +}LIBLTE_MME_PDN_CONNECTIVITY_REJECT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_connectivity_reject_msg(LIBLTE_MME_PDN_CONNECTIVITY_REJECT_MSG_STRUCT *pdn_con_rej, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_connectivity_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_PDN_CONNECTIVITY_REJECT_MSG_STRUCT *pdn_con_rej); /********************************************************************* Message Name: PDN Connectivity Request @@ -2425,7 +4178,6 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT // Defines #define LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_IEI 0xD #define LIBLTE_MME_ACCESS_POINT_NAME_IEI 0x28 -#define LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_IEI 0x27 #define LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_DEVICE_PROPERTIES_IEI 0xC // Enums // Structs @@ -2460,8 +4212,18 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_connectivity_request_msg(LIBLTE_BYTE_MSG // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 esm_cause; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_PDN_DISCONNECT_REJECT_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_disconnect_reject_msg(LIBLTE_MME_PDN_DISCONNECT_REJECT_MSG_STRUCT *pdn_discon_rej, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_disconnect_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_PDN_DISCONNECT_REJECT_MSG_STRUCT *pdn_discon_rej); /********************************************************************* Message Name: PDN Disconnect Request @@ -2474,7 +4236,17 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_connectivity_request_msg(LIBLTE_BYTE_MSG // Defines // Enums // Structs +typedef struct{ + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + uint8 linked_eps_bearer_id; + bool protocol_cnfg_opts_present; +}LIBLTE_MME_PDN_DISCONNECT_REQUEST_MSG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_disconnect_request_msg(LIBLTE_MME_PDN_DISCONNECT_REQUEST_MSG_STRUCT *pdn_discon_req, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_disconnect_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_PDN_DISCONNECT_REQUEST_MSG_STRUCT *pdn_discon_req); #endif /* __LIBLTE_MME_H__ */ diff --git a/liblte/hdr/liblte_pdcp.h b/liblte/hdr/liblte_pdcp.h new file mode 100755 index 0000000..4b9771a --- /dev/null +++ b/liblte/hdr/liblte_pdcp.h @@ -0,0 +1,262 @@ +/******************************************************************************* + + Copyright 2014-2015 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: liblte_pdcp.h + + Description: Contains all the definitions for the LTE Packet Data + Convergence Protocol Layer library. + + Revision History + ---------- ------------- -------------------------------------------- + 08/03/2014 Ben Wojtowicz Created file. + 11/01/2014 Ben Wojtowicz Added integrity protection of messages. + 11/29/2014 Ben Wojtowicz Using the byte message struct for everything + except RRC SDUs and added user plan data + processing. + 03/11/2015 Ben Wojtowicz Added data PDU with short SN support. + 12/06/2015 Ben Wojtowicz Added control PDU for interspersed ROHC + feedback and RN user plane data PDU with + integrity protection support. + +*******************************************************************************/ + +#ifndef __LIBLTE_PDCP_H__ +#define __LIBLTE_PDCP_H__ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "liblte_common.h" + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + PARAMETER DECLARATIONS +*******************************************************************************/ + +/********************************************************************* + Parameter: MAC-I + + Description: Carries the calculated message authentication code. + + Document Reference: 36.323 v10.1.0 Section 6.3.4 +*********************************************************************/ +// Defines +#define LIBLTE_PDCP_CONTROL_MAC_I 0x00000000 +// Enums +// Structs +// Functions + +/********************************************************************* + Parameter: D/C + + Description: Specifies whether the PDU is data or control. + + Document Reference: 36.323 v10.1.0 Section 6.3.7 +*********************************************************************/ +// Defines +// Enums +typedef enum{ + LIBLTE_PDCP_D_C_CONTROL_PDU = 0, + LIBLTE_PDCP_D_C_DATA_PDU, + LIBLTE_PDCP_D_C_N_ITEMS, +}LIBLTE_PDCP_D_C_ENUM; +static const char liblte_pdcp_d_c_text[LIBLTE_PDCP_D_C_N_ITEMS][20] = {"Control PDU", + "Data PDU"}; +// Structs +// Functions + +/********************************************************************* + Parameter: PDU Type + + Description: Specifies what type of PDU is present. + + Document Reference: 36.323 v10.1.0 Section 6.3.8 +*********************************************************************/ +// Defines +#define LIBLTE_PDCP_PDU_TYPE_PDCP_STATUS_REPORT 0x0 +#define LIBLTE_PDCP_PDU_TYPE_INTERSPERSED_ROHC_FEEDBACK_PACKET 0x1 +// Enums +// Structs +// Functions + +/********************************************************************* + Parameter: Bitmap + + Description: Specifies whether SDUs have or have not been + received. + + Document Reference: 36.323 v10.1.0 Section 6.3.10 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions + +/******************************************************************************* + PDU DECLARATIONS +*******************************************************************************/ + +/********************************************************************* + PDU Type: Control Plane PDCP Data PDU + + Document Reference: 36.323 v10.1.0 Section 6.2.2 +*********************************************************************/ +// Defines +// Enums +// Structs +typedef struct{ + LIBLTE_BIT_MSG_STRUCT data; + uint32 count; +}LIBLTE_PDCP_CONTROL_PDU_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu(LIBLTE_PDCP_CONTROL_PDU_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu(LIBLTE_PDCP_CONTROL_PDU_STRUCT *contents, + LIBLTE_BIT_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu(LIBLTE_PDCP_CONTROL_PDU_STRUCT *contents, + uint8 *key_256, + uint8 direction, + uint8 rb_id, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu(LIBLTE_PDCP_CONTROL_PDU_STRUCT *contents, + LIBLTE_BIT_MSG_STRUCT *data, + uint8 *key_256, + uint8 direction, + uint8 rb_id, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_unpack_control_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_PDCP_CONTROL_PDU_STRUCT *contents); + +/********************************************************************* + PDU Type: User Plane PDCP Data PDU with long PDCP SN + + Document Reference: 36.323 v10.1.0 Section 6.2.3 +*********************************************************************/ +// Defines +// Enums +// Structs +typedef struct{ + LIBLTE_BYTE_MSG_STRUCT data; + uint32 count; +}LIBLTE_PDCP_DATA_PDU_WITH_LONG_SN_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_pdcp_pack_data_pdu_with_long_sn(LIBLTE_PDCP_DATA_PDU_WITH_LONG_SN_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_pack_data_pdu_with_long_sn(LIBLTE_PDCP_DATA_PDU_WITH_LONG_SN_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_unpack_data_pdu_with_long_sn(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_PDCP_DATA_PDU_WITH_LONG_SN_STRUCT *contents); + +/********************************************************************* + PDU Type: User Plane PDCP Data PDU with short PDCP SN + + Document Reference: 36.323 v10.1.0 Section 6.2.4 +*********************************************************************/ +// Defines +// Enums +// Structs +typedef LIBLTE_PDCP_DATA_PDU_WITH_LONG_SN_STRUCT LIBLTE_PDCP_DATA_PDU_WITH_SHORT_SN_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_pdcp_pack_data_pdu_with_short_sn(LIBLTE_PDCP_DATA_PDU_WITH_SHORT_SN_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_pack_data_pdu_with_short_sn(LIBLTE_PDCP_DATA_PDU_WITH_SHORT_SN_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_unpack_data_pdu_with_short_sn(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_PDCP_DATA_PDU_WITH_SHORT_SN_STRUCT *contents); + +/********************************************************************* + PDU Type: PDCP Control PDU for interspersed ROHC feedback packet + + Document Reference: 36.323 v10.1.0 Section 6.2.5 +*********************************************************************/ +// Defines +#define LIBLTE_PDCP_PDU_TYPE_STATUS_REPORT 0x0 +#define LIBLTE_PDCP_PDU_TYPE_INTERSPERSED_ROHC_FEEDBACK_PACKET 0x1 +// Enums +// Structs +typedef struct{ + LIBLTE_BYTE_MSG_STRUCT rohc_feedback_packet; + uint8 pdu_type; +}LIBLTE_PDCP_CONTROL_PDU_FOR_INTERSPERSED_ROHC_FEEDBACK_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu_for_interspersed_rohc_feedback(LIBLTE_PDCP_CONTROL_PDU_FOR_INTERSPERSED_ROHC_FEEDBACK_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu_for_interspersed_rohc_feedback(LIBLTE_PDCP_CONTROL_PDU_FOR_INTERSPERSED_ROHC_FEEDBACK_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *rohc_feedback_packet, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_unpack_control_pdu_for_interspersed_rohc_feedback(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_PDCP_CONTROL_PDU_FOR_INTERSPERSED_ROHC_FEEDBACK_STRUCT *contents); + +/********************************************************************* + PDU Type: PDCP Control PDU for PDCP status report + + Document Reference: 36.323 v10.1.0 Section 6.2.6 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +// FIXME + +/********************************************************************* + PDU Type: RN User Plane PDCP Data PDU with integrity protection + + Document Reference: 36.323 v10.1.0 Section 6.2.8 +*********************************************************************/ +// Defines +// Enums +// Structs +typedef struct{ + LIBLTE_BYTE_MSG_STRUCT data; + uint32 count; +}LIBLTE_PDCP_RN_USER_PLANE_DATA_PDU_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_pdcp_pack_rn_user_plane_data_pdu(LIBLTE_PDCP_RN_USER_PLANE_DATA_PDU_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_pack_rn_user_plane_data_pdu(LIBLTE_PDCP_RN_USER_PLANE_DATA_PDU_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_pack_rn_user_plane_data_pdu(LIBLTE_PDCP_RN_USER_PLANE_DATA_PDU_STRUCT *contents, + uint8 *key_256, + uint8 direction, + uint8 rb_id, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_pack_rn_user_plane_data_pdu(LIBLTE_PDCP_RN_USER_PLANE_DATA_PDU_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *data, + uint8 *key_256, + uint8 direction, + uint8 rb_id, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_pdcp_unpack_rn_user_plane_data_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_PDCP_RN_USER_PLANE_DATA_PDU_STRUCT *contents); + +#endif /* __LIBLTE_PDCP_H__ */ diff --git a/liblte/hdr/liblte_phy.h b/liblte/hdr/liblte_phy.h old mode 100644 new mode 100755 index 1168f68..bd575e4 --- a/liblte/hdr/liblte_phy.h +++ b/liblte/hdr/liblte_phy.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2012-2014 Ben Wojtowicz + Copyright 2012-2017 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -60,6 +60,24 @@ in each slot. 05/04/2014 Ben Wojtowicz Added PHICH and TPC support. 06/15/2014 Ben Wojtowicz Added TPC values for DCI 0, 3, and 4. + 07/14/2015 Ben Wojtowicz Added a constant definition of Fs as an + integer. + 12/06/2015 Ben Wojtowicz Added defines for many of the array sizes in + LIBLTE_PHY_STRUCT and corrected the order of + sizes in the rate match/unmatch arrays in + LIBLTE_PHY_STRUCT (thanks to Ziming He for + finding this). + 02/13/2016 Ben Wojtowicz Moved turbo coder rate match/unmatch and + code block segmentation/desegmentation to + globally available routines to support unit + tests. + 03/12/2016 Ben Wojtowicz Added PUCCH channel decode support. + 07/03/2016 Ben Wojtowicz Added PDCCH size defines. + 07/31/2016 Ben Wojtowicz Added harq_retx_count to allocation struct. + 07/29/2017 Ben Wojtowicz Added two codeword support, refactored PUCCH + channel decoding for PUCCH types 1, 1A, and + 1B, and added a function to map the SR + configuration index. *******************************************************************************/ @@ -108,6 +126,10 @@ #define LIBLTE_PHY_N_SC_RB_DL_NORMAL_CP 12 // FIXME: Add Extended CP +// M_pucch_rs +#define LIBLTE_PHY_M_PUCCH_RS 3 +// FIXME: Add Extended CP + // N_ant #define LIBLTE_PHY_N_ANT_MAX 4 @@ -152,6 +174,21 @@ #define LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ (LIBLTE_PHY_N_SAMPS_PER_SLOT_1_92MHZ*LIBLTE_PHY_N_SLOTS_PER_SUBFR) #define LIBLTE_PHY_N_SAMPS_PER_FRAME_1_92MHZ (LIBLTE_PHY_N_SAMPS_PER_SUBFR_1_92MHZ*LIBLTE_PHY_N_SUBFR_PER_FRAME) +// Turbo/Viterbi coding +#define LIBLTE_PHY_MAX_CODE_BLOCK_SIZE 6176 +#define LIBLTE_PHY_MAX_VITERBI_STATES 128 +#define LIBLTE_PHY_BASE_CODING_RATE 3 + +// Rate matching +#define LIBLTE_PHY_N_COLUMNS_RATE_MATCH 32 + +// PDCCH +#define LIBLTE_PHY_PDCCH_N_REGS_MAX 787 +#define LIBLTE_PHY_PDCCH_N_REG_CCE 9 +#define LIBLTE_PHY_PDCCH_N_RE_CCE (LIBLTE_PHY_PDCCH_N_REG_CCE * 4) +#define LIBLTE_PHY_PDCCH_N_CCE_MAX (LIBLTE_PHY_PDCCH_N_REGS_MAX / LIBLTE_PHY_PDCCH_N_REG_CCE) +#define LIBLTE_PHY_PDCCH_N_BITS_MAX 576 + /******************************************************************************* TYPEDEFS *******************************************************************************/ @@ -165,6 +202,7 @@ typedef enum{ LIBLTE_PHY_FS_N_ITEMS, }LIBLTE_PHY_FS_ENUM; static const char liblte_phy_fs_text[LIBLTE_PHY_FS_N_ITEMS][20] = {"1.92", "3.84", "7.68", "15.36", "30.72"}; +static const uint32 liblte_phy_fs_num[LIBLTE_PHY_FS_N_ITEMS] = {1920000, 3840000, 7680000, 15360000, 30720000}; typedef enum{ LIBLTE_PHY_PRE_CODER_TYPE_TX_DIVERSITY = 0, @@ -182,6 +220,7 @@ typedef enum{ LIBLTE_PHY_CHAN_TYPE_DLSCH = 0, LIBLTE_PHY_CHAN_TYPE_PCH, LIBLTE_PHY_CHAN_TYPE_ULSCH, + LIBLTE_PHY_CHAN_TYPE_ULCCH, }LIBLTE_PHY_CHAN_TYPE_ENUM; typedef struct{ @@ -242,6 +281,18 @@ typedef struct{ uint8 pusch_scramb_bits[28800]; int8 pusch_soft_bits[28800]; + // PUCCH + float pucch_z_est_re[LIBLTE_PHY_N_SC_RB_UL*14]; + float pucch_z_est_im[LIBLTE_PHY_N_SC_RB_UL*14]; + float pucch_c_est_0_re[LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL]; + float pucch_c_est_0_im[LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL]; + float pucch_c_est_1_re[LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL]; + float pucch_c_est_1_im[LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL]; + float pucch_c_est_re[LIBLTE_PHY_N_SC_RB_UL*14]; + float pucch_c_est_im[LIBLTE_PHY_N_SC_RB_UL*14]; + float pucch_z_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_N_SC_RB_UL*14]; + float pucch_z_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_N_SC_RB_UL*14]; + // UL Reference Signals float ulrs_x_q_re[2048]; float ulrs_x_q_im[2048]; @@ -250,11 +301,20 @@ typedef struct{ uint32 ulrs_c[160]; // DMRS - float dmrs_0_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL]; - float dmrs_0_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL]; - float dmrs_1_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL]; - float dmrs_1_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL]; - uint32 dmrs_c[1120]; + float pusch_dmrs_0_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL]; + float pusch_dmrs_0_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL]; + float pusch_dmrs_1_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL]; + float pusch_dmrs_1_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL]; + float pucch_dmrs_0_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL]; + float pucch_dmrs_0_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL]; + float pucch_dmrs_1_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL]; + float pucch_dmrs_1_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL]; + float pucch_r_u_v_alpha_p_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][2][7][LIBLTE_PHY_N_SC_RB_UL]; + float pucch_r_u_v_alpha_p_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][2][7][LIBLTE_PHY_N_SC_RB_UL]; + uint32 pusch_dmrs_c[1120]; + uint32 pucch_dmrs_c[1120]; + uint32 pucch_n_prime_p[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][2]; + uint32 pucch_n_oc_p[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][2]; // PRACH fftwf_complex *prach_dft_in; @@ -324,51 +384,50 @@ typedef struct{ int8 bch_soft_bits[480]; // PDCCH - // FIXME: Sizes - float pdcch_reg_y_est_re[550][4]; - float pdcch_reg_y_est_im[550][4]; - float pdcch_reg_c_est_re[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_reg_c_est_im[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_shift_y_est_re[550][4]; - float pdcch_shift_y_est_im[550][4]; - float pdcch_shift_c_est_re[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_shift_c_est_im[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_perm_y_est_re[550][4]; - float pdcch_perm_y_est_im[550][4]; - float pdcch_perm_c_est_re[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_perm_c_est_im[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_cce_y_est_re[50][576]; - float pdcch_cce_y_est_im[50][576]; - float pdcch_cce_c_est_re[LIBLTE_PHY_N_ANT_MAX][50][576]; - float pdcch_cce_c_est_im[LIBLTE_PHY_N_ANT_MAX][50][576]; - float pdcch_y_est_re[576]; - float pdcch_y_est_im[576]; - float pdcch_c_est_re[LIBLTE_PHY_N_ANT_MAX][576]; - float pdcch_c_est_im[LIBLTE_PHY_N_ANT_MAX][576]; - float pdcch_y_re[LIBLTE_PHY_N_ANT_MAX][576]; - float pdcch_y_im[LIBLTE_PHY_N_ANT_MAX][576]; - float pdcch_cce_re[LIBLTE_PHY_N_ANT_MAX][50][576]; - float pdcch_cce_im[LIBLTE_PHY_N_ANT_MAX][50][576]; - float pdcch_reg_re[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_reg_im[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_perm_re[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_perm_im[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_shift_re[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_shift_im[LIBLTE_PHY_N_ANT_MAX][550][4]; - float pdcch_x_re[576]; - float pdcch_x_im[576]; - float pdcch_d_re[576]; - float pdcch_d_im[576]; - float pdcch_descramb_bits[576]; - uint32 pdcch_c[1152]; - uint32 pdcch_permute_map[550][550]; - uint16 pdcch_reg_vec[550]; - uint16 pdcch_reg_perm_vec[550]; - uint8 pdcch_dci[100]; // FIXME: This is a guess at worst case - uint8 pdcch_encode_bits[576]; - uint8 pdcch_scramb_bits[576]; - int8 pdcch_soft_bits[576]; - bool pdcch_cce_used[50]; + float pdcch_reg_y_est_re[LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_reg_y_est_im[LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_reg_c_est_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_reg_c_est_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_shift_y_est_re[LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_shift_y_est_im[LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_shift_c_est_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_shift_c_est_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_perm_y_est_re[LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_perm_y_est_im[LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_perm_c_est_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_perm_c_est_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_cce_y_est_re[LIBLTE_PHY_PDCCH_N_CCE_MAX][LIBLTE_PHY_PDCCH_N_RE_CCE]; + float pdcch_cce_y_est_im[LIBLTE_PHY_PDCCH_N_CCE_MAX][LIBLTE_PHY_PDCCH_N_RE_CCE]; + float pdcch_cce_c_est_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_CCE_MAX][LIBLTE_PHY_PDCCH_N_RE_CCE]; + float pdcch_cce_c_est_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_CCE_MAX][LIBLTE_PHY_PDCCH_N_RE_CCE]; + float pdcch_y_est_re[LIBLTE_PHY_PDCCH_N_BITS_MAX / 2]; + float pdcch_y_est_im[LIBLTE_PHY_PDCCH_N_BITS_MAX / 2]; + float pdcch_c_est_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_BITS_MAX / 2]; + float pdcch_c_est_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_BITS_MAX / 2]; + float pdcch_y_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_BITS_MAX / 2]; + float pdcch_y_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_BITS_MAX / 2]; + float pdcch_cce_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_CCE_MAX][LIBLTE_PHY_PDCCH_N_RE_CCE]; + float pdcch_cce_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_CCE_MAX][LIBLTE_PHY_PDCCH_N_RE_CCE]; + float pdcch_reg_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_reg_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_perm_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_perm_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_shift_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_shift_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX][4]; + float pdcch_x_re[LIBLTE_PHY_PDCCH_N_BITS_MAX / 2]; + float pdcch_x_im[LIBLTE_PHY_PDCCH_N_BITS_MAX / 2]; + float pdcch_d_re[LIBLTE_PHY_PDCCH_N_BITS_MAX / 2]; + float pdcch_d_im[LIBLTE_PHY_PDCCH_N_BITS_MAX / 2]; + float pdcch_descramb_bits[LIBLTE_PHY_PDCCH_N_BITS_MAX]; + uint32 pdcch_c[LIBLTE_PHY_PDCCH_N_BITS_MAX * 2]; + uint32 pdcch_permute_map[LIBLTE_PHY_PDCCH_N_REGS_MAX][LIBLTE_PHY_PDCCH_N_REGS_MAX]; + uint16 pdcch_reg_vec[LIBLTE_PHY_PDCCH_N_REGS_MAX]; + uint16 pdcch_reg_perm_vec[LIBLTE_PHY_PDCCH_N_REGS_MAX]; + uint8 pdcch_dci[LIBLTE_PHY_PDCCH_N_BITS_MAX]; + uint8 pdcch_encode_bits[LIBLTE_PHY_PDCCH_N_BITS_MAX]; + uint8 pdcch_scramb_bits[LIBLTE_PHY_PDCCH_N_BITS_MAX]; + int8 pdcch_soft_bits[LIBLTE_PHY_PDCCH_N_BITS_MAX]; + bool pdcch_cce_used[LIBLTE_PHY_PDCCH_N_CCE_MAX]; // PHICH uint32 N_group_phich; @@ -429,95 +488,95 @@ typedef struct{ fftwf_plan samps_to_symbs_ul_plan; // Viterbi decode - float vd_path_metric[128][2048]; - float vd_br_metric[128][2]; - float vd_p_metric[128][2]; - float vd_br_weight[128][2]; - float vd_w_metric[128][2048]; - float vd_tb_state[2048]; - float vd_tb_weight[2048]; - uint8 vd_st_output[128][2][3]; + float vd_path_metric[LIBLTE_PHY_MAX_VITERBI_STATES][LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + float vd_br_metric[LIBLTE_PHY_MAX_VITERBI_STATES][2]; + float vd_p_metric[LIBLTE_PHY_MAX_VITERBI_STATES][2]; + float vd_br_weight[LIBLTE_PHY_MAX_VITERBI_STATES][2]; + float vd_w_metric[LIBLTE_PHY_MAX_VITERBI_STATES][LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + float vd_tb_state[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + float vd_tb_weight[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + uint8 vd_st_output[LIBLTE_PHY_MAX_VITERBI_STATES][2][3]; // Turbo encode - uint8 te_z[6144]; - uint8 te_fb1[6144]; - uint8 te_c_prime[6144]; - uint8 te_z_prime[6144]; - uint8 te_x_prime[6144]; + uint8 te_z[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + uint8 te_fb1[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + uint8 te_c_prime[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + uint8 te_z_prime[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + uint8 te_x_prime[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; // Turbo decode - int8 td_vitdec_in[18432]; - int8 td_in_int[6144]; - int8 td_in_calc_1[6144]; - int8 td_in_calc_2[6144]; - int8 td_in_calc_3[6144]; - int8 td_in_int_1[6144]; - int8 td_int_calc_1[6144]; - int8 td_int_calc_2[6144]; - int8 td_in_act_1[6144]; - int8 td_fb_1[6144]; - int8 td_int_act_1[6144]; - int8 td_int_act_2[6144]; - int8 td_fb_int_1[6144]; - int8 td_fb_int_2[6144]; + int8 td_vitdec_in[LIBLTE_PHY_BASE_CODING_RATE*LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_in_int[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_in_calc_1[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_in_calc_2[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_in_calc_3[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_in_int_1[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_int_calc_1[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_int_calc_2[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_in_act_1[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_fb_1[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_int_act_1[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_int_act_2[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_fb_int_1[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + int8 td_fb_int_2[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; // Rate Match Turbo - uint8 rmt_tmp[6144]; - uint8 rmt_sb_mat[32][192]; - uint8 rmt_sb_perm_mat[32][192]; - uint8 rmt_y[6144]; - uint8 rmt_w[18432]; + uint8 rmt_tmp[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + uint8 rmt_sb_mat[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE/LIBLTE_PHY_N_COLUMNS_RATE_MATCH][LIBLTE_PHY_N_COLUMNS_RATE_MATCH]; + uint8 rmt_sb_perm_mat[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE/LIBLTE_PHY_N_COLUMNS_RATE_MATCH][LIBLTE_PHY_N_COLUMNS_RATE_MATCH]; + uint8 rmt_y[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + uint8 rmt_w[LIBLTE_PHY_BASE_CODING_RATE*LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; // Rate Unmatch Turbo - float rut_tmp[6144]; - float rut_sb_mat[32][192]; - float rut_sb_perm_mat[32][192]; - float rut_y[6144]; - float rut_w_dum[18432]; - float rut_w[18432]; - float rut_v[3][6144]; + float rut_tmp[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + float rut_sb_mat[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE/LIBLTE_PHY_N_COLUMNS_RATE_MATCH][LIBLTE_PHY_N_COLUMNS_RATE_MATCH]; + float rut_sb_perm_mat[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE/LIBLTE_PHY_N_COLUMNS_RATE_MATCH][LIBLTE_PHY_N_COLUMNS_RATE_MATCH]; + float rut_y[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + float rut_w_dum[LIBLTE_PHY_BASE_CODING_RATE*LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + float rut_w[LIBLTE_PHY_BASE_CODING_RATE*LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + float rut_v[LIBLTE_PHY_BASE_CODING_RATE][LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; // Rate Match Conv - uint8 rmc_tmp[1024]; - uint8 rmc_sb_mat[32][32]; - uint8 rmc_sb_perm_mat[32][32]; - uint8 rmc_w[3*1024]; + uint8 rmc_tmp[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + uint8 rmc_sb_mat[LIBLTE_PHY_N_COLUMNS_RATE_MATCH][LIBLTE_PHY_MAX_CODE_BLOCK_SIZE/LIBLTE_PHY_N_COLUMNS_RATE_MATCH]; + uint8 rmc_sb_perm_mat[LIBLTE_PHY_N_COLUMNS_RATE_MATCH][LIBLTE_PHY_MAX_CODE_BLOCK_SIZE/LIBLTE_PHY_N_COLUMNS_RATE_MATCH]; + uint8 rmc_w[LIBLTE_PHY_BASE_CODING_RATE*LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; // Rate Unatch Conv - float ruc_tmp[1024]; - float ruc_sb_mat[32][32]; - float ruc_sb_perm_mat[32][32]; - float ruc_w_dum[3*1024]; - float ruc_w[3*1024]; - float ruc_v[3][1024]; + float ruc_tmp[LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + float ruc_sb_mat[LIBLTE_PHY_N_COLUMNS_RATE_MATCH][LIBLTE_PHY_MAX_CODE_BLOCK_SIZE/LIBLTE_PHY_N_COLUMNS_RATE_MATCH]; + float ruc_sb_perm_mat[LIBLTE_PHY_N_COLUMNS_RATE_MATCH][LIBLTE_PHY_MAX_CODE_BLOCK_SIZE/LIBLTE_PHY_N_COLUMNS_RATE_MATCH]; + float ruc_w_dum[LIBLTE_PHY_BASE_CODING_RATE*LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + float ruc_w[LIBLTE_PHY_BASE_CODING_RATE*LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; + float ruc_v[LIBLTE_PHY_BASE_CODING_RATE][LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; // ULSCH // FIXME: Sizes float ulsch_y_idx[92160]; float ulsch_y_mat[92160]; float ulsch_rx_d_bits[75376]; - float ulsch_rx_e_bits[5][18432]; + float ulsch_rx_e_bits[5][LIBLTE_PHY_BASE_CODING_RATE*LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; float ulsch_rx_f_bits[92160]; float ulsch_rx_g_bits[92160]; uint32 ulsch_N_c_bits[5]; uint32 ulsch_N_e_bits[5]; uint8 ulsch_b_bits[30720]; - uint8 ulsch_c_bits[5][6144]; + uint8 ulsch_c_bits[5][LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; uint8 ulsch_tx_d_bits[75376]; - uint8 ulsch_tx_e_bits[5][18432]; + uint8 ulsch_tx_e_bits[5][LIBLTE_PHY_BASE_CODING_RATE*LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; uint8 ulsch_tx_f_bits[92160]; uint8 ulsch_tx_g_bits[92160]; // DLSCH // FIXME: Sizes float dlsch_rx_d_bits[75376]; - float dlsch_rx_e_bits[5][18432]; + float dlsch_rx_e_bits[5][LIBLTE_PHY_BASE_CODING_RATE*LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; uint32 dlsch_N_c_bits[5]; uint32 dlsch_N_e_bits[5]; uint8 dlsch_b_bits[30720]; - uint8 dlsch_c_bits[5][6144]; + uint8 dlsch_c_bits[5][LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; uint8 dlsch_tx_d_bits[75376]; - uint8 dlsch_tx_e_bits[5][18432]; + uint8 dlsch_tx_e_bits[5][LIBLTE_PHY_BASE_CODING_RATE*LIBLTE_PHY_MAX_CODE_BLOCK_SIZE]; // DCI float dci_rx_d_bits[576]; @@ -540,6 +599,7 @@ typedef struct{ uint32 N_sc_rb_ul; uint32 FFT_pad_size; uint32 FFT_size; + uint8 N_ant; bool ul_init; }LIBLTE_PHY_STRUCT; // Functions @@ -560,7 +620,9 @@ LIBLTE_ERROR_ENUM liblte_phy_ul_init(LIBLTE_PHY_STRUCT *phy_struct, bool group_hopping_enabled, bool sequence_hopping_enabled, uint8 cyclic_shift, - uint8 cyclic_shift_dci); + uint8 cyclic_shift_dci, + uint8 N_cs_an, + uint8 delta_pucch_shift); /********************************************************************* Name: liblte_phy_cleanup @@ -620,7 +682,7 @@ typedef enum{ static const char liblte_phy_tpc_command_dci_1_1a_1b_1d_2_3_text[LIBLTE_PHY_TPC_COMMAND_DCI_1_1A_1B_1D_2_3_N_ITEMS][20] = {"-1dB", "0dB", "1dB", "3dB"}; // Structs typedef struct{ - LIBLTE_BIT_MSG_STRUCT msg; + LIBLTE_BIT_MSG_STRUCT msg[2]; LIBLTE_PHY_PRE_CODER_TYPE_ENUM pre_coder_type; LIBLTE_PHY_MODULATION_TYPE_ENUM mod_type; LIBLTE_PHY_CHAN_TYPE_ENUM chan_type; @@ -631,10 +693,12 @@ typedef struct{ uint32 N_codewords; uint32 N_layers; uint32 tx_mode; + uint32 harq_retx_count; uint16 rnti; uint8 mcs; uint8 tpc; bool ndi; + bool dl_alloc; }LIBLTE_PHY_ALLOCATION_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_phy_pusch_channel_encode(LIBLTE_PHY_STRUCT *phy_struct, @@ -663,6 +727,110 @@ LIBLTE_ERROR_ENUM liblte_phy_pusch_channel_decode(LIBLTE_PHY_STRUCT * uint8 *out_bits, uint32 *N_out_bits); +/********************************************************************* + Name: liblte_phy_pucch_format_1_1a_1b_channel_encode + + Description: Encodes and modulates the Physical Uplink Control + Channel for formats 1, 1a, and 1b + + Document Reference: 3GPP TS 36.211 v10.1.0 section 5.4.1 + 3GPP TS 36.212 v10.1.0 section 5.2.3 + + Notes: Only handling normal CP and N_ant=1 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +// FIXME + +/********************************************************************* + Name: liblte_phy_pucch_format_1_1a_1b_channel_decode + + Description: Demodulates and decodes the Physical Uplink Control + Channel for formats 1, 1a, and 1b + + Document Reference: 3GPP TS 36.211 v10.1.0 section 5.4.1 + 3GPP TS 36.212 v10.1.0 section 5.2.3 + + Notes: Only handling normal CP and N_ant=1 +*********************************************************************/ +// Defines +// Enums +typedef enum{ + LIBLTE_PHY_PUCCH_FORMAT_1 = 0, + LIBLTE_PHY_PUCCH_FORMAT_1A, + LIBLTE_PHY_PUCCH_FORMAT_1B, + LIBLTE_PHY_PUCCH_FORMAT_2, + LIBLTE_PHY_PUCCH_FORMAT_2A, + LIBLTE_PHY_PUCCH_FORMAT_2B, + LIBLTE_PHY_PUCCH_FORMAT_3, + LIBLTE_PHY_PUCCH_FORMAT_N_ITEMS, +}LIBLTE_PHY_PUCCH_FORMAT_ENUM; +static const char liblte_phy_pucch_format_text[LIBLTE_PHY_PUCCH_FORMAT_N_ITEMS][20] = { "1", "1a", "1b", + "2", "2a", "2b", + "3"}; +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_phy_pucch_format_1_1a_1b_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, + LIBLTE_PHY_SUBFRAME_STRUCT *subframe, + LIBLTE_PHY_PUCCH_FORMAT_ENUM format, + uint32 N_id_cell, + uint8 N_ant, + uint32 N_1_p_pucch, + uint8 *out_bits, + uint32 *N_out_bits); + +/********************************************************************* + Name: liblte_phy_pucch_format_2_2a_2b_channel_encode + + Description: Encodes and modulates the Physical Uplink Control + Channel for formats 2, 2a, and 2b + + Document Reference: 3GPP TS 36.211 v10.1.0 section 5.4.2 + 3GPP TS 36.212 v10.1.0 section 5.2.3 + + Notes: Only handling normal CP and N_ant=1 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +// FIXME + +/********************************************************************* + Name: liblte_phy_pucch_format_2_2a_2b_channel_decode + + Description: Demodulates and decodes the Physical Uplink Control + Channel for formats 2, 2a, and 2b + + Document Reference: 3GPP TS 36.211 v10.1.0 section 5.4.2 + 3GPP TS 36.212 v10.1.0 section 5.2.3 + + Notes: Only handling normal CP and N_ant=1 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +// FIXME + +/********************************************************************* + Name: liblte_phy_pucch_map_sr_config_idx + + Description: Maps SR configuration index to SR periodicity and + SR subframe offset + + Document Reference: 3GPP TS 36.213 v10.3.0 table 10.1.5-1 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void liblte_phy_pucch_map_sr_config_idx(uint32 i_sr, + uint32 *sr_periodicity, + uint32 *N_offset_sr); + /********************************************************************* Name: liblte_phy_generate_prach @@ -708,7 +876,7 @@ LIBLTE_ERROR_ENUM liblte_phy_detect_prach(LIBLTE_PHY_STRUCT *phy_struct, Document Reference: 3GPP TS 36.211 v10.1.0 sections 6.3 and 6.4 *********************************************************************/ // Defines -#define LIBLTE_PHY_PDCCH_MAX_ALLOC 10 +#define LIBLTE_PHY_PDCCH_MAX_ALLOC 6 // Enums // Structs typedef struct{ @@ -1106,4 +1274,91 @@ LIBLTE_ERROR_ENUM liblte_phy_get_n_cce(LIBLTE_PHY_STRUCT *phy_struct, uint8 N_ant, uint32 *N_cce); +/********************************************************************* + Name: liblte_phy_rate_match_turbo + + Description: Rate matches turbo encoded data + + Document Reference: 3GPP TS 36.212 v10.1.0 section 5.1.4.1 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void liblte_phy_rate_match_turbo(LIBLTE_PHY_STRUCT *phy_struct, + uint8 *d_bits, + uint32 N_d_bits, + uint32 N_codeblocks, + uint32 tx_mode, + uint32 N_soft, + uint32 M_dl_harq, + LIBLTE_PHY_CHAN_TYPE_ENUM chan_type, + uint32 rv_idx, + uint32 N_e_bits, + uint8 *e_bits); + +/********************************************************************* + Name: liblte_phy_rate_unmatch_turbo + + Description: Rate unmatches turbo encoded data + + Document Reference: 3GPP TS 36.212 v10.1.0 section 5.1.4.1 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void liblte_phy_rate_unmatch_turbo(LIBLTE_PHY_STRUCT *phy_struct, + float *e_bits, + uint32 N_e_bits, + uint8 *dummy_bits, + uint32 N_dummy_bits, + uint32 N_codeblocks, + uint32 tx_mode, + uint32 N_soft, + uint32 M_dl_harq, + LIBLTE_PHY_CHAN_TYPE_ENUM chan_type, + uint32 rv_idx, + float *d_bits, + uint32 *N_d_bits); + +/********************************************************************* + Name: liblte_phy_code_block_segmentation + + Description: Performs code block segmentation for turbo coded + channels + + Document Reference: 3GPP TS 36.212 v10.1.0 section 5.1.2 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void liblte_phy_code_block_segmentation(uint8 *b_bits, + uint32 N_b_bits, + uint32 *N_codeblocks, + uint32 *N_filler_bits, + uint8 *c_bits, + uint32 N_c_bits_max, + uint32 *N_c_bits); + +/********************************************************************* + Name: liblte_phy_code_block_desegmentation + + Description: Performs code block desegmentation for turbo coded + channels + + Document Reference: 3GPP TS 36.212 v10.1.0 section 5.1.2 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void liblte_phy_code_block_desegmentation(uint8 *c_bits, + uint32 *N_c_bits, + uint32 N_c_bits_max, + uint32 tbs, + uint8 *b_bits, + uint32 N_b_bits); + #endif /* __LIBLTE_PHY_H__ */ diff --git a/liblte/hdr/liblte_rlc.h b/liblte/hdr/liblte_rlc.h old mode 100644 new mode 100755 index ad7137c..bc49f80 --- a/liblte/hdr/liblte_rlc.h +++ b/liblte/hdr/liblte_rlc.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2014 Ben Wojtowicz + Copyright 2014-2016 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -25,6 +25,13 @@ Revision History ---------- ------------- -------------------------------------------- 06/15/2014 Ben Wojtowicz Created file. + 08/03/2014 Ben Wojtowicz Added NACK support. + 11/29/2014 Ben Wojtowicz Added UMD support and using the byte message + struct. + 02/15/2015 Ben Wojtowicz Added header extension handling to UMD. + 03/11/2015 Ben Wojtowicz Added header extension handling to AMD. + 07/03/2016 Ben Wojtowicz Added AMD PDU segment support. + 12/18/2016 Ben Wojtowicz Properly handling multiple AMD PDUs. *******************************************************************************/ @@ -243,10 +250,33 @@ static const char liblte_rlc_e2_field_text[LIBLTE_RLC_E2_FIELD_N_ITEMS][20] = {" Document Reference: 36.322 v10.0.0 Section 6.2.1.3 *********************************************************************/ // Defines +#define LIBLTE_RLC_UMD_MAX_N_DATA 5 // Enums +typedef enum{ + LIBLTE_RLC_UMD_SN_SIZE_5_BITS = 0, + LIBLTE_RLC_UMD_SN_SIZE_10_BITS, + LIBLTE_RLC_UMD_SN_SIZE_N_ITEMS, +}LIBLTE_RLC_UMD_SN_SIZE_ENUM; +static const char liblte_rlc_umd_sn_size_text[LIBLTE_RLC_UMD_SN_SIZE_N_ITEMS][20] = {"5 bits", "10 bits"}; // Structs +typedef struct{ + LIBLTE_RLC_FI_FIELD_ENUM fi; + LIBLTE_RLC_UMD_SN_SIZE_ENUM sn_size; + uint16 sn; +}LIBLTE_RLC_UMD_PDU_HEADER_STRUCT; +typedef struct{ + LIBLTE_RLC_UMD_PDU_HEADER_STRUCT hdr; + LIBLTE_BYTE_MSG_STRUCT data[LIBLTE_RLC_UMD_MAX_N_DATA]; + uint32 N_data; +}LIBLTE_RLC_UMD_PDU_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rlc_pack_umd_pdu(LIBLTE_RLC_UMD_PDU_STRUCT *umd, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_rlc_pack_umd_pdu(LIBLTE_RLC_UMD_PDU_STRUCT *umd, + LIBLTE_BYTE_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_rlc_unpack_umd_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_RLC_UMD_PDU_STRUCT *umd); /********************************************************************* PDU Type: Acknowledged Mode Data PDU @@ -254,23 +284,34 @@ static const char liblte_rlc_e2_field_text[LIBLTE_RLC_E2_FIELD_N_ITEMS][20] = {" Document Reference: 36.322 v10.0.0 Sections 6.2.1.4 & 6.2.1.5 *********************************************************************/ // Defines +#define LIBLTE_RLC_AMD_MAX_N_PDU 5 // Enums // Structs typedef struct{ - LIBLTE_RLC_RF_FIELD_ENUM rf; - LIBLTE_RLC_P_FIELD_ENUM p; - LIBLTE_RLC_FI_FIELD_ENUM fi; - uint16 sn; + LIBLTE_RLC_DC_FIELD_ENUM dc; + LIBLTE_RLC_RF_FIELD_ENUM rf; + LIBLTE_RLC_P_FIELD_ENUM p; + LIBLTE_RLC_FI_FIELD_ENUM fi; + LIBLTE_RLC_LSF_FIELD_ENUM lsf; + uint16 sn; + uint16 so; }LIBLTE_RLC_AMD_PDU_HEADER_STRUCT; typedef struct{ LIBLTE_RLC_AMD_PDU_HEADER_STRUCT hdr; - LIBLTE_BIT_MSG_STRUCT data; -}LIBLTE_RLC_AMD_PDU_STRUCT; + LIBLTE_BYTE_MSG_STRUCT data; +}LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT; +typedef struct{ + LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT pdu[LIBLTE_RLC_AMD_MAX_N_PDU]; + uint32 N_pdu; +}LIBLTE_RLC_AMD_PDUS_STRUCT; // Functions -LIBLTE_ERROR_ENUM liblte_rlc_pack_amd_pdu(LIBLTE_RLC_AMD_PDU_STRUCT *amd, - LIBLTE_BIT_MSG_STRUCT *pdu); -LIBLTE_ERROR_ENUM liblte_rlc_unpack_amd_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, - LIBLTE_RLC_AMD_PDU_STRUCT *amd); +LIBLTE_ERROR_ENUM liblte_rlc_pack_amd_pdu(LIBLTE_RLC_AMD_PDUS_STRUCT *amd, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_rlc_pack_amd_pdu(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT *amd, + LIBLTE_BYTE_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_rlc_unpack_amd_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_RLC_AMD_PDUS_STRUCT *amd); /********************************************************************* PDU Type: Status PDU @@ -281,12 +322,14 @@ LIBLTE_ERROR_ENUM liblte_rlc_unpack_amd_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, // Enums // Structs typedef struct{ + uint32 N_nack; uint16 ack_sn; + uint16 nack_sn[LIBLTE_RLC_AM_WINDOW_SIZE]; }LIBLTE_RLC_STATUS_PDU_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_rlc_pack_status_pdu(LIBLTE_RLC_STATUS_PDU_STRUCT *status, - LIBLTE_BIT_MSG_STRUCT *pdu); -LIBLTE_ERROR_ENUM liblte_rlc_unpack_status_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, + LIBLTE_BYTE_MSG_STRUCT *pdu); +LIBLTE_ERROR_ENUM liblte_rlc_unpack_status_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, LIBLTE_RLC_STATUS_PDU_STRUCT *status); #endif /* __LIBLTE_RLC_H__ */ diff --git a/liblte/hdr/liblte_rrc.h b/liblte/hdr/liblte_rrc.h old mode 100644 new mode 100755 index 3ab67a6..d2c7a01 --- a/liblte/hdr/liblte_rrc.h +++ b/liblte/hdr/liblte_rrc.h @@ -1,6 +1,9 @@ /******************************************************************************* - Copyright 2012-2014 Ben Wojtowicz + Copyright 2012-2016 Ben Wojtowicz + Copyright 2014 Andrew Murphy (SIB13 unpack) + Copyright 2016 Przemek Bereski (UE capability RAT container list IE and + UE capability enquiry message pack/unpack) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -41,6 +44,24 @@ and UL CCCH Messages. 05/04/2014 Ben Wojtowicz Added support for DL CCCH Messages. 06/15/2014 Ben Wojtowicz Added support for UL DCCH Messages. + 08/03/2014 Ben Wojtowicz Added more decoding/encoding. + 09/19/2014 Andrew Murphy Added SIB13 unpack. + 11/01/2014 Ben Wojtowicz Added more decoding/encoding. + 11/09/2014 Ben Wojtowicz Added SIB13 pack. + 11/29/2014 Ben Wojtowicz Fixed a bug in RRC connection reestablishment + UE identity. + 03/11/2015 Ben Wojtowicz Converting to/from actual hysteresis value. + 07/25/2015 Ben Wojtowicz Fixed a bug with the default value of + filter_coeff in + LIBLTE_RRC_UL_POWER_CONTROL_DEDICATED_STRUCT. + Thanks to Paul Sutton for finding this. + 07/03/2016 Ben Wojtowicz Padded all enums to nearest power of 2, added + PMCH info list, cross carrier scheduling + config, CSI RS config, and RN subframe config + IE support. + 07/03/2016 Przemek Bereski Added UE capability RAT container list IE and + UE capability enquiry message support. + 10/09/2016 Ben Wojtowicz Added SIB13 non critical extension handling. *******************************************************************************/ @@ -107,10 +128,56 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mbsfn_notification_config_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.7 *********************************************************************/ // Defines -// Enums -// Structs -// Functions -// FIXME +#define LIBLTE_RRC_MAX_MBSFN_AREAS 8 +// Enums +typedef enum{ + LIBLTE_RRC_NON_MBSFN_REGION_LENGTH_S1 = 0, + LIBLTE_RRC_NON_MBSFN_REGION_LENGTH_S2, + LIBLTE_RRC_NON_MBSFN_REGION_LENGTH_N_ITEMS, +}LIBLTE_RRC_NON_MBSFN_REGION_LENGTH_ENUM; +static const char liblte_rrc_non_mbsfn_region_length_text[LIBLTE_RRC_NON_MBSFN_REGION_LENGTH_N_ITEMS][20] = {"1", "2"}; +static const uint8 liblte_rrc_non_mbsfn_region_length_num[LIBLTE_RRC_NON_MBSFN_REGION_LENGTH_N_ITEMS] = {1, 2}; +typedef enum{ + LIBLTE_RRC_MCCH_REPETITION_PERIOD_RF32 = 0, + LIBLTE_RRC_MCCH_REPETITION_PERIOD_RF64, + LIBLTE_RRC_MCCH_REPETITION_PERIOD_RF128, + LIBLTE_RRC_MCCH_REPETITION_PERIOD_RF256, + LIBLTE_RRC_MCCH_REPETITION_PERIOD_N_ITEMS, +}LIBLTE_RRC_MCCH_REPETITION_PERIOD_ENUM; +static const char liblte_rrc_mcch_repetition_period_r9_text[LIBLTE_RRC_MCCH_REPETITION_PERIOD_N_ITEMS][20] = {"32", "64", "128", "256"}; +static const uint16 liblte_rrc_mcch_repetition_period_r9_num[LIBLTE_RRC_MCCH_REPETITION_PERIOD_N_ITEMS] = {32, 64, 128, 256}; +typedef enum{ + LIBLTE_RRC_MCCH_MODIFICATION_PERIOD_512 = 0, + LIBLTE_RRC_MCCH_MODIFICATION_PERIOD_1024, + LIBLTE_RRC_MCCH_MODIFICATION_PERIOD_N_ITEMS, +}LIBLTE_RRC_MCCH_MODIFICATION_PERIOD_ENUM; +static const char liblte_rrc_mcch_modification_period_r9_text[LIBLTE_RRC_MCCH_MODIFICATION_PERIOD_N_ITEMS][20] = {"512", "1024"}; +static const uint16 liblte_rrc_mcch_modification_period_r9_num[LIBLTE_RRC_MCCH_MODIFICATION_PERIOD_N_ITEMS] = {512, 1024}; +typedef enum{ + LIBLTE_RRC_MCCH_SIGNALLING_MCS_N2 = 0, + LIBLTE_RRC_MCCH_SIGNALLING_MCS_N7, + LIBLTE_RRC_MCCH_SIGNALLING_MCS_N13, + LIBLTE_RRC_MCCH_SIGNALLING_MCS_N19, + LIBLTE_RRC_MCCH_SIGNALLING_MCS_N_ITEMS, +}LIBLTE_RRC_MCCH_SIGNALLING_MCS_ENUM; +static const char liblte_rrc_mcch_signalling_mcs_r9_text[LIBLTE_RRC_MCCH_SIGNALLING_MCS_N_ITEMS][20] = {"2", "7", "13", "19"}; +static const uint8 liblte_rrc_mcch_signalling_mcs_r9_num[LIBLTE_RRC_MCCH_SIGNALLING_MCS_N_ITEMS] = {2, 7, 13, 19}; +// Structs +typedef struct{ + LIBLTE_RRC_NON_MBSFN_REGION_LENGTH_ENUM non_mbsfn_region_length; + LIBLTE_RRC_MCCH_REPETITION_PERIOD_ENUM mcch_repetition_period_r9; + LIBLTE_RRC_MCCH_MODIFICATION_PERIOD_ENUM mcch_modification_period_r9; + LIBLTE_RRC_MCCH_SIGNALLING_MCS_ENUM signalling_mcs_r9; + uint8 mbsfn_area_id_r9; + uint8 notification_indicator_r9; + uint8 mcch_offset_r9; + uint8 sf_alloc_info_r9; +}LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_mbsfn_area_info_ie(LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *mbsfn_area_info, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_mbsfn_area_info_ie(uint8 **ie_ptr, + LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *mbsfn_area_info); /********************************************************************* IE Name: MBSFN Subframe Config @@ -130,11 +197,13 @@ typedef enum{ LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N8, LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N16, LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N32, + LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_SPARE1, + LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_SPARE2, LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N_ITEMS, }LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_ENUM; -static const char liblte_rrc_radio_frame_allocation_period_text[LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N_ITEMS][20] = { "1", "2", "4", "8", - "16", "32"}; -static const uint8 liblte_rrc_radio_frame_allocation_period_num[LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N_ITEMS] = {1, 2, 4, 8, 16, 32}; +static const char liblte_rrc_radio_frame_allocation_period_text[LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N_ITEMS][20] = { "1", "2", "4", "8", + "16", "32", "SPARE1", "SPARE2"}; +static const uint8 liblte_rrc_radio_frame_allocation_period_num[LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N_ITEMS] = {1, 2, 4, 8, 16, 32, 0, 0}; typedef enum{ LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE = 0, LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_FOUR, @@ -163,10 +232,65 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mbsfn_subframe_config_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.7 *********************************************************************/ // Defines +#define LIBLTE_RRC_MAX_PMCH_PER_MBSFN 15 +#define LIBLTE_RRC_MAX_SESSION_PER_PMCH 29 // Enums +typedef enum{ + LIBLTE_RRC_MCH_SCHEDULING_PERIOD_RF8 = 0, + LIBLTE_RRC_MCH_SCHEDULING_PERIOD_RF16, + LIBLTE_RRC_MCH_SCHEDULING_PERIOD_RF32, + LIBLTE_RRC_MCH_SCHEDULING_PERIOD_RF64, + LIBLTE_RRC_MCH_SCHEDULING_PERIOD_RF128, + LIBLTE_RRC_MCH_SCHEDULING_PERIOD_RF256, + LIBLTE_RRC_MCH_SCHEDULING_PERIOD_RF512, + LIBLTE_RRC_MCH_SCHEDULING_PERIOD_RF1024, + LIBLTE_RRC_MCH_SCHEDULING_PERIOD_N_ITEMS, +}LIBLTE_RRC_MCH_SCHEDULING_PERIOD_ENUM; +static const char liblte_rrc_mch_scheduling_period_text[LIBLTE_RRC_MCH_SCHEDULING_PERIOD_N_ITEMS][20] = { "rf8", "rf16", "rf32", "rf64", + "rf128", "rf256", "rf512", "rf1024"}; +static const uint16 liblte_rrc_mch_scheduling_period_num[LIBLTE_RRC_MCH_SCHEDULING_PERIOD_N_ITEMS] = {8, 16, 32, 64, 128, 256, 512, 1024}; +typedef enum{ + LIBLTE_RRC_PLMN_ID_CHOICE_INDEX = 0, + LIBLTE_RRC_PLMN_ID_CHOICE_EXPLICIT_VALUE, + LIBLTE_RRC_PLMN_ID_CHOICE_N_ITEMS, +}LIBLTE_RRC_PLMN_ID_CHOICE_ENUM; +static const char liblte_rrc_plmn_id_choice_text[LIBLTE_RRC_PLMN_ID_CHOICE_N_ITEMS][20] = {"index", "explicit value"}; // Structs +typedef struct{ + uint16 mcc; + uint16 mnc; +}LIBLTE_RRC_PLMN_IDENTITY_STRUCT; +typedef struct{ + LIBLTE_RRC_MCH_SCHEDULING_PERIOD_ENUM mch_scheduling_period; + uint16 sf_alloc_end; + uint8 data_mcs; +}LIBLTE_RRC_PMCH_CONFIG_STRUCT; +typedef struct{ + LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id; + LIBLTE_RRC_PLMN_ID_CHOICE_ENUM plmn_id_choice; + uint8 plmn_idx; + uint8 service_id[3]; +}LIBLTE_RRC_TMGI_STRUCT; +typedef struct{ + LIBLTE_RRC_TMGI_STRUCT tmgi; + uint8 session_id; + uint8 logical_channel_id; + bool session_id_present; +}LIBLTE_RRC_MBMS_SESSION_INFO_STRUCT; +typedef struct{ + LIBLTE_RRC_PMCH_CONFIG_STRUCT pmch_config; + LIBLTE_RRC_MBMS_SESSION_INFO_STRUCT mbms_session_info_list[LIBLTE_RRC_MAX_SESSION_PER_PMCH]; + uint8 mbms_session_info_list_size; +}LIBLTE_RRC_PMCH_INFO_STRUCT; +typedef struct{ + LIBLTE_RRC_PMCH_INFO_STRUCT pmch_info_list[LIBLTE_RRC_MAX_PMCH_PER_MBSFN]; + uint8 pmch_info_list_size; +}LIBLTE_RRC_PMCH_INFO_LIST_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_pmch_info_list_ie(LIBLTE_RRC_PMCH_INFO_LIST_STRUCT *pmch_info_list, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_pmch_info_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_PMCH_INFO_LIST_STRUCT *pmch_info_list); /********************************************************************* IE Name: C-RNTI @@ -196,12 +320,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_c_rnti_ie(uint8 **ie_ptr, // Enums // Structs // Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(uint8 *ded_info_cdma2000, - uint32 length, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_cdma2000_ie(uint8 **ie_ptr, - uint8 *ded_info_cdma2000, - uint32 *length); +LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(LIBLTE_BYTE_MSG_STRUCT *ded_info_cdma2000, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_cdma2000_ie(uint8 **ie_ptr, + LIBLTE_BYTE_MSG_STRUCT *ded_info_cdma2000); /********************************************************************* IE Name: Dedicated Info NAS @@ -426,10 +548,26 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_s_tmsi_ie(uint8 **ie_ptr, Document Reference: 36.331 v10.0.0 Section 6.3.6 *********************************************************************/ // Defines +#define LIBLTE_RRC_MAX_RAT_CAPABILITIES 8 // Enums // Structs +typedef struct{ + LIBLTE_RRC_RAT_TYPE_ENUM rat_type; + LIBLTE_BYTE_MSG_STRUCT ue_capability_rat_container; +}LIBLTE_RRC_UE_CAPABILITY_RAT_CONTAINER_STRUCT; +typedef struct{ + LIBLTE_RRC_UE_CAPABILITY_RAT_CONTAINER_STRUCT rat_container_list[LIBLTE_RRC_MAX_RAT_CAPABILITIES]; + uint32 N_rat_container; +}LIBLTE_RRC_UE_CAPABILITY_RAT_CONTAINER_LIST_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_octet_string_ie(LIBLTE_BYTE_MSG_STRUCT *octet_string, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_octet_string_ie(uint8 **ie_ptr, + LIBLTE_BYTE_MSG_STRUCT *octet_string); +LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_capability_rat_container_list_ie(LIBLTE_RRC_UE_CAPABILITY_RAT_CONTAINER_LIST_STRUCT *ue_capability_rat_container_list, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_capability_rat_container_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_UE_CAPABILITY_RAT_CONTAINER_LIST_STRUCT *ue_capability_rat_container_list); /********************************************************************* IE Name: UE EUTRA Capability @@ -491,11 +629,12 @@ typedef enum{ LIBLTE_RRC_T310_MS500, LIBLTE_RRC_T310_MS1000, LIBLTE_RRC_T310_MS2000, + LIBLTE_RRC_T310_SPARE, LIBLTE_RRC_T310_N_ITEMS, }LIBLTE_RRC_T310_ENUM; -static const char liblte_rrc_t310_text[LIBLTE_RRC_T310_N_ITEMS][20] = { "0", "50", "100", "200", - "500", "1000", "2000"}; -static const uint16 liblte_rrc_t310_num[LIBLTE_RRC_T310_N_ITEMS] = {0, 50, 100, 200, 500, 1000, 2000}; +static const char liblte_rrc_t310_text[LIBLTE_RRC_T310_N_ITEMS][20] = { "0", "50", "100", "200", + "500", "1000", "2000", "SPARE"}; +static const uint16 liblte_rrc_t310_num[LIBLTE_RRC_T310_N_ITEMS] = {0, 50, 100, 200, 500, 1000, 2000, 0}; typedef enum{ LIBLTE_RRC_N310_N1 = 0, LIBLTE_RRC_N310_N2, @@ -518,11 +657,12 @@ typedef enum{ LIBLTE_RRC_T311_MS15000, LIBLTE_RRC_T311_MS20000, LIBLTE_RRC_T311_MS30000, + LIBLTE_RRC_T311_SPARE, LIBLTE_RRC_T311_N_ITEMS, }LIBLTE_RRC_T311_ENUM; static const char liblte_rrc_t311_text[LIBLTE_RRC_T311_N_ITEMS][20] = { "1000", "3000", "5000", "10000", - "15000", "20000", "30000"}; -static const uint16 liblte_rrc_t311_num[LIBLTE_RRC_T311_N_ITEMS] = {1000, 3000, 5000, 10000, 15000, 20000, 30000}; + "15000", "20000", "30000", "SPARE"}; +static const uint16 liblte_rrc_t311_num[LIBLTE_RRC_T311_N_ITEMS] = {1000, 3000, 5000, 10000, 15000, 20000, 30000, 0}; typedef enum{ LIBLTE_RRC_N311_N1 = 0, LIBLTE_RRC_N311_N2, @@ -570,11 +710,13 @@ typedef enum{ LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_MBW50, LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_MBW75, LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_MBW100, + LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_SPARE1, + LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_SPARE2, LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_N_ITEMS, }LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_ENUM; -static const char liblte_rrc_allowed_meas_bandwidth_text[LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_N_ITEMS][20] = {"1.4", "3", "5", "10", - "15", "20"}; -static const double liblte_rrc_allowed_meas_bandwidth_num[LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_N_ITEMS] = {1.4, 3, 5, 10, 15, 20}; +static const char liblte_rrc_allowed_meas_bandwidth_text[LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_N_ITEMS][20] = { "1.4", "3", "5", "10", + "15", "20", "SPARE1", "SPARE2"}; +static const double liblte_rrc_allowed_meas_bandwidth_num[LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_N_ITEMS] = {1.4, 3, 5, 10, 15, 20, 0, 0}; // Structs // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_allowed_meas_bandwidth_ie(LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_ENUM allowed_meas_bw, @@ -594,10 +736,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_allowed_meas_bandwidth_ie(uint8 // Enums // Structs // Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_hysteresis_ie(uint8 hysteresis, +LIBLTE_ERROR_ENUM liblte_rrc_pack_hysteresis_ie(float hysteresis, uint8 **ie_ptr); LIBLTE_ERROR_ENUM liblte_rrc_unpack_hysteresis_ie(uint8 **ie_ptr, - uint8 *hysteresis); + float *hysteresis); /********************************************************************* IE Name: Location Info @@ -624,432 +766,11 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_hysteresis_ie(uint8 **ie_ptr, Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ // Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Meas ID - - Description: Identifies a measurement configuration, i.e. linking - of a measurement object and a reporting configuration - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -#define LIBLTE_RRC_MAX_MEAS_ID 32 -// Enums -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_id_ie(uint8 meas_id, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_id_ie(uint8 **ie_ptr, - uint8 *meas_id); - -/********************************************************************* - IE Name: Meas Id To Add Mod List - - Description: Concerns a list of measurement identities to add or - modify, with for each entry the meas ID, the - associated meas object ID and the associated report - config ID - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Meas Object CDMA2000 - - Description: Specifies information applicable for inter-RAT - CDMA2000 neighboring cells - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Meas Object EUTRA - - Description: Specifies information applicable for intra-frequency - or inter-frequency E-UTRA cells - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Meas Object GERAN - - Description: Specifies information applicable for inter-RAT - GERAN neighboring frequencies - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Meas Object ID - - Description: Identifies a measurement object configuration - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -#define LIBLTE_RRC_MAX_OBJECT_ID 32 -// Enums -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_id_ie(uint8 meas_object_id, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_id_ie(uint8 **ie_ptr, - uint8 *meas_object_id); - -/********************************************************************* - IE Name: Meas Object To Add Mod List - - Description: Concerns a list of measurement objects to add or - modify - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Meas Object UTRA - - Description: Specifies information applicable for inter-RAT UTRA - neighboring cells - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Meas Results - - Description: Covers measured results for intra-frequency, - inter-frequency and inter-RAT mobility - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Quantity Config - - Description: Specifies the measurement quantities and layer 3 - filtering coefficients for E-UTRA and inter-RAT - measurements - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Report Config EUTRA - - Description: Specifies criteria for triggering of an E-UTRA - measurement reporting event - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Report Config ID - - Description: Identifies a measurement reporting configuration - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -#define LIBLTE_RRC_MAX_REPORT_CONFIG_ID 32 -// Enums -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_id_ie(uint8 report_cnfg_id, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_id_ie(uint8 **ie_ptr, - uint8 *report_cnfg_id); - -/********************************************************************* - IE Name: Report Config Inter RAT - - Description: Specifies criteria for triggering of an inter-RAT - measurement reporting event - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Report Config To Add Mod List - - Description: Concerns a list of reporting configurations to add - or modify - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME - -/********************************************************************* - IE Name: Report Interval - - Description: Indicates the interval between periodic reports - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -typedef enum{ - LIBLTE_RRC_REPORT_INTERVAL_MS120 = 0, - LIBLTE_RRC_REPORT_INTERVAL_MS240, - LIBLTE_RRC_REPORT_INTERVAL_MS480, - LIBLTE_RRC_REPORT_INTERVAL_MS640, - LIBLTE_RRC_REPORT_INTERVAL_MS1024, - LIBLTE_RRC_REPORT_INTERVAL_MS2048, - LIBLTE_RRC_REPORT_INTERVAL_MS5120, - LIBLTE_RRC_REPORT_INTERVAL_MS10240, - LIBLTE_RRC_REPORT_INTERVAL_MIN1, - LIBLTE_RRC_REPORT_INTERVAL_MIN6, - LIBLTE_RRC_REPORT_INTERVAL_MIN12, - LIBLTE_RRC_REPORT_INTERVAL_MIN30, - LIBLTE_RRC_REPORT_INTERVAL_MIN60, - LIBLTE_RRC_REPORT_INTERVAL_SPARE3, - LIBLTE_RRC_REPORT_INTERVAL_SPARE2, - LIBLTE_RRC_REPORT_INTERVAL_SPARE1, - LIBLTE_RRC_REPORT_INTERVAL_N_ITEMS, -}LIBLTE_RRC_REPORT_INTERVAL_ENUM; -static const char liblte_rrc_report_interval_text[LIBLTE_RRC_REPORT_INTERVAL_N_ITEMS][20] = { "120", "240", "480", "640", - "1024", "2048", "5120", "10240", - "60000", "360000", "720000", "1800000", - "3600000", "SPARE", "SPARE", "SPARE"}; -static const int32 liblte_rrc_report_interval_num[LIBLTE_RRC_REPORT_INTERVAL_N_ITEMS] = {120, 240, 480, 640, 1024, 2048, 5120, 10240, 60000, 360000, 720000, 1800000, 3600000, -1, -1, -1}; -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_report_interval_ie(LIBLTE_RRC_REPORT_INTERVAL_ENUM report_int, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_interval_ie(uint8 **ie_ptr, - LIBLTE_RRC_REPORT_INTERVAL_ENUM *report_int); - -/********************************************************************* - IE Name: RSRP Range - - Description: Specifies the value range used in RSRP measurements - and thresholds - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_rsrp_range_ie(uint8 rsrp_range, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_rsrp_range_ie(uint8 **ie_ptr, - uint8 *rsrp_range); - -/********************************************************************* - IE Name: RSRQ Range - - Description: Specifies the value range used in RSRQ measurements - and thresholds - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_rsrq_range_ie(uint8 rsrq_range, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_rsrq_range_ie(uint8 **ie_ptr, - uint8 *rsrq_range); - -/********************************************************************* - IE Name: Time To Trigger - - Description: Specifies the value range used for the time to - trigger parameter, which concerns the time during - which specific criteria for the event needs to be - met in order to trigger a measurement report - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// Defines -// Enums -typedef enum{ - LIBLTE_RRC_TIME_TO_TRIGGER_MS0 = 0, - LIBLTE_RRC_TIME_TO_TRIGGER_MS40, - LIBLTE_RRC_TIME_TO_TRIGGER_MS64, - LIBLTE_RRC_TIME_TO_TRIGGER_MS80, - LIBLTE_RRC_TIME_TO_TRIGGER_MS100, - LIBLTE_RRC_TIME_TO_TRIGGER_MS128, - LIBLTE_RRC_TIME_TO_TRIGGER_MS160, - LIBLTE_RRC_TIME_TO_TRIGGER_MS256, - LIBLTE_RRC_TIME_TO_TRIGGER_MS320, - LIBLTE_RRC_TIME_TO_TRIGGER_MS480, - LIBLTE_RRC_TIME_TO_TRIGGER_MS512, - LIBLTE_RRC_TIME_TO_TRIGGER_MS640, - LIBLTE_RRC_TIME_TO_TRIGGER_MS1024, - LIBLTE_RRC_TIME_TO_TRIGGER_MS1280, - LIBLTE_RRC_TIME_TO_TRIGGER_MS2560, - LIBLTE_RRC_TIME_TO_TRIGGER_MS5120, - LIBLTE_RRC_TIME_TO_TRIGGER_N_ITEMS, -}LIBLTE_RRC_TIME_TO_TRIGGER_ENUM; -static const char liblte_rrc_time_to_trigger_text[LIBLTE_RRC_TIME_TO_TRIGGER_N_ITEMS][20] = { "0", "40", "64", "80", - "100", "128", "160", "256", - "320", "480", "512", "640", - "1024", "1280", "2560", "5120"}; -static const uint16 liblte_rrc_time_to_trigger_num[LIBLTE_RRC_TIME_TO_TRIGGER_N_ITEMS] = {0, 40, 64, 80, 100, 128, 160, 256, 320, 480, 512, 640, 1024, 1280, 2560, 5120}; -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_time_to_trigger_ie(LIBLTE_RRC_TIME_TO_TRIGGER_ENUM time_to_trigger, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_time_to_trigger_ie(uint8 **ie_ptr, - LIBLTE_RRC_TIME_TO_TRIGGER_ENUM *time_to_trigger); - -/********************************************************************* - IE Name: Additional Spectrum Emission - - Description: FIXME - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_additional_spectrum_emission_ie(uint8 add_spect_em, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_additional_spectrum_emission_ie(uint8 **ie_ptr, - uint8 *add_spect_em); - -/********************************************************************* - IE Name: ARFCN value CDMA2000 - - Description: Indicates the CDMA2000 carrier frequency within - a CDMA2000 band - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_cdma2000_ie(uint16 arfcn, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_cdma2000_ie(uint8 **ie_ptr, - uint16 *arfcn); - -/********************************************************************* - IE Name: ARFCN value EUTRA - - Description: Indicates the ARFCN applicable for a downlink, - uplink, or bi-directional (TDD) E-UTRA carrier - frequency - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_eutra_ie(uint16 arfcn, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_eutra_ie(uint8 **ie_ptr, - uint16 *arfcn); - -/********************************************************************* - IE Name: ARFCN value GERAN - - Description: Specifies the ARFCN value applicable for a GERAN - BCCH carrier frequency - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_geran_ie(uint16 arfcn, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_geran_ie(uint8 **ie_ptr, - uint16 *arfcn); - -/********************************************************************* - IE Name: ARFCN value UTRA - - Description: Indicates the ARFCN applicable for a downlink (Nd, - FDD) or bi-directional (Nt, TDD) UTRA carrier - frequency - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_utra_ie(uint16 arfcn, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_utra_ie(uint8 **ie_ptr, - uint16 *arfcn); - -/********************************************************************* - IE Name: Band Class CDMA2000 - - Description: Defines the CDMA2000 band in which the CDMA2000 - carrier frequency can be found - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines +#define LIBLTE_RRC_MAX_EXPLICIT_LIST_OF_ARFCNS 31 +#define LIBLTE_RRC_MAX_CELL_MEAS 32 +#define LIBLTE_RRC_MAX_OBJECT_ID 32 +#define LIBLTE_RRC_MAX_REPORT_CONFIG_ID 32 +#define LIBLTE_RRC_MAX_MEAS_ID 32 // Enums typedef enum{ LIBLTE_RRC_BAND_CLASS_CDMA2000_BC0 = 0, @@ -1096,88 +817,12 @@ static const char liblte_rrc_band_class_cdma2000_text[LIBLTE_RRC_BAND_CLASS_CDMA "SPARE", "SPARE", "SPARE", "SPARE"}; static const int8 liblte_rrc_band_class_cdma2000_num[LIBLTE_RRC_BAND_CLASS_CDMA2000_N_ITEMS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_band_class_cdma2000_ie(LIBLTE_RRC_BAND_CLASS_CDMA2000_ENUM bc_cdma2000, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_band_class_cdma2000_ie(uint8 **ie_ptr, - LIBLTE_RRC_BAND_CLASS_CDMA2000_ENUM *bc_cdma2000); - -/********************************************************************* - IE Name: Band Indicator GERAN - - Description: Indicates how to interpret an associated GERAN - carrier ARFCN - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -// Enums typedef enum{ LIBLTE_RRC_BAND_INDICATOR_GERAN_DCS1800 = 0, LIBLTE_RRC_BAND_INDICATOR_GERAN_PCS1900, LIBLTE_RRC_BAND_INDICATOR_GERAN_N_ITEMS, }LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM; static const char liblte_rrc_band_indicator_geran_text[LIBLTE_RRC_BAND_INDICATOR_GERAN_N_ITEMS][20] = {"DCS1800", "PCS1900"}; -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_band_indicator_geran_ie(LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM bi_geran, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_band_indicator_geran_ie(uint8 **ie_ptr, - LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM *bi_geran); - -/********************************************************************* - IE Name: Carrier Freq CDMA2000 - - Description: Provides the CDMA2000 carrier information - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -// Enums -// Structs -typedef struct{ - LIBLTE_RRC_BAND_CLASS_CDMA2000_ENUM bandclass; - uint16 arfcn; -}LIBLTE_RRC_CARRIER_FREQ_CDMA2000_STRUCT; -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_carrier_freq_cdma2000_ie(LIBLTE_RRC_CARRIER_FREQ_CDMA2000_STRUCT *carrier_freq, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_carrier_freq_cdma2000_ie(uint8 **ie_ptr, - LIBLTE_RRC_CARRIER_FREQ_CDMA2000_STRUCT *carrier_freq); - -/********************************************************************* - IE Name: Carrier Freq GERAN - - Description: Provides an unambiguous carrier frequency description - of a GERAN cell - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -// Enums -// Structs -typedef struct{ - LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM band_indicator; - uint16 arfcn; -}LIBLTE_RRC_CARRIER_FREQ_GERAN_STRUCT; -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_carrier_freq_geran_ie(LIBLTE_RRC_CARRIER_FREQ_GERAN_STRUCT *carrier_freq, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_carrier_freq_geran_ie(uint8 **ie_ptr, - LIBLTE_RRC_CARRIER_FREQ_GERAN_STRUCT *carrier_freq); - -/********************************************************************* - IE Name: Carrier Freqs GERAN - - Description: Provides one or more GERAN ARFCN values, which - represent a list of GERAN BCCH carrier frequencies - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -#define LIBLTE_RRC_MAX_EXPLICIT_LIST_OF_ARFCNS 31 -// Enums typedef enum{ LIBLTE_RRC_FOLLOWING_ARFCNS_EXPLICIT_LIST = 0, LIBLTE_RRC_FOLLOWING_ARFCNS_EQUALLY_SPACED, @@ -1185,7 +830,338 @@ typedef enum{ LIBLTE_RRC_FOLLOWING_ARFCNS_N_ITEMS, }LIBLTE_RRC_FOLLOWING_ARFCNS_ENUM; static const char liblte_rrc_following_arfcns_text[LIBLTE_RRC_FOLLOWING_ARFCNS_N_ITEMS][20] = {"Explicit List", "Equally Spaced", "Variable Bit Map"}; +typedef enum{ + LIBLTE_RRC_CDMA2000_TYPE_1XRTT = 0, + LIBLTE_RRC_CDMA2000_TYPE_HRPD, + LIBLTE_RRC_CDMA2000_TYPE_N_ITEMS, +}LIBLTE_RRC_CDMA2000_TYPE_ENUM; +static const char liblte_rrc_cdma2000_type_text[LIBLTE_RRC_CDMA2000_TYPE_N_ITEMS][20] = {"1xrtt", "hrpd"}; +typedef enum{ + LIBLTE_RRC_T_EVALUATION_S30 = 0, + LIBLTE_RRC_T_EVALUATION_S60, + LIBLTE_RRC_T_EVALUATION_S120, + LIBLTE_RRC_T_EVALUATION_S180, + LIBLTE_RRC_T_EVALUATION_S240, + LIBLTE_RRC_T_EVALUATION_SPARE3, + LIBLTE_RRC_T_EVALUATION_SPARE2, + LIBLTE_RRC_T_EVALUATION_SPARE1, + LIBLTE_RRC_T_EVALUATION_N_ITEMS, +}LIBLTE_RRC_T_EVALUATION_ENUM; +static const char liblte_rrc_t_evaluation_text[LIBLTE_RRC_T_EVALUATION_N_ITEMS][20] = { "30", "60", "120", "180", + "240", "SPARE", "SPARE", "SPARE"}; +static const int16 liblte_rrc_t_evaluation_num[LIBLTE_RRC_T_EVALUATION_N_ITEMS] = {30, 60, 120, 180, 240, -1, -1, -1}; +typedef enum{ + LIBLTE_RRC_T_HYST_NORMAL_S30 = 0, + LIBLTE_RRC_T_HYST_NORMAL_S60, + LIBLTE_RRC_T_HYST_NORMAL_S120, + LIBLTE_RRC_T_HYST_NORMAL_S180, + LIBLTE_RRC_T_HYST_NORMAL_S240, + LIBLTE_RRC_T_HYST_NORMAL_SPARE3, + LIBLTE_RRC_T_HYST_NORMAL_SPARE2, + LIBLTE_RRC_T_HYST_NORMAL_SPARE1, + LIBLTE_RRC_T_HYST_NORMAL_N_ITEMS, +}LIBLTE_RRC_T_HYST_NORMAL_ENUM; +static const char liblte_rrc_t_hyst_normal_text[LIBLTE_RRC_T_HYST_NORMAL_N_ITEMS][20] = { "30", "60", "120", "180", + "240", "SPARE", "SPARE", "SPARE"}; +static const int16 liblte_rrc_t_hyst_normal_num[LIBLTE_RRC_T_HYST_NORMAL_N_ITEMS] = {30, 60, 120, 180, 240, -1, -1, -1}; +typedef enum{ + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N4 = 0, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N8, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N12, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N16, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N24, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N32, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N48, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N64, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N84, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N96, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N128, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N168, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N252, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N504, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_SPARE2, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_SPARE1, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N1, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_N_ITEMS, +}LIBLTE_RRC_PHYS_CELL_ID_RANGE_ENUM; +static const char liblte_rrc_phys_cell_id_range_text[LIBLTE_RRC_PHYS_CELL_ID_RANGE_N_ITEMS][20] = { "4", "8", "12", "16", + "24", "32", "48", "64", + "84", "96", "128", "168", + "252", "504", "SPARE", "SPARE", + "1"}; +static const int16 liblte_rrc_phys_cell_id_range_num[LIBLTE_RRC_PHYS_CELL_ID_RANGE_N_ITEMS] = {4, 8, 12, 16, 24, 32, 48, 64, 84, 96, 128, 168, 252, 504, -1, -1, 1}; +typedef enum{ + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N24 = 0, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N22, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N20, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N18, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N16, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N14, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N12, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N10, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N8, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N6, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N5, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N4, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N3, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N2, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_N1, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_0, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_1, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_2, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_3, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_4, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_5, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_6, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_8, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_10, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_12, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_14, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_16, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_18, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_20, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_22, + LIBLTE_RRC_Q_OFFSET_RANGE_DB_24, + LIBLTE_RRC_Q_OFFSET_RANGE_SPARE, + LIBLTE_RRC_Q_OFFSET_RANGE_N_ITEMS, +}LIBLTE_RRC_Q_OFFSET_RANGE_ENUM; +static const char liblte_rrc_q_offset_range_text[LIBLTE_RRC_Q_OFFSET_RANGE_N_ITEMS][20] = { "-24", "-22", "-20", "-18", + "-16", "-14", "-12", "-10", + "-8", "-6", "-5", "-4", + "-3", "-2", "-1", "0", + "1", "2", "3", "4", + "5", "6", "8", "10", + "12", "14", "16", "18", + "20", "22", "24", "SPARE"}; +static const int8 liblte_rrc_q_offset_range_num[LIBLTE_RRC_Q_OFFSET_RANGE_N_ITEMS] = {-24, -22, -20, -18, -16, -14, -12, -10, -8, -6, -5, -4, -3, -2, -1, 0, + 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 0}; +typedef enum{ + LIBLTE_RRC_SSSF_MEDIUM_0DOT25 = 0, + LIBLTE_RRC_SSSF_MEDIUM_0DOT5, + LIBLTE_RRC_SSSF_MEDIUM_0DOT75, + LIBLTE_RRC_SSSF_MEDIUM_1DOT0, + LIBLTE_RRC_SSSF_MEDIUM_N_ITEMS, +}LIBLTE_RRC_SSSF_MEDIUM_ENUM; +static const char liblte_rrc_sssf_medium_text[LIBLTE_RRC_SSSF_MEDIUM_N_ITEMS][20] = {"0.25", "0.5", "0.75", "1.0"}; +static const double liblte_rrc_sssf_medium_num[LIBLTE_RRC_SSSF_MEDIUM_N_ITEMS] = {0.25, 0.5, 0.75, 1.0}; +typedef enum{ + LIBLTE_RRC_SSSF_HIGH_0DOT25 = 0, + LIBLTE_RRC_SSSF_HIGH_0DOT5, + LIBLTE_RRC_SSSF_HIGH_0DOT75, + LIBLTE_RRC_SSSF_HIGH_1DOT0, + LIBLTE_RRC_SSSF_HIGH_N_ITEMS, +}LIBLTE_RRC_SSSF_HIGH_ENUM; +static const char liblte_rrc_sssf_high_text[LIBLTE_RRC_SSSF_HIGH_N_ITEMS][20] = {"0.25", "0.5", "0.75", "1.0"}; +static const double liblte_rrc_sssf_high_num[LIBLTE_RRC_SSSF_HIGH_N_ITEMS] = {0.25, 0.5, 0.75, 1.0}; +typedef enum{ + LIBLTE_RRC_GAP_OFFSET_TYPE_GP0 = 0, + LIBLTE_RRC_GAP_OFFSET_TYPE_GP1, + LIBLTE_RRC_GAP_OFFSET_TYPE_RELEASE, + LIBLTE_RRC_GAP_OFFSET_TYPE_N_ITEMS, +}LIBLTE_RRC_GAP_OFFSET_TYPE_ENUM; +static const char liblte_rrc_gap_offset_type_text[LIBLTE_RRC_GAP_OFFSET_TYPE_N_ITEMS][20] = {"GP0", + "GP1", + "RELEASE"}; +typedef enum{ + LIBLTE_RRC_UTRA_SYSTEM_TYPE_FDD = 0, + LIBLTE_RRC_UTRA_SYSTEM_TYPE_TDD, + LIBLTE_RRC_UTRA_SYSTEM_TYPE_N_ITEMS, +}LIBLTE_RRC_UTRA_SYSTEM_TYPE_ENUM; +static const char liblte_rrc_utra_system_type_text[LIBLTE_RRC_UTRA_SYSTEM_TYPE_N_ITEMS][20] = {"FDD", + "TDD"}; +typedef enum{ + LIBLTE_RRC_MEAS_OBJECT_TYPE_EUTRA = 0, + LIBLTE_RRC_MEAS_OBJECT_TYPE_UTRA, + LIBLTE_RRC_MEAS_OBJECT_TYPE_GERAN, + LIBLTE_RRC_MEAS_OBJECT_TYPE_CDMA2000, + LIBLTE_RRC_MEAS_OBJECT_TYPE_N_ITEMS, +}LIBLTE_RRC_MEAS_OBJECT_TYPE_ENUM; +static const char liblte_rrc_meas_object_type_text[LIBLTE_RRC_MEAS_OBJECT_TYPE_N_ITEMS][20] = {"EUTRA", + "UTRA", + "GERAN", + "CDMA2000"}; +typedef enum{ + LIBLTE_RRC_MEAS_QUANTITY_UTRA_FDD_CPICH_RSCP = 0, + LIBLTE_RRC_MEAS_QUANTITY_UTRA_FDD_CPICH_ECNO, + LIBLTE_RRC_MEAS_QUANTITY_UTRA_FDD_N_ITEMS, +}LIBLTE_RRC_MEAS_QUANTITY_UTRA_FDD_ENUM; +static const char liblte_rrc_meas_quantity_utra_fdd_text[LIBLTE_RRC_MEAS_QUANTITY_UTRA_FDD_N_ITEMS][20] = {"CPICH RSCP", + "CPICH Ec/No"}; +typedef enum{ + LIBLTE_RRC_MEAS_QUANTITY_UTRA_TDD_PCCPCH_RSCP = 0, + LIBLTE_RRC_MEAS_QUANTITY_UTRA_TDD_N_ITEMS, +}LIBLTE_RRC_MEAS_QUANTITY_UTRA_TDD_ENUM; +static const char liblte_rrc_meas_quantity_utra_tdd_text[LIBLTE_RRC_MEAS_QUANTITY_UTRA_TDD_N_ITEMS][20] = {"PCCPCH RSCP"}; +typedef enum{ + LIBLTE_RRC_MEAS_QUANTITY_GERAN_RSSI = 0, + LIBLTE_RRC_MEAS_QUANTITY_GERAN_N_ITEMS, +}LIBLTE_RRC_MEAS_QUANTITY_GERAN_ENUM; +static const char liblte_rrc_meas_quantity_geran_text[LIBLTE_RRC_MEAS_QUANTITY_GERAN_N_ITEMS][20] = {"RSSI"}; +typedef enum{ + LIBLTE_RRC_MEAS_QUANTITY_CDMA2000_PILOT_STRENGTH = 0, + LIBLTE_RRC_MEAS_QUANTITY_CDMA2000_PILOT_PN_PHASE_AND_STRENGTH, + LIBLTE_RRC_MEAS_QUANTITY_CDMA2000_N_ITEMS, +}LIBLTE_RRC_MEAS_QUANTITY_CDMA2000_ENUM; +static const char liblte_rrc_meas_quantity_cdma2000_text[LIBLTE_RRC_MEAS_QUANTITY_CDMA2000_N_ITEMS][100] = {"Pilot Strength", + "Pilot PN Phase and Strength"}; +typedef enum{ + LIBLTE_RRC_REPORT_INTERVAL_MS120 = 0, + LIBLTE_RRC_REPORT_INTERVAL_MS240, + LIBLTE_RRC_REPORT_INTERVAL_MS480, + LIBLTE_RRC_REPORT_INTERVAL_MS640, + LIBLTE_RRC_REPORT_INTERVAL_MS1024, + LIBLTE_RRC_REPORT_INTERVAL_MS2048, + LIBLTE_RRC_REPORT_INTERVAL_MS5120, + LIBLTE_RRC_REPORT_INTERVAL_MS10240, + LIBLTE_RRC_REPORT_INTERVAL_MIN1, + LIBLTE_RRC_REPORT_INTERVAL_MIN6, + LIBLTE_RRC_REPORT_INTERVAL_MIN12, + LIBLTE_RRC_REPORT_INTERVAL_MIN30, + LIBLTE_RRC_REPORT_INTERVAL_MIN60, + LIBLTE_RRC_REPORT_INTERVAL_SPARE3, + LIBLTE_RRC_REPORT_INTERVAL_SPARE2, + LIBLTE_RRC_REPORT_INTERVAL_SPARE1, + LIBLTE_RRC_REPORT_INTERVAL_N_ITEMS, +}LIBLTE_RRC_REPORT_INTERVAL_ENUM; +static const char liblte_rrc_report_interval_text[LIBLTE_RRC_REPORT_INTERVAL_N_ITEMS][20] = { "120", "240", "480", "640", + "1024", "2048", "5120", "10240", + "60000", "360000", "720000", "1800000", + "3600000", "SPARE", "SPARE", "SPARE"}; +static const int32 liblte_rrc_report_interval_num[LIBLTE_RRC_REPORT_INTERVAL_N_ITEMS] = {120, 240, 480, 640, 1024, 2048, 5120, 10240, 60000, 360000, 720000, 1800000, 3600000, -1, -1, -1}; +typedef enum{ + LIBLTE_RRC_TIME_TO_TRIGGER_MS0 = 0, + LIBLTE_RRC_TIME_TO_TRIGGER_MS40, + LIBLTE_RRC_TIME_TO_TRIGGER_MS64, + LIBLTE_RRC_TIME_TO_TRIGGER_MS80, + LIBLTE_RRC_TIME_TO_TRIGGER_MS100, + LIBLTE_RRC_TIME_TO_TRIGGER_MS128, + LIBLTE_RRC_TIME_TO_TRIGGER_MS160, + LIBLTE_RRC_TIME_TO_TRIGGER_MS256, + LIBLTE_RRC_TIME_TO_TRIGGER_MS320, + LIBLTE_RRC_TIME_TO_TRIGGER_MS480, + LIBLTE_RRC_TIME_TO_TRIGGER_MS512, + LIBLTE_RRC_TIME_TO_TRIGGER_MS640, + LIBLTE_RRC_TIME_TO_TRIGGER_MS1024, + LIBLTE_RRC_TIME_TO_TRIGGER_MS1280, + LIBLTE_RRC_TIME_TO_TRIGGER_MS2560, + LIBLTE_RRC_TIME_TO_TRIGGER_MS5120, + LIBLTE_RRC_TIME_TO_TRIGGER_N_ITEMS, +}LIBLTE_RRC_TIME_TO_TRIGGER_ENUM; +static const char liblte_rrc_time_to_trigger_text[LIBLTE_RRC_TIME_TO_TRIGGER_N_ITEMS][20] = { "0", "40", "64", "80", + "100", "128", "160", "256", + "320", "480", "512", "640", + "1024", "1280", "2560", "5120"}; +static const uint16 liblte_rrc_time_to_trigger_num[LIBLTE_RRC_TIME_TO_TRIGGER_N_ITEMS] = {0, 40, 64, 80, 100, 128, 160, 256, 320, 480, 512, 640, 1024, 1280, 2560, 5120}; +typedef enum{ + LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP = 0, + LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRQ, + LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_N_ITEMS, +}LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM; +static const char liblte_rrc_threshold_eutra_type_text[LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_N_ITEMS][20] = {"RSRP", + "RSRQ"}; +typedef enum{ + LIBLTE_RRC_EVENT_ID_EUTRA_A1 = 0, + LIBLTE_RRC_EVENT_ID_EUTRA_A2, + LIBLTE_RRC_EVENT_ID_EUTRA_A3, + LIBLTE_RRC_EVENT_ID_EUTRA_A4, + LIBLTE_RRC_EVENT_ID_EUTRA_A5, + LIBLTE_RRC_EVENT_ID_EUTRA_A6, + LIBLTE_RRC_EVENT_ID_EUTRA_N_ITEMS, +}LIBLTE_RRC_EVENT_ID_EUTRA_ENUM; +static const char liblte_rrc_event_id_eutra_text[LIBLTE_RRC_EVENT_ID_EUTRA_N_ITEMS][20] = {"A1", "A2", "A3", + "A4", "A5", "A6"}; +typedef enum{ + LIBLTE_RRC_PURPOSE_EUTRA_REPORT_STRONGEST_CELL = 0, + LIBLTE_RRC_PURPOSE_EUTRA_REPORT_CGI, + LIBLTE_RRC_PURPOSE_EUTRA_N_ITEMS, +}LIBLTE_RRC_PURPOSE_EUTRA_ENUM; +static const char liblte_rrc_purpose_eutra_text[LIBLTE_RRC_PURPOSE_EUTRA_N_ITEMS][100] = {"Report Strongest Cell", + "Report CGI"}; +typedef enum{ + LIBLTE_RRC_TRIGGER_TYPE_EUTRA_EVENT = 0, + LIBLTE_RRC_TRIGGER_TYPE_EUTRA_PERIODICAL, + LIBLTE_RRC_TRIGGER_TYPE_EUTRA_N_ITEMS, +}LIBLTE_RRC_TRIGGER_TYPE_EUTRA_ENUM; +static const char liblte_rrc_trigger_type_eutra_text[LIBLTE_RRC_TRIGGER_TYPE_EUTRA_N_ITEMS][20] = {"Event", + "Periodical"}; +typedef enum{ + LIBLTE_RRC_TRIGGER_QUANTITY_RSRP = 0, + LIBLTE_RRC_TRIGGER_QUANTITY_RSRQ, + LIBLTE_RRC_TRIGGER_QUANTITY_N_ITEMS, +}LIBLTE_RRC_TRIGGER_QUANTITY_ENUM; +static const char liblte_rrc_trigger_quantity_text[LIBLTE_RRC_TRIGGER_QUANTITY_N_ITEMS][20] = {"RSRP", + "RSRQ"}; +typedef enum{ + LIBLTE_RRC_REPORT_QUANTITY_SAME_AS_TRIGGER_QUANTITY = 0, + LIBLTE_RRC_REPORT_QUANTITY_BOTH, + LIBLTE_RRC_REPORT_QUANTITY_N_ITEMS, +}LIBLTE_RRC_REPORT_QUANTITY_ENUM; +static const char liblte_rrc_report_quantity_text[LIBLTE_RRC_REPORT_QUANTITY_N_ITEMS][100] = {"Same As Trigger Quantity", + "Both"}; +typedef enum{ + LIBLTE_RRC_REPORT_AMOUNT_R1 = 0, + LIBLTE_RRC_REPORT_AMOUNT_R2, + LIBLTE_RRC_REPORT_AMOUNT_R4, + LIBLTE_RRC_REPORT_AMOUNT_R8, + LIBLTE_RRC_REPORT_AMOUNT_R16, + LIBLTE_RRC_REPORT_AMOUNT_R32, + LIBLTE_RRC_REPORT_AMOUNT_R64, + LIBLTE_RRC_REPORT_AMOUNT_INFINITY, + LIBLTE_RRC_REPORT_AMOUNT_N_ITEMS, +}LIBLTE_RRC_REPORT_AMOUNT_ENUM; +static const char liblte_rrc_report_amount_text[LIBLTE_RRC_REPORT_AMOUNT_N_ITEMS][20] = { "r1", "r2", "r4", "r8", + "r16", "r32", "r64", "INFINITY"}; +typedef enum{ + LIBLTE_RRC_THRESHOLD_UTRA_TYPE_RSCP = 0, + LIBLTE_RRC_THRESHOLD_UTRA_TYPE_ECNO, + LIBLTE_RRC_THRESHOLD_UTRA_TYPE_N_ITEMS, +}LIBLTE_RRC_THRESHOLD_UTRA_TYPE_ENUM; +static const char liblte_rrc_threshold_utra_type_text[LIBLTE_RRC_THRESHOLD_UTRA_TYPE_N_ITEMS][20] = {"RSCP", + "Ec/No"}; +typedef enum{ + LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_UTRA = 0, + LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_GERAN, + LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_CDMA2000, + LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_N_ITEMS, +}LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_ENUM; +static const char liblte_rrc_threshold_inter_rat_type_text[LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_N_ITEMS][20] = {"UTRA", + "GERAN", + "CDMA2000"}; +typedef enum{ + LIBLTE_RRC_EVENT_ID_INTER_RAT_B1 = 0, + LIBLTE_RRC_EVENT_ID_INTER_RAT_B2, + LIBLTE_RRC_EVENT_ID_INTER_RAT_N_ITEMS, +}LIBLTE_RRC_EVENT_ID_INTER_RAT_ENUM; +static const char liblte_rrc_event_id_inter_rat_text[LIBLTE_RRC_EVENT_ID_INTER_RAT_N_ITEMS][20] = {"B1", + "B2"}; +typedef enum{ + LIBLTE_RRC_PURPOSE_INTER_RAT_REPORT_STRONGEST_CELLS = 0, + LIBLTE_RRC_PURPOSE_INTER_RAT_REPORT_STRONGEST_CELLS_FOR_SON, + LIBLTE_RRC_PURPOSE_INTER_RAT_REPORT_CGI, + LIBLTE_RRC_PURPOSE_INTER_RAT_N_ITEMS, +}LIBLTE_RRC_PURPOSE_INTER_RAT_ENUM; +static const char liblte_rrc_purpose_inter_rat_text[LIBLTE_RRC_PURPOSE_INTER_RAT_N_ITEMS][100] = {"Report Strongest Cells", + "Report Strongest Cells for SON", + "Report CGI"}; +typedef enum{ + LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_EVENT = 0, + LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_PERIODICAL, + LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_N_ITEMS, +}LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_ENUM; +static const char liblte_rrc_trigger_type_inter_rat_text[LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_N_ITEMS][20] = {"Event", + "Periodical"}; +typedef enum{ + LIBLTE_RRC_REPORT_CONFIG_TYPE_EUTRA = 0, + LIBLTE_RRC_REPORT_CONFIG_TYPE_INTER_RAT, + LIBLTE_RRC_REPORT_CONFIG_TYPE_N_ITEMS, +}LIBLTE_RRC_REPORT_CONFIG_TYPE_ENUM; +static const char liblte_rrc_report_config_type_text[LIBLTE_RRC_REPORT_CONFIG_TYPE_N_ITEMS][20] = {"EUTRA", + "Inter RAT"}; // Structs +typedef struct{ + LIBLTE_RRC_BAND_CLASS_CDMA2000_ENUM bandclass; + uint16 arfcn; +}LIBLTE_RRC_CARRIER_FREQ_CDMA2000_STRUCT; typedef struct{ uint8 arfcn_spacing; uint8 number_of_arfcns; @@ -1199,247 +1175,1553 @@ typedef struct{ uint16 variable_bit_map_of_arfcns; uint8 explicit_list_of_arfcns_size; }LIBLTE_RRC_CARRIER_FREQS_GERAN_STRUCT; -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_carrier_freqs_geran_ie(LIBLTE_RRC_CARRIER_FREQS_GERAN_STRUCT *carrier_freqs, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_carrier_freqs_geran_ie(uint8 **ie_ptr, - LIBLTE_RRC_CARRIER_FREQS_GERAN_STRUCT *carrier_freqs); +typedef struct{ + uint32 N_cell_idx; + uint8 cell_idx[LIBLTE_RRC_MAX_CELL_MEAS]; +}LIBLTE_RRC_CELL_INDEX_LIST_STRUCT; +typedef struct{ + LIBLTE_RRC_T_EVALUATION_ENUM t_eval; + LIBLTE_RRC_T_HYST_NORMAL_ENUM t_hyst_normal; + uint8 n_cell_change_medium; + uint8 n_cell_change_high; +}LIBLTE_RRC_MOBILITY_STATE_PARAMETERS_STRUCT; +typedef struct{ + LIBLTE_RRC_PHYS_CELL_ID_RANGE_ENUM range; + uint16 start; +}LIBLTE_RRC_PHYS_CELL_ID_RANGE_STRUCT; +typedef struct{ + uint8 ncc; + uint8 bcc; +}LIBLTE_RRC_PHYS_CELL_ID_GERAN_STRUCT; +typedef struct{ + uint8 pre_reg_zone_id; + uint8 secondary_pre_reg_zone_id_list[2]; + uint8 secondary_pre_reg_zone_id_list_size; + bool pre_reg_allowed; + bool pre_reg_zone_id_present; +}LIBLTE_RRC_PRE_REGISTRATION_INFO_HRPD_STRUCT; +typedef struct{ + LIBLTE_RRC_SSSF_MEDIUM_ENUM sf_medium; + LIBLTE_RRC_SSSF_HIGH_ENUM sf_high; +}LIBLTE_RRC_SPEED_STATE_SCALE_FACTORS_STRUCT; +typedef struct{ + LIBLTE_RRC_GAP_OFFSET_TYPE_ENUM gap_offset_type; + uint8 gap_offset; +}LIBLTE_RRC_MEAS_GAP_CONFIG_STRUCT; +typedef struct{ + uint8 meas_id; + uint8 meas_obj_id; + uint8 rep_cnfg_id; +}LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_STRUCT; +typedef struct{ + LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_STRUCT meas_id_list[LIBLTE_RRC_MAX_MEAS_ID]; + uint32 N_meas_id; +}LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_LIST_STRUCT; +typedef struct{ + uint16 pci; + uint8 cell_idx; +}LIBLTE_RRC_CELLS_TO_ADD_MOD_CDMA2000_STRUCT; +typedef struct{ + LIBLTE_RRC_CARRIER_FREQ_CDMA2000_STRUCT carrier_freq; + LIBLTE_RRC_CELL_INDEX_LIST_STRUCT cells_to_remove_list; + LIBLTE_RRC_CELLS_TO_ADD_MOD_CDMA2000_STRUCT cells_to_add_mod_list[LIBLTE_RRC_MAX_CELL_MEAS]; + LIBLTE_RRC_CDMA2000_TYPE_ENUM cdma2000_type; + uint32 N_cells_to_add_mod; + uint16 cell_for_which_to_rep_cgi; + uint8 search_win_size; + int8 offset_freq; + bool search_win_size_present; + bool cells_to_remove_list_present; + bool cell_for_which_to_rep_cgi_present; +}LIBLTE_RRC_MEAS_OBJECT_CDMA2000_STRUCT; +typedef struct{ + LIBLTE_RRC_Q_OFFSET_RANGE_ENUM cell_offset; + uint16 pci; + uint8 cell_idx; +}LIBLTE_RRC_CELLS_TO_ADD_MOD_STRUCT; +typedef struct{ + LIBLTE_RRC_PHYS_CELL_ID_RANGE_STRUCT pci_range; + uint8 cell_idx; +}LIBLTE_RRC_BLACK_CELLS_TO_ADD_MOD_STRUCT; +typedef struct{ + LIBLTE_RRC_CELL_INDEX_LIST_STRUCT cells_to_remove_list; + LIBLTE_RRC_CELLS_TO_ADD_MOD_STRUCT cells_to_add_mod_list[LIBLTE_RRC_MAX_CELL_MEAS]; + LIBLTE_RRC_CELL_INDEX_LIST_STRUCT black_cells_to_remove_list; + LIBLTE_RRC_BLACK_CELLS_TO_ADD_MOD_STRUCT black_cells_to_add_mod_list[LIBLTE_RRC_MAX_CELL_MEAS]; + LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_ENUM allowed_meas_bw; + LIBLTE_RRC_Q_OFFSET_RANGE_ENUM offset_freq; + uint32 N_cells_to_add_mod; + uint32 N_black_cells_to_add_mod; + uint16 carrier_freq; + uint16 cell_for_which_to_rep_cgi; + uint8 neigh_cell_cnfg; + bool presence_ant_port_1; + bool cells_to_remove_list_present; + bool black_cells_to_remove_list_present; + bool cell_for_which_to_rep_cgi_present; +}LIBLTE_RRC_MEAS_OBJECT_EUTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_CARRIER_FREQS_GERAN_STRUCT carrier_freqs; + LIBLTE_RRC_PHYS_CELL_ID_GERAN_STRUCT cell_for_which_to_rep_cgi; + int8 offset_freq; + uint8 ncc_permitted; + bool cell_for_which_to_rep_cgi_present; +}LIBLTE_RRC_MEAS_OBJECT_GERAN_STRUCT; +typedef struct{ + uint16 pci; + uint8 cell_idx; +}LIBLTE_RRC_CELLS_TO_ADD_MOD_LIST_UTRA_FDD_STRUCT; +typedef struct{ + uint8 cell_idx; + uint8 pci; +}LIBLTE_RRC_CELLS_TO_ADD_MOD_LIST_UTRA_TDD_STRUCT; +typedef struct{ + LIBLTE_RRC_CELLS_TO_ADD_MOD_LIST_UTRA_FDD_STRUCT cells_fdd[LIBLTE_RRC_MAX_CELL_MEAS]; + LIBLTE_RRC_CELLS_TO_ADD_MOD_LIST_UTRA_TDD_STRUCT cells_tdd[LIBLTE_RRC_MAX_CELL_MEAS]; + LIBLTE_RRC_UTRA_SYSTEM_TYPE_ENUM type; + uint32 N_cells; +}LIBLTE_RRC_CELLS_TO_ADD_MOD_LIST_UTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_UTRA_SYSTEM_TYPE_ENUM type; + uint16 pci_fdd; + uint8 pci_tdd; +}LIBLTE_RRC_CELLS_FOR_WHICH_TO_REPORT_CGI_STRUCT; +typedef struct{ + LIBLTE_RRC_CELL_INDEX_LIST_STRUCT cells_to_remove_list; + LIBLTE_RRC_CELLS_TO_ADD_MOD_LIST_UTRA_STRUCT cells_to_add_mod_list; + LIBLTE_RRC_CELLS_FOR_WHICH_TO_REPORT_CGI_STRUCT cells_for_which_to_rep_cgi; + uint16 carrier_freq; + int8 offset_freq; + bool cells_to_remove_list_present; + bool cells_to_add_mod_list_present; + bool cells_for_which_to_rep_cgi_present; +}LIBLTE_RRC_MEAS_OBJECT_UTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_MEAS_OBJECT_EUTRA_STRUCT meas_obj_eutra; + LIBLTE_RRC_MEAS_OBJECT_UTRA_STRUCT meas_obj_utra; + LIBLTE_RRC_MEAS_OBJECT_GERAN_STRUCT meas_obj_geran; + LIBLTE_RRC_MEAS_OBJECT_CDMA2000_STRUCT meas_obj_cdma2000; + LIBLTE_RRC_MEAS_OBJECT_TYPE_ENUM meas_obj_type; + uint8 meas_obj_id; +}LIBLTE_RRC_MEAS_OBJECT_TO_ADD_MOD_STRUCT; +typedef struct{ + LIBLTE_RRC_MEAS_OBJECT_TO_ADD_MOD_STRUCT meas_obj_list[LIBLTE_RRC_MAX_OBJECT_ID]; + uint32 N_meas_obj; +}LIBLTE_RRC_MEAS_OBJECT_TO_ADD_MOD_LIST_STRUCT; +typedef struct{ + LIBLTE_RRC_FILTER_COEFFICIENT_ENUM fc_rsrp; + LIBLTE_RRC_FILTER_COEFFICIENT_ENUM fc_rsrq; +}LIBLTE_RRC_QUANTITY_CONFIG_EUTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_MEAS_QUANTITY_UTRA_FDD_ENUM mq_fdd; + LIBLTE_RRC_MEAS_QUANTITY_UTRA_TDD_ENUM mq_tdd; + LIBLTE_RRC_FILTER_COEFFICIENT_ENUM fc; +}LIBLTE_RRC_QUANTITY_CONFIG_UTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_MEAS_QUANTITY_GERAN_ENUM mq; + LIBLTE_RRC_FILTER_COEFFICIENT_ENUM fc; +}LIBLTE_RRC_QUANTITY_CONFIG_GERAN_STRUCT; +typedef struct{ + LIBLTE_RRC_MEAS_QUANTITY_CDMA2000_ENUM mq; +}LIBLTE_RRC_QUANTITY_CONFIG_CDMA2000_STRUCT; +typedef struct{ + LIBLTE_RRC_QUANTITY_CONFIG_EUTRA_STRUCT qc_eutra; + LIBLTE_RRC_QUANTITY_CONFIG_UTRA_STRUCT qc_utra; + LIBLTE_RRC_QUANTITY_CONFIG_GERAN_STRUCT qc_geran; + LIBLTE_RRC_QUANTITY_CONFIG_CDMA2000_STRUCT qc_cdma2000; + bool qc_eutra_present; + bool qc_utra_present; + bool qc_geran_present; + bool qc_cdma2000_present; +}LIBLTE_RRC_QUANTITY_CONFIG_STRUCT; +typedef struct{ + LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM type; + uint8 range; +}LIBLTE_RRC_THRESHOLD_EUTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_THRESHOLD_EUTRA_STRUCT eutra; +}LIBLTE_RRC_EVENT_A1_STRUCT; +typedef struct{ + LIBLTE_RRC_THRESHOLD_EUTRA_STRUCT eutra; +}LIBLTE_RRC_EVENT_A2_STRUCT; +typedef struct{ + int8 offset; + bool report_on_leave; +}LIBLTE_RRC_EVENT_A3_STRUCT; +typedef struct{ + LIBLTE_RRC_THRESHOLD_EUTRA_STRUCT eutra; +}LIBLTE_RRC_EVENT_A4_STRUCT; +typedef struct{ + LIBLTE_RRC_THRESHOLD_EUTRA_STRUCT eutra1; + LIBLTE_RRC_THRESHOLD_EUTRA_STRUCT eutra2; +}LIBLTE_RRC_EVENT_A5_STRUCT; +typedef struct{ + int8 offset; + bool report_on_leave; +}LIBLTE_RRC_EVENT_A6_STRUCT; +typedef struct{ + LIBLTE_RRC_EVENT_A1_STRUCT event_a1; + LIBLTE_RRC_EVENT_A2_STRUCT event_a2; + LIBLTE_RRC_EVENT_A3_STRUCT event_a3; + LIBLTE_RRC_EVENT_A4_STRUCT event_a4; + LIBLTE_RRC_EVENT_A5_STRUCT event_a5; + LIBLTE_RRC_EVENT_A6_STRUCT event_a6; + LIBLTE_RRC_EVENT_ID_EUTRA_ENUM event_id; + LIBLTE_RRC_TIME_TO_TRIGGER_ENUM time_to_trigger; + float hysteresis; +}LIBLTE_RRC_EVENT_EUTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_PURPOSE_EUTRA_ENUM purpose; +}LIBLTE_RRC_PERIODICAL_EUTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_EVENT_EUTRA_STRUCT event; + LIBLTE_RRC_PERIODICAL_EUTRA_STRUCT periodical; + LIBLTE_RRC_TRIGGER_TYPE_EUTRA_ENUM trigger_type; + LIBLTE_RRC_TRIGGER_QUANTITY_ENUM trigger_quantity; + LIBLTE_RRC_REPORT_QUANTITY_ENUM report_quantity; + LIBLTE_RRC_REPORT_INTERVAL_ENUM report_interval; + LIBLTE_RRC_REPORT_AMOUNT_ENUM report_amount; + uint8 max_report_cells; +}LIBLTE_RRC_REPORT_CONFIG_EUTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_THRESHOLD_UTRA_TYPE_ENUM type; + int8 value; +}LIBLTE_RRC_THRESHOLD_UTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_THRESHOLD_UTRA_STRUCT utra; + LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_ENUM type; + uint8 geran; + uint8 cdma2000; +}LIBLTE_RRC_EVENT_B1_STRUCT; +typedef struct{ + LIBLTE_RRC_THRESHOLD_UTRA_STRUCT utra; + LIBLTE_RRC_THRESHOLD_EUTRA_STRUCT eutra; + LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_ENUM type2; + uint8 geran; + uint8 cdma2000; +}LIBLTE_RRC_EVENT_B2_STRUCT; +typedef struct{ + LIBLTE_RRC_EVENT_B1_STRUCT event_b1; + LIBLTE_RRC_EVENT_B2_STRUCT event_b2; + LIBLTE_RRC_EVENT_ID_INTER_RAT_ENUM event_id; + LIBLTE_RRC_TIME_TO_TRIGGER_ENUM time_to_trigger; + float hysteresis; +}LIBLTE_RRC_EVENT_INTER_RAT_STRUCT; +typedef struct{ + LIBLTE_RRC_PURPOSE_INTER_RAT_ENUM purpose; +}LIBLTE_RRC_PERIODICAL_INTER_RAT_STRUCT; +typedef struct{ + LIBLTE_RRC_EVENT_INTER_RAT_STRUCT event; + LIBLTE_RRC_PERIODICAL_INTER_RAT_STRUCT periodical; + LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_ENUM trigger_type; + LIBLTE_RRC_REPORT_INTERVAL_ENUM report_interval; + LIBLTE_RRC_REPORT_AMOUNT_ENUM report_amount; + uint8 max_report_cells; +}LIBLTE_RRC_REPORT_CONFIG_INTER_RAT_STRUCT; +typedef struct{ + LIBLTE_RRC_REPORT_CONFIG_EUTRA_STRUCT rep_cnfg_eutra; + LIBLTE_RRC_REPORT_CONFIG_INTER_RAT_STRUCT rep_cnfg_inter_rat; + LIBLTE_RRC_REPORT_CONFIG_TYPE_ENUM rep_cnfg_type; + uint8 rep_cnfg_id; +}LIBLTE_RRC_REPORT_CONFIG_TO_ADD_MOD_STRUCT; +typedef struct{ + LIBLTE_RRC_REPORT_CONFIG_TO_ADD_MOD_STRUCT rep_cnfg_list[LIBLTE_RRC_MAX_REPORT_CONFIG_ID]; + uint32 N_rep_cnfg; +}LIBLTE_RRC_REPORT_CONFIG_TO_ADD_MOD_LIST_STRUCT; +typedef struct{ + LIBLTE_RRC_MOBILITY_STATE_PARAMETERS_STRUCT mob_state_params; + LIBLTE_RRC_SPEED_STATE_SCALE_FACTORS_STRUCT time_to_trig_sf; +}LIBLTE_RRC_SPEED_STATE_PARAMS_STRUCT; +typedef struct{ + LIBLTE_RRC_MEAS_OBJECT_TO_ADD_MOD_LIST_STRUCT meas_obj_to_add_mod_list; + LIBLTE_RRC_REPORT_CONFIG_TO_ADD_MOD_LIST_STRUCT rep_cnfg_to_add_mod_list; + LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_LIST_STRUCT meas_id_to_add_mod_list; + LIBLTE_RRC_QUANTITY_CONFIG_STRUCT quantity_cnfg; + LIBLTE_RRC_MEAS_GAP_CONFIG_STRUCT meas_gap_cnfg; + LIBLTE_RRC_PRE_REGISTRATION_INFO_HRPD_STRUCT pre_reg_info_hrpd; + LIBLTE_RRC_SPEED_STATE_PARAMS_STRUCT speed_state_params; + uint32 N_meas_obj_to_remove; + uint32 N_rep_cnfg_to_remove; + uint32 N_meas_id_to_remove; + uint8 meas_obj_to_remove_list[LIBLTE_RRC_MAX_OBJECT_ID]; + uint8 rep_cnfg_to_remove_list[LIBLTE_RRC_MAX_REPORT_CONFIG_ID]; + uint8 meas_id_to_remove_list[LIBLTE_RRC_MAX_MEAS_ID]; + uint8 s_meas; + bool meas_obj_to_add_mod_list_present; + bool rep_cnfg_to_add_mod_list_present; + bool meas_id_to_add_mod_list_present; + bool quantity_cnfg_present; + bool meas_gap_cnfg_present; + bool s_meas_present; + bool pre_reg_info_hrpd_present; + bool speed_state_params_present; +}LIBLTE_RRC_MEAS_CONFIG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_config_ie(LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_cnfg, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_cnfg); /********************************************************************* - IE Name: CDMA2000 Type + IE Name: Meas Gap Config - Description: Describes the type of CDMA2000 network + Description: Specifies the measurement gap configuration and + controls setup/release of measurement gaps - Document Reference: 36.331 v10.0.0 Section 6.3.4 + Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ // Defines // Enums -typedef enum{ - LIBLTE_RRC_CDMA2000_TYPE_1XRTT = 0, - LIBLTE_RRC_CDMA2000_TYPE_HRPD, - LIBLTE_RRC_CDMA2000_TYPE_N_ITEMS, -}LIBLTE_RRC_CDMA2000_TYPE_ENUM; -static const char liblte_rrc_cdma2000_type_text[LIBLTE_RRC_CDMA2000_TYPE_N_ITEMS][20] = {"1xrtt", "hrpd"}; +// Meas Gap Config enum defined above // Structs +// Meas Gap Config struct defined above // Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_cdma2000_type_ie(LIBLTE_RRC_CDMA2000_TYPE_ENUM cdma2000_type, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_cdma2000_type_ie(uint8 **ie_ptr, - LIBLTE_RRC_CDMA2000_TYPE_ENUM *cdma2000_type); +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_gap_config_ie(LIBLTE_RRC_MEAS_GAP_CONFIG_STRUCT *meas_gap_cnfg, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_gap_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_GAP_CONFIG_STRUCT *meas_gap_cnfg); /********************************************************************* - IE Name: Cell Identity + IE Name: Meas ID - Description: Unambiguously identifies a cell within a PLMN + Description: Identifies a measurement configuration, i.e. linking + of a measurement object and a reporting configuration - Document Reference: 36.331 v10.0.0 Section 6.3.4 + Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ // Defines // Enums // Structs // Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_identity_ie(uint32 cell_id, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_identity_ie(uint8 **ie_ptr, - uint32 *cell_id); +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_id_ie(uint8 meas_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_id_ie(uint8 **ie_ptr, + uint8 *meas_id); /********************************************************************* - IE Name: Cell Index List + IE Name: Meas Id To Add Mod List - Description: Concerns a list of cell indecies, which may be used - for different purposes + Description: Concerns a list of measurement identities to add or + modify, with for each entry the meas ID, the + associated meas object ID and the associated report + config ID - Document Reference: 36.331 v10.0.0 Section 6.3.4 + Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ // Defines // Enums // Structs +// Meas ID To Add Mod List structs defined above // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_id_to_add_mod_list_ie(LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_LIST_STRUCT *list, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_id_to_add_mod_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_LIST_STRUCT *list); /********************************************************************* - IE Name: Cell Reselection Priority + IE Name: Meas Object CDMA2000 - Description: Contains the absolute priority of the concerned - carrier frequency/set of frequencies (GERAN)/ - bandclass (CDMA2000), as used by the cell - reselection procedure + Description: Specifies information applicable for inter-RAT + CDMA2000 neighboring cells - Document Reference: 36.331 v10.0.0 Section 6.3.4 + Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ // Defines // Enums // Structs +// Meas Object CDMA2000 structs defined above // Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_reselection_priority_ie(uint8 cell_resel_prio, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_reselection_priority_ie(uint8 **ie_ptr, - uint8 *cell_resel_prio); +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_cdma2000_ie(LIBLTE_RRC_MEAS_OBJECT_CDMA2000_STRUCT *meas_obj_cdma2000, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_cdma2000_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_OBJECT_CDMA2000_STRUCT *meas_obj_cdma2000); /********************************************************************* - IE Name: CSFB Registration Param 1xRTT + IE Name: Meas Object EUTRA - Description: Indicates whether or not the UE shall perform a - CDMA2000 1xRTT pre-registration if the UE does not - have a valid/current pre-registration + Description: Specifies information applicable for intra-frequency + or inter-frequency E-UTRA cells - Document Reference: 36.331 v10.0.0 Section 6.3.4 + Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ // Defines // Enums -typedef enum{ - LIBLTE_RRC_POWER_DOWN_REG_R9_TRUE = 0, - LIBLTE_RRC_POWER_DOWN_REG_R9_N_ITEMS, -}LIBLTE_RRC_POWER_DOWN_REG_R9_ENUM; -static const char liblte_rrc_power_down_reg_r9_text[LIBLTE_RRC_POWER_DOWN_REG_R9_N_ITEMS][20] = {"TRUE"}; // Structs -typedef struct{ - uint16 sid; - uint16 nid; - uint16 reg_zone; - uint8 reg_period; - uint8 total_zone; - uint8 zone_timer; - bool multiple_sid; - bool multiple_nid; - bool home_reg; - bool foreign_sid_reg; - bool foreign_nid_reg; - bool param_reg; - bool power_up_reg; -}LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_STRUCT; -typedef struct{ - LIBLTE_RRC_POWER_DOWN_REG_R9_ENUM power_down_reg; -}LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_V920_STRUCT; +// Meas Object EUTRA structs defined above // Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_csfb_registration_param_1xrtt_ie(LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_STRUCT *csfb_reg_param, +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_eutra_ie(LIBLTE_RRC_MEAS_OBJECT_EUTRA_STRUCT *meas_obj_eutra, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_eutra_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_OBJECT_EUTRA_STRUCT *meas_obj_eutra); + +/********************************************************************* + IE Name: Meas Object GERAN + + Description: Specifies information applicable for inter-RAT + GERAN neighboring frequencies + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Enums +// Structs +// Meas Object GERAN struct defined above +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_geran_ie(LIBLTE_RRC_MEAS_OBJECT_GERAN_STRUCT *meas_obj_geran, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_geran_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_OBJECT_GERAN_STRUCT *meas_obj_geran); + +/********************************************************************* + IE Name: Meas Object ID + + Description: Identifies a measurement object configuration + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_id_ie(uint8 meas_object_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_id_ie(uint8 **ie_ptr, + uint8 *meas_object_id); + +/********************************************************************* + IE Name: Meas Object To Add Mod List + + Description: Concerns a list of measurement objects to add or + modify + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Enums +// Meas Object To Add Mod List enum defined above +// Structs +// Meas Object To Add Mod List structs defined above +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_to_add_mod_list_ie(LIBLTE_RRC_MEAS_OBJECT_TO_ADD_MOD_LIST_STRUCT *list, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_to_add_mod_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_OBJECT_TO_ADD_MOD_LIST_STRUCT *list); + +/********************************************************************* + IE Name: Meas Object UTRA + + Description: Specifies information applicable for inter-RAT UTRA + neighboring cells + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Meas Object UTRA define defined above +// Enums +// Meas Object UTRA enum defined above +// Structs +// Meas Object UTRA structs defined above +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_utra_ie(LIBLTE_RRC_MEAS_OBJECT_UTRA_STRUCT *meas_obj_utra, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_utra_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_OBJECT_UTRA_STRUCT *meas_obj_utra); + +/********************************************************************* + IE Name: Meas Results + + Description: Covers measured results for intra-frequency, + inter-frequency and inter-RAT mobility + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +// FIXME + +/********************************************************************* + IE Name: Quantity Config + + Description: Specifies the measurement quantities and layer 3 + filtering coefficients for E-UTRA and inter-RAT + measurements + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Enums +// Quantity Config enums defined above +// Structs +// Quantity Config structs defined above +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_quantity_config_ie(LIBLTE_RRC_QUANTITY_CONFIG_STRUCT *qc, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_quantity_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_QUANTITY_CONFIG_STRUCT *qc); + +/********************************************************************* + IE Name: Report Config EUTRA + + Description: Specifies criteria for triggering of an E-UTRA + measurement reporting event + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Enums +// Report Config EUTRA enums defined above +// Structs +// Report Config EUTRA structs defined above +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_eutra_ie(LIBLTE_RRC_REPORT_CONFIG_EUTRA_STRUCT *rep_cnfg_eutra, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_eutra_ie(uint8 **ie_ptr, + LIBLTE_RRC_REPORT_CONFIG_EUTRA_STRUCT *rep_cnfg_eutra); + +/********************************************************************* + IE Name: Report Config ID + + Description: Identifies a measurement reporting configuration + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_id_ie(uint8 report_cnfg_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_id_ie(uint8 **ie_ptr, + uint8 *report_cnfg_id); + +/********************************************************************* + IE Name: Report Config Inter RAT + + Description: Specifies criteria for triggering of an inter-RAT + measurement reporting event + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Enums +// Report Config Inter RAT enums defined above +// Structs +// Report Config Inter RAT structs defined above +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_inter_rat_ie(LIBLTE_RRC_REPORT_CONFIG_INTER_RAT_STRUCT *rep_cnfg_inter_rat, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_inter_rat_ie(uint8 **ie_ptr, + LIBLTE_RRC_REPORT_CONFIG_INTER_RAT_STRUCT *rep_cnfg_inter_rat); + +/********************************************************************* + IE Name: Report Config To Add Mod List + + Description: Concerns a list of reporting configurations to add + or modify + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Enums +// Report Config To Add Mod List enum defined above +// Structs +// Report Config To Add Mod List structs defined above +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_to_add_mod_list_ie(LIBLTE_RRC_REPORT_CONFIG_TO_ADD_MOD_LIST_STRUCT *list, uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_csfb_registration_param_1xrtt_ie(uint8 **ie_ptr, - LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_STRUCT *csfb_reg_param); -LIBLTE_ERROR_ENUM liblte_rrc_pack_csfb_registration_param_1xrtt_v920_ie(LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_V920_STRUCT *csfb_reg_param, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_csfb_registration_param_1xrtt_v920_ie(uint8 **ie_ptr, - LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_V920_STRUCT *csfb_reg_param); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_to_add_mod_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_REPORT_CONFIG_TO_ADD_MOD_LIST_STRUCT *list); /********************************************************************* - IE Name: Cell Global ID EUTRA + IE Name: Report Interval - Description: Specifies the Evolved Cell Global Identifier (ECGI), - the globally unique identity of a cell in E-UTRA + Description: Indicates the interval between periodic reports - Document Reference: 36.331 v10.0.0 Section 6.3.4 + Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ // Defines // Enums +// Report Interval enum defined above // Structs -typedef struct{ - uint16 mcc; - uint16 mnc; -}LIBLTE_RRC_PLMN_IDENTITY_STRUCT; -typedef struct{ - LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id; - uint32 cell_id; -}LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT; // Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_eutra_ie(LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT *cell_global_id, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_eutra_ie(uint8 **ie_ptr, - LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT *cell_global_id); +LIBLTE_ERROR_ENUM liblte_rrc_pack_report_interval_ie(LIBLTE_RRC_REPORT_INTERVAL_ENUM report_int, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_interval_ie(uint8 **ie_ptr, + LIBLTE_RRC_REPORT_INTERVAL_ENUM *report_int); /********************************************************************* - IE Name: Cell Global ID UTRA + IE Name: RSRP Range - Description: Specifies the global UTRAN Cell Identifier, the - globally unique identity of a cell in UTRA + Description: Specifies the value range used in RSRP measurements + and thresholds - Document Reference: 36.331 v10.0.0 Section 6.3.4 + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_rsrp_range_ie(uint8 rsrp_range, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_rsrp_range_ie(uint8 **ie_ptr, + uint8 *rsrp_range); + +/********************************************************************* + IE Name: RSRQ Range + + Description: Specifies the value range used in RSRQ measurements + and thresholds + + Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ // Defines // Enums // Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_rsrq_range_ie(uint8 rsrq_range, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_rsrq_range_ie(uint8 **ie_ptr, + uint8 *rsrq_range); + +/********************************************************************* + IE Name: Time To Trigger + + Description: Specifies the value range used for the time to + trigger parameter, which concerns the time during + which specific criteria for the event needs to be + met in order to trigger a measurement report + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// Defines +// Enums +// Time To Trigger enum defined above +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_time_to_trigger_ie(LIBLTE_RRC_TIME_TO_TRIGGER_ENUM time_to_trigger, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_time_to_trigger_ie(uint8 **ie_ptr, + LIBLTE_RRC_TIME_TO_TRIGGER_ENUM *time_to_trigger); + +/********************************************************************* + IE Name: Additional Spectrum Emission + + Description: FIXME + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_additional_spectrum_emission_ie(uint8 add_spect_em, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_additional_spectrum_emission_ie(uint8 **ie_ptr, + uint8 *add_spect_em); + +/********************************************************************* + IE Name: ARFCN value CDMA2000 + + Description: Indicates the CDMA2000 carrier frequency within + a CDMA2000 band + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_cdma2000_ie(uint16 arfcn, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_cdma2000_ie(uint8 **ie_ptr, + uint16 *arfcn); + +/********************************************************************* + IE Name: ARFCN value EUTRA + + Description: Indicates the ARFCN applicable for a downlink, + uplink, or bi-directional (TDD) E-UTRA carrier + frequency + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_eutra_ie(uint16 arfcn, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_eutra_ie(uint8 **ie_ptr, + uint16 *arfcn); + +/********************************************************************* + IE Name: ARFCN value GERAN + + Description: Specifies the ARFCN value applicable for a GERAN + BCCH carrier frequency + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_geran_ie(uint16 arfcn, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_geran_ie(uint8 **ie_ptr, + uint16 *arfcn); + +/********************************************************************* + IE Name: ARFCN value UTRA + + Description: Indicates the ARFCN applicable for a downlink (Nd, + FDD) or bi-directional (Nt, TDD) UTRA carrier + frequency + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_utra_ie(uint16 arfcn, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_utra_ie(uint8 **ie_ptr, + uint16 *arfcn); + +/********************************************************************* + IE Name: Band Class CDMA2000 + + Description: Defines the CDMA2000 band in which the CDMA2000 + carrier frequency can be found + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Band Class CDMA2000 enum defined above +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_band_class_cdma2000_ie(LIBLTE_RRC_BAND_CLASS_CDMA2000_ENUM bc_cdma2000, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_band_class_cdma2000_ie(uint8 **ie_ptr, + LIBLTE_RRC_BAND_CLASS_CDMA2000_ENUM *bc_cdma2000); + +/********************************************************************* + IE Name: Band Indicator GERAN + + Description: Indicates how to interpret an associated GERAN + carrier ARFCN + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Band Indicator GERAN enum defined above +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_band_indicator_geran_ie(LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM bi_geran, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_band_indicator_geran_ie(uint8 **ie_ptr, + LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM *bi_geran); + +/********************************************************************* + IE Name: Carrier Freq CDMA2000 + + Description: Provides the CDMA2000 carrier information + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +// Carrier Freq CDMA2000 struct defined above +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_carrier_freq_cdma2000_ie(LIBLTE_RRC_CARRIER_FREQ_CDMA2000_STRUCT *carrier_freq, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_carrier_freq_cdma2000_ie(uint8 **ie_ptr, + LIBLTE_RRC_CARRIER_FREQ_CDMA2000_STRUCT *carrier_freq); + +/********************************************************************* + IE Name: Carrier Freq GERAN + + Description: Provides an unambiguous carrier frequency description + of a GERAN cell + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +typedef struct{ + LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM band_indicator; + uint16 arfcn; +}LIBLTE_RRC_CARRIER_FREQ_GERAN_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_carrier_freq_geran_ie(LIBLTE_RRC_CARRIER_FREQ_GERAN_STRUCT *carrier_freq, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_carrier_freq_geran_ie(uint8 **ie_ptr, + LIBLTE_RRC_CARRIER_FREQ_GERAN_STRUCT *carrier_freq); + +/********************************************************************* + IE Name: Carrier Freqs GERAN + + Description: Provides one or more GERAN ARFCN values, which + represent a list of GERAN BCCH carrier frequencies + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Carrier Freqs GERAN define defined above +// Enums +// Carrier Freqs GERAN enum defined above +// Structs +// Carrier Freqs GERAN structs defined above +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_carrier_freqs_geran_ie(LIBLTE_RRC_CARRIER_FREQS_GERAN_STRUCT *carrier_freqs, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_carrier_freqs_geran_ie(uint8 **ie_ptr, + LIBLTE_RRC_CARRIER_FREQS_GERAN_STRUCT *carrier_freqs); + +/********************************************************************* + IE Name: CDMA2000 Type + + Description: Describes the type of CDMA2000 network + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// CDMA2000 Type enum defined above +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_cdma2000_type_ie(LIBLTE_RRC_CDMA2000_TYPE_ENUM cdma2000_type, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cdma2000_type_ie(uint8 **ie_ptr, + LIBLTE_RRC_CDMA2000_TYPE_ENUM *cdma2000_type); + +/********************************************************************* + IE Name: Cell Identity + + Description: Unambiguously identifies a cell within a PLMN + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_identity_ie(uint32 cell_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_identity_ie(uint8 **ie_ptr, + uint32 *cell_id); + +/********************************************************************* + IE Name: Cell Index List + + Description: Concerns a list of cell indecies, which may be used + for different purposes + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +// Cell Index List struct defined above +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_index_list_ie(LIBLTE_RRC_CELL_INDEX_LIST_STRUCT *cell_idx_list, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_index_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_CELL_INDEX_LIST_STRUCT *cell_idx_list); + +/********************************************************************* + IE Name: Cell Reselection Priority + + Description: Contains the absolute priority of the concerned + carrier frequency/set of frequencies (GERAN)/ + bandclass (CDMA2000), as used by the cell + reselection procedure + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_reselection_priority_ie(uint8 cell_resel_prio, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_reselection_priority_ie(uint8 **ie_ptr, + uint8 *cell_resel_prio); + +/********************************************************************* + IE Name: CSFB Registration Param 1xRTT + + Description: Indicates whether or not the UE shall perform a + CDMA2000 1xRTT pre-registration if the UE does not + have a valid/current pre-registration + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +typedef enum{ + LIBLTE_RRC_POWER_DOWN_REG_R9_TRUE = 0, + LIBLTE_RRC_POWER_DOWN_REG_R9_N_ITEMS, +}LIBLTE_RRC_POWER_DOWN_REG_R9_ENUM; +static const char liblte_rrc_power_down_reg_r9_text[LIBLTE_RRC_POWER_DOWN_REG_R9_N_ITEMS][20] = {"TRUE"}; +// Structs +typedef struct{ + uint16 sid; + uint16 nid; + uint16 reg_zone; + uint8 reg_period; + uint8 total_zone; + uint8 zone_timer; + bool multiple_sid; + bool multiple_nid; + bool home_reg; + bool foreign_sid_reg; + bool foreign_nid_reg; + bool param_reg; + bool power_up_reg; +}LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_STRUCT; +typedef struct{ + LIBLTE_RRC_POWER_DOWN_REG_R9_ENUM power_down_reg; +}LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_V920_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_csfb_registration_param_1xrtt_ie(LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_STRUCT *csfb_reg_param, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_csfb_registration_param_1xrtt_ie(uint8 **ie_ptr, + LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_STRUCT *csfb_reg_param); +LIBLTE_ERROR_ENUM liblte_rrc_pack_csfb_registration_param_1xrtt_v920_ie(LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_V920_STRUCT *csfb_reg_param, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_csfb_registration_param_1xrtt_v920_ie(uint8 **ie_ptr, + LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_V920_STRUCT *csfb_reg_param); + +/********************************************************************* + IE Name: Cell Global ID EUTRA + + Description: Specifies the Evolved Cell Global Identifier (ECGI), + the globally unique identity of a cell in E-UTRA + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +typedef struct{ + LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id; + uint32 cell_id; +}LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_eutra_ie(LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT *cell_global_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_eutra_ie(uint8 **ie_ptr, + LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT *cell_global_id); + +/********************************************************************* + IE Name: Cell Global ID UTRA + + Description: Specifies the global UTRAN Cell Identifier, the + globally unique identity of a cell in UTRA + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +typedef struct{ + LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id; + uint32 cell_id; +}LIBLTE_RRC_CELL_GLOBAL_ID_UTRA_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_utra_ie(LIBLTE_RRC_CELL_GLOBAL_ID_UTRA_STRUCT *cell_global_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_utra_ie(uint8 **ie_ptr, + LIBLTE_RRC_CELL_GLOBAL_ID_UTRA_STRUCT *cell_global_id); + +/********************************************************************* + IE Name: Cell Global ID GERAN + + Description: Specifies the Cell Global Identity (CGI), the + globally unique identity of a cell in GERAN + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +typedef struct{ + LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id; + uint16 lac; + uint16 cell_id; +}LIBLTE_RRC_CELL_GLOBAL_ID_GERAN_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_geran_ie(LIBLTE_RRC_CELL_GLOBAL_ID_GERAN_STRUCT *cell_global_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_geran_ie(uint8 **ie_ptr, + LIBLTE_RRC_CELL_GLOBAL_ID_GERAN_STRUCT *cell_global_id); + +/********************************************************************* + IE Name: Cell Global ID CDMA2000 + + Description: Specifies the Cell Global Identity (CGI), the + globally unique identity of a cell in CDMA2000 + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +// Structs +typedef struct{ + uint64 onexrtt; + uint32 hrpd[4]; +}LIBLTE_RRC_CELL_GLOBAL_ID_CDMA2000_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_cdma2000_ie(LIBLTE_RRC_CELL_GLOBAL_ID_CDMA2000_STRUCT *cell_global_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_cdma2000_ie(uint8 **ie_ptr, + LIBLTE_RRC_CELL_GLOBAL_ID_CDMA2000_STRUCT *cell_global_id); + +/********************************************************************* + IE Name: CSG Identity + + Description: Identifies a Closed Subscriber Group + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +#define LIBLTE_RRC_CSG_IDENTITY_NOT_PRESENT 0xFFFFFFFF +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_csg_identity_ie(uint32 csg_id, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_csg_identity_ie(uint8 **ie_ptr, + uint32 *csg_id); + +/********************************************************************* + IE Name: Mobility Control Info + + Description: Includes parameters relevant for network controlled + mobility to/within E-UTRA + + Document Reference: 36.331 v10.0.0 Section 6.3.4 +*********************************************************************/ +// Defines +// Enums +typedef enum{ + LIBLTE_RRC_ANTENNA_PORTS_COUNT_AN1 = 0, + LIBLTE_RRC_ANTENNA_PORTS_COUNT_AN2, + LIBLTE_RRC_ANTENNA_PORTS_COUNT_AN4, + LIBLTE_RRC_ANTENNA_PORTS_COUNT_SPARE1, + LIBLTE_RRC_ANTENNA_PORTS_COUNT_N_ITEMS, +}LIBLTE_RRC_ANTENNA_PORTS_COUNT_ENUM; +static const char liblte_rrc_antenna_ports_count_text[LIBLTE_RRC_ANTENNA_PORTS_COUNT_N_ITEMS][20] = {"an1", "an2", "an4", "SPARE"}; +typedef enum{ + LIBLTE_RRC_PHICH_DURATION_NORMAL = 0, + LIBLTE_RRC_PHICH_DURATION_EXTENDED, + LIBLTE_RRC_PHICH_DURATION_N_ITEMS, +}LIBLTE_RRC_PHICH_DURATION_ENUM; +static const char liblte_rrc_phich_duration_text[LIBLTE_RRC_PHICH_DURATION_N_ITEMS][20] = {"Normal", "Extended"}; +typedef enum{ + LIBLTE_RRC_PHICH_RESOURCE_1_6 = 0, + LIBLTE_RRC_PHICH_RESOURCE_1_2, + LIBLTE_RRC_PHICH_RESOURCE_1, + LIBLTE_RRC_PHICH_RESOURCE_2, + LIBLTE_RRC_PHICH_RESOURCE_N_ITEMS, +}LIBLTE_RRC_PHICH_RESOURCE_ENUM; +static const char liblte_rrc_phich_resource_text[LIBLTE_RRC_PHICH_RESOURCE_N_ITEMS][20] = {"1/6", "1/2", "1", "2"}; +static const double liblte_rrc_phich_resource_num[LIBLTE_RRC_PHICH_RESOURCE_N_ITEMS] = {0.16666667, 0.5, 1, 2}; +typedef enum{ + LIBLTE_RRC_DELTA_PUCCH_SHIFT_DS1 = 0, + LIBLTE_RRC_DELTA_PUCCH_SHIFT_DS2, + LIBLTE_RRC_DELTA_PUCCH_SHIFT_DS3, + LIBLTE_RRC_DELTA_PUCCH_SHIFT_SPARE, + LIBLTE_RRC_DELTA_PUCCH_SHIFT_N_ITEMS, +}LIBLTE_RRC_DELTA_PUCCH_SHIFT_ENUM; +static const char liblte_rrc_delta_pucch_shift_text[LIBLTE_RRC_DELTA_PUCCH_SHIFT_N_ITEMS][20] = {"1", "2", "3", "SPARE"}; +static const uint8 liblte_rrc_delta_pucch_shift_num[LIBLTE_RRC_DELTA_PUCCH_SHIFT_N_ITEMS] = {1, 2, 3, 0}; +typedef enum{ + LIBLTE_RRC_HOPPING_MODE_INTER_SUBFRAME = 0, + LIBLTE_RRC_HOPPING_MODE_INTRA_AND_INTER_SUBFRAME, +}LIBLTE_RRC_HOPPING_MODE_ENUM; +typedef enum{ + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N4 = 0, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N8, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N12, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N16, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N20, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N24, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N28, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N32, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N36, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N40, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N44, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N48, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N52, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N56, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N60, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N64, + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N_ITEMS, +}LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_ENUM; +static const char liblte_rrc_number_of_ra_preambles_text[LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N_ITEMS][20] = { "4", "8", "12", "16", + "20", "24", "28", "32", + "36", "40", "44", "48", + "52", "56", "60", "64"}; +static const uint8 liblte_rrc_number_of_ra_preambles_num[LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N_ITEMS] = {4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64}; +typedef enum{ + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N4 = 0, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N8, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N12, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N16, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N20, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N24, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N28, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N32, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N36, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N40, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N44, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N48, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N52, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N56, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N60, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_SPARE, + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N_ITEMS, +}LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_ENUM; +static const char liblte_rrc_size_of_ra_preambles_group_a_text[LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N_ITEMS][20] = { "4", "8", "12", "16", + "20", "24", "28", "32", + "36", "40", "44", "48", + "52", "56", "60", "SPARE"}; +static const uint8 liblte_rrc_size_of_ra_preambles_group_a_num[LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N_ITEMS] = {4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 0}; +typedef enum{ + LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_B56 = 0, + LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_B144, + LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_B208, + LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_B256, + LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_N_ITEMS, +}LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_ENUM; +static const char liblte_rrc_message_size_group_a_text[LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_N_ITEMS][20] = {"56", "144", "208", "256"}; +static const uint16 liblte_rrc_message_size_group_a_num[LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_N_ITEMS] = {56, 144, 208, 256}; +typedef enum{ + LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_MINUS_INFINITY = 0, + LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB0, + LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB5, + LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB8, + LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB10, + LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB12, + LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB15, + LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB18, + LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_N_ITEMS, +}LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_ENUM; +static const char liblte_rrc_message_power_offset_group_b_text[LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_N_ITEMS][20] = {"-INFINITY", "0", "5", "8", + "10", "12", "15", "18"}; +typedef enum{ + LIBLTE_RRC_POWER_RAMPING_STEP_DB0 = 0, + LIBLTE_RRC_POWER_RAMPING_STEP_DB2, + LIBLTE_RRC_POWER_RAMPING_STEP_DB4, + LIBLTE_RRC_POWER_RAMPING_STEP_DB6, + LIBLTE_RRC_POWER_RAMPING_STEP_N_ITEMS, +}LIBLTE_RRC_POWER_RAMPING_STEP_ENUM; +static const char liblte_rrc_power_ramping_step_text[LIBLTE_RRC_POWER_RAMPING_STEP_N_ITEMS][20] = {"0", "2", "4", "6"}; +static const uint8 liblte_rrc_power_ramping_step_num[LIBLTE_RRC_POWER_RAMPING_STEP_N_ITEMS] = {0, 2, 4, 6}; +typedef enum{ + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N120 = 0, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N118, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N116, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N114, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N112, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N110, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N108, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N106, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N104, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N102, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N100, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N98, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N96, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N94, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N92, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N90, + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_N_ITEMS, +}LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_ENUM; +static const char liblte_rrc_preamble_initial_received_target_power_text[LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_N_ITEMS][20] = {"-120", "-118", "-116", "-114", + "-112", "-110", "-108", "-106", + "-104", "-102", "-100", "-98", + "-96", "-94", "-92", "-90"}; +static const int8 liblte_rrc_preamble_initial_received_target_power_num[LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_N_ITEMS] = {-120, -118, -116, -114, -112, -110, -108, -106, + -104, -102, -100, -98, -96, -94, -92, -90}; +typedef enum{ + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N3 = 0, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N4, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N5, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N6, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N7, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N8, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N10, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N20, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N50, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N100, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N200, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_SPARE1, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_SPARE2, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_SPARE3, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_SPARE4, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_SPARE5, + LIBLTE_RRC_PREAMBLE_TRANS_MAX_N_ITEMS, +}LIBLTE_RRC_PREAMBLE_TRANS_MAX_ENUM; +static const char liblte_rrc_preamble_trans_max_text[LIBLTE_RRC_PREAMBLE_TRANS_MAX_N_ITEMS][20] = { "3", "4", "5", "6", + "7", "8", "10", "20", + "50", "100", "200", "SPARE1", + "SPARE2", "SPARE3", "SPARE4", "SPARE5"}; +static const uint8 liblte_rrc_preamble_trans_max_num[LIBLTE_RRC_PREAMBLE_TRANS_MAX_N_ITEMS] = {3, 4, 5, 6, 7, 8, 10, 20, 50, 100, 200, 0, 0, 0, 0, 0}; +typedef enum{ + LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF2 = 0, + LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF3, + LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF4, + LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF5, + LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF6, + LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF7, + LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF8, + LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF10, + LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_N_ITEMS, +}LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_ENUM; +static const char liblte_rrc_ra_response_window_size_text[LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_N_ITEMS][20] = { "2", "3", "4", "5", + "6", "7", "8", "10"}; +static const uint8 liblte_rrc_ra_response_window_size_num[LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_N_ITEMS] = {2, 3, 4, 5, 6, 7, 8, 10}; +typedef enum{ + LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF8 = 0, + LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF16, + LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF24, + LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF32, + LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF40, + LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF48, + LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF56, + LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF64, + LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_N_ITEMS, +}LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_ENUM; +static const char liblte_rrc_mac_contention_resolution_timer_text[LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_N_ITEMS][20] = { "8", "16", "24", "32", + "40", "48", "56", "64"}; +static const uint8 liblte_rrc_mac_contention_resolution_timer_num[LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_N_ITEMS] = {8, 16, 24, 32, 40, 48, 56, 64}; +typedef enum{ + LIBLTE_RRC_UL_CP_LENGTH_1 = 0, + LIBLTE_RRC_UL_CP_LENGTH_2, + LIBLTE_RRC_UL_CP_LENGTH_N_ITEMS, +}LIBLTE_RRC_UL_CP_LENGTH_ENUM; +static const char liblte_rrc_ul_cp_length_text[LIBLTE_RRC_UL_CP_LENGTH_N_ITEMS][20] = {"Normal", "Extended"}; +typedef enum{ + LIBLTE_RRC_SRS_BW_CONFIG_0 = 0, + LIBLTE_RRC_SRS_BW_CONFIG_1, + LIBLTE_RRC_SRS_BW_CONFIG_2, + LIBLTE_RRC_SRS_BW_CONFIG_3, + LIBLTE_RRC_SRS_BW_CONFIG_4, + LIBLTE_RRC_SRS_BW_CONFIG_5, + LIBLTE_RRC_SRS_BW_CONFIG_6, + LIBLTE_RRC_SRS_BW_CONFIG_7, + LIBLTE_RRC_SRS_BW_CONFIG_N_ITEMS, +}LIBLTE_RRC_SRS_BW_CONFIG_ENUM; +static const char liblte_rrc_srs_bw_config_text[LIBLTE_RRC_SRS_BW_CONFIG_N_ITEMS][20] = {"0", "1", "2", "3", + "4", "5", "6", "7"}; +static const uint8 liblte_rrc_srs_bw_config_num[LIBLTE_RRC_SRS_BW_CONFIG_N_ITEMS] = {0, 1, 2, 3, 4, 5, 6, 7}; +typedef enum{ + LIBLTE_RRC_SRS_SUBFR_CONFIG_0 = 0, + LIBLTE_RRC_SRS_SUBFR_CONFIG_1, + LIBLTE_RRC_SRS_SUBFR_CONFIG_2, + LIBLTE_RRC_SRS_SUBFR_CONFIG_3, + LIBLTE_RRC_SRS_SUBFR_CONFIG_4, + LIBLTE_RRC_SRS_SUBFR_CONFIG_5, + LIBLTE_RRC_SRS_SUBFR_CONFIG_6, + LIBLTE_RRC_SRS_SUBFR_CONFIG_7, + LIBLTE_RRC_SRS_SUBFR_CONFIG_8, + LIBLTE_RRC_SRS_SUBFR_CONFIG_9, + LIBLTE_RRC_SRS_SUBFR_CONFIG_10, + LIBLTE_RRC_SRS_SUBFR_CONFIG_11, + LIBLTE_RRC_SRS_SUBFR_CONFIG_12, + LIBLTE_RRC_SRS_SUBFR_CONFIG_13, + LIBLTE_RRC_SRS_SUBFR_CONFIG_14, + LIBLTE_RRC_SRS_SUBFR_CONFIG_15, + LIBLTE_RRC_SRS_SUBFR_CONFIG_N_ITEMS, +}LIBLTE_RRC_SRS_SUBFR_CONFIG_ENUM; +static const char liblte_rrc_srs_subfr_config_text[LIBLTE_RRC_SRS_SUBFR_CONFIG_N_ITEMS][20] = { "0", "1", "2", "3", + "4", "5", "6", "7", + "8", "9", "10", "11", + "12", "13", "14", "15"}; +static const uint8 liblte_rrc_srs_subfr_config_num[LIBLTE_RRC_SRS_SUBFR_CONFIG_N_ITEMS] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; +typedef enum{ + LIBLTE_RRC_SUBFRAME_ASSIGNMENT_0 = 0, + LIBLTE_RRC_SUBFRAME_ASSIGNMENT_1, + LIBLTE_RRC_SUBFRAME_ASSIGNMENT_2, + LIBLTE_RRC_SUBFRAME_ASSIGNMENT_3, + LIBLTE_RRC_SUBFRAME_ASSIGNMENT_4, + LIBLTE_RRC_SUBFRAME_ASSIGNMENT_5, + LIBLTE_RRC_SUBFRAME_ASSIGNMENT_6, + LIBLTE_RRC_SUBFRAME_ASSIGNMENT_SPARE, + LIBLTE_RRC_SUBFRAME_ASSIGNMENT_N_ITEMS, +}LIBLTE_RRC_SUBFRAME_ASSIGNMENT_ENUM; +static const char liblte_rrc_subframe_assignment_text[LIBLTE_RRC_SUBFRAME_ASSIGNMENT_N_ITEMS][20] = { "0", "1", "2", "3", + "4", "5", "6", "SPARE"}; +static const uint8 liblte_rrc_subframe_assignment_num[LIBLTE_RRC_SUBFRAME_ASSIGNMENT_N_ITEMS] = {0, 1, 2, 3, 4, 5, 6, 0}; +typedef enum{ + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_0 = 0, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_1, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_2, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_3, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_4, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_5, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_6, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_7, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_8, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_SPARE1, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_SPARE2, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_SPARE3, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_SPARE4, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_SPARE5, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_SPARE6, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_SPARE7, + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_N_ITEMS, +}LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_ENUM; +static const char liblte_rrc_special_subframe_patterns_text[LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_N_ITEMS][20] = { "0", "1", "2", "3", + "4", "5", "6", "7", + "8", "SPARE1", "SPARE2", "SPARE3", + "SPARE4", "SPARE5", "SPARE6", "SPARE7"}; +static const uint8 liblte_rrc_special_subframe_patterns_num[LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_N_ITEMS] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0}; +typedef enum{ + LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_0 = 0, + LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_04, + LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_05, + LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_06, + LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_07, + LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_08, + LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_09, + LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_1, + LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_N_ITEMS, +}LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_ENUM; +static const char liblte_rrc_ul_power_control_alpha_text[LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_N_ITEMS][20] = {"0.0", "0.4", "0.5", "0.6", + "0.7", "0.8", "0.9", "1.0"}; +static const double liblte_rrc_ul_power_control_alpha_num[LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_N_ITEMS] = {0.0, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; +typedef enum{ + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_NEG_2 = 0, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_0, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_2, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_SPARE, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_N_ITEMS, +}LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_ENUM; +static const char liblte_rrc_delta_f_pucch_format_1_text[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_N_ITEMS][20] = {"-2", "0", "2", "SPARE"}; +static const int8 liblte_rrc_delta_f_pucch_format_1_num[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_N_ITEMS] = {-2, 0, 2, 0}; +typedef enum{ + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_1 = 0, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_3, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_5, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_SPARE, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_N_ITEMS, +}LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_ENUM; +static const char liblte_rrc_delta_f_pucch_format_1b_text[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_N_ITEMS][20] = {"1", "3", "5", "SPARE"}; +static const uint8 liblte_rrc_delta_f_pucch_format_1b_num[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_N_ITEMS] = {1, 3, 5, 0}; +typedef enum{ + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_NEG_2 = 0, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_0, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_1, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_2, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_N_ITEMS, +}LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_ENUM; +static const char liblte_rrc_delta_f_pucch_format_2_text[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_N_ITEMS][20] = {"-2", "0", "1", "2"}; +static const int8 liblte_rrc_delta_f_pucch_format_2_num[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_N_ITEMS] = {-2, 0, 1, 2}; +typedef enum{ + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_NEG_2 = 0, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_0, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_2, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_SPARE, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_N_ITEMS, +}LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_ENUM; +static const char liblte_rrc_delta_f_pucch_format_2a_text[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_N_ITEMS][20] = {"-2", "0", "2", "SPARE"}; +static const int8 liblte_rrc_delta_f_pucch_format_2a_num[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_N_ITEMS] = {-2, 0, 2, 0}; +typedef enum{ + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_NEG_2 = 0, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_0, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_2, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_SPARE, + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_N_ITEMS, +}LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_ENUM; +static const char liblte_rrc_delta_f_pucch_format_2b_text[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_N_ITEMS][20] = {"-2", "0", "2", "SPARE"}; +static const int8 liblte_rrc_delta_f_pucch_format_2b_num[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_N_ITEMS] = {-2, 0, 2, 0}; +typedef enum{ + LIBLTE_RRC_BANDWIDTH_N6 = 0, + LIBLTE_RRC_BANDWIDTH_N15, + LIBLTE_RRC_BANDWIDTH_N25, + LIBLTE_RRC_BANDWIDTH_N50, + LIBLTE_RRC_BANDWIDTH_N75, + LIBLTE_RRC_BANDWIDTH_N100, + LIBLTE_RRC_BANDWIDTH_SPARE10, + LIBLTE_RRC_BANDWIDTH_SPARE9, + LIBLTE_RRC_BANDWIDTH_SPARE8, + LIBLTE_RRC_BANDWIDTH_SPARE7, + LIBLTE_RRC_BANDWIDTH_SPARE6, + LIBLTE_RRC_BANDWIDTH_SPARE5, + LIBLTE_RRC_BANDWIDTH_SPARE4, + LIBLTE_RRC_BANDWIDTH_SPARE3, + LIBLTE_RRC_BANDWIDTH_SPARE2, + LIBLTE_RRC_BANDWIDTH_SPARE1, + LIBLTE_RRC_BANDWIDTH_N_ITEMS, +}LIBLTE_RRC_BANDWIDTH_ENUM; +static const char liblte_rrc_bandwidth_text[LIBLTE_RRC_BANDWIDTH_N_ITEMS][20] = { "1.4", "3", "5", "10", + "15", "20", "SPARE", "SPARE", + "SPARE", "SPARE", "SPARE", "SPARE", + "SPARE", "SPARE", "SPARE", "SPARE"}; +typedef enum{ + LIBLTE_RRC_T304_MS50 = 0, + LIBLTE_RRC_T304_MS100, + LIBLTE_RRC_T304_MS150, + LIBLTE_RRC_T304_MS200, + LIBLTE_RRC_T304_MS500, + LIBLTE_RRC_T304_MS1000, + LIBLTE_RRC_T304_MS2000, + LIBLTE_RRC_T304_SPARE, + LIBLTE_RRC_T304_N_ITEMS, +}LIBLTE_RRC_T304_ENUM; +static const char liblte_rrc_t304_text[LIBLTE_RRC_T304_N_ITEMS][20] = { "50", "100", "150", "200", + "500", "1000", "2000", "SPARE"}; +// Structs +typedef struct{ + uint8 p_b; + int8 rs_power; +}LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT; +typedef struct{ + LIBLTE_RRC_PHICH_DURATION_ENUM dur; + LIBLTE_RRC_PHICH_RESOURCE_ENUM res; +}LIBLTE_RRC_PHICH_CONFIG_STRUCT; +typedef struct{ + uint8 prach_config_index; + uint8 zero_correlation_zone_config; + uint8 prach_freq_offset; + bool high_speed_flag; +}LIBLTE_RRC_PRACH_CONFIG_INFO_STRUCT; +typedef struct{ + LIBLTE_RRC_PRACH_CONFIG_INFO_STRUCT prach_cnfg_info; + uint16 root_sequence_index; +}LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT; +typedef struct{ + LIBLTE_RRC_PRACH_CONFIG_INFO_STRUCT prach_cnfg_info; + uint16 root_sequence_index; + bool prach_cnfg_info_present; +}LIBLTE_RRC_PRACH_CONFIG_STRUCT; +typedef struct{ + LIBLTE_RRC_DELTA_PUCCH_SHIFT_ENUM delta_pucch_shift; + uint16 n1_pucch_an; + uint8 n_rb_cqi; + uint8 n_cs_an; +}LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT; +typedef struct{ + uint8 group_assignment_pusch; + uint8 cyclic_shift; + bool group_hopping_enabled; + bool sequence_hopping_enabled; +}LIBLTE_RRC_UL_RS_PUSCH_STRUCT; +typedef struct{ + LIBLTE_RRC_UL_RS_PUSCH_STRUCT ul_rs; + LIBLTE_RRC_HOPPING_MODE_ENUM hopping_mode; + uint8 n_sb; + uint8 pusch_hopping_offset; + bool enable_64_qam; +}LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT; +typedef struct{ + LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_ENUM size_of_ra; + LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_ENUM msg_size; + LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_ENUM msg_pwr_offset_group_b; + bool present; +}LIBLTE_RRC_PREAMBLES_GROUP_A_STRUCT; +typedef struct{ + LIBLTE_RRC_PREAMBLES_GROUP_A_STRUCT preambles_group_a_cnfg; + LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_ENUM num_ra_preambles; + LIBLTE_RRC_POWER_RAMPING_STEP_ENUM pwr_ramping_step; + LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_ENUM preamble_init_rx_target_pwr; + LIBLTE_RRC_PREAMBLE_TRANS_MAX_ENUM preamble_trans_max; + LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_ENUM ra_resp_win_size; + LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_ENUM mac_con_res_timer; + uint8 max_harq_msg3_tx; +}LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT; +typedef struct{ + uint8 preamble_index; + uint8 prach_mask_index; +}LIBLTE_RRC_RACH_CONFIG_DEDICATED_STRUCT; +typedef struct{ + LIBLTE_RRC_SRS_BW_CONFIG_ENUM bw_cnfg; + LIBLTE_RRC_SRS_SUBFR_CONFIG_ENUM subfr_cnfg; + bool ack_nack_simul_tx; + bool max_up_pts; + bool max_up_pts_present; + bool present; +}LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT; typedef struct{ - LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id; - uint32 cell_id; -}LIBLTE_RRC_CELL_GLOBAL_ID_UTRA_STRUCT; -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_utra_ie(LIBLTE_RRC_CELL_GLOBAL_ID_UTRA_STRUCT *cell_global_id, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_utra_ie(uint8 **ie_ptr, - LIBLTE_RRC_CELL_GLOBAL_ID_UTRA_STRUCT *cell_global_id); - -/********************************************************************* - IE Name: Cell Global ID GERAN - - Description: Specifies the Cell Global Identity (CGI), the - globally unique identity of a cell in GERAN - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -// Enums -// Structs + LIBLTE_RRC_SUBFRAME_ASSIGNMENT_ENUM sf_assignment; + LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_ENUM special_sf_patterns; +}LIBLTE_RRC_TDD_CONFIG_STRUCT; typedef struct{ - LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id; - uint16 lac; - uint16 cell_id; -}LIBLTE_RRC_CELL_GLOBAL_ID_GERAN_STRUCT; -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_geran_ie(LIBLTE_RRC_CELL_GLOBAL_ID_GERAN_STRUCT *cell_global_id, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_geran_ie(uint8 **ie_ptr, - LIBLTE_RRC_CELL_GLOBAL_ID_GERAN_STRUCT *cell_global_id); - -/********************************************************************* - IE Name: Cell Global ID CDMA2000 - - Description: Specifies the Cell Global Identity (CGI), the - globally unique identity of a cell in CDMA2000 - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -// Enums -// Structs + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_ENUM format_1; + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_ENUM format_1b; + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_ENUM format_2; + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_ENUM format_2a; + LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_ENUM format_2b; +}LIBLTE_RRC_DELTA_FLIST_PUCCH_STRUCT; typedef struct{ - uint64 onexrtt; - uint32 hrpd[4]; -}LIBLTE_RRC_CELL_GLOBAL_ID_CDMA2000_STRUCT; -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_cdma2000_ie(LIBLTE_RRC_CELL_GLOBAL_ID_CDMA2000_STRUCT *cell_global_id, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_cdma2000_ie(uint8 **ie_ptr, - LIBLTE_RRC_CELL_GLOBAL_ID_CDMA2000_STRUCT *cell_global_id); - -/********************************************************************* - IE Name: CSG Identity - - Description: Identifies a Closed Subscriber Group - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -#define LIBLTE_RRC_CSG_IDENTITY_NOT_PRESENT 0xFFFFFFFF -// Enums -// Structs -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_csg_identity_ie(uint32 csg_id, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_csg_identity_ie(uint8 **ie_ptr, - uint32 *csg_id); - -/********************************************************************* - IE Name: Mobility Control Info - - Description: Includes parameters relevant for network controlled - mobility to/within E-UTRA - - Document Reference: 36.331 v10.0.0 Section 6.3.4 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -// FIXME + LIBLTE_RRC_DELTA_FLIST_PUCCH_STRUCT delta_flist_pucch; + LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_ENUM alpha; + int8 p0_nominal_pusch; + int8 p0_nominal_pucch; + int8 delta_preamble_msg3; +}LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT; +typedef struct{ + LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT rach_cnfg; + LIBLTE_RRC_PRACH_CONFIG_STRUCT prach_cnfg; + LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT pdsch_cnfg; + LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT pusch_cnfg; + LIBLTE_RRC_PHICH_CONFIG_STRUCT phich_cnfg; + LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT pucch_cnfg; + LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT srs_ul_cnfg; + LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT ul_pwr_ctrl; + LIBLTE_RRC_TDD_CONFIG_STRUCT tdd_cnfg; + LIBLTE_RRC_ANTENNA_PORTS_COUNT_ENUM ant_info; + LIBLTE_RRC_UL_CP_LENGTH_ENUM ul_cp_length; + int8 p_max; + bool rach_cnfg_present; + bool pdsch_cnfg_present; + bool phich_cnfg_present; + bool pucch_cnfg_present; + bool srs_ul_cnfg_present; + bool ul_pwr_ctrl_present; + bool ant_info_present; + bool p_max_present; + bool tdd_cnfg_present; +}LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT; +typedef struct{ + uint16 dl_carrier_freq; + uint16 ul_carrier_freq; + bool ul_carrier_freq_present; +}LIBLTE_RRC_CARRIER_FREQ_EUTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_BANDWIDTH_ENUM dl_bw; + LIBLTE_RRC_BANDWIDTH_ENUM ul_bw; + bool ul_bw_present; +}LIBLTE_RRC_CARRIER_BANDWIDTH_EUTRA_STRUCT; +typedef struct{ + LIBLTE_RRC_CARRIER_FREQ_EUTRA_STRUCT carrier_freq_eutra; + LIBLTE_RRC_CARRIER_BANDWIDTH_EUTRA_STRUCT carrier_bw_eutra; + LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT rr_cnfg_common; + LIBLTE_RRC_RACH_CONFIG_DEDICATED_STRUCT rach_cnfg_ded; + LIBLTE_RRC_T304_ENUM t304; + uint16 target_pci; + uint16 new_ue_id; + uint8 add_spect_em; + bool carrier_freq_eutra_present; + bool carrier_bw_eutra_present; + bool add_spect_em_present; + bool rach_cnfg_ded_present; +}LIBLTE_RRC_MOBILITY_CONTROL_INFO_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_mobility_control_info_ie(LIBLTE_RRC_MOBILITY_CONTROL_INFO_STRUCT *mob_ctrl_info, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_mobility_control_info_ie(uint8 **ie_ptr, + LIBLTE_RRC_MOBILITY_CONTROL_INFO_STRUCT *mob_ctrl_info); /********************************************************************* IE Name: Mobility Parameters CDMA2000 (1xRTT) @@ -1464,41 +2746,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_csg_identity_ie(uint8 **ie_ptr, *********************************************************************/ // Defines // Enums -typedef enum{ - LIBLTE_RRC_T_EVALUATION_S30 = 0, - LIBLTE_RRC_T_EVALUATION_S60, - LIBLTE_RRC_T_EVALUATION_S120, - LIBLTE_RRC_T_EVALUATION_S180, - LIBLTE_RRC_T_EVALUATION_S240, - LIBLTE_RRC_T_EVALUATION_SPARE3, - LIBLTE_RRC_T_EVALUATION_SPARE2, - LIBLTE_RRC_T_EVALUATION_SPARE1, - LIBLTE_RRC_T_EVALUATION_N_ITEMS, -}LIBLTE_RRC_T_EVALUATION_ENUM; -static const char liblte_rrc_t_evaluation_text[LIBLTE_RRC_T_EVALUATION_N_ITEMS][20] = { "30", "60", "120", "180", - "240", "SPARE", "SPARE", "SPARE"}; -static const int16 liblte_rrc_t_evaluation_num[LIBLTE_RRC_T_EVALUATION_N_ITEMS] = {30, 60, 120, 180, 240, -1, -1, -1}; -typedef enum{ - LIBLTE_RRC_T_HYST_NORMAL_S30 = 0, - LIBLTE_RRC_T_HYST_NORMAL_S60, - LIBLTE_RRC_T_HYST_NORMAL_S120, - LIBLTE_RRC_T_HYST_NORMAL_S180, - LIBLTE_RRC_T_HYST_NORMAL_S240, - LIBLTE_RRC_T_HYST_NORMAL_SPARE3, - LIBLTE_RRC_T_HYST_NORMAL_SPARE2, - LIBLTE_RRC_T_HYST_NORMAL_SPARE1, - LIBLTE_RRC_T_HYST_NORMAL_N_ITEMS, -}LIBLTE_RRC_T_HYST_NORMAL_ENUM; -static const char liblte_rrc_t_hyst_normal_text[LIBLTE_RRC_T_HYST_NORMAL_N_ITEMS][20] = { "30", "60", "120", "180", - "240", "SPARE", "SPARE", "SPARE"}; -static const int16 liblte_rrc_t_hyst_normal_num[LIBLTE_RRC_T_HYST_NORMAL_N_ITEMS] = {30, 60, 120, 180, 240, -1, -1, -1}; +// Mobility State Parameters enums defined above // Structs -typedef struct{ - LIBLTE_RRC_T_EVALUATION_ENUM t_eval; - LIBLTE_RRC_T_HYST_NORMAL_ENUM t_hyst_normal; - uint8 n_cell_change_medium; - uint8 n_cell_change_high; -}LIBLTE_RRC_MOBILITY_STATE_PARAMETERS_STRUCT; +// Mobility State Parameters struct defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_mobility_state_parameters_ie(LIBLTE_RRC_MOBILITY_STATE_PARAMETERS_STRUCT *mobility_state_params, uint8 **ie_ptr); @@ -1531,37 +2781,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_ie(uint8 **ie_ptr, *********************************************************************/ // Defines // Enums -typedef enum{ - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N4 = 0, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N8, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N12, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N16, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N24, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N32, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N48, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N64, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N84, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N96, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N128, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N168, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N252, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N504, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_SPARE2, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_SPARE1, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N1, - LIBLTE_RRC_PHYS_CELL_ID_RANGE_N_ITEMS, -}LIBLTE_RRC_PHYS_CELL_ID_RANGE_ENUM; -static const char liblte_rrc_phys_cell_id_range_text[LIBLTE_RRC_PHYS_CELL_ID_RANGE_N_ITEMS][20] = { "4", "8", "12", "16", - "24", "32", "48", "64", - "84", "96", "128", "168", - "252", "504", "SPARE", "SPARE", - "1"}; -static const int16 liblte_rrc_phys_cell_id_range_num[LIBLTE_RRC_PHYS_CELL_ID_RANGE_N_ITEMS] = {4, 8, 12, 16, 24, 32, 48, 64, 84, 96, 128, 168, 252, 504, -1, -1, 1}; +// Phys Cell ID Range enum defined above // Structs -typedef struct{ - LIBLTE_RRC_PHYS_CELL_ID_RANGE_ENUM range; - uint16 start; -}LIBLTE_RRC_PHYS_CELL_ID_RANGE_STRUCT; +// Phys Cell ID Range struct defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_range_ie(LIBLTE_RRC_PHYS_CELL_ID_RANGE_STRUCT *phys_cell_id_range, uint8 **ie_ptr); @@ -1576,10 +2798,23 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_range_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.4 *********************************************************************/ // Defines +#define LIBLTE_RRC_MAX_PHYS_CELL_ID_RANGE 4 // Enums // Structs +typedef struct{ + uint16 start; + uint16 range; + bool range_present; +}LIBLTE_RRC_PHYS_CELL_ID_RANGE_UTRA_FDD_STRUCT; +typedef struct{ + LIBLTE_RRC_PHYS_CELL_ID_RANGE_UTRA_FDD_STRUCT phys_cell_id_range_list[LIBLTE_RRC_MAX_PHYS_CELL_ID_RANGE]; + uint8 phys_cell_id_range_list_size; +}LIBLTE_RRC_PHYS_CELL_ID_RANGE_UTRA_FDD_LIST_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_range_utra_fdd_list_ie(LIBLTE_RRC_PHYS_CELL_ID_RANGE_UTRA_FDD_LIST_STRUCT *list, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_range_utra_fdd_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_UTRA_FDD_LIST_STRUCT *list); /********************************************************************* IE Name: Phys Cell ID CDMA2000 @@ -1609,10 +2844,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_cdma2000_ie(uint8 **ie_ptr, // Defines // Enums // Structs -typedef struct{ - uint8 ncc; - uint8 bcc; -}LIBLTE_RRC_PHYS_CELL_ID_GERAN_STRUCT; +// Phys Cell ID GERAN struct defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_geran_ie(LIBLTE_RRC_PHYS_CELL_ID_GERAN_STRUCT *phys_cell_id, uint8 **ie_ptr); @@ -1679,13 +2911,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_plmn_identity_ie(uint8 // Defines // Enums // Structs -typedef struct{ - uint8 pre_reg_zone_id; - uint8 secondary_pre_reg_zone_id_list[2]; - uint8 secondary_pre_reg_zone_id_list_size; - bool pre_reg_allowed; - bool pre_reg_zone_id_present; -}LIBLTE_RRC_PRE_REGISTRATION_INFO_HRPD_STRUCT; +// Pre Registration Info HRPD struct defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_pre_registration_info_hrpd_ie(LIBLTE_RRC_PRE_REGISTRATION_INFO_HRPD_STRUCT *pre_reg_info_hrpd, uint8 **ie_ptr); @@ -1739,50 +2965,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_q_rx_lev_min_ie(uint8 **ie_ptr, *********************************************************************/ // Defines // Enums -typedef enum{ - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N24 = 0, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N22, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N20, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N18, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N16, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N14, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N12, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N10, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N8, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N6, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N5, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N4, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N3, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N2, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_N1, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_0, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_1, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_2, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_3, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_4, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_5, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_6, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_8, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_10, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_12, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_14, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_16, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_18, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_20, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_22, - LIBLTE_RRC_Q_OFFSET_RANGE_DB_24, - LIBLTE_RRC_Q_OFFSET_RANGE_N_ITEMS, -}LIBLTE_RRC_Q_OFFSET_RANGE_ENUM; -static const char liblte_rrc_q_offset_range_text[LIBLTE_RRC_Q_OFFSET_RANGE_N_ITEMS][20] = {"-24", "-22", "-20", "-18", - "-16", "-14", "-12", "-10", - "-8", "-6", "-5", "-4", - "-3", "-2", "-1", "0", - "1", "2", "3", "4", - "5", "6", "8", "10", - "12", "14", "16", "18", - "20", "22", "24"}; -static const int8 liblte_rrc_q_offset_range_num[LIBLTE_RRC_Q_OFFSET_RANGE_N_ITEMS] = {-24, -22, -20, -18, -16, -14, -12, -10, -8, -6, -5, -4, -3, -2, -1, 0, - 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24}; +// Q Offset Range enum defined above // Structs // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_q_offset_range_ie(LIBLTE_RRC_Q_OFFSET_RANGE_ENUM q_offset_range, @@ -1886,29 +3069,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_serv_cell_index_ie(uint8 **ie_ptr, *********************************************************************/ // Defines // Enums -typedef enum{ - LIBLTE_RRC_SSSF_MEDIUM_0DOT25 = 0, - LIBLTE_RRC_SSSF_MEDIUM_0DOT5, - LIBLTE_RRC_SSSF_MEDIUM_0DOT75, - LIBLTE_RRC_SSSF_MEDIUM_1DOT0, - LIBLTE_RRC_SSSF_MEDIUM_N_ITEMS, -}LIBLTE_RRC_SSSF_MEDIUM_ENUM; -static const char liblte_rrc_sssf_medium_text[LIBLTE_RRC_SSSF_MEDIUM_N_ITEMS][20] = {"0.25", "0.5", "0.75", "1.0"}; -static const double liblte_rrc_sssf_medium_num[LIBLTE_RRC_SSSF_MEDIUM_N_ITEMS] = {0.25, 0.5, 0.75, 1.0}; -typedef enum{ - LIBLTE_RRC_SSSF_HIGH_0DOT25 = 0, - LIBLTE_RRC_SSSF_HIGH_0DOT5, - LIBLTE_RRC_SSSF_HIGH_0DOT75, - LIBLTE_RRC_SSSF_HIGH_1DOT0, - LIBLTE_RRC_SSSF_HIGH_N_ITEMS, -}LIBLTE_RRC_SSSF_HIGH_ENUM; -static const char liblte_rrc_sssf_high_text[LIBLTE_RRC_SSSF_HIGH_N_ITEMS][20] = {"0.25", "0.5", "0.75", "1.0"}; -static const double liblte_rrc_sssf_high_num[LIBLTE_RRC_SSSF_HIGH_N_ITEMS] = {0.25, 0.5, 0.75, 1.0}; +// Speed State Scale Factors enums defined above // Structs -typedef struct{ - LIBLTE_RRC_SSSF_MEDIUM_ENUM sf_medium; - LIBLTE_RRC_SSSF_HIGH_ENUM sf_high; -}LIBLTE_RRC_SPEED_STATE_SCALE_FACTORS_STRUCT; +// Speed State Scale Factors struct defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_speed_state_scale_factors_ie(LIBLTE_RRC_SPEED_STATE_SCALE_FACTORS_STRUCT *speed_state_scale_factors, uint8 **ie_ptr); @@ -1923,10 +3086,22 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_speed_state_scale_factors_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.4 *********************************************************************/ // Defines +#define LIBLTE_RRC_MAX_GERAN_SI 10 // Enums // Structs +typedef struct{ + uint8 system_info[23]; + uint8 system_info_size; +}LIBLTE_RRC_SYSTEM_INFO_GERAN_STRUCT; +typedef struct{ + LIBLTE_RRC_SYSTEM_INFO_GERAN_STRUCT system_info_list_geran[LIBLTE_RRC_MAX_GERAN_SI]; + uint8 system_info_list_geran_size; +}LIBLTE_RRC_SYSTEM_INFO_LIST_GERAN_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_system_info_list_geran_ie(LIBLTE_RRC_SYSTEM_INFO_LIST_GERAN_STRUCT *list, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_system_info_list_geran_ie(uint8 **ie_ptr, + LIBLTE_RRC_SYSTEM_INFO_LIST_GERAN_STRUCT *list); /********************************************************************* IE Name: System Time Info CDMA2000 @@ -2073,16 +3248,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_short_mac_i_ie(uint8 **ie_ptr, Document Reference: 36.331 v10.0.0 Section 6.3.2 *********************************************************************/ -// Defines -// Enums -typedef enum{ - LIBLTE_RRC_ANTENNA_PORTS_COUNT_AN1 = 0, - LIBLTE_RRC_ANTENNA_PORTS_COUNT_AN2, - LIBLTE_RRC_ANTENNA_PORTS_COUNT_AN4, - LIBLTE_RRC_ANTENNA_PORTS_COUNT_SPARE1, - LIBLTE_RRC_ANTENNA_PORTS_COUNT_N_ITEMS, -}LIBLTE_RRC_ANTENNA_PORTS_COUNT_ENUM; -static const char liblte_rrc_antenna_ports_count_text[LIBLTE_RRC_ANTENNA_PORTS_COUNT_N_ITEMS][20] = {"an1", "an2", "an4", "SPARE"}; +// Defines +// Enums +// Antenna Ports Count enum defined above typedef enum{ LIBLTE_RRC_TRANSMISSION_MODE_1 = 0, LIBLTE_RRC_TRANSMISSION_MODE_2, @@ -2197,9 +3365,24 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_cqi_report_config_ie(uint8 *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_RRC_SCHEDULING_CONFIG_INFO_CHOICE_OWN = 0, + LIBLTE_RRC_SCHEDULING_CONFIG_INFO_CHOICE_OTHER, + LIBLTE_RRC_SCHEDULING_CONFIG_INFO_CHOICE_N_ITEMS, +}LIBLTE_RRC_SCHEDULING_CONFIG_INFO_CHOICE_ENUM; +static const char liblte_rrc_scheduling_config_info_choice_text[LIBLTE_RRC_SCHEDULING_CONFIG_INFO_CHOICE_N_ITEMS][20] = {"own", "other"}; // Structs +typedef struct{ + LIBLTE_RRC_SCHEDULING_CONFIG_INFO_CHOICE_ENUM sched_cnfg_info_choice; + uint8 other_serv_cell_idx; + uint8 other_pdsch_start; + bool own_cif_presence; +}LIBLTE_RRC_CROSS_CARRIER_SCHEDULING_CONFIG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_cross_carrier_scheduling_config_ie(LIBLTE_RRC_CROSS_CARRIER_SCHEDULING_CONFIG_STRUCT *cross_carrier_sched_cnfg, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cross_carrier_scheduling_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_CROSS_CARRIER_SCHEDULING_CONFIG_STRUCT *cross_carrier_sched_cnfg); /********************************************************************* IE Name: CSI RS Config @@ -2211,9 +3394,35 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_cqi_report_config_ie(uint8 *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_RRC_CSI_RS_CONFIG_CHOICE_RELEASE = 0, + LIBLTE_RRC_CSI_RS_CONFIG_CHOICE_SETUP, + LIBLTE_RRC_CSI_RS_CONFIG_CHOICE_N_ITEMS, +}LIBLTE_RRC_CSI_RS_CONFIG_CHOICE_ENUM; +static const char liblte_rrc_csi_rs_config_choice_text[LIBLTE_RRC_CSI_RS_CONFIG_CHOICE_N_ITEMS][20] = {"release", "setup"}; +typedef enum{ + LIBLTE_RRC_CSI_RS_PORTS_AN1 = 0, + LIBLTE_RRC_CSI_RS_PORTS_AN2, + LIBLTE_RRC_CSI_RS_PORTS_AN4, + LIBLTE_RRC_CSI_RS_PORTS_AN8, + LIBLTE_RRC_CSI_RS_PORTS_N_ITEMS, +}LIBLTE_RRC_CSI_RS_PORTS_ENUM; +static const char liblte_rrc_csi_rs_ports_text[LIBLTE_RRC_CSI_RS_PORTS_N_ITEMS][20] = {"an1", "an2", "an4", "an8"}; +static const uint8 liblte_rrc_csi_rs_ports_num[LIBLTE_RRC_CSI_RS_PORTS_N_ITEMS] = {1, 2, 4, 8}; // Structs +typedef struct{ + LIBLTE_RRC_CSI_RS_CONFIG_CHOICE_ENUM choice; + LIBLTE_RRC_CSI_RS_PORTS_ENUM csi_rs_ports; + uint16 rho_c; + uint16 csi_rs_w_zero_tx_power; + uint8 location_idx; + uint8 csi_rs_subfr_cnfg; +}LIBLTE_RRC_CSI_RS_CONFIG_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_csi_rs_config_ie(LIBLTE_RRC_CSI_RS_CONFIG_STRUCT *csi_rs_cnfg, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_csi_rs_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_CSI_RS_CONFIG_STRUCT *csi_rs_cnfg); /********************************************************************* IE Name: DRB Identity @@ -2619,10 +3828,6 @@ typedef struct{ LIBLTE_RRC_DISCARD_TIMER_ENUM discard_timer; LIBLTE_RRC_PDCP_SN_SIZE_ENUM rlc_um_pdcp_sn_size; uint32 hdr_compression_max_cid; - bool discard_timer_present; - bool rlc_am_status_report_required_present; - bool rlc_am_status_report_required; - bool rlc_um_pdcp_sn_size_present; bool hdr_compression_rohc; bool hdr_compression_profile_0001; bool hdr_compression_profile_0002; @@ -2633,6 +3838,10 @@ typedef struct{ bool hdr_compression_profile_0102; bool hdr_compression_profile_0103; bool hdr_compression_profile_0104; + bool discard_timer_present; + bool rlc_am_status_report_required_present; + bool rlc_am_status_report_required; + bool rlc_um_pdcp_sn_size_present; }LIBLTE_RRC_PDCP_CONFIG_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_pdcp_config_ie(LIBLTE_RRC_PDCP_CONFIG_STRUCT *pdcp_cnfg, @@ -2665,10 +3874,7 @@ static const char liblte_rrc_pdsch_config_p_a_text[LIBLTE_RRC_PDSCH_CONFIG_P_A_N "0", "1", "2", "3"}; static const double liblte_rrc_pdsch_config_p_a_num[LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS] = {-6, -4.77, -3, -1.77, 0, 1, 2, 3}; // Structs -typedef struct{ - uint8 p_b; - int8 rs_power; -}LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT; +// PDSCH Config Common struct defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_pdsch_config_common_ie(LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT *pdsch_config, uint8 **ie_ptr); @@ -2688,26 +3894,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_pdsch_config_dedicated_ie(uint8 *********************************************************************/ // Defines // Enums -typedef enum{ - LIBLTE_RRC_PHICH_DURATION_NORMAL = 0, - LIBLTE_RRC_PHICH_DURATION_EXTENDED, - LIBLTE_RRC_PHICH_DURATION_N_ITEMS, -}LIBLTE_RRC_PHICH_DURATION_ENUM; -static const char liblte_rrc_phich_duration_text[LIBLTE_RRC_PHICH_DURATION_N_ITEMS][20] = {"Normal", "Extended"}; -typedef enum{ - LIBLTE_RRC_PHICH_RESOURCE_1_6 = 0, - LIBLTE_RRC_PHICH_RESOURCE_1_2, - LIBLTE_RRC_PHICH_RESOURCE_1, - LIBLTE_RRC_PHICH_RESOURCE_2, - LIBLTE_RRC_PHICH_RESOURCE_N_ITEMS, -}LIBLTE_RRC_PHICH_RESOURCE_ENUM; -static const char liblte_rrc_phich_resource_text[LIBLTE_RRC_PHICH_RESOURCE_N_ITEMS][20] = {"1/6", "1/2", "1", "2"}; -static const double liblte_rrc_phich_resource_num[LIBLTE_RRC_PHICH_RESOURCE_N_ITEMS] = {0.16666667, 0.5, 1, 2}; +// PHICH Config enums defined above // Structs -typedef struct{ - LIBLTE_RRC_PHICH_DURATION_ENUM dur; - LIBLTE_RRC_PHICH_RESOURCE_ENUM res; -}LIBLTE_RRC_PHICH_CONFIG_STRUCT; +// PHICH Config struct defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_phich_config_ie(LIBLTE_RRC_PHICH_CONFIG_STRUCT *phich_config, uint8 **ie_ptr); @@ -2812,6 +4001,7 @@ typedef struct{ int32 p0_ue_pusch; int32 p0_ue_pucch; bool accumulation_en; + bool filter_coeff_present; }LIBLTE_RRC_UL_POWER_CONTROL_DEDICATED_STRUCT; typedef struct{ LIBLTE_RRC_TPC_INDEX_ENUM tpc_idx_choice; @@ -2893,21 +4083,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_p_max_ie(uint8 **ie_ptr, // Defines // Enums // Structs -typedef struct{ - uint8 prach_config_index; - uint8 zero_correlation_zone_config; - uint8 prach_freq_offset; - bool high_speed_flag; -}LIBLTE_RRC_PRACH_CONFIG_INFO_STRUCT; -typedef struct{ - LIBLTE_RRC_PRACH_CONFIG_INFO_STRUCT prach_cnfg_info; - uint16 root_sequence_index; -}LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT; -typedef struct{ - LIBLTE_RRC_PRACH_CONFIG_INFO_STRUCT prach_cnfg_info; - uint16 root_sequence_index; - bool prach_cnfg_info_present; -}LIBLTE_RRC_PRACH_CONFIG_STRUCT; +// PRACH Config structs defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_prach_config_sib_ie(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *prach_cnfg, uint8 **ie_ptr); @@ -2949,22 +4125,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_presence_antenna_port_1_ie(uint8 **ie_ptr, *********************************************************************/ // Defines // Enums -typedef enum{ - LIBLTE_RRC_DELTA_PUCCH_SHIFT_DS1 = 0, - LIBLTE_RRC_DELTA_PUCCH_SHIFT_DS2, - LIBLTE_RRC_DELTA_PUCCH_SHIFT_DS3, - LIBLTE_RRC_DELTA_PUCCH_SHIFT_N_ITEMS, -}LIBLTE_RRC_DELTA_PUCCH_SHIFT_ENUM; -static const char liblte_rrc_delta_pucch_shift_text[LIBLTE_RRC_DELTA_PUCCH_SHIFT_N_ITEMS][20] = {"1", "2", "3"}; -static const uint8 liblte_rrc_delta_pucch_shift_num[LIBLTE_RRC_DELTA_PUCCH_SHIFT_N_ITEMS] = {1, 2, 3}; +// PUCCH Config enum defined above // Structs -typedef struct{ - LIBLTE_RRC_DELTA_PUCCH_SHIFT_ENUM delta_pucch_shift; - uint16 n1_pucch_an; - uint8 n_rb_cqi; - uint8 n_cs_an; -}LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT; -// PUCCH Config Dedicated struct is defined above +// PUCCH Config structs defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_pucch_config_common_ie(LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT *pucch_cnfg, uint8 **ie_ptr); @@ -2975,221 +4138,42 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_pucch_config_dedicated_ie(LIBLTE_RRC_PUCCH_CON LIBLTE_ERROR_ENUM liblte_rrc_unpack_pucch_config_dedicated_ie(uint8 **ie_ptr, LIBLTE_RRC_PUCCH_CONFIG_DEDICATED_STRUCT *pucch_cnfg); -/********************************************************************* - IE Name: PUSCH Config - - Description: Specifies the common and the UE specific PUSCH - configuration and the reference signal configuration - for PUSCH and PUCCH - - Document Reference: 36.331 v10.0.0 Section 6.3.2 -*********************************************************************/ -// Defines -// Enums -typedef enum{ - LIBLTE_RRC_HOPPING_MODE_INTER_SUBFRAME = 0, - LIBLTE_RRC_HOPPING_MODE_INTRA_AND_INTER_SUBFRAME, -}LIBLTE_RRC_HOPPING_MODE_ENUM; -// Structs -typedef struct{ - uint8 group_assignment_pusch; - uint8 cyclic_shift; - bool group_hopping_enabled; - bool sequence_hopping_enabled; -}LIBLTE_RRC_UL_RS_PUSCH_STRUCT; -typedef struct{ - LIBLTE_RRC_UL_RS_PUSCH_STRUCT ul_rs; - LIBLTE_RRC_HOPPING_MODE_ENUM hopping_mode; - uint8 n_sb; - uint8 pusch_hopping_offset; - bool enable_64_qam; -}LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT; -// PUSCH Config Dedicated struct defined above -// Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_pusch_config_common_ie(LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT *pusch_cnfg, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_pusch_config_common_ie(uint8 **ie_ptr, - LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT *pusch_cnfg); -LIBLTE_ERROR_ENUM liblte_rrc_pack_pusch_config_dedicated_ie(LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT *pusch_cnfg, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_pusch_config_dedicated_ie(uint8 **ie_ptr, - LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT *pusch_cnfg); - -/********************************************************************* - IE Name: RACH Config Common - - Description: Specifies the generic random access parameters - - Document Reference: 36.331 v10.0.0 Section 6.3.2 -*********************************************************************/ -// Defines -// Enums -typedef enum{ - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N4 = 0, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N8, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N12, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N16, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N20, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N24, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N28, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N32, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N36, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N40, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N44, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N48, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N52, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N56, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N60, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N64, - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N_ITEMS, -}LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_ENUM; -static const char liblte_rrc_number_of_ra_preambles_text[LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N_ITEMS][20] = { "4", "8", "12", "16", - "20", "24", "28", "32", - "36", "40", "44", "48", - "52", "56", "60", "64"}; -static const uint8 liblte_rrc_number_of_ra_preambles_num[LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N_ITEMS] = {4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64}; -typedef enum{ - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N4 = 0, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N8, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N12, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N16, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N20, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N24, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N28, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N32, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N36, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N40, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N44, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N48, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N52, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N56, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N60, - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N_ITEMS, -}LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_ENUM; -static const char liblte_rrc_size_of_ra_preambles_group_a_text[LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N_ITEMS][20] = { "4", "8", "12", "16", - "20", "24", "28", "32", - "36", "40", "44", "48", - "52", "56", "60"}; -static const uint8 liblte_rrc_size_of_ra_preambles_group_a_num[LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_N_ITEMS] = {4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60}; -typedef enum{ - LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_B56 = 0, - LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_B144, - LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_B208, - LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_B256, - LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_N_ITEMS, -}LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_ENUM; -static const char liblte_rrc_message_size_group_a_text[LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_N_ITEMS][20] = {"56", "144", "208", "256"}; -static const uint16 liblte_rrc_message_size_group_a_num[LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_N_ITEMS] = {56, 144, 208, 256}; -typedef enum{ - LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_MINUS_INFINITY = 0, - LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB0, - LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB5, - LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB8, - LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB10, - LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB12, - LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB15, - LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_DB18, - LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_N_ITEMS, -}LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_ENUM; -static const char liblte_rrc_message_power_offset_group_b_text[LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_N_ITEMS][20] = {"-INFINITY", "0", "5", "8", - "10", "12", "15", "18"}; -typedef enum{ - LIBLTE_RRC_POWER_RAMPING_STEP_DB0 = 0, - LIBLTE_RRC_POWER_RAMPING_STEP_DB2, - LIBLTE_RRC_POWER_RAMPING_STEP_DB4, - LIBLTE_RRC_POWER_RAMPING_STEP_DB6, - LIBLTE_RRC_POWER_RAMPING_STEP_N_ITEMS, -}LIBLTE_RRC_POWER_RAMPING_STEP_ENUM; -static const char liblte_rrc_power_ramping_step_text[LIBLTE_RRC_POWER_RAMPING_STEP_N_ITEMS][20] = {"0", "2", "4", "6"}; -static const uint8 liblte_rrc_power_ramping_step_num[LIBLTE_RRC_POWER_RAMPING_STEP_N_ITEMS] = {0, 2, 4, 6}; -typedef enum{ - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N120 = 0, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N118, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N116, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N114, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N112, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N110, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N108, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N106, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N104, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N102, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N100, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N98, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N96, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N94, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N92, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N90, - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_N_ITEMS, -}LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_ENUM; -static const char liblte_rrc_preamble_initial_received_target_power_text[LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_N_ITEMS][20] = {"-120", "-118", "-116", "-114", - "-112", "-110", "-108", "-106", - "-104", "-102", "-100", "-98", - "-96", "-94", "-92", "-90"}; -static const int8 liblte_rrc_preamble_initial_received_target_power_num[LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_N_ITEMS] = {-120, -118, -116, -114, -112, -110, -108, -106, - -104, -102, -100, -98, -96, -94, -92, -90}; -typedef enum{ - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N3 = 0, - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N4, - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N5, - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N6, - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N7, - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N8, - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N10, - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N20, - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N50, - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N100, - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N200, - LIBLTE_RRC_PREAMBLE_TRANS_MAX_N_ITEMS, -}LIBLTE_RRC_PREAMBLE_TRANS_MAX_ENUM; -static const char liblte_rrc_preamble_trans_max_text[LIBLTE_RRC_PREAMBLE_TRANS_MAX_N_ITEMS][20] = { "3", "4", "5", "6", - "7", "8", "10", "20", - "50", "100", "200"}; -static const uint8 liblte_rrc_preamble_trans_max_num[LIBLTE_RRC_PREAMBLE_TRANS_MAX_N_ITEMS] = {3, 4, 5, 6, 7, 8, 10, 20, 50, 100, 200}; -typedef enum{ - LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF2 = 0, - LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF3, - LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF4, - LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF5, - LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF6, - LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF7, - LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF8, - LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF10, - LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_N_ITEMS, -}LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_ENUM; -static const char liblte_rrc_ra_response_window_size_text[LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_N_ITEMS][20] = { "2", "3", "4", "5", - "6", "7", "8", "10"}; -static const uint8 liblte_rrc_ra_response_window_size_num[LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_N_ITEMS] = {2, 3, 4, 5, 6, 7, 8, 10}; -typedef enum{ - LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF8 = 0, - LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF16, - LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF24, - LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF32, - LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF40, - LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF48, - LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF56, - LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF64, - LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_N_ITEMS, -}LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_ENUM; -static const char liblte_rrc_mac_contention_resolution_timer_text[LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_N_ITEMS][20] = { "8", "16", "24", "32", - "40", "48", "56", "64"}; -static const uint8 liblte_rrc_mac_contention_resolution_timer_num[LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_N_ITEMS] = {8, 16, 24, 32, 40, 48, 56, 64}; +/********************************************************************* + IE Name: PUSCH Config + + Description: Specifies the common and the UE specific PUSCH + configuration and the reference signal configuration + for PUSCH and PUCCH + + Document Reference: 36.331 v10.0.0 Section 6.3.2 +*********************************************************************/ +// Defines +// Enums +// PUSCH Config enum defined above // Structs -typedef struct{ - LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_ENUM size_of_ra; - LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_ENUM msg_size; - LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_ENUM msg_pwr_offset_group_b; - bool present; -}LIBLTE_RRC_PREAMBLES_GROUP_A_STRUCT; -typedef struct{ - LIBLTE_RRC_PREAMBLES_GROUP_A_STRUCT preambles_group_a_cnfg; - LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_ENUM num_ra_preambles; - LIBLTE_RRC_POWER_RAMPING_STEP_ENUM pwr_ramping_step; - LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_ENUM preamble_init_rx_target_pwr; - LIBLTE_RRC_PREAMBLE_TRANS_MAX_ENUM preamble_trans_max; - LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_ENUM ra_resp_win_size; - LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_ENUM mac_con_res_timer; - uint8 max_harq_msg3_tx; -}LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT; +// PUSCH Config structs defined above +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_pusch_config_common_ie(LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT *pusch_cnfg, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_pusch_config_common_ie(uint8 **ie_ptr, + LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT *pusch_cnfg); +LIBLTE_ERROR_ENUM liblte_rrc_pack_pusch_config_dedicated_ie(LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT *pusch_cnfg, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_pusch_config_dedicated_ie(uint8 **ie_ptr, + LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT *pusch_cnfg); + +/********************************************************************* + IE Name: RACH Config Common + + Description: Specifies the generic random access parameters + + Document Reference: 36.331 v10.0.0 Section 6.3.2 +*********************************************************************/ +// Defines +// Enums +// RACH Config Common enums defined above +// Structs +// RACH Config Common structs defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_rach_config_common_ie(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT *rach_cnfg, uint8 **ie_ptr); @@ -3206,10 +4190,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rach_config_common_ie(uint8 // Defines // Enums // Structs -typedef struct{ - uint8 preamble_index; - uint8 prach_mask_index; -}LIBLTE_RRC_RACH_CONFIG_DEDICATED_STRUCT; +// RACH Config Dedicated struct defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_rach_config_dedicated_ie(LIBLTE_RRC_RACH_CONFIG_DEDICATED_STRUCT *rach_cnfg, uint8 **ie_ptr); @@ -3260,105 +4241,6 @@ typedef enum{ static const char liblte_rrc_nb_text[LIBLTE_RRC_NB_N_ITEMS][20] = { "4", "2", "1", "1/2", "1/4", "1/8", "1/16", "1/32"}; static const double liblte_rrc_nb_num[LIBLTE_RRC_NB_N_ITEMS] = {4.0, 2.0, 1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125}; -typedef enum{ - LIBLTE_RRC_UL_CP_LENGTH_1 = 0, - LIBLTE_RRC_UL_CP_LENGTH_2, - LIBLTE_RRC_UL_CP_LENGTH_N_ITEMS, -}LIBLTE_RRC_UL_CP_LENGTH_ENUM; -static const char liblte_rrc_ul_cp_length_text[LIBLTE_RRC_UL_CP_LENGTH_N_ITEMS][20] = {"Normal", "Extended"}; -typedef enum{ - LIBLTE_RRC_SRS_BW_CONFIG_0 = 0, - LIBLTE_RRC_SRS_BW_CONFIG_1, - LIBLTE_RRC_SRS_BW_CONFIG_2, - LIBLTE_RRC_SRS_BW_CONFIG_3, - LIBLTE_RRC_SRS_BW_CONFIG_4, - LIBLTE_RRC_SRS_BW_CONFIG_5, - LIBLTE_RRC_SRS_BW_CONFIG_6, - LIBLTE_RRC_SRS_BW_CONFIG_7, - LIBLTE_RRC_SRS_BW_CONFIG_N_ITEMS, -}LIBLTE_RRC_SRS_BW_CONFIG_ENUM; -static const char liblte_rrc_srs_bw_config_text[LIBLTE_RRC_SRS_BW_CONFIG_N_ITEMS][20] = {"0", "1", "2", "3", - "4", "5", "6", "7"}; -static const uint8 liblte_rrc_srs_bw_config_num[LIBLTE_RRC_SRS_BW_CONFIG_N_ITEMS] = {0, 1, 2, 3, 4, 5, 6, 7}; -typedef enum{ - LIBLTE_RRC_SRS_SUBFR_CONFIG_0 = 0, - LIBLTE_RRC_SRS_SUBFR_CONFIG_1, - LIBLTE_RRC_SRS_SUBFR_CONFIG_2, - LIBLTE_RRC_SRS_SUBFR_CONFIG_3, - LIBLTE_RRC_SRS_SUBFR_CONFIG_4, - LIBLTE_RRC_SRS_SUBFR_CONFIG_5, - LIBLTE_RRC_SRS_SUBFR_CONFIG_6, - LIBLTE_RRC_SRS_SUBFR_CONFIG_7, - LIBLTE_RRC_SRS_SUBFR_CONFIG_8, - LIBLTE_RRC_SRS_SUBFR_CONFIG_9, - LIBLTE_RRC_SRS_SUBFR_CONFIG_10, - LIBLTE_RRC_SRS_SUBFR_CONFIG_11, - LIBLTE_RRC_SRS_SUBFR_CONFIG_12, - LIBLTE_RRC_SRS_SUBFR_CONFIG_13, - LIBLTE_RRC_SRS_SUBFR_CONFIG_14, - LIBLTE_RRC_SRS_SUBFR_CONFIG_15, - LIBLTE_RRC_SRS_SUBFR_CONFIG_N_ITEMS, -}LIBLTE_RRC_SRS_SUBFR_CONFIG_ENUM; -static const char liblte_rrc_srs_subfr_config_text[LIBLTE_RRC_SRS_SUBFR_CONFIG_N_ITEMS][20] = { "0", "1", "2", "3", - "4", "5", "6", "7", - "8", "9", "10", "11", - "12", "13", "14", "15"}; -static const uint8 liblte_rrc_srs_subfr_config_num[LIBLTE_RRC_SRS_SUBFR_CONFIG_N_ITEMS] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; -typedef enum{ - LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_0 = 0, - LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_04, - LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_05, - LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_06, - LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_07, - LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_08, - LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_09, - LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_1, - LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_N_ITEMS, -}LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_ENUM; -static const char liblte_rrc_ul_power_control_alpha_text[LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_N_ITEMS][20] = {"0.0", "0.4", "0.5", "0.6", - "0.7", "0.8", "0.9", "1.0"}; -static const double liblte_rrc_ul_power_control_alpha_num[LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_N_ITEMS] = {0.0, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; -typedef enum{ - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_NEG_2 = 0, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_0, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_2, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_N_ITEMS, -}LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_ENUM; -static const char liblte_rrc_delta_f_pucch_format_1_text[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_N_ITEMS][20] = {"-2", "0", "2"}; -static const int8 liblte_rrc_delta_f_pucch_format_1_num[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_N_ITEMS] = {-2, 0, 2}; -typedef enum{ - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_1 = 0, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_3, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_5, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_N_ITEMS, -}LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_ENUM; -static const char liblte_rrc_delta_f_pucch_format_1b_text[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_N_ITEMS][20] = {"1", "3", "5"}; -static const uint8 liblte_rrc_delta_f_pucch_format_1b_num[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_N_ITEMS] = {1, 3, 5}; -typedef enum{ - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_NEG_2 = 0, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_0, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_1, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_2, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_N_ITEMS, -}LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_ENUM; -static const char liblte_rrc_delta_f_pucch_format_2_text[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_N_ITEMS][20] = {"-2", "0", "1", "2"}; -static const int8 liblte_rrc_delta_f_pucch_format_2_num[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_N_ITEMS] = {-2, 0, 1, 2}; -typedef enum{ - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_NEG_2 = 0, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_0, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_2, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_N_ITEMS, -}LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_ENUM; -static const char liblte_rrc_delta_f_pucch_format_2a_text[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_N_ITEMS][20] = {"-2", "0", "2"}; -static const int8 liblte_rrc_delta_f_pucch_format_2a_num[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_N_ITEMS] = {-2, 0, 2}; -typedef enum{ - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_NEG_2 = 0, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_0, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_2, - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_N_ITEMS, -}LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_ENUM; -static const char liblte_rrc_delta_f_pucch_format_2b_text[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_N_ITEMS][20] = {"-2", "0", "2"}; -static const int8 liblte_rrc_delta_f_pucch_format_2b_num[LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_N_ITEMS] = {-2, 0, 2}; // Structs typedef struct{ LIBLTE_RRC_MODIFICATION_PERIOD_COEFF_ENUM modification_period_coeff; @@ -3367,28 +4249,6 @@ typedef struct{ LIBLTE_RRC_DEFAULT_PAGING_CYCLE_ENUM default_paging_cycle; LIBLTE_RRC_NB_ENUM nB; }LIBLTE_RRC_PCCH_CONFIG_STRUCT; -typedef struct{ - LIBLTE_RRC_SRS_BW_CONFIG_ENUM bw_cnfg; - LIBLTE_RRC_SRS_SUBFR_CONFIG_ENUM subfr_cnfg; - bool ack_nack_simul_tx; - bool max_up_pts; - bool max_up_pts_present; - bool present; -}LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT; -typedef struct{ - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_ENUM format_1; - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_ENUM format_1b; - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_ENUM format_2; - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_ENUM format_2a; - LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_ENUM format_2b; -}LIBLTE_RRC_DELTA_FLIST_PUCCH_STRUCT; -typedef struct{ - LIBLTE_RRC_DELTA_FLIST_PUCCH_STRUCT delta_flist_pucch; - LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_ENUM alpha; - int8 p0_nominal_pusch; - int8 p0_nominal_pucch; - int8 delta_preamble_msg3; -}LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT; typedef struct{ LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT rach_cnfg; LIBLTE_RRC_BCCH_CONFIG_STRUCT bcch_cnfg; @@ -3401,12 +4261,16 @@ typedef struct{ LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT ul_pwr_ctrl; LIBLTE_RRC_UL_CP_LENGTH_ENUM ul_cp_length; }LIBLTE_RRC_RR_CONFIG_COMMON_SIB_STRUCT; +// RR Config Common struct defined above // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_common_sib_ie(LIBLTE_RRC_RR_CONFIG_COMMON_SIB_STRUCT *rr_cnfg, uint8 **ie_ptr); LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_common_sib_ie(uint8 **ie_ptr, LIBLTE_RRC_RR_CONFIG_COMMON_SIB_STRUCT *rr_cnfg); -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_common_ie(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *rr_cnfg, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_common_ie(uint8 **ie_ptr, + LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *rr_cnfg); /********************************************************************* IE Name: Radio Resource Config Dedicated @@ -3595,6 +4459,17 @@ static const char liblte_rrc_t_reordering_text[LIBLTE_RRC_T_REORDERING_N_ITEMS][ "ms100", "ms110", "ms120", "ms130", "ms140", "ms150", "ms160", "ms170", "ms180", "ms190", "ms200", "SPARE"}; +typedef enum{ + LIBLTE_RRC_RLC_MODE_AM = 0, + LIBLTE_RRC_RLC_MODE_UM_BI, + LIBLTE_RRC_RLC_MODE_UM_UNI_UL, + LIBLTE_RRC_RLC_MODE_UM_UNI_DL, + LIBLTE_RRC_RLC_MODE_N_ITEMS, +}LIBLTE_RRC_RLC_MODE_ENUM; +static const char liblte_rrc_rlc_mode_text[LIBLTE_RRC_RLC_MODE_N_ITEMS][20] = {"AM", + "UM BI", + "UM UNI UL", + "UM UNI DL"}; typedef enum{ LIBLTE_RRC_T_STATUS_PROHIBIT_MS0 = 0, LIBLTE_RRC_T_STATUS_PROHIBIT_MS5, @@ -3768,6 +4643,7 @@ typedef struct{ LIBLTE_RRC_DL_UM_RLC_STRUCT dl_um_bi_rlc; LIBLTE_RRC_UL_UM_RLC_STRUCT ul_um_uni_rlc; LIBLTE_RRC_DL_UM_RLC_STRUCT dl_um_uni_rlc; + LIBLTE_RRC_RLC_MODE_ENUM rlc_mode; }LIBLTE_RRC_RLC_CONFIG_STRUCT; typedef struct{ LIBLTE_RRC_RLC_CONFIG_STRUCT rlc_explicit_cnfg; @@ -3893,9 +4769,65 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rlf_timers_and_constants_ie(uint8 *********************************************************************/ // Defines // Enums -// Structs -// Functions -// FIXME +typedef enum{ + LIBLTE_RRC_FRAME_STRUCTURE_TYPE_FDD = 0, + LIBLTE_RRC_FRAME_STRUCTURE_TYPE_TDD, + LIBLTE_RRC_FRAME_STRUCTURE_TYPE_N_ITEMS, +}LIBLTE_RRC_FRAME_STRUCTURE_TYPE_ENUM; +static const char liblte_rrc_frame_structure_type_text[LIBLTE_RRC_FRAME_STRUCTURE_TYPE_N_ITEMS][20] = {"fdd", "tdd"}; +typedef enum{ + LIBLTE_RRC_RESOURCE_ALLOCATION_TYPE_0 = 0, + LIBLTE_RRC_RESOURCE_ALLOCATION_TYPE_1, + LIBLTE_RRC_RESOURCE_ALLOCATION_TYPE_2_LOCALIZED, + LIBLTE_RRC_RESOURCE_ALLOCATION_TYPE_2_DISTRIBUTED, + LIBLTE_RRC_RESOURCE_ALLOCATION_TYPE_N_ITEMS, +}LIBLTE_RRC_RESOURCE_ALLOCATION_TYPE_ENUM; +static const char liblte_rrc_resource_allocation_type_text[LIBLTE_RRC_RESOURCE_ALLOCATION_TYPE_N_ITEMS][20] = {"0", "1", "2-localized", "2-distributed"}; +typedef enum{ + LIBLTE_RRC_RESOURCE_BLOCK_ASSIGNMENT_CHOICE_TYPE_0 = 0, + LIBLTE_RRC_RESOURCE_BLOCK_ASSIGNMENT_CHOICE_TYPE_1, + LIBLTE_RRC_RESOURCE_BLOCK_ASSIGNMENT_CHOICE_N_ITEMS, +}LIBLTE_RRC_RESOURCE_BLOCK_ASSIGNMENT_CHOICE_ENUM; +static const char liblte_rrc_resource_block_assignment_choice_text[LIBLTE_RRC_RESOURCE_BLOCK_ASSIGNMENT_CHOICE_N_ITEMS][20] = {"type-0", "type-1"}; +typedef enum{ + LIBLTE_RRC_DEMODULATION_RS_CHOICE_INTERLEAVING = 0, + LIBLTE_RRC_DEMODULATION_RS_CHOICE_NO_INTERLEAVING, + LIBLTE_RRC_DEMODULATION_RS_CHOICE_N_ITEMS, +}LIBLTE_RRC_DEMODULATION_RS_CHOICE_ENUM; +static const char liblte_rrc_demodulation_rs_choice_text[LIBLTE_RRC_DEMODULATION_RS_CHOICE_N_ITEMS][20] = {"interleaving", "no-interleaving"}; +typedef enum{ + LIBLTE_RRC_DEMODULATION_RS_TYPE_CRS = 0, + LIBLTE_RRC_DEMODULATION_RS_TYPE_DMRS, + LIBLTE_RRC_DEMODULATION_RS_TYPE_N_ITEMS, +}LIBLTE_RRC_DEMODULATION_RS_TYPE_ENUM; +static const char liblte_rrc_demodulation_rs_type_text[LIBLTE_RRC_DEMODULATION_RS_TYPE_N_ITEMS][20] = {"crs", "dmrs"}; +// Structs +typedef struct{ + LIBLTE_RRC_RESOURCE_ALLOCATION_TYPE_ENUM resource_alloc_type; + LIBLTE_RRC_RESOURCE_BLOCK_ASSIGNMENT_CHOICE_ENUM resource_block_assignment_choice; + LIBLTE_RRC_DEMODULATION_RS_CHOICE_ENUM demod_rs_choice; + LIBLTE_RRC_DEMODULATION_RS_TYPE_ENUM demod_rs_type; + uint32 rba_nrb50; + uint32 rba_nrb75; + uint32 rba_nrb100; + uint16 rba_nrb25; + uint16 n1_pucch_an_port_0; + uint16 n1_pucch_an_port_1; + uint8 rba_nrb6; + uint8 rba_nrb15; + uint8 pdsch_start; +}LIBLTE_RRC_RPDCCH_CONFIG_STRUCT; +typedef struct{ + LIBLTE_RRC_RPDCCH_CONFIG_STRUCT rpdcch_cnfg; + LIBLTE_RRC_FRAME_STRUCTURE_TYPE_ENUM fr_struct_type; + uint8 subfr_cnfg_pattern; + bool rpdcch_cnfg_present; +}LIBLTE_RRC_RN_SUBFRAME_CONFIG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_rn_subframe_config_ie(LIBLTE_RRC_RN_SUBFRAME_CONFIG_STRUCT *rn_subfr_cnfg, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_rn_subframe_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_RN_SUBFRAME_CONFIG_STRUCT *rn_subfr_cnfg); /********************************************************************* IE Name: Scheduling Request Config @@ -3965,43 +4897,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sps_config_ie(uint8 * *********************************************************************/ // Defines // Enums -typedef enum{ - LIBLTE_RRC_SUBFRAME_ASSIGNMENT_0 = 0, - LIBLTE_RRC_SUBFRAME_ASSIGNMENT_1, - LIBLTE_RRC_SUBFRAME_ASSIGNMENT_2, - LIBLTE_RRC_SUBFRAME_ASSIGNMENT_3, - LIBLTE_RRC_SUBFRAME_ASSIGNMENT_4, - LIBLTE_RRC_SUBFRAME_ASSIGNMENT_5, - LIBLTE_RRC_SUBFRAME_ASSIGNMENT_6, - LIBLTE_RRC_SUBFRAME_ASSIGNMENT_N_ITEMS, -}LIBLTE_RRC_SUBFRAME_ASSIGNMENT_ENUM; -static const char liblte_rrc_subframe_assignment_text[LIBLTE_RRC_SUBFRAME_ASSIGNMENT_N_ITEMS][20] = {"0", "1", "2", "3", - "4", "5", "6"}; -static const uint8 liblte_rrc_subframe_assignment_num[LIBLTE_RRC_SUBFRAME_ASSIGNMENT_N_ITEMS] = {0, 1, 2, 3, 4, 5, 6}; -typedef enum{ - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_0 = 0, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_1, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_2, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_3, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_4, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_5, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_6, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_7, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_8, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_N_ITEMS, -}LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_ENUM; -static const char liblte_rrc_special_subframe_patterns_text[LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_N_ITEMS][20] = {"0", "1", "2", "3", - "4", "5", "6", "7", - "8"}; -static const uint8 liblte_rrc_special_subframe_patterns_num[LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_N_ITEMS] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; +// TDD Config enums defined above // Structs +// TDD Config struct defined above // Functions -LIBLTE_ERROR_ENUM liblte_rrc_pack_tdd_config_ie(LIBLTE_RRC_SUBFRAME_ASSIGNMENT_ENUM sa, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_ENUM ssp, - uint8 **ie_ptr); -LIBLTE_ERROR_ENUM liblte_rrc_unpack_tdd_config_ie(uint8 **ie_ptr, - LIBLTE_RRC_SUBFRAME_ASSIGNMENT_ENUM *sa, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_ENUM *ssp); +LIBLTE_ERROR_ENUM liblte_rrc_pack_tdd_config_ie(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd_cnfg, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_tdd_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd_cnfg); /********************************************************************* IE Name: Time Alignment Timer @@ -4152,11 +5055,13 @@ typedef enum{ LIBLTE_RRC_UL_BW_N50, LIBLTE_RRC_UL_BW_N75, LIBLTE_RRC_UL_BW_N100, + LIBLTE_RRC_UL_BW_SPARE1, + LIBLTE_RRC_UL_BW_SPARE2, LIBLTE_RRC_UL_BW_N_ITEMS, }LIBLTE_RRC_UL_BW_ENUM; -static const char liblte_rrc_ul_bw_text[LIBLTE_RRC_UL_BW_N_ITEMS][20] = {"1.4", "3", "5", "10", - "15", "20"}; -static const double liblte_rrc_ul_bw_num[LIBLTE_RRC_UL_BW_N_ITEMS] = {1.4, 3, 5, 10, 15, 20}; +static const char liblte_rrc_ul_bw_text[LIBLTE_RRC_UL_BW_N_ITEMS][20] = { "1.4", "3", "5", "10", + "15", "20", "SPARE1", "SPARE2"}; +static const double liblte_rrc_ul_bw_num[LIBLTE_RRC_UL_BW_N_ITEMS] = {1.4, 3, 5, 10, 15, 20, 0, 0}; // Structs typedef struct{ LIBLTE_RRC_AC_BARRING_FACTOR_ENUM factor; @@ -4577,8 +5482,18 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_8_ie(uint8 // Defines // Enums // Structs +typedef struct{ + LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT mbsfn_area_info_list_r9[LIBLTE_RRC_MAX_MBSFN_AREAS]; + LIBLTE_RRC_MBSFN_NOTIFICATION_CONFIG_STRUCT mbms_notification_config; + LIBLTE_BYTE_MSG_STRUCT non_crit_ext; + uint8 mbsfn_area_info_list_r9_size; + bool non_crit_ext_present; +}LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_13_ie(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_13_ie(uint8 **ie_ptr, + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13); /******************************************************************************* MESSAGE DECLARATIONS @@ -4594,9 +5509,21 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_8_ie(uint8 *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_NAS = 0, + LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_CDMA2000_1XRTT, + LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_CDMA2000_HRPD, + LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_SPARE, + LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_N_ITEMS, +}LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_ENUM; +static const char liblte_rrc_ul_information_transfer_type_text[LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_N_ITEMS][20] = {"NAS", + "CDMA2000-1XRTT", + "CDMA2000-HRPD", + "SPARE"}; // Structs typedef struct{ - // FIXME + LIBLTE_BYTE_MSG_STRUCT dedicated_info; + LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_ENUM dedicated_info_type; }LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_information_transfer_msg(LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT *ul_info_transfer, @@ -4655,8 +5582,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_information_response_msg(LIBLTE_BIT_MSG_S // Defines // Enums // Structs +typedef struct{ + uint8 rrc_transaction_id; + bool rach_report_req; + bool rlf_report_req; +}LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_information_request_msg(LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT *ue_info_req, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_information_request_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT *ue_info_req); /********************************************************************* Message Name: UE Capability Information @@ -4670,7 +5605,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_information_response_msg(LIBLTE_BIT_MSG_S // Enums // Structs typedef struct{ - // FIXME + LIBLTE_RRC_UE_CAPABILITY_RAT_CONTAINER_LIST_STRUCT ue_capability_rat_container_list; + uint8 rrc_transaction_id; }LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_capability_information_msg(LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *ue_capability_info, @@ -4689,8 +5625,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_capability_information_msg(LIBLTE_BIT_MSG // Defines // Enums // Structs +typedef struct{ + LIBLTE_RRC_RAT_TYPE_ENUM rat_type_list[LIBLTE_RRC_MAX_RAT_CAPABILITIES]; + uint32 rat_type_list_size; + uint8 rrc_transaction_id; +}LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_capability_enquiry_msg(LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT *ue_cap_enquiry, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_capability_enquiry_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT *ue_cap_enquiry); /********************************************************************* Message Name: System Information Block Type 1 @@ -4726,11 +5670,12 @@ typedef enum{ LIBLTE_RRC_SI_WINDOW_LENGTH_MS15, LIBLTE_RRC_SI_WINDOW_LENGTH_MS20, LIBLTE_RRC_SI_WINDOW_LENGTH_MS40, + LIBLTE_RRC_SI_WINDOW_LENGTH_SPARE, LIBLTE_RRC_SI_WINDOW_LENGTH_N_ITEMS, }LIBLTE_RRC_SI_WINDOW_LENGTH_ENUM; -static const char liblte_rrc_si_window_length_text[LIBLTE_RRC_SI_WINDOW_LENGTH_N_ITEMS][20] = { "1", "2", "5", "10", - "15", "20", "40"}; -static const uint8 liblte_rrc_si_window_length_num[LIBLTE_RRC_SI_WINDOW_LENGTH_N_ITEMS] = {1, 2, 5, 10, 15, 20, 40}; +static const char liblte_rrc_si_window_length_text[LIBLTE_RRC_SI_WINDOW_LENGTH_N_ITEMS][20] = { "1", "2", "5", "10", + "15", "20", "40", "SPARE"}; +static const uint8 liblte_rrc_si_window_length_num[LIBLTE_RRC_SI_WINDOW_LENGTH_N_ITEMS] = {1, 2, 5, 10, 15, 20, 40, 0}; typedef enum{ LIBLTE_RRC_RESV_FOR_OPER = 0, LIBLTE_RRC_NOT_RESV_FOR_OPER, @@ -4745,11 +5690,12 @@ typedef enum{ LIBLTE_RRC_SI_PERIODICITY_RF128, LIBLTE_RRC_SI_PERIODICITY_RF256, LIBLTE_RRC_SI_PERIODICITY_RF512, + LIBLTE_RRC_SI_PERIODICITY_SPARE, LIBLTE_RRC_SI_PERIODICITY_N_ITEMS, }LIBLTE_RRC_SI_PERIODICITY_ENUM; -static const char liblte_rrc_si_periodicity_text[LIBLTE_RRC_SI_PERIODICITY_N_ITEMS][20] = { "8", "16", "32", "64", - "128", "256", "512"}; -static const uint16 liblte_rrc_si_periodicity_num[LIBLTE_RRC_SI_PERIODICITY_N_ITEMS] = {8, 16, 32, 64, 128, 256, 512}; +static const char liblte_rrc_si_periodicity_text[LIBLTE_RRC_SI_PERIODICITY_N_ITEMS][20] = { "8", "16", "32", "64", + "128", "256", "512", "SPARE"}; +static const uint16 liblte_rrc_si_periodicity_num[LIBLTE_RRC_SI_PERIODICITY_N_ITEMS] = {8, 16, 32, 64, 128, 256, 512, 0}; typedef enum{ LIBLTE_RRC_SIB_TYPE_3 = 0, LIBLTE_RRC_SIB_TYPE_4, @@ -4790,11 +5736,10 @@ typedef struct{ typedef struct{ LIBLTE_RRC_PLMN_IDENTITY_LIST_STRUCT plmn_id[LIBLTE_RRC_MAX_N_PLMN_IDENTITIES]; LIBLTE_RRC_SCHEDULING_INFO_STRUCT sched_info[LIBLTE_RRC_MAX_SI_MESSAGE]; + LIBLTE_RRC_TDD_CONFIG_STRUCT tdd_cnfg; LIBLTE_RRC_CELL_BARRED_ENUM cell_barred; LIBLTE_RRC_INTRA_FREQ_RESELECTION_ENUM intra_freq_reselection; LIBLTE_RRC_SI_WINDOW_LENGTH_ENUM si_window_length; - LIBLTE_RRC_SUBFRAME_ASSIGNMENT_ENUM sf_assignment; - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_ENUM special_sf_patterns; uint32 cell_id; uint32 csg_id; uint32 N_plmn_ids; @@ -4838,24 +5783,30 @@ typedef enum{ LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_11, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_12, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13, + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_SPARE1, + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_SPARE2, + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_SPARE3, + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_SPARE4, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1, // Intentionally not first LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_N_ITEMS, }LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_ENUM; -static const char liblte_rrc_sys_info_block_type_text[LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_N_ITEMS][20] = { "2", "3", "4", "5", - "6", "7", "8", "9", - "10", "11", "12", "13", - "1"}; -static const uint8 liblte_rrc_sys_info_block_type_num[LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_N_ITEMS] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1}; +static const char liblte_rrc_sys_info_block_type_text[LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_N_ITEMS][20] = { "2", "3", "4", "5", + "6", "7", "8", "9", + "10", "11", "12", "13", + "SPARE1", "SPARE2", "SPARE3", "SPARE4", + "1"}; +static const uint8 liblte_rrc_sys_info_block_type_num[LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_N_ITEMS] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0, 1}; // Structs typedef union{ - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1; - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2; - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3; - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT sib4; - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_5_STRUCT sib5; - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_6_STRUCT sib6; - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7_STRUCT sib7; - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT sib8; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT sib4; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_5_STRUCT sib5; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_6_STRUCT sib6; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7_STRUCT sib7; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT sib8; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13; }LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_UNION; typedef struct{ LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_UNION sib; @@ -4921,8 +5872,15 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_security_mode_complete_msg(LIBLTE_BIT_MSG_ST // Defines // Enums // Structs +typedef struct{ + LIBLTE_RRC_SECURITY_ALGORITHM_CONFIG_STRUCT sec_algs; + uint8 rrc_transaction_id; +}LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_security_mode_command_msg(LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT *security_mode_cmd, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_security_mode_command_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT *security_mode_cmd); /********************************************************************* Message Name: RRC Connection Setup Complete @@ -4944,7 +5902,7 @@ typedef struct{ typedef struct{ LIBLTE_RRC_REGISTERED_MME_STRUCT registered_mme; LIBLTE_BYTE_MSG_STRUCT dedicated_info_nas; - uint8 transaction_id; + uint8 rrc_transaction_id; uint8 selected_plmn_id; bool registered_mme_present; }LIBLTE_RRC_CONNECTION_SETUP_COMPLETE_STRUCT; @@ -4966,7 +5924,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_setup_complete_msg(LIBLTE_BIT // Structs typedef struct{ LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT rr_cnfg; - uint8 transaction_id; + uint8 rrc_transaction_id; }LIBLTE_RRC_CONNECTION_SETUP_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_setup_msg(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *con_setup, @@ -5035,9 +5993,27 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_request_msg(LIBLTE_BIT_MSG_ST *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_RRC_RELEASE_CAUSE_LOAD_BALANCING_TAU_REQUIRED = 0, + LIBLTE_RRC_RELEASE_CAUSE_OTHER, + LIBLTE_RRC_RELEASE_CAUSE_CS_FALLBACK_HIGH_PRIORITY, + LIBLTE_RRC_RELEASE_CAUSE_SPARE1, + LIBLTE_RRC_RELEASE_CAUSE_N_ITEMS, +}LIBLTE_RRC_RELEASE_CAUSE_ENUM; +static const char liblte_rrc_release_cause_text[LIBLTE_RRC_RELEASE_CAUSE_N_ITEMS][100] = {"Load Balancing TAU Required", + "Other", + "CS Fallback High Priority", + "SPARE"}; // Structs +typedef struct{ + LIBLTE_RRC_RELEASE_CAUSE_ENUM release_cause; + uint8 rrc_transaction_id; +}LIBLTE_RRC_CONNECTION_RELEASE_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_release_msg(LIBLTE_RRC_CONNECTION_RELEASE_STRUCT *con_release, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_release_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_CONNECTION_RELEASE_STRUCT *con_release); /********************************************************************* Message Name: RRC Connection Reject @@ -5068,15 +6044,6 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reject_msg(LIBLTE_BIT_MSG_STR *********************************************************************/ // Defines // Enums -typedef enum{ - LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_C_RNTI = 0, - LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_PHYS_CELL_ID, - LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_SHORT_MAC_I, - LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_N_ITEMS, -}LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_ENUM; -static const char liblte_rrc_con_reest_req_ue_id_type_text[LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_N_ITEMS][20] = {"C-RNTI", - "Phys Cell ID", - "Short MAC I"}; typedef enum{ LIBLTE_RRC_CON_REEST_REQ_CAUSE_RECONFIG_FAILURE = 0, LIBLTE_RRC_CON_REEST_REQ_CAUSE_HANDOVER_FAILURE, @@ -5089,15 +6056,14 @@ static const char liblte_rrc_con_reest_req_cause_text[LIBLTE_RRC_CON_REEST_REQ_C "Other Failure", "SPARE"}; // Structs -typedef union{ +typedef struct{ uint16 c_rnti; uint16 phys_cell_id; uint16 short_mac_i; -}LIBLTE_RRC_CON_REEST_REQ_UE_ID_UNION; +}LIBLTE_RRC_CON_REEST_REQ_UE_ID_STRUCT; typedef struct{ - LIBLTE_RRC_CON_REEST_REQ_UE_ID_UNION ue_id; - LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_ENUM ue_id_type; - LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause; + LIBLTE_RRC_CON_REEST_REQ_UE_ID_STRUCT ue_id; + LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause; }LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reestablishment_request_msg(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *con_reest_req, @@ -5156,7 +6122,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reestablishment_complete_msg( // Structs typedef struct{ LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT rr_cnfg; - uint8 transaction_id; + uint8 rrc_transaction_id; uint8 next_hop_chaining_count; }LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT; // Functions @@ -5194,9 +6160,47 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reconfiguration_complete_msg( *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_RRC_HANDOVER_TYPE_INTRA_LTE = 0, + LIBLTE_RRC_HANDOVER_TYPE_INTER_RAT, + LIBLTE_RRC_HANDOVER_TYPE_N_ITEMS, +}LIBLTE_RRC_HANDOVER_TYPE_ENUM; +static const char liblte_rrc_handover_type_text[LIBLTE_RRC_HANDOVER_TYPE_N_ITEMS][20] = {"Intra LTE", + "Inter RAT"}; // Structs +typedef struct{ + LIBLTE_RRC_SECURITY_ALGORITHM_CONFIG_STRUCT sec_alg_cnfg; + uint8 next_hop_chaining_count; + bool key_change_ind; + bool sec_alg_cnfg_present; +}LIBLTE_RRC_INTRA_LTE_HANDOVER_STRUCT; +typedef struct{ + LIBLTE_RRC_SECURITY_ALGORITHM_CONFIG_STRUCT sec_alg_cnfg; + uint8 nas_sec_param_to_eutra[6]; +}LIBLTE_RRC_INTER_RAT_HANDOVER_STRUCT; +typedef struct{ + LIBLTE_RRC_INTRA_LTE_HANDOVER_STRUCT intra_lte; + LIBLTE_RRC_INTER_RAT_HANDOVER_STRUCT inter_rat; + LIBLTE_RRC_HANDOVER_TYPE_ENUM ho_type; +}LIBLTE_RRC_SECURITY_CONFIG_HO_STRUCT; +typedef struct{ + LIBLTE_RRC_MEAS_CONFIG_STRUCT meas_cnfg; + LIBLTE_RRC_MOBILITY_CONTROL_INFO_STRUCT mob_ctrl_info; + LIBLTE_BYTE_MSG_STRUCT ded_info_nas_list[LIBLTE_RRC_MAX_DRB]; + LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT rr_cnfg_ded; + LIBLTE_RRC_SECURITY_CONFIG_HO_STRUCT sec_cnfg_ho; + uint32 N_ded_info_nas; + uint8 rrc_transaction_id; + bool meas_cnfg_present; + bool mob_ctrl_info_present; + bool rr_cnfg_ded_present; + bool sec_cnfg_ho_present; +}LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reconfiguration_msg(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *con_reconfig, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reconfiguration_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *con_reconfig); /********************************************************************* Message Name: RN Reconfiguration Complete @@ -5229,8 +6233,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rn_reconfiguration_complete_msg(LIBLTE_BIT_M // Defines // Enums // Structs +typedef struct{ + // FIXME +}LIBLTE_RRC_RN_RECONFIGURATION_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_rn_reconfiguration_msg(LIBLTE_RRC_RN_RECONFIGURATION_STRUCT *rn_reconfig, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_rn_reconfiguration_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_RN_RECONFIGURATION_STRUCT *rn_reconfig); /********************************************************************* Message Name: Proximity Indication @@ -5354,8 +6364,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_paging_msg(LIBLTE_BIT_MSG_STRUCT *msg, // Defines // Enums // Structs +typedef struct{ + // FIXME +}LIBLTE_RRC_MOBILITY_FROM_EUTRA_COMMAND_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_mobility_from_eutra_command_msg(LIBLTE_RRC_MOBILITY_FROM_EUTRA_COMMAND_STRUCT *mobility_from_eutra_cmd, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_mobility_from_eutra_command_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_MOBILITY_FROM_EUTRA_COMMAND_STRUCT *mobility_from_eutra_cmd); /********************************************************************* Message Name: Measurement Report @@ -5410,8 +6426,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_measurement_report_msg(LIBLTE_BIT_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + // FIXME +}LIBLTE_RRC_LOGGED_MEASUREMENTS_CONFIGURATION_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_logged_measurements_configuration_msg(LIBLTE_RRC_LOGGED_MEASUREMENTS_CONFIGURATION_STRUCT *logged_measurements_config, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_logged_measurements_configuration_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_LOGGED_MEASUREMENTS_CONFIGURATION_STRUCT *logged_measurements_config); /********************************************************************* Message Name: Handover From EUTRA Preparation Request (CDMA2000) @@ -5424,8 +6446,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_measurement_report_msg(LIBLTE_BIT_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + // FIXME +}LIBLTE_RRC_HANDOVER_FROM_EUTRA_PREPARATION_REQUEST_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_handover_from_eutra_preparation_request_msg(LIBLTE_RRC_HANDOVER_FROM_EUTRA_PREPARATION_REQUEST_STRUCT *handover_from_eutra_prep_req, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_handover_from_eutra_preparation_request_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_HANDOVER_FROM_EUTRA_PREPARATION_REQUEST_STRUCT *handover_from_eutra_prep_req); /********************************************************************* Message Name: DL Information Transfer @@ -5437,9 +6465,28 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_measurement_report_msg(LIBLTE_BIT_MSG_STRUCT *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_NAS = 0, + LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_CDMA2000_1XRTT, + LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_CDMA2000_HRPD, + LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_SPARE, + LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_N_ITEMS, +}LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_ENUM; +static const char liblte_rrc_dl_information_transfer_type_text[LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_N_ITEMS][20] = {"NAS", + "CDMA2000-1XRTT", + "CDMA2000-HRPD", + "SPARE"}; // Structs +typedef struct{ + LIBLTE_BYTE_MSG_STRUCT dedicated_info; + LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_ENUM dedicated_info_type; + uint8 rrc_transaction_id; +}LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_dl_information_transfer_msg(LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT *dl_info_transfer, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_dl_information_transfer_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT *dl_info_transfer); /********************************************************************* Message Name: CSFB Parameters Response CDMA2000 @@ -5453,8 +6500,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_measurement_report_msg(LIBLTE_BIT_MSG_STRUCT // Defines // Enums // Structs +typedef struct{ + // FIXME +}LIBLTE_RRC_CSFB_PARAMETERS_RESPONSE_CDMA2000_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_csfb_parameters_response_cdma2000_msg(LIBLTE_RRC_CSFB_PARAMETERS_RESPONSE_CDMA2000_STRUCT *csfb_params_resp_cdma2000, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_csfb_parameters_response_cdma2000_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_CSFB_PARAMETERS_RESPONSE_CDMA2000_STRUCT *csfb_params_resp_cdma2000); /********************************************************************* Message Name: CSFB Parameters Request CDMA2000 @@ -5507,8 +6560,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_counter_check_response_msg(LIBLTE_BIT_MSG_ST // Defines // Enums // Structs +typedef struct{ + // FIXME +}LIBLTE_RRC_COUNTER_CHECK_STRUCT; // Functions -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_counter_check_msg(LIBLTE_RRC_COUNTER_CHECK_STRUCT *counter_check, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_counter_check_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_COUNTER_CHECK_STRUCT *counter_check); /********************************************************************* Message Name: BCCH BCH Message @@ -5528,11 +6587,13 @@ typedef enum{ LIBLTE_RRC_DL_BANDWIDTH_50, LIBLTE_RRC_DL_BANDWIDTH_75, LIBLTE_RRC_DL_BANDWIDTH_100, + LIBLTE_RRC_DL_BANDWIDTH_SPARE1, + LIBLTE_RRC_DL_BANDWIDTH_SPARE2, LIBLTE_RRC_DL_BANDWIDTH_N_ITEMS, }LIBLTE_RRC_DL_BANDWIDTH_ENUM; -static const char liblte_rrc_dl_bandwidth_text[LIBLTE_RRC_DL_BANDWIDTH_N_ITEMS][20] = {"1.4", "3", "5", "10", - "15", "20"}; -static const double liblte_rrc_dl_bandwidth_num[LIBLTE_RRC_DL_BANDWIDTH_N_ITEMS] = {1.4, 3, 5, 10, 15, 20}; +static const char liblte_rrc_dl_bandwidth_text[LIBLTE_RRC_DL_BANDWIDTH_N_ITEMS][20] = { "1.4", "3", "5", "10", + "15", "20", "SPARE1", "SPARE2"}; +static const double liblte_rrc_dl_bandwidth_num[LIBLTE_RRC_DL_BANDWIDTH_N_ITEMS] = {1.4, 3, 5, 10, 15, 20, 0, 0}; // Structs typedef struct{ LIBLTE_RRC_PHICH_CONFIG_STRUCT phich_config; @@ -5648,9 +6709,57 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_dl_ccch_msg(LIBLTE_BIT_MSG_STRUCT *m *********************************************************************/ // Defines // Enums +typedef enum{ + LIBLTE_RRC_DL_DCCH_MSG_TYPE_CSFB_PARAMS_RESP_CDMA2000 = 0, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_DL_INFO_TRANSFER, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_HANDOVER_FROM_EUTRA_PREP_REQ, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_MOBILITY_FROM_EUTRA_COMMAND, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RECONFIG, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RELEASE, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_SECURITY_MODE_COMMAND, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_CAPABILITY_ENQUIRY, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_COUNTER_CHECK, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_INFO_REQ, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_LOGGED_MEASUREMENTS_CONFIG, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_RN_RECONFIG, + LIBLTE_RRC_DL_DCCH_MSG_TYPE_N_ITEMS, +}LIBLTE_RRC_DL_DCCH_MSG_TYPE_ENUM; +static const char liblte_rrc_dl_dcch_msg_type_text[LIBLTE_RRC_DL_DCCH_MSG_TYPE_N_ITEMS][100] = {"CSFB Parameters Response CDMA2000", + "DL Information Transfer", + "Handover From EUTRA Preparation Request", + "Mobility From EUTRA Command", + "RRC Connection Reconfiguration", + "RRC Connection Release", + "Security Mode Command", + "UE Capability Enquiry", + "Counter Check", + "UE Information Request", + "Logged Measurements Configuration", + "RN Reconfiguration"}; // Structs -// Functions -// FIXME +typedef union{ + LIBLTE_RRC_CSFB_PARAMETERS_RESPONSE_CDMA2000_STRUCT csfb_params_resp_cdma2000; + LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT dl_info_transfer; + LIBLTE_RRC_HANDOVER_FROM_EUTRA_PREPARATION_REQUEST_STRUCT handover_from_eutra_prep_req; + LIBLTE_RRC_MOBILITY_FROM_EUTRA_COMMAND_STRUCT mobility_from_eutra_cmd; + LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT rrc_con_reconfig; + LIBLTE_RRC_CONNECTION_RELEASE_STRUCT rrc_con_release; + LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT security_mode_cmd; + LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT ue_cap_enquiry; + LIBLTE_RRC_COUNTER_CHECK_STRUCT counter_check; + LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT ue_info_req; + LIBLTE_RRC_LOGGED_MEASUREMENTS_CONFIGURATION_STRUCT logged_measurements_config; + LIBLTE_RRC_RN_RECONFIGURATION_STRUCT rn_reconfig; +}LIBLTE_RRC_DL_DCCH_MSG_TYPE_UNION; +typedef struct{ + LIBLTE_RRC_DL_DCCH_MSG_TYPE_UNION msg; + LIBLTE_RRC_DL_DCCH_MSG_TYPE_ENUM msg_type; +}LIBLTE_RRC_DL_DCCH_MSG_STRUCT; +// Functions +LIBLTE_ERROR_ENUM liblte_rrc_pack_dl_dcch_msg(LIBLTE_RRC_DL_DCCH_MSG_STRUCT *dl_dcch_msg, + LIBLTE_BIT_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_dl_dcch_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_DL_DCCH_MSG_STRUCT *dl_dcch_msg); /********************************************************************* Message Name: UL CCCH Message diff --git a/liblte/hdr/liblte_security.h b/liblte/hdr/liblte_security.h new file mode 100755 index 0000000..e3aaa2a --- /dev/null +++ b/liblte/hdr/liblte_security.h @@ -0,0 +1,266 @@ +/******************************************************************************* + + Copyright 2014 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: liblte_security.h + + Description: Contains all the definitions for the LTE security algorithm + library. + + Revision History + ---------- ------------- -------------------------------------------- + 08/03/2014 Ben Wojtowicz Created file. + 09/03/2014 Ben Wojtowicz Added key generation and EIA2. + +*******************************************************************************/ + +#ifndef __LIBLTE_SECURITY_H__ +#define __LIBLTE_SECURITY_H__ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "liblte_common.h" + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + DECLARATIONS +*******************************************************************************/ + +/********************************************************************* + Name: liblte_security_generate_k_asme + + Description: Generate the security key Kasme. + + Document Reference: 33.401 v10.0.0 Annex A.2 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_security_generate_k_asme(uint8 *ck, + uint8 *ik, + uint8 *ak, + uint8 *sqn, + uint16 mcc, + uint16 mnc, + uint8 *k_asme); + +/********************************************************************* + Name: liblte_security_generate_k_enb + + Description: Generate the security key Kenb. + + Document Reference: 33.401 v10.0.0 Annex A.2 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_security_generate_k_enb(uint8 *k_asme, + uint32 nas_count, + uint8 *k_enb); + +/********************************************************************* + Name: liblte_security_generate_k_nas + + Description: Generate the NAS security keys KNASenc and KNASint. + + Document Reference: 33.401 v10.0.0 Annex A.2 +*********************************************************************/ +// Defines +// Enums +typedef enum{ + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_EEA0 = 0, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_128_EEA1, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_128_EEA2, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_N_ITEMS, +}LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM; +static const char liblte_security_ciphering_algorithm_id_text[LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_N_ITEMS][20] = {"EEA0", + "128-EEA1", + "128-EEA2"}; +typedef enum{ + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_EIA0 = 0, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_128_EIA1, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_128_EIA2, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_N_ITEMS, +}LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM; +static const char liblte_security_integrity_algorithm_id_text[LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = {"EIA0", + "128-EIA1", + "128-EIA2"}; +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_security_generate_k_nas(uint8 *k_asme, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8 *k_nas_enc, + uint8 *k_nas_int); + +/********************************************************************* + Name: liblte_security_generate_k_rrc + + Description: Generate the RRC security keys KRRCenc and KRRCint. + + Document Reference: 33.401 v10.0.0 Annex A.2 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_security_generate_k_rrc(uint8 *k_enb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8 *k_rrc_enc, + uint8 *k_rrc_int); + +/********************************************************************* + Name: liblte_security_generate_k_up + + Description: Generate the user plane security keys KUPenc and + KUPint. + + Document Reference: 33.401 v10.0.0 Annex A.2 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_security_generate_k_up(uint8 *k_enb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8 *k_up_enc, + uint8 *k_up_int); + +/********************************************************************* + Name: liblte_security_128_eia2 + + Description: 128-bit integrity algorithm EIA2. + + Document Reference: 33.401 v10.0.0 Annex B.2.3 + 33.102 v10.0.0 Section 6.5.4 + RFC4493 +*********************************************************************/ +// Defines +#define LIBLTE_SECURITY_DIRECTION_UPLINK 0 +#define LIBLTE_SECURITY_DIRECTION_DOWNLINK 1 +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_security_128_eia2(uint8 *key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8 *msg, + uint32 msg_len, + uint8 *mac); +LIBLTE_ERROR_ENUM liblte_security_128_eia2(uint8 *key, + uint32 count, + uint8 bearer, + uint8 direction, + LIBLTE_BIT_MSG_STRUCT *msg, + uint8 *mac); + +/********************************************************************* + Name: liblte_security_milenage_f1 + + Description: Milenage security function F1. Computes network + authentication code MAC-A from key K, random + challenge RAND, sequence number SQN, and + authentication management field AMF. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8 *k, + uint8 *rand, + uint8 *sqn, + uint8 *amf, + uint8 *mac_a); + +/********************************************************************* + Name: liblte_security_milenage_f1_star + + Description: Milenage security function F1*. Computes resynch + authentication code MAC-S from key K, random + challenge RAND, sequence number SQN, and + authentication management field AMF. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_security_milenage_f1_star(uint8 *k, + uint8 *rand, + uint8 *sqn, + uint8 *amf, + uint8 *mac_s); + +/********************************************************************* + Name: liblte_security_milenage_f2345 + + Description: Milenage security functions F2, F3, F4, and F5. + Computes response RES, confidentiality key CK, + integrity key IK, and anonymity key AK from random + challenge RAND. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_security_milenage_f2345(uint8 *k, + uint8 *rand, + uint8 *res, + uint8 *ck, + uint8 *ik, + uint8 *ak); + +/********************************************************************* + Name: liblte_security_milenage_f5_star + + Description: Milenage security function F5*. Computes resynch + anonymity key AK from key K and random challenge + RAND. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +LIBLTE_ERROR_ENUM liblte_security_milenage_f5_star(uint8 *k, + uint8 *rand, + uint8 *ak); + +#endif /* __LIBLTE_SECURITY_H__ */ diff --git a/liblte/manual_tests/Makefile b/liblte/manual_tests/Makefile new file mode 100755 index 0000000..01a7f6b --- /dev/null +++ b/liblte/manual_tests/Makefile @@ -0,0 +1,2 @@ +all: + g++ -I../hdr/ -I../../cmn_hdr ../src/liblte_phy.cc ../src/liblte_mac.cc ../src/liblte_rrc.cc ../src/liblte_common.cc ratematch_test.cc -o ratematch_test -lfftw3f -litpp diff --git a/liblte/manual_tests/ratematch_test.cc b/liblte/manual_tests/ratematch_test.cc new file mode 100755 index 0000000..d9f052e --- /dev/null +++ b/liblte/manual_tests/ratematch_test.cc @@ -0,0 +1,251 @@ +/******************************************************************************* + + Copyright 2015 Ziming He (ziming.he@pathintel.com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + +/********************************************************************* + Name: ratematch.cc + + Description: unit tests for openlte turbo rate matching/unmatching + compile and run under path: /openlte-code/tests/ + complile: make -f Makefile_ratematch + run: ./ratematch + Author: Ziming He + Company: Path Intelligence Limited, Portsmouth, England, UK + +*********************************************************************/ + +#include "liblte_phy.h" +#include "itpp/itcomm.h" +using namespace itpp; +using std::cout; +using std::endl; + +uint32 TURBO_K_TABLE[188] = { 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, + 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, + 200, 208, 216, 224, 232, 240, 248, 256, 264, 272, + 280, 288, 296, 304, 312, 320, 328, 336, 344, 352, + 360, 368, 376, 384, 392, 400, 408, 416, 424, 432, + 440, 448, 456, 464, 472, 480, 488, 496, 504, 512, + 528, 544, 560, 576, 592, 608, 624, 640, 656, 672, + 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, + 848, 864, 880, 896, 912, 928, 944, 960, 976, 992, + 1008,1024,1056,1088,1120,1152,1184,1216,1248,1280, + 1312,1344,1376,1408,1440,1472,1504,1536,1568,1600, + 1632,1664,1696,1728,1760,1792,1824,1856,1888,1920, + 1952,1984,2016,2048,2112,2176,2240,2304,2368,2432, + 2496,2560,2624,2688,2752,2816,2880,2944,3008,3072, + 3136,3200,3264,3328,3392,3456,3520,3584,3648,3712, + 3776,3840,3904,3968,4032,4096,4160,4224,4288,4352, + 4416,4480,4544,4608,4672,4736,4800,4864,4928,4992, + 5056,5120,5184,5248,5312,5376,5440,5504,5568,5632, + 5696,5760,5824,5888,5952,6016,6080,6144}; + +int main(void) +{ + + int i, k, g; + LIBLTE_PHY_STRUCT *phy_struct_tx; + phy_struct_tx = (LIBLTE_PHY_STRUCT *)malloc(sizeof(LIBLTE_PHY_STRUCT)); + LIBLTE_PHY_STRUCT *phy_struct_rx; + phy_struct_rx = (LIBLTE_PHY_STRUCT *)malloc(sizeof(LIBLTE_PHY_STRUCT)); + uint32 N_b_bits; // N_b_bits=N_c_bits=K for single codeblock case + uint32 D; // defined in 36.212 5.1.4.1.1 + uint32 N_tx_d_bits; // number of transmitted d bits + uint32 tx_mode = 2; // transmission mode + LIBLTE_PHY_CHAN_TYPE_ENUM chan_type = LIBLTE_PHY_CHAN_TYPE_DLSCH; + uint32 rv_idx = 0; // redundancy version, either 0, 1, 2 or 3 + uint32 N_soft = 250368; // N_{soft} cat 1 UE + uint32 M_dl_harq = 4; // 8 for FDD-LTE + uint32 N_codeblocks = 1; // number of code blocks + uint32 cb = 0; // there is only 1 codeblock + uint32 G; // minimum value >= 3*D, N_bits_tot (defined in 36.212 5.1.4.1.2, total available bits for one transport block) + uint32 N_l = 2; // 2 for transmit diversity + uint32 Q_m = 2; // 2 for QPSK + uint32 G_prime; // G' defined in 36.212 5.1.4.1.2 + uint32 lambda; // gamma defined in 36.212 5.1.4.1.2 + uint32 N_fill_bits; // not used + uint32 N_rx_d_bits; // need to be determined at receiver + BERC berc_d_bits; // d bits transmission error evaluation + uint32 count=0; // test fail counter + + // for evaluating K_w and N_cb in 36.212 5.1.4.1.2 + uint32 R_tc_sb; + uint32 K_pi; + uint32 K_w; + uint32 K_mimo; + uint32 N_ir; + uint32 N_cb; + + for (k=0; k<188; k++){ // turbo code internal interleaver size + + for (g=0; g<1; g++){ // try different values of G = 3*D+g + + // generate transmitted bits + N_b_bits = TURBO_K_TABLE[k]; + D = N_b_bits + 4; + N_tx_d_bits = 3*D; + bvec dlsch_tx_d_bits_itpp(N_tx_d_bits); + RNG_randomize(); + dlsch_tx_d_bits_itpp = randb(N_tx_d_bits); + for (i=0; idlsch_tx_d_bits[i] = int(dlsch_tx_d_bits_itpp(i)); + } + + G = 3*D + g; // min=3*D, otherwise causes error in d bits transmission + + // calculate K_w and N_cb + R_tc_sb = 0; + while(D > (32*R_tc_sb)) + { + R_tc_sb++; + } + K_pi = 32*R_tc_sb; + K_w = 3*K_pi; + if(tx_mode == 3 || + tx_mode == 4 || + tx_mode == 8 || + tx_mode == 9) + { + K_mimo = 2; + }else{ + K_mimo = 1; + } + if(M_dl_harq < 8) + { + N_ir = N_soft/(K_mimo*M_dl_harq); + }else{ + N_ir = N_soft/(K_mimo*8); + } + if(LIBLTE_PHY_CHAN_TYPE_DLSCH == chan_type || + LIBLTE_PHY_CHAN_TYPE_PCH == chan_type) + { + if((N_ir/N_codeblocks) < K_w) + { + N_cb = N_ir/N_codeblocks; + }else{ + N_cb = K_w; + } + }else{ + N_cb = K_w; + } + if (N_cb != K_w){ + cout << "N_cb is not equal to K_w, skips the tests when K = " << N_b_bits << endl; + break; + } + + // Determine E (number of e bits for a codeblock) + G_prime = G/(N_l*Q_m); + lambda = G_prime % N_codeblocks; + if(cb <= (N_codeblocks - lambda - 1)) + { + phy_struct_tx->dlsch_N_e_bits[cb] = N_l*Q_m*(G_prime/N_codeblocks); + }else{ + phy_struct_tx->dlsch_N_e_bits[cb] = N_l*Q_m*(uint32)ceilf((float)G_prime/(float)N_codeblocks); + } + + liblte_phy_rate_match_turbo(phy_struct_tx, + phy_struct_tx->dlsch_tx_d_bits, + N_tx_d_bits, + N_codeblocks, + tx_mode, + N_soft, + M_dl_harq, + LIBLTE_PHY_CHAN_TYPE_DLSCH, + rv_idx, + phy_struct_tx->dlsch_N_e_bits[cb], + phy_struct_tx->dlsch_tx_e_bits[cb]); + + // error-free reception of e bits + // number of e bits (E) and e bits are obtained after code_block_deconcatenation + for (i=0; idlsch_N_e_bits[cb]; i++){ + if(phy_struct_tx->dlsch_tx_e_bits[cb][i] == 0){ + phy_struct_rx->dlsch_rx_e_bits[cb][i] = 1.0; + }else{ + phy_struct_rx->dlsch_rx_e_bits[cb][i] = -1.0; + } + } + phy_struct_rx->dlsch_N_e_bits[cb] = phy_struct_tx->dlsch_N_e_bits[cb]; + + // determine N_codeblocks and number of b, c, d bits for a codeblock + memset(phy_struct_rx->dlsch_b_bits, 0, sizeof(uint8)*N_b_bits); // N_b_bits obtained from tbs+24, where tbs known at the receiver + liblte_phy_code_block_segmentation(phy_struct_rx->dlsch_b_bits, + N_b_bits, + &N_codeblocks, // output, also determined by code_block_deconcatenation + &N_fill_bits, + phy_struct_rx->dlsch_c_bits[0], // output (not used) + LIBLTE_PHY_MAX_CODE_BLOCK_SIZE, + phy_struct_rx->dlsch_N_c_bits); // output + N_rx_d_bits = 3*(phy_struct_rx->dlsch_N_c_bits[cb]+4); + + // generate 0 bits to determine NULL bit locations in virtual circular buffer wk + for (i=0; idlsch_tx_d_bits[i] = 0; + } + liblte_phy_rate_unmatch_turbo(phy_struct_rx, + phy_struct_rx->dlsch_rx_e_bits[cb], // input + phy_struct_rx->dlsch_N_e_bits[cb], // E, input + phy_struct_rx->dlsch_tx_d_bits, //all 0 bits input + N_rx_d_bits/3, // = D, input + N_codeblocks, // input + tx_mode, // input + N_soft, // input + M_dl_harq, // input + LIBLTE_PHY_CHAN_TYPE_DLSCH, // input + rv_idx,// input + phy_struct_rx->dlsch_rx_d_bits, // output + &N_rx_d_bits); //=3*D + // ========================================================================================= + + // compares tx-rx d bits + bvec dlsch_rx_d_bits_itpp_tmp(N_rx_d_bits); // output d_bits from rate_unmatch_turbo + for (i=0; idlsch_rx_d_bits[i] > 0.0){ + dlsch_rx_d_bits_itpp_tmp(i) = bin(0); + }else{ + dlsch_rx_d_bits_itpp_tmp(i) = bin(1); + } + } + bvec dlsch_rx_d_bits_itpp(N_rx_d_bits); // transfer to match the tx d_bit format + for (i=0; i < D; i++){ + dlsch_rx_d_bits_itpp(i) = dlsch_rx_d_bits_itpp_tmp(3*i); + dlsch_rx_d_bits_itpp(i+D) = dlsch_rx_d_bits_itpp_tmp(3*i+1); + dlsch_rx_d_bits_itpp(i+2*D) = dlsch_rx_d_bits_itpp_tmp(3*i+2); + } + berc_d_bits.clear(); + berc_d_bits.count(dlsch_tx_d_bits_itpp, dlsch_rx_d_bits_itpp); + if(berc_d_bits.get_errors() == 0){ + // cout << "test pass for K = " << N_b_bits << "; G = " << G << "; K_w = " << K_w << "; N_cb = " << N_cb << endl; + }else{ + cout << "test fails for K = " << N_b_bits << "; G = " << G << "; K_w = " << K_w << "; N_cb = " << N_cb << "; BER = " << berc_d_bits.get_errorrate() << endl; + count++; + } + + } // g loop + + } // k loop + + if(count == 0){ + cout << "all tests pass !! " << endl; + }else{ + // cout << "some tests fails !! " << endl; + } + + return 0; + +} diff --git a/liblte/src/liblte_common.cc b/liblte/src/liblte_common.cc new file mode 100755 index 0000000..012fbd3 --- /dev/null +++ b/liblte/src/liblte_common.cc @@ -0,0 +1,93 @@ +/******************************************************************************* + + Copyright 2014 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: liblte_common.cc + + Description: Contains all the implementations for the LTE common library. + + Revision History + ---------- ------------- -------------------------------------------- + 08/03/2014 Ben Wojtowicz Created file. + 11/29/2014 Ben Wojtowicz Added liblte prefix to value_2_bits and + bits_2_value. + +*******************************************************************************/ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "liblte_common.h" + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + GLOBAL VARIABLES +*******************************************************************************/ + + +/******************************************************************************* + FUNCTIONS +*******************************************************************************/ + +/********************************************************************* + Name: liblte_value_2_bits + + Description: Converts a value to a bit string +*********************************************************************/ +void liblte_value_2_bits(uint32 value, + uint8 **bits, + uint32 N_bits) +{ + uint32 i; + + for(i=0; i> (N_bits-i-1)) & 0x1; + } + *bits += N_bits; +} + +/********************************************************************* + Name: liblte_bits_2_value + + Description: Converts a bit string to a value +*********************************************************************/ +uint32 liblte_bits_2_value(uint8 **bits, + uint32 N_bits) +{ + uint32 value = 0; + uint32 i; + + for(i=0; i= ul_earfcn) + liblte_interface_last_ul_earfcn[25] >= ul_earfcn) { // FDD dl_earfcn = ul_earfcn - 18000; @@ -148,16 +151,17 @@ uint32 liblte_interface_ul_earfcn_to_frequency(uint16 ul_earfcn) 1749900000, 1710000000, 1427900000, 699000000, 777000000, 788000000, 704000000, 815000000, 830000000, 832000000, 1447900000, 3410000000UL, - 2000000000, 1626500000, 1850000000, 1900000000, - 2010000000, 1850000000, 1930000000, 1910000000, - 2570000000UL, 1880000000, 2300000000UL, 2496000000UL, - 3400000000UL, 3600000000UL}; + 2000000000, 1626500000, 1850000000, 814000000, + 807000000, 703000000, 1900000000, 2010000000, + 1850000000, 1930000000, 1910000000, 2570000000UL, + 1880000000, 2300000000UL, 2496000000UL, 3400000000UL, + 3600000000UL}; uint32 i; uint16 N_offs_ul[LIBLTE_INTERFACE_BAND_N_ITEMS] = {18000, 18600, 19200, 19950, 20400, 20650, 20750, 21450, 21800, 22150, 22750, 23010, 23180, 23280, 23730, 23850, - 24000, 24150, 24450, 24600, 25500, 25700, 26040, 36000, - 36200, 36350, 36950, 37550, 37750, 38250, 38650, 39650, - 41590, 43590}; + 24000, 24150, 24450, 24600, 25500, 25700, 26040, 26690, + 27040, 27210, 36000, 36200, 36350, 36950, 37550, 37750, + 38250, 38650, 39650, 41590, 43590}; for(i=0; i= dl_earfcn) + liblte_interface_last_dl_earfcn[25] >= dl_earfcn) { // FDD ul_earfcn = dl_earfcn + 18000; diff --git a/liblte/src/liblte_mac.cc b/liblte/src/liblte_mac.cc old mode 100644 new mode 100755 index 4dbec48..fd41120 --- a/liblte/src/liblte_mac.cc +++ b/liblte/src/liblte_mac.cc @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013-2014 Ben Wojtowicz + Copyright 2013-2016 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -29,6 +29,13 @@ 05/04/2014 Ben Wojtowicz Added control element handling. 06/15/2014 Ben Wojtowicz Added support for padding LCIDs and breaking out max and min buffer sizes for BSRs. + 08/03/2014 Ben Wojtowicz Using the common value_2_bits and + bits_2_value functions. + 11/29/2014 Ben Wojtowicz Using byte message struct for SDUs. + 02/15/2015 Ben Wojtowicz Removed FIXMEs for transparent mode and mcs. + 03/11/2015 Ben Wojtowicz Fixed long BSR CE and added extended power + headroom CE support. + 07/03/2016 Ben Wojtowicz Fixed extended power headroom CE. *******************************************************************************/ @@ -52,43 +59,22 @@ GLOBAL VARIABLES *******************************************************************************/ -uint32 truncated_short_bsr_max_buffer_size[64] = { 0, 10, 12, 14, 17, 19, 22, 26, - 31, 36, 42, 49, 57, 67, 78, 91, - 107, 125, 146, 171, 200, 234, 274, 321, - 376, 440, 515, 603, 706, 826, 967, 1132, - 1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, - 4677, 5476, 6411, 7505, 8787, 10287, 12043, 14099, - 16507, 19325, 22624, 26487, 31009, 36304, 42502, 49759, - 58255, 68201, 79864, 93479, 109439, 128125, 150000, 150000}; -uint32 truncated_short_bsr_min_buffer_size[64] = { 0, 0, 10, 12, 14, 17, 19, 22, - 26, 31, 36, 42, 49, 57, 67, 78, - 91, 107, 125, 146, 171, 200, 234, 274, - 321, 376, 440, 515, 603, 706, 826, 967, - 1132, 1326, 1552, 1817, 2127, 2490, 2915, 3413, - 3995, 4677, 5476, 6411, 7505, 8787, 10287, 12043, - 14099, 16507, 19325, 22624, 26487, 31009, 36304, 42502, - 49759, 58255, 68201, 79864, 93479, 109439, 128125, 150000}; - -/******************************************************************************* - LOCAL FUNCTION PROTOTYPES -*******************************************************************************/ - -/********************************************************************* - Name: mac_value_2_bits - - Description: Converts a value to a bit string -*********************************************************************/ -void mac_value_2_bits(uint32 value, - uint8 **bits, - uint32 N_bits); - -/********************************************************************* - Name: mac_bits_2_value - - Description: Converts a bit string to a value -*********************************************************************/ -uint32 mac_bits_2_value(uint8 **bits, - uint32 N_bits); +uint32 bsr_max_buffer_size[64] = { 0, 10, 12, 14, 17, 19, 22, 26, + 31, 36, 42, 49, 57, 67, 78, 91, + 107, 125, 146, 171, 200, 234, 274, 321, + 376, 440, 515, 603, 706, 826, 967, 1132, + 1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, + 4677, 5476, 6411, 7505, 8787, 10287, 12043, 14099, + 16507, 19325, 22624, 26487, 31009, 36304, 42502, 49759, + 58255, 68201, 79864, 93479, 109439, 128125, 150000, 150000}; +uint32 bsr_min_buffer_size[64] = { 0, 0, 10, 12, 14, 17, 19, 22, + 26, 31, 36, 42, 49, 57, 67, 78, + 91, 107, 125, 146, 171, 200, 234, 274, + 321, 376, 440, 515, 603, 706, 826, 967, + 1132, 1326, 1552, 1817, 2127, 2490, 2915, 3413, + 3995, 4677, 5476, 6411, 7505, 8787, 10287, 12043, + 14099, 16507, 19325, 22624, 26487, 31009, 36304, 42502, + 49759, 58255, 68201, 79864, 93479, 109439, 128125, 150000}; /******************************************************************************* CONTROL ELEMENT FUNCTIONS @@ -111,19 +97,19 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_truncated_bsr_ce(LIBLTE_MAC_TRUNCATED_BSR_CE_S if(truncated_bsr != NULL && ce_ptr != NULL) { - mac_value_2_bits(truncated_bsr->lcg_id, ce_ptr, 2); + liblte_value_2_bits(truncated_bsr->lcg_id, ce_ptr, 2); for(i=0; i<64; i++) { - if(truncated_bsr->max_buffer_size > truncated_short_bsr_min_buffer_size[i] && - truncated_bsr->max_buffer_size <= truncated_short_bsr_max_buffer_size[i]) + if(truncated_bsr->min_buffer_size > bsr_min_buffer_size[i] && + truncated_bsr->max_buffer_size <= bsr_max_buffer_size[i]) { - mac_value_2_bits(i, ce_ptr, 6); + liblte_value_2_bits(i, ce_ptr, 6); break; } } if(i == 64) { - mac_value_2_bits(63, ce_ptr, 6); + liblte_value_2_bits(63, ce_ptr, 6); } err = LIBLTE_SUCCESS; @@ -140,10 +126,10 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_truncated_bsr_ce(uint8 if(ce_ptr != NULL && truncated_bsr != NULL) { - truncated_bsr->lcg_id = mac_bits_2_value(ce_ptr, 2); - buffer_size_idx = mac_bits_2_value(ce_ptr, 6); - truncated_bsr->max_buffer_size = truncated_short_bsr_max_buffer_size[buffer_size_idx]; - truncated_bsr->min_buffer_size = truncated_short_bsr_min_buffer_size[buffer_size_idx]; + truncated_bsr->lcg_id = liblte_bits_2_value(ce_ptr, 2); + buffer_size_idx = liblte_bits_2_value(ce_ptr, 6); + truncated_bsr->max_buffer_size = bsr_max_buffer_size[buffer_size_idx]; + truncated_bsr->min_buffer_size = bsr_min_buffer_size[buffer_size_idx]; err = LIBLTE_SUCCESS; } @@ -182,14 +168,42 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_long_bsr_ce(LIBLTE_MAC_LONG_BSR_CE_STRUCT *lo uint8 **ce_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + uint32 buffer_size_0; + uint32 buffer_size_1; + uint32 buffer_size_2; + uint32 buffer_size_3; if(long_bsr != NULL && ce_ptr != NULL) { - mac_value_2_bits(long_bsr->buffer_size_0, ce_ptr, 6); - mac_value_2_bits(long_bsr->buffer_size_1, ce_ptr, 6); - mac_value_2_bits(long_bsr->buffer_size_2, ce_ptr, 6); - mac_value_2_bits(long_bsr->buffer_size_3, ce_ptr, 6); + for(i=0; i<64; i++) + { + if(long_bsr->min_buffer_size_0 > bsr_min_buffer_size[i] && + long_bsr->max_buffer_size_0 <= bsr_max_buffer_size[i]) + { + buffer_size_0 = i; + } + if(long_bsr->min_buffer_size_1 > bsr_min_buffer_size[i] && + long_bsr->max_buffer_size_1 <= bsr_max_buffer_size[i]) + { + buffer_size_1 = i; + } + if(long_bsr->min_buffer_size_2 > bsr_min_buffer_size[i] && + long_bsr->max_buffer_size_2 <= bsr_max_buffer_size[i]) + { + buffer_size_2 = i; + } + if(long_bsr->min_buffer_size_3 > bsr_min_buffer_size[i] && + long_bsr->max_buffer_size_3 <= bsr_max_buffer_size[i]) + { + buffer_size_3 = i; + } + } + liblte_value_2_bits(buffer_size_0, ce_ptr, 6); + liblte_value_2_bits(buffer_size_1, ce_ptr, 6); + liblte_value_2_bits(buffer_size_2, ce_ptr, 6); + liblte_value_2_bits(buffer_size_3, ce_ptr, 6); err = LIBLTE_SUCCESS; } @@ -200,14 +214,26 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_long_bsr_ce(uint8 ** LIBLTE_MAC_LONG_BSR_CE_STRUCT *long_bsr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 buffer_size_0; + uint32 buffer_size_1; + uint32 buffer_size_2; + uint32 buffer_size_3; if(ce_ptr != NULL && long_bsr != NULL) { - long_bsr->buffer_size_0 = mac_bits_2_value(ce_ptr, 6); - long_bsr->buffer_size_1 = mac_bits_2_value(ce_ptr, 6); - long_bsr->buffer_size_2 = mac_bits_2_value(ce_ptr, 6); - long_bsr->buffer_size_3 = mac_bits_2_value(ce_ptr, 6); + buffer_size_0 = liblte_bits_2_value(ce_ptr, 6); + buffer_size_1 = liblte_bits_2_value(ce_ptr, 6); + buffer_size_2 = liblte_bits_2_value(ce_ptr, 6); + buffer_size_3 = liblte_bits_2_value(ce_ptr, 6); + long_bsr->max_buffer_size_0 = bsr_max_buffer_size[buffer_size_0]; + long_bsr->min_buffer_size_0 = bsr_min_buffer_size[buffer_size_0]; + long_bsr->max_buffer_size_1 = bsr_max_buffer_size[buffer_size_1]; + long_bsr->min_buffer_size_1 = bsr_min_buffer_size[buffer_size_1]; + long_bsr->max_buffer_size_2 = bsr_max_buffer_size[buffer_size_2]; + long_bsr->min_buffer_size_2 = bsr_min_buffer_size[buffer_size_2]; + long_bsr->max_buffer_size_3 = bsr_max_buffer_size[buffer_size_3]; + long_bsr->min_buffer_size_3 = bsr_min_buffer_size[buffer_size_3]; err = LIBLTE_SUCCESS; } @@ -230,7 +256,7 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_c_rnti_ce(LIBLTE_MAC_C_RNTI_CE_STRUCT *c_rnti if(c_rnti != NULL && ce_ptr != NULL) { - mac_value_2_bits(c_rnti->c_rnti, ce_ptr, 16); + liblte_value_2_bits(c_rnti->c_rnti, ce_ptr, 16); err = LIBLTE_SUCCESS; } @@ -245,7 +271,7 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_c_rnti_ce(uint8 **ce_p if(ce_ptr != NULL && c_rnti != NULL) { - c_rnti->c_rnti = mac_bits_2_value(ce_ptr, 16); + c_rnti->c_rnti = liblte_bits_2_value(ce_ptr, 16); err = LIBLTE_SUCCESS; } @@ -277,8 +303,8 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_ue_contention_resolution_id_ce(LIBLTE_MAC_UE_C if(ue_con_res_id != NULL && ce_ptr != NULL) { - mac_value_2_bits((uint32)(ue_con_res_id->id >> 32), ce_ptr, 16); - mac_value_2_bits((uint32)(ue_con_res_id->id), ce_ptr, 32); + liblte_value_2_bits((uint32)(ue_con_res_id->id >> 32), ce_ptr, 16); + liblte_value_2_bits((uint32)(ue_con_res_id->id), ce_ptr, 32); err = LIBLTE_SUCCESS; } @@ -293,8 +319,8 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_ue_contention_resolution_id_ce(uint8 if(ce_ptr != NULL && ue_con_res_id != NULL) { - ue_con_res_id->id = (uint64)mac_bits_2_value(ce_ptr, 16) << 32; - ue_con_res_id->id |= (uint64)mac_bits_2_value(ce_ptr, 32); + ue_con_res_id->id = (uint64)liblte_bits_2_value(ce_ptr, 16) << 32; + ue_con_res_id->id |= (uint64)liblte_bits_2_value(ce_ptr, 32); err = LIBLTE_SUCCESS; } @@ -317,9 +343,9 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_ta_command_ce(LIBLTE_MAC_TA_COMMAND_CE_STRUCT if(ta_command != NULL && ce_ptr != NULL) { - mac_value_2_bits(0, ce_ptr, 1); // R - mac_value_2_bits(0, ce_ptr, 1); // R - mac_value_2_bits(ta_command->ta, ce_ptr, 6); + liblte_value_2_bits(0, ce_ptr, 1); // R + liblte_value_2_bits(0, ce_ptr, 1); // R + liblte_value_2_bits(ta_command->ta, ce_ptr, 6); err = LIBLTE_SUCCESS; } @@ -334,9 +360,9 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_ta_command_ce(uint8 if(ce_ptr != NULL && ta_command != NULL) { - mac_bits_2_value(ce_ptr, 1); // R - mac_bits_2_value(ce_ptr, 1); // R - ta_command->ta = mac_bits_2_value(ce_ptr, 6); + liblte_bits_2_value(ce_ptr, 1); // R + liblte_bits_2_value(ce_ptr, 1); // R + ta_command->ta = liblte_bits_2_value(ce_ptr, 6); err = LIBLTE_SUCCESS; } @@ -359,9 +385,9 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_power_headroom_ce(LIBLTE_MAC_POWER_HEADROOM_CE if(power_headroom != NULL && ce_ptr != NULL) { - mac_value_2_bits(0, ce_ptr, 1); // R - mac_value_2_bits(0, ce_ptr, 1); // R - mac_value_2_bits(power_headroom->ph, ce_ptr, 6); + liblte_value_2_bits(0, ce_ptr, 1); // R + liblte_value_2_bits(0, ce_ptr, 1); // R + liblte_value_2_bits(power_headroom->ph, ce_ptr, 6); err = LIBLTE_SUCCESS; } @@ -376,9 +402,9 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_power_headroom_ce(uint8 if(ce_ptr != NULL && power_headroom != NULL) { - mac_bits_2_value(ce_ptr, 1); // R - mac_bits_2_value(ce_ptr, 1); // R - power_headroom->ph = mac_bits_2_value(ce_ptr, 6); + liblte_bits_2_value(ce_ptr, 1); // R + liblte_bits_2_value(ce_ptr, 1); // R + power_headroom->ph = liblte_bits_2_value(ce_ptr, 6); err = LIBLTE_SUCCESS; } @@ -396,14 +422,131 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_power_headroom_ce(uint8 LIBLTE_ERROR_ENUM liblte_mac_pack_ext_power_headroom_ce(LIBLTE_MAC_EXT_POWER_HEADROOM_CE_STRUCT *ext_power_headroom, uint8 **ce_ptr) { - // FIXME - return(LIBLTE_ERROR_INVALID_INPUTS); + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ext_power_headroom != NULL && + ce_ptr != NULL) + { + // SCell Presence Indicators + for(i=0; i<7; i++) + { + liblte_value_2_bits(ext_power_headroom->scell_present[6-i], ce_ptr, 1); + } + liblte_value_2_bits(0, ce_ptr, 1); // R + + // PCell Type 2 + if(ext_power_headroom->pcell_type_2_present) + { + liblte_value_2_bits(ext_power_headroom->pcell_type_2.p, ce_ptr, 1); + liblte_value_2_bits(ext_power_headroom->pcell_type_2.v, ce_ptr, 1); + liblte_value_2_bits(ext_power_headroom->pcell_type_2.ph, ce_ptr, 6); + if(!ext_power_headroom->pcell_type_2.v) + { + liblte_value_2_bits(0, ce_ptr, 1); // R + liblte_value_2_bits(0, ce_ptr, 1); // R + liblte_value_2_bits(ext_power_headroom->pcell_type_2.p_cmax, ce_ptr, 6); + } + } + + // PCell Type 1 + liblte_value_2_bits(ext_power_headroom->pcell_type_1.p, ce_ptr, 1); + liblte_value_2_bits(ext_power_headroom->pcell_type_1.v, ce_ptr, 1); + liblte_value_2_bits(ext_power_headroom->pcell_type_1.ph, ce_ptr, 6); + if(!ext_power_headroom->pcell_type_1.v) + { + liblte_value_2_bits(0, ce_ptr, 1); // R + liblte_value_2_bits(0, ce_ptr, 1); // R + liblte_value_2_bits(ext_power_headroom->pcell_type_1.p_cmax, ce_ptr, 6); + } + + // SCell + for(i=0; i<7; i++) + { + if(ext_power_headroom->scell_present[i]) + { + liblte_value_2_bits(ext_power_headroom->scell[i].p, ce_ptr, 1); + liblte_value_2_bits(ext_power_headroom->scell[i].v, ce_ptr, 1); + liblte_value_2_bits(ext_power_headroom->scell[i].ph, ce_ptr, 6); + if(!ext_power_headroom->scell[i].v) + { + liblte_value_2_bits(0, ce_ptr, 1); // R + liblte_value_2_bits(0, ce_ptr, 1); // R + liblte_value_2_bits(ext_power_headroom->scell[i].p_cmax, ce_ptr, 6); + } + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); } LIBLTE_ERROR_ENUM liblte_mac_unpack_ext_power_headroom_ce(uint8 **ce_ptr, + bool simultaneous_pucch_pusch, LIBLTE_MAC_EXT_POWER_HEADROOM_CE_STRUCT *ext_power_headroom) { - // FIXME - return(LIBLTE_ERROR_INVALID_INPUTS); + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ce_ptr != NULL && + ext_power_headroom != NULL) + { + // SCell Presence Indicators + for(i=0; i<7; i++) + { + ext_power_headroom->scell_present[6-i] = liblte_bits_2_value(ce_ptr, 1); + } + liblte_bits_2_value(ce_ptr, 1); // R + + // PCell Type 2 + ext_power_headroom->pcell_type_2_present = false; + if(simultaneous_pucch_pusch) + { + ext_power_headroom->pcell_type_2_present = true; + ext_power_headroom->pcell_type_2.p = liblte_bits_2_value(ce_ptr, 1); + ext_power_headroom->pcell_type_2.v = liblte_bits_2_value(ce_ptr, 1); + ext_power_headroom->pcell_type_2.ph = liblte_bits_2_value(ce_ptr, 6); + if(!ext_power_headroom->pcell_type_2.v) + { + liblte_bits_2_value(ce_ptr, 1); // R + liblte_bits_2_value(ce_ptr, 1); // R + ext_power_headroom->pcell_type_2.p_cmax = liblte_bits_2_value(ce_ptr, 6); + } + } + + // PCell Type 1 + ext_power_headroom->pcell_type_1.p = liblte_bits_2_value(ce_ptr, 1); + ext_power_headroom->pcell_type_1.v = liblte_bits_2_value(ce_ptr, 1); + ext_power_headroom->pcell_type_1.ph = liblte_bits_2_value(ce_ptr, 6); + if(!ext_power_headroom->pcell_type_1.v) + { + liblte_bits_2_value(ce_ptr, 1); // R + liblte_bits_2_value(ce_ptr, 1); // R + ext_power_headroom->pcell_type_1.p_cmax = liblte_bits_2_value(ce_ptr, 6); + } + + // SCell + for(i=0; i<7; i++) + { + if(ext_power_headroom->scell_present[i]) + { + ext_power_headroom->scell[i].p = liblte_bits_2_value(ce_ptr, 1); + ext_power_headroom->scell[i].v = liblte_bits_2_value(ce_ptr, 1); + ext_power_headroom->scell[i].ph = liblte_bits_2_value(ce_ptr, 6); + if(!ext_power_headroom->scell[i].v) + { + liblte_bits_2_value(ce_ptr, 1); // R + liblte_bits_2_value(ce_ptr, 1); // R + ext_power_headroom->scell[i].p_cmax = liblte_bits_2_value(ce_ptr, 6); + } + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); } /********************************************************************* @@ -425,8 +568,8 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_mch_scheduling_information_ce(LIBLTE_MAC_MCH_S { for(i=0; iN_items; i++) { - mac_value_2_bits(mch_sched_info->lcid[i], ce_ptr, 5); - mac_value_2_bits(mch_sched_info->stop_mch[i], ce_ptr, 11); + liblte_value_2_bits(mch_sched_info->lcid[i], ce_ptr, 5); + liblte_value_2_bits(mch_sched_info->stop_mch[i], ce_ptr, 11); } err = LIBLTE_SUCCESS; @@ -446,8 +589,8 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_mch_scheduling_information_ce(uint8 { for(i=0; iN_items; i++) { - mch_sched_info->lcid[i] = mac_bits_2_value(ce_ptr, 5); - mch_sched_info->stop_mch[i] = mac_bits_2_value(ce_ptr, 11); + mch_sched_info->lcid[i] = liblte_bits_2_value(ce_ptr, 5); + mch_sched_info->stop_mch[i] = liblte_bits_2_value(ce_ptr, 11); } err = LIBLTE_SUCCESS; @@ -471,14 +614,14 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_activation_deactivation_ce(LIBLTE_MAC_ACTIVATI if(act_deact != NULL && ce_ptr != NULL) { - mac_value_2_bits(act_deact->c7, ce_ptr, 1); - mac_value_2_bits(act_deact->c6, ce_ptr, 1); - mac_value_2_bits(act_deact->c5, ce_ptr, 1); - mac_value_2_bits(act_deact->c4, ce_ptr, 1); - mac_value_2_bits(act_deact->c3, ce_ptr, 1); - mac_value_2_bits(act_deact->c2, ce_ptr, 1); - mac_value_2_bits(act_deact->c1, ce_ptr, 1); - mac_value_2_bits(0, ce_ptr, 1); // R + liblte_value_2_bits(act_deact->c7, ce_ptr, 1); + liblte_value_2_bits(act_deact->c6, ce_ptr, 1); + liblte_value_2_bits(act_deact->c5, ce_ptr, 1); + liblte_value_2_bits(act_deact->c4, ce_ptr, 1); + liblte_value_2_bits(act_deact->c3, ce_ptr, 1); + liblte_value_2_bits(act_deact->c2, ce_ptr, 1); + liblte_value_2_bits(act_deact->c1, ce_ptr, 1); + liblte_value_2_bits(0, ce_ptr, 1); // R err = LIBLTE_SUCCESS; } @@ -493,14 +636,14 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_activation_deactivation_ce(uint8 if(ce_ptr != NULL && act_deact != NULL) { - act_deact->c7 = mac_bits_2_value(ce_ptr, 1); - act_deact->c6 = mac_bits_2_value(ce_ptr, 1); - act_deact->c5 = mac_bits_2_value(ce_ptr, 1); - act_deact->c4 = mac_bits_2_value(ce_ptr, 1); - act_deact->c3 = mac_bits_2_value(ce_ptr, 1); - act_deact->c2 = mac_bits_2_value(ce_ptr, 1); - act_deact->c1 = mac_bits_2_value(ce_ptr, 1); - mac_bits_2_value(ce_ptr, 1); // R + act_deact->c7 = liblte_bits_2_value(ce_ptr, 1); + act_deact->c6 = liblte_bits_2_value(ce_ptr, 1); + act_deact->c5 = liblte_bits_2_value(ce_ptr, 1); + act_deact->c4 = liblte_bits_2_value(ce_ptr, 1); + act_deact->c3 = liblte_bits_2_value(ce_ptr, 1); + act_deact->c2 = liblte_bits_2_value(ce_ptr, 1); + act_deact->c1 = liblte_bits_2_value(ce_ptr, 1); + liblte_bits_2_value(ce_ptr, 1); // R err = LIBLTE_SUCCESS; } @@ -526,6 +669,8 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_mac_pdu(LIBLTE_MAC_PDU_STRUCT *pdu, LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint8 *msg_ptr = msg->msg; uint32 i; + uint32 j; + uint32 length; if(pdu != NULL && msg != NULL) @@ -533,15 +678,15 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_mac_pdu(LIBLTE_MAC_PDU_STRUCT *pdu, // Pack the subheaders for(i=0; iN_subheaders; i++) { - mac_value_2_bits(0, &msg_ptr, 1); // R - mac_value_2_bits(0, &msg_ptr, 1); // R + liblte_value_2_bits(0, &msg_ptr, 1); // R + liblte_value_2_bits(0, &msg_ptr, 1); // R if(i != pdu->N_subheaders-1) { - mac_value_2_bits(1, &msg_ptr, 1); // E + liblte_value_2_bits(1, &msg_ptr, 1); // E }else{ - mac_value_2_bits(0, &msg_ptr, 1); // E + liblte_value_2_bits(0, &msg_ptr, 1); // E } - mac_value_2_bits(pdu->subheader[i].lcid, &msg_ptr, 5); + liblte_value_2_bits(pdu->subheader[i].lcid, &msg_ptr, 5); if(LIBLTE_MAC_CHAN_TYPE_DLSCH == pdu->chan_type) { if(!(LIBLTE_MAC_DLSCH_ACTIVATION_DEACTIVATION_LCID == pdu->subheader[i].lcid || @@ -552,20 +697,56 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_mac_pdu(LIBLTE_MAC_PDU_STRUCT *pdu, { if(i != (pdu->N_subheaders-1)) { - if((pdu->subheader[i].payload.sdu.N_bits/8) < 128) + if(pdu->subheader[i].payload.sdu.N_bytes < 128) { - mac_value_2_bits(0, &msg_ptr, 1); // F - mac_value_2_bits(pdu->subheader[i].payload.sdu.N_bits/8, &msg_ptr, 7); + liblte_value_2_bits(0, &msg_ptr, 1); // F + liblte_value_2_bits(pdu->subheader[i].payload.sdu.N_bytes, &msg_ptr, 7); }else{ - mac_value_2_bits(1, &msg_ptr, 1); // F - mac_value_2_bits(pdu->subheader[i].payload.sdu.N_bits/8, &msg_ptr, 15); + liblte_value_2_bits(1, &msg_ptr, 1); // F + liblte_value_2_bits(pdu->subheader[i].payload.sdu.N_bytes, &msg_ptr, 15); } } } }else if(LIBLTE_MAC_CHAN_TYPE_ULSCH == pdu->chan_type){ if(LIBLTE_MAC_ULSCH_EXT_POWER_HEADROOM_REPORT_LCID == pdu->subheader[i].lcid) { - // FIXME + // SCell presence byte is always present + length = 1; + if(pdu->subheader[i].payload.ext_power_headroom.pcell_type_2_present) + { + length++; + if(!pdu->subheader[i].payload.ext_power_headroom.pcell_type_2.v) + { + length++; + } + } + length++; + if(!pdu->subheader[i].payload.ext_power_headroom.pcell_type_1.v) + { + length++; + } + for(j=0; j<7; j++) + { + if(pdu->subheader[i].payload.ext_power_headroom.scell_present[j]) + { + length++; + if(!pdu->subheader[i].payload.ext_power_headroom.scell[j].v) + { + length++; + } + } + } + if(i != (pdu->N_subheaders-1)) + { + if(length < 128) + { + liblte_value_2_bits(0, &msg_ptr, 1); // F + liblte_value_2_bits(length, &msg_ptr, 7); + }else{ + liblte_value_2_bits(1, &msg_ptr, 1); // F + liblte_value_2_bits(length, &msg_ptr, 15); + } + } }else if(!(LIBLTE_MAC_ULSCH_POWER_HEADROOM_REPORT_LCID == pdu->subheader[i].lcid || LIBLTE_MAC_ULSCH_C_RNTI_LCID == pdu->subheader[i].lcid || LIBLTE_MAC_ULSCH_TRUNCATED_BSR_LCID == pdu->subheader[i].lcid || @@ -574,13 +755,13 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_mac_pdu(LIBLTE_MAC_PDU_STRUCT *pdu, LIBLTE_MAC_ULSCH_PADDING_LCID == pdu->subheader[i].lcid)){ if(i != (pdu->N_subheaders-1)) { - if((pdu->subheader[i].payload.sdu.N_bits/8) < 128) + if(pdu->subheader[i].payload.sdu.N_bytes < 128) { - mac_value_2_bits(0, &msg_ptr, 1); // F - mac_value_2_bits(pdu->subheader[i].payload.sdu.N_bits/8, &msg_ptr, 7); + liblte_value_2_bits(0, &msg_ptr, 1); // F + liblte_value_2_bits(pdu->subheader[i].payload.sdu.N_bytes, &msg_ptr, 7); }else{ - mac_value_2_bits(1, &msg_ptr, 1); // F - mac_value_2_bits(pdu->subheader[i].payload.sdu.N_bits/8, &msg_ptr, 15); + liblte_value_2_bits(1, &msg_ptr, 1); // F + liblte_value_2_bits(pdu->subheader[i].payload.sdu.N_bytes, &msg_ptr, 15); } } } @@ -591,23 +772,23 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_mac_pdu(LIBLTE_MAC_PDU_STRUCT *pdu, { if((pdu->subheader[i].payload.mch_sched_info.N_items*2) < 128) { - mac_value_2_bits(0, &msg_ptr, 1); // F - mac_value_2_bits(pdu->subheader[i].payload.mch_sched_info.N_items*2, &msg_ptr, 7); + liblte_value_2_bits(0, &msg_ptr, 1); // F + liblte_value_2_bits(pdu->subheader[i].payload.mch_sched_info.N_items*2, &msg_ptr, 7); }else{ - mac_value_2_bits(1, &msg_ptr, 1); // F - mac_value_2_bits(pdu->subheader[i].payload.mch_sched_info.N_items*2, &msg_ptr, 15); + liblte_value_2_bits(1, &msg_ptr, 1); // F + liblte_value_2_bits(pdu->subheader[i].payload.mch_sched_info.N_items*2, &msg_ptr, 15); } } }else{ if(i != (pdu->N_subheaders-1)) { - if((pdu->subheader[i].payload.sdu.N_bits/8) < 128) + if(pdu->subheader[i].payload.sdu.N_bytes < 128) { - mac_value_2_bits(0, &msg_ptr, 1); // F - mac_value_2_bits(pdu->subheader[i].payload.sdu.N_bits/8, &msg_ptr, 7); + liblte_value_2_bits(0, &msg_ptr, 1); // F + liblte_value_2_bits(pdu->subheader[i].payload.sdu.N_bytes, &msg_ptr, 7); }else{ - mac_value_2_bits(1, &msg_ptr, 1); // F - mac_value_2_bits(pdu->subheader[i].payload.sdu.N_bits/8, &msg_ptr, 15); + liblte_value_2_bits(1, &msg_ptr, 1); // F + liblte_value_2_bits(pdu->subheader[i].payload.sdu.N_bytes, &msg_ptr, 15); } } } @@ -628,9 +809,13 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_mac_pdu(LIBLTE_MAC_PDU_STRUCT *pdu, liblte_mac_pack_ta_command_ce(&pdu->subheader[i].payload.ta_command, &msg_ptr); }else if(LIBLTE_MAC_DLSCH_DRX_COMMAND_LCID == pdu->subheader[i].lcid){ // No content for DRX Command CE + }else if(LIBLTE_MAC_DLSCH_PADDING_LCID == pdu->subheader[i].lcid){ + // No content for PADDING CE }else{ // SDU - memcpy(msg_ptr, pdu->subheader[i].payload.sdu.msg, pdu->subheader[i].payload.sdu.N_bits); - msg_ptr += pdu->subheader[i].payload.sdu.N_bits; + for(j=0; jsubheader[i].payload.sdu.N_bytes; j++) + { + liblte_value_2_bits(pdu->subheader[i].payload.sdu.msg[j], &msg_ptr, 8); + } } }else if(LIBLTE_MAC_CHAN_TYPE_ULSCH == pdu->chan_type){ if(LIBLTE_MAC_ULSCH_EXT_POWER_HEADROOM_REPORT_LCID == pdu->subheader[i].lcid) @@ -647,16 +832,20 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_mac_pdu(LIBLTE_MAC_PDU_STRUCT *pdu, }else if(LIBLTE_MAC_ULSCH_LONG_BSR_LCID == pdu->subheader[i].lcid){ liblte_mac_pack_long_bsr_ce(&pdu->subheader[i].payload.long_bsr, &msg_ptr); }else{ // SDU - memcpy(msg_ptr, pdu->subheader[i].payload.sdu.msg, pdu->subheader[i].payload.sdu.N_bits); - msg_ptr += pdu->subheader[i].payload.sdu.N_bits; + for(j=0; jsubheader[i].payload.sdu.N_bytes; j++) + { + liblte_value_2_bits(pdu->subheader[i].payload.sdu.msg[j], &msg_ptr, 8); + } } }else{ // LIBLTE_MAC_CHAN_TYPE_MCH == mac_pdu->chan_type if(LIBLTE_MAC_MCH_SCHEDULING_INFORMATION_LCID == pdu->subheader[i].lcid) { liblte_mac_pack_mch_scheduling_information_ce(&pdu->subheader[i].payload.mch_sched_info, &msg_ptr); }else{ // SDU - memcpy(msg_ptr, pdu->subheader[i].payload.sdu.msg, pdu->subheader[i].payload.sdu.N_bits); - msg_ptr += pdu->subheader[i].payload.sdu.N_bits; + for(j=0; jsubheader[i].payload.sdu.N_bytes; j++) + { + liblte_value_2_bits(pdu->subheader[i].payload.sdu.msg[j], &msg_ptr, 8); + } } } } @@ -668,11 +857,13 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_mac_pdu(LIBLTE_MAC_PDU_STRUCT *pdu, return(err); } LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *msg, + bool simultaneous_pucch_pusch, LIBLTE_MAC_PDU_STRUCT *pdu) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint8 *msg_ptr = msg->msg; uint32 i; + uint32 j; uint8 e_bit = 1; if(msg != NULL && @@ -682,9 +873,9 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *msg, pdu->N_subheaders = 0; while(e_bit) { - mac_bits_2_value(&msg_ptr, 2); // R - e_bit = mac_bits_2_value(&msg_ptr, 1); - pdu->subheader[pdu->N_subheaders].lcid = mac_bits_2_value(&msg_ptr, 5); + liblte_bits_2_value(&msg_ptr, 2); // R + e_bit = liblte_bits_2_value(&msg_ptr, 1); + pdu->subheader[pdu->N_subheaders].lcid = liblte_bits_2_value(&msg_ptr, 5); if(LIBLTE_MAC_CHAN_TYPE_DLSCH == pdu->chan_type) { @@ -696,20 +887,29 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *msg, { if(e_bit) { - if(mac_bits_2_value(&msg_ptr, 1)) // F + if(liblte_bits_2_value(&msg_ptr, 1)) // F { - pdu->subheader[pdu->N_subheaders].payload.sdu.N_bits = mac_bits_2_value(&msg_ptr, 15) * 8; + pdu->subheader[pdu->N_subheaders].payload.sdu.N_bytes = liblte_bits_2_value(&msg_ptr, 15); }else{ - pdu->subheader[pdu->N_subheaders].payload.sdu.N_bits = mac_bits_2_value(&msg_ptr, 7) * 8; + pdu->subheader[pdu->N_subheaders].payload.sdu.N_bytes = liblte_bits_2_value(&msg_ptr, 7); } }else{ - pdu->subheader[pdu->N_subheaders].payload.sdu.N_bits = 0; + pdu->subheader[pdu->N_subheaders].payload.sdu.N_bytes = 0; } } }else if(LIBLTE_MAC_CHAN_TYPE_ULSCH == pdu->chan_type){ if(LIBLTE_MAC_ULSCH_EXT_POWER_HEADROOM_REPORT_LCID == pdu->subheader[pdu->N_subheaders].lcid) { - // FIXME + // Skip over length fields + if(e_bit) + { + if(liblte_bits_2_value(&msg_ptr, 1)) // F + { + liblte_bits_2_value(&msg_ptr, 15); + }else{ + liblte_bits_2_value(&msg_ptr, 7); + } + } }else if(!(LIBLTE_MAC_ULSCH_POWER_HEADROOM_REPORT_LCID == pdu->subheader[pdu->N_subheaders].lcid || LIBLTE_MAC_ULSCH_C_RNTI_LCID == pdu->subheader[pdu->N_subheaders].lcid || LIBLTE_MAC_ULSCH_TRUNCATED_BSR_LCID == pdu->subheader[pdu->N_subheaders].lcid || @@ -718,14 +918,14 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *msg, LIBLTE_MAC_ULSCH_PADDING_LCID == pdu->subheader[pdu->N_subheaders].lcid)){ if(e_bit) { - if(mac_bits_2_value(&msg_ptr, 1)) // F + if(liblte_bits_2_value(&msg_ptr, 1)) // F { - pdu->subheader[pdu->N_subheaders].payload.sdu.N_bits = mac_bits_2_value(&msg_ptr, 15) * 8; + pdu->subheader[pdu->N_subheaders].payload.sdu.N_bytes = liblte_bits_2_value(&msg_ptr, 15); }else{ - pdu->subheader[pdu->N_subheaders].payload.sdu.N_bits = mac_bits_2_value(&msg_ptr, 7) * 8; + pdu->subheader[pdu->N_subheaders].payload.sdu.N_bytes = liblte_bits_2_value(&msg_ptr, 7); } }else{ - pdu->subheader[pdu->N_subheaders].payload.sdu.N_bits = 0; + pdu->subheader[pdu->N_subheaders].payload.sdu.N_bytes = 0; } } }else{ // LIBLTE_MAC_CHAN_TYPE_MCH == mac_pdu->subheader[i].lcid @@ -733,11 +933,11 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *msg, { if(e_bit) { - if(mac_bits_2_value(&msg_ptr, 1)) // F + if(liblte_bits_2_value(&msg_ptr, 1)) // F { - pdu->subheader[pdu->N_subheaders].payload.mch_sched_info.N_items = mac_bits_2_value(&msg_ptr, 15) / 2; + pdu->subheader[pdu->N_subheaders].payload.mch_sched_info.N_items = liblte_bits_2_value(&msg_ptr, 15) / 2; }else{ - pdu->subheader[pdu->N_subheaders].payload.mch_sched_info.N_items = mac_bits_2_value(&msg_ptr, 7) / 2; + pdu->subheader[pdu->N_subheaders].payload.mch_sched_info.N_items = liblte_bits_2_value(&msg_ptr, 7) / 2; } }else{ pdu->subheader[pdu->N_subheaders].payload.mch_sched_info.N_items = 0; @@ -745,14 +945,14 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *msg, }else{ if(e_bit) { - if(mac_bits_2_value(&msg_ptr, 1)) // F + if(liblte_bits_2_value(&msg_ptr, 1)) // F { - pdu->subheader[pdu->N_subheaders].payload.sdu.N_bits = mac_bits_2_value(&msg_ptr, 15) * 8; + pdu->subheader[pdu->N_subheaders].payload.sdu.N_bytes = liblte_bits_2_value(&msg_ptr, 15); }else{ - pdu->subheader[pdu->N_subheaders].payload.sdu.N_bits = mac_bits_2_value(&msg_ptr, 7) * 8; + pdu->subheader[pdu->N_subheaders].payload.sdu.N_bytes = liblte_bits_2_value(&msg_ptr, 7); } }else{ - pdu->subheader[pdu->N_subheaders].payload.sdu.N_bits = 0; + pdu->subheader[pdu->N_subheaders].payload.sdu.N_bytes = 0; } } } @@ -776,17 +976,19 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *msg, }else if(LIBLTE_MAC_DLSCH_PADDING_LCID == pdu->subheader[i].lcid){ // No content for PADDING CE }else{ // SDU - if(pdu->subheader[i].payload.sdu.N_bits == 0) + if(pdu->subheader[i].payload.sdu.N_bytes == 0) { - pdu->subheader[i].payload.sdu.N_bits = msg->N_bits - (msg_ptr - msg->msg); + pdu->subheader[i].payload.sdu.N_bytes = (msg->N_bits - (msg_ptr - msg->msg))/8; + } + for(j=0; jsubheader[i].payload.sdu.N_bytes; j++) + { + pdu->subheader[i].payload.sdu.msg[j] = liblte_bits_2_value(&msg_ptr, 8); } - memcpy(pdu->subheader[i].payload.sdu.msg, msg_ptr, pdu->subheader[i].payload.sdu.N_bits); - msg_ptr += pdu->subheader[i].payload.sdu.N_bits; } }else if(LIBLTE_MAC_CHAN_TYPE_ULSCH == pdu->chan_type){ if(LIBLTE_MAC_ULSCH_EXT_POWER_HEADROOM_REPORT_LCID == pdu->subheader[i].lcid) { - liblte_mac_unpack_ext_power_headroom_ce(&msg_ptr, &pdu->subheader[i].payload.ext_power_headroom); + liblte_mac_unpack_ext_power_headroom_ce(&msg_ptr, simultaneous_pucch_pusch, &pdu->subheader[i].payload.ext_power_headroom); }else if(LIBLTE_MAC_ULSCH_POWER_HEADROOM_REPORT_LCID == pdu->subheader[i].lcid){ liblte_mac_unpack_power_headroom_ce(&msg_ptr, &pdu->subheader[i].payload.power_headroom); }else if(LIBLTE_MAC_ULSCH_C_RNTI_LCID == pdu->subheader[i].lcid){ @@ -800,12 +1002,14 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *msg, }else if(LIBLTE_MAC_ULSCH_PADDING_LCID == pdu->subheader[i].lcid){ // No content for PADDING CE }else{ // SDU - if(pdu->subheader[i].payload.sdu.N_bits == 0) + if(pdu->subheader[i].payload.sdu.N_bytes == 0) + { + pdu->subheader[i].payload.sdu.N_bytes = (msg->N_bits - (msg_ptr - msg->msg))/8; + } + for(j=0; jsubheader[i].payload.sdu.N_bytes; j++) { - pdu->subheader[i].payload.sdu.N_bits = msg->N_bits - (msg_ptr - msg->msg); + pdu->subheader[i].payload.sdu.msg[j] = liblte_bits_2_value(&msg_ptr, 8); } - memcpy(pdu->subheader[i].payload.sdu.msg, msg_ptr, pdu->subheader[i].payload.sdu.N_bits); - msg_ptr += pdu->subheader[i].payload.sdu.N_bits; } }else{ // LIBLTE_MAC_CHAN_TYPE_MCH == mac_pdu->chan_type if(LIBLTE_MAC_MCH_SCHEDULING_INFORMATION_LCID == pdu->subheader[i].lcid) @@ -818,12 +1022,14 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *msg, }else if(LIBLTE_MAC_MCH_PADDING_LCID == pdu->subheader[i].lcid){ // No content for PADDING CE }else{ // SDU - if(pdu->subheader[i].payload.sdu.N_bits == 0) + if(pdu->subheader[i].payload.sdu.N_bytes == 0) { - pdu->subheader[i].payload.sdu.N_bits = msg->N_bits - (msg_ptr - msg->msg); + pdu->subheader[i].payload.sdu.N_bytes = (msg->N_bits - (msg_ptr - msg->msg))/8; + } + for(j=0; jsubheader[i].payload.sdu.N_bytes; j++) + { + pdu->subheader[i].payload.sdu.msg[j] = liblte_bits_2_value(&msg_ptr, 8); } - memcpy(pdu->subheader[i].payload.sdu.msg, msg_ptr, pdu->subheader[i].payload.sdu.N_bits); - msg_ptr += pdu->subheader[i].payload.sdu.N_bits; } } } @@ -841,7 +1047,6 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_mac_pdu(LIBLTE_BIT_MSG_STRUCT *msg, Document Reference: 36.321 v10.2.0 Section 6.1.4 *********************************************************************/ -// FIXME /********************************************************************* PDU Name: Random Access Response @@ -865,28 +1070,28 @@ LIBLTE_ERROR_ENUM liblte_mac_pack_random_access_response_pdu(LIBLTE_MAC_RAR_STRU if(LIBLTE_MAC_RAR_HEADER_TYPE_BI == rar->hdr_type) { // Pack Header - mac_value_2_bits(0, &pdu_ptr, 1); // E - mac_value_2_bits(rar->hdr_type, &pdu_ptr, 1); - mac_value_2_bits(0, &pdu_ptr, 2); // R - mac_value_2_bits(rar->BI, &pdu_ptr, 4); + liblte_value_2_bits(0, &pdu_ptr, 1); // E + liblte_value_2_bits(rar->hdr_type, &pdu_ptr, 1); + liblte_value_2_bits(0, &pdu_ptr, 2); // R + liblte_value_2_bits(rar->BI, &pdu_ptr, 4); err = LIBLTE_SUCCESS; }else if(LIBLTE_MAC_RAR_HEADER_TYPE_RAPID == rar->hdr_type){ // Pack Header - mac_value_2_bits(0, &pdu_ptr, 1); // E - mac_value_2_bits(rar->hdr_type, &pdu_ptr, 1); - mac_value_2_bits(rar->RAPID, &pdu_ptr, 6); + liblte_value_2_bits(0, &pdu_ptr, 1); // E + liblte_value_2_bits(rar->hdr_type, &pdu_ptr, 1); + liblte_value_2_bits(rar->RAPID, &pdu_ptr, 6); // Pack RAR - mac_value_2_bits(0, &pdu_ptr, 1); // R - mac_value_2_bits(rar->timing_adv_cmd, &pdu_ptr, 11); - mac_value_2_bits(rar->hopping_flag, &pdu_ptr, 1); - mac_value_2_bits(rar->rba, &pdu_ptr, 10); // FIXME - mac_value_2_bits(rar->mcs, &pdu_ptr, 4); // FIXME - mac_value_2_bits(rar->tpc_command, &pdu_ptr, 3); - mac_value_2_bits(rar->ul_delay, &pdu_ptr, 1); - mac_value_2_bits(rar->csi_req, &pdu_ptr, 1); - mac_value_2_bits(rar->temp_c_rnti, &pdu_ptr, 16); + liblte_value_2_bits(0, &pdu_ptr, 1); // R + liblte_value_2_bits(rar->timing_adv_cmd, &pdu_ptr, 11); + liblte_value_2_bits(rar->hopping_flag, &pdu_ptr, 1); + liblte_value_2_bits(rar->rba, &pdu_ptr, 10); + liblte_value_2_bits(rar->mcs, &pdu_ptr, 4); + liblte_value_2_bits(rar->tpc_command, &pdu_ptr, 3); + liblte_value_2_bits(rar->ul_delay, &pdu_ptr, 1); + liblte_value_2_bits(rar->csi_req, &pdu_ptr, 1); + liblte_value_2_bits(rar->temp_c_rnti, &pdu_ptr, 16); err = LIBLTE_SUCCESS; } @@ -905,28 +1110,28 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_random_access_response_pdu(LIBLTE_BIT_MSG_ST if(pdu != NULL && rar != NULL) { - mac_bits_2_value(&pdu_ptr, 1); // E - rar->hdr_type = (LIBLTE_MAC_RAR_HEADER_TYPE_ENUM)mac_bits_2_value(&pdu_ptr, 1); + liblte_bits_2_value(&pdu_ptr, 1); // E + rar->hdr_type = (LIBLTE_MAC_RAR_HEADER_TYPE_ENUM)liblte_bits_2_value(&pdu_ptr, 1); if(LIBLTE_MAC_RAR_HEADER_TYPE_BI == rar->hdr_type) { - mac_bits_2_value(&pdu_ptr, 2); // R - rar->BI = mac_bits_2_value(&pdu_ptr, 4); + liblte_bits_2_value(&pdu_ptr, 2); // R + rar->BI = liblte_bits_2_value(&pdu_ptr, 4); err = LIBLTE_SUCCESS; }else if(LIBLTE_MAC_RAR_HEADER_TYPE_RAPID == rar->hdr_type){ // Unpack header - rar->RAPID = mac_bits_2_value(&pdu_ptr, 6); + rar->RAPID = liblte_bits_2_value(&pdu_ptr, 6); // Unpack RAR - mac_bits_2_value(&pdu_ptr, 1); // R - rar->timing_adv_cmd = mac_bits_2_value(&pdu_ptr, 11); - rar->hopping_flag = (LIBLTE_MAC_RAR_HOPPING_ENUM)mac_bits_2_value(&pdu_ptr, 1); - rar->rba = mac_bits_2_value(&pdu_ptr, 10); // FIXME - rar->mcs = mac_bits_2_value(&pdu_ptr, 4); // FIXME - rar->tpc_command = (LIBLTE_MAC_RAR_TPC_COMMAND_ENUM)mac_bits_2_value(&pdu_ptr, 3); - rar->ul_delay = (LIBLTE_MAC_RAR_UL_DELAY_ENUM)mac_bits_2_value(&pdu_ptr, 1); - rar->csi_req = (LIBLTE_MAC_RAR_CSI_REQ_ENUM)mac_bits_2_value(&pdu_ptr, 1); - rar->temp_c_rnti = mac_bits_2_value(&pdu_ptr, 16); + liblte_bits_2_value(&pdu_ptr, 1); // R + rar->timing_adv_cmd = liblte_bits_2_value(&pdu_ptr, 11); + rar->hopping_flag = (LIBLTE_MAC_RAR_HOPPING_ENUM)liblte_bits_2_value(&pdu_ptr, 1); + rar->rba = liblte_bits_2_value(&pdu_ptr, 10); + rar->mcs = liblte_bits_2_value(&pdu_ptr, 4); + rar->tpc_command = (LIBLTE_MAC_RAR_TPC_COMMAND_ENUM)liblte_bits_2_value(&pdu_ptr, 3); + rar->ul_delay = (LIBLTE_MAC_RAR_UL_DELAY_ENUM)liblte_bits_2_value(&pdu_ptr, 1); + rar->csi_req = (LIBLTE_MAC_RAR_CSI_REQ_ENUM)liblte_bits_2_value(&pdu_ptr, 1); + rar->temp_c_rnti = liblte_bits_2_value(&pdu_ptr, 16); err = LIBLTE_SUCCESS; } @@ -934,45 +1139,3 @@ LIBLTE_ERROR_ENUM liblte_mac_unpack_random_access_response_pdu(LIBLTE_BIT_MSG_ST return(err); } - -/******************************************************************************* - LOCAL FUNCTIONS -*******************************************************************************/ - -/********************************************************************* - Name: mac_value_2_bits - - Description: Converts a value to a bit string -*********************************************************************/ -void mac_value_2_bits(uint32 value, - uint8 **bits, - uint32 N_bits) -{ - uint32 i; - - for(i=0; i> (N_bits-i-1)) & 0x1; - } - *bits += N_bits; -} - -/********************************************************************* - Name: mac_bits_2_value - - Description: Converts a bit string to a value -*********************************************************************/ -uint32 mac_bits_2_value(uint8 **bits, - uint32 N_bits) -{ - uint32 value = 0; - uint32 i; - - for(i=0; iN_octets; + for(i=0; iN_octets; i++) + { + (*ie_ptr)[1+i] = add_info->info[i]; + } + *ie_ptr += add_info->N_octets + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_information_ie(uint8 **ie_ptr, + LIBLTE_MME_ADDITIONAL_INFORMATION_STRUCT *add_info) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ie_ptr != NULL && + add_info != NULL) + { + add_info->N_octets = (*ie_ptr)[0]; + for(i=0; iN_octets; i++) + { + add_info->info[i] = (*ie_ptr)[1+i]; + } + *ie_ptr += add_info->N_octets + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* IE Name: Device Properties @@ -118,7 +186,59 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_device_properties_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.2.1 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_bearer_context_status_ie(LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_STRUCT *ebcs, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ebcs != NULL && + ie_ptr != NULL) + { + (*ie_ptr)[0] = 2; + (*ie_ptr)[1] = (ebcs->ebi[7] << 7); + (*ie_ptr)[1] |= (ebcs->ebi[6] << 6); + (*ie_ptr)[1] |= (ebcs->ebi[5] << 5); + (*ie_ptr)[2] = (ebcs->ebi[15] << 7); + (*ie_ptr)[2] |= (ebcs->ebi[14] << 6); + (*ie_ptr)[2] |= (ebcs->ebi[13] << 5); + (*ie_ptr)[2] |= (ebcs->ebi[12] << 4); + (*ie_ptr)[2] |= (ebcs->ebi[11] << 3); + (*ie_ptr)[2] |= (ebcs->ebi[10] << 2); + (*ie_ptr)[2] |= (ebcs->ebi[9] << 1); + (*ie_ptr)[2] |= ebcs->ebi[8]; + *ie_ptr += 3; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_bearer_context_status_ie(uint8 **ie_ptr, + LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_STRUCT *ebcs) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + ebcs != NULL) + { + ebcs->ebi[5] = ((*ie_ptr)[1] >> 5) & 0x01; + ebcs->ebi[6] = ((*ie_ptr)[1] >> 6) & 0x01; + ebcs->ebi[7] = ((*ie_ptr)[1] >> 7) & 0x01; + ebcs->ebi[8] = (*ie_ptr)[2] & 0x01; + ebcs->ebi[9] = ((*ie_ptr)[2] >> 1) & 0x01; + ebcs->ebi[10] = ((*ie_ptr)[2] >> 2) & 0x01; + ebcs->ebi[11] = ((*ie_ptr)[2] >> 3) & 0x01; + ebcs->ebi[12] = ((*ie_ptr)[2] >> 4) & 0x01; + ebcs->ebi[13] = ((*ie_ptr)[2] >> 5) & 0x01; + ebcs->ebi[14] = ((*ie_ptr)[2] >> 6) & 0x01; + ebcs->ebi[15] = ((*ie_ptr)[2] >> 7) & 0x01; + *ie_ptr += 3; + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* IE Name: Location Area Identification @@ -137,24 +257,18 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_location_area_id_ie(LIBLTE_MME_LOCATION_AREA_I if(lai != NULL && ie_ptr != NULL) { - **ie_ptr = ((lai->mcc/10) % 10) | ((lai->mcc/100) % 10); - *ie_ptr += 1; - if(lai->mnc > 100) + (*ie_ptr)[0] = (((lai->mcc/10) % 10) << 4) | ((lai->mcc/100) % 10); + if(lai->mnc < 100) { - **ie_ptr = 0xF | (lai->mcc % 10); - *ie_ptr += 1; - **ie_ptr = (lai->mnc % 10) | ((lai->mnc/10) % 10); - *ie_ptr += 1; + (*ie_ptr)[1] = 0xF0 | (lai->mcc % 10); + (*ie_ptr)[2] = ((lai->mnc % 10) << 4) | ((lai->mnc/10) % 10); }else{ - **ie_ptr = (lai->mnc % 10) | (lai->mcc % 10); - *ie_ptr += 1; - **ie_ptr = ((lai->mnc/10) % 10) | ((lai->mnc/100) % 10); - *ie_ptr += 1; + (*ie_ptr)[1] = ((lai->mnc % 10) << 4) | (lai->mcc % 10); + (*ie_ptr)[2] = (((lai->mnc/10) % 10) << 4) | ((lai->mnc/100) % 10); } - **ie_ptr = (lai->lac >> 8) & 0xFF; - *ie_ptr += 1; - **ie_ptr = lai->lac & 0xFF; - *ie_ptr += 1; + (*ie_ptr)[3] = (lai->lac >> 8) & 0xFF; + (*ie_ptr)[4] = lai->lac & 0xFF; + *ie_ptr += 5; err = LIBLTE_SUCCESS; } @@ -169,27 +283,21 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_location_area_id_ie(uint8 if(ie_ptr != NULL && lai != NULL) { - lai->mcc = (**ie_ptr & 0x0F)*100; - lai->mcc += ((**ie_ptr >> 4) & 0x0F)*10; - *ie_ptr += 1; - lai->mcc += **ie_ptr & 0x0F; - if(((**ie_ptr >> 4) & 0x0F) == 0x0F) + lai->mcc = ((*ie_ptr)[0] & 0x0F)*100; + lai->mcc += (((*ie_ptr)[0] >> 4) & 0x0F)*10; + lai->mcc += (*ie_ptr)[1] & 0x0F; + if((((*ie_ptr)[1] >> 4) & 0x0F) == 0x0F) { - *ie_ptr += 1; - lai->mnc = (**ie_ptr & 0x0F)*10; - lai->mnc += (**ie_ptr >> 4) & 0x0F; - *ie_ptr += 1; + lai->mnc = ((*ie_ptr)[2] & 0x0F)*10; + lai->mnc += ((*ie_ptr)[2] >> 4) & 0x0F; }else{ - lai->mnc = (**ie_ptr >> 4) & 0x0F; - *ie_ptr += 1; - lai->mnc += (**ie_ptr & 0x0F)*100; - lai->mnc += ((**ie_ptr >> 4) & 0x0F)*10; - *ie_ptr += 1; + lai->mnc = ((*ie_ptr)[1] >> 4) & 0x0F; + lai->mnc += ((*ie_ptr)[2] & 0x0F)*100; + lai->mnc += (((*ie_ptr)[2] >> 4) & 0x0F)*10; } - lai->lac = **ie_ptr << 8; - *ie_ptr += 1; - lai->lac |= **ie_ptr; - *ie_ptr += 1; + lai->lac = (*ie_ptr)[3] << 8; + lai->lac |= (*ie_ptr)[4]; + *ie_ptr += 5; err = LIBLTE_SUCCESS; } @@ -207,7 +315,216 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_location_area_id_ie(uint8 Document Reference: 24.301 v10.2.0 Section 9.9.2.3 24.008 v10.2.0 Section 10.5.1.4 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_mobile_id_ie(LIBLTE_MME_MOBILE_ID_STRUCT *mobile_id, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *id; + uint32 i; + + if(mobile_id != NULL && + ie_ptr != NULL) + { + if(LIBLTE_MME_MOBILE_ID_TYPE_IMSI == mobile_id->type_of_id || + LIBLTE_MME_MOBILE_ID_TYPE_IMEI == mobile_id->type_of_id) + { + if(LIBLTE_MME_MOBILE_ID_TYPE_IMSI == mobile_id->type_of_id) + { + id = mobile_id->imsi; + }else{ + id = mobile_id->imei; + } + **ie_ptr = 8; // Length + *ie_ptr += 1; + **ie_ptr = (id[0] << 4) | (1 << 3) | mobile_id->type_of_id; + *ie_ptr += 1; + for(i=0; i<7; i++) + { + (*ie_ptr)[i] = (id[i*2+2] << 4) | id[i*2+1]; + } + *ie_ptr += 7; + + err = LIBLTE_SUCCESS; + }else if(LIBLTE_MME_MOBILE_ID_TYPE_IMEISV == mobile_id->type_of_id){ + **ie_ptr = 9; // Length + *ie_ptr += 1; + id = mobile_id->imeisv; + **ie_ptr = (id[0] << 4) | mobile_id->type_of_id; + *ie_ptr += 1; + for(i=0; i<7; i++) + { + (*ie_ptr)[i] = (id[i*2+2] << 4) | id[i*2+1]; + } + *ie_ptr += 7; + **ie_ptr = 0xF0 | id[i*2+1]; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + }else if(LIBLTE_MME_MOBILE_ID_TYPE_TMSI == mobile_id->type_of_id){ + **ie_ptr = 5; // Length + *ie_ptr += 1; + **ie_ptr = 0xF0 | mobile_id->type_of_id; + *ie_ptr += 1; + **ie_ptr = (mobile_id->tmsi >> 24) & 0xFF; + *ie_ptr += 1; + **ie_ptr = (mobile_id->tmsi >> 16) & 0xFF; + *ie_ptr += 1; + **ie_ptr = (mobile_id->tmsi >> 8) & 0xFF; + *ie_ptr += 1; + **ie_ptr = mobile_id->tmsi && 0xFF; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + }else if(LIBLTE_MME_MOBILE_ID_TYPE_TMGI == mobile_id->type_of_id){ + **ie_ptr = 4; // Length + if(mobile_id->tmgi.mbms_session_id_ind) + { + **ie_ptr = **ie_ptr + 1; + }else if(mobile_id->tmgi.mcc_mnc_ind){ + **ie_ptr = **ie_ptr + 3; + } + *ie_ptr += 1; + **ie_ptr = ((mobile_id->tmgi.mbms_session_id_ind << 5) | + (mobile_id->tmgi.mcc_mnc_ind << 4) | + mobile_id->type_of_id); + *ie_ptr += 1; + **ie_ptr = (mobile_id->tmgi.mbms_service_id >> 16) & 0xFF; + *ie_ptr += 1; + **ie_ptr = (mobile_id->tmgi.mbms_service_id >> 8) & 0xFF; + *ie_ptr += 1; + **ie_ptr = mobile_id->tmgi.mbms_service_id & 0xFF; + *ie_ptr += 1; + if(mobile_id->tmgi.mcc_mnc_ind) + { + **ie_ptr = (((mobile_id->tmgi.mcc/10) % 10) << 4) | ((mobile_id->tmgi.mcc/100) % 10); + *ie_ptr += 1; + if(mobile_id->tmgi.mnc < 100) + { + **ie_ptr = 0xF0 | (mobile_id->tmgi.mcc % 10); + *ie_ptr += 1; + **ie_ptr = ((mobile_id->tmgi.mnc % 10) << 4) | ((mobile_id->tmgi.mnc/10) % 10); + *ie_ptr += 1; + }else{ + **ie_ptr = ((mobile_id->tmgi.mnc % 10) << 4) | (mobile_id->tmgi.mcc % 10); + *ie_ptr += 1; + **ie_ptr = (((mobile_id->tmgi.mnc/10) % 10) << 4) | ((mobile_id->tmgi.mnc/100) % 10); + *ie_ptr += 1; + } + } + if(mobile_id->tmgi.mbms_session_id_ind) + { + **ie_ptr = mobile_id->tmgi.mbms_session_id; + *ie_ptr += 1; + } + + err = LIBLTE_SUCCESS; + } + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_id_ie(uint8 **ie_ptr, + LIBLTE_MME_MOBILE_ID_STRUCT *mobile_id) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *id; + uint32 length; + uint32 i; + bool odd = false; + + if(ie_ptr != NULL && + mobile_id != NULL) + { + length = **ie_ptr; + *ie_ptr += 1; + + mobile_id->type_of_id = **ie_ptr & 0x07; + + if(LIBLTE_MME_MOBILE_ID_TYPE_IMSI == mobile_id->type_of_id || + LIBLTE_MME_MOBILE_ID_TYPE_IMEI == mobile_id->type_of_id || + LIBLTE_MME_MOBILE_ID_TYPE_IMEISV == mobile_id->type_of_id) + { + if(LIBLTE_MME_MOBILE_ID_TYPE_IMSI == mobile_id->type_of_id) + { + id = mobile_id->imsi; + odd = true; + }else if(LIBLTE_MME_MOBILE_ID_TYPE_IMEI == mobile_id->type_of_id){ + id = mobile_id->imei; + odd = true; + }else{ + id = mobile_id->imeisv; + odd = false; + } + + id[0] = **ie_ptr >> 4; + *ie_ptr += 1; + for(i=0; i<7; i++) + { + id[i*2+1] = (*ie_ptr)[i] & 0x0F; + id[i*2+2] = (*ie_ptr)[i] >> 4; + } + if(odd) + { + *ie_ptr += 7; + }else{ + id[i*2+1] = (*ie_ptr)[i] & 0xF; + *ie_ptr += 8; + } + + err = LIBLTE_SUCCESS; + }else if(LIBLTE_MME_MOBILE_ID_TYPE_TMSI == mobile_id->type_of_id){ + *ie_ptr += 1; + mobile_id->tmsi = (**ie_ptr) << 24; + *ie_ptr += 1; + mobile_id->tmsi |= (**ie_ptr) << 16; + *ie_ptr += 1; + mobile_id->tmsi |= (**ie_ptr) << 8; + *ie_ptr += 1; + mobile_id->tmsi |= **ie_ptr; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + }else if(LIBLTE_MME_MOBILE_ID_TYPE_TMGI == mobile_id->type_of_id){ + mobile_id->tmgi.mbms_session_id_ind = ((**ie_ptr) >> 5) & 0x01; + mobile_id->tmgi.mcc_mnc_ind = ((**ie_ptr) >> 4) & 0x01; + *ie_ptr += 1; + mobile_id->tmgi.mbms_service_id = (**ie_ptr) << 16; + *ie_ptr += 1; + mobile_id->tmgi.mbms_service_id |= (**ie_ptr) << 8; + *ie_ptr += 1; + mobile_id->tmgi.mbms_service_id |= **ie_ptr; + *ie_ptr += 1; + if(mobile_id->tmgi.mcc_mnc_ind) + { + mobile_id->tmgi.mcc = ((**ie_ptr) & 0x0F)*100; + mobile_id->tmgi.mcc += (((**ie_ptr) >> 4) & 0x0F)*10; + *ie_ptr += 1; + mobile_id->tmgi.mcc += (**ie_ptr) & 0x0F; + if(((**ie_ptr) & 0xF0) == 0xF0) + { + *ie_ptr += 1; + mobile_id->tmgi.mnc = ((**ie_ptr) & 0x0F)*10; + mobile_id->tmgi.mnc += ((**ie_ptr) >> 4) & 0x0F; + }else{ + mobile_id->tmgi.mnc = ((**ie_ptr) >> 4) & 0x0F; + *ie_ptr += 1; + mobile_id->tmgi.mnc += ((**ie_ptr) & 0x0F)*100; + mobile_id->tmgi.mnc += (((**ie_ptr) >> 4) & 0x0F)*10; + } + *ie_ptr += 1; + } + if(mobile_id->tmgi.mbms_session_id_ind) + { + mobile_id->tmgi.mbms_session_id = **ie_ptr; + *ie_ptr += 1; + } + + err = LIBLTE_SUCCESS; + } + } + + return(err); +} /********************************************************************* IE Name: Mobile Station Classmark 2 @@ -226,10 +543,25 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_mobile_station_classmark_2_ie(LIBLTE_MME_MOBIL if(ms_cm2 != NULL && ie_ptr != NULL) { - // FIXME - **ie_ptr = 3; - *ie_ptr += 1; - *ie_ptr += 3; + (*ie_ptr)[0] = 3; + (*ie_ptr)[1] = (ms_cm2->rev_lev & 0x03) << 5; + (*ie_ptr)[1] |= ms_cm2->es_ind << 4; + (*ie_ptr)[1] |= ms_cm2->a5_1 << 3; + (*ie_ptr)[1] |= ms_cm2->rf_power_cap & 0x07; + (*ie_ptr)[2] = ms_cm2->ps_cap << 6; + (*ie_ptr)[2] |= (ms_cm2->ss_screen_ind & 0x03) << 4; + (*ie_ptr)[2] |= ms_cm2->sm_cap << 3; + (*ie_ptr)[2] |= ms_cm2->vbs << 2; + (*ie_ptr)[2] |= ms_cm2->vgcs << 1; + (*ie_ptr)[2] |= ms_cm2->fc; + (*ie_ptr)[3] = ms_cm2->cm3 << 7; + (*ie_ptr)[3] |= ms_cm2->lcsva_cap << 5; + (*ie_ptr)[3] |= ms_cm2->ucs2 << 4; + (*ie_ptr)[3] |= ms_cm2->solsa << 3; + (*ie_ptr)[3] |= ms_cm2->cmsp << 2; + (*ie_ptr)[3] |= ms_cm2->a5_3 << 1; + (*ie_ptr)[3] |= ms_cm2->a5_2; + *ie_ptr += 4; err = LIBLTE_SUCCESS; } @@ -244,8 +576,24 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_station_classmark_2_ie(uint8 if(ie_ptr != NULL && ms_cm2 != NULL) { - // FIXME - *ie_ptr += 4; + ms_cm2->rev_lev = (LIBLTE_MME_REVISION_LEVEL_ENUM)(((*ie_ptr)[1] >> 5) & 0x03); + ms_cm2->es_ind = ((*ie_ptr)[1] >> 4) & 0x01; + ms_cm2->a5_1 = ((*ie_ptr)[1] >> 3) & 0x01; + ms_cm2->rf_power_cap = (LIBLTE_MME_RF_POWER_CAPABILITY_ENUM)((*ie_ptr)[1] & 0x07); + ms_cm2->ps_cap = ((*ie_ptr)[2] >> 6) & 0x01; + ms_cm2->ss_screen_ind = (LIBLTE_MME_SS_SCREEN_INDICATOR_ENUM)(((*ie_ptr)[2] >> 4) & 0x03); + ms_cm2->sm_cap = ((*ie_ptr)[2] >> 3) & 0x01; + ms_cm2->vbs = ((*ie_ptr)[2] >> 2) & 0x01; + ms_cm2->vgcs = ((*ie_ptr)[2] >> 1) & 0x01; + ms_cm2->fc = (*ie_ptr)[2] & 0x01; + ms_cm2->cm3 = ((*ie_ptr)[3] >> 7) & 0x01; + ms_cm2->lcsva_cap = ((*ie_ptr)[3] >> 5) & 0x01; + ms_cm2->ucs2 = ((*ie_ptr)[3] >> 4) & 0x01; + ms_cm2->solsa = ((*ie_ptr)[3] >> 3) & 0x01; + ms_cm2->cmsp = ((*ie_ptr)[3] >> 2) & 0x01; + ms_cm2->a5_3 = ((*ie_ptr)[3] >> 1) & 0x01; + ms_cm2->a5_2 = (*ie_ptr)[3] & 0x01; + *ie_ptr += 4; err = LIBLTE_SUCCESS; } @@ -265,354 +613,706 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_station_classmark_2_ie(uint8 LIBLTE_ERROR_ENUM liblte_mme_pack_mobile_station_classmark_3_ie(LIBLTE_MME_MOBILE_STATION_CLASSMARK_3_STRUCT *ms_cm3, uint8 **ie_ptr) { - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_BIT_MSG_STRUCT bit_msg; + uint8 *msg_ptr = bit_msg.msg; + uint32 i; if(ms_cm3 != NULL && ie_ptr != NULL) { - // FIXME - - err = LIBLTE_SUCCESS; - } + // Multi Band Support + liblte_value_2_bits(ms_cm3->multi_band_support.pgsm_support, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->multi_band_support.e_rgsm_support, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->multi_band_support.gsm_1800_support, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->multi_band_support.a5_7, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->multi_band_support.a5_6, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->multi_band_support.a5_5, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->multi_band_support.a5_4, &msg_ptr, 1); + if(ms_cm3->multi_band_support.pgsm_support && + (ms_cm3->multi_band_support.e_rgsm_support || + ms_cm3->multi_band_support.gsm_1800_support)) + { + liblte_value_2_bits(ms_cm3->multi_band_support.assoc_radio_cap_2, &msg_ptr, 4); + liblte_value_2_bits(ms_cm3->multi_band_support.assoc_radio_cap_1, &msg_ptr, 4); + }else if(ms_cm3->multi_band_support.pgsm_support || + ms_cm3->multi_band_support.e_rgsm_support || + ms_cm3->multi_band_support.gsm_1800_support){ + liblte_value_2_bits(0, &msg_ptr, 4); + liblte_value_2_bits(ms_cm3->multi_band_support.assoc_radio_cap_1, &msg_ptr, 4); + } - return(err); -} -LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_station_classmark_3_ie(uint8 **ie_ptr, - LIBLTE_MME_MOBILE_STATION_CLASSMARK_3_STRUCT *ms_cm3) -{ - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + // R Support + if(ms_cm3->r_support_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->r_support, &msg_ptr, 3); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - if(ie_ptr != NULL && - ms_cm3 != NULL) - { - // FIXME + // HSCSD Multi Slot Capability + if(ms_cm3->hscsd_multi_slot_cap_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->hscsd_multi_slot_cap, &msg_ptr, 5); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - err = LIBLTE_SUCCESS; - } + // UCS2 Treatment + liblte_value_2_bits(ms_cm3->ucs2_treatment, &msg_ptr, 1); - return(err); -} + // Extended Measurement Capability + liblte_value_2_bits(ms_cm3->ext_meas_cap, &msg_ptr, 1); -/********************************************************************* - IE Name: NAS Security Parameters From E-UTRA + // MS Measurement Capability + if(ms_cm3->ms_meas_cap_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->ms_meas_cap.sms_value, &msg_ptr, 4); + liblte_value_2_bits(ms_cm3->ms_meas_cap.sm_value, &msg_ptr, 4); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - Description: Provides the UE with information that enables the UE - to create a mapped UMTS security context. + // MS Positioning Method Capability + if(ms_cm3->ms_pos_method_cap_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->ms_pos_method_cap, &msg_ptr, 5); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - Document Reference: 24.301 v10.2.0 Section 9.9.2.6 -*********************************************************************/ -// FIXME + // ECSD Multi Slot Capability + if(ms_cm3->ecsd_multi_slot_cap_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->ecsd_multi_slot_cap, &msg_ptr, 5); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } -/********************************************************************* - IE Name: NAS Security Parameters To E-UTRA + // 8-PSK Struct + if(ms_cm3->eight_psk_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->eight_psk.modulation_cap, &msg_ptr, 1); + if(ms_cm3->eight_psk.eight_psk_rf_power_cap_1_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->eight_psk.eight_psk_rf_power_cap_1, &msg_ptr, 2); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } + if(ms_cm3->eight_psk.eight_psk_rf_power_cap_2_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->eight_psk.eight_psk_rf_power_cap_2, &msg_ptr, 2); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - Description: Provides the UE with parameters that enables the UE - to create a mapped EPS security context and take - this context into use after inter-system handover to - S1 mode. + // GSM 400 + if(ms_cm3->gsm400_support_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->gsm400_support.gsm450_support, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->gsm400_support.gsm480_support, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->gsm400_support.assoc_radio_cap, &msg_ptr, 4); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - Document Reference: 24.301 v10.2.0 Section 9.9.2.7 -*********************************************************************/ -// FIXME + // GSM 850 Associated Radio Capability + if(ms_cm3->gsm850_assoc_radio_cap_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->gsm850_assoc_radio_cap, &msg_ptr, 4); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } -/********************************************************************* - IE Name: PLMN List + // GSM 1900 Associated Radio Capability + if(ms_cm3->gsm1900_assoc_radio_cap_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->gsm1900_assoc_radio_cap, &msg_ptr, 4); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - Description: Provides a list of PLMN codes to the UE. + // UMTS FDD Radio Access Technology Capability + liblte_value_2_bits(ms_cm3->umts_fdd_rat_cap, &msg_ptr, 1); - Document Reference: 24.301 v10.2.0 Section 9.9.2.8 - 24.008 v10.2.0 Section 10.5.1.13 -*********************************************************************/ -// FIXME + // UMTS 3.84 Mcps TDD Radio Access Technology Capability + liblte_value_2_bits(ms_cm3->umts_3_84_mcps_tdd_rat_cap, &msg_ptr, 1); -/********************************************************************* - IE Name: Spare Half Octet + // CDMA 2000 Radio Access Technology Capability + liblte_value_2_bits(ms_cm3->cdma2000_rat_cap, &msg_ptr, 1); - Description: Used in the description of EMM and ESM messages when - an odd number of half octet type 1 information - elements are used. + // Dual Transfer Mode + if(ms_cm3->dtm_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->dtm.dtm_gprs_multi_slot_class, &msg_ptr, 2); + liblte_value_2_bits(ms_cm3->dtm.single_slot_dtm, &msg_ptr, 1); + if(ms_cm3->dtm.dtm_egprs_multi_slot_class_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->dtm.dtm_egprs_multi_slot_class, &msg_ptr, 2); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - Document Reference: 24.301 v10.2.0 Section 9.9.2.9 -*********************************************************************/ -// FIXME + // Single Band Support + if(ms_cm3->single_band_support_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->single_band_support, &msg_ptr, 4); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } -/********************************************************************* - IE Name: Supported Codec List + // GSM 750 Associated Radio Capability + if(ms_cm3->gsm750_assoc_radio_cap_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->gsm750_assoc_radio_cap, &msg_ptr, 4); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - Description: Provides the network with information about the - speech codecs supported by the UE. + // UMTS 1.28 Mcps TDD Radio Access Technology Capability + liblte_value_2_bits(ms_cm3->umts_1_28_mcps_tdd_rat_cap, &msg_ptr, 1); - Document Reference: 24.301 v10.2.0 Section 9.9.2.10 - 24.008 v10.2.0 Section 10.5.4.32 -*********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_supported_codec_list_ie(LIBLTE_MME_SUPPORTED_CODEC_LIST_STRUCT *supported_codec_list, - uint8 **ie_ptr) -{ - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + // GERAN Feature Package + liblte_value_2_bits(ms_cm3->geran_feature_package, &msg_ptr, 1); - if(supported_codec_list != NULL && - ie_ptr != NULL) - { - // FIXME - **ie_ptr = 0; - *ie_ptr += 1; + // Extended Dual Transfer Mode + if(ms_cm3->ext_dtm_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->ext_dtm.extended_dtm_gprs_multi_slot_class, &msg_ptr, 2); + liblte_value_2_bits(ms_cm3->ext_dtm.extended_dtm_egprs_multi_slot_class, &msg_ptr, 2); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - err = LIBLTE_SUCCESS; - } + // High Multislot Capability + if(ms_cm3->high_multi_slot_cap_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->high_multi_slot_cap, &msg_ptr, 2); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - return(err); -} -LIBLTE_ERROR_ENUM liblte_mme_unpack_supported_codec_list_ie(uint8 **ie_ptr, - LIBLTE_MME_SUPPORTED_CODEC_LIST_STRUCT *supported_codec_list) -{ - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + // GERAN Iu Mode Capabilities + if(ms_cm3->geran_iu_mode_cap_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->geran_iu_mode_cap.flo_iu_cap, &msg_ptr, 1); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - if(ie_ptr != NULL && - supported_codec_list != NULL) - { - // FIXME - *ie_ptr += **ie_ptr; + // GERAN Feature Package 2 + liblte_value_2_bits(ms_cm3->geran_feature_package_2, &msg_ptr, 1); - err = LIBLTE_SUCCESS; - } + // GMSK Multi Slot Power Profile + liblte_value_2_bits(ms_cm3->gmsk_multi_slot_power_profile, &msg_ptr, 2); - return(err); -} + // 8-PSK Multi Slot Power Profile + liblte_value_2_bits(ms_cm3->eight_psk_multi_slot_power_profile, &msg_ptr, 2); -/********************************************************************* - IE Name: Additional Update Result + // T-GSM 400 Support + if(ms_cm3->tgsm400_support_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->tgsm400_support.tgsm_410_support, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->tgsm400_support.tgsm_380_support, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->tgsm400_support.assoc_radio_cap, &msg_ptr, 4); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - Description: Provides additional information about the result of - a combined attached procedure or a combined tracking - area updating procedure. + // -0- + liblte_value_2_bits(0, &msg_ptr, 1); - Document Reference: 24.301 v10.2.0 Section 9.9.3.0A -*********************************************************************/ -// FIXME + // Downlink Advanced Receiver Performance + liblte_value_2_bits(ms_cm3->darp, &msg_ptr, 2); -/********************************************************************* - IE Name: Additional Update Type + // DTM Enhancements Capability + liblte_value_2_bits(ms_cm3->dtm_enhancements_cap, &msg_ptr, 1); - Description: Provides additional information about the type of - request for a combined attach or a combined tracking - area updating procedure. + // DTM High Multi Slot + if(ms_cm3->dtm_high_multi_slot_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->dtm_high_multi_slot.dtm_gprs_high_multi_slot_class, &msg_ptr, 3); + liblte_value_2_bits(ms_cm3->dtm_high_multi_slot.offset_required, &msg_ptr, 1); + if(ms_cm3->dtm_high_multi_slot.dtm_egprs_high_multi_slot_class_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->dtm_high_multi_slot.dtm_egprs_high_multi_slot_class, &msg_ptr, 3); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.0B -*********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_additional_update_type_ie(LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_ENUM aut, - uint8 bit_offset, - uint8 **ie_ptr) -{ - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + // Repeated ACCH Capability + liblte_value_2_bits(ms_cm3->repeated_acch_cap, &msg_ptr, 1); - if(ie_ptr != NULL) - { - **ie_ptr |= aut << bit_offset; + // GSM 710 Associated Radio Capability + if(ms_cm3->gsm710_assoc_radio_cap_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->gsm710_assoc_radio_cap, &msg_ptr, 4); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } + + // T-GSM 810 Associated Radio Capability + if(ms_cm3->tgsm810_assoc_radio_cap_present) + { + liblte_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(ms_cm3->tgsm810_assoc_radio_cap, &msg_ptr, 4); + }else{ + liblte_value_2_bits(0, &msg_ptr, 1); + } + + // Ciphering Mode Setting Capability + liblte_value_2_bits(ms_cm3->ciphering_mode_setting_cap, &msg_ptr, 1); + + // Additional Positioning Capabilities + liblte_value_2_bits(ms_cm3->additional_pos_cap, &msg_ptr, 1); + + // E-UTRA FDD Support + liblte_value_2_bits(ms_cm3->eutra_fdd_support, &msg_ptr, 1); + + // E-UTRA TDD Support + liblte_value_2_bits(ms_cm3->eutra_tdd_support, &msg_ptr, 1); + + // E-UTRA Measurement And Reporting Support + liblte_value_2_bits(ms_cm3->eutra_meas_and_reporting_support, &msg_ptr, 1); + + // Priority-based Reselection Support + liblte_value_2_bits(ms_cm3->prio_based_reselection_support, &msg_ptr, 1); + + // UTRA CSG Cells Reporting + liblte_value_2_bits(ms_cm3->utra_csg_cells_reporting, &msg_ptr, 1); + + // VAMOS Level + liblte_value_2_bits(ms_cm3->vamos_level, &msg_ptr, 2); + + // Fill in the number of bits used + bit_msg.N_bits = msg_ptr - bit_msg.msg; + + // Pad to an octet boundry + if((bit_msg.N_bits % 8) != 0) + { + liblte_value_2_bits(0, &msg_ptr, 8 - (bit_msg.N_bits % 8)); + bit_msg.N_bits += 8 - (bit_msg.N_bits % 8); + } + + // Pack into byte message + msg_ptr = bit_msg.msg; + for(i=0; i> bit_offset) & 0x01); + // Pack into bit message + for(i=0; imulti_band_support.pgsm_support = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->multi_band_support.e_rgsm_support = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->multi_band_support.gsm_1800_support = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->multi_band_support.a5_7 = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->multi_band_support.a5_6 = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->multi_band_support.a5_5 = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->multi_band_support.a5_4 = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->multi_band_support.pgsm_support && + (ms_cm3->multi_band_support.e_rgsm_support || + ms_cm3->multi_band_support.gsm_1800_support)) + { + ms_cm3->multi_band_support.assoc_radio_cap_2 = liblte_bits_2_value(&msg_ptr, 4); + ms_cm3->multi_band_support.assoc_radio_cap_1 = liblte_bits_2_value(&msg_ptr, 4); + }else if(ms_cm3->multi_band_support.pgsm_support || + ms_cm3->multi_band_support.e_rgsm_support || + ms_cm3->multi_band_support.gsm_1800_support){ + liblte_bits_2_value(&msg_ptr, 4); + ms_cm3->multi_band_support.assoc_radio_cap_1 = liblte_bits_2_value(&msg_ptr, 4); + } - err = LIBLTE_SUCCESS; - } + // R Support + ms_cm3->r_support_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->r_support_present) + { + ms_cm3->r_support = liblte_bits_2_value(&msg_ptr, 3); + } - return(err); -} + // HSCSD Multi Slot Capability + ms_cm3->hscsd_multi_slot_cap_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->hscsd_multi_slot_cap_present) + { + ms_cm3->hscsd_multi_slot_cap = liblte_bits_2_value(&msg_ptr, 5); + } -/********************************************************************* - IE Name: Authentication Failure Parameter + // UCS2 Treatment + ms_cm3->ucs2_treatment = liblte_bits_2_value(&msg_ptr, 1); - Description: Provides the network with the necessary information - to begin a re-authentication procedure in the case - of a 'Synch failure', following a UMTS or EPS - authentication challenge. + // Extended Measurement Capability + ms_cm3->ext_meas_cap = liblte_bits_2_value(&msg_ptr, 1); - Document Reference: 24.301 v10.2.0 Section 9.9.3.1 - 24.008 v10.2.0 Section 10.5.3.2.2 -*********************************************************************/ -// FIXME + // MS Measurement Capability + ms_cm3->ms_meas_cap_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->ms_meas_cap_present) + { + ms_cm3->ms_meas_cap.sms_value = liblte_bits_2_value(&msg_ptr, 4); + ms_cm3->ms_meas_cap.sm_value = liblte_bits_2_value(&msg_ptr, 4); + } -/********************************************************************* - IE Name: Authentication Parameter AUTN + // MS Positioning Method Capability + ms_cm3->ms_pos_method_cap_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->ms_pos_method_cap_present) + { + ms_cm3->ms_pos_method_cap = liblte_bits_2_value(&msg_ptr, 5); + } - Description: Provides the UE with a means of authenticating the - network. + // ECSD Multi Slot Capability + ms_cm3->ecsd_multi_slot_cap_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->ecsd_multi_slot_cap_present) + { + ms_cm3->ecsd_multi_slot_cap = liblte_bits_2_value(&msg_ptr, 5); + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.2 - 24.008 v10.2.0 Section 10.5.3.1.1 -*********************************************************************/ -// FIXME + // 8-PSK Struct + ms_cm3->eight_psk_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->eight_psk_present) + { + ms_cm3->eight_psk.modulation_cap = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->eight_psk.eight_psk_rf_power_cap_1_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->eight_psk.eight_psk_rf_power_cap_1_present) + { + ms_cm3->eight_psk.eight_psk_rf_power_cap_1 = liblte_bits_2_value(&msg_ptr, 2); + } + ms_cm3->eight_psk.eight_psk_rf_power_cap_2_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->eight_psk.eight_psk_rf_power_cap_2_present) + { + ms_cm3->eight_psk.eight_psk_rf_power_cap_2 = liblte_bits_2_value(&msg_ptr, 2); + } + } -/********************************************************************* - IE Name: Authentication Parameter RAND + // GSM 400 + ms_cm3->gsm400_support_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->gsm400_support_present) + { + ms_cm3->gsm400_support.gsm450_support = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->gsm400_support.gsm480_support = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->gsm400_support.assoc_radio_cap = liblte_bits_2_value(&msg_ptr, 4); + } - Description: Provides the UE with a non-predictable number to be - used to calculate the authentication signature SRES - and the ciphering key Kc (for a GSM authentication - challenge), or the response RES and both the - ciphering key CK and the integrity key IK (for a - UMTS authentication challenge). + // GSM 850 Associated Radio Capability + ms_cm3->gsm850_assoc_radio_cap_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->gsm850_assoc_radio_cap_present) + { + ms_cm3->gsm850_assoc_radio_cap = liblte_bits_2_value(&msg_ptr, 4); + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.3 - 24.008 v10.2.0 Section 10.5.3.1 -*********************************************************************/ -// FIXME + // GSM 1900 Associated Radio Capability + ms_cm3->gsm1900_assoc_radio_cap_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->gsm1900_assoc_radio_cap_present) + { + ms_cm3->gsm1900_assoc_radio_cap = liblte_bits_2_value(&msg_ptr, 4); + } -/********************************************************************* - IE Name: Authentication Response Parameter + // UMTS FDD Radio Access Technology Capability + ms_cm3->umts_fdd_rat_cap = liblte_bits_2_value(&msg_ptr, 1); - Description: Provides the network with the authentication - response calculated in the USIM. + // UMTS 3.84 Mcps TDD Radio Access Technology Capability + ms_cm3->umts_3_84_mcps_tdd_rat_cap = liblte_bits_2_value(&msg_ptr, 1); - Document Reference: 24.301 v10.2.0 Section 9.9.3.4 -*********************************************************************/ -// FIXME + // CDMA 2000 Radio Access Technology Capability + ms_cm3->cdma2000_rat_cap = liblte_bits_2_value(&msg_ptr, 1); -/********************************************************************* - IE Name: Ciphering Key Sequence Number + // Dual Transfer Mode + ms_cm3->dtm_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->dtm_present) + { + ms_cm3->dtm.dtm_gprs_multi_slot_class = liblte_bits_2_value(&msg_ptr, 2); + ms_cm3->dtm.single_slot_dtm = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->dtm.dtm_egprs_multi_slot_class_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->dtm.dtm_egprs_multi_slot_class_present) + { + ms_cm3->dtm.dtm_egprs_multi_slot_class = liblte_bits_2_value(&msg_ptr, 2); + } + } - Description: Makes it possible for the network to identify the - ciphering key Kc which is stored in the UE without - invoking the authentication procedure. + // Single Band Support + ms_cm3->single_band_support_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->single_band_support_present) + { + ms_cm3->single_band_support = liblte_bits_2_value(&msg_ptr, 4); + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.4A - 24.008 v10.2.0 Section 10.5.1.2 -*********************************************************************/ -// FIXME + // GSM 750 Associated Radio Capability + ms_cm3->gsm750_assoc_radio_cap_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->gsm750_assoc_radio_cap_present) + { + ms_cm3->gsm750_assoc_radio_cap = liblte_bits_2_value(&msg_ptr, 4); + } -/********************************************************************* - IE Name: CSFB Response + // UMTS 1.28 Mcps TDD Radio Access Technology Capability + ms_cm3->umts_1_28_mcps_tdd_rat_cap = liblte_bits_2_value(&msg_ptr, 1); - Description: Indicates whether the UE accepts or rejects a paging - for CS fallback. + // GERAN Feature Package + ms_cm3->geran_feature_package = liblte_bits_2_value(&msg_ptr, 1); - Document Reference: 24.301 v10.2.0 Section 9.9.3.5 -*********************************************************************/ -// FIXME + // Extended Dual Transfer Mode + ms_cm3->ext_dtm_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->ext_dtm_present) + { + ms_cm3->ext_dtm.extended_dtm_gprs_multi_slot_class = liblte_bits_2_value(&msg_ptr, 2); + ms_cm3->ext_dtm.extended_dtm_egprs_multi_slot_class = liblte_bits_2_value(&msg_ptr, 2); + } -/********************************************************************* - IE Name: Daylight Savings Time + // High Multislot Capability + ms_cm3->high_multi_slot_cap_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->high_multi_slot_cap_present) + { + ms_cm3->high_multi_slot_cap = liblte_bits_2_value(&msg_ptr, 2); + } - Description: Encodes the daylight savings time in steps of 1 hour. + // GERAN Iu Mode Capabilities + ms_cm3->geran_iu_mode_cap_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->geran_iu_mode_cap_present) + { + length = liblte_bits_2_value(&msg_ptr, 4); + ms_cm3->geran_iu_mode_cap.flo_iu_cap = liblte_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, length - 1); + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.6 - 24.008 v10.2.0 Section 10.5.3.12 -*********************************************************************/ -// FIXME + // GERAN Feature Package 2 + ms_cm3->geran_feature_package_2 = liblte_bits_2_value(&msg_ptr, 1); -/********************************************************************* - IE Name: Detach Type + // GMSK Multi Slot Power Profile + ms_cm3->gmsk_multi_slot_power_profile = liblte_bits_2_value(&msg_ptr, 2); - Description: Indicates the type of detach. + // 8-PSK Multi Slot Power Profile + ms_cm3->eight_psk_multi_slot_power_profile = liblte_bits_2_value(&msg_ptr, 2); - Document Reference: 24.301 v10.2.0 Section 9.9.3.7 -*********************************************************************/ -// FIXME + // T-GSM 400 Support + ms_cm3->tgsm400_support_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->tgsm400_support_present) + { + ms_cm3->tgsm400_support.tgsm_410_support = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->tgsm400_support.tgsm_380_support = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->tgsm400_support.assoc_radio_cap = liblte_bits_2_value(&msg_ptr, 4); + } -/********************************************************************* - IE Name: DRX Parameter + // -0- + liblte_bits_2_value(&msg_ptr, 1); - Description: Indicates whether the UE uses DRX mode or not. + // Downlink Advanced Receiver Performance + ms_cm3->darp = liblte_bits_2_value(&msg_ptr, 2); - Document Reference: 24.301 v10.2.0 Section 9.9.3.8 - 24.008 v10.2.0 Section 10.5.5.6 -*********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_drx_parameter_ie(LIBLTE_MME_DRX_PARAMETER_STRUCT *drx_param, - uint8 **ie_ptr) -{ - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + // DTM Enhancements Capability + ms_cm3->dtm_enhancements_cap = liblte_bits_2_value(&msg_ptr, 1); - if(drx_param != NULL && - ie_ptr != NULL) - { - // FIXME - *ie_ptr += 2; + // DTM High Multi Slot + ms_cm3->dtm_high_multi_slot_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->dtm_high_multi_slot_present) + { + ms_cm3->dtm_high_multi_slot.dtm_gprs_high_multi_slot_class = liblte_bits_2_value(&msg_ptr, 3); + ms_cm3->dtm_high_multi_slot.offset_required = liblte_bits_2_value(&msg_ptr, 1); + ms_cm3->dtm_high_multi_slot.dtm_egprs_high_multi_slot_class_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->dtm_high_multi_slot.dtm_egprs_high_multi_slot_class_present) + { + ms_cm3->dtm_high_multi_slot.dtm_egprs_high_multi_slot_class = liblte_bits_2_value(&msg_ptr, 3); + } + } - err = LIBLTE_SUCCESS; - } + // Repeated ACCH Capability + ms_cm3->repeated_acch_cap = liblte_bits_2_value(&msg_ptr, 1); - return(err); -} -LIBLTE_ERROR_ENUM liblte_mme_unpack_drx_parameter_ie(uint8 **ie_ptr, - LIBLTE_MME_DRX_PARAMETER_STRUCT *drx_param) -{ - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + // GSM 710 Associated Radio Capability + ms_cm3->gsm710_assoc_radio_cap_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->gsm710_assoc_radio_cap_present) + { + ms_cm3->gsm710_assoc_radio_cap = liblte_bits_2_value(&msg_ptr, 4); + } - if(ie_ptr != NULL && - drx_param != NULL) - { - // FIXME - *ie_ptr += 2; + // T-GSM 810 Associated Radio Capability + ms_cm3->tgsm810_assoc_radio_cap_present = liblte_bits_2_value(&msg_ptr, 1); + if(ms_cm3->tgsm810_assoc_radio_cap_present) + { + ms_cm3->tgsm810_assoc_radio_cap = liblte_bits_2_value(&msg_ptr, 4); + } - err = LIBLTE_SUCCESS; - } + // Ciphering Mode Setting Capability + ms_cm3->ciphering_mode_setting_cap = liblte_bits_2_value(&msg_ptr, 1); - return(err); -} + // Additional Positioning Capabilities + ms_cm3->additional_pos_cap = liblte_bits_2_value(&msg_ptr, 1); -/********************************************************************* - IE Name: EMM Cause + // E-UTRA FDD Support + ms_cm3->eutra_fdd_support = liblte_bits_2_value(&msg_ptr, 1); - Description: Indicates the reason why an EMM request from the UE - is rejected by the network. + // E-UTRA TDD Support + ms_cm3->eutra_tdd_support = liblte_bits_2_value(&msg_ptr, 1); - Document Reference: 24.301 v10.2.0 Section 9.9.3.9 -*********************************************************************/ -// FIXME + // E-UTRA Measurement And Reporting Support + ms_cm3->eutra_meas_and_reporting_support = liblte_bits_2_value(&msg_ptr, 1); + + // Priority-based Reselection Support + ms_cm3->prio_based_reselection_support = liblte_bits_2_value(&msg_ptr, 1); + + // UTRA CSG Cells Reporting + ms_cm3->utra_csg_cells_reporting = liblte_bits_2_value(&msg_ptr, 1); + + // VAMOS Level + ms_cm3->vamos_level = liblte_bits_2_value(&msg_ptr, 2); + + // Fill in the number of bits used + bit_msg.N_bits = msg_ptr - bit_msg.msg; + if((bit_msg.N_bits % 8) != 0) + { + bit_msg.N_bits += 8 - (bit_msg.N_bits % 8); + } + + *ie_ptr += bit_msg.N_bits/8; + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - IE Name: EPS Attach Result + IE Name: NAS Security Parameters From E-UTRA - Description: Specifies the result of an attach procedure. + Description: Provides the UE with information that enables the UE + to create a mapped UMTS security context. - Document Reference: 24.301 v10.2.0 Section 9.9.3.10 + Document Reference: 24.301 v10.2.0 Section 9.9.2.6 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_nas_security_parameters_from_eutra_ie(uint8 dl_nas_count, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = dl_nas_count & 0x0F; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_security_parameters_from_eutra_ie(uint8 **ie_ptr, + uint8 *dl_nas_count) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + dl_nas_count != NULL) + { + *dl_nas_count = (*ie_ptr)[0]; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - IE Name: EPS Attach Type + IE Name: NAS Security Parameters To E-UTRA - Description: Indicates the type of the requested attach. + Description: Provides the UE with parameters that enables the UE + to create a mapped EPS security context and take + this context into use after inter-system handover to + S1 mode. - Document Reference: 24.301 v10.2.0 Section 9.9.3.11 + Document Reference: 24.301 v10.2.0 Section 9.9.2.7 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_eps_attach_type_ie(uint8 attach_type, - uint8 bit_offset, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_nas_security_parameters_to_eutra_ie(LIBLTE_MME_NAS_SECURITY_PARAMETERS_TO_EUTRA_STRUCT *sec_params, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL) + if(sec_params != NULL && + ie_ptr != NULL) { - **ie_ptr |= attach_type << bit_offset; + (*ie_ptr)[0] = (sec_params->nonce_mme >> 24) & 0xFF; + (*ie_ptr)[1] = (sec_params->nonce_mme >> 16) & 0xFF; + (*ie_ptr)[2] = (sec_params->nonce_mme >> 8) & 0xFF; + (*ie_ptr)[3] = sec_params->nonce_mme & 0xFF; + (*ie_ptr)[4] = (sec_params->eea & 0x07) << 4; + (*ie_ptr)[4] |= sec_params->eia & 0x07; + (*ie_ptr)[5] = (sec_params->tsc_flag & 0x01) << 3; + (*ie_ptr)[5] |= sec_params->nas_ksi & 0x07; + *ie_ptr += 6; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_attach_type_ie(uint8 **ie_ptr, - uint8 bit_offset, - uint8 *attach_type) +LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_security_parameters_to_eutra_ie(uint8 **ie_ptr, + LIBLTE_MME_NAS_SECURITY_PARAMETERS_TO_EUTRA_STRUCT *sec_params) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL && - attach_type != NULL) + if(ie_ptr != NULL && + sec_params != NULL) { - *attach_type = (**ie_ptr >> bit_offset) & 0x07; + sec_params->nonce_mme = (*ie_ptr)[0] << 24; + sec_params->nonce_mme |= (*ie_ptr)[1] << 16; + sec_params->nonce_mme |= (*ie_ptr)[2] << 8; + sec_params->nonce_mme |= (*ie_ptr)[3]; + sec_params->eea = (LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM)(((*ie_ptr)[4] >> 4) & 0x07); + sec_params->eia = (LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM)((*ie_ptr)[4] & 0x07); + sec_params->tsc_flag = (LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM)(((*ie_ptr)[5] >> 3) & 0x01); + sec_params->nas_ksi = (*ie_ptr)[5] & 0x07; + *ie_ptr += 6; err = LIBLTE_SUCCESS; } @@ -621,145 +1321,68 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_attach_type_ie(uint8 **ie_ptr, } /********************************************************************* - IE Name: EPS Mobile Identity + IE Name: PLMN List - Description: Provides either the IMSI, the GUTI, or the IMEI. + Description: Provides a list of PLMN codes to the UE. - Document Reference: 24.301 v10.2.0 Section 9.9.3.12 + Document Reference: 24.301 v10.2.0 Section 9.9.2.8 + 24.008 v10.2.0 Section 10.5.1.13 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_eps_mobile_id_ie(LIBLTE_MME_EPS_MOBILE_ID_STRUCT *eps_mobile_id, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_plmn_list_ie(LIBLTE_MME_PLMN_LIST_STRUCT *plmn_list, + uint8 **ie_ptr) { - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - uint8 *id; - uint32 i; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; - if(eps_mobile_id != NULL && - ie_ptr != NULL) + if(plmn_list != NULL && + ie_ptr != NULL) { - if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI == eps_mobile_id->type_of_id) + (*ie_ptr)[0] = plmn_list->N_plmns * 3; + for(i=0; iN_plmns; i++) { - **ie_ptr = 11; - *ie_ptr += 1; - **ie_ptr = 0xF0 | eps_mobile_id->type_of_id; - *ie_ptr += 1; - **ie_ptr = ((eps_mobile_id->guti.mcc/10) % 10) | ((eps_mobile_id->guti.mcc/100) % 10); - *ie_ptr += 1; - if(eps_mobile_id->guti.mcc > 100) - { - **ie_ptr = 0xF | (eps_mobile_id->guti.mcc % 10); - *ie_ptr += 1; - **ie_ptr = (eps_mobile_id->guti.mnc % 10) | ((eps_mobile_id->guti.mnc/10) % 10); - *ie_ptr += 1; - }else{ - **ie_ptr = (eps_mobile_id->guti.mnc % 10) | (eps_mobile_id->guti.mcc % 10); - *ie_ptr += 1; - **ie_ptr = ((eps_mobile_id->guti.mnc/10) % 10) | ((eps_mobile_id->guti.mnc/100) % 10); - *ie_ptr += 1; - } - **ie_ptr = (eps_mobile_id->guti.mme_group_id >> 8) & 0x0F; - *ie_ptr += 1; - **ie_ptr = eps_mobile_id->guti.mme_group_id & 0x0F; - *ie_ptr += 1; - **ie_ptr = eps_mobile_id->guti.mme_code; - *ie_ptr += 1; - **ie_ptr = (eps_mobile_id->guti.m_tmsi >> 24) & 0xFF; - *ie_ptr += 1; - **ie_ptr = (eps_mobile_id->guti.m_tmsi >> 16) & 0xFF; - *ie_ptr += 1; - **ie_ptr = (eps_mobile_id->guti.m_tmsi >> 8) & 0xFF; - *ie_ptr += 1; - **ie_ptr = eps_mobile_id->guti.m_tmsi & 0xFF; - *ie_ptr += 1; - }else{ - if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI == eps_mobile_id->type_of_id) + (*ie_ptr)[i*3+0] = (((plmn_list->mcc[i]/10) % 10) << 4) | ((plmn_list->mcc[i]/100) % 10); + if(plmn_list->mnc[i] < 100) { - id = eps_mobile_id->imsi; + (*ie_ptr)[i*3+1] = 0xF0 | (plmn_list->mcc[i] % 10); + (*ie_ptr)[i*3+2] = ((plmn_list->mnc[i] % 10) << 4) | ((plmn_list->mnc[i]/10) % 10); }else{ - id = eps_mobile_id->imei; - } - - **ie_ptr = (id[0] << 4) | (1 << 3) | eps_mobile_id->type_of_id; - *ie_ptr += 1; - for(i=0; i<7; i++) - { - **ie_ptr = (id[i*2+1] << 4) | id[i*2+2]; - *ie_ptr += 1; + (*ie_ptr)[i*3+1] = ((plmn_list->mnc[i] % 10) << 4) | (plmn_list->mcc[i] % 10); + (*ie_ptr)[i*3+2] = (((plmn_list->mnc[i]/10) % 10) << 4) | ((plmn_list->mnc[i]/100) % 10); } } + *ie_ptr += (plmn_list->N_plmns * 3) + 1; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_mobile_id_ie(uint8 **ie_ptr, - LIBLTE_MME_EPS_MOBILE_ID_STRUCT *eps_mobile_id) +LIBLTE_ERROR_ENUM liblte_mme_unpack_plmn_list_ie(uint8 **ie_ptr, + LIBLTE_MME_PLMN_LIST_STRUCT *plmn_list) { - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - uint8 *id; - uint32 length; - uint32 i; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; - if(ie_ptr != NULL && - eps_mobile_id != NULL) + if(ie_ptr != NULL && + plmn_list != NULL) { - length = **ie_ptr; - *ie_ptr += 1; - - eps_mobile_id->type_of_id = **ie_ptr & 0x07; - - if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI == eps_mobile_id->type_of_id) + plmn_list->N_plmns = (*ie_ptr)[0] / 3; + for(i=0; iN_plmns; i++) { - *ie_ptr += 1; - eps_mobile_id->guti.mcc = (**ie_ptr & 0x0F)*100; - eps_mobile_id->guti.mcc += ((**ie_ptr >> 4) & 0x0F)*10; - *ie_ptr += 1; - eps_mobile_id->guti.mcc += **ie_ptr & 0x0F; - if(((**ie_ptr >> 4) & 0x0F) == 0x0F) - { - *ie_ptr += 1; - eps_mobile_id->guti.mnc = (**ie_ptr & 0x0F)*10; - eps_mobile_id->guti.mnc += (**ie_ptr >> 4) & 0x0F; - *ie_ptr += 1; - }else{ - eps_mobile_id->guti.mnc = (**ie_ptr >> 4) & 0x0F; - *ie_ptr += 1; - eps_mobile_id->guti.mnc += (**ie_ptr & 0x0F)*100; - eps_mobile_id->guti.mnc += ((**ie_ptr >> 4) & 0x0F)*10; - *ie_ptr += 1; - } - eps_mobile_id->guti.mme_group_id = **ie_ptr << 8; - *ie_ptr += 1; - eps_mobile_id->guti.mme_group_id |= **ie_ptr; - *ie_ptr += 1; - eps_mobile_id->guti.mme_code = **ie_ptr; - *ie_ptr += 1; - eps_mobile_id->guti.m_tmsi = **ie_ptr << 24; - *ie_ptr += 1; - eps_mobile_id->guti.m_tmsi |= **ie_ptr << 16; - *ie_ptr += 1; - eps_mobile_id->guti.m_tmsi |= **ie_ptr << 8; - *ie_ptr += 1; - eps_mobile_id->guti.m_tmsi |= **ie_ptr; - *ie_ptr += 1; - }else{ - if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI == eps_mobile_id->type_of_id) + plmn_list->mcc[i] = ((*ie_ptr)[i*3+0] & 0x0F)*100; + plmn_list->mcc[i] += (((*ie_ptr)[i*3+0] >> 4) & 0x0F)*10; + plmn_list->mcc[i] += (*ie_ptr)[i*3+1] & 0x0F; + if((((*ie_ptr)[i*3+1] >> 4) & 0x0F) == 0x0F) { - id = eps_mobile_id->imsi; + plmn_list->mnc[i] = ((*ie_ptr)[i*3+2] & 0x0F)*10; + plmn_list->mnc[i] += ((*ie_ptr)[i*3+2] >> 4) & 0x0F; }else{ - id = eps_mobile_id->imei; - } - - id[0] = **ie_ptr >> 4; - *ie_ptr += 1; - for(i=0; i<7; i++) - { - id[i*2+1] = **ie_ptr >> 4; - id[i*2+2] = **ie_ptr & 0x0F; - *ie_ptr += 1; + plmn_list->mnc[i] = ((*ie_ptr)[i*3+1] >> 4) & 0x0F; + plmn_list->mnc[i] += ((*ie_ptr)[i*3+2] & 0x0F)*100; + plmn_list->mnc[i] += (((*ie_ptr)[i*3+2] >> 4) & 0x0F)*10; } } + *ie_ptr += (*ie_ptr)[0] + 1; err = LIBLTE_SUCCESS; } @@ -768,85 +1391,65 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_mobile_id_ie(uint8 } /********************************************************************* - IE Name: EPS Network Feature Support - - Description: Indicates whether certain features are supported by - the network. - - Document Reference: 24.301 v10.2.0 Section 9.9.3.12A -*********************************************************************/ -// FIXME - -/********************************************************************* - IE Name: EPS Update Result - - Description: Specifies the result of the associated updating - procedure. - - Document Reference: 24.301 v10.2.0 Section 9.9.3.13 -*********************************************************************/ -// FIXME - -/********************************************************************* - IE Name: EPS Update Type + IE Name: Spare Half Octet - Description: Specifies the area the updating procedure is - associated with. + Description: Used in the description of EMM and ESM messages when + an odd number of half octet type 1 information + elements are used. - Document Reference: 24.301 v10.2.0 Section 9.9.3.14 + Document Reference: 24.301 v10.2.0 Section 9.9.2.9 *********************************************************************/ -// FIXME /********************************************************************* - IE Name: ESM Message Container + IE Name: Supported Codec List - Description: Enables piggybacked transfer of a single ESM message - within an EMM message. + Description: Provides the network with information about the + speech codecs supported by the UE. - Document Reference: 24.301 v10.2.0 Section 9.9.3.15 + Document Reference: 24.301 v10.2.0 Section 9.9.2.10 + 24.008 v10.2.0 Section 10.5.4.32 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_esm_message_container_ie(LIBLTE_BYTE_MSG_STRUCT *esm_msg, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_supported_codec_list_ie(LIBLTE_MME_SUPPORTED_CODEC_LIST_STRUCT *supported_codec_list, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; - if(esm_msg != NULL && - ie_ptr != NULL) + if(supported_codec_list != NULL && + ie_ptr != NULL) { - **ie_ptr = esm_msg->N_bytes >> 8; - *ie_ptr += 1; - **ie_ptr = esm_msg->N_bytes & 0xFF; - *ie_ptr += 1; - for(i=0; iN_bytes; i++) + (*ie_ptr)[0] = supported_codec_list->N_supported_codecs*4; + for(i=0; iN_supported_codecs; i++) { - **ie_ptr = esm_msg->msg[i]; - *ie_ptr += 1; + (*ie_ptr)[1+i*4+0] = supported_codec_list->supported_codec[i].sys_id; + (*ie_ptr)[1+i*4+1] = 2; + (*ie_ptr)[1+i*4+2] = (supported_codec_list->supported_codec[i].codec_bitmap >> 8) & 0xFF; + (*ie_ptr)[1+i*4+3] = supported_codec_list->supported_codec[i].codec_bitmap & 0xFF; } + *ie_ptr += (supported_codec_list->N_supported_codecs*4) + 1; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8 **ie_ptr, - LIBLTE_BYTE_MSG_STRUCT *esm_msg) +LIBLTE_ERROR_ENUM liblte_mme_unpack_supported_codec_list_ie(uint8 **ie_ptr, + LIBLTE_MME_SUPPORTED_CODEC_LIST_STRUCT *supported_codec_list) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; - if(ie_ptr != NULL && - esm_msg != NULL) + if(ie_ptr != NULL && + supported_codec_list != NULL) { - esm_msg->N_bytes = **ie_ptr << 8; - *ie_ptr += 1; - esm_msg->N_bytes |= **ie_ptr; - *ie_ptr += 1; - for(i=0; iN_bytes; i++) + supported_codec_list->N_supported_codecs = ((*ie_ptr)[0]/4); + for(i=0; iN_supported_codecs; i++) { - esm_msg->msg[i] = **ie_ptr; - *ie_ptr += 1; + supported_codec_list->supported_codec[i].sys_id = (*ie_ptr)[1+i*4+0]; + supported_codec_list->supported_codec[i].codec_bitmap = (*ie_ptr)[1+i*4+2] << 8; + supported_codec_list->supported_codec[i].codec_bitmap |= (*ie_ptr)[1+i*4+3]; } + *ie_ptr += (supported_codec_list->N_supported_codecs*4) + 1; err = LIBLTE_SUCCESS; } @@ -855,106 +1458,133 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8 } /********************************************************************* - IE Name: GPRS Timer + IE Name: Additional Update Result - Description: Specifies GPRS specific timer values. + Description: Provides additional information about the result of + a combined attached procedure or a combined tracking + area updating procedure. - Document Reference: 24.301 v10.2.0 Section 9.9.3.16 - 24.008 v10.2.0 Section 10.5.7.3 + Document Reference: 24.301 v10.2.0 Section 9.9.3.0A *********************************************************************/ -// FIXME - -/********************************************************************* - IE Name: GPRS Timer 2 +LIBLTE_ERROR_ENUM liblte_mme_pack_additional_update_result_ie(LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM result, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - Description: Specifies GPRS specific timer values. + if(ie_ptr != NULL) + { + **ie_ptr |= result << bit_offset; - Document Reference: 24.301 v10.2.0 Section 9.9.3.16A - 24.008 v10.2.0 Section 10.5.7.4 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } -/********************************************************************* - IE Name: GPRS Timer 3 + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_result_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM *result) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - Description: Specifies GPRS specific timer values. + if(result != NULL && + ie_ptr != NULL) + { + *result = (LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM)((**ie_ptr >> bit_offset) & 0x03); - Document Reference: 24.301 v10.2.0 Section 9.9.3.16B - 24.008 v10.2.0 Section 10.5.7.4A -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - IE Name: Identity Type 2 + IE Name: Additional Update Type - Description: Specifies which identity is requested. + Description: Provides additional information about the type of + request for a combined attach or a combined tracking + area updating procedure. - Document Reference: 24.301 v10.2.0 Section 9.9.3.17 - 24.008 v10.2.0 Section 10.5.5.9 + Document Reference: 24.301 v10.2.0 Section 9.9.3.0B *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_additional_update_type_ie(LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_ENUM aut, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: IMEISV Request + if(ie_ptr != NULL) + { + **ie_ptr |= aut << bit_offset; - Description: Indicates that the IMEISV shall be included by the - UE in the authentication and ciphering response - message. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.18 - 24.008 v10.2.0 Section 10.5.5.10 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_ENUM *aut) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: KSI And Sequence Number + if(ie_ptr != NULL && + aut != NULL) + { + *aut = (LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_ENUM)((**ie_ptr >> bit_offset) & 0x01); - Description: Provides the network with the key set identifier - (KSI) value of the current EPS security context and - the 5 least significant bits of the NAS COUNT value - applicable for the message including this information - element. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.19 -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - IE Name: MS Network Capability + IE Name: Authentication Failure Parameter - Description: Provides the network with information concerning - aspects of the UE related to GPRS. + Description: Provides the network with the necessary information + to begin a re-authentication procedure in the case + of a 'Synch failure', following a UMTS or EPS + authentication challenge. - Document Reference: 24.301 v10.2.0 Section 9.9.3.20 - 24.008 v10.2.0 Section 10.5.5.12 + Document Reference: 24.301 v10.2.0 Section 9.9.3.1 + 24.008 v10.2.0 Section 10.5.3.2.2 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_ms_network_capability_ie(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT *ms_network_cap, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_failure_parameter_ie(uint8 *auth_fail_param, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; - if(ms_network_cap != NULL && - ie_ptr != NULL) + if(auth_fail_param != NULL && + ie_ptr != NULL) { - // FIXME - **ie_ptr = 0; - *ie_ptr += 1; + (*ie_ptr)[0] = 14; + for(i=0; i<14; i++) + { + (*ie_ptr)[i+1] = auth_fail_param[i]; + } + *ie_ptr += 15; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_ms_network_capability_ie(uint8 **ie_ptr, - LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT *ms_network_cap) +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_failure_parameter_ie(uint8 **ie_ptr, + uint8 *auth_fail_param) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; - if(ie_ptr != NULL && - ms_network_cap != NULL) + if(ie_ptr != NULL && + auth_fail_param != NULL) { - // FIXME - *ie_ptr += **ie_ptr + 1; + for(i=0; i<14; i++) + { + auth_fail_param[i] = (*ie_ptr)[i+1]; + } + *ie_ptr += 15; err = LIBLTE_SUCCESS; } @@ -963,41 +1593,49 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_ms_network_capability_ie(uint8 } /********************************************************************* - IE Name: NAS Key Set Identifier + IE Name: Authentication Parameter AUTN - Description: Provides the NAS key set identifier that is allocated - by the network. + Description: Provides the UE with a means of authenticating the + network. - Document Reference: 24.301 v10.2.0 Section 9.9.3.21 + Document Reference: 24.301 v10.2.0 Section 9.9.3.2 + 24.008 v10.2.0 Section 10.5.3.1.1 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_nas_key_set_id_ie(LIBLTE_MME_NAS_KEY_SET_ID_STRUCT *nas_ksi, - uint8 bit_offset, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_parameter_autn_ie(uint8 *autn, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; - if(nas_ksi != NULL && - ie_ptr != NULL) + if(autn != NULL && + ie_ptr != NULL) { - **ie_ptr |= nas_ksi->tsc_flag << (bit_offset + 3); - **ie_ptr |= nas_ksi->nas_ksi << bit_offset; + (*ie_ptr)[0] = 16; + for(i=0; i<16; i++) + { + (*ie_ptr)[i+1] = autn[i]; + } + *ie_ptr += 17; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_key_set_id_ie(uint8 **ie_ptr, - uint8 bit_offset, - LIBLTE_MME_NAS_KEY_SET_ID_STRUCT *nas_ksi) +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_parameter_autn_ie(uint8 **ie_ptr, + uint8 *autn) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; - if(ie_ptr != NULL && - nas_ksi != NULL) + if(ie_ptr != NULL && + autn != NULL) { - nas_ksi->tsc_flag = (LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM)((**ie_ptr >> (bit_offset + 3)) & 0x01); - nas_ksi->nas_ksi = (**ie_ptr >> bit_offset) & 0x07; + for(i=0; i<16; i++) + { + autn[i] = (*ie_ptr)[i+1]; + } + *ie_ptr += 17; err = LIBLTE_SUCCESS; } @@ -1006,100 +1644,144 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_key_set_id_ie(uint8 } /********************************************************************* - IE Name: NAS Message Container + IE Name: Authentication Parameter RAND - Description: Encapsulates the SMS messages transferred between - the UE and the network. + Description: Provides the UE with a non-predictable number to be + used to calculate the authentication signature SRES + and the ciphering key Kc (for a GSM authentication + challenge), or the response RES and both the + ciphering key CK and the integrity key IK (for a + UMTS authentication challenge). - Document Reference: 24.301 v10.2.0 Section 9.9.3.22 + Document Reference: 24.301 v10.2.0 Section 9.9.3.3 + 24.008 v10.2.0 Section 10.5.3.1 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_parameter_rand_ie(uint8 *rand_val, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; -/********************************************************************* - IE Name: NAS Security Algorithms + if(rand_val != NULL && + ie_ptr != NULL) + { + for(i=0; i<16; i++) + { + (*ie_ptr)[i] = rand_val[i]; + } + *ie_ptr += 16; - Description: Indicates the algorithms to be used for ciphering - and integrity protection. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.23 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_parameter_rand_ie(uint8 **ie_ptr, + uint8 *rand_val) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; -/********************************************************************* - IE Name: Network Name + if(ie_ptr != NULL && + rand_val != NULL) + { + for(i=0; i<16; i++) + { + rand_val[i] = (*ie_ptr)[i]; + } + *ie_ptr += 16; - Description: Passes a text string to the UE. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.24 - 24.008 v10.2.0 Section 10.5.3.5A -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - IE Name: Nonce + IE Name: Authentication Response Parameter - Description: Transfers a 32-bit nonce value to support deriving - a new mapped EPS security context. + Description: Provides the network with the authentication + response calculated in the USIM. - Document Reference: 24.301 v10.2.0 Section 9.9.3.25 + Document Reference: 24.301 v10.2.0 Section 9.9.3.4 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_response_parameter_ie(uint8 *res, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; -/********************************************************************* - IE Name: Paging Identity + if(res != NULL && + ie_ptr != NULL) + { + (*ie_ptr)[0] = 8; + for(i=0; i<8; i++) + { + (*ie_ptr)[i+1] = res[i]; + } + *ie_ptr += 9; - Description: Indicates the identity used for paging for non-EPS - services. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.25A -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_response_parameter_ie(uint8 **ie_ptr, + uint8 *res) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ie_ptr != NULL && + res != NULL) + { + for(i=0; i<(*ie_ptr)[0]; i++) + { + res[i] = (*ie_ptr)[i+1]; + } + *ie_ptr += (*ie_ptr)[0] + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - IE Name: P-TMSI Signature + IE Name: Ciphering Key Sequence Number - Description: Identifies a GMM context of a UE. + Description: Makes it possible for the network to identify the + ciphering key Kc which is stored in the UE without + invoking the authentication procedure. - Document Reference: 24.301 v10.2.0 Section 9.9.3.26 - 24.008 v10.2.0 Section 10.5.5.8 + Document Reference: 24.301 v10.2.0 Section 9.9.3.4A + 24.008 v10.2.0 Section 10.5.1.2 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_p_tmsi_signature_ie(uint32 p_tmsi_signature, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_ciphering_key_sequence_number_ie(uint8 key_seq, + uint8 bit_offset, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; if(ie_ptr != NULL) { - **ie_ptr = (p_tmsi_signature >> 24) & 0xFF; - *ie_ptr += 1; - **ie_ptr = (p_tmsi_signature >> 16) & 0xFF; - *ie_ptr += 1; - **ie_ptr = (p_tmsi_signature >> 8) & 0xFF; - *ie_ptr += 1; - **ie_ptr = p_tmsi_signature & 0xFF; - *ie_ptr += 1; + (*ie_ptr)[0] |= (key_seq & 0x07) << bit_offset; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_p_tmsi_signature_ie(uint8 **ie_ptr, - uint32 *p_tmsi_signature) +LIBLTE_ERROR_ENUM liblte_mme_unpack_ciphering_key_sequence_number_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *key_seq) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL && - p_tmsi_signature != NULL) + if(ie_ptr != NULL && + key_seq != NULL) { - *p_tmsi_signature = (**ie_ptr << 24); - *ie_ptr += 1; - *p_tmsi_signature |= (**ie_ptr << 16); - *ie_ptr += 1; - *p_tmsi_signature |= (**ie_ptr << 8); - *ie_ptr += 1; - *p_tmsi_signature |= **ie_ptr; - *ie_ptr += 1; + *key_seq = ((*ie_ptr)[0] >> bit_offset) & 0x07; err = LIBLTE_SUCCESS; } @@ -1108,82 +1790,79 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_p_tmsi_signature_ie(uint8 **ie_ptr, } /********************************************************************* - IE Name: Service Type + IE Name: CSFB Response - Description: Specifies the purpose of the service request - procedure. + Description: Indicates whether the UE accepts or rejects a paging + for CS fallback. - Document Reference: 24.301 v10.2.0 Section 9.9.3.27 -*********************************************************************/ -// FIXME - -/********************************************************************* - IE Name: Short MAC - - Description: Protects the integrity of a SERVICE REQUEST message. - - Document Reference: 24.301 v10.2.0 Section 9.9.3.28 + Document Reference: 24.301 v10.2.0 Section 9.9.3.5 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_csfb_response_ie(uint8 csfb_resp, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: Time Zone + if(ie_ptr != NULL) + { + (*ie_ptr)[0] |= (csfb_resp & 0x07) << bit_offset; - Description: Encodes the offset between universal time and local - time in steps of 15 minutes. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.29 - 24.008 v10.2.0 Section 10.5.3.8 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_csfb_response_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *csfb_resp) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: Time Zone And Time + if(ie_ptr != NULL && + csfb_resp != NULL) + { + *csfb_resp = ((*ie_ptr)[0] & 0x07) >> bit_offset; - Description: Encodes the offset between universal time and local - time in steps of 15 minutes and encodes the universal - time at which the IE may have been sent by the - network. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.30 - 24.008 v10.2.0 Section 10.5.3.9 -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - IE Name: TMSI Status + IE Name: Daylight Saving Time - Description: Indicates whether a valid TMSI is available in the - UE or not. + Description: Encodes the daylight saving time in steps of 1 hour. - Document Reference: 24.301 v10.2.0 Section 9.9.3.31 - 24.008 v10.2.0 Section 10.5.5.4 + Document Reference: 24.301 v10.2.0 Section 9.9.3.6 + 24.008 v10.2.0 Section 10.5.3.12 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_tmsi_status_ie(LIBLTE_MME_TMSI_STATUS_ENUM tmsi_status, - uint8 bit_offset, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_daylight_saving_time_ie(LIBLTE_MME_DAYLIGHT_SAVING_TIME_ENUM dst, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; if(ie_ptr != NULL) { - **ie_ptr |= tmsi_status << bit_offset; + (*ie_ptr)[0] = 1; + (*ie_ptr)[1] = dst & 0x03; + *ie_ptr += 2; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_tmsi_status_ie(uint8 **ie_ptr, - uint8 bit_offset, - LIBLTE_MME_TMSI_STATUS_ENUM *tmsi_status) +LIBLTE_ERROR_ENUM liblte_mme_unpack_daylight_saving_time_ie(uint8 **ie_ptr, + LIBLTE_MME_DAYLIGHT_SAVING_TIME_ENUM *dst) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL && - tmsi_status != NULL) + if(ie_ptr != NULL && + dst != NULL) { - *tmsi_status = (LIBLTE_MME_TMSI_STATUS_ENUM)((**ie_ptr >> bit_offset) & 0x01); + *dst = (LIBLTE_MME_DAYLIGHT_SAVING_TIME_ENUM)((*ie_ptr)[1] & 0x03); + *ie_ptr += 2; err = LIBLTE_SUCCESS; } @@ -1192,74 +1871,40 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_tmsi_status_ie(uint8 * } /********************************************************************* - IE Name: Tracking Area Identity + IE Name: Detach Type - Description: Provides an unambiguous identification of tracking - areas within the area covered by the 3GPP system. + Description: Indicates the type of detach. - Document Reference: 24.301 v10.2.0 Section 9.9.3.32 + Document Reference: 24.301 v10.2.0 Section 9.9.3.7 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_id_ie(LIBLTE_MME_TRACKING_AREA_ID_STRUCT *tai, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_detach_type_ie(LIBLTE_MME_DETACH_TYPE_STRUCT *detach_type, + uint8 bit_offset, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(tai != NULL && - ie_ptr != NULL) + if(detach_type != NULL && + ie_ptr != NULL) { - **ie_ptr = ((tai->mcc/10) % 10) | ((tai->mcc/100) % 10); - *ie_ptr += 1; - if(tai->mnc > 100) - { - **ie_ptr = 0xF | (tai->mcc % 10); - *ie_ptr += 1; - **ie_ptr = (tai->mnc % 10) | ((tai->mnc/10) % 10); - *ie_ptr += 1; - }else{ - **ie_ptr = (tai->mnc % 10) | (tai->mcc % 10); - *ie_ptr += 1; - **ie_ptr = ((tai->mnc/10) % 10) | ((tai->mnc/100) % 10); - *ie_ptr += 1; - } - **ie_ptr = (tai->tac >> 8) & 0xFF; - *ie_ptr += 1; - **ie_ptr = tai->tac & 0xFF; - *ie_ptr += 1; + (*ie_ptr)[0] |= (detach_type->switch_off & 0x01) << (3 + bit_offset); + (*ie_ptr)[0] |= (detach_type->type_of_detach & 0x07) << bit_offset; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_id_ie(uint8 **ie_ptr, - LIBLTE_MME_TRACKING_AREA_ID_STRUCT *tai) +LIBLTE_ERROR_ENUM liblte_mme_unpack_detach_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_DETACH_TYPE_STRUCT *detach_type) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL && - tai != NULL) + if(ie_ptr != NULL && + detach_type != NULL) { - tai->mcc = (**ie_ptr & 0x0F)*100; - tai->mcc += ((**ie_ptr >> 4) & 0x0F)*10; - *ie_ptr += 1; - tai->mcc += **ie_ptr & 0x0F; - if(((**ie_ptr >> 4) & 0x0F) == 0x0F) - { - *ie_ptr += 1; - tai->mnc = (**ie_ptr & 0x0F)*10; - tai->mnc += (**ie_ptr >> 4) & 0x0F; - *ie_ptr += 1; - }else{ - tai->mnc = (**ie_ptr >> 4) & 0x0F; - *ie_ptr += 1; - tai->mnc += (**ie_ptr & 0x0F)*100; - tai->mnc += ((**ie_ptr >> 4) & 0x0F)*10; - *ie_ptr += 1; - } - tai->tac = **ie_ptr << 8; - *ie_ptr += 1; - tai->tac |= **ie_ptr; - *ie_ptr += 1; + detach_type->switch_off = ((*ie_ptr)[0] >> (3 + bit_offset)) & 0x01; + detach_type->type_of_detach = ((*ie_ptr)[0] >> bit_offset) & 0x07; err = LIBLTE_SUCCESS; } @@ -1268,146 +1913,45 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_id_ie(uint8 } /********************************************************************* - IE Name: Tracking Area Identity List - - Description: Transfers a list of tracking areas from the network - to the UE. - - Document Reference: 24.301 v10.2.0 Section 9.9.3.33 -*********************************************************************/ -// FIXME - -/********************************************************************* - IE Name: UE Network Capability + IE Name: DRX Parameter - Description: Provides the network with information concerning - aspects of the UE related to EPS or interworking with - GPRS. + Description: Indicates whether the UE uses DRX mode or not. - Document Reference: 24.301 v10.2.0 Section 9.9.3.34 + Document Reference: 24.301 v10.2.0 Section 9.9.3.8 + 24.008 v10.2.0 Section 10.5.5.6 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_ue_network_capability_ie(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT *ue_network_cap, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_drx_parameter_ie(LIBLTE_MME_DRX_PARAMETER_STRUCT *drx_param, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ue_network_cap != NULL && - ie_ptr != NULL) + if(drx_param != NULL && + ie_ptr != NULL) { - **ie_ptr = 5; - *ie_ptr += 1; - **ie_ptr = ue_network_cap->eea0 << 7; - **ie_ptr |= ue_network_cap->eea1 << 6; - **ie_ptr |= ue_network_cap->eea2 << 5; - **ie_ptr |= ue_network_cap->eea3 << 4; - **ie_ptr |= ue_network_cap->eea4 << 3; - **ie_ptr |= ue_network_cap->eea5 << 2; - **ie_ptr |= ue_network_cap->eea6 << 1; - **ie_ptr |= ue_network_cap->eea7; - *ie_ptr += 1; - **ie_ptr = ue_network_cap->eia0 << 7; - **ie_ptr |= ue_network_cap->eia1 << 6; - **ie_ptr |= ue_network_cap->eia2 << 5; - **ie_ptr |= ue_network_cap->eia3 << 4; - **ie_ptr |= ue_network_cap->eia4 << 3; - **ie_ptr |= ue_network_cap->eia5 << 2; - **ie_ptr |= ue_network_cap->eia6 << 1; - **ie_ptr |= ue_network_cap->eia7; - *ie_ptr += 1; - **ie_ptr = ue_network_cap->uea0 << 7; - **ie_ptr |= ue_network_cap->uea1 << 6; - **ie_ptr |= ue_network_cap->uea2 << 5; - **ie_ptr |= ue_network_cap->uea3 << 4; - **ie_ptr |= ue_network_cap->uea4 << 3; - **ie_ptr |= ue_network_cap->uea5 << 2; - **ie_ptr |= ue_network_cap->uea6 << 1; - **ie_ptr |= ue_network_cap->uea7; - *ie_ptr += 1; - **ie_ptr = ue_network_cap->ucs2 << 7; - **ie_ptr |= ue_network_cap->uia1 << 6; - **ie_ptr |= ue_network_cap->uia2 << 5; - **ie_ptr |= ue_network_cap->uia3 << 4; - **ie_ptr |= ue_network_cap->uia4 << 3; - **ie_ptr |= ue_network_cap->uia5 << 2; - **ie_ptr |= ue_network_cap->uia6 << 1; - **ie_ptr |= ue_network_cap->uia7; - *ie_ptr += 1; - **ie_ptr = ue_network_cap->lpp << 3; - **ie_ptr |= ue_network_cap->lcs << 2; - **ie_ptr |= ue_network_cap->onexsrvcc << 1; - **ie_ptr |= ue_network_cap->nf; - *ie_ptr += 1; + (*ie_ptr)[0] = drx_param->split_pg_cycle_code; + (*ie_ptr)[1] = (drx_param->drx_cycle_len_coeff_and_value & 0x0F) << 4; + (*ie_ptr)[1] |= (drx_param->split_on_ccch & 0x01) << 3; + (*ie_ptr)[1] |= drx_param->non_drx_timer & 0x07; + *ie_ptr += 2; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_network_capability_ie(uint8 **ie_ptr, - LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT *ue_network_cap) +LIBLTE_ERROR_ENUM liblte_mme_unpack_drx_parameter_ie(uint8 **ie_ptr, + LIBLTE_MME_DRX_PARAMETER_STRUCT *drx_param) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - uint32 length; - if(ie_ptr != NULL && - ue_network_cap != NULL) + if(ie_ptr != NULL && + drx_param != NULL) { - length = **ie_ptr; - *ie_ptr += 1; - ue_network_cap->eea0 = (**ie_ptr >> 7) & 0x01; - ue_network_cap->eea1 = (**ie_ptr >> 6) & 0x01; - ue_network_cap->eea2 = (**ie_ptr >> 5) & 0x01; - ue_network_cap->eea3 = (**ie_ptr >> 4) & 0x01; - ue_network_cap->eea4 = (**ie_ptr >> 3) & 0x01; - ue_network_cap->eea5 = (**ie_ptr >> 2) & 0x01; - ue_network_cap->eea6 = (**ie_ptr >> 1) & 0x01; - ue_network_cap->eea7 = **ie_ptr & 0x01; - *ie_ptr += 1; - ue_network_cap->eia0 = (**ie_ptr >> 7) & 0x01; - ue_network_cap->eia1 = (**ie_ptr >> 6) & 0x01; - ue_network_cap->eia2 = (**ie_ptr >> 5) & 0x01; - ue_network_cap->eia3 = (**ie_ptr >> 4) & 0x01; - ue_network_cap->eia4 = (**ie_ptr >> 3) & 0x01; - ue_network_cap->eia5 = (**ie_ptr >> 2) & 0x01; - ue_network_cap->eia6 = (**ie_ptr >> 1) & 0x01; - ue_network_cap->eia7 = **ie_ptr & 0x01; - *ie_ptr += 1; - if(length > 2) - { - ue_network_cap->uea0 = (**ie_ptr >> 7) & 0x01; - ue_network_cap->uea1 = (**ie_ptr >> 6) & 0x01; - ue_network_cap->uea2 = (**ie_ptr >> 5) & 0x01; - ue_network_cap->uea3 = (**ie_ptr >> 4) & 0x01; - ue_network_cap->uea4 = (**ie_ptr >> 3) & 0x01; - ue_network_cap->uea5 = (**ie_ptr >> 2) & 0x01; - ue_network_cap->uea6 = (**ie_ptr >> 1) & 0x01; - ue_network_cap->uea7 = **ie_ptr & 0x01; - *ie_ptr += 1; - } - if(length > 3) - { - ue_network_cap->ucs2 = (**ie_ptr >> 7) & 0x01; - ue_network_cap->uia1 = (**ie_ptr >> 6) & 0x01; - ue_network_cap->uia2 = (**ie_ptr >> 5) & 0x01; - ue_network_cap->uia3 = (**ie_ptr >> 4) & 0x01; - ue_network_cap->uia4 = (**ie_ptr >> 3) & 0x01; - ue_network_cap->uia5 = (**ie_ptr >> 2) & 0x01; - ue_network_cap->uia6 = (**ie_ptr >> 1) & 0x01; - ue_network_cap->uia7 = **ie_ptr & 0x01; - *ie_ptr += 1; - } - if(length > 4) - { - ue_network_cap->lpp = (**ie_ptr >> 3) & 0x01; - ue_network_cap->lcs = (**ie_ptr >> 2) & 0x01; - ue_network_cap->onexsrvcc = (**ie_ptr >> 1) & 0x01; - ue_network_cap->nf = **ie_ptr >> 1; - *ie_ptr += 1; - } - if(length > 5) - { - *ie_ptr += length-5; - } + drx_param->split_pg_cycle_code = (*ie_ptr)[0]; + drx_param->drx_cycle_len_coeff_and_value = ((*ie_ptr)[1] >> 4) & 0x0F; + drx_param->split_on_ccch = ((*ie_ptr)[1] >> 3) & 0x01; + drx_param->non_drx_timer = (LIBLTE_MME_NON_DRX_TIMER_ENUM)((*ie_ptr)[1] & 0x07); + *ie_ptr += 2; err = LIBLTE_SUCCESS; } @@ -1416,139 +1960,265 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_network_capability_ie(uint8 } /********************************************************************* - IE Name: UE Radio Capability Update Needed + IE Name: EMM Cause - Description: Indicates whether the MME shall delete the stored - UE radio capability information, if any. + Description: Indicates the reason why an EMM request from the UE + is rejected by the network. - Document Reference: 24.301 v10.2.0 Section 9.9.3.35 + Document Reference: 24.301 v10.2.0 Section 9.9.3.9 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_emm_cause_ie(uint8 emm_cause, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: UE Security Capability + if(ie_ptr != NULL) + { + **ie_ptr = emm_cause; + *ie_ptr += 1; - Description: Indicates which security algorithms are supported by - the UE in S1 mode. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.36 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_emm_cause_ie(uint8 **ie_ptr, + uint8 *emm_cause) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: Emergency Number List + if(ie_ptr != NULL && + emm_cause != NULL) + { + *emm_cause = **ie_ptr; + *ie_ptr += 1; - Description: Encodes emergency number(s) for use within the - country (as indicated by MCC) where the IE is - received. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.37 - 24.008 v10.2.0 Section 10.5.3.13 -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - IE Name: CLI + IE Name: EPS Attach Result - Description: Conveys information about the calling line for a - terminated call to a CS fallback capable UE. + Description: Specifies the result of an attach procedure. - Document Reference: 24.301 v10.2.0 Section 9.9.3.38 + Document Reference: 24.301 v10.2.0 Section 9.9.3.10 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_attach_result_ie(uint8 result, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: SS Code + if(ie_ptr != NULL) + { + **ie_ptr |= result << bit_offset; - Description: Conveys information related to a network initiated - supplementary service request to a CS fallback - capable UE. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.39 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_attach_result_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *result) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: LCS Indicator + if(ie_ptr != NULL && + result != NULL) + { + *result = (**ie_ptr >> bit_offset) & 0x07; - Description: Indicates that the origin of the message is due to a - LCS request and the type of this request to a CS - fallback capable UE. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.3.40 -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - IE Name: LCS Client Identity + IE Name: EPS Attach Type - Description: Conveys information related to the client of a LCS - request for a CS fallback capable UE. + Description: Indicates the type of the requested attach. - Document Reference: 24.301 v10.2.0 Section 9.9.3.41 + Document Reference: 24.301 v10.2.0 Section 9.9.3.11 *********************************************************************/ -// FIXME - -/********************************************************************* - IE Name: Generic Message Container Type +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_attach_type_ie(uint8 attach_type, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - Description: Specifies the type of message contained in the - generic message container IE. + if(ie_ptr != NULL) + { + **ie_ptr |= attach_type << bit_offset; - Document Reference: 24.301 v10.2.0 Section 9.9.3.42 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } -/********************************************************************* - IE Name: Generic Message Container + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_attach_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *attach_type) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - Description: Encapsulates the application message transferred - between the UE and the network. + if(ie_ptr != NULL && + attach_type != NULL) + { + *attach_type = (**ie_ptr >> bit_offset) & 0x07; - Document Reference: 24.301 v10.2.0 Section 9.9.3.43 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - IE Name: Voice Domain Preference and UE's Usage Setting + IE Name: EPS Mobile Identity - Description: Provides the network with the UE's usage setting and - the voice domain preference for the E-UTRAN. + Description: Provides either the IMSI, the GUTI, or the IMEI. - Document Reference: 24.301 v10.2.0 Section 9.9.3.44 - 24.008 v10.2.0 Section 10.5.5.28 + Document Reference: 24.301 v10.2.0 Section 9.9.3.12 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_voice_domain_pref_and_ue_usage_setting_ie(LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_STRUCT *voice_domain_pref_and_ue_usage_setting, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_mobile_id_ie(LIBLTE_MME_EPS_MOBILE_ID_STRUCT *eps_mobile_id, + uint8 **ie_ptr) { - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *id; + uint32 i; - if(voice_domain_pref_and_ue_usage_setting != NULL && - ie_ptr != NULL) + if(eps_mobile_id != NULL && + ie_ptr != NULL) { - **ie_ptr = 1; - *ie_ptr += 1; - **ie_ptr = voice_domain_pref_and_ue_usage_setting->ue_usage_setting << 2; - **ie_ptr |= voice_domain_pref_and_ue_usage_setting->voice_domain_pref; - *ie_ptr += 1; + if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI == eps_mobile_id->type_of_id) + { + **ie_ptr = 11; + *ie_ptr += 1; + **ie_ptr = 0xF0 | eps_mobile_id->type_of_id; + *ie_ptr += 1; + **ie_ptr = (((eps_mobile_id->guti.mcc/10) % 10) << 4) | ((eps_mobile_id->guti.mcc/100) % 10); + *ie_ptr += 1; + if(eps_mobile_id->guti.mnc < 100) + { + **ie_ptr = 0xF0 | (eps_mobile_id->guti.mcc % 10); + *ie_ptr += 1; + **ie_ptr = ((eps_mobile_id->guti.mnc % 10) << 4) | ((eps_mobile_id->guti.mnc/10) % 10); + *ie_ptr += 1; + }else{ + **ie_ptr = ((eps_mobile_id->guti.mnc % 10) << 4) | (eps_mobile_id->guti.mcc % 10); + *ie_ptr += 1; + **ie_ptr = (((eps_mobile_id->guti.mnc/10) % 10) << 4) | ((eps_mobile_id->guti.mnc/100) % 10); + *ie_ptr += 1; + } + **ie_ptr = (eps_mobile_id->guti.mme_group_id >> 8) & 0xFF; + *ie_ptr += 1; + **ie_ptr = eps_mobile_id->guti.mme_group_id & 0xFF; + *ie_ptr += 1; + **ie_ptr = eps_mobile_id->guti.mme_code; + *ie_ptr += 1; + **ie_ptr = (eps_mobile_id->guti.m_tmsi >> 24) & 0xFF; + *ie_ptr += 1; + **ie_ptr = (eps_mobile_id->guti.m_tmsi >> 16) & 0xFF; + *ie_ptr += 1; + **ie_ptr = (eps_mobile_id->guti.m_tmsi >> 8) & 0xFF; + *ie_ptr += 1; + **ie_ptr = eps_mobile_id->guti.m_tmsi & 0xFF; + *ie_ptr += 1; + }else{ + if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI == eps_mobile_id->type_of_id) + { + id = eps_mobile_id->imsi; + }else{ + id = eps_mobile_id->imei; + } + + **ie_ptr = 8; + *ie_ptr += 1; + **ie_ptr = (id[0] << 4) | (1 << 3) | eps_mobile_id->type_of_id; + *ie_ptr += 1; + for(i=0; i<7; i++) + { + **ie_ptr = (id[i*2+2] << 4) | id[i*2+1]; + *ie_ptr += 1; + } + } err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_voice_domain_pref_and_ue_usage_setting_ie(uint8 **ie_ptr, - LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_STRUCT *voice_domain_pref_and_ue_usage_setting) +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_mobile_id_ie(uint8 **ie_ptr, + LIBLTE_MME_EPS_MOBILE_ID_STRUCT *eps_mobile_id) { - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *id; + uint32 length; + uint32 i; - if(ie_ptr != NULL && - voice_domain_pref_and_ue_usage_setting != NULL) + if(ie_ptr != NULL && + eps_mobile_id != NULL) { - *ie_ptr += 1; - voice_domain_pref_and_ue_usage_setting->ue_usage_setting = (LIBLTE_MME_UE_USAGE_SETTING_ENUM)((**ie_ptr >> 2) & 0x01); - voice_domain_pref_and_ue_usage_setting->voice_domain_pref = (LIBLTE_MME_VOICE_DOMAIN_PREF_ENUM)(**ie_ptr & 0x03); - *ie_ptr += 1; + length = **ie_ptr; + *ie_ptr += 1; + + eps_mobile_id->type_of_id = **ie_ptr & 0x07; + + if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI == eps_mobile_id->type_of_id) + { + *ie_ptr += 1; + eps_mobile_id->guti.mcc = (**ie_ptr & 0x0F)*100; + eps_mobile_id->guti.mcc += ((**ie_ptr >> 4) & 0x0F)*10; + *ie_ptr += 1; + eps_mobile_id->guti.mcc += **ie_ptr & 0x0F; + if(((**ie_ptr >> 4) & 0x0F) == 0x0F) + { + *ie_ptr += 1; + eps_mobile_id->guti.mnc = (**ie_ptr & 0x0F)*10; + eps_mobile_id->guti.mnc += (**ie_ptr >> 4) & 0x0F; + *ie_ptr += 1; + }else{ + eps_mobile_id->guti.mnc = (**ie_ptr >> 4) & 0x0F; + *ie_ptr += 1; + eps_mobile_id->guti.mnc += (**ie_ptr & 0x0F)*100; + eps_mobile_id->guti.mnc += ((**ie_ptr >> 4) & 0x0F)*10; + *ie_ptr += 1; + } + eps_mobile_id->guti.mme_group_id = **ie_ptr << 8; + *ie_ptr += 1; + eps_mobile_id->guti.mme_group_id |= **ie_ptr; + *ie_ptr += 1; + eps_mobile_id->guti.mme_code = **ie_ptr; + *ie_ptr += 1; + eps_mobile_id->guti.m_tmsi = **ie_ptr << 24; + *ie_ptr += 1; + eps_mobile_id->guti.m_tmsi |= **ie_ptr << 16; + *ie_ptr += 1; + eps_mobile_id->guti.m_tmsi |= **ie_ptr << 8; + *ie_ptr += 1; + eps_mobile_id->guti.m_tmsi |= **ie_ptr; + *ie_ptr += 1; + }else{ + if(LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI == eps_mobile_id->type_of_id) + { + id = eps_mobile_id->imsi; + }else{ + id = eps_mobile_id->imei; + } + + id[0] = **ie_ptr >> 4; + *ie_ptr += 1; + for(i=0; i<7; i++) + { + id[i*2+1] = **ie_ptr & 0x0F; + id[i*2+2] = **ie_ptr >> 4; + *ie_ptr += 1; + } + } err = LIBLTE_SUCCESS; } @@ -1557,40 +2227,48 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_voice_domain_pref_and_ue_usage_setting_ie(ui } /********************************************************************* - IE Name: GUTI Type + IE Name: EPS Network Feature Support - Description: Indicates whether the GUTI included in the same - message in an information element of type EPS - mobility identity represents a native GUTI or a - mapped GUTI. + Description: Indicates whether certain features are supported by + the network. - Document Reference: 24.301 v10.2.0 Section 9.9.3.45 + Document Reference: 24.301 v10.2.0 Section 9.9.3.12A *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_guti_type_ie(LIBLTE_MME_GUTI_TYPE_ENUM guti_type, - uint8 bit_offset, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_network_feature_support_ie(LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_STRUCT *eps_nfs, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL) + if(eps_nfs != NULL && + ie_ptr != NULL) { - **ie_ptr |= guti_type << bit_offset; + (*ie_ptr)[0] = 1; + (*ie_ptr)[1] = eps_nfs->esrps << 5; + (*ie_ptr)[1] |= (eps_nfs->cs_lcs & 0x03) << 3; + (*ie_ptr)[1] |= eps_nfs->epc_lcs << 2; + (*ie_ptr)[1] |= eps_nfs->emc_bs << 1; + (*ie_ptr)[1] |= eps_nfs->ims_vops; + *ie_ptr += 2; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_type_ie(uint8 **ie_ptr, - uint8 bit_offset, - LIBLTE_MME_GUTI_TYPE_ENUM *guti_type) +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_network_feature_support_ie(uint8 **ie_ptr, + LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_STRUCT *eps_nfs) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL && - guti_type != NULL) + if(ie_ptr != NULL && + eps_nfs != NULL) { - *guti_type = (LIBLTE_MME_GUTI_TYPE_ENUM)((**ie_ptr >> bit_offset) & 0x01); + eps_nfs->esrps = ((*ie_ptr)[1] >> 5) & 0x01; + eps_nfs->cs_lcs = (LIBLTE_MME_CS_LCS_ENUM)(((*ie_ptr)[1] >> 3) & 0x03); + eps_nfs->epc_lcs = ((*ie_ptr)[1] >> 2) & 0x01; + eps_nfs->emc_bs = ((*ie_ptr)[1] >> 1) & 0x01; + eps_nfs->ims_vops = (*ie_ptr)[1] & 0x01; + *ie_ptr += 2; err = LIBLTE_SUCCESS; } @@ -1599,43 +2277,38 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_type_ie(uint8 **ie_ } /********************************************************************* - IE Name: Access Point Name + IE Name: EPS Update Result - Description: Identifies the packet data network to which the GPRS - user wishes to connect and notifies the access point - of the packet data network that wishes to connect to - the UE. + Description: Specifies the result of the associated updating + procedure. - Document Reference: 24.301 v10.2.0 Section 9.9.4.1 - 24.008 v10.2.0 Section 10.5.6.1 + Document Reference: 24.301 v10.2.0 Section 9.9.3.13 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_access_point_name_ie(LIBLTE_MME_ACCESS_POINT_NAME_STRUCT *apn, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_update_result_ie(uint8 eps_update_res, + uint8 bit_offset, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(apn != NULL && - ie_ptr != NULL) + if(ie_ptr != NULL) { - // FIXME - **ie_ptr = 0; - *ie_ptr += 1; + (*ie_ptr)[0] |= (eps_update_res & 0x07) << bit_offset; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_access_point_name_ie(uint8 **ie_ptr, - LIBLTE_MME_ACCESS_POINT_NAME_STRUCT *apn) +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_update_result_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *eps_update_res) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL && - apn != NULL) + if(ie_ptr != NULL && + eps_update_res != NULL) { - // FIXME - *ie_ptr += **ie_ptr + 1; + *eps_update_res = ((*ie_ptr)[0] >> bit_offset) & 0x07; err = LIBLTE_SUCCESS; } @@ -1644,81 +2317,94 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_access_point_name_ie(uint8 } /********************************************************************* - IE Name: APN Aggregate Maximum Bit Rate + IE Name: EPS Update Type - Description: Indicates the initial subscribed APN-AMBR when the - UE establishes a PDN connection or indicates the new - APN-AMBR if it is changed by the network. + Description: Specifies the area the updating procedure is + associated with. - Document Reference: 24.301 v10.2.0 Section 9.9.4.2 + Document Reference: 24.301 v10.2.0 Section 9.9.3.14 *********************************************************************/ -// FIXME - -/********************************************************************* - IE Name: Connectivity Type +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_update_type_ie(LIBLTE_MME_EPS_UPDATE_TYPE_STRUCT *eps_update_type, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - Description: Specifies the type of connectivity selected by the - network for the PDN connection. + if(eps_update_type != NULL && + ie_ptr != NULL) + { + (*ie_ptr)[0] |= (eps_update_type->active_flag & 0x01) << (bit_offset + 3); + (*ie_ptr)[0] |= (eps_update_type->type & 0x07) << bit_offset; - Document Reference: 24.301 v10.2.0 Section 9.9.4.2A - 24.008 v10.2.0 Section 10.5.6.19 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } -/********************************************************************* - IE Name: EPS Quality Of Service + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_update_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_EPS_UPDATE_TYPE_STRUCT *eps_update_type) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - Description: Specifies the QoS parameters for an EPS bearer - context. + if(ie_ptr != NULL && + eps_update_type != NULL) + { + eps_update_type->active_flag = ((*ie_ptr)[0] >> (bit_offset + 3)) & 0x01; + eps_update_type->type = (LIBLTE_MME_EPS_UPDATE_TYPE_ENUM)(((*ie_ptr)[0] >> bit_offset) & 0x07); - Document Reference: 24.301 v10.2.0 Section 9.9.4.3 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } -/********************************************************************* - IE Name: ESM Cause - - Description: Indicates the reason why a session management request - is rejected. - - Document Reference: 24.301 v10.2.0 Section 9.9.4.4 -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - IE Name: ESM Information Transfer Flag + IE Name: ESM Message Container - Description: Indicates whether ESM information, i.e. protocol - configuration options or APN or both, is to be - transferred security protected. + Description: Enables piggybacked transfer of a single ESM message + within an EMM message. - Document Reference: 24.301 v10.2.0 Section 9.9.4.5 + Document Reference: 24.301 v10.2.0 Section 9.9.3.15 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_esm_info_transfer_flag_ie(LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_ENUM esm_info_transfer_flag, - uint8 bit_offset, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_esm_message_container_ie(LIBLTE_BYTE_MSG_STRUCT *esm_msg, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; - if(ie_ptr != NULL) + if(esm_msg != NULL && + ie_ptr != NULL) { - **ie_ptr |= esm_info_transfer_flag << bit_offset; + (*ie_ptr)[0] = esm_msg->N_bytes >> 8; + (*ie_ptr)[1] = esm_msg->N_bytes & 0xFF; + for(i=0; iN_bytes; i++) + { + (*ie_ptr)[2+i] = esm_msg->msg[i]; + } + *ie_ptr += esm_msg->N_bytes + 2; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_info_transfer_flag_ie(uint8 **ie_ptr, - uint8 bit_offset, - LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_ENUM *esm_info_transfer_flag) +LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8 **ie_ptr, + LIBLTE_BYTE_MSG_STRUCT *esm_msg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; - if(ie_ptr != NULL && - esm_info_transfer_flag != NULL) + if(ie_ptr != NULL && + esm_msg != NULL) { - *esm_info_transfer_flag = (LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_ENUM)((**ie_ptr >> bit_offset) & 0x01); + esm_msg->N_bytes = (*ie_ptr)[0] << 8; + esm_msg->N_bytes |= (*ie_ptr)[1]; + for(i=0; iN_bytes; i++) + { + esm_msg->msg[i] = (*ie_ptr)[2+i]; + } + *ie_ptr += esm_msg->N_bytes + 2; err = LIBLTE_SUCCESS; } @@ -1727,96 +2413,126 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_info_transfer_flag_ie(uint8 } /********************************************************************* - IE Name: Linked EPS Bearer Identity + IE Name: GPRS Timer - Description: Identifies the default bearer that is associated - with a dedicated EPS bearer or identifies the EPS - bearer (default or dedicated) with which one or more - packet filters specified in a traffic flow aggregate - are associated. + Description: Specifies GPRS specific timer values. - Document Reference: 24.301 v10.2.0 Section 9.9.4.6 + Document Reference: 24.301 v10.2.0 Section 9.9.3.16 + 24.008 v10.2.0 Section 10.5.7.3 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_gprs_timer_ie(LIBLTE_MME_GPRS_TIMER_STRUCT *timer, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: LLC Service Access Point Identifier + if(timer != NULL && + ie_ptr != NULL) + { + **ie_ptr = ((timer->unit & 0x07) << 5) | (timer->value & 0x1F); + *ie_ptr += 1; - Description: Identifies the service access point that is used for - the GPRS data transfer at LLC layer. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.4.7 - 24.008 v10.2.0 Section 10.5.6.9 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_gprs_timer_ie(uint8 **ie_ptr, + LIBLTE_MME_GPRS_TIMER_STRUCT *timer) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: Notification Indicator + if(ie_ptr != NULL && + timer != NULL) + { + timer->unit = **ie_ptr >> 5; + timer->value = **ie_ptr & 0x1F; + *ie_ptr += 1; - Description: Informs the UE about an event which is relevant for - the upper layer using an EPS bearer context or - having requested a procedure transaction. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.4.7A -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - IE Name: Packet Flow Identifier + IE Name: GPRS Timer 2 - Description: Indicates the packet flow identifier for a packet - flow context. + Description: Specifies GPRS specific timer values. - Document Reference: 24.301 v10.2.0 Section 9.9.4.8 - 24.008 v10.2.0 Section 10.5.6.11 + Document Reference: 24.301 v10.2.0 Section 9.9.3.16A + 24.008 v10.2.0 Section 10.5.7.4 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_gprs_timer_2_ie(uint8 value, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: PDN Address + if(ie_ptr != NULL) + { + **ie_ptr = 1; + *ie_ptr += 1; + **ie_ptr = value; + *ie_ptr += 1; - Description: Assigns an IPv4 address to the UE associated with a - packet data network and provides the UE with an - interface identifier to be used to build the IPv6 - link local address. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.4.9 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_gprs_timer_2_ie(uint8 **ie_ptr, + uint8 *value) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + value != NULL) + { + *ie_ptr += 1; + *value = **ie_ptr; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - IE Name: PDN Type + IE Name: GPRS Timer 3 - Description: Indicates the IP version capability of the IP stack - associated with the UE. + Description: Specifies GPRS specific timer values. - Document Reference: 24.301 v10.2.0 Section 9.9.4.10 + Document Reference: 24.301 v10.2.0 Section 9.9.3.16B + 24.008 v10.2.0 Section 10.5.7.4A *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_type_ie(uint8 pdn_type, - uint8 bit_offset, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_gprs_timer_3_ie(LIBLTE_MME_GPRS_TIMER_3_STRUCT *timer, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL) + if(timer != NULL && + ie_ptr != NULL) { - **ie_ptr |= pdn_type << bit_offset; + (*ie_ptr)[0] = 1; + (*ie_ptr)[1] = ((timer->unit & 0x07) << 5) | (timer->value & 0x1F); + *ie_ptr += 2; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_type_ie(uint8 **ie_ptr, - uint8 bit_offset, - uint8 *pdn_type) +LIBLTE_ERROR_ENUM liblte_mme_unpack_gprs_timer_3_ie(uint8 **ie_ptr, + LIBLTE_MME_GPRS_TIMER_3_STRUCT *timer) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL && - pdn_type != NULL) + if(ie_ptr != NULL && + timer != NULL) { - *pdn_type = (**ie_ptr >> bit_offset) & 0x07; + timer->unit = (*ie_ptr)[1] >> 5; + timer->value = (*ie_ptr)[1] & 0x1F; + *ie_ptr += 2; err = LIBLTE_SUCCESS; } @@ -1825,45 +2541,38 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_type_ie(uint8 **ie_ptr, } /********************************************************************* - IE Name: Protocol Configuration Options + IE Name: Identity Type 2 - Description: Transfers external network protocol options - associated with a PDP context activation and - transfers additional (protocol) data (e.g. - configuration parameters, error codes or messages/ - events) associated with an external protocol or an - application. + Description: Specifies which identity is requested. - Document Reference: 24.301 v10.2.0 Section 9.9.4.11 - 24.008 v10.2.0 Section 10.5.6.3 + Document Reference: 24.301 v10.2.0 Section 9.9.3.17 + 24.008 v10.2.0 Section 10.5.5.9 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_protocol_config_options_ie(LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT *protocol_cnfg_opts, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_identity_type_2_ie(uint8 id_type, + uint8 bit_offset, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(protocol_cnfg_opts != NULL && - ie_ptr != NULL) + if(ie_ptr != NULL) { - // FIXME - **ie_ptr = 0; - *ie_ptr += 1; + **ie_ptr |= id_type << bit_offset; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_protocol_config_options_ie(uint8 **ie_ptr, - LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT *protocol_cnfg_opts) +LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_type_2_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *id_type) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL && - protocol_cnfg_opts != NULL) + if(ie_ptr != NULL && + id_type != NULL) { - // FIXME - *ie_ptr += **ie_ptr + 1; + *id_type = (**ie_ptr >> bit_offset) & 0x07; err = LIBLTE_SUCCESS; } @@ -1872,63 +2581,86 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_protocol_config_options_ie(uint8 } /********************************************************************* - IE Name: Quality Of Service + IE Name: IMEISV Request - Description: Specifies the QoS parameters for a PDP context. + Description: Indicates that the IMEISV shall be included by the + UE in the authentication and ciphering response + message. - Document Reference: 24.301 v10.2.0 Section 9.9.4.12 - 24.008 v10.2.0 Section 10.5.6.5 + Document Reference: 24.301 v10.2.0 Section 9.9.3.18 + 24.008 v10.2.0 Section 10.5.5.10 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_imeisv_request_ie(LIBLTE_MME_IMEISV_REQUEST_ENUM imeisv_req, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: Radio Priority + if(ie_ptr != NULL) + { + **ie_ptr |= imeisv_req << bit_offset; - Description: Specifies the priority level the UE shall use at the - lower layers for transmission of data related to a - PDP context or for mobile originated SMS - transmission. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 9.9.4.13 - 24.008 v10.2.0 Section 10.5.7.2 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_imeisv_request_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_IMEISV_REQUEST_ENUM *imeisv_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + imeisv_req != NULL) + { + *imeisv_req = (LIBLTE_MME_IMEISV_REQUEST_ENUM)((**ie_ptr >> bit_offset) & 0x07); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - IE Name: Request Type + IE Name: KSI And Sequence Number - Description: Indicates whether the UE requests to establish a new - connectivity to a PDN or keep the connection(s) to - which it has connected via non-3GPP access. + Description: Provides the network with the key set identifier + (KSI) value of the current EPS security context and + the 5 least significant bits of the NAS COUNT value + applicable for the message including this information + element. - Document Reference: 24.301 v10.2.0 Section 9.9.4.14 - 24.008 v10.2.0 Section 10.5.6.17 + Document Reference: 24.301 v10.2.0 Section 9.9.3.19 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_request_type_ie(uint8 req_type, - uint8 bit_offset, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_mme_pack_ksi_and_sequence_number_ie(LIBLTE_MME_KSI_AND_SEQUENCE_NUMBER_STRUCT *ksi_and_seq_num, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL) + if(ksi_and_seq_num != NULL && + ie_ptr != NULL) { - **ie_ptr |= req_type << bit_offset; + (*ie_ptr)[0] = (ksi_and_seq_num->ksi & 0x07) << 5; + (*ie_ptr)[0] |= ksi_and_seq_num->seq_num & 0x1F; + *ie_ptr += 1; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_request_type_ie(uint8 **ie_ptr, - uint8 bit_offset, - uint8 *req_type) +LIBLTE_ERROR_ENUM liblte_mme_unpack_ksi_and_sequence_number_ie(uint8 **ie_ptr, + LIBLTE_MME_KSI_AND_SEQUENCE_NUMBER_STRUCT *ksi_and_seq_num) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL && - req_type != NULL) + if(ie_ptr != NULL && + ksi_and_seq_num != NULL) { - *req_type = (**ie_ptr >> bit_offset) & 0x07; + ksi_and_seq_num->ksi = ((*ie_ptr)[0] >> 5) & 0x07; + ksi_and_seq_num->seq_num = (*ie_ptr)[0] & 0x1F; + *ie_ptr += 1; err = LIBLTE_SUCCESS; } @@ -1937,70 +2669,126 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_request_type_ie(uint8 **ie_ptr, } /********************************************************************* - IE Name: Traffic Flow Aggregate Description + IE Name: MS Network Capability - Description: Specifies the aggregate of one or more packet filters - and their related parameters and operations. + Description: Provides the network with information concerning + aspects of the UE related to GPRS. - Document Reference: 24.301 v10.2.0 Section 9.9.4.15 -*********************************************************************/ -// FIXME - -/********************************************************************* - IE Name: Traffic Flow Template + Document Reference: 24.301 v10.2.0 Section 9.9.3.20 + 24.008 v10.2.0 Section 10.5.5.12 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_ms_network_capability_ie(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT *ms_network_cap, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - Description: Specifies the TFT parameters and operations for a - PDP context. + if(ms_network_cap != NULL && + ie_ptr != NULL) + { + (*ie_ptr)[0] = 3; + (*ie_ptr)[1] = ms_network_cap->gea[1] << 7; + (*ie_ptr)[1] |= ms_network_cap->sm_cap_ded << 6; + (*ie_ptr)[1] |= ms_network_cap->sm_cap_gprs << 5; + (*ie_ptr)[1] |= ms_network_cap->ucs2 << 4; + (*ie_ptr)[1] |= (ms_network_cap->ss_screening & 0x03) << 2; + (*ie_ptr)[1] |= ms_network_cap->solsa << 1; + (*ie_ptr)[1] |= ms_network_cap->revision; + (*ie_ptr)[2] = ms_network_cap->pfc << 7; + (*ie_ptr)[2] |= ms_network_cap->gea[2] << 6; + (*ie_ptr)[2] |= ms_network_cap->gea[3] << 5; + (*ie_ptr)[2] |= ms_network_cap->gea[4] << 4; + (*ie_ptr)[2] |= ms_network_cap->gea[5] << 3; + (*ie_ptr)[2] |= ms_network_cap->gea[6] << 2; + (*ie_ptr)[2] |= ms_network_cap->gea[7] << 1; + (*ie_ptr)[2] |= ms_network_cap->lcsva; + (*ie_ptr)[3] = ms_network_cap->ho_g2u_via_iu << 7; + (*ie_ptr)[3] |= ms_network_cap->ho_g2e_via_s1 << 6; + (*ie_ptr)[3] |= ms_network_cap->emm_comb << 5; + (*ie_ptr)[3] |= ms_network_cap->isr << 4; + (*ie_ptr)[3] |= ms_network_cap->srvcc << 3; + (*ie_ptr)[3] |= ms_network_cap->epc << 2; + (*ie_ptr)[3] |= ms_network_cap->nf << 1; + *ie_ptr += 4; - Document Reference: 24.301 v10.2.0 Section 9.9.4.16 - 24.008 v10.2.0 Section 10.5.6.12 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } -/********************************************************************* - IE Name: Transaction Identifier + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_ms_network_capability_ie(uint8 **ie_ptr, + LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT *ms_network_cap) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - Description: Represents the corresponding PDP context in A/Gb - mode or Iu mode which is mapped from the EPS bearer - context. + if(ie_ptr != NULL && + ms_network_cap != NULL) + { + ms_network_cap->gea[1] = ((*ie_ptr)[1] >> 7) & 0x01; + ms_network_cap->sm_cap_ded = ((*ie_ptr)[1] >> 6) & 0x01; + ms_network_cap->sm_cap_gprs = ((*ie_ptr)[1] >> 5) & 0x01; + ms_network_cap->ucs2 = ((*ie_ptr)[1] >> 4) & 0x01; + ms_network_cap->ss_screening = (LIBLTE_MME_SS_SCREENING_INDICATOR_ENUM)(((*ie_ptr)[1] >> 2) & 0x03); + ms_network_cap->solsa = ((*ie_ptr)[1] >> 1) & 0x01; + ms_network_cap->revision = (*ie_ptr)[1] & 0x01; + ms_network_cap->pfc = ((*ie_ptr)[2] >> 7) & 0x01; + ms_network_cap->gea[2] = ((*ie_ptr)[2] >> 6) & 0x01; + ms_network_cap->gea[3] = ((*ie_ptr)[2] >> 5) & 0x01; + ms_network_cap->gea[4] = ((*ie_ptr)[2] >> 4) & 0x01; + ms_network_cap->gea[5] = ((*ie_ptr)[2] >> 3) & 0x01; + ms_network_cap->gea[6] = ((*ie_ptr)[2] >> 2) & 0x01; + ms_network_cap->gea[7] = ((*ie_ptr)[2] >> 1) & 0x01; + ms_network_cap->lcsva = (*ie_ptr)[2] & 0x01; + ms_network_cap->ho_g2u_via_iu = ((*ie_ptr)[3] >> 7) & 0x01; + ms_network_cap->ho_g2e_via_s1 = ((*ie_ptr)[3] >> 6) & 0x01; + ms_network_cap->emm_comb = ((*ie_ptr)[3] >> 5) & 0x01; + ms_network_cap->isr = ((*ie_ptr)[3] >> 4) & 0x01; + ms_network_cap->srvcc = ((*ie_ptr)[3] >> 3) & 0x01; + ms_network_cap->epc = ((*ie_ptr)[3] >> 2) & 0x01; + ms_network_cap->nf = ((*ie_ptr)[3] >> 1) & 0x01; + *ie_ptr += (*ie_ptr)[0] + 1; - Document Reference: 24.301 v10.2.0 Section 9.9.4.17 - 24.008 v10.2.0 Section 10.5.6.7 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } -/******************************************************************************* - MESSAGE FUNCTIONS -*******************************************************************************/ + return(err); +} /********************************************************************* - Message Name: Message Header (Plain NAS Message) + IE Name: NAS Key Set Identifier - Description: Message header for plain NAS messages. + Description: Provides the NAS key set identifier that is allocated + by the network. - Document Reference: 24.301 v10.2.0 Section 9.1 + Document Reference: 24.301 v10.2.0 Section 9.9.3.21 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_parse_msg_header(LIBLTE_BYTE_MSG_STRUCT *msg, - uint8 *pd, - uint8 *msg_type) +LIBLTE_ERROR_ENUM liblte_mme_pack_nas_key_set_id_ie(LIBLTE_MME_NAS_KEY_SET_ID_STRUCT *nas_ksi, + uint8 bit_offset, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(msg != NULL && - pd != NULL && - msg_type != NULL) + if(nas_ksi != NULL && + ie_ptr != NULL) { - // Protocol Discriminator - *pd = msg->msg[0] & 0x0F; + **ie_ptr |= nas_ksi->tsc_flag << (bit_offset + 3); + **ie_ptr |= nas_ksi->nas_ksi << bit_offset; - if(LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT == *pd) - { - // Message Type - *msg_type = msg->msg[2]; - }else{ - // Message Type - *msg_type = msg->msg[1]; - } + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_key_set_id_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_NAS_KEY_SET_ID_STRUCT *nas_ksi) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + nas_ksi != NULL) + { + nas_ksi->tsc_flag = (LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM)((**ie_ptr >> (bit_offset + 3)) & 0x01); + nas_ksi->nas_ksi = (**ie_ptr >> bit_offset) & 0x07; err = LIBLTE_SUCCESS; } @@ -2009,185 +2797,7966 @@ LIBLTE_ERROR_ENUM liblte_mme_parse_msg_header(LIBLTE_BYTE_MSG_STRUCT *msg, } /********************************************************************* - Message Name: Attach Accept + IE Name: NAS Message Container - Description: Sent by the network to the UE to indicate that the - corresponding attach request has been accepted. + Description: Encapsulates the SMS messages transferred between + the UE and the network. - Document Reference: 24.301 v10.2.0 Section 8.2.1 + Document Reference: 24.301 v10.2.0 Section 9.9.3.22 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_nas_message_container_ie(LIBLTE_BYTE_MSG_STRUCT *nas_msg, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; -/********************************************************************* - Message Name: Attach Complete + if(nas_msg != NULL && + ie_ptr != NULL) + { + (*ie_ptr)[0] = nas_msg->N_bytes & 0xFF; + for(i=0; iN_bytes; i++) + { + (*ie_ptr)[1+i] = nas_msg->msg[i]; + } + *ie_ptr += nas_msg->N_bytes + 1; - Description: Sent by the UE to the network in response to an - ATTACH ACCEPT message. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 8.2.2 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_message_container_ie(uint8 **ie_ptr, + LIBLTE_BYTE_MSG_STRUCT *nas_msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; -/********************************************************************* - Message Name: Attach Reject + if(ie_ptr != NULL && + nas_msg != NULL) + { + nas_msg->N_bytes = (*ie_ptr)[0]; + for(i=0; iN_bytes; i++) + { + nas_msg->msg[i] = (*ie_ptr)[1+i]; + } + *ie_ptr += nas_msg->N_bytes + 1; - Description: Sent by the network to the UE to indicate that the - corresponding attach request has been rejected. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 8.2.3 -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - Message Name: Attach Request + IE Name: NAS Security Algorithms - Description: Sent by the UE to the network to perform an attach - procedure. + Description: Indicates the algorithms to be used for ciphering + and integrity protection. - Document Reference: 24.301 v10.2.0 Section 8.2.4 + Document Reference: 24.301 v10.2.0 Section 9.9.3.23 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, - LIBLTE_BYTE_MSG_STRUCT *msg) +LIBLTE_ERROR_ENUM liblte_mme_pack_nas_security_algorithms_ie(LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT *nas_sec_algs, + uint8 **ie_ptr) { - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - uint8 *msg_ptr = msg->msg; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(attach_req != NULL && - msg != NULL) + if(nas_sec_algs != NULL && + ie_ptr != NULL) { - // Protocol Discriminator and Security Header Type - *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); - msg_ptr++; + **ie_ptr = (nas_sec_algs->type_of_eea << 4) | (nas_sec_algs->type_of_eia); + *ie_ptr += 1; - // Message Type - *msg_ptr = LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST; - msg_ptr++; + err = LIBLTE_SUCCESS; + } - // EPS Attach Type & NAS Key Set Identifier - *msg_ptr = 0; - liblte_mme_pack_eps_attach_type_ie(attach_req->eps_type_result, 0, &msg_ptr); - liblte_mme_pack_nas_key_set_id_ie(&attach_req->nas_ksi, 4, &msg_ptr); - msg_ptr++; + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_security_algorithms_ie(uint8 **ie_ptr, + LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT *nas_sec_algs) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - // EPS Mobile ID - liblte_mme_pack_eps_mobile_id_ie(&attach_req->eps_mobile_id, &msg_ptr); + if(ie_ptr != NULL && + nas_sec_algs != NULL) + { + nas_sec_algs->type_of_eea = (LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM)((**ie_ptr >> 4) & 0x07); + nas_sec_algs->type_of_eia = (LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM)(**ie_ptr & 0x07); + *ie_ptr += 1; - // UE Network Capability - liblte_mme_pack_ue_network_capability_ie(&attach_req->ue_network_cap, &msg_ptr); + err = LIBLTE_SUCCESS; + } - // ESM Message Container - liblte_mme_pack_esm_message_container_ie(&attach_req->esm_msg, &msg_ptr); + return(err); +} - // Old P-TMSI Signature - if(attach_req->old_p_tmsi_signature_present) - { - *msg_ptr = LIBLTE_MME_P_TMSI_SIGNATURE_IEI; - msg_ptr++; - liblte_mme_pack_p_tmsi_signature_ie(attach_req->old_p_tmsi_signature, &msg_ptr); - } +/********************************************************************* + IE Name: Network Name - // Additional GUTI - if(attach_req->additional_guti_present) - { - *msg_ptr = LIBLTE_MME_ADDITIONAL_GUTI_IEI; - msg_ptr++; - liblte_mme_pack_eps_mobile_id_ie(&attach_req->additional_guti, &msg_ptr); - } + Description: Passes a text string to the UE. - // Last Visited Registered TAI - if(attach_req->last_visited_registered_tai_present) - { - *msg_ptr = LIBLTE_MME_LAST_VISITED_REGISTERED_TAI_IEI; - msg_ptr++; - liblte_mme_pack_tracking_area_id_ie(&attach_req->last_visited_registered_tai, &msg_ptr); - } + Document Reference: 24.301 v10.2.0 Section 9.9.3.24 + 24.008 v10.2.0 Section 10.5.3.5A +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_network_name_ie(LIBLTE_MME_NETWORK_NAME_STRUCT *net_name, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + uint32 bit_offset; + uint32 byte_offset; + const char *char_str = net_name->name.c_str(); - // DRX Parameter - if(attach_req->drx_param_present) + if(net_name != NULL && + ie_ptr != NULL) + { + bit_offset = 0; + byte_offset = 2; + for(i=0; iname.size(); i++) { - *msg_ptr = LIBLTE_MME_DRX_PARAMETER_IEI; - msg_ptr++; - liblte_mme_pack_drx_parameter_ie(&attach_req->drx_param, &msg_ptr); + if(char_str[i] == 0x0A || + char_str[i] == 0x0D || + (char_str[i] >= 0x20 && + char_str[i] <= 0x3F) || + (char_str[i] >= 0x41 && + char_str[i] <= 0x5A) || + (char_str[i] >= 0x61 && + char_str[i] <= 0x7A)) + { + switch(bit_offset) + { + case 0: + (*ie_ptr)[byte_offset] = char_str[i]; + bit_offset = 7; + break; + case 1: + (*ie_ptr)[byte_offset] |= (char_str[i] << 1); + bit_offset = 0; + byte_offset++; + break; + case 2: + (*ie_ptr)[byte_offset] |= ((char_str[i] << 2) & 0xFC); + byte_offset++; + (*ie_ptr)[byte_offset] = ((char_str[i] >> 6) & 0x01); + bit_offset = 1; + break; + case 3: + (*ie_ptr)[byte_offset] |= ((char_str[i] << 3) & 0xF8); + byte_offset++; + (*ie_ptr)[byte_offset] = ((char_str[i] >> 5) & 0x03); + bit_offset = 2; + break; + case 4: + (*ie_ptr)[byte_offset] |= ((char_str[i] << 4) & 0xF0); + byte_offset++; + (*ie_ptr)[byte_offset] = ((char_str[i] >> 4) & 0x07); + bit_offset = 3; + break; + case 5: + (*ie_ptr)[byte_offset] |= ((char_str[i] << 5) & 0xE0); + byte_offset++; + (*ie_ptr)[byte_offset] = ((char_str[i] >> 3) & 0x0F); + bit_offset = 4; + break; + case 6: + (*ie_ptr)[byte_offset] |= ((char_str[i] << 6) & 0xC0); + byte_offset++; + (*ie_ptr)[byte_offset] = ((char_str[i] >> 2) & 0x1F); + bit_offset = 5; + break; + case 7: + (*ie_ptr)[byte_offset] |= ((char_str[i] << 7) & 0x80); + byte_offset++; + (*ie_ptr)[byte_offset] = ((char_str[i] >> 1) & 0x3F); + bit_offset = 6; + break; + } + } } - - // MS Network Capability - if(attach_req->ms_network_cap_present) + if(0 == bit_offset) { - *msg_ptr = LIBLTE_MME_MS_NETWORK_CAPABILITY_IEI; - msg_ptr++; - liblte_mme_pack_ms_network_capability_ie(&attach_req->ms_network_cap, &msg_ptr); + (*ie_ptr)[0] = byte_offset - 1; + (*ie_ptr)[1] = 0x80 | ((net_name->add_ci & 0x01) << 3); + *ie_ptr += byte_offset; + }else{ + (*ie_ptr)[0] = byte_offset; + (*ie_ptr)[1] = 0x80 | ((net_name->add_ci & 0x01) << 3) | ((8 - bit_offset) & 0x07); + *ie_ptr += byte_offset + 1; } - // Old Location Area ID - if(attach_req->old_lai_present) + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_network_name_ie(uint8 **ie_ptr, + LIBLTE_MME_NETWORK_NAME_STRUCT *net_name) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + uint32 bit_offset; + uint32 byte_offset; + uint32 N_bytes; + uint8 spare_field; + char tmp_char; + + if(ie_ptr != NULL && + net_name != NULL) + { + net_name->add_ci = (LIBLTE_MME_ADD_CI_ENUM)(((*ie_ptr)[1] >> 3) & 0x01); + spare_field = (*ie_ptr)[1] & 0x07; + N_bytes = (*ie_ptr)[0]; + bit_offset = 0; + byte_offset = 2; + net_name->name = ""; + while(byte_offset < N_bytes) { - *msg_ptr = LIBLTE_MME_LOCATION_AREA_ID_IEI; - msg_ptr++; - liblte_mme_pack_location_area_id_ie(&attach_req->old_lai, &msg_ptr); + switch(bit_offset) + { + case 0: + tmp_char = (*ie_ptr)[byte_offset] & 0x7F; + bit_offset = 7; + break; + case 1: + tmp_char = ((*ie_ptr)[byte_offset] >> 1) & 0x7F; + bit_offset = 0; + byte_offset++; + break; + case 2: + tmp_char = ((*ie_ptr)[byte_offset] >> 2) & 0x3F; + byte_offset++; + tmp_char |= ((*ie_ptr)[byte_offset] << 6) & 0x40; + bit_offset = 1; + break; + case 3: + tmp_char = ((*ie_ptr)[byte_offset] >> 3) & 0x1F; + byte_offset++; + tmp_char |= ((*ie_ptr)[byte_offset] << 5) & 0x60; + bit_offset = 2; + break; + case 4: + tmp_char = ((*ie_ptr)[byte_offset] >> 4) & 0x0F; + byte_offset++; + tmp_char |= ((*ie_ptr)[byte_offset] << 4) & 0x70; + bit_offset = 3; + break; + case 5: + tmp_char = ((*ie_ptr)[byte_offset] >> 5) & 0x07; + byte_offset++; + tmp_char |= ((*ie_ptr)[byte_offset] << 3) & 0x78; + bit_offset = 4; + break; + case 6: + tmp_char = ((*ie_ptr)[byte_offset] >> 6) & 0x03; + byte_offset++; + tmp_char |= ((*ie_ptr)[byte_offset] << 2) & 0x7C; + bit_offset = 5; + break; + case 7: + tmp_char = ((*ie_ptr)[byte_offset] >> 7) & 0x01; + byte_offset++; + tmp_char |= ((*ie_ptr)[byte_offset] << 1) & 0x7E; + bit_offset = 6; + break; + } + + if(tmp_char == 0x0A || + tmp_char == 0x0D || + (tmp_char >= 0x20 && + tmp_char <= 0x3F) || + (tmp_char >= 0x41 && + tmp_char <= 0x5A) || + (tmp_char >= 0x61 && + tmp_char <= 0x7A)) + { + net_name->name += tmp_char; + } } - // TMSI Status - if(attach_req->tmsi_status_present) + if(0 == bit_offset || + (1 == bit_offset && + 0 == spare_field)) { - *msg_ptr = LIBLTE_MME_TMSI_STATUS_IEI << 4; - liblte_mme_pack_tmsi_status_ie(attach_req->tmsi_status, 0, &msg_ptr); - msg_ptr++; + if(0 == bit_offset) + { + tmp_char = (*ie_ptr)[byte_offset] & 0x7F; + }else{ + tmp_char = ((*ie_ptr)[byte_offset] >> 1) & 0x7F; + } + if(tmp_char == 0x0A || + tmp_char == 0x0D || + (tmp_char >= 0x20 && + tmp_char <= 0x3F) || + (tmp_char >= 0x41 && + tmp_char <= 0x5A) || + (tmp_char >= 0x61 && + tmp_char <= 0x7A)) + { + net_name->name += tmp_char; + } } - // Mobile Station Classmark 2 - if(attach_req->ms_cm2_present) + *ie_ptr += byte_offset + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Nonce + + Description: Transfers a 32-bit nonce value to support deriving + a new mapped EPS security context. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.25 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_nonce_ie(uint32 nonce, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = (nonce >> 24) & 0xFF; + (*ie_ptr)[1] = (nonce >> 16) & 0xFF; + (*ie_ptr)[2] = (nonce >> 8) & 0xFF; + (*ie_ptr)[3] = nonce & 0xFF; + *ie_ptr += 4; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_nonce_ie(uint8 **ie_ptr, + uint32 *nonce) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + nonce != NULL) + { + *nonce = (*ie_ptr)[0] << 24; + *nonce |= (*ie_ptr)[1] << 16; + *nonce |= (*ie_ptr)[2] << 8; + *nonce |= (*ie_ptr)[3]; + *ie_ptr += 4; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Paging Identity + + Description: Indicates the identity used for paging for non-EPS + services. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.25A +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_paging_identity_ie(uint8 paging_id, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = paging_id & 0x01; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_paging_identity_ie(uint8 **ie_ptr, + uint8 *paging_id) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + paging_id != NULL) + { + *paging_id = (*ie_ptr)[0] & 0x01; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: P-TMSI Signature + + Description: Identifies a GMM context of a UE. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.26 + 24.008 v10.2.0 Section 10.5.5.8 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_p_tmsi_signature_ie(uint32 p_tmsi_signature, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = (p_tmsi_signature >> 24) & 0xFF; + (*ie_ptr)[1] = (p_tmsi_signature >> 16) & 0xFF; + (*ie_ptr)[2] = (p_tmsi_signature >> 8) & 0xFF; + (*ie_ptr)[3] = p_tmsi_signature & 0xFF; + *ie_ptr += 4; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_p_tmsi_signature_ie(uint8 **ie_ptr, + uint32 *p_tmsi_signature) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + p_tmsi_signature != NULL) + { + *p_tmsi_signature = (*ie_ptr)[0] << 24; + *p_tmsi_signature |= (*ie_ptr)[1] << 16; + *p_tmsi_signature |= (*ie_ptr)[2] << 8; + *p_tmsi_signature |= (*ie_ptr)[3]; + *ie_ptr += 4; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Service Type + + Description: Specifies the purpose of the service request + procedure. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.27 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_service_type_ie(uint8 value, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] |= (value & 0x0F) << bit_offset; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_service_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *value) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + value != NULL) + { + *value = ((*ie_ptr)[0] >> bit_offset) & 0x0F; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Short MAC + + Description: Protects the integrity of a SERVICE REQUEST message. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.28 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_short_mac_ie(uint16 short_mac, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = (short_mac >> 8) & 0xFF; + (*ie_ptr)[1] = short_mac & 0xFF; + *ie_ptr += 2; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_short_mac_ie(uint8 **ie_ptr, + uint16 *short_mac) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + short_mac != NULL) + { + *short_mac = (*ie_ptr)[0] << 8; + *short_mac |= (*ie_ptr)[1]; + *ie_ptr += 2; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Time Zone + + Description: Encodes the offset between universal time and local + time in steps of 15 minutes. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.29 + 24.008 v10.2.0 Section 10.5.3.8 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_time_zone_ie(uint8 tz, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = tz; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_time_zone_ie(uint8 **ie_ptr, + uint8 *tz) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + tz != NULL) + { + *tz = (*ie_ptr)[0]; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Time Zone And Time + + Description: Encodes the offset between universal time and local + time in steps of 15 minutes and encodes the universal + time at which the IE may have been sent by the + network. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.30 + 24.008 v10.2.0 Section 10.5.3.9 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_time_zone_and_time_ie(LIBLTE_MME_TIME_ZONE_AND_TIME_STRUCT *ttz, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ttz != NULL && + ie_ptr != NULL) + { + (*ie_ptr)[0] = ((ttz->year % 10) << 4) | ((ttz->year % 100) / 10); + (*ie_ptr)[1] = ((ttz->month % 10) << 4) | (ttz->month / 10); + (*ie_ptr)[2] = ((ttz->day % 10) << 4) | (ttz->day / 10); + (*ie_ptr)[3] = ((ttz->hour % 10) << 4) | (ttz->hour / 10); + (*ie_ptr)[4] = ((ttz->minute % 10) << 4) | (ttz->minute / 10); + (*ie_ptr)[5] = ((ttz->second % 10) << 4) | (ttz->second / 10); + (*ie_ptr)[6] = ttz->tz; + *ie_ptr += 7; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_time_zone_and_time_ie(uint8 **ie_ptr, + LIBLTE_MME_TIME_ZONE_AND_TIME_STRUCT *ttz) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + ttz != NULL) + { + ttz->year = 2000 + (((*ie_ptr)[0] & 0x0F) * 10) + (((*ie_ptr)[0] >> 4) & 0x0F); + ttz->month = (((*ie_ptr)[1] & 0x0F) * 10) + (((*ie_ptr)[1] >> 4) & 0x0F); + ttz->day = (((*ie_ptr)[2] & 0x0F) * 10) + (((*ie_ptr)[2] >> 4) & 0x0F); + ttz->hour = (((*ie_ptr)[3] & 0x0F) * 10) + (((*ie_ptr)[3] >> 4) & 0x0F); + ttz->minute = (((*ie_ptr)[4] & 0x0F) * 10) + (((*ie_ptr)[4] >> 4) & 0x0F); + ttz->second = (((*ie_ptr)[5] & 0x0F) * 10) + (((*ie_ptr)[5] >> 4) & 0x0F); + ttz->tz = (*ie_ptr)[6]; + *ie_ptr += 7; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: TMSI Status + + Description: Indicates whether a valid TMSI is available in the + UE or not. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.31 + 24.008 v10.2.0 Section 10.5.5.4 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_tmsi_status_ie(LIBLTE_MME_TMSI_STATUS_ENUM tmsi_status, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + **ie_ptr |= tmsi_status << bit_offset; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_tmsi_status_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_TMSI_STATUS_ENUM *tmsi_status) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + tmsi_status != NULL) + { + *tmsi_status = (LIBLTE_MME_TMSI_STATUS_ENUM)((**ie_ptr >> bit_offset) & 0x01); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Tracking Area Identity + + Description: Provides an unambiguous identification of tracking + areas within the area covered by the 3GPP system. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.32 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_id_ie(LIBLTE_MME_TRACKING_AREA_ID_STRUCT *tai, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(tai != NULL && + ie_ptr != NULL) + { + (*ie_ptr)[0] = (((tai->mcc/10) % 10) << 4) | ((tai->mcc/100) % 10); + if(tai->mnc < 100) + { + (*ie_ptr)[1] = 0xF0 | (tai->mcc % 10); + (*ie_ptr)[2] = ((tai->mnc % 10) << 4) | ((tai->mnc/10) % 10); + }else{ + (*ie_ptr)[1] = ((tai->mnc % 10) << 4) | (tai->mcc % 10); + (*ie_ptr)[2] = (((tai->mnc/10) % 10) << 4) | ((tai->mnc/100) % 10); + } + (*ie_ptr)[3] = (tai->tac >> 8) & 0xFF; + (*ie_ptr)[4] = tai->tac & 0xFF; + *ie_ptr += 5; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_id_ie(uint8 **ie_ptr, + LIBLTE_MME_TRACKING_AREA_ID_STRUCT *tai) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + tai != NULL) + { + tai->mcc = ((*ie_ptr)[0] & 0x0F)*100; + tai->mcc += (((*ie_ptr)[0] >> 4) & 0x0F)*10; + tai->mcc += (*ie_ptr)[1] & 0x0F; + if((((*ie_ptr)[1] >> 4) & 0x0F) == 0x0F) + { + tai->mnc = ((*ie_ptr)[2] & 0x0F)*10; + tai->mnc += ((*ie_ptr)[2] >> 4) & 0x0F; + }else{ + tai->mnc = ((*ie_ptr)[1] >> 4) & 0x0F; + tai->mnc += ((*ie_ptr)[2] & 0x0F)*100; + tai->mnc += (((*ie_ptr)[2] >> 4) & 0x0F)*10; + } + tai->tac = (*ie_ptr)[3] << 8; + tai->tac |= (*ie_ptr)[4]; + *ie_ptr += 5; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Tracking Area Identity List + + Description: Transfers a list of tracking areas from the network + to the UE. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.33 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_identity_list_ie(LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_STRUCT *tai_list, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(tai_list != NULL && + ie_ptr != NULL) + { + (*ie_ptr)[0] = (tai_list->N_tais*5) + 1; + // FIXME: Support all types + if(1 == tai_list->N_tais) + { + (*ie_ptr)[1] = (LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ONE_PLMN_NON_CONSECUTIVE_TACS << 5) | ((tai_list->N_tais - 1) & 0x1F); + }else{ + (*ie_ptr)[1] = (LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_DIFFERENT_PLMNS << 5) | ((tai_list->N_tais - 1) & 0x1F); + } + *ie_ptr += 2; + for(i=0; iN_tais; i++) + { + liblte_mme_pack_tracking_area_id_ie(&tai_list->tai[i], ie_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_identity_list_ie(uint8 **ie_ptr, + LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_STRUCT *tai_list) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ENUM type; + uint32 sent_length; + uint32 length; + uint32 i; + uint32 N_elems; + uint16 mcc; + uint16 mnc; + uint16 tac; + + if(ie_ptr != NULL && + tai_list != NULL) + { + sent_length = (*ie_ptr)[0] + 1; + length = 1; + tai_list->N_tais = 0; + while(length < sent_length) + { + type = (LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ENUM)(((*ie_ptr)[length] >> 5) & 0x03); + N_elems = (*ie_ptr)[length++] & 0x1F; + if(LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ONE_PLMN_NON_CONSECUTIVE_TACS == type) + { + mcc = ((*ie_ptr)[length] & 0x0F)*100; + mcc += (((*ie_ptr)[length++] >> 4) & 0x0F)*10; + mcc += (*ie_ptr)[length] & 0x0F; + if((((*ie_ptr)[length] >> 4) & 0x0F) == 0x0F) + { + length++; + mnc = ((*ie_ptr)[length] & 0x0F)*10; + mnc += ((*ie_ptr)[length++] >> 4) & 0x0F; + }else{ + mnc = ((*ie_ptr)[length++] >> 4) & 0x0F; + mnc += ((*ie_ptr)[length] & 0x0F)*100; + mnc += (((*ie_ptr)[length++] >> 4) & 0x0F)*10; + } + for(i=0; itai[tai_list->N_tais].mcc = mcc; + tai_list->tai[tai_list->N_tais].mnc = mnc; + tai_list->tai[tai_list->N_tais].tac = (*ie_ptr)[length++] << 8; + tai_list->tai[tai_list->N_tais].tac |= (*ie_ptr)[length++]; + tai_list->N_tais++; + } + }else if(LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ONE_PLMN_CONSECUTIVE_TACS == type){ + mcc = ((*ie_ptr)[length] & 0x0F)*100; + mcc += (((*ie_ptr)[length++] >> 4) & 0x0F)*10; + mcc += (*ie_ptr)[length] & 0x0F; + if((((*ie_ptr)[length] >> 4) & 0x0F) == 0x0F) + { + length++; + mnc = ((*ie_ptr)[length] & 0x0F)*10; + mnc += ((*ie_ptr)[length++] >> 4) & 0x0F; + }else{ + mnc = ((*ie_ptr)[length++] >> 4) & 0x0F; + mnc += ((*ie_ptr)[length] & 0x0F)*100; + mnc += (((*ie_ptr)[length++] >> 4) & 0x0F)*10; + } + tac = (*ie_ptr)[length++] << 8; + tac |= (*ie_ptr)[length++]; + for(i=0; itai[tai_list->N_tais].mcc = mcc; + tai_list->tai[tai_list->N_tais].mnc = mnc; + tai_list->tai[tai_list->N_tais].tac = tac + i; + tai_list->N_tais++; + } + }else{ + for(i=0; itai[tai_list->N_tais].mcc = ((*ie_ptr)[length] & 0x0F)*100; + tai_list->tai[tai_list->N_tais].mcc += (((*ie_ptr)[length++] >> 4) & 0x0F)*10; + tai_list->tai[tai_list->N_tais].mcc += (*ie_ptr)[length] & 0x0F; + if((((*ie_ptr)[length] >> 4) & 0x0F) == 0x0F) + { + length++; + tai_list->tai[tai_list->N_tais].mnc = ((*ie_ptr)[length] & 0x0F)*10; + tai_list->tai[tai_list->N_tais].mnc += ((*ie_ptr)[length++] >> 4) & 0x0F; + }else{ + tai_list->tai[tai_list->N_tais].mnc = ((*ie_ptr)[length++] >> 4) & 0x0F; + tai_list->tai[tai_list->N_tais].mnc += ((*ie_ptr)[length] & 0x0F)*100; + tai_list->tai[tai_list->N_tais].mnc += (((*ie_ptr)[length++] >> 4) & 0x0F)*10; + } + tai_list->tai[tai_list->N_tais].tac = (*ie_ptr)[length++] << 8; + tai_list->tai[tai_list->N_tais].tac |= (*ie_ptr)[length++]; + tai_list->N_tais++; + } + } + } + *ie_ptr += (*ie_ptr)[0] + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: UE Network Capability + + Description: Provides the network with information concerning + aspects of the UE related to EPS or interworking with + GPRS. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.34 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_ue_network_capability_ie(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT *ue_network_cap, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ue_network_cap != NULL && + ie_ptr != NULL) + { + if(ue_network_cap->uea_present && + (ue_network_cap->ucs2_present || + ue_network_cap->uia_present) && + (ue_network_cap->lpp_present || + ue_network_cap->lcs_present || + ue_network_cap->onexsrvcc_present || + ue_network_cap->nf_present)) + { + **ie_ptr = 5; + }else if(ue_network_cap->uea_present && + (ue_network_cap->ucs2_present || + ue_network_cap->uia_present)){ + **ie_ptr = 4; + }else if(ue_network_cap->uea_present){ + **ie_ptr = 3; + }else{ + **ie_ptr = 2; + } + *ie_ptr += 1; + **ie_ptr = ue_network_cap->eea[0] << 7; + **ie_ptr |= ue_network_cap->eea[1] << 6; + **ie_ptr |= ue_network_cap->eea[2] << 5; + **ie_ptr |= ue_network_cap->eea[3] << 4; + **ie_ptr |= ue_network_cap->eea[4] << 3; + **ie_ptr |= ue_network_cap->eea[5] << 2; + **ie_ptr |= ue_network_cap->eea[6] << 1; + **ie_ptr |= ue_network_cap->eea[7]; + *ie_ptr += 1; + **ie_ptr = ue_network_cap->eia[0] << 7; + **ie_ptr |= ue_network_cap->eia[1] << 6; + **ie_ptr |= ue_network_cap->eia[2] << 5; + **ie_ptr |= ue_network_cap->eia[3] << 4; + **ie_ptr |= ue_network_cap->eia[4] << 3; + **ie_ptr |= ue_network_cap->eia[5] << 2; + **ie_ptr |= ue_network_cap->eia[6] << 1; + **ie_ptr |= ue_network_cap->eia[7]; + *ie_ptr += 1; + if(ue_network_cap->uea_present) + { + **ie_ptr = ue_network_cap->uea[0] << 7; + **ie_ptr |= ue_network_cap->uea[1] << 6; + **ie_ptr |= ue_network_cap->uea[2] << 5; + **ie_ptr |= ue_network_cap->uea[3] << 4; + **ie_ptr |= ue_network_cap->uea[4] << 3; + **ie_ptr |= ue_network_cap->uea[5] << 2; + **ie_ptr |= ue_network_cap->uea[6] << 1; + **ie_ptr |= ue_network_cap->uea[7]; + *ie_ptr += 1; + } + if(ue_network_cap->ucs2_present || + ue_network_cap->uia_present) + { + **ie_ptr = ue_network_cap->ucs2 << 7; + **ie_ptr |= ue_network_cap->uia[1] << 6; + **ie_ptr |= ue_network_cap->uia[2] << 5; + **ie_ptr |= ue_network_cap->uia[3] << 4; + **ie_ptr |= ue_network_cap->uia[4] << 3; + **ie_ptr |= ue_network_cap->uia[5] << 2; + **ie_ptr |= ue_network_cap->uia[6] << 1; + **ie_ptr |= ue_network_cap->uia[7]; + *ie_ptr += 1; + } + if(ue_network_cap->lpp_present || + ue_network_cap->lcs_present || + ue_network_cap->onexsrvcc_present || + ue_network_cap->nf_present) + { + **ie_ptr = ue_network_cap->lpp << 3; + **ie_ptr |= ue_network_cap->lcs << 2; + **ie_ptr |= ue_network_cap->onexsrvcc << 1; + **ie_ptr |= ue_network_cap->nf; + *ie_ptr += 1; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_network_capability_ie(uint8 **ie_ptr, + LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT *ue_network_cap) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 length; + + if(ie_ptr != NULL && + ue_network_cap != NULL) + { + length = **ie_ptr; + *ie_ptr += 1; + ue_network_cap->eea[0] = (**ie_ptr >> 7) & 0x01; + ue_network_cap->eea[1] = (**ie_ptr >> 6) & 0x01; + ue_network_cap->eea[2] = (**ie_ptr >> 5) & 0x01; + ue_network_cap->eea[3] = (**ie_ptr >> 4) & 0x01; + ue_network_cap->eea[4] = (**ie_ptr >> 3) & 0x01; + ue_network_cap->eea[5] = (**ie_ptr >> 2) & 0x01; + ue_network_cap->eea[6] = (**ie_ptr >> 1) & 0x01; + ue_network_cap->eea[7] = **ie_ptr & 0x01; + *ie_ptr += 1; + ue_network_cap->eia[0] = (**ie_ptr >> 7) & 0x01; + ue_network_cap->eia[1] = (**ie_ptr >> 6) & 0x01; + ue_network_cap->eia[2] = (**ie_ptr >> 5) & 0x01; + ue_network_cap->eia[3] = (**ie_ptr >> 4) & 0x01; + ue_network_cap->eia[4] = (**ie_ptr >> 3) & 0x01; + ue_network_cap->eia[5] = (**ie_ptr >> 2) & 0x01; + ue_network_cap->eia[6] = (**ie_ptr >> 1) & 0x01; + ue_network_cap->eia[7] = **ie_ptr & 0x01; + *ie_ptr += 1; + if(length > 2) + { + ue_network_cap->uea[0] = (**ie_ptr >> 7) & 0x01; + ue_network_cap->uea[1] = (**ie_ptr >> 6) & 0x01; + ue_network_cap->uea[2] = (**ie_ptr >> 5) & 0x01; + ue_network_cap->uea[3] = (**ie_ptr >> 4) & 0x01; + ue_network_cap->uea[4] = (**ie_ptr >> 3) & 0x01; + ue_network_cap->uea[5] = (**ie_ptr >> 2) & 0x01; + ue_network_cap->uea[6] = (**ie_ptr >> 1) & 0x01; + ue_network_cap->uea[7] = **ie_ptr & 0x01; + ue_network_cap->uea_present = true; + *ie_ptr += 1; + }else{ + ue_network_cap->uea_present = false; + } + if(length > 3) + { + ue_network_cap->ucs2 = (**ie_ptr >> 7) & 0x01; + ue_network_cap->ucs2_present = true; + ue_network_cap->uia[1] = (**ie_ptr >> 6) & 0x01; + ue_network_cap->uia[2] = (**ie_ptr >> 5) & 0x01; + ue_network_cap->uia[3] = (**ie_ptr >> 4) & 0x01; + ue_network_cap->uia[4] = (**ie_ptr >> 3) & 0x01; + ue_network_cap->uia[5] = (**ie_ptr >> 2) & 0x01; + ue_network_cap->uia[6] = (**ie_ptr >> 1) & 0x01; + ue_network_cap->uia[7] = **ie_ptr & 0x01; + ue_network_cap->uia_present = true; + *ie_ptr += 1; + }else{ + ue_network_cap->ucs2_present = false; + ue_network_cap->uia_present = false; + } + if(length > 4) + { + ue_network_cap->lpp = (**ie_ptr >> 3) & 0x01; + ue_network_cap->lpp_present = true; + ue_network_cap->lcs = (**ie_ptr >> 2) & 0x01; + ue_network_cap->lcs_present = true; + ue_network_cap->onexsrvcc = (**ie_ptr >> 1) & 0x01; + ue_network_cap->onexsrvcc_present = true; + ue_network_cap->nf = **ie_ptr >> 1; + ue_network_cap->nf_present = true; + *ie_ptr += 1; + }else{ + ue_network_cap->lpp_present = false; + ue_network_cap->lcs_present = false; + ue_network_cap->onexsrvcc_present = false; + ue_network_cap->nf_present = false; + } + if(length > 5) + { + *ie_ptr += length-5; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: UE Radio Capability Update Needed + + Description: Indicates whether the MME shall delete the stored + UE radio capability information, if any. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.35 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_ue_radio_capability_update_needed_ie(uint8 urc_update, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] |= (urc_update & 0x01) << bit_offset; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_radio_capability_update_needed_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *urc_update) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + urc_update != NULL) + { + *urc_update = ((*ie_ptr)[0] >> bit_offset) & 0x01; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: UE Security Capability + + Description: Indicates which security algorithms are supported by + the UE in S1 mode. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.36 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_ue_security_capabilities_ie(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *ue_sec_cap, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 idx; + + if(ue_sec_cap != NULL && + ie_ptr != NULL) + { + if(ue_sec_cap->uea_present && + ue_sec_cap->uia_present && + ue_sec_cap->gea_present) + { + (*ie_ptr)[0] = 5; + }else if(ue_sec_cap->uea_present && + ue_sec_cap->uia_present){ + (*ie_ptr)[0] = 4; + }else if(ue_sec_cap->uea_present){ + (*ie_ptr)[0] = 3; + }else{ + (*ie_ptr)[0] = 2; + } + idx = 1; + (*ie_ptr)[idx] = ue_sec_cap->eea[0] << 7; + (*ie_ptr)[idx] |= ue_sec_cap->eea[1] << 6; + (*ie_ptr)[idx] |= ue_sec_cap->eea[2] << 5; + (*ie_ptr)[idx] |= ue_sec_cap->eea[3] << 4; + (*ie_ptr)[idx] |= ue_sec_cap->eea[4] << 3; + (*ie_ptr)[idx] |= ue_sec_cap->eea[5] << 2; + (*ie_ptr)[idx] |= ue_sec_cap->eea[6] << 1; + (*ie_ptr)[idx] |= ue_sec_cap->eea[7]; + idx++; + (*ie_ptr)[idx] = ue_sec_cap->eia[0] << 7; + (*ie_ptr)[idx] |= ue_sec_cap->eia[1] << 6; + (*ie_ptr)[idx] |= ue_sec_cap->eia[2] << 5; + (*ie_ptr)[idx] |= ue_sec_cap->eia[3] << 4; + (*ie_ptr)[idx] |= ue_sec_cap->eia[4] << 3; + (*ie_ptr)[idx] |= ue_sec_cap->eia[5] << 2; + (*ie_ptr)[idx] |= ue_sec_cap->eia[6] << 1; + (*ie_ptr)[idx] |= ue_sec_cap->eia[7]; + idx++; + if(ue_sec_cap->uea_present) + { + (*ie_ptr)[idx] = ue_sec_cap->uea[0] << 7; + (*ie_ptr)[idx] |= ue_sec_cap->uea[1] << 6; + (*ie_ptr)[idx] |= ue_sec_cap->uea[2] << 5; + (*ie_ptr)[idx] |= ue_sec_cap->uea[3] << 4; + (*ie_ptr)[idx] |= ue_sec_cap->uea[4] << 3; + (*ie_ptr)[idx] |= ue_sec_cap->uea[5] << 2; + (*ie_ptr)[idx] |= ue_sec_cap->uea[6] << 1; + (*ie_ptr)[idx] |= ue_sec_cap->uea[7]; + idx++; + } + if(ue_sec_cap->uia_present) + { + (*ie_ptr)[idx] = ue_sec_cap->uia[1] << 6; + (*ie_ptr)[idx] |= ue_sec_cap->uia[2] << 5; + (*ie_ptr)[idx] |= ue_sec_cap->uia[3] << 4; + (*ie_ptr)[idx] |= ue_sec_cap->uia[4] << 3; + (*ie_ptr)[idx] |= ue_sec_cap->uia[5] << 2; + (*ie_ptr)[idx] |= ue_sec_cap->uia[6] << 1; + (*ie_ptr)[idx] |= ue_sec_cap->uia[7]; + idx++; + } + if(ue_sec_cap->gea_present) + { + (*ie_ptr)[idx] = ue_sec_cap->gea[1] << 6; + (*ie_ptr)[idx] |= ue_sec_cap->gea[2] << 5; + (*ie_ptr)[idx] |= ue_sec_cap->gea[3] << 4; + (*ie_ptr)[idx] |= ue_sec_cap->gea[4] << 3; + (*ie_ptr)[idx] |= ue_sec_cap->gea[5] << 2; + (*ie_ptr)[idx] |= ue_sec_cap->gea[6] << 1; + (*ie_ptr)[idx] |= ue_sec_cap->gea[7]; + idx++; + } + *ie_ptr += idx; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_security_capabilities_ie(uint8 **ie_ptr, + LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *ue_sec_cap) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 length; + + if(ie_ptr != NULL && + ue_sec_cap != NULL) + { + length = (*ie_ptr)[0]; + ue_sec_cap->eea[0] = ((*ie_ptr)[1] >> 7) & 0x01; + ue_sec_cap->eea[1] = ((*ie_ptr)[1] >> 6) & 0x01; + ue_sec_cap->eea[2] = ((*ie_ptr)[1] >> 5) & 0x01; + ue_sec_cap->eea[3] = ((*ie_ptr)[1] >> 4) & 0x01; + ue_sec_cap->eea[4] = ((*ie_ptr)[1] >> 3) & 0x01; + ue_sec_cap->eea[5] = ((*ie_ptr)[1] >> 2) & 0x01; + ue_sec_cap->eea[6] = ((*ie_ptr)[1] >> 1) & 0x01; + ue_sec_cap->eea[7] = (*ie_ptr)[1] & 0x01; + ue_sec_cap->eia[0] = ((*ie_ptr)[2] >> 7) & 0x01; + ue_sec_cap->eia[1] = ((*ie_ptr)[2] >> 6) & 0x01; + ue_sec_cap->eia[2] = ((*ie_ptr)[2] >> 5) & 0x01; + ue_sec_cap->eia[3] = ((*ie_ptr)[2] >> 4) & 0x01; + ue_sec_cap->eia[4] = ((*ie_ptr)[2] >> 3) & 0x01; + ue_sec_cap->eia[5] = ((*ie_ptr)[2] >> 2) & 0x01; + ue_sec_cap->eia[6] = ((*ie_ptr)[2] >> 1) & 0x01; + ue_sec_cap->eia[7] = (*ie_ptr)[2] & 0x01; + if(length > 2) + { + ue_sec_cap->uea[0] = ((*ie_ptr)[3] >> 7) & 0x01; + ue_sec_cap->uea[1] = ((*ie_ptr)[3] >> 6) & 0x01; + ue_sec_cap->uea[2] = ((*ie_ptr)[3] >> 5) & 0x01; + ue_sec_cap->uea[3] = ((*ie_ptr)[3] >> 4) & 0x01; + ue_sec_cap->uea[4] = ((*ie_ptr)[3] >> 3) & 0x01; + ue_sec_cap->uea[5] = ((*ie_ptr)[3] >> 2) & 0x01; + ue_sec_cap->uea[6] = ((*ie_ptr)[3] >> 1) & 0x01; + ue_sec_cap->uea[7] = (*ie_ptr)[3] & 0x01; + ue_sec_cap->uea_present = true; + }else{ + ue_sec_cap->uea_present = false; + } + if(length > 3) + { + ue_sec_cap->uia[1] = ((*ie_ptr)[4] >> 6) & 0x01; + ue_sec_cap->uia[2] = ((*ie_ptr)[4] >> 5) & 0x01; + ue_sec_cap->uia[3] = ((*ie_ptr)[4] >> 4) & 0x01; + ue_sec_cap->uia[4] = ((*ie_ptr)[4] >> 3) & 0x01; + ue_sec_cap->uia[5] = ((*ie_ptr)[4] >> 2) & 0x01; + ue_sec_cap->uia[6] = ((*ie_ptr)[4] >> 1) & 0x01; + ue_sec_cap->uia[7] = (*ie_ptr)[4] & 0x01; + ue_sec_cap->uia_present = true; + }else{ + ue_sec_cap->uia_present = false; + } + if(length > 4) + { + ue_sec_cap->gea[1] = ((*ie_ptr)[5] >> 6) & 0x01; + ue_sec_cap->gea[2] = ((*ie_ptr)[5] >> 5) & 0x01; + ue_sec_cap->gea[3] = ((*ie_ptr)[5] >> 4) & 0x01; + ue_sec_cap->gea[4] = ((*ie_ptr)[5] >> 3) & 0x01; + ue_sec_cap->gea[5] = ((*ie_ptr)[5] >> 2) & 0x01; + ue_sec_cap->gea[6] = ((*ie_ptr)[5] >> 1) & 0x01; + ue_sec_cap->gea[7] = (*ie_ptr)[5] & 0x01; + ue_sec_cap->gea_present = true; + }else{ + ue_sec_cap->gea_present = false; + } + *ie_ptr += length + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Emergency Number List + + Description: Encodes emergency number(s) for use within the + country (as indicated by MCC) where the IE is + received. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.37 + 24.008 v10.2.0 Section 10.5.3.13 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_emergency_number_list_ie(LIBLTE_MME_EMERGENCY_NUMBER_LIST_STRUCT *emerg_num_list, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + uint32 j; + uint32 length; + + if(emerg_num_list != NULL && + ie_ptr != NULL) + { + length = 1; + for(i=0; iN_emerg_nums; i++) + { + if((emerg_num_list->emerg_num[i].N_emerg_num_digits % 2) == 0) + { + (*ie_ptr)[length++] = (emerg_num_list->emerg_num[i].N_emerg_num_digits/2) + 1; + (*ie_ptr)[length++] = emerg_num_list->emerg_num[i].emerg_service_cat; + for(j=0; jemerg_num[i].N_emerg_num_digits/2; j++) + { + (*ie_ptr)[length] = emerg_num_list->emerg_num[i].emerg_num[j*2+0]; + (*ie_ptr)[length++] |= emerg_num_list->emerg_num[i].emerg_num[j*2+1] << 4; + } + }else{ + (*ie_ptr)[length++] = (emerg_num_list->emerg_num[i].N_emerg_num_digits/2) + 2; + (*ie_ptr)[length++] = emerg_num_list->emerg_num[i].emerg_service_cat; + for(j=0; jemerg_num[i].N_emerg_num_digits/2; j++) + { + (*ie_ptr)[length] = emerg_num_list->emerg_num[i].emerg_num[j*2+0]; + (*ie_ptr)[length++] |= emerg_num_list->emerg_num[i].emerg_num[j*2+1] << 4; + } + (*ie_ptr)[length++] = 0xF0 | emerg_num_list->emerg_num[i].emerg_num[j*2]; + } + } + (*ie_ptr)[0] = length - 2; + *ie_ptr += length - 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_emergency_number_list_ie(uint8 **ie_ptr, + LIBLTE_MME_EMERGENCY_NUMBER_LIST_STRUCT *emerg_num_list) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 sent_length; + uint32 length; + uint32 idx; + uint32 i; + + if(ie_ptr != NULL && + emerg_num_list != NULL) + { + sent_length = (*ie_ptr)[0] + 1; + length = 1; + emerg_num_list->N_emerg_nums = 0; + while(length < sent_length) + { + idx = emerg_num_list->N_emerg_nums; + emerg_num_list->emerg_num[idx].N_emerg_num_digits = ((*ie_ptr)[length++] - 1) * 2; + emerg_num_list->emerg_num[idx].emerg_service_cat = (LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_ENUM)((*ie_ptr)[length++] & 0x1F); + for(i=0; iemerg_num[idx].N_emerg_num_digits/2; i++) + { + emerg_num_list->emerg_num[idx].emerg_num[i*2+0] = (*ie_ptr)[length] & 0x0F; + emerg_num_list->emerg_num[idx].emerg_num[i*2+1] = (*ie_ptr)[length++] >> 4; + } + if(emerg_num_list->emerg_num[idx].emerg_num[i*2-1] == 0x0F) + { + emerg_num_list->emerg_num[idx].N_emerg_num_digits--; + } + emerg_num_list->N_emerg_nums++; + } + *ie_ptr += (*ie_ptr)[0] + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: CLI + + Description: Conveys information about the calling line for a + terminated call to a CS fallback capable UE. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.38 +*********************************************************************/ +// FIXME + +/********************************************************************* + IE Name: SS Code + + Description: Conveys information related to a network initiated + supplementary service request to a CS fallback + capable UE. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.39 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_ss_code_ie(uint8 code, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = code; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_ss_code_ie(uint8 **ie_ptr, + uint8 *code) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + code != NULL) + { + *code = (*ie_ptr)[0]; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: LCS Indicator + + Description: Indicates that the origin of the message is due to a + LCS request and the type of this request to a CS + fallback capable UE. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.40 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_lcs_indicator_ie(uint8 lcs_ind, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = lcs_ind; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_lcs_indicator_ie(uint8 **ie_ptr, + uint8 *lcs_ind) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + lcs_ind != NULL) + { + *lcs_ind = (*ie_ptr)[0]; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: LCS Client Identity + + Description: Conveys information related to the client of a LCS + request for a CS fallback capable UE. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.41 +*********************************************************************/ +// FIXME + +/********************************************************************* + IE Name: Generic Message Container Type + + Description: Specifies the type of message contained in the + generic message container IE. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.42 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_generic_message_container_type_ie(uint8 msg_cont_type, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = msg_cont_type; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_generic_message_container_type_ie(uint8 **ie_ptr, + uint8 *msg_cont_type) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + msg_cont_type != NULL) + { + *msg_cont_type = (*ie_ptr)[0]; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Generic Message Container + + Description: Encapsulates the application message transferred + between the UE and the network. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.43 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_generic_message_container_ie(LIBLTE_BYTE_MSG_STRUCT *msg, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(msg != NULL && + ie_ptr != NULL) + { + (*ie_ptr)[0] = msg->N_bytes >> 8; + (*ie_ptr)[1] = msg->N_bytes & 0xFF; + for(i=0; iN_bytes; i++) + { + (*ie_ptr)[2+i] = msg->msg[i]; + } + *ie_ptr += msg->N_bytes + 2; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_generic_message_container_ie(uint8 **ie_ptr, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ie_ptr != NULL && + msg != NULL) + { + msg->N_bytes = (*ie_ptr)[0] << 8; + msg->N_bytes |= (*ie_ptr)[1]; + for(i=0; iN_bytes; i++) + { + msg->msg[i] = (*ie_ptr)[2+i]; + } + *ie_ptr += msg->N_bytes + 2; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Voice Domain Preference and UE's Usage Setting + + Description: Provides the network with the UE's usage setting and + the voice domain preference for the E-UTRAN. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.44 + 24.008 v10.2.0 Section 10.5.5.28 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_voice_domain_pref_and_ue_usage_setting_ie(LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_STRUCT *voice_domain_pref_and_ue_usage_setting, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(voice_domain_pref_and_ue_usage_setting != NULL && + ie_ptr != NULL) + { + **ie_ptr = 1; + *ie_ptr += 1; + **ie_ptr = voice_domain_pref_and_ue_usage_setting->ue_usage_setting << 2; + **ie_ptr |= voice_domain_pref_and_ue_usage_setting->voice_domain_pref; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_voice_domain_pref_and_ue_usage_setting_ie(uint8 **ie_ptr, + LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_STRUCT *voice_domain_pref_and_ue_usage_setting) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + voice_domain_pref_and_ue_usage_setting != NULL) + { + *ie_ptr += 1; + voice_domain_pref_and_ue_usage_setting->ue_usage_setting = (LIBLTE_MME_UE_USAGE_SETTING_ENUM)((**ie_ptr >> 2) & 0x01); + voice_domain_pref_and_ue_usage_setting->voice_domain_pref = (LIBLTE_MME_VOICE_DOMAIN_PREF_ENUM)(**ie_ptr & 0x03); + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: GUTI Type + + Description: Indicates whether the GUTI included in the same + message in an information element of type EPS + mobility identity represents a native GUTI or a + mapped GUTI. + + Document Reference: 24.301 v10.2.0 Section 9.9.3.45 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_guti_type_ie(LIBLTE_MME_GUTI_TYPE_ENUM guti_type, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + **ie_ptr |= guti_type << bit_offset; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_GUTI_TYPE_ENUM *guti_type) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + guti_type != NULL) + { + *guti_type = (LIBLTE_MME_GUTI_TYPE_ENUM)((**ie_ptr >> bit_offset) & 0x01); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Access Point Name + + Description: Identifies the packet data network to which the GPRS + user wishes to connect and notifies the access point + of the packet data network that wishes to connect to + the UE. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.1 + 24.008 v10.2.0 Section 10.5.6.1 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_access_point_name_ie(LIBLTE_MME_ACCESS_POINT_NAME_STRUCT *apn, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + const char *apn_str; + uint32 i; + uint32 len_idx; + uint32 apn_idx; + uint32 label_len; + + if(apn != NULL && + ie_ptr != NULL) + { + apn_str = apn->apn.c_str(); + (*ie_ptr)[0] = apn->apn.length()+1; + len_idx = 0; + apn_idx = 0; + label_len = 0; + while(apn->apn.length() > apn_idx) + { + (*ie_ptr)[1+apn_idx+1] = (uint8)apn_str[apn_idx]; + apn_idx++; + label_len++; + + if(apn_str[apn_idx] == '.') + { + (*ie_ptr)[1+len_idx] = label_len; + label_len = 0; + len_idx = apn_idx+1; + apn_idx++; + } + } + (*ie_ptr)[1+len_idx] = label_len; + *ie_ptr += apn->apn.length() + 2; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_access_point_name_ie(uint8 **ie_ptr, + LIBLTE_MME_ACCESS_POINT_NAME_STRUCT *apn) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + uint32 ie_idx; + uint32 label_len; + + if(ie_ptr != NULL && + apn != NULL) + { + apn->apn.clear(); + ie_idx = 0; + while(ie_idx < (*ie_ptr)[0]) + { + label_len = (*ie_ptr)[1+ie_idx]; + for(i=0; iapn += (char)((*ie_ptr)[1+ie_idx+i+1]); + } + ie_idx += label_len + 1; + if(ie_idx < (*ie_ptr)[0]) + { + apn->apn += '.'; + } + } + apn->apn += "\0"; + *ie_ptr += (*ie_ptr)[0] + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: APN Aggregate Maximum Bit Rate + + Description: Indicates the initial subscribed APN-AMBR when the + UE establishes a PDN connection or indicates the new + APN-AMBR if it is changed by the network. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_apn_aggregate_maximum_bit_rate_ie(LIBLTE_MME_APN_AGGREGATE_MAXIMUM_BIT_RATE_STRUCT *apn_ambr, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(apn_ambr != NULL && + ie_ptr != NULL) + { + if(apn_ambr->ext_present && + apn_ambr->ext2_present) + { + (*ie_ptr)[0] = 6; + }else if(apn_ambr->ext_present){ + (*ie_ptr)[0] = 4; + }else{ + (*ie_ptr)[0] = 2; + } + (*ie_ptr)[1] = apn_ambr->apn_ambr_dl; + (*ie_ptr)[2] = apn_ambr->apn_ambr_ul; + if(apn_ambr->ext_present) + { + (*ie_ptr)[3] = apn_ambr->apn_ambr_dl_ext; + (*ie_ptr)[4] = apn_ambr->apn_ambr_ul_ext; + } + if(apn_ambr->ext2_present) + { + (*ie_ptr)[5] = apn_ambr->apn_ambr_dl_ext2; + (*ie_ptr)[6] = apn_ambr->apn_ambr_ul_ext2; + } + if(apn_ambr->ext_present && + apn_ambr->ext2_present) + { + *ie_ptr += 7; + }else if(apn_ambr->ext_present){ + *ie_ptr += 5; + }else{ + *ie_ptr += 3; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_apn_aggregate_maximum_bit_rate_ie(uint8 **ie_ptr, + LIBLTE_MME_APN_AGGREGATE_MAXIMUM_BIT_RATE_STRUCT *apn_ambr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + apn_ambr != NULL) + { + if(6 == (*ie_ptr)[0]) + { + apn_ambr->ext_present = true; + apn_ambr->ext2_present = true; + }else if(4 == (*ie_ptr)[0]){ + apn_ambr->ext_present = true; + apn_ambr->ext2_present = false; + }else{ + apn_ambr->ext_present = false; + apn_ambr->ext2_present = false; + } + apn_ambr->apn_ambr_dl = (*ie_ptr)[1]; + apn_ambr->apn_ambr_ul = (*ie_ptr)[2]; + if(apn_ambr->ext_present) + { + apn_ambr->apn_ambr_dl_ext = (*ie_ptr)[3]; + apn_ambr->apn_ambr_ul_ext = (*ie_ptr)[4]; + } + if(apn_ambr->ext2_present) + { + apn_ambr->apn_ambr_dl_ext2 = (*ie_ptr)[5]; + apn_ambr->apn_ambr_ul_ext2 = (*ie_ptr)[6]; + } + if(apn_ambr->ext_present && + apn_ambr->ext2_present) + { + *ie_ptr += 7; + }else if(apn_ambr->ext_present){ + *ie_ptr += 5; + }else{ + *ie_ptr += 3; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Connectivity Type + + Description: Specifies the type of connectivity selected by the + network for the PDN connection. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.2A + 24.008 v10.2.0 Section 10.5.6.19 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_connectivity_type_ie(uint8 con_type, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] |= con_type << bit_offset; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_connectivity_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *con_type) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + con_type != NULL) + { + *con_type = ((*ie_ptr)[0] >> bit_offset) & 0x0F; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: EPS Quality Of Service + + Description: Specifies the QoS parameters for an EPS bearer + context. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_eps_quality_of_service_ie(LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT *qos, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(qos != NULL && + ie_ptr != NULL) + { + if(qos->br_present && + qos->br_ext_present) + { + (*ie_ptr)[0] = 9; + }else if(qos->br_present){ + (*ie_ptr)[0] = 5; + }else{ + (*ie_ptr)[0] = 1; + } + (*ie_ptr)[1] = qos->qci; + if(qos->br_present) + { + (*ie_ptr)[2] = qos->mbr_ul; + (*ie_ptr)[3] = qos->mbr_dl; + (*ie_ptr)[4] = qos->gbr_ul; + (*ie_ptr)[5] = qos->gbr_dl; + } + if(qos->br_ext_present) + { + (*ie_ptr)[6] = qos->mbr_ul_ext; + (*ie_ptr)[7] = qos->mbr_dl_ext; + (*ie_ptr)[8] = qos->gbr_ul_ext; + (*ie_ptr)[9] = qos->gbr_dl_ext; + } + if(qos->br_present && + qos->br_ext_present) + { + *ie_ptr += 10; + }else if(qos->br_present){ + *ie_ptr += 6; + }else{ + *ie_ptr += 2; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_quality_of_service_ie(uint8 **ie_ptr, + LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT *qos) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + qos != NULL) + { + if((*ie_ptr)[0] == 1) + { + qos->br_present = false; + qos->br_ext_present = false; + }else if((*ie_ptr)[1] == 5){ + qos->br_present = true; + qos->br_ext_present = false; + }else{ + qos->br_present = true; + qos->br_ext_present = true; + } + qos->qci = (*ie_ptr)[1]; + if(qos->br_present) + { + qos->mbr_ul = (*ie_ptr)[2]; + qos->mbr_dl = (*ie_ptr)[3]; + qos->gbr_ul = (*ie_ptr)[4]; + qos->gbr_dl = (*ie_ptr)[5]; + } + if(qos->br_ext_present) + { + qos->mbr_ul_ext = (*ie_ptr)[6]; + qos->mbr_dl_ext = (*ie_ptr)[7]; + qos->gbr_ul_ext = (*ie_ptr)[8]; + qos->gbr_dl_ext = (*ie_ptr)[9]; + } + if(qos->br_present && + qos->br_ext_present) + { + *ie_ptr += 10; + }else if(qos->br_present){ + *ie_ptr += 6; + }else{ + *ie_ptr += 2; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: ESM Cause + + Description: Indicates the reason why a session management request + is rejected. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.4 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_esm_cause_ie(uint8 cause, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = cause; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_cause_ie(uint8 **ie_ptr, + uint8 *cause) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + cause != NULL) + { + *cause = (*ie_ptr)[0]; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: ESM Information Transfer Flag + + Description: Indicates whether ESM information, i.e. protocol + configuration options or APN or both, is to be + transferred security protected. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_esm_info_transfer_flag_ie(LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_ENUM esm_info_transfer_flag, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + **ie_ptr |= esm_info_transfer_flag << bit_offset; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_info_transfer_flag_ie(uint8 **ie_ptr, + uint8 bit_offset, + LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_ENUM *esm_info_transfer_flag) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + esm_info_transfer_flag != NULL) + { + *esm_info_transfer_flag = (LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_ENUM)((**ie_ptr >> bit_offset) & 0x01); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Linked EPS Bearer Identity + + Description: Identifies the default bearer that is associated + with a dedicated EPS bearer or identifies the EPS + bearer (default or dedicated) with which one or more + packet filters specified in a traffic flow aggregate + are associated. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.6 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_linked_eps_bearer_identity_ie(uint8 bearer_id, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] |= (bearer_id & 0x0F) << bit_offset; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_linked_eps_bearer_identity_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *bearer_id) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + bearer_id != NULL) + { + *bearer_id = ((*ie_ptr)[0] >> bit_offset) & 0x0F; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: LLC Service Access Point Identifier + + Description: Identifies the service access point that is used for + the GPRS data transfer at LLC layer. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.7 + 24.008 v10.2.0 Section 10.5.6.9 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_llc_service_access_point_identifier_ie(uint8 llc_sapi, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = llc_sapi; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_llc_service_access_point_identifier_ie(uint8 **ie_ptr, + uint8 *llc_sapi) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + llc_sapi != NULL) + { + *llc_sapi = (*ie_ptr)[0]; + *ie_ptr += 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Notification Indicator + + Description: Informs the UE about an event which is relevant for + the upper layer using an EPS bearer context or + having requested a procedure transaction. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.7A +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_notification_indicator_ie(uint8 notification_ind, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = 1; + (*ie_ptr)[1] = notification_ind; + *ie_ptr += 2; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_notification_indicator_ie(uint8 **ie_ptr, + uint8 *notification_ind) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + notification_ind != NULL) + { + *notification_ind = (*ie_ptr)[1]; + *ie_ptr += 2; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Packet Flow Identifier + + Description: Indicates the packet flow identifier for a packet + flow context. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.8 + 24.008 v10.2.0 Section 10.5.6.11 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_packet_flow_identifier_ie(uint8 packet_flow_id, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] = 1; + (*ie_ptr)[1] = packet_flow_id; + *ie_ptr += 2; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_packet_flow_identifier_ie(uint8 **ie_ptr, + uint8 *packet_flow_id) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + packet_flow_id != NULL) + { + *packet_flow_id = (*ie_ptr)[1]; + *ie_ptr += (*ie_ptr)[0]; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: PDN Address + + Description: Assigns an IPv4 address to the UE associated with a + packet data network and provides the UE with an + interface identifier to be used to build the IPv6 + link local address. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.9 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_address_ie(LIBLTE_MME_PDN_ADDRESS_STRUCT *pdn_addr, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(pdn_addr != NULL && + ie_ptr != NULL) + { + (*ie_ptr)[1] = 0x00 | (pdn_addr->pdn_type & 0x07); + if(LIBLTE_MME_PDN_TYPE_IPV4 == pdn_addr->pdn_type) + { + for(i=0; i<4; i++) + { + (*ie_ptr)[2+i] = pdn_addr->addr[i]; + } + (*ie_ptr)[0] = 5; + *ie_ptr += 6; + }else if(LIBLTE_MME_PDN_TYPE_IPV6 == pdn_addr->pdn_type){ + for(i=0; i<8; i++) + { + (*ie_ptr)[2+i] = pdn_addr->addr[i]; + } + (*ie_ptr)[0] = 9; + *ie_ptr += 10; + }else{ + for(i=0; i<12; i++) + { + (*ie_ptr)[2+i] = pdn_addr->addr[i]; + } + (*ie_ptr)[0] = 13; + *ie_ptr += 14; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_address_ie(uint8 **ie_ptr, + LIBLTE_MME_PDN_ADDRESS_STRUCT *pdn_addr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ie_ptr != NULL && + pdn_addr != NULL) + { + pdn_addr->pdn_type = (*ie_ptr)[1] & 0x07; + if(LIBLTE_MME_PDN_TYPE_IPV4 == pdn_addr->pdn_type) + { + for(i=0; i<4; i++) + { + pdn_addr->addr[i] = (*ie_ptr)[2+i]; + } + }else if(LIBLTE_MME_PDN_TYPE_IPV6 == pdn_addr->pdn_type){ + for(i=0; i<8; i++) + { + pdn_addr->addr[i] = (*ie_ptr)[2+i]; + } + }else{ + for(i=0; i<12; i++) + { + pdn_addr->addr[i] = (*ie_ptr)[2+i]; + } + } + *ie_ptr += (*ie_ptr)[0] + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: PDN Type + + Description: Indicates the IP version capability of the IP stack + associated with the UE. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.10 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_type_ie(uint8 pdn_type, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + **ie_ptr |= pdn_type << bit_offset; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *pdn_type) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + pdn_type != NULL) + { + *pdn_type = (**ie_ptr >> bit_offset) & 0x07; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Protocol Configuration Options + + Description: Transfers external network protocol options + associated with a PDP context activation and + transfers additional (protocol) data (e.g. + configuration parameters, error codes or messages/ + events) associated with an external protocol or an + application. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.11 + 24.008 v10.2.0 Section 10.5.6.3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_protocol_config_options_ie(LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT *protocol_cnfg_opts, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 idx; + uint32 i; + uint32 j; + + if(protocol_cnfg_opts != NULL && + ie_ptr != NULL) + { + (*ie_ptr)[1] = 0x80; + idx = 2; + for(i=0; iN_opts; i++) + { + (*ie_ptr)[idx++] = protocol_cnfg_opts->opt[i].id >> 8; + (*ie_ptr)[idx++] = protocol_cnfg_opts->opt[i].id & 0x00FF; + (*ie_ptr)[idx++] = protocol_cnfg_opts->opt[i].len; + for(j=0; jopt[i].len; j++) + { + (*ie_ptr)[idx++] = protocol_cnfg_opts->opt[i].contents[j]; + } + } + (*ie_ptr)[0] = idx - 1; + *ie_ptr += idx; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_protocol_config_options_ie(uint8 **ie_ptr, + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT *protocol_cnfg_opts) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 idx; + uint32 i; + + if(ie_ptr != NULL && + protocol_cnfg_opts != NULL) + { + idx = 2; + protocol_cnfg_opts->N_opts = 0; + while(idx < (*ie_ptr)[0]) + { + protocol_cnfg_opts->opt[protocol_cnfg_opts->N_opts].id = (*ie_ptr)[idx++] << 8; + protocol_cnfg_opts->opt[protocol_cnfg_opts->N_opts].id |= (*ie_ptr)[idx++]; + protocol_cnfg_opts->opt[protocol_cnfg_opts->N_opts].len = (*ie_ptr)[idx++]; + for(i=0; iopt[protocol_cnfg_opts->N_opts].len; i++) + { + protocol_cnfg_opts->opt[protocol_cnfg_opts->N_opts].contents[i] = (*ie_ptr)[idx++]; + } + protocol_cnfg_opts->N_opts++; + } + *ie_ptr += (*ie_ptr)[0] + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Quality Of Service + + Description: Specifies the QoS parameters for a PDP context. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.12 + 24.008 v10.2.0 Section 10.5.6.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_quality_of_service_ie(LIBLTE_MME_QUALITY_OF_SERVICE_STRUCT *qos, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(qos != NULL && + ie_ptr != NULL) + { + if(qos->dl_ext_present && + qos->ul_ext_present) + { + (*ie_ptr)[0] = 16; + }else if(qos->dl_ext_present){ + (*ie_ptr)[0] = 14; + }else{ + (*ie_ptr)[0] = 12; + } + (*ie_ptr)[1] = ((qos->delay_class & 0x07) << 3) | (qos->reliability_class & 0x07); + (*ie_ptr)[2] = ((qos->peak_throughput & 0x0F) << 4) | (qos->precedence_class & 0x07); + (*ie_ptr)[3] = qos->mean_throughput & 0x1F; + (*ie_ptr)[4] = ((qos->traffic_class & 0x07) << 5) | ((qos->delivery_order & 0x03) << 3) | (qos->delivery_of_erroneous_sdu & 0x03); + (*ie_ptr)[5] = qos->max_sdu_size; + (*ie_ptr)[6] = qos->mbr_ul; + (*ie_ptr)[7] = qos->mbr_dl; + (*ie_ptr)[8] = ((qos->residual_ber & 0x0F) << 4) | (qos->sdu_error_ratio & 0x0F); + (*ie_ptr)[9] = ((qos->transfer_delay & 0x3F) << 2) | (qos->traffic_handling_prio & 0x03); + (*ie_ptr)[10] = qos->gbr_ul; + (*ie_ptr)[11] = qos->gbr_dl; + (*ie_ptr)[12] = ((qos->signalling_ind & 0x01) << 4) | (qos->source_stats_descriptor & 0x0F); + if(qos->dl_ext_present) + { + (*ie_ptr)[13] = qos->mbr_dl_ext; + (*ie_ptr)[14] = qos->gbr_dl_ext; + } + if(qos->ul_ext_present) + { + (*ie_ptr)[15] = qos->mbr_ul_ext; + (*ie_ptr)[16] = qos->gbr_ul_ext; + } + if(qos->dl_ext_present && + qos->ul_ext_present) + { + *ie_ptr += 17; + }else if(qos->dl_ext_present){ + *ie_ptr += 15; + }else{ + *ie_ptr += 13; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_quality_of_service_ie(uint8 **ie_ptr, + LIBLTE_MME_QUALITY_OF_SERVICE_STRUCT *qos) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + qos != NULL) + { + if(16 == (*ie_ptr)[0]) + { + qos->dl_ext_present = true; + qos->ul_ext_present = true; + }else if(14 == (*ie_ptr)[0]){ + qos->dl_ext_present = true; + qos->ul_ext_present = false; + }else{ + qos->dl_ext_present = false; + qos->ul_ext_present = false; + } + qos->delay_class = ((*ie_ptr)[1] >> 3) & 0x07; + qos->reliability_class = (*ie_ptr)[1] & 0x07; + qos->peak_throughput = (*ie_ptr)[2] >> 4; + qos->precedence_class = (*ie_ptr)[2] & 0x07; + qos->mean_throughput = (*ie_ptr)[3] & 0x1F; + qos->traffic_class = ((*ie_ptr)[4] >> 5) & 0x07; + qos->delivery_order = ((*ie_ptr)[4] >> 3) & 0x03; + qos->delivery_of_erroneous_sdu = (*ie_ptr)[4] & 0x07; + qos->max_sdu_size = (*ie_ptr)[5]; + qos->mbr_ul = (*ie_ptr)[6]; + qos->mbr_dl = (*ie_ptr)[7]; + qos->residual_ber = ((*ie_ptr)[8] >> 4) & 0x0F; + qos->sdu_error_ratio = (*ie_ptr)[8] & 0x0F; + qos->transfer_delay = ((*ie_ptr)[9] >> 2) & 0x3F; + qos->traffic_handling_prio = (*ie_ptr)[9] & 0x03; + qos->gbr_ul = (*ie_ptr)[10]; + qos->gbr_dl = (*ie_ptr)[11]; + qos->signalling_ind = ((*ie_ptr)[12] >> 4) & 0x01; + qos->source_stats_descriptor = (*ie_ptr)[12] & 0x0F; + if(qos->dl_ext_present) + { + qos->mbr_dl_ext = (*ie_ptr)[13]; + qos->gbr_dl_ext = (*ie_ptr)[14]; + } + if(qos->ul_ext_present) + { + qos->mbr_ul_ext = (*ie_ptr)[15]; + qos->gbr_ul_ext = (*ie_ptr)[16]; + } + if(qos->dl_ext_present && + qos->ul_ext_present) + { + *ie_ptr += 17; + }else if(qos->dl_ext_present){ + *ie_ptr += 15; + }else{ + *ie_ptr += 13; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Radio Priority + + Description: Specifies the priority level the UE shall use at the + lower layers for transmission of data related to a + PDP context or for mobile originated SMS + transmission. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.13 + 24.008 v10.2.0 Section 10.5.7.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_radio_priority_ie(uint8 radio_prio, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + (*ie_ptr)[0] |= radio_prio << bit_offset; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_radio_priority_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *radio_prio) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + radio_prio != NULL) + { + *radio_prio |= ((*ie_ptr)[0] >> bit_offset) & 0x07; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Request Type + + Description: Indicates whether the UE requests to establish a new + connectivity to a PDN or keep the connection(s) to + which it has connected via non-3GPP access. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.14 + 24.008 v10.2.0 Section 10.5.6.17 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_request_type_ie(uint8 req_type, + uint8 bit_offset, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + **ie_ptr |= req_type << bit_offset; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_request_type_ie(uint8 **ie_ptr, + uint8 bit_offset, + uint8 *req_type) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + req_type != NULL) + { + *req_type = (**ie_ptr >> bit_offset) & 0x07; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Traffic Flow Aggregate Description + + Description: Specifies the aggregate of one or more packet filters + and their related parameters and operations. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.15 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_traffic_flow_aggregate_description_ie(LIBLTE_MME_TRAFFIC_FLOW_AGGREGATE_DESCRIPTION_STRUCT *tfad, + uint8 **ie_ptr) +{ + return(liblte_mme_pack_traffic_flow_template_ie((LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT *)tfad, ie_ptr)); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_traffic_flow_aggregate_description_ie(uint8 **ie_ptr, + LIBLTE_MME_TRAFFIC_FLOW_AGGREGATE_DESCRIPTION_STRUCT *tfad) +{ + return(liblte_mme_unpack_traffic_flow_template_ie(ie_ptr, (LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT *)tfad)); +} + +/********************************************************************* + IE Name: Traffic Flow Template + + Description: Specifies the TFT parameters and operations for a + PDP context. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.16 + 24.008 v10.2.0 Section 10.5.6.12 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_traffic_flow_template_ie(LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT *tft, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 idx; + uint32 i; + uint32 j; + + if(tft != NULL && + ie_ptr != NULL) + { + idx = 1; + (*ie_ptr)[idx] = (tft->tft_op_code & 0x07) << 5; + if(0 != tft->parameter_list_size) + { + (*ie_ptr)[idx] |= 0x10; + } + (*ie_ptr)[idx] |= tft->packet_filter_list_size & 0x0F; + idx++; + + for(i=0; ipacket_filter_list_size; i++) + { + (*ie_ptr)[idx] = (tft->packet_filter_list[i].dir & 0x0F) << 4; + (*ie_ptr)[idx] |= tft->packet_filter_list[i].id & 0x0F; + idx++; + if(LIBLTE_MME_TFT_OPERATION_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING_TFT != tft->tft_op_code) + { + (*ie_ptr)[idx] = tft->packet_filter_list[i].eval_precedence; + idx++; + (*ie_ptr)[idx] = tft->packet_filter_list[i].filter_size; + idx++; + for(j=0; jpacket_filter_list[i].filter_size; j++) + { + (*ie_ptr)[idx] = tft->packet_filter_list[i].filter[j]; + idx++; + } + } + } + + for(i=0; iparameter_list_size; i++) + { + (*ie_ptr)[idx] = tft->parameter_list[i].id; + idx++; + (*ie_ptr)[idx] = tft->parameter_list[i].parameter_size; + idx++; + for(j=0; jparameter_list[i].parameter_size; j++) + { + (*ie_ptr)[idx] = tft->parameter_list[i].parameter[j]; + idx++; + } + } + (*ie_ptr)[0] = idx - 1; + *ie_ptr += idx; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_traffic_flow_template_ie(uint8 **ie_ptr, + LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT *tft) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 idx; + uint32 i; + uint32 j; + bool param_list_present; + + if(ie_ptr != NULL && + tft != NULL) + { + idx = 1; + tft->tft_op_code = (LIBLTE_MME_TFT_OPERATION_CODE_ENUM)(((*ie_ptr)[idx] >> 5) & 0x07); + param_list_present = ((*ie_ptr)[idx] >> 4) & 0x01; + tft->packet_filter_list_size = (*ie_ptr)[idx] & 0x0F; + idx++; + + for(i=0; ipacket_filter_list_size; i++) + { + tft->packet_filter_list[i].dir = (LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_ENUM)(((*ie_ptr)[idx] >> 4) & 0x0F); + tft->packet_filter_list[i].id = (*ie_ptr)[idx] & 0x0F; + idx++; + if(LIBLTE_MME_TFT_OPERATION_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING_TFT != tft->tft_op_code) + { + tft->packet_filter_list[i].eval_precedence = (*ie_ptr)[idx]; + idx++; + tft->packet_filter_list[i].filter_size = (*ie_ptr)[idx]; + idx++; + for(j=0; jpacket_filter_list[i].filter_size; j++) + { + tft->packet_filter_list[i].filter[j] = (*ie_ptr)[idx]; + idx++; + } + } + } + + if(param_list_present) + { + tft->parameter_list_size = 0; + while(idx < (*ie_ptr)[0]) + { + tft->parameter_list[tft->parameter_list_size].id = (*ie_ptr)[idx]; + idx++; + tft->parameter_list[tft->parameter_list_size].parameter_size = (*ie_ptr)[idx]; + idx++; + for(i=0; iparameter_list[tft->parameter_list_size].parameter_size; i++) + { + tft->parameter_list[tft->parameter_list_size].parameter[i] = (*ie_ptr)[idx]; + idx++; + } + tft->parameter_list_size++; + } + } + + *ie_ptr += (*ie_ptr)[0] + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Transaction Identifier + + Description: Represents the corresponding PDP context in A/Gb + mode or Iu mode which is mapped from the EPS bearer + context. + + Document Reference: 24.301 v10.2.0 Section 9.9.4.17 + 24.008 v10.2.0 Section 10.5.6.7 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_transaction_identifier_ie(LIBLTE_MME_TRANSACTION_IDENTIFIER_STRUCT *trans_id, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(trans_id != NULL && + ie_ptr != NULL) + { + if(LIBLTE_MME_TI_VALUE_IS_GIVEN_BY_TIE == trans_id->tio) + { + (*ie_ptr)[0] = 2; + }else{ + (*ie_ptr)[0] = 1; + } + (*ie_ptr)[1] = ((trans_id->ti_flag & 0x01) << 7) | ((trans_id->tio & 0x07) << 4); + if(LIBLTE_MME_TI_VALUE_IS_GIVEN_BY_TIE == trans_id->tio) + { + (*ie_ptr)[2] = 0x80 | (trans_id->tie & 0x7F); + *ie_ptr += 3; + }else{ + *ie_ptr += 2; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_transaction_identifier_ie(uint8 **ie_ptr, + LIBLTE_MME_TRANSACTION_IDENTIFIER_STRUCT *trans_id) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + trans_id != NULL) + { + trans_id->ti_flag = (*ie_ptr)[1] >> 7; + trans_id->tio = ((*ie_ptr)[1] >> 4) & 0x07; + if(LIBLTE_MME_TI_VALUE_IS_GIVEN_BY_TIE == trans_id->tio) + { + trans_id->tie = (*ie_ptr)[2] & 0x7F; + } + *ie_ptr += (*ie_ptr)[0] + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/******************************************************************************* + MESSAGE FUNCTIONS +*******************************************************************************/ + +/********************************************************************* + Message Name: Message Header (Plain NAS Message) + + Description: Message header for plain NAS messages. + + Document Reference: 24.301 v10.2.0 Section 9.1 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_parse_msg_header(LIBLTE_BYTE_MSG_STRUCT *msg, + uint8 *pd, + uint8 *msg_type) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 sec_hdr_type; + + if(msg != NULL && + pd != NULL && + msg_type != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + + // Protocol Discriminator + *pd = msg->msg[0] & 0x0F; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST == sec_hdr_type) + { + *msg_type = LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST; + }else{ + if(LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT == *pd) + { + // Message Type + *msg_type = msg->msg[2]; + }else{ + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + // Message Type + *msg_type = msg->msg[1]; + }else{ + // Protocol Discriminator + *pd = msg->msg[6] & 0x0F; + + if(LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT == *pd) + { + *msg_type = msg->msg[8]; + }else{ + *msg_type = msg->msg[7]; + } + } + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_pack_security_protected_nas_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *sec_msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = sec_msg->msg; + uint32 i; + + if(msg != NULL && + key_256 != NULL && + sec_msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // NAS Message + for(i=0; iN_bytes; i++) + { + *msg_ptr = msg->msg[i]; + msg_ptr++; + } + + // Fill in the number of bytes used + sec_msg->N_bytes = msg_ptr - sec_msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &sec_msg->msg[5], + sec_msg->N_bytes-5, + &sec_msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Attach Accept + + Description: Sent by the network to the UE to indicate that the + corresponding attach request has been accepted. + + Document Reference: 24.301 v10.2.0 Section 8.2.1 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_attach_accept_msg(LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT *attach_accept, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(attach_accept != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ATTACH_ACCEPT; + msg_ptr++; + + // EPS Attach Result & Spare Half Octet + *msg_ptr = 0; + liblte_mme_pack_eps_attach_result_ie(attach_accept->eps_attach_result, 0, &msg_ptr); + msg_ptr++; + + // T3412 Value + liblte_mme_pack_gprs_timer_ie(&attach_accept->t3412, &msg_ptr); + + // TAI List + liblte_mme_pack_tracking_area_identity_list_ie(&attach_accept->tai_list, &msg_ptr); + + // ESM Message Container + liblte_mme_pack_esm_message_container_ie(&attach_accept->esm_msg, &msg_ptr); + + // GUTI + if(attach_accept->guti_present) + { + *msg_ptr = LIBLTE_MME_GUTI_IEI; + msg_ptr++; + liblte_mme_pack_eps_mobile_id_ie(&attach_accept->guti, &msg_ptr); + } + + // Location Area Identification + if(attach_accept->lai_present) + { + *msg_ptr = LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI; + msg_ptr++; + liblte_mme_pack_location_area_id_ie(&attach_accept->lai, &msg_ptr); + } + + // MS Identity + if(attach_accept->ms_id_present) + { + *msg_ptr = LIBLTE_MME_MS_IDENTITY_IEI; + msg_ptr++; + liblte_mme_pack_mobile_id_ie(&attach_accept->ms_id, &msg_ptr); + } + + // EMM Cause + if(attach_accept->emm_cause_present) + { + *msg_ptr = LIBLTE_MME_EMM_CAUSE_IEI; + msg_ptr++; + liblte_mme_pack_emm_cause_ie(attach_accept->emm_cause, &msg_ptr); + } + + // T3402 Value + if(attach_accept->t3402_present) + { + *msg_ptr = LIBLTE_MME_T3402_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_ie(&attach_accept->t3402, &msg_ptr); + } + + // T3423 Value + if(attach_accept->t3423_present) + { + *msg_ptr = LIBLTE_MME_T3423_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_ie(&attach_accept->t3423, &msg_ptr); + } + + // Equivalent PLMNs + if(attach_accept->equivalent_plmns_present) + { + *msg_ptr = LIBLTE_MME_EQUIVALENT_PLMNS_IEI; + msg_ptr++; + liblte_mme_pack_plmn_list_ie(&attach_accept->equivalent_plmns, &msg_ptr); + } + + // Emergency Number List + if(attach_accept->emerg_num_list_present) + { + *msg_ptr = LIBLTE_MME_EMERGENCY_NUMBER_LIST_IEI; + msg_ptr++; + liblte_mme_pack_emergency_number_list_ie(&attach_accept->emerg_num_list, &msg_ptr); + } + + // EPS Network Feature Support + if(attach_accept->eps_network_feature_support_present) + { + *msg_ptr = LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_IEI; + msg_ptr++; + liblte_mme_pack_eps_network_feature_support_ie(&attach_accept->eps_network_feature_support, &msg_ptr); + } + + // Additional Update Result + if(attach_accept->additional_update_result_present) + { + *msg_ptr = LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_IEI << 4; + liblte_mme_pack_additional_update_result_ie(attach_accept->additional_update_result, 0, &msg_ptr); + msg_ptr++; + } + + // T3412 Extended Value + if(attach_accept->t3412_ext_present) + { + *msg_ptr = LIBLTE_MME_T3412_EXTENDED_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_3_ie(&attach_accept->t3412_ext, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT *attach_accept) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + attach_accept != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // EPS Attach Result & Spare Half Octet + liblte_mme_unpack_eps_attach_result_ie(&msg_ptr, 0, &attach_accept->eps_attach_result); + msg_ptr++; + + // T3412 Value + liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &attach_accept->t3412); + + // TAI List + liblte_mme_unpack_tracking_area_identity_list_ie(&msg_ptr, &attach_accept->tai_list); + + // ESM Message Container + liblte_mme_unpack_esm_message_container_ie(&msg_ptr, &attach_accept->esm_msg); + + // GUTI + if(LIBLTE_MME_GUTI_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &attach_accept->guti); + attach_accept->guti_present = true; + }else{ + attach_accept->guti_present = false; + } + + // Location Area Identification + if(LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_location_area_id_ie(&msg_ptr, &attach_accept->lai); + attach_accept->lai_present = true; + }else{ + attach_accept->lai_present = false; + } + + // MS Identity + if(LIBLTE_MME_MS_IDENTITY_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_mobile_id_ie(&msg_ptr, &attach_accept->ms_id); + attach_accept->ms_id_present = true; + }else{ + attach_accept->ms_id_present = false; + } + + // EMM Cause + if(LIBLTE_MME_EMM_CAUSE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_emm_cause_ie(&msg_ptr, &attach_accept->emm_cause); + attach_accept->emm_cause_present = true; + }else{ + attach_accept->emm_cause_present = false; + } + + // T3402 Value + if(LIBLTE_MME_T3402_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &attach_accept->t3402); + attach_accept->t3402_present = true; + }else{ + attach_accept->t3402_present = false; + } + + // T3423 Value + if(LIBLTE_MME_T3423_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &attach_accept->t3423); + attach_accept->t3423_present = true; + }else{ + attach_accept->t3423_present = false; + } + + // Equivalent PLMNs + if(LIBLTE_MME_EQUIVALENT_PLMNS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_plmn_list_ie(&msg_ptr, &attach_accept->equivalent_plmns); + attach_accept->equivalent_plmns_present = true; + }else{ + attach_accept->equivalent_plmns_present = false; + } + + // Emergency Number List + if(LIBLTE_MME_EMERGENCY_NUMBER_LIST_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_emergency_number_list_ie(&msg_ptr, &attach_accept->emerg_num_list); + attach_accept->emerg_num_list_present = true; + }else{ + attach_accept->emerg_num_list_present = false; + } + + // EPS Network Feature Support + if(LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_eps_network_feature_support_ie(&msg_ptr, &attach_accept->eps_network_feature_support); + attach_accept->eps_network_feature_support_present = true; + }else{ + attach_accept->eps_network_feature_support_present = false; + } + + // Additional Update Result + if((LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_additional_update_result_ie(&msg_ptr, 0, &attach_accept->additional_update_result); + msg_ptr++; + attach_accept->additional_update_result_present = true; + }else{ + attach_accept->additional_update_result_present = false; + } + + // T3412 Extended Value + if(LIBLTE_MME_T3412_EXTENDED_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_3_ie(&msg_ptr, &attach_accept->t3412_ext); + attach_accept->t3412_ext_present = true; + }else{ + attach_accept->t3412_ext_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Attach Complete + + Description: Sent by the UE to the network in response to an + ATTACH ACCEPT message. + + Document Reference: 24.301 v10.2.0 Section 8.2.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_attach_complete_msg(LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT *attach_comp, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(attach_comp != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE; + msg_ptr++; + + // ESM Message Container + liblte_mme_pack_esm_message_container_ie(&attach_comp->esm_msg, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_complete_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT *attach_comp) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + attach_comp != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // ESM Message Container + liblte_mme_unpack_esm_message_container_ie(&msg_ptr, &attach_comp->esm_msg); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Attach Reject + + Description: Sent by the network to the UE to indicate that the + corresponding attach request has been rejected. + + Document Reference: 24.301 v10.2.0 Section 8.2.3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_attach_reject_msg(LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT *attach_rej, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(attach_rej != NULL && + msg != NULL) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ATTACH_REJECT; + msg_ptr++; + + // EMM Cause + liblte_mme_pack_emm_cause_ie(attach_rej->emm_cause, &msg_ptr); + + // ESM Message Container + if(attach_rej->esm_msg_present) + { + *msg_ptr = LIBLTE_MME_ESM_MSG_CONTAINER_IEI; + msg_ptr++; + liblte_mme_pack_esm_message_container_ie(&attach_rej->esm_msg, &msg_ptr); + } + + // T3446 Value + if(attach_rej->t3446_value_present) + { + *msg_ptr = LIBLTE_MME_T3446_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_2_ie(attach_rej->t3446_value, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT *attach_rej) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + attach_rej != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // EMM Cause + liblte_mme_unpack_emm_cause_ie(&msg_ptr, &attach_rej->emm_cause); + + // ESM Message Container + if(LIBLTE_MME_ESM_MSG_CONTAINER_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_esm_message_container_ie(&msg_ptr, &attach_rej->esm_msg); + attach_rej->esm_msg_present = true; + }else{ + attach_rej->esm_msg_present = false; + } + + // T3446 Value + if(LIBLTE_MME_T3446_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_2_ie(&msg_ptr, &attach_rej->t3446_value); + attach_rej->t3446_value_present = true; + }else{ + attach_rej->t3446_value_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Attach Request + + Description: Sent by the UE to the network to perform an attach + procedure. + + Document Reference: 24.301 v10.2.0 Section 8.2.4 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(attach_req != NULL && + msg != NULL) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST; + msg_ptr++; + + // EPS Attach Type & NAS Key Set Identifier + *msg_ptr = 0; + liblte_mme_pack_eps_attach_type_ie(attach_req->eps_attach_type, 0, &msg_ptr); + liblte_mme_pack_nas_key_set_id_ie(&attach_req->nas_ksi, 4, &msg_ptr); + msg_ptr++; + + // EPS Mobile ID + liblte_mme_pack_eps_mobile_id_ie(&attach_req->eps_mobile_id, &msg_ptr); + + // UE Network Capability + liblte_mme_pack_ue_network_capability_ie(&attach_req->ue_network_cap, &msg_ptr); + + // ESM Message Container + liblte_mme_pack_esm_message_container_ie(&attach_req->esm_msg, &msg_ptr); + + // Old P-TMSI Signature + if(attach_req->old_p_tmsi_signature_present) + { + *msg_ptr = LIBLTE_MME_P_TMSI_SIGNATURE_IEI; + msg_ptr++; + liblte_mme_pack_p_tmsi_signature_ie(attach_req->old_p_tmsi_signature, &msg_ptr); + } + + // Additional GUTI + if(attach_req->additional_guti_present) + { + *msg_ptr = LIBLTE_MME_ADDITIONAL_GUTI_IEI; + msg_ptr++; + liblte_mme_pack_eps_mobile_id_ie(&attach_req->additional_guti, &msg_ptr); + } + + // Last Visited Registered TAI + if(attach_req->last_visited_registered_tai_present) + { + *msg_ptr = LIBLTE_MME_LAST_VISITED_REGISTERED_TAI_IEI; + msg_ptr++; + liblte_mme_pack_tracking_area_id_ie(&attach_req->last_visited_registered_tai, &msg_ptr); + } + + // DRX Parameter + if(attach_req->drx_param_present) + { + *msg_ptr = LIBLTE_MME_DRX_PARAMETER_IEI; + msg_ptr++; + liblte_mme_pack_drx_parameter_ie(&attach_req->drx_param, &msg_ptr); + } + + // MS Network Capability + if(attach_req->ms_network_cap_present) + { + *msg_ptr = LIBLTE_MME_MS_NETWORK_CAPABILITY_IEI; + msg_ptr++; + liblte_mme_pack_ms_network_capability_ie(&attach_req->ms_network_cap, &msg_ptr); + } + + // Old Location Area ID + if(attach_req->old_lai_present) + { + *msg_ptr = LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI; + msg_ptr++; + liblte_mme_pack_location_area_id_ie(&attach_req->old_lai, &msg_ptr); + } + + // TMSI Status + if(attach_req->tmsi_status_present) + { + *msg_ptr = LIBLTE_MME_TMSI_STATUS_IEI << 4; + liblte_mme_pack_tmsi_status_ie(attach_req->tmsi_status, 0, &msg_ptr); + msg_ptr++; + } + + // Mobile Station Classmark 2 + if(attach_req->ms_cm2_present) + { + *msg_ptr = LIBLTE_MME_MS_CLASSMARK_2_IEI; + msg_ptr++; + liblte_mme_pack_mobile_station_classmark_2_ie(&attach_req->ms_cm2, &msg_ptr); + } + + // Mobile Station Classmark 3 + if(attach_req->ms_cm3_present) + { + *msg_ptr = LIBLTE_MME_MS_CLASSMARK_3_IEI; + msg_ptr++; + liblte_mme_pack_mobile_station_classmark_3_ie(&attach_req->ms_cm3, &msg_ptr); + } + + // Supported Codecs + if(attach_req->supported_codecs_present) + { + *msg_ptr = LIBLTE_MME_SUPPORTED_CODEC_LIST_IEI; + msg_ptr++; + liblte_mme_pack_supported_codec_list_ie(&attach_req->supported_codecs, &msg_ptr); + } + + // Additional Update Type + if(attach_req->additional_update_type_present) + { + *msg_ptr = LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_IEI << 4; + liblte_mme_pack_additional_update_type_ie(attach_req->additional_update_type, 0, &msg_ptr); + msg_ptr++; + } + + // Voice Domain Preference and UE's Usage Setting + if(attach_req->voice_domain_pref_and_ue_usage_setting_present) + { + *msg_ptr = LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_IEI; + msg_ptr++; + liblte_mme_pack_voice_domain_pref_and_ue_usage_setting_ie(&attach_req->voice_domain_pref_and_ue_usage_setting, &msg_ptr); + } + + // Device Properties + if(attach_req->device_properties_present) + { + *msg_ptr = LIBLTE_MME_ATTACH_REQUEST_DEVICE_PROPERTIES_IEI << 4; + liblte_mme_pack_device_properties_ie(attach_req->device_properties, 0, &msg_ptr); + msg_ptr++; + } + + // Old GUTI Type + if(attach_req->old_guti_type_present) + { + *msg_ptr = LIBLTE_MME_GUTI_TYPE_IEI << 4; + liblte_mme_pack_guti_type_ie(attach_req->old_guti_type, 0, &msg_ptr); + msg_ptr++; + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + attach_req != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // EPS Attach Type & NAS Key Set Identifier + liblte_mme_unpack_eps_attach_type_ie(&msg_ptr, 0, &attach_req->eps_attach_type); + liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 4, &attach_req->nas_ksi); + msg_ptr++; + + // EPS Mobile ID + liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &attach_req->eps_mobile_id); + + // UE Network Capability + liblte_mme_unpack_ue_network_capability_ie(&msg_ptr, &attach_req->ue_network_cap); + + // ESM Message Container + liblte_mme_unpack_esm_message_container_ie(&msg_ptr, &attach_req->esm_msg); + + // Old P-TMSI Signature + if(LIBLTE_MME_P_TMSI_SIGNATURE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_p_tmsi_signature_ie(&msg_ptr, &attach_req->old_p_tmsi_signature); + attach_req->old_p_tmsi_signature_present = true; + }else{ + attach_req->old_p_tmsi_signature_present = false; + } + + // Additional GUTI + if(LIBLTE_MME_ADDITIONAL_GUTI_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &attach_req->additional_guti); + attach_req->additional_guti_present = true; + }else{ + attach_req->additional_guti_present = false; + } + + // Last Visited Registered TAI + if(LIBLTE_MME_LAST_VISITED_REGISTERED_TAI_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_tracking_area_id_ie(&msg_ptr, &attach_req->last_visited_registered_tai); + attach_req->last_visited_registered_tai_present = true; + }else{ + attach_req->last_visited_registered_tai_present = false; + } + + // DRX Parameter + if(LIBLTE_MME_DRX_PARAMETER_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_drx_parameter_ie(&msg_ptr, &attach_req->drx_param); + attach_req->drx_param_present = true; + }else{ + attach_req->drx_param_present = false; + } + + // MS Network Capability + if(LIBLTE_MME_MS_NETWORK_CAPABILITY_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_ms_network_capability_ie(&msg_ptr, &attach_req->ms_network_cap); + attach_req->ms_network_cap_present = true; + }else{ + attach_req->ms_network_cap_present = false; + } + + // Old Location Area ID + if(LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_location_area_id_ie(&msg_ptr, &attach_req->old_lai); + attach_req->old_lai_present = true; + }else{ + attach_req->old_lai_present = false; + } + + // TMSI Status + if((LIBLTE_MME_TMSI_STATUS_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_tmsi_status_ie(&msg_ptr, 0, &attach_req->tmsi_status); + msg_ptr++; + attach_req->tmsi_status_present = true; + }else{ + attach_req->tmsi_status_present = false; + } + + // Mobile Station Classmark 2 + if(LIBLTE_MME_MS_CLASSMARK_2_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_mobile_station_classmark_2_ie(&msg_ptr, &attach_req->ms_cm2); + attach_req->ms_cm2_present = true; + }else{ + attach_req->ms_cm2_present = false; + } + + // Mobile Station Classmark 3 + if(LIBLTE_MME_MS_CLASSMARK_3_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_mobile_station_classmark_3_ie(&msg_ptr, &attach_req->ms_cm3); + attach_req->ms_cm3_present = true; + }else{ + attach_req->ms_cm3_present = false; + } + + // Supported Codecs + if(LIBLTE_MME_SUPPORTED_CODEC_LIST_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_supported_codec_list_ie(&msg_ptr, &attach_req->supported_codecs); + attach_req->supported_codecs_present = true; + }else{ + attach_req->supported_codecs_present = false; + } + + // Additional Update Type + if((LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_additional_update_type_ie(&msg_ptr, 0, &attach_req->additional_update_type); + msg_ptr++; + attach_req->additional_update_type_present = true; + }else{ + attach_req->additional_update_type_present = false; + } + + // Voice Domain Preference and UE's Usage Setting + if(LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_voice_domain_pref_and_ue_usage_setting_ie(&msg_ptr, &attach_req->voice_domain_pref_and_ue_usage_setting); + attach_req->voice_domain_pref_and_ue_usage_setting_present = true; + }else{ + attach_req->voice_domain_pref_and_ue_usage_setting_present = false; + } + + // Device Properties + if((LIBLTE_MME_ATTACH_REQUEST_DEVICE_PROPERTIES_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_device_properties_ie(&msg_ptr, 0, &attach_req->device_properties); + msg_ptr++; + attach_req->device_properties_present = true; + }else{ + attach_req->device_properties_present = false; + } + + // Old GUTI Type + if((LIBLTE_MME_GUTI_TYPE_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_guti_type_ie(&msg_ptr, 0, &attach_req->old_guti_type); + msg_ptr++; + attach_req->old_guti_type_present = true; + }else{ + attach_req->old_guti_type_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Authentication Failure + + Description: Sent by the UE to the network to indicate that + authentication of the network has failed. + + Document Reference: 24.301 v10.2.0 Section 8.2.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_failure_msg(LIBLTE_MME_AUTHENTICATION_FAILURE_MSG_STRUCT *auth_fail, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(auth_fail != NULL && + msg != NULL) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE; + msg_ptr++; + + // EMM Cause + liblte_mme_pack_emm_cause_ie(auth_fail->emm_cause, &msg_ptr); + + // Authentication Failure Parameter + if(auth_fail->auth_fail_param_present) + { + *msg_ptr = LIBLTE_MME_AUTHENTICATION_FAILURE_PARAMETER_IEI; + msg_ptr++; + liblte_mme_pack_authentication_failure_parameter_ie(auth_fail->auth_fail_param, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_failure_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_AUTHENTICATION_FAILURE_MSG_STRUCT *auth_fail) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + auth_fail != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // EMM Cause + liblte_mme_unpack_emm_cause_ie(&msg_ptr, &auth_fail->emm_cause); + + // Authentication Failure Parameter + if(LIBLTE_MME_AUTHENTICATION_FAILURE_PARAMETER_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_authentication_failure_parameter_ie(&msg_ptr, auth_fail->auth_fail_param); + auth_fail->auth_fail_param_present = true; + }else{ + auth_fail->auth_fail_param_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Authentication Reject + + Description: Sent by the network to the UE to indicate that the + authentication procedure has failed and that the UE + shall abort all activities. + + Document Reference: 24.301 v10.2.0 Section 8.2.6 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_reject_msg(LIBLTE_MME_AUTHENTICATION_REJECT_MSG_STRUCT *auth_reject, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(auth_reject != NULL && + msg != NULL) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_AUTHENTICATION_REJECT; + msg_ptr++; + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_AUTHENTICATION_REJECT_MSG_STRUCT *auth_reject) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + auth_reject != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Authentication Request + + Description: Sent by the network to the UE to initiate + authentication of the UE identity. + + Document Reference: 24.301 v10.2.0 Section 8.2.7 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_request_msg(LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT *auth_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(auth_req != NULL && + msg != NULL) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_AUTHENTICATION_REQUEST; + msg_ptr++; + + // NAS Key Set Identifier & Spare Half Octet + *msg_ptr = 0; + liblte_mme_pack_nas_key_set_id_ie(&auth_req->nas_ksi, 0, &msg_ptr); + msg_ptr++; + + // Authentication Parameter RAND + liblte_mme_pack_authentication_parameter_rand_ie(auth_req->rand, &msg_ptr); + + // Authentication Parameter AUTN + liblte_mme_pack_authentication_parameter_autn_ie(auth_req->autn, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT *auth_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + auth_req != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // NAS Key Set Identifier & Spare Half Octet + liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 0, &auth_req->nas_ksi); + msg_ptr++; + + // Authentication Parameter RAND + liblte_mme_unpack_authentication_parameter_rand_ie(&msg_ptr, auth_req->rand); + + // Authentication Parameter AUTN + liblte_mme_unpack_authentication_parameter_autn_ie(&msg_ptr, auth_req->autn); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Authentication Response + + Description: Sent by the UE to the network to deliver a calculated + authentication response to the network. + + Document Reference: 24.301 v10.2.0 Section 8.2.8 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_response_msg(LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(auth_resp != NULL && + msg != NULL) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE; + msg_ptr++; + + // Authentication Response Parameter (RES) + liblte_mme_pack_authentication_response_parameter_ie(auth_resp->res, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + auth_resp != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // Authentication Response Parameter (RES) + liblte_mme_unpack_authentication_response_parameter_ie(&msg_ptr, auth_resp->res); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: CS Service Notification + + Description: Sent by the network when a paging request with CS + call indicator was received via SGs for a UE, and a + NAS signalling connection is already established for + the UE. + + Document Reference: 24.301 v10.2.0 Section 8.2.9 +*********************************************************************/ +// FIXME + +/********************************************************************* + Message Name: Detach Accept + + Description: Sent by the network to indicate that the detach + procedure has been completed. + + Document Reference: 24.301 v10.2.0 Section 8.2.10 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_detach_accept_msg(LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT *detach_accept, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(detach_accept != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_DETACH_ACCEPT; + msg_ptr++; + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_detach_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT *detach_accept) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + detach_accept != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Detach Request + + Description: Sent by the UE to request the release of an EMM + context. + + Document Reference: 24.301 v10.2.0 Section 8.2.11 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_detach_request_msg(LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT *detach_req, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(detach_req != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_DETACH_REQUEST; + msg_ptr++; + + // Detach Type & NAS Key Set Identifier + *msg_ptr = 0; + liblte_mme_pack_detach_type_ie(&detach_req->detach_type, 0, &msg_ptr); + liblte_mme_pack_nas_key_set_id_ie(&detach_req->nas_ksi, 4, &msg_ptr); + msg_ptr++; + + // EPS Mobile ID + liblte_mme_pack_eps_mobile_id_ie(&detach_req->eps_mobile_id, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_detach_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT *detach_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + detach_req != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // Detach Type & NAS Key Set Identifier + liblte_mme_unpack_detach_type_ie(&msg_ptr, 0, &detach_req->detach_type); + liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 4, &detach_req->nas_ksi); + msg_ptr++; + + // EPS Mobile ID + liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &detach_req->eps_mobile_id); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Downlink NAS Transport + + Description: Sent by the network to the UE in order to carry an + SMS message in encapsulated format. + + Document Reference: 24.301 v10.2.0 Section 8.2.12 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_downlink_nas_transport_msg(LIBLTE_MME_DOWNLINK_NAS_TRANSPORT_MSG_STRUCT *dl_nas_transport, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(dl_nas_transport != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_DOWNLINK_NAS_TRANSPORT; + msg_ptr++; + + // NAS Message Container + liblte_mme_pack_nas_message_container_ie(&dl_nas_transport->nas_msg, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_downlink_nas_transport_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DOWNLINK_NAS_TRANSPORT_MSG_STRUCT *dl_nas_transport) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + dl_nas_transport != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // NAS Message Container + liblte_mme_unpack_nas_message_container_ie(&msg_ptr, &dl_nas_transport->nas_msg); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: EMM Information + + Description: Sent by the network at any time during EMM context is + established to send certain information to the UE. + + Document Reference: 24.301 v10.2.0 Section 8.2.13 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_emm_information_msg(LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT *emm_info, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(emm_info != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_EMM_INFORMATION; + msg_ptr++; + + // Full Name For Network + if(emm_info->full_net_name_present) + { + *msg_ptr = LIBLTE_MME_FULL_NAME_FOR_NETWORK_IEI; + msg_ptr++; + liblte_mme_pack_network_name_ie(&emm_info->full_net_name, &msg_ptr); + } + + // Short Name For Network + if(emm_info->short_net_name_present) + { + *msg_ptr = LIBLTE_MME_SHORT_NAME_FOR_NETWORK_IEI; + msg_ptr++; + liblte_mme_pack_network_name_ie(&emm_info->short_net_name, &msg_ptr); + } + + // Local Time Zone + if(emm_info->local_time_zone_present) + { + *msg_ptr = LIBLTE_MME_LOCAL_TIME_ZONE_IEI; + msg_ptr++; + liblte_mme_pack_time_zone_ie(emm_info->local_time_zone, &msg_ptr); + } + + // Universal Time And Local Time Zone + if(emm_info->utc_and_local_time_zone_present) + { + *msg_ptr = LIBLTE_MME_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_IEI; + msg_ptr++; + liblte_mme_pack_time_zone_and_time_ie(&emm_info->utc_and_local_time_zone, &msg_ptr); + } + + // Network Daylight Saving Time + if(emm_info->net_dst_present) + { + *msg_ptr = LIBLTE_MME_NETWORK_DAYLIGHT_SAVING_TIME_IEI; + msg_ptr++; + liblte_mme_pack_daylight_saving_time_ie(emm_info->net_dst, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_emm_information_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT *emm_info) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + emm_info != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // Full Name For Network + if(LIBLTE_MME_FULL_NAME_FOR_NETWORK_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_network_name_ie(&msg_ptr, &emm_info->full_net_name); + emm_info->full_net_name_present = true; + }else{ + emm_info->full_net_name_present = false; + } + + // Short Name For Network + if(LIBLTE_MME_SHORT_NAME_FOR_NETWORK_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_network_name_ie(&msg_ptr, &emm_info->short_net_name); + emm_info->short_net_name_present = true; + }else{ + emm_info->short_net_name_present = false; + } + + // Local Time Zone + if(LIBLTE_MME_LOCAL_TIME_ZONE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_time_zone_ie(&msg_ptr, &emm_info->local_time_zone); + emm_info->local_time_zone_present = true; + }else{ + emm_info->local_time_zone_present = false; + } + + // Universal Time And Local Time Zone + if(LIBLTE_MME_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_time_zone_and_time_ie(&msg_ptr, &emm_info->utc_and_local_time_zone); + emm_info->utc_and_local_time_zone_present = true; + }else{ + emm_info->utc_and_local_time_zone_present = false; + } + + // Network Daylight Saving Time + if(LIBLTE_MME_NETWORK_DAYLIGHT_SAVING_TIME_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_daylight_saving_time_ie(&msg_ptr, &emm_info->net_dst); + emm_info->net_dst_present = true; + }else{ + emm_info->net_dst_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: EMM Status + + Description: Sent by the UE or by the network at any time to + report certain error conditions. + + Document Reference: 24.301 v10.2.0 Section 8.2.14 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_emm_status_msg(LIBLTE_MME_EMM_STATUS_MSG_STRUCT *emm_status, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(emm_status != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_EMM_STATUS; + msg_ptr++; + + // EMM Cause + liblte_mme_pack_emm_cause_ie(emm_status->emm_cause, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_emm_status_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_EMM_STATUS_MSG_STRUCT *emm_status) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + emm_status != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // EMM Cause + liblte_mme_unpack_emm_cause_ie(&msg_ptr, &emm_status->emm_cause); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Extended Service Request + + Description: Sent by the UE to the network to initiate a CS + fallback or 1xCS fallback call or respond to a mobile + terminated CS fallback or 1xCS fallback request from + the network or to request the establishment of a NAS + signalling connection and of the radio and S1 bearers + for packet services, if the UE needs to provide + additional information that cannot be provided via a + SERVICE REQUEST message. + + Document Reference: 24.301 v10.2.0 Section 8.2.15 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_extended_service_request_msg(LIBLTE_MME_EXTENDED_SERVICE_REQUEST_MSG_STRUCT *ext_service_req, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(ext_service_req != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_EXTENDED_SERVICE_REQUEST; + msg_ptr++; + + // Service Type & NAS Key Set Identifier + *msg_ptr = 0; + liblte_mme_pack_service_type_ie(ext_service_req->service_type, 0, &msg_ptr); + liblte_mme_pack_nas_key_set_id_ie(&ext_service_req->nas_ksi, 4, &msg_ptr); + msg_ptr++; + + // M-TMSI + liblte_mme_pack_mobile_id_ie(&ext_service_req->m_tmsi, &msg_ptr); + + // CSFB Response + if(ext_service_req->csfb_resp_present) + { + *msg_ptr = LIBLTE_MME_CSFB_RESPONSE_IEI << 4; + liblte_mme_pack_csfb_response_ie(ext_service_req->csfb_resp, 0, &msg_ptr); + msg_ptr++; + } + + // EPS Bearer Context Status + if(ext_service_req->eps_bearer_context_status_present) + { + *msg_ptr = LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_IEI; + msg_ptr++; + liblte_mme_pack_eps_bearer_context_status_ie(&ext_service_req->eps_bearer_context_status, &msg_ptr); + } + + // Device Properties + if(ext_service_req->device_props_present) + { + *msg_ptr = LIBLTE_MME_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_IEI << 4; + liblte_mme_pack_device_properties_ie(ext_service_req->device_props, 0, &msg_ptr); + msg_ptr++; + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_extended_service_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_EXTENDED_SERVICE_REQUEST_MSG_STRUCT *ext_service_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + ext_service_req != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // Service Type & NAS Key Set Identifier + liblte_mme_unpack_service_type_ie(&msg_ptr, 0, &ext_service_req->service_type); + liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 4, &ext_service_req->nas_ksi); + msg_ptr++; + + // M-TMSI + liblte_mme_unpack_mobile_id_ie(&msg_ptr, &ext_service_req->m_tmsi); + + // CSFB Response + if((LIBLTE_MME_CSFB_RESPONSE_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_csfb_response_ie(&msg_ptr, 0, &ext_service_req->csfb_resp); + msg_ptr++; + ext_service_req->csfb_resp_present = true; + }else{ + ext_service_req->csfb_resp_present = false; + } + + // EPS Bearer Context Status + if(LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_eps_bearer_context_status_ie(&msg_ptr, &ext_service_req->eps_bearer_context_status); + ext_service_req->eps_bearer_context_status_present = true; + }else{ + ext_service_req->eps_bearer_context_status_present = false; + } + + // Device Properties + if((LIBLTE_MME_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_device_properties_ie(&msg_ptr, 0, &ext_service_req->device_props); + msg_ptr++; + ext_service_req->device_props_present = true; + }else{ + ext_service_req->device_props_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: GUTI Reallocation Command + + Description: Sent by the network to the UE to reallocate a GUTI + and optionally provide a new TAI list. + + Document Reference: 24.301 v10.2.0 Section 8.2.16 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_guti_reallocation_command_msg(LIBLTE_MME_GUTI_REALLOCATION_COMMAND_MSG_STRUCT *guti_realloc_cmd, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(guti_realloc_cmd != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_GUTI_REALLOCATION_COMMAND; + msg_ptr++; + + // GUTI + liblte_mme_pack_eps_mobile_id_ie(&guti_realloc_cmd->guti, &msg_ptr); + + // TAI List + if(guti_realloc_cmd->tai_list_present) + { + *msg_ptr = LIBLTE_MME_TAI_LIST_IEI; + msg_ptr++; + liblte_mme_pack_tracking_area_identity_list_ie(&guti_realloc_cmd->tai_list, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_reallocation_command_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_GUTI_REALLOCATION_COMMAND_MSG_STRUCT *guti_realloc_cmd) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + guti_realloc_cmd != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // GUTI + liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &guti_realloc_cmd->guti); + + // TAI List + if(LIBLTE_MME_TAI_LIST_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_tracking_area_identity_list_ie(&msg_ptr, &guti_realloc_cmd->tai_list); + guti_realloc_cmd->tai_list_present = true; + }else{ + guti_realloc_cmd->tai_list_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: GUTI Reallocation Complete + + Description: Sent by the UE to the network to indicate that + reallocation of a GUTI has taken place. + + Document Reference: 24.301 v10.2.0 Section 8.2.17 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_guti_reallocation_complete_msg(LIBLTE_MME_GUTI_REALLOCATION_COMPLETE_MSG_STRUCT *guti_realloc_complete, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(guti_realloc_complete != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_GUTI_REALLOCATION_COMPLETE; + msg_ptr++; + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_reallocation_complete_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_GUTI_REALLOCATION_COMPLETE_MSG_STRUCT *guti_realloc_complete) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + guti_realloc_complete != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Identity Request + + Description: Sent by the network to the UE to request the UE to + provide the specified identity. + + Document Reference: 24.301 v10.2.0 Section 8.2.18 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_identity_request_msg(LIBLTE_MME_ID_REQUEST_MSG_STRUCT *id_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(id_req != NULL && + msg != NULL) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_IDENTITY_REQUEST; + msg_ptr++; + + // ID Type & Spare Half Octet + *msg_ptr = 0; + liblte_mme_pack_identity_type_2_ie(id_req->id_type, 0, &msg_ptr); + msg_ptr++; + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ID_REQUEST_MSG_STRUCT *id_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + id_req != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // ID Type & Spare Half Offset + liblte_mme_unpack_identity_type_2_ie(&msg_ptr, 0, &id_req->id_type); + msg_ptr++; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Identity Response + + Description: Sent by the UE to the network in response to an + IDENTITY REQUEST message and provides the requested + identity. + + Document Reference: 24.301 v10.2.0 Section 8.2.19 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_identity_response_msg(LIBLTE_MME_ID_RESPONSE_MSG_STRUCT *id_resp, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(id_resp != NULL && + msg != NULL) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE; + msg_ptr++; + + // Mobile Identity + liblte_mme_pack_mobile_id_ie(&id_resp->mobile_id, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ID_RESPONSE_MSG_STRUCT *id_resp) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + id_resp != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // Mobile Identity + liblte_mme_unpack_mobile_id_ie(&msg_ptr, &id_resp->mobile_id); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Security Mode Command + + Description: Sent by the network to the UE to establish NAS + signalling security. + + Document Reference: 24.301 v10.2.0 Section 8.2.20 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_security_mode_command_msg(LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT *sec_mode_cmd, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(sec_mode_cmd != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMMAND; + msg_ptr++; + + // Selected NAS Security Algorithms + liblte_mme_pack_nas_security_algorithms_ie(&sec_mode_cmd->selected_nas_sec_algs, &msg_ptr); + + // NAS Key Set Identifier & Spare Half Octet + *msg_ptr = 0; + liblte_mme_pack_nas_key_set_id_ie(&sec_mode_cmd->nas_ksi, 0, &msg_ptr); + msg_ptr++; + + // Replayed UE Security Capabilities + liblte_mme_pack_ue_security_capabilities_ie(&sec_mode_cmd->ue_security_cap, &msg_ptr); + + // IMEISV Request + if(sec_mode_cmd->imeisv_req_present) + { + *msg_ptr = LIBLTE_MME_IMEISV_REQUEST_IEI << 4; + liblte_mme_pack_imeisv_request_ie(sec_mode_cmd->imeisv_req, 0, &msg_ptr); + msg_ptr++; + } + + // Replayed NONCE_ue + if(sec_mode_cmd->nonce_ue_present) + { + *msg_ptr = LIBLTE_MME_REPLAYED_NONCE_UE_IEI; + msg_ptr++; + liblte_mme_pack_nonce_ie(sec_mode_cmd->nonce_ue, &msg_ptr); + } + + // NONCE_mme + if(sec_mode_cmd->nonce_mme_present) + { + *msg_ptr = LIBLTE_MME_NONCE_MME_IEI; + msg_ptr++; + liblte_mme_pack_nonce_ie(sec_mode_cmd->nonce_mme, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_security_mode_command_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT *sec_mode_cmd) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + sec_mode_cmd != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // Selected NAS Security Algorithms + liblte_mme_unpack_nas_security_algorithms_ie(&msg_ptr, &sec_mode_cmd->selected_nas_sec_algs); + + // NAS Key Set Identifier & Spare Half Octet + liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 0, &sec_mode_cmd->nas_ksi); + msg_ptr++; + + // Replayed UE Security Capabilities + liblte_mme_unpack_ue_security_capabilities_ie(&msg_ptr, &sec_mode_cmd->ue_security_cap); + + // IMEISV Request + if((LIBLTE_MME_IMEISV_REQUEST_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_imeisv_request_ie(&msg_ptr, 0, &sec_mode_cmd->imeisv_req); + msg_ptr++; + sec_mode_cmd->imeisv_req_present = true; + }else{ + sec_mode_cmd->imeisv_req_present = false; + } + + // Replayed NONCE_ue + if(LIBLTE_MME_REPLAYED_NONCE_UE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_nonce_ie(&msg_ptr, &sec_mode_cmd->nonce_ue); + sec_mode_cmd->nonce_ue_present = true; + }else{ + sec_mode_cmd->nonce_ue_present = false; + } + + // NONCE_mme + if(LIBLTE_MME_NONCE_MME_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_nonce_ie(&msg_ptr, &sec_mode_cmd->nonce_mme); + sec_mode_cmd->nonce_mme_present = true; + }else{ + sec_mode_cmd->nonce_mme_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Security Mode Complete + + Description: Sent by the UE to the network in response to a + SECURITY MODE COMMAND message. + + Document Reference: 24.301 v10.2.0 Section 8.2.21 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_security_mode_complete_msg(LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT *sec_mode_comp, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(sec_mode_comp != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE; + msg_ptr++; + + // IMEISV + if(sec_mode_comp->imeisv_present) + { + *msg_ptr = LIBLTE_MME_IMEISV_IEI; + msg_ptr++; + liblte_mme_pack_mobile_id_ie(&sec_mode_comp->imeisv, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_security_mode_complete_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT *sec_mode_comp) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + sec_mode_comp != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // IMEISV + if(LIBLTE_MME_IMEISV_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_mobile_id_ie(&msg_ptr, &sec_mode_comp->imeisv); + sec_mode_comp->imeisv_present = true; + }else{ + sec_mode_comp->imeisv_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Security Mode Reject + + Description: Sent by the UE to the network to indicate that the + corresponding security mode command has been + rejected. + + Document Reference: 24.301 v10.2.0 Section 8.2.22 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_security_mode_reject_msg(LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT *sec_mode_rej, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(sec_mode_rej != NULL && + msg != NULL) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_SECURITY_MODE_REJECT; + msg_ptr++; + + // EMM Cause + liblte_mme_pack_emm_cause_ie(sec_mode_rej->emm_cause, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_security_mode_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT *sec_mode_rej) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + sec_mode_rej != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // EMM Cause + liblte_mme_unpack_emm_cause_ie(&msg_ptr, &sec_mode_rej->emm_cause); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Service Reject + + Description: Sent by the network to the UE in order to reject the + service request procedure. + + Document Reference: 24.301 v10.2.0 Section 8.2.24 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_service_reject_msg(LIBLTE_MME_SERVICE_REJECT_MSG_STRUCT *service_rej, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(service_rej != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_SERVICE_REJECT; + msg_ptr++; + + // EMM Cause + liblte_mme_pack_emm_cause_ie(service_rej->emm_cause, &msg_ptr); + + // T3442 Value + if(service_rej->t3442_present) + { + *msg_ptr = LIBLTE_MME_T3442_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_ie(&service_rej->t3442, &msg_ptr); + } + + // T3446 Value + if(service_rej->t3446_present) + { + *msg_ptr = LIBLTE_MME_T3446_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_2_ie(service_rej->t3446, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type && + NULL != key_256) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_service_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_SERVICE_REJECT_MSG_STRUCT *service_rej) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + service_rej != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // EMM Cause + liblte_mme_unpack_emm_cause_ie(&msg_ptr, &service_rej->emm_cause); + + // T3442 Value + if(LIBLTE_MME_T3442_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &service_rej->t3442); + service_rej->t3442_present = true; + }else{ + service_rej->t3442_present = false; + } + + // T3446 Value + if(LIBLTE_MME_T3446_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_2_ie(&msg_ptr, &service_rej->t3446); + service_rej->t3446_present = true; + }else{ + service_rej->t3446_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Service Request + + Description: Sent by the UE to the network to request the + establishment of a NAS signalling connection and of + the radio and S1 bearers. + + Document Reference: 24.301 v10.2.0 Section 8.2.25 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_service_request_msg(LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT *service_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(service_req != NULL && + msg != NULL) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // KSI and Sequence Number + liblte_mme_pack_ksi_and_sequence_number_ie(&service_req->ksi_and_seq_num, &msg_ptr); + + // Short MAC + liblte_mme_pack_short_mac_ie(service_req->short_mac, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_service_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT *service_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + service_req != NULL) + { + // Protocol Discriminator and Security Header Type + msg_ptr++; + + // KSI and Sequence Number + liblte_mme_unpack_ksi_and_sequence_number_ie(&msg_ptr, &service_req->ksi_and_seq_num); + + // Short MAC + liblte_mme_unpack_short_mac_ie(&msg_ptr, &service_req->short_mac); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Tracking Area Update Accept + + Description: Sent by the network to the UE to provide the UE with + EPS mobility management related data in response to + a tracking area update request message. + + Document Reference: 24.301 v10.2.0 Section 8.2.26 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_update_accept_msg(LIBLTE_MME_TRACKING_AREA_UPDATE_ACCEPT_MSG_STRUCT *ta_update_accept, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(ta_update_accept != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_ACCEPT; + msg_ptr++; + + // EPS Update Result & Spare Half Octet + *msg_ptr = 0; + liblte_mme_pack_eps_update_result_ie(ta_update_accept->eps_update_result, 0, &msg_ptr); + msg_ptr++; + + // T3412 Value + if(ta_update_accept->t3412_present) + { + *msg_ptr = LIBLTE_MME_T3412_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_ie(&ta_update_accept->t3412, &msg_ptr); + } + + // GUTI + if(ta_update_accept->guti_present) + { + *msg_ptr = LIBLTE_MME_GUTI_IEI; + msg_ptr++; + liblte_mme_pack_eps_mobile_id_ie(&ta_update_accept->guti, &msg_ptr); + } + + // TAI List + if(ta_update_accept->tai_list_present) + { + *msg_ptr = LIBLTE_MME_TAI_LIST_IEI; + msg_ptr++; + liblte_mme_pack_tracking_area_identity_list_ie(&ta_update_accept->tai_list, &msg_ptr); + } + + // EPS Bearer Context Status + if(ta_update_accept->eps_bearer_context_status_present) + { + *msg_ptr = LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_IEI; + msg_ptr++; + liblte_mme_pack_eps_bearer_context_status_ie(&ta_update_accept->eps_bearer_context_status, &msg_ptr); + } + + // Location Area Identification + if(ta_update_accept->lai_present) + { + *msg_ptr = LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI; + msg_ptr++; + liblte_mme_pack_location_area_id_ie(&ta_update_accept->lai, &msg_ptr); + } + + // MS Identity + if(ta_update_accept->ms_id_present) + { + *msg_ptr = LIBLTE_MME_MS_IDENTITY_IEI; + msg_ptr++; + liblte_mme_pack_mobile_id_ie(&ta_update_accept->ms_id, &msg_ptr); + } + + // EMM Cause + if(ta_update_accept->emm_cause_present) + { + *msg_ptr = LIBLTE_MME_EMM_CAUSE_IEI; + msg_ptr++; + liblte_mme_pack_emm_cause_ie(ta_update_accept->emm_cause, &msg_ptr); + } + + // T3402 Value + if(ta_update_accept->t3402_present) + { + *msg_ptr = LIBLTE_MME_T3402_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_ie(&ta_update_accept->t3402, &msg_ptr); + } + + // T3423 Value + if(ta_update_accept->t3423_present) + { + *msg_ptr = LIBLTE_MME_T3423_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_ie(&ta_update_accept->t3423, &msg_ptr); + } + + // Equivalent PLMNs + if(ta_update_accept->equivalent_plmns_present) + { + *msg_ptr = LIBLTE_MME_EQUIVALENT_PLMNS_IEI; + msg_ptr++; + liblte_mme_pack_plmn_list_ie(&ta_update_accept->equivalent_plmns, &msg_ptr); + } + + // Emergency Number List + if(ta_update_accept->emerg_num_list_present) + { + *msg_ptr = LIBLTE_MME_EMERGENCY_NUMBER_LIST_IEI; + msg_ptr++; + liblte_mme_pack_emergency_number_list_ie(&ta_update_accept->emerg_num_list, &msg_ptr); + } + + // EPS Network Feature Support + if(ta_update_accept->eps_network_feature_support_present) + { + *msg_ptr = LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_IEI; + msg_ptr++; + liblte_mme_pack_eps_network_feature_support_ie(&ta_update_accept->eps_network_feature_support, &msg_ptr); + } + + // Additional Update Result + if(ta_update_accept->additional_update_result_present) + { + *msg_ptr = LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_IEI << 4; + liblte_mme_pack_additional_update_result_ie(ta_update_accept->additional_update_result, 0, &msg_ptr); + msg_ptr++; + } + + // T3412 Extended Value + if(ta_update_accept->t3412_ext_present) + { + *msg_ptr = LIBLTE_MME_T3412_EXTENDED_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_3_ie(&ta_update_accept->t3412_ext, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_update_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_TRACKING_AREA_UPDATE_ACCEPT_MSG_STRUCT *ta_update_accept) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + ta_update_accept != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // EPS Update Result & Spare Half Octet + liblte_mme_unpack_eps_update_result_ie(&msg_ptr, 0, &ta_update_accept->eps_update_result); + msg_ptr++; + + // T3412 Value + if(LIBLTE_MME_T3412_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &ta_update_accept->t3412); + ta_update_accept->t3412_present = true; + }else{ + ta_update_accept->t3412_present = false; + } + + // GUTI + if(LIBLTE_MME_GUTI_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &ta_update_accept->guti); + ta_update_accept->guti_present = true; + }else{ + ta_update_accept->guti_present = false; + } + + // TAI List + if(LIBLTE_MME_TAI_LIST_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_tracking_area_identity_list_ie(&msg_ptr, &ta_update_accept->tai_list); + ta_update_accept->tai_list_present = true; + }else{ + ta_update_accept->tai_list_present = false; + } + + // EPS Bearer Context Status + if(LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_eps_bearer_context_status_ie(&msg_ptr, &ta_update_accept->eps_bearer_context_status); + ta_update_accept->eps_bearer_context_status_present = true; + }else{ + ta_update_accept->eps_bearer_context_status_present = false; + } + + // Location Area Identification + if(LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_location_area_id_ie(&msg_ptr, &ta_update_accept->lai); + ta_update_accept->lai_present = true; + }else{ + ta_update_accept->lai_present = false; + } + + // MS Identity + if(LIBLTE_MME_MS_IDENTITY_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_mobile_id_ie(&msg_ptr, &ta_update_accept->ms_id); + ta_update_accept->ms_id_present = true; + }else{ + ta_update_accept->ms_id_present = false; + } + + // EMM Cause + if(LIBLTE_MME_EMM_CAUSE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_emm_cause_ie(&msg_ptr, &ta_update_accept->emm_cause); + ta_update_accept->emm_cause_present = true; + }else{ + ta_update_accept->emm_cause_present = false; + } + + // T3402 Value + if(LIBLTE_MME_T3402_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &ta_update_accept->t3402); + ta_update_accept->t3402_present = true; + }else{ + ta_update_accept->t3402_present = false; + } + + // T3423 Value + if(LIBLTE_MME_T3423_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &ta_update_accept->t3423); + ta_update_accept->t3423_present = true; + }else{ + ta_update_accept->t3423_present = false; + } + + // Equivalent PLMNs + if(LIBLTE_MME_EQUIVALENT_PLMNS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_plmn_list_ie(&msg_ptr, &ta_update_accept->equivalent_plmns); + ta_update_accept->equivalent_plmns_present = true; + }else{ + ta_update_accept->equivalent_plmns_present = false; + } + + // Emergency Number List + if(LIBLTE_MME_EMERGENCY_NUMBER_LIST_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_emergency_number_list_ie(&msg_ptr, &ta_update_accept->emerg_num_list); + ta_update_accept->emerg_num_list_present = true; + }else{ + ta_update_accept->emerg_num_list_present = false; + } + + // EPS Network Feature Support + if(LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_eps_network_feature_support_ie(&msg_ptr, &ta_update_accept->eps_network_feature_support); + ta_update_accept->eps_network_feature_support_present = true; + }else{ + ta_update_accept->eps_network_feature_support_present = false; + } + + // Additional Update Result + if((LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_additional_update_result_ie(&msg_ptr, 0, &ta_update_accept->additional_update_result); + msg_ptr++; + ta_update_accept->additional_update_result_present = true; + }else{ + ta_update_accept->additional_update_result_present = false; + } + + // T3412 Extended Value + if(LIBLTE_MME_T3412_EXTENDED_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_3_ie(&msg_ptr, &ta_update_accept->t3412_ext); + ta_update_accept->t3412_ext_present = true; + }else{ + ta_update_accept->t3412_ext_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Tracking Area Update Complete + + Description: Sent by the UE to the network in response to a + tracking area update accept message if a GUTI has + been changed or a new TMSI has been assigned. + + Document Reference: 24.301 v10.2.0 Section 8.2.27 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_update_complete_msg(LIBLTE_MME_TRACKING_AREA_UPDATE_COMPLETE_MSG_STRUCT *ta_update_complete, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(ta_update_complete != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_COMPLETE; + msg_ptr++; + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_update_complete_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_TRACKING_AREA_UPDATE_COMPLETE_MSG_STRUCT *ta_update_complete) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + ta_update_complete != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Tracking Area Update Reject + + Description: Sent by the network to the UE in order to reject the + tracking area updating procedure. + + Document Reference: 24.301 v10.2.0 Section 8.2.28 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_update_reject_msg(LIBLTE_MME_TRACKING_AREA_UPDATE_REJECT_MSG_STRUCT *ta_update_rej, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(ta_update_rej != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REJECT; + msg_ptr++; + + // EMM Cause + liblte_mme_pack_emm_cause_ie(ta_update_rej->emm_cause, &msg_ptr); + + // T3446 Value + if(ta_update_rej->t3446_present) + { + *msg_ptr = LIBLTE_MME_T3446_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_2_ie(ta_update_rej->t3446, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_update_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_TRACKING_AREA_UPDATE_REJECT_MSG_STRUCT *ta_update_rej) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + ta_update_rej != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // EMM Cause + liblte_mme_unpack_emm_cause_ie(&msg_ptr, &ta_update_rej->emm_cause); + + // T3446 Value + if(LIBLTE_MME_T3446_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_2_ie(&msg_ptr, &ta_update_rej->t3446); + ta_update_rej->t3446_present = true; + }else{ + ta_update_rej->t3446_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Tracking Area Update Request + + Description: Sent by the UE to the network to initiate a tracking + area updating procedure. + + Document Reference: 24.301 v10.2.0 Section 8.2.29 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_update_request_msg(LIBLTE_MME_TRACKING_AREA_UPDATE_REQUEST_MSG_STRUCT *ta_update_req, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(ta_update_req != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST; + msg_ptr++; + + // EPS Update Type & NAS Key Set Identifier + *msg_ptr = 0; + liblte_mme_pack_eps_update_type_ie(&ta_update_req->eps_update_type, 0, &msg_ptr); + liblte_mme_pack_nas_key_set_id_ie(&ta_update_req->nas_ksi, 4, &msg_ptr); + msg_ptr++; + + // Old GUTI + liblte_mme_pack_eps_mobile_id_ie(&ta_update_req->old_guti, &msg_ptr); + + // Non-current Native NAS Key Set Identifier + if(ta_update_req->non_current_native_nas_ksi_present) + { + *msg_ptr = LIBLTE_MME_NAS_KEY_SET_IDENTIFIER_IEI << 4; + liblte_mme_pack_nas_key_set_id_ie(&ta_update_req->non_current_native_nas_ksi, 0, &msg_ptr); + msg_ptr++; + } + + // GPRS Ciphering Key Sequence Number + if(ta_update_req->gprs_ciphering_ksn_present) + { + *msg_ptr = LIBLTE_MME_CIPHERING_KEY_SEQUENCE_NUMBER_IEI << 4; + liblte_mme_pack_ciphering_key_sequence_number_ie(ta_update_req->gprs_ciphering_ksn, 0, &msg_ptr); + msg_ptr++; + } + + // Old P-TMSI Signature + if(ta_update_req->old_p_tmsi_signature_present) + { + *msg_ptr = LIBLTE_MME_P_TMSI_SIGNATURE_IEI; + msg_ptr++; + liblte_mme_pack_p_tmsi_signature_ie(ta_update_req->old_p_tmsi_signature, &msg_ptr); + } + + // Additional GUTI + if(ta_update_req->additional_guti_present) + { + *msg_ptr = LIBLTE_MME_ADDITIONAL_GUTI_IEI; + msg_ptr++; + liblte_mme_pack_eps_mobile_id_ie(&ta_update_req->additional_guti, &msg_ptr); + } + + // NONCE UE + if(ta_update_req->nonce_ue_present) + { + *msg_ptr = LIBLTE_MME_NONCE_UE_IEI; + msg_ptr++; + liblte_mme_pack_nonce_ie(ta_update_req->nonce_ue, &msg_ptr); + } + + // UE Network Capability + if(ta_update_req->ue_network_cap_present) + { + *msg_ptr = LIBLTE_MME_UE_NETWORK_CAPABILITY_IEI; + msg_ptr++; + liblte_mme_pack_ue_network_capability_ie(&ta_update_req->ue_network_cap, &msg_ptr); + } + + // Last Visited Registered TAI + if(ta_update_req->last_visited_registered_tai_present) + { + *msg_ptr = LIBLTE_MME_LAST_VISITED_REGISTERED_TAI_IEI; + msg_ptr++; + liblte_mme_pack_tracking_area_id_ie(&ta_update_req->last_visited_registered_tai, &msg_ptr); + } + + // DRX Parameter + if(ta_update_req->drx_param_present) + { + *msg_ptr = LIBLTE_MME_DRX_PARAMETER_IEI; + msg_ptr++; + liblte_mme_pack_drx_parameter_ie(&ta_update_req->drx_param, &msg_ptr); + } + + // UE Radio Capability Information Update Needed + if(ta_update_req->ue_radio_cap_update_needed_present) + { + *msg_ptr = LIBLTE_MME_UE_RADIO_CAPABILITY_INFORMATION_UPDATE_NEEDED_IEI << 4; + liblte_mme_pack_ue_radio_capability_update_needed_ie(ta_update_req->ue_radio_cap_update_needed, 0, &msg_ptr); + msg_ptr++; + } + + // EPS Bearer Context Status + if(ta_update_req->eps_bearer_context_status_present) + { + *msg_ptr = LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_IEI; + msg_ptr++; + liblte_mme_pack_eps_bearer_context_status_ie(&ta_update_req->eps_bearer_context_status, &msg_ptr); + } + + // MS Network Capability + if(ta_update_req->ms_network_cap_present) + { + *msg_ptr = LIBLTE_MME_MS_NETWORK_CAPABILITY_IEI; + msg_ptr++; + liblte_mme_pack_ms_network_capability_ie(&ta_update_req->ms_network_cap, &msg_ptr); + } + + // Old Location Area Identification + if(ta_update_req->old_lai_present) + { + *msg_ptr = LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI; + msg_ptr++; + liblte_mme_pack_location_area_id_ie(&ta_update_req->old_lai, &msg_ptr); + } + + // TMSI Status + if(ta_update_req->tmsi_status_present) + { + *msg_ptr = LIBLTE_MME_TMSI_STATUS_IEI << 4; + liblte_mme_pack_tmsi_status_ie(ta_update_req->tmsi_status, 0, &msg_ptr); + msg_ptr++; + } + + // Mobile Station Classmark 2 + if(ta_update_req->ms_cm2_present) + { + *msg_ptr = LIBLTE_MME_MS_CLASSMARK_2_IEI; + msg_ptr++; + liblte_mme_pack_mobile_station_classmark_2_ie(&ta_update_req->ms_cm2, &msg_ptr); + } + + // Mobile Station Classmark 3 + if(ta_update_req->ms_cm3_present) + { + *msg_ptr = LIBLTE_MME_MS_CLASSMARK_3_IEI; + msg_ptr++; + liblte_mme_pack_mobile_station_classmark_3_ie(&ta_update_req->ms_cm3, &msg_ptr); + } + + // Supported Codecs + if(ta_update_req->supported_codecs_present) + { + *msg_ptr = LIBLTE_MME_SUPPORTED_CODEC_LIST_IEI; + msg_ptr++; + liblte_mme_pack_supported_codec_list_ie(&ta_update_req->supported_codecs, &msg_ptr); + } + + // Additional Update Type + if(ta_update_req->additional_update_type_present) + { + *msg_ptr = LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_IEI << 4; + liblte_mme_pack_additional_update_type_ie(ta_update_req->additional_update_type, 0, &msg_ptr); + msg_ptr++; + } + + // Voice Domain Preference and UE's Usage Setting + if(ta_update_req->voice_domain_pref_and_ue_usage_setting_present) + { + *msg_ptr = LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_IEI; + msg_ptr++; + liblte_mme_pack_voice_domain_pref_and_ue_usage_setting_ie(&ta_update_req->voice_domain_pref_and_ue_usage_setting, &msg_ptr); + } + + // Old GUTI Type + if(ta_update_req->old_guti_type_present) + { + *msg_ptr = LIBLTE_MME_GUTI_TYPE_IEI << 4; + liblte_mme_pack_guti_type_ie(ta_update_req->old_guti_type, 0, &msg_ptr); + msg_ptr++; + } + + // Device Properties + if(ta_update_req->device_properties_present) + { + *msg_ptr = LIBLTE_MME_TRACKING_AREA_UPDATE_REQUEST_DEVICE_PROPERTIES_IEI << 4; + liblte_mme_pack_device_properties_ie(ta_update_req->device_properties, 0, &msg_ptr); + msg_ptr++; + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_update_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_TRACKING_AREA_UPDATE_REQUEST_MSG_STRUCT *ta_update_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + ta_update_req != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // EPS Update Type & NAS Key Set Identifier + liblte_mme_unpack_eps_update_type_ie(&msg_ptr, 0, &ta_update_req->eps_update_type); + liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 4, &ta_update_req->nas_ksi); + msg_ptr++; + + // Old GUTI + liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &ta_update_req->old_guti); + + // Non-current Native NAS Key Set Identifier + if((LIBLTE_MME_NAS_KEY_SET_IDENTIFIER_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 0, &ta_update_req->non_current_native_nas_ksi); + msg_ptr++; + ta_update_req->non_current_native_nas_ksi_present = true; + }else{ + ta_update_req->non_current_native_nas_ksi_present = false; + } + + // GPRS Ciphering Key Sequence Number + if((LIBLTE_MME_CIPHERING_KEY_SEQUENCE_NUMBER_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_ciphering_key_sequence_number_ie(&msg_ptr, 0, &ta_update_req->gprs_ciphering_ksn); + msg_ptr++; + ta_update_req->gprs_ciphering_ksn_present = true; + }else{ + ta_update_req->gprs_ciphering_ksn_present = false; + } + + // Old P-TMSI Signature + if(LIBLTE_MME_P_TMSI_SIGNATURE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_p_tmsi_signature_ie(&msg_ptr, &ta_update_req->old_p_tmsi_signature); + ta_update_req->old_p_tmsi_signature_present = true; + }else{ + ta_update_req->old_p_tmsi_signature_present = false; + } + + // Additional GUTI + if(LIBLTE_MME_ADDITIONAL_GUTI_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &ta_update_req->additional_guti); + ta_update_req->additional_guti_present = true; + }else{ + ta_update_req->additional_guti_present = false; + } + + // NONCE UE + if(LIBLTE_MME_NONCE_UE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_nonce_ie(&msg_ptr, &ta_update_req->nonce_ue); + ta_update_req->nonce_ue_present = true; + }else{ + ta_update_req->nonce_ue_present = false; + } + + // UE Network Capability + if(LIBLTE_MME_UE_NETWORK_CAPABILITY_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_ue_network_capability_ie(&msg_ptr, &ta_update_req->ue_network_cap); + ta_update_req->ue_network_cap_present = true; + }else{ + ta_update_req->ue_network_cap_present = false; + } + + // Last Visited Registered TAI + if(LIBLTE_MME_LAST_VISITED_REGISTERED_TAI_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_tracking_area_id_ie(&msg_ptr, &ta_update_req->last_visited_registered_tai); + ta_update_req->last_visited_registered_tai_present = true; + }else{ + ta_update_req->last_visited_registered_tai_present = false; + } + + // DRX Parameter + if(LIBLTE_MME_DRX_PARAMETER_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_drx_parameter_ie(&msg_ptr, &ta_update_req->drx_param); + ta_update_req->drx_param_present = true; + }else{ + ta_update_req->drx_param_present = false; + } + + // UE Radio Capability Information Update Needed + if((LIBLTE_MME_UE_RADIO_CAPABILITY_INFORMATION_UPDATE_NEEDED_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_ue_radio_capability_update_needed_ie(&msg_ptr, 0, &ta_update_req->ue_radio_cap_update_needed); + msg_ptr++; + ta_update_req->ue_radio_cap_update_needed_present = true; + }else{ + ta_update_req->ue_radio_cap_update_needed_present = false; + } + + // EPS Bearer Context Status + if(LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_eps_bearer_context_status_ie(&msg_ptr, &ta_update_req->eps_bearer_context_status); + ta_update_req->eps_bearer_context_status_present = true; + }else{ + ta_update_req->eps_bearer_context_status_present = false; + } + + // MS Network Capability + if(LIBLTE_MME_MS_NETWORK_CAPABILITY_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_ms_network_capability_ie(&msg_ptr, &ta_update_req->ms_network_cap); + ta_update_req->ms_network_cap_present = true; + }else{ + ta_update_req->ms_network_cap_present = false; + } + + // Old Location Area Identification + if(LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_location_area_id_ie(&msg_ptr, &ta_update_req->old_lai); + ta_update_req->old_lai_present = true; + }else{ + ta_update_req->old_lai_present = false; + } + + // TMSI Status + if((LIBLTE_MME_TMSI_STATUS_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_tmsi_status_ie(&msg_ptr, 0, &ta_update_req->tmsi_status); + msg_ptr++; + ta_update_req->tmsi_status_present = true; + }else{ + ta_update_req->tmsi_status_present = false; + } + + // Mobile Station Classmark 2 + if(LIBLTE_MME_MS_CLASSMARK_2_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_mobile_station_classmark_2_ie(&msg_ptr, &ta_update_req->ms_cm2); + ta_update_req->ms_cm2_present = true; + }else{ + ta_update_req->ms_cm2_present = false; + } + + // Mobile Station Classmark 3 + if(LIBLTE_MME_MS_CLASSMARK_3_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_mobile_station_classmark_3_ie(&msg_ptr, &ta_update_req->ms_cm3); + ta_update_req->ms_cm3_present = true; + }else{ + ta_update_req->ms_cm3_present = false; + } + + // Supported Codecs + if(LIBLTE_MME_SUPPORTED_CODEC_LIST_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_supported_codec_list_ie(&msg_ptr, &ta_update_req->supported_codecs); + ta_update_req->supported_codecs_present = true; + }else{ + ta_update_req->supported_codecs_present = false; + } + + // Additional Update Type + if((LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_additional_update_type_ie(&msg_ptr, 0, &ta_update_req->additional_update_type); + msg_ptr++; + ta_update_req->additional_update_type_present = true; + }else{ + ta_update_req->additional_update_type_present = false; + } + + // Voice Domain Preference and UE's Usage Setting + if(LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_voice_domain_pref_and_ue_usage_setting_ie(&msg_ptr, &ta_update_req->voice_domain_pref_and_ue_usage_setting); + ta_update_req->voice_domain_pref_and_ue_usage_setting_present = true; + }else{ + ta_update_req->voice_domain_pref_and_ue_usage_setting_present = false; + } + + // Old GUTI Type + if((LIBLTE_MME_GUTI_TYPE_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_guti_type_ie(&msg_ptr, 0, &ta_update_req->old_guti_type); + msg_ptr++; + ta_update_req->old_guti_type_present = true; + }else{ + ta_update_req->old_guti_type_present = false; + } + + // Device Properties + if((LIBLTE_MME_TRACKING_AREA_UPDATE_REQUEST_DEVICE_PROPERTIES_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_device_properties_ie(&msg_ptr, 0, &ta_update_req->device_properties); + msg_ptr++; + ta_update_req->device_properties_present = true; + }else{ + ta_update_req->device_properties_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Uplink NAS Transport + + Description: Sent by the UE to the network in order to carry an + SMS message in encapsulated format. + + Document Reference: 24.301 v10.2.0 Section 8.2.30 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_uplink_nas_transport_msg(LIBLTE_MME_UPLINK_NAS_TRANSPORT_MSG_STRUCT *ul_nas_transport, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(ul_nas_transport != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_UPLINK_NAS_TRANSPORT; + msg_ptr++; + + // NAS Message Container + liblte_mme_pack_nas_message_container_ie(&ul_nas_transport->nas_msg, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_uplink_nas_transport_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_UPLINK_NAS_TRANSPORT_MSG_STRUCT *ul_nas_transport) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + ul_nas_transport != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // NAS Message Container + liblte_mme_unpack_nas_message_container_ie(&msg_ptr, &ul_nas_transport->nas_msg); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Downlink Generic NAS Transport + + Description: Sent by the network to the UE in order to carry an + application message in encapsulated format. + + Document Reference: 24.301 v10.2.0 Section 8.2.31 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_downlink_generic_nas_transport_msg(LIBLTE_MME_DOWNLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT *dl_generic_nas_transport, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(dl_generic_nas_transport != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_DOWNLINK_GENERIC_NAS_TRANSPORT; + msg_ptr++; + + // Generic Message Container Type + liblte_mme_pack_generic_message_container_type_ie(dl_generic_nas_transport->generic_msg_cont_type, &msg_ptr); + + // Generic Message Container + liblte_mme_pack_generic_message_container_ie(&dl_generic_nas_transport->generic_msg_cont, &msg_ptr); + + // Additional Information + liblte_mme_pack_additional_information_ie(&dl_generic_nas_transport->add_info, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_downlink_generic_nas_transport_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DOWNLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT *dl_generic_nas_transport) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + dl_generic_nas_transport != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // Generic Message Container Type + liblte_mme_unpack_generic_message_container_type_ie(&msg_ptr, &dl_generic_nas_transport->generic_msg_cont_type); + + // Generic Message Container + liblte_mme_unpack_generic_message_container_ie(&msg_ptr, &dl_generic_nas_transport->generic_msg_cont); + + // Additional Information + liblte_mme_unpack_additional_information_ie(&msg_ptr, &dl_generic_nas_transport->add_info); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Uplink Generic NAS Transport + + Description: Sent by the UE to the network in order to carry an + application protocol message in encapsulated format. + + Document Reference: 24.301 v10.2.0 Section 8.2.32 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_uplink_generic_nas_transport_msg(LIBLTE_MME_UPLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT *ul_generic_nas_transport, + uint8 sec_hdr_type, + uint8 *key_256, + uint32 count, + uint8 direction, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(ul_generic_nas_transport != NULL && + key_256 != NULL && + msg != NULL) + { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + + // Protocol Discriminator and Security Header Type + *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_UPLINK_GENERIC_NAS_TRANSPORT; + msg_ptr++; + + // Generic Message Container Type + liblte_mme_pack_generic_message_container_type_ie(ul_generic_nas_transport->generic_msg_cont_type, &msg_ptr); + + // Generic Message Container + liblte_mme_pack_generic_message_container_ie(&ul_generic_nas_transport->generic_msg_cont, &msg_ptr); + + // Additional Information + liblte_mme_pack_additional_information_ie(&ul_generic_nas_transport->add_info, &msg_ptr); + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Calculate MAC + liblte_security_128_eia2(&key_256[16], + count, + 0, + direction, + &msg->msg[5], + msg->N_bytes-5, + &msg->msg[1]); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_uplink_generic_nas_transport_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_UPLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT *ul_generic_nas_transport) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + ul_generic_nas_transport != NULL) + { + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + + // Skip Message Type + msg_ptr++; + + // Generic Message Container Type + liblte_mme_unpack_generic_message_container_type_ie(&msg_ptr, &ul_generic_nas_transport->generic_msg_cont_type); + + // Generic Message Container + liblte_mme_unpack_generic_message_container_ie(&msg_ptr, &ul_generic_nas_transport->generic_msg_cont); + + // Additional Information + liblte_mme_unpack_additional_information_ie(&msg_ptr, &ul_generic_nas_transport->add_info); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Activate Dedicated EPS Bearer Context Accept + + Description: Sent by the UE to the network to acknowledge + activation of a dedicated EPS bearer context + associated with the same PDN address(es) and APN as + an already active EPS bearer context. + + Document Reference: 24.301 v10.2.0 Section 8.3.1 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_dedicated_eps_bearer_context_accept_msg(LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *act_ded_eps_bearer_context_accept, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(act_ded_eps_bearer_context_accept != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (act_ded_eps_bearer_context_accept->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = act_ded_eps_bearer_context_accept->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT; + msg_ptr++; + + // Protocol Configuration Options + if(act_ded_eps_bearer_context_accept->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&act_ded_eps_bearer_context_accept->protocol_cnfg_opts, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_dedicated_eps_bearer_context_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *act_ded_eps_bearer_context_accept) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + act_ded_eps_bearer_context_accept != NULL) + { + // EPS Bearer ID + act_ded_eps_bearer_context_accept->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + act_ded_eps_bearer_context_accept->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_ded_eps_bearer_context_accept->protocol_cnfg_opts); + act_ded_eps_bearer_context_accept->protocol_cnfg_opts_present = true; + }else{ + act_ded_eps_bearer_context_accept->protocol_cnfg_opts_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Activate Dedicated EPS Bearer Context Reject + + Description: Sent by the UE to the network to reject activation + of a dedicated EPS bearer context. + + Document Reference: 24.301 v10.2.0 Section 8.3.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_dedicated_eps_bearer_context_reject_msg(LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *act_ded_eps_bearer_context_rej, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(act_ded_eps_bearer_context_rej != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (act_ded_eps_bearer_context_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = act_ded_eps_bearer_context_rej->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT; + msg_ptr++; + + // ESM Cause + liblte_mme_pack_esm_cause_ie(act_ded_eps_bearer_context_rej->esm_cause, &msg_ptr); + + // Protocol Configuration Options + if(act_ded_eps_bearer_context_rej->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&act_ded_eps_bearer_context_rej->protocol_cnfg_opts, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_dedicated_eps_bearer_context_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *act_ded_eps_bearer_context_rej) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + act_ded_eps_bearer_context_rej != NULL) + { + // EPS Bearer ID + act_ded_eps_bearer_context_rej->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + act_ded_eps_bearer_context_rej->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // ESM Cause + liblte_mme_unpack_esm_cause_ie(&msg_ptr, &act_ded_eps_bearer_context_rej->esm_cause); + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_ded_eps_bearer_context_rej->protocol_cnfg_opts); + act_ded_eps_bearer_context_rej->protocol_cnfg_opts_present = true; + }else{ + act_ded_eps_bearer_context_rej->protocol_cnfg_opts_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Activate Dedicated EPS Bearer Context Request + + Description: Sent by the network to the UE to request activation + of a dedicated EPS bearer context associated with + the same PDN address(es) and APN as an already + active default EPS bearer context. + + Document Reference: 24.301 v10.2.0 Section 8.3.3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_dedicated_eps_bearer_context_request_msg(LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *act_ded_eps_bearer_context_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(act_ded_eps_bearer_context_req != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (act_ded_eps_bearer_context_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = act_ded_eps_bearer_context_req->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST; + msg_ptr++; + + // Linked EPS Bearer Identity & Spare Half Octet + *msg_ptr = 0; + liblte_mme_pack_linked_eps_bearer_identity_ie(act_ded_eps_bearer_context_req->linked_eps_bearer_id, 0, &msg_ptr); + msg_ptr++; + + // EPS QoS + liblte_mme_pack_eps_quality_of_service_ie(&act_ded_eps_bearer_context_req->eps_qos, &msg_ptr); + + // TFT + liblte_mme_pack_traffic_flow_template_ie(&act_ded_eps_bearer_context_req->tft, &msg_ptr); + + // Transaction Identifier + if(act_ded_eps_bearer_context_req->transaction_id_present) + { + *msg_ptr = LIBLTE_MME_TRANSACTION_IDENTIFIER_IEI; + msg_ptr++; + liblte_mme_pack_transaction_identifier_ie(&act_ded_eps_bearer_context_req->transaction_id, &msg_ptr); + } + + // Negotiated QoS + if(act_ded_eps_bearer_context_req->negotiated_qos_present) + { + *msg_ptr = LIBLTE_MME_QUALITY_OF_SERVICE_IEI; + msg_ptr++; + liblte_mme_pack_quality_of_service_ie(&act_ded_eps_bearer_context_req->negotiated_qos, &msg_ptr); + } + + // Negotiated LLC SAPI + if(act_ded_eps_bearer_context_req->llc_sapi_present) + { + *msg_ptr = LIBLTE_MME_LLC_SAPI_IEI; + msg_ptr++; + liblte_mme_pack_llc_service_access_point_identifier_ie(act_ded_eps_bearer_context_req->llc_sapi, &msg_ptr); + } + + // Radio Priority + if(act_ded_eps_bearer_context_req->radio_prio_present) + { + *msg_ptr = LIBLTE_MME_RADIO_PRIORITY_IEI << 4; + liblte_mme_pack_radio_priority_ie(act_ded_eps_bearer_context_req->radio_prio, 0, &msg_ptr); + msg_ptr++; + } + + // Packet Flow Identifier + if(act_ded_eps_bearer_context_req->packet_flow_id_present) + { + *msg_ptr = LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI; + msg_ptr++; + liblte_mme_pack_packet_flow_identifier_ie(act_ded_eps_bearer_context_req->packet_flow_id, &msg_ptr); + } + + // Protocol Configuration Options + if(act_ded_eps_bearer_context_req->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&act_ded_eps_bearer_context_req->protocol_cnfg_opts, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_dedicated_eps_bearer_context_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *act_ded_eps_bearer_context_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + act_ded_eps_bearer_context_req != NULL) + { + // EPS Bearer ID + act_ded_eps_bearer_context_req->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + act_ded_eps_bearer_context_req->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // Linked Bearer Identity & Spare Half Octet + liblte_mme_unpack_linked_eps_bearer_identity_ie(&msg_ptr, 0, &act_ded_eps_bearer_context_req->linked_eps_bearer_id); + msg_ptr++; + + // EPS QoS + liblte_mme_unpack_eps_quality_of_service_ie(&msg_ptr, &act_ded_eps_bearer_context_req->eps_qos); + + // TFT + liblte_mme_unpack_traffic_flow_template_ie(&msg_ptr, &act_ded_eps_bearer_context_req->tft); + + // Transaction Identifier + if(LIBLTE_MME_TRANSACTION_IDENTIFIER_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_transaction_identifier_ie(&msg_ptr, &act_ded_eps_bearer_context_req->transaction_id); + act_ded_eps_bearer_context_req->transaction_id_present = true; + }else{ + act_ded_eps_bearer_context_req->transaction_id_present = false; + } + + // Negotiated QoS + if(LIBLTE_MME_QUALITY_OF_SERVICE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_quality_of_service_ie(&msg_ptr, &act_ded_eps_bearer_context_req->negotiated_qos); + act_ded_eps_bearer_context_req->negotiated_qos_present = true; + }else{ + act_ded_eps_bearer_context_req->negotiated_qos_present = false; + } + + // Negotiated LLC SAPI + if(LIBLTE_MME_LLC_SAPI_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_llc_service_access_point_identifier_ie(&msg_ptr, &act_ded_eps_bearer_context_req->llc_sapi); + act_ded_eps_bearer_context_req->llc_sapi_present = true; + }else{ + act_ded_eps_bearer_context_req->llc_sapi_present = false; + } + + // Radio Priority + if((LIBLTE_MME_RADIO_PRIORITY_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_radio_priority_ie(&msg_ptr, 0, &act_ded_eps_bearer_context_req->radio_prio); + msg_ptr++; + act_ded_eps_bearer_context_req->radio_prio_present = true; + }else{ + act_ded_eps_bearer_context_req->radio_prio_present = false; + } + + // Packet Flow Identifier + if(LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_packet_flow_identifier_ie(&msg_ptr, &act_ded_eps_bearer_context_req->packet_flow_id); + act_ded_eps_bearer_context_req->packet_flow_id_present = true; + }else{ + act_ded_eps_bearer_context_req->packet_flow_id_present = false; + } + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_ded_eps_bearer_context_req->protocol_cnfg_opts); + act_ded_eps_bearer_context_req->protocol_cnfg_opts_present = true; + }else{ + act_ded_eps_bearer_context_req->protocol_cnfg_opts_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Activate Default EPS Bearer Context Accept + + Description: Sent by the UE to the network to acknowledge + activation of a default EPS bearer context. + + Document Reference: 24.301 v10.2.0 Section 8.3.4 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_default_eps_bearer_context_accept_msg(LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *act_def_eps_bearer_context_accept, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(act_def_eps_bearer_context_accept != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (act_def_eps_bearer_context_accept->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = act_def_eps_bearer_context_accept->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT; + msg_ptr++; + + // Protocol Configuration Options + if(act_def_eps_bearer_context_accept->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&act_def_eps_bearer_context_accept->protocol_cnfg_opts, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_default_eps_bearer_context_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *act_def_eps_bearer_context_accept) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + act_def_eps_bearer_context_accept != NULL) + { + // EPS Bearer ID + act_def_eps_bearer_context_accept->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + act_def_eps_bearer_context_accept->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_def_eps_bearer_context_accept->protocol_cnfg_opts); + act_def_eps_bearer_context_accept->protocol_cnfg_opts_present = true; + }else{ + act_def_eps_bearer_context_accept->protocol_cnfg_opts_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Activate Default EPS Bearer Context Reject + + Description: Sent by the UE to the network to reject activation + of a default EPS bearer context. + + Document Reference: 24.301 v10.2.0 Section 8.3.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_default_eps_bearer_context_reject_msg(LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *act_def_eps_bearer_context_rej, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(act_def_eps_bearer_context_rej != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (act_def_eps_bearer_context_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = act_def_eps_bearer_context_rej->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT; + msg_ptr++; + + // ESM Cause + liblte_mme_pack_esm_cause_ie(act_def_eps_bearer_context_rej->esm_cause, &msg_ptr); + + // Protocol Configuration Options + if(act_def_eps_bearer_context_rej->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&act_def_eps_bearer_context_rej->protocol_cnfg_opts, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_default_eps_bearer_context_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *act_def_eps_bearer_context_rej) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + act_def_eps_bearer_context_rej != NULL) + { + // EPS Bearer ID + act_def_eps_bearer_context_rej->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + act_def_eps_bearer_context_rej->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // ESM Cause + liblte_mme_unpack_esm_cause_ie(&msg_ptr, &act_def_eps_bearer_context_rej->esm_cause); + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_def_eps_bearer_context_rej->protocol_cnfg_opts); + act_def_eps_bearer_context_rej->protocol_cnfg_opts_present = true; + }else{ + act_def_eps_bearer_context_rej->protocol_cnfg_opts_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Activate Default EPS Bearer Context Request + + Description: Sent by the network to the UE to request activation + of a default EPS bearer context. + + Document Reference: 24.301 v10.2.0 Section 8.3.6 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_activate_default_eps_bearer_context_request_msg(LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *act_def_eps_bearer_context_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(act_def_eps_bearer_context_req != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (act_def_eps_bearer_context_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = act_def_eps_bearer_context_req->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST; + msg_ptr++; + + // EPS QoS + liblte_mme_pack_eps_quality_of_service_ie(&act_def_eps_bearer_context_req->eps_qos, &msg_ptr); + + // Access Point Name + liblte_mme_pack_access_point_name_ie(&act_def_eps_bearer_context_req->apn, &msg_ptr); + + // PDN Address + liblte_mme_pack_pdn_address_ie(&act_def_eps_bearer_context_req->pdn_addr, &msg_ptr); + + // Transaction Identifier + if(act_def_eps_bearer_context_req->transaction_id_present) + { + *msg_ptr = LIBLTE_MME_TRANSACTION_IDENTIFIER_IEI; + msg_ptr++; + liblte_mme_pack_transaction_identifier_ie(&act_def_eps_bearer_context_req->transaction_id, &msg_ptr); + } + + // Negotiated QoS + if(act_def_eps_bearer_context_req->negotiated_qos_present) + { + *msg_ptr = LIBLTE_MME_QUALITY_OF_SERVICE_IEI; + msg_ptr++; + liblte_mme_pack_quality_of_service_ie(&act_def_eps_bearer_context_req->negotiated_qos, &msg_ptr); + } + + // Negotiated LLC SAPI + if(act_def_eps_bearer_context_req->llc_sapi_present) + { + *msg_ptr = LIBLTE_MME_LLC_SAPI_IEI; + msg_ptr++; + liblte_mme_pack_llc_service_access_point_identifier_ie(act_def_eps_bearer_context_req->llc_sapi, &msg_ptr); + } + + // Radio Priority + if(act_def_eps_bearer_context_req->radio_prio_present) + { + *msg_ptr = LIBLTE_MME_RADIO_PRIORITY_IEI << 4; + liblte_mme_pack_radio_priority_ie(act_def_eps_bearer_context_req->radio_prio, 0, &msg_ptr); + msg_ptr++; + } + + // Packet Flow Identifier + if(act_def_eps_bearer_context_req->packet_flow_id_present) + { + *msg_ptr = LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI; + msg_ptr++; + liblte_mme_pack_packet_flow_identifier_ie(act_def_eps_bearer_context_req->packet_flow_id, &msg_ptr); + } + + // APN-AMBR + if(act_def_eps_bearer_context_req->apn_ambr_present) + { + *msg_ptr = LIBLTE_MME_APN_AMBR_IEI; + msg_ptr++; + liblte_mme_pack_apn_aggregate_maximum_bit_rate_ie(&act_def_eps_bearer_context_req->apn_ambr, &msg_ptr); + } + + // ESM Cause + if(act_def_eps_bearer_context_req->esm_cause_present) + { + *msg_ptr = LIBLTE_MME_ESM_CAUSE_IEI; + msg_ptr++; + liblte_mme_pack_esm_cause_ie(act_def_eps_bearer_context_req->esm_cause, &msg_ptr); + } + + // Protocol Configuration Options + if(act_def_eps_bearer_context_req->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&act_def_eps_bearer_context_req->protocol_cnfg_opts, &msg_ptr); + } + + // Connectivity Type + if(act_def_eps_bearer_context_req->connectivity_type_present) + { + *msg_ptr = LIBLTE_MME_CONNECTIVITY_TYPE_IEI << 4; + liblte_mme_pack_connectivity_type_ie(act_def_eps_bearer_context_req->connectivity_type, 0, &msg_ptr); + msg_ptr++; + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_default_eps_bearer_context_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *act_def_eps_bearer_context_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + act_def_eps_bearer_context_req != NULL) + { + // EPS Bearer ID + act_def_eps_bearer_context_req->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + act_def_eps_bearer_context_req->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // EPS QoS + liblte_mme_unpack_eps_quality_of_service_ie(&msg_ptr, &act_def_eps_bearer_context_req->eps_qos); + + // Access Point Name + liblte_mme_unpack_access_point_name_ie(&msg_ptr, &act_def_eps_bearer_context_req->apn); + + // PDN Address + liblte_mme_unpack_pdn_address_ie(&msg_ptr, &act_def_eps_bearer_context_req->pdn_addr); + + // Transaction Identifier + if(LIBLTE_MME_TRANSACTION_IDENTIFIER_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_transaction_identifier_ie(&msg_ptr, &act_def_eps_bearer_context_req->transaction_id); + act_def_eps_bearer_context_req->transaction_id_present = true; + }else{ + act_def_eps_bearer_context_req->transaction_id_present = false; + } + + // Negotiated QoS + if(LIBLTE_MME_QUALITY_OF_SERVICE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_quality_of_service_ie(&msg_ptr, &act_def_eps_bearer_context_req->negotiated_qos); + act_def_eps_bearer_context_req->negotiated_qos_present = true; + }else{ + act_def_eps_bearer_context_req->negotiated_qos_present = false; + } + + // Negotiated LLC SAPI + if(LIBLTE_MME_LLC_SAPI_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_llc_service_access_point_identifier_ie(&msg_ptr, &act_def_eps_bearer_context_req->llc_sapi); + act_def_eps_bearer_context_req->llc_sapi_present = true; + }else{ + act_def_eps_bearer_context_req->llc_sapi_present = false; + } + + // Radio Priority + if((LIBLTE_MME_RADIO_PRIORITY_IEI << 4) == (*msg_ptr & 0xF0)) + { + liblte_mme_unpack_radio_priority_ie(&msg_ptr, 0, &act_def_eps_bearer_context_req->radio_prio); + msg_ptr++; + act_def_eps_bearer_context_req->radio_prio_present = true; + }else{ + act_def_eps_bearer_context_req->radio_prio_present = false; + } + + // Packet Flow Identifier + if(LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_packet_flow_identifier_ie(&msg_ptr, &act_def_eps_bearer_context_req->packet_flow_id); + act_def_eps_bearer_context_req->packet_flow_id_present = true; + }else{ + act_def_eps_bearer_context_req->packet_flow_id_present = false; + } + + // APN-AMBR + if(LIBLTE_MME_APN_AMBR_IEI == *msg_ptr) { - *msg_ptr = LIBLTE_MME_MS_CLASSMARK_2_IEI; msg_ptr++; - liblte_mme_pack_mobile_station_classmark_2_ie(&attach_req->ms_cm2, &msg_ptr); + liblte_mme_unpack_apn_aggregate_maximum_bit_rate_ie(&msg_ptr, &act_def_eps_bearer_context_req->apn_ambr); + act_def_eps_bearer_context_req->apn_ambr_present = true; + }else{ + act_def_eps_bearer_context_req->apn_ambr_present = false; } - // Mobile Station Classmark 3 - if(attach_req->ms_cm3_present) + // ESM Cause + if(LIBLTE_MME_ESM_CAUSE_IEI == *msg_ptr) { - *msg_ptr = LIBLTE_MME_MS_CLASSMARK_3_IEI; msg_ptr++; - liblte_mme_pack_mobile_station_classmark_3_ie(&attach_req->ms_cm3, &msg_ptr); + liblte_mme_unpack_esm_cause_ie(&msg_ptr, &act_def_eps_bearer_context_req->esm_cause); + act_def_eps_bearer_context_req->esm_cause_present = true; + }else{ + act_def_eps_bearer_context_req->esm_cause_present = false; } - // Supported Codecs - if(attach_req->supported_codecs_present) + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) { - *msg_ptr = LIBLTE_MME_SUPPORTED_CODEC_LIST_IEI; msg_ptr++; - liblte_mme_pack_supported_codec_list_ie(&attach_req->supported_codecs, &msg_ptr); + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_def_eps_bearer_context_req->protocol_cnfg_opts); + act_def_eps_bearer_context_req->protocol_cnfg_opts_present = true; + }else{ + act_def_eps_bearer_context_req->protocol_cnfg_opts_present = false; } - // Additional Update Type - if(attach_req->additional_update_type_present) + // Connectivity Type + if((LIBLTE_MME_CONNECTIVITY_TYPE_IEI << 4) == (*msg_ptr & 0xF0)) { - *msg_ptr = LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_IEI << 4; - liblte_mme_pack_additional_update_type_ie(attach_req->additional_update_type, 0, &msg_ptr); + liblte_mme_unpack_connectivity_type_ie(&msg_ptr, 0, &act_def_eps_bearer_context_req->connectivity_type); msg_ptr++; + act_def_eps_bearer_context_req->connectivity_type_present = true; + }else{ + act_def_eps_bearer_context_req->connectivity_type_present = false; } - // Voice Domain Preference and UE's Usage Setting - if(attach_req->voice_domain_pref_and_ue_usage_setting_present) + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Bearer Resource Allocation Reject + + Description: Sent by the network to the UE to reject the + allocation of a dedicated bearer resource. + + Document Reference: 24.301 v10.2.0 Section 8.3.7 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_allocation_reject_msg(LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REJECT_MSG_STRUCT *bearer_res_alloc_rej, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(bearer_res_alloc_rej != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (bearer_res_alloc_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = bearer_res_alloc_rej->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_ALLOCATION_REJECT; + msg_ptr++; + + // ESM Cause + liblte_mme_pack_esm_cause_ie(bearer_res_alloc_rej->esm_cause, &msg_ptr); + + // Protocol Configuration Options + if(bearer_res_alloc_rej->protocol_cnfg_opts_present) { - *msg_ptr = LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_IEI; + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; msg_ptr++; - liblte_mme_pack_voice_domain_pref_and_ue_usage_setting_ie(&attach_req->voice_domain_pref_and_ue_usage_setting, &msg_ptr); + liblte_mme_pack_protocol_config_options_ie(&bearer_res_alloc_rej->protocol_cnfg_opts, &msg_ptr); } - // Device Properties - if(attach_req->device_properties_present) + // T3496 Value + if(bearer_res_alloc_rej->t3496_present) { - *msg_ptr = LIBLTE_MME_ATTACH_REQUEST_DEVICE_PROPERTIES_IEI << 4; - liblte_mme_pack_device_properties_ie(attach_req->device_properties, 0, &msg_ptr); + *msg_ptr = LIBLTE_MME_T3496_VALUE_IEI; msg_ptr++; + liblte_mme_pack_gprs_timer_3_ie(&bearer_res_alloc_rej->t3496, &msg_ptr); } - // Old GUTI Type - if(attach_req->old_guti_type_present) + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_allocation_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REJECT_MSG_STRUCT *bearer_res_alloc_rej) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + bearer_res_alloc_rej != NULL) + { + // EPS Bearer ID + bearer_res_alloc_rej->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + bearer_res_alloc_rej->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // ESM Cause + liblte_mme_unpack_esm_cause_ie(&msg_ptr, &bearer_res_alloc_rej->esm_cause); + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &bearer_res_alloc_rej->protocol_cnfg_opts); + bearer_res_alloc_rej->protocol_cnfg_opts_present = true; + }else{ + bearer_res_alloc_rej->protocol_cnfg_opts_present = false; + } + + // T3496 Value + if(LIBLTE_MME_T3496_VALUE_IEI == *msg_ptr) { - *msg_ptr = LIBLTE_MME_GUTI_TYPE_IEI << 4; - liblte_mme_pack_guti_type_ie(attach_req->old_guti_type, 0, &msg_ptr); msg_ptr++; + liblte_mme_unpack_gprs_timer_3_ie(&msg_ptr, &bearer_res_alloc_rej->t3496); + bearer_res_alloc_rej->t3496_present = true; + }else{ + bearer_res_alloc_rej->t3496_present = false; } err = LIBLTE_SUCCESS; @@ -2195,173 +10764,450 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_M return(err); } -LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, - LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req) + +/********************************************************************* + Message Name: Bearer Resource Allocation Request + + Description: Sent by the UE to the network to request the + allocation of a dedicated bearer resource. + + Document Reference: 24.301 v10.2.0 Section 8.3.8 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_allocation_request_msg(LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_MSG_STRUCT *bearer_res_alloc_req, + LIBLTE_BYTE_MSG_STRUCT *msg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint8 *msg_ptr = msg->msg; - if(msg != NULL && - attach_req != NULL) + if(bearer_res_alloc_req != NULL && + msg != NULL) { - // Skip Protocol Discriminator and Security Header Type + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (bearer_res_alloc_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); msg_ptr++; - // Skip Message Type + // Procedure Transaction ID + *msg_ptr = bearer_res_alloc_req->proc_transaction_id; msg_ptr++; - // EPS Attach Type & NAS Key Set Identifier - liblte_mme_unpack_eps_attach_type_ie(&msg_ptr, 0, &attach_req->eps_type_result); - liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 4, &attach_req->nas_ksi); + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_ALLOCATION_REQUEST; msg_ptr++; - // EPS Mobile ID - liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &attach_req->eps_mobile_id); + // Linked EPS Bearer Identity & Spare Half Octet + liblte_mme_pack_linked_eps_bearer_identity_ie(bearer_res_alloc_req->linked_eps_bearer_id, 0, &msg_ptr); - // UE Network Capability - liblte_mme_unpack_ue_network_capability_ie(&msg_ptr, &attach_req->ue_network_cap); + // Traffic Flow Aggregate + liblte_mme_pack_traffic_flow_aggregate_description_ie(&bearer_res_alloc_req->tfa, &msg_ptr); - // ESM Message Container - liblte_mme_unpack_esm_message_container_ie(&msg_ptr, &attach_req->esm_msg); + // Required Traffic Flow QoS + liblte_mme_pack_eps_quality_of_service_ie(&bearer_res_alloc_req->req_tf_qos, &msg_ptr); - // Old P-TMSI Signature - if(LIBLTE_MME_P_TMSI_SIGNATURE_IEI == *msg_ptr) + // Protocol Configuration Options + if(bearer_res_alloc_req->protocol_cnfg_opts_present) { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; msg_ptr++; - liblte_mme_unpack_p_tmsi_signature_ie(&msg_ptr, &attach_req->old_p_tmsi_signature); - attach_req->old_p_tmsi_signature_present = true; + liblte_mme_pack_protocol_config_options_ie(&bearer_res_alloc_req->protocol_cnfg_opts, &msg_ptr); + } + + // Device Properties + if(bearer_res_alloc_req->device_properties_present) + { + *msg_ptr = LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_IEI << 4; + liblte_mme_pack_device_properties_ie(bearer_res_alloc_req->device_properties, 0, &msg_ptr); + msg_ptr++; + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_allocation_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_MSG_STRUCT *bearer_res_alloc_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + bearer_res_alloc_req != NULL) + { + // EPS Bearer ID + bearer_res_alloc_req->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + bearer_res_alloc_req->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // Linked EPS Bearer Identity & Spare Half Octet + liblte_mme_unpack_linked_eps_bearer_identity_ie(&msg_ptr, 0, &bearer_res_alloc_req->linked_eps_bearer_id); + + // Traffic Flow Aggregate + liblte_mme_unpack_traffic_flow_aggregate_description_ie(&msg_ptr, &bearer_res_alloc_req->tfa); + + // Required Traffic Flow QoS + liblte_mme_unpack_eps_quality_of_service_ie(&msg_ptr, &bearer_res_alloc_req->req_tf_qos); + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &bearer_res_alloc_req->protocol_cnfg_opts); + bearer_res_alloc_req->protocol_cnfg_opts_present = true; }else{ - attach_req->old_p_tmsi_signature_present = false; + bearer_res_alloc_req->protocol_cnfg_opts_present = false; } - // Additional GUTI - if(LIBLTE_MME_ADDITIONAL_GUTI_IEI == *msg_ptr) + // Device Properties + if((LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_IEI << 4) == *msg_ptr) { + liblte_mme_unpack_device_properties_ie(&msg_ptr, 0, &bearer_res_alloc_req->device_properties); msg_ptr++; - liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &attach_req->additional_guti); - attach_req->additional_guti_present = true; + bearer_res_alloc_req->device_properties_present = true; }else{ - attach_req->additional_guti_present = false; + bearer_res_alloc_req->device_properties_present = false; } - // Last Visited Registered TAI - if(LIBLTE_MME_LAST_VISITED_REGISTERED_TAI_IEI == *msg_ptr) + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Bearer Resource Modification Reject + + Description: Sent by the network to the UE to reject the + modification of a dedicated bearer resource. + + Document Reference: 24.301 v10.2.0 Section 8.3.9 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_modification_reject_msg(LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REJECT_MSG_STRUCT *bearer_res_mod_rej, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(bearer_res_mod_rej != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (bearer_res_mod_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = bearer_res_mod_rej->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_MODIFICATION_REJECT; + msg_ptr++; + + // ESM Cause + liblte_mme_pack_esm_cause_ie(bearer_res_mod_rej->esm_cause, &msg_ptr); + + // Protocol Configuration Options + if(bearer_res_mod_rej->protocol_cnfg_opts_present) { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; msg_ptr++; - liblte_mme_unpack_tracking_area_id_ie(&msg_ptr, &attach_req->last_visited_registered_tai); - attach_req->last_visited_registered_tai_present = true; + liblte_mme_pack_protocol_config_options_ie(&bearer_res_mod_rej->protocol_cnfg_opts, &msg_ptr); + } + + // T3496 Value + if(bearer_res_mod_rej->t3496_present) + { + *msg_ptr = LIBLTE_MME_T3496_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_3_ie(&bearer_res_mod_rej->t3496, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_modification_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REJECT_MSG_STRUCT *bearer_res_mod_rej) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + bearer_res_mod_rej != NULL) + { + // EPS Bearer ID + bearer_res_mod_rej->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + bearer_res_mod_rej->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // ESM Cause + liblte_mme_unpack_esm_cause_ie(&msg_ptr, &bearer_res_mod_rej->esm_cause); + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &bearer_res_mod_rej->protocol_cnfg_opts); + bearer_res_mod_rej->protocol_cnfg_opts_present = true; }else{ - attach_req->last_visited_registered_tai_present = false; + bearer_res_mod_rej->protocol_cnfg_opts_present = false; } - // DRX Parameter - if(LIBLTE_MME_DRX_PARAMETER_IEI == *msg_ptr) + // T3496 Value + if(LIBLTE_MME_T3496_VALUE_IEI == *msg_ptr) { msg_ptr++; - liblte_mme_unpack_drx_parameter_ie(&msg_ptr, &attach_req->drx_param); - attach_req->drx_param_present = true; + liblte_mme_unpack_gprs_timer_3_ie(&msg_ptr, &bearer_res_mod_rej->t3496); + bearer_res_mod_rej->t3496_present = true; }else{ - attach_req->drx_param_present = false; + bearer_res_mod_rej->t3496_present = false; } - // MS Network Capability - if(LIBLTE_MME_MS_NETWORK_CAPABILITY_IEI == *msg_ptr) + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Bearer Resource Modification Request + + Description: Sent by the UE to the network to request the + modification of a dedicated bearer resource. + + Document Reference: 24.301 v10.2.0 Section 8.3.10 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_modification_request_msg(LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_MSG_STRUCT *bearer_res_mod_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(bearer_res_mod_req != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (bearer_res_mod_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = bearer_res_mod_req->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_MODIFICATION_REQUEST; + msg_ptr++; + + // EPS Bearer Identity For Packet Filter & Spare Half Octet + liblte_mme_pack_linked_eps_bearer_identity_ie(bearer_res_mod_req->eps_bearer_id_for_packet_filter, 0, &msg_ptr); + + // Traffic Flow Aggregate + liblte_mme_pack_traffic_flow_aggregate_description_ie(&bearer_res_mod_req->tfa, &msg_ptr); + + // Required Traffic Flow QoS + if(bearer_res_mod_req->req_tf_qos_present) { + *msg_ptr = LIBLTE_MME_EPS_QUALITY_OF_SERVICE_IEI; msg_ptr++; - liblte_mme_unpack_ms_network_capability_ie(&msg_ptr, &attach_req->ms_network_cap); - attach_req->ms_network_cap_present = true; - }else{ - attach_req->ms_network_cap_present = false; + liblte_mme_pack_eps_quality_of_service_ie(&bearer_res_mod_req->req_tf_qos, &msg_ptr); } - // Old Location Area ID - if(LIBLTE_MME_LOCATION_AREA_ID_IEI == *msg_ptr) + // ESM Cause + if(bearer_res_mod_req->esm_cause_present) { + *msg_ptr = LIBLTE_MME_ESM_CAUSE_IEI; msg_ptr++; - liblte_mme_unpack_location_area_id_ie(&msg_ptr, &attach_req->old_lai); - attach_req->old_lai_present = true; - }else{ - attach_req->old_lai_present = false; + liblte_mme_pack_esm_cause_ie(bearer_res_mod_req->esm_cause, &msg_ptr); } - // TMSI Status - if((LIBLTE_MME_TMSI_STATUS_IEI << 4) == (*msg_ptr & 0xF0)) + // Protocol Configuration Options + if(bearer_res_mod_req->protocol_cnfg_opts_present) { - liblte_mme_unpack_tmsi_status_ie(&msg_ptr, 0, &attach_req->tmsi_status); + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; msg_ptr++; - attach_req->tmsi_status_present = true; - }else{ - attach_req->tmsi_status_present = false; + liblte_mme_pack_protocol_config_options_ie(&bearer_res_mod_req->protocol_cnfg_opts, &msg_ptr); } - // Mobile Station Classmark 2 - if(LIBLTE_MME_MS_CLASSMARK_2_IEI == *msg_ptr) + // Device Properties + if(bearer_res_mod_req->device_properties_present) { + *msg_ptr = LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_IEI << 4; + liblte_mme_pack_device_properties_ie(bearer_res_mod_req->device_properties, 0, &msg_ptr); msg_ptr++; - liblte_mme_unpack_mobile_station_classmark_2_ie(&msg_ptr, &attach_req->ms_cm2); - attach_req->ms_cm2_present = true; - }else{ - attach_req->ms_cm2_present = false; } - // Mobile Station Classmark 3 - if(LIBLTE_MME_MS_CLASSMARK_3_IEI == *msg_ptr) + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_modification_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_MSG_STRUCT *bearer_res_mod_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + bearer_res_mod_req != NULL) + { + // EPS Bearer ID + bearer_res_mod_req->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + bearer_res_mod_req->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // EPS Bearer Identity For Packet Filter & Spare Half Octet + liblte_mme_unpack_linked_eps_bearer_identity_ie(&msg_ptr, 0, &bearer_res_mod_req->eps_bearer_id_for_packet_filter); + + // Traffic Flow Aggregate + liblte_mme_unpack_traffic_flow_aggregate_description_ie(&msg_ptr, &bearer_res_mod_req->tfa); + + // Required Traffic Flow QoS + if(LIBLTE_MME_EPS_QUALITY_OF_SERVICE_IEI == *msg_ptr) { msg_ptr++; - liblte_mme_unpack_mobile_station_classmark_3_ie(&msg_ptr, &attach_req->ms_cm3); - attach_req->ms_cm3_present = true; + liblte_mme_unpack_eps_quality_of_service_ie(&msg_ptr, &bearer_res_mod_req->req_tf_qos); + bearer_res_mod_req->req_tf_qos_present = true; }else{ - attach_req->ms_cm3_present = false; + bearer_res_mod_req->req_tf_qos_present = false; } - // Supported Codecs - if(LIBLTE_MME_SUPPORTED_CODEC_LIST_IEI == *msg_ptr) + // ESM Cause + if(LIBLTE_MME_ESM_CAUSE_IEI == *msg_ptr) { msg_ptr++; - liblte_mme_unpack_supported_codec_list_ie(&msg_ptr, &attach_req->supported_codecs); - attach_req->supported_codecs_present = true; + liblte_mme_unpack_esm_cause_ie(&msg_ptr, &bearer_res_mod_req->esm_cause); + bearer_res_mod_req->esm_cause_present = true; }else{ - attach_req->supported_codecs_present = false; + bearer_res_mod_req->esm_cause_present = false; } - // Additional Update Type - if((LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_IEI << 4) == (*msg_ptr & 0xF0)) + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) { - liblte_mme_unpack_additional_update_type_ie(&msg_ptr, 0, &attach_req->additional_update_type); msg_ptr++; - attach_req->additional_update_type_present = true; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &bearer_res_mod_req->protocol_cnfg_opts); + bearer_res_mod_req->protocol_cnfg_opts_present = true; }else{ - attach_req->additional_update_type_present = false; + bearer_res_mod_req->protocol_cnfg_opts_present = false; } - // Voice Domain Preference and UE's Usage Setting - if(LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_IEI == *msg_ptr) + // Device Properties + if((LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_IEI << 4) == *msg_ptr) { + liblte_mme_unpack_device_properties_ie(&msg_ptr, 0, &bearer_res_mod_req->device_properties); msg_ptr++; - liblte_mme_unpack_voice_domain_pref_and_ue_usage_setting_ie(&msg_ptr, &attach_req->voice_domain_pref_and_ue_usage_setting); - attach_req->voice_domain_pref_and_ue_usage_setting_present = true; + bearer_res_mod_req->device_properties_present = true; }else{ - attach_req->voice_domain_pref_and_ue_usage_setting_present = false; + bearer_res_mod_req->device_properties_present = false; } - // Device Properties - if((LIBLTE_MME_ATTACH_REQUEST_DEVICE_PROPERTIES_IEI << 4) == (*msg_ptr & 0xF0)) + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: Deactivate EPS Bearer Context Accept + + Description: Sent by the UE to acknowledge deactivation of the + EPS bearer context requested in the corresponding + deactivate EPS bearer context request message. + + Document Reference: 24.301 v10.2.0 Section 8.3.11 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_mme_pack_deactivate_eps_bearer_context_accept_msg(LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *deact_eps_bearer_context_accept, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(deact_eps_bearer_context_accept != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (deact_eps_bearer_context_accept->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = deact_eps_bearer_context_accept->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT; + msg_ptr++; + + // Protocol Configuration Options + if(deact_eps_bearer_context_accept->protocol_cnfg_opts_present) { - liblte_mme_unpack_device_properties_ie(&msg_ptr, 0, &attach_req->device_properties); + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; msg_ptr++; - attach_req->device_properties_present = true; - }else{ - attach_req->device_properties_present = false; + liblte_mme_pack_protocol_config_options_ie(&deact_eps_bearer_context_accept->protocol_cnfg_opts, &msg_ptr); } - // Old GUTI Type - if((LIBLTE_MME_GUTI_TYPE_IEI << 4) == (*msg_ptr & 0xF0)) + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_deactivate_eps_bearer_context_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *deact_eps_bearer_context_accept) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + deact_eps_bearer_context_accept != NULL) + { + // EPS Bearer ID + deact_eps_bearer_context_accept->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + deact_eps_bearer_context_accept->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) { - liblte_mme_unpack_guti_type_ie(&msg_ptr, 0, &attach_req->old_guti_type); msg_ptr++; - attach_req->old_guti_type_present = true; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &deact_eps_bearer_context_accept->protocol_cnfg_opts); + deact_eps_bearer_context_accept->protocol_cnfg_opts_present = true; }else{ - attach_req->old_guti_type_present = false; + deact_eps_bearer_context_accept->protocol_cnfg_opts_present = false; } err = LIBLTE_SUCCESS; @@ -2371,509 +11217,876 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT } /********************************************************************* - Message Name: Authentication Failure + Message Name: Deactivate EPS Bearer Context Request - Description: Sent by the UE to the network to indicate that - authentication of the network has failed. + Description: Sent by the network to request deactivation of an + EPS bearer context. - Document Reference: 24.301 v10.2.0 Section 8.2.5 + Document Reference: 24.301 v10.2.0 Section 8.3.12 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_deactivate_eps_bearer_context_request_msg(LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *deact_eps_bearer_context_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; -/********************************************************************* - Message Name: Authentication Reject + if(deact_eps_bearer_context_req != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (deact_eps_bearer_context_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; - Description: Sent by the network to the UE to indicate that the - authentication procedure has failed and that the UE - shall abort all activities. + // Procedure Transaction ID + *msg_ptr = deact_eps_bearer_context_req->proc_transaction_id; + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.2.6 -*********************************************************************/ -// FIXME + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST; + msg_ptr++; -/********************************************************************* - Message Name: Authentication Request + // ESM Cause + liblte_mme_pack_esm_cause_ie(deact_eps_bearer_context_req->esm_cause, &msg_ptr); - Description: Sent by the network to the UE to initiate - authentication of the UE identity. + // Protocol Configuration Options + if(deact_eps_bearer_context_req->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&deact_eps_bearer_context_req->protocol_cnfg_opts, &msg_ptr); + } - Document Reference: 24.301 v10.2.0 Section 8.2.7 -*********************************************************************/ -// FIXME + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; -/********************************************************************* - Message Name: Authentication Response + err = LIBLTE_SUCCESS; + } - Description: Sent by the UE to the network to deliver a calculated - authentication response to the network. + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_deactivate_eps_bearer_context_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *deact_eps_bearer_context_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; - Document Reference: 24.301 v10.2.0 Section 8.2.8 -*********************************************************************/ -// FIXME + if(msg != NULL && + deact_eps_bearer_context_req != NULL) + { + // EPS Bearer ID + deact_eps_bearer_context_req->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + deact_eps_bearer_context_req->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // ESM Cause + liblte_mme_unpack_esm_cause_ie(&msg_ptr, &deact_eps_bearer_context_req->esm_cause); + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &deact_eps_bearer_context_req->protocol_cnfg_opts); + deact_eps_bearer_context_req->protocol_cnfg_opts_present = true; + }else{ + deact_eps_bearer_context_req->protocol_cnfg_opts_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - Message Name: CS Service Notification + Message Name: ESM Information Request - Description: Sent by the network when a paging request with CS - call indicator was received via SGs for a UE, and a - NAS signalling connection is already established for - the UE. + Description: Sent by the network to the UE to request the UE to + provide ESM information, i.e. protocol configuration + options or APN or both. - Document Reference: 24.301 v10.2.0 Section 8.2.9 + Document Reference: 24.301 v10.2.0 Section 8.3.13 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(esm_info_req != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (esm_info_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = esm_info_req->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_REQUEST; + msg_ptr++; + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + esm_info_req != NULL) + { + // EPS Bearer ID + esm_info_req->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + esm_info_req->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - Message Name: Detach Accept + Message Name: ESM Information Response - Description: Sent by the network to indicate that the detach - procedure has been completed. + Description: Sent by the UE to the network in response to an ESM + INFORMATION REQUEST message and provides the + requested ESM information. - Document Reference: 24.301 v10.2.0 Section 8.2.10 + Document Reference: 24.301 v10.2.0 Section 8.3.14 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_response_msg(LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; -/********************************************************************* - Message Name: Detach Request + if(esm_info_resp != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (esm_info_resp->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; - Description: Sent by the UE to request the release of an EMM - context. + // Procedure Transaction ID + *msg_ptr = esm_info_resp->proc_transaction_id; + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.2.11 -*********************************************************************/ -// FIXME + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE; + msg_ptr++; -/********************************************************************* - Message Name: Downlink NAS Transport + // Access Point Name + if(esm_info_resp->apn_present) + { + *msg_ptr = LIBLTE_MME_ACCESS_POINT_NAME_IEI; + msg_ptr++; + liblte_mme_pack_access_point_name_ie(&esm_info_resp->apn, &msg_ptr); + } - Description: Sent by the network to the UE in order to carry an - SMS message in encapsulated format. + // Protocol Configuration Options + if(esm_info_resp->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&esm_info_resp->protocol_cnfg_opts, &msg_ptr); + } - Document Reference: 24.301 v10.2.0 Section 8.2.12 -*********************************************************************/ -// FIXME + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; -/********************************************************************* - Message Name: EMM Information + err = LIBLTE_SUCCESS; + } - Description: Sent by the network at any time during EMM context is - established to send certain information to the UE. + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; - Document Reference: 24.301 v10.2.0 Section 8.2.13 -*********************************************************************/ -// FIXME + if(msg != NULL && + esm_info_resp != NULL) + { + // EPS Bearer ID + esm_info_resp->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; -/********************************************************************* - Message Name: EMM Status + // Procedure Transaction ID + esm_info_resp->proc_transaction_id = *msg_ptr; + msg_ptr++; - Description: Sent by the UE or by the network at any time to - report certain error conditions. + // Skip Message Type + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.2.14 -*********************************************************************/ -// FIXME + // Access Point Name + if(LIBLTE_MME_ACCESS_POINT_NAME_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_access_point_name_ie(&msg_ptr, &esm_info_resp->apn); + esm_info_resp->apn_present = true; + }else{ + esm_info_resp->apn_present = false; + } -/********************************************************************* - Message Name: Extended Service Request + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &esm_info_resp->protocol_cnfg_opts); + esm_info_resp->protocol_cnfg_opts_present = true; + }else{ + esm_info_resp->protocol_cnfg_opts_present = false; + } - Description: Sent by the UE to the network to initiate a CS - fallback or 1xCS fallback call or respond to a mobile - terminated CS fallback or 1xCS fallback request from - the network or to request the establishment of a NAS - signalling connection and of the radio and S1 bearers - for packet services, if the UE needs to provide - additional information that cannot be provided via a - SERVICE REQUEST message. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 8.2.15 -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - Message Name: GUTI Reallocation Command + Message Name: ESM Status - Description: Sent by the network to the UE to reallocate a GUTI - and optionally provide a new TAI list. + Description: Sent by the network or the UE to pass information on + the status of the indicated EPS bearer context and + report certain error conditions. - Document Reference: 24.301 v10.2.0 Section 8.2.16 + Document Reference: 24.301 v10.2.0 Section 8.3.15 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_esm_status_msg(LIBLTE_MME_ESM_STATUS_MSG_STRUCT *esm_status, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; -/********************************************************************* - Message Name: GUTI Reallocation Complete + if(esm_status != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (esm_status->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; - Description: Sent by the UE to the network to indicate that - reallocation of a GUTI has taken place. + // Procedure Transaction ID + *msg_ptr = esm_status->proc_transaction_id; + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.2.17 -*********************************************************************/ -// FIXME + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ESM_STATUS; + msg_ptr++; -/********************************************************************* - Message Name: Identity Request + // ESM Cause + liblte_mme_pack_esm_cause_ie(esm_status->esm_cause, &msg_ptr); - Description: Sent by the network to the UE to request the UE to - provide the specified identity. + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; - Document Reference: 24.301 v10.2.0 Section 8.2.18 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } -/********************************************************************* - Message Name: Identity Response + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_status_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ESM_STATUS_MSG_STRUCT *esm_status) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; - Description: Sent by the UE to the network in response to an - IDENTITY REQUEST message and provides the requested - identity. + if(msg != NULL && + esm_status != NULL) + { + // EPS Bearer ID + esm_status->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.2.19 -*********************************************************************/ -// FIXME + // Procedure Transaction ID + esm_status->proc_transaction_id = *msg_ptr; + msg_ptr++; -/********************************************************************* - Message Name: Security Mode Command + // Skip Message Type + msg_ptr++; - Description: Sent by the network to the UE to establish NAS - signalling security. + // ESM Cause + liblte_mme_unpack_esm_cause_ie(&msg_ptr, &esm_status->esm_cause); - Document Reference: 24.301 v10.2.0 Section 8.2.20 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - Message Name: Security Mode Complete + Message Name: Modify EPS Bearer Context Accept - Description: Sent by the UE to the network in response to a - SECURITY MODE COMMAND message. + Description: Sent by the UE to the network to acknowledge the + modification of an active EPS bearer context. - Document Reference: 24.301 v10.2.0 Section 8.2.21 + Document Reference: 24.301 v10.2.0 Section 8.3.16 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_modify_eps_bearer_context_accept_msg(LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *mod_eps_bearer_context_accept, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; -/********************************************************************* - Message Name: Security Mode Reject + if(mod_eps_bearer_context_accept != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (mod_eps_bearer_context_accept->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; - Description: Sent by the UE to the network to indicate that the - corresponding security mode command has been - rejected. + // Procedure Transaction ID + *msg_ptr = mod_eps_bearer_context_accept->proc_transaction_id; + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.2.22 -*********************************************************************/ -// FIXME + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_MODIFY_EPS_BEARER_CONTEXT_ACCEPT; + msg_ptr++; -/********************************************************************* - Message Name: Security Protected NAS Message + // Protocol Configuration Options + if(mod_eps_bearer_context_accept->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&mod_eps_bearer_context_accept->protocol_cnfg_opts, &msg_ptr); + } - Description: Sent by the UE or the network to transfer a NAS - message together with the sequence number and the - message authentication code protecting the message. + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; - Document Reference: 24.301 v10.2.0 Section 8.2.23 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } -/********************************************************************* - Message Name: Service Reject + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_modify_eps_bearer_context_accept_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT *mod_eps_bearer_context_accept) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; - Description: Sent by the network to the UE in order to reject the - service request procedure. + if(msg != NULL && + mod_eps_bearer_context_accept != NULL) + { + // EPS Bearer ID + mod_eps_bearer_context_accept->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.2.24 -*********************************************************************/ -// FIXME + // Procedure Transaction ID + mod_eps_bearer_context_accept->proc_transaction_id = *msg_ptr; + msg_ptr++; -/********************************************************************* - Message Name: Service Request + // Skip Message Type + msg_ptr++; - Description: Sent by the UE to the network to request the - establishment of a NAS signalling connection and of - the radio and S1 bearers. + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &mod_eps_bearer_context_accept->protocol_cnfg_opts); + mod_eps_bearer_context_accept->protocol_cnfg_opts_present = true; + }else{ + mod_eps_bearer_context_accept->protocol_cnfg_opts_present = false; + } - Document Reference: 24.301 v10.2.0 Section 8.2.25 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - Message Name: Tracking Area Update Accept + Message Name: Modify EPS Bearer Context Reject - Description: Sent by the network to the UE to provide the UE with - EPS mobility management related data in response to - a tracking area update request message. + Description: Sent by the UE or the network to reject a + modification of an active EPS bearer context. - Document Reference: 24.301 v10.2.0 Section 8.2.26 + Document Reference: 24.301 v10.2.0 Section 8.3.17 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_modify_eps_bearer_context_reject_msg(LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *mod_eps_bearer_context_rej, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; -/********************************************************************* - Message Name: Tracking Area Update Complete + if(mod_eps_bearer_context_rej != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (mod_eps_bearer_context_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; - Description: Sent by the UE to the network in response to a - tracking area update accept message if a GUTI has - been changed or a new TMSI has been assigned. + // Procedure Transaction ID + *msg_ptr = mod_eps_bearer_context_rej->proc_transaction_id; + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.2.27 -*********************************************************************/ -// FIXME + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_MODIFY_EPS_BEARER_CONTEXT_REJECT; + msg_ptr++; -/********************************************************************* - Message Name: Tracking Area Update Reject + // ESM Cause + liblte_mme_pack_esm_cause_ie(mod_eps_bearer_context_rej->esm_cause, &msg_ptr); - Description: Sent by the network to the UE in order to reject the - tracking area updating procedure. + // Protocol Configuration Options + if(mod_eps_bearer_context_rej->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&mod_eps_bearer_context_rej->protocol_cnfg_opts, &msg_ptr); + } - Document Reference: 24.301 v10.2.0 Section 8.2.28 -*********************************************************************/ -// FIXME + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; -/********************************************************************* - Message Name: Tracking Area Update Request + err = LIBLTE_SUCCESS; + } - Description: Sent by the UE to the network to initiate a tracking - area updating procedure. + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_modify_eps_bearer_context_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT *mod_eps_bearer_context_rej) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; - Document Reference: 24.301 v10.2.0 Section 8.2.29 -*********************************************************************/ -// FIXME + if(msg != NULL && + mod_eps_bearer_context_rej != NULL) + { + // EPS Bearer ID + mod_eps_bearer_context_rej->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; -/********************************************************************* - Message Name: Uplink NAS Transport + // Procedure Transaction ID + mod_eps_bearer_context_rej->proc_transaction_id = *msg_ptr; + msg_ptr++; - Description: Sent by the UE to the network in order to carry an - SMS message in encapsulated format. + // Skip Message Type + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.2.30 -*********************************************************************/ -// FIXME + // ESM Cause + liblte_mme_unpack_esm_cause_ie(&msg_ptr, &mod_eps_bearer_context_rej->esm_cause); -/********************************************************************* - Message Name: Downlink Generic NAS Transport + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &mod_eps_bearer_context_rej->protocol_cnfg_opts); + mod_eps_bearer_context_rej->protocol_cnfg_opts_present = true; + }else{ + mod_eps_bearer_context_rej->protocol_cnfg_opts_present = false; + } - Description: Sent by the network to the UE in order to carry an - application message in encapsulated format. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 8.2.31 -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - Message Name: Uplink Generic NAS Transport + Message Name: Modify EPS Bearer Context Request - Description: Sent by the UE to the network in order to carry an - application protocol message in encapsulated format. + Description: Sent by the network to the UE to request modification + of an active EPS bearer context. - Document Reference: 24.301 v10.2.0 Section 8.2.32 + Document Reference: 24.301 v10.2.0 Section 8.3.18 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_modify_eps_bearer_context_request_msg(LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *mod_eps_bearer_context_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; -/********************************************************************* - Message Name: Activate Dedicated EPS Bearer Context Accept + if(mod_eps_bearer_context_req != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (mod_eps_bearer_context_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; - Description: Sent by the UE to the network to acknowledge - activation of a dedicated EPS bearer context - associated with the same PDN address(es) and APN as - an already active EPS bearer context. + // Procedure Transaction ID + *msg_ptr = mod_eps_bearer_context_req->proc_transaction_id; + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.3.1 -*********************************************************************/ -// FIXME + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_MODIFY_EPS_BEARER_CONTEXT_REQUEST; + msg_ptr++; -/********************************************************************* - Message Name: Activate Dedicated EPS Bearer Context Reject + // New EPS QoS + if(mod_eps_bearer_context_req->new_eps_qos_present) + { + *msg_ptr = LIBLTE_MME_EPS_QUALITY_OF_SERVICE_IEI; + msg_ptr++; + liblte_mme_pack_eps_quality_of_service_ie(&mod_eps_bearer_context_req->new_eps_qos, &msg_ptr); + } - Description: Sent by the UE to the network to reject activation - of a dedicated EPS bearer context. + // TFT + if(mod_eps_bearer_context_req->tft_present) + { + *msg_ptr = LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_IEI; + msg_ptr++; + liblte_mme_pack_traffic_flow_template_ie(&mod_eps_bearer_context_req->tft, &msg_ptr); + } - Document Reference: 24.301 v10.2.0 Section 8.3.2 -*********************************************************************/ -// FIXME + // New QoS + if(mod_eps_bearer_context_req->new_qos_present) + { + *msg_ptr = LIBLTE_MME_QUALITY_OF_SERVICE_IEI; + msg_ptr++; + liblte_mme_pack_quality_of_service_ie(&mod_eps_bearer_context_req->new_qos, &msg_ptr); + } -/********************************************************************* - Message Name: Activate Dedicated EPS Bearer Context Request + // Negotiated LLC SAPI + if(mod_eps_bearer_context_req->negotiated_llc_sapi_present) + { + *msg_ptr = LIBLTE_MME_LLC_SAPI_IEI; + msg_ptr++; + liblte_mme_pack_llc_service_access_point_identifier_ie(mod_eps_bearer_context_req->negotiated_llc_sapi, &msg_ptr); + } - Description: Sent by the network to the UE to request activation - of a dedicated EPS bearer context associated with - the same PDN address(es) and APN as an already - active default EPS bearer context. + // Radio Priority + if(mod_eps_bearer_context_req->radio_prio_present) + { + *msg_ptr = LIBLTE_MME_RADIO_PRIORITY_IEI << 4; + liblte_mme_pack_radio_priority_ie(mod_eps_bearer_context_req->radio_prio, 0, &msg_ptr); + msg_ptr++; + } - Document Reference: 24.301 v10.2.0 Section 8.3.3 -*********************************************************************/ -// FIXME + // Packet Flow Identifier + if(mod_eps_bearer_context_req->packet_flow_id_present) + { + *msg_ptr = LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI; + msg_ptr++; + liblte_mme_pack_packet_flow_identifier_ie(mod_eps_bearer_context_req->packet_flow_id, &msg_ptr); + } -/********************************************************************* - Message Name: Activate Default EPS Bearer Context Accept + // APN-AMBR + if(mod_eps_bearer_context_req->apn_ambr_present) + { + *msg_ptr = LIBLTE_MME_APN_AMBR_IEI; + msg_ptr++; + liblte_mme_pack_apn_aggregate_maximum_bit_rate_ie(&mod_eps_bearer_context_req->apn_ambr, &msg_ptr); + } - Description: Sent by the UE to the network to acknowledge - activation of a default EPS bearer context. + // Protocol Configuration Options + if(mod_eps_bearer_context_req->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&mod_eps_bearer_context_req->protocol_cnfg_opts, &msg_ptr); + } - Document Reference: 24.301 v10.2.0 Section 8.3.4 -*********************************************************************/ -// FIXME + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; -/********************************************************************* - Message Name: Activate Default EPS Bearer Context Reject + err = LIBLTE_SUCCESS; + } - Description: Sent by the UE to the network to reject activation - of a default EPS bearer context. + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_modify_eps_bearer_context_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT *mod_eps_bearer_context_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; - Document Reference: 24.301 v10.2.0 Section 8.3.5 -*********************************************************************/ -// FIXME + if(msg != NULL && + mod_eps_bearer_context_req != NULL) + { + // EPS Bearer ID + mod_eps_bearer_context_req->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; -/********************************************************************* - Message Name: Activate Default EPS Bearer Context Request + // Procedure Transaction ID + mod_eps_bearer_context_req->proc_transaction_id = *msg_ptr; + msg_ptr++; - Description: Sent by the network to the UE to request activation - of a default EPS bearer context. + // Skip Message Type + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.3.6 -*********************************************************************/ -// FIXME + // New EPS QoS + if(LIBLTE_MME_EPS_QUALITY_OF_SERVICE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_eps_quality_of_service_ie(&msg_ptr, &mod_eps_bearer_context_req->new_eps_qos); + mod_eps_bearer_context_req->new_eps_qos_present = true; + }else{ + mod_eps_bearer_context_req->new_eps_qos_present = false; + } -/********************************************************************* - Message Name: Bearer Resource Allocation Reject + // TFT + if(LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_traffic_flow_template_ie(&msg_ptr, &mod_eps_bearer_context_req->tft); + mod_eps_bearer_context_req->tft_present = true; + }else{ + mod_eps_bearer_context_req->tft_present = false; + } - Description: Sent by the network to the UE to reject the - allocation of a dedicated bearer resource. + // New QoS + if(LIBLTE_MME_QUALITY_OF_SERVICE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_quality_of_service_ie(&msg_ptr, &mod_eps_bearer_context_req->new_qos); + mod_eps_bearer_context_req->new_qos_present = true; + }else{ + mod_eps_bearer_context_req->new_qos_present = false; + } - Document Reference: 24.301 v10.2.0 Section 8.3.7 -*********************************************************************/ -// FIXME + // Negotiated LLC SAPI + if(LIBLTE_MME_LLC_SAPI_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_llc_service_access_point_identifier_ie(&msg_ptr, &mod_eps_bearer_context_req->negotiated_llc_sapi); + mod_eps_bearer_context_req->negotiated_llc_sapi_present = true; + }else{ + mod_eps_bearer_context_req->negotiated_llc_sapi_present = false; + } -/********************************************************************* - Message Name: Bearer Resource Allocation Request + // Radio Priority + if((LIBLTE_MME_RADIO_PRIORITY_IEI << 4) == *msg_ptr) + { + liblte_mme_unpack_radio_priority_ie(&msg_ptr, 0, &mod_eps_bearer_context_req->radio_prio); + msg_ptr++; + mod_eps_bearer_context_req->radio_prio_present = true; + }else{ + mod_eps_bearer_context_req->radio_prio_present = false; + } - Description: Sent by the UE to the network to request the - allocation of a dedicated bearer resource. + // Packet Flow Identifier + if(LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_packet_flow_identifier_ie(&msg_ptr, &mod_eps_bearer_context_req->packet_flow_id); + mod_eps_bearer_context_req->packet_flow_id_present = true; + }else{ + mod_eps_bearer_context_req->packet_flow_id_present = false; + } - Document Reference: 24.301 v10.2.0 Section 8.3.8 -*********************************************************************/ -// FIXME + // APN-AMBR + if(LIBLTE_MME_APN_AMBR_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_apn_aggregate_maximum_bit_rate_ie(&msg_ptr, &mod_eps_bearer_context_req->apn_ambr); + mod_eps_bearer_context_req->apn_ambr_present = true; + }else{ + mod_eps_bearer_context_req->apn_ambr_present = false; + } -/********************************************************************* - Message Name: Bearer Resource Modification Reject + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &mod_eps_bearer_context_req->protocol_cnfg_opts); + mod_eps_bearer_context_req->protocol_cnfg_opts_present = true; + }else{ + mod_eps_bearer_context_req->protocol_cnfg_opts_present = false; + } - Description: Sent by the network to the UE to reject the - modification of a dedicated bearer resource. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 8.3.9 -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - Message Name: Bearer Resource Modification Request + Message Name: Notification - Description: Sent by the UE to the network to request the - modification of a dedicated bearer resource. + Description: Sent by the network to inform the UE about events + which are relevant for the upper layer using an EPS + bearer context or having requested a procedure + transaction. - Document Reference: 24.301 v10.2.0 Section 8.3.10 + Document Reference: 24.301 v10.2.0 Section 8.3.18A *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_notification_msg(LIBLTE_MME_NOTIFICATION_MSG_STRUCT *notification, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; -/********************************************************************* - Message Name: Deactivate EPS Bearer Context Accept + if(notification != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (notification->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = notification->proc_transaction_id; + msg_ptr++; - Description: Sent by the UE to acknowledge deactivation of the - EPS bearer context requested in the corresponding - deactivate EPS bearer context request message. + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_NOTIFICATION; + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.3.11 -*********************************************************************/ -// FIXME + // Notification Indicator + liblte_mme_pack_notification_indicator_ie(notification->notification_ind, &msg_ptr); -/********************************************************************* - Message Name: Deactivate EPS Bearer Context Request + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; - Description: Sent by the network to request deactivation of an - EPS bearer context. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 8.3.12 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_notification_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_NOTIFICATION_MSG_STRUCT *notification) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; -/********************************************************************* - Message Name: ESM Information Request + if(msg != NULL && + notification != NULL) + { + // EPS Bearer ID + notification->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; - Description: Sent by the network to the UE to request the UE to - provide ESM information, i.e. protocol configuration - options or APN or both. + // Procedure Transaction ID + notification->proc_transaction_id = *msg_ptr; + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.3.13 -*********************************************************************/ -// FIXME + // Skip Message Type + msg_ptr++; -/********************************************************************* - Message Name: ESM Information Response + // Notification Indicator + liblte_mme_unpack_notification_indicator_ie(&msg_ptr, ¬ification->notification_ind); - Description: Sent by the UE to the network in response to an ESM - INFORMATION REQUEST message and provides the - requested ESM information. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 8.3.14 -*********************************************************************/ -// FIXME + return(err); +} /********************************************************************* - Message Name: ESM Status + Message Name: PDN Connectivity Reject - Description: Sent by the network or the UE to pass information on - the status of the indicated EPS bearer context and - report certain error conditions. + Description: Sent by the network to the UE to reject establishment + of a PDN connection. - Document Reference: 24.301 v10.2.0 Section 8.3.15 + Document Reference: 24.301 v10.2.0 Section 8.3.19 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_connectivity_reject_msg(LIBLTE_MME_PDN_CONNECTIVITY_REJECT_MSG_STRUCT *pdn_con_rej, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; -/********************************************************************* - Message Name: Modify EPS Bearer Context Accept + if(pdn_con_rej != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (pdn_con_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; - Description: Sent by the UE to the network to acknowledge the - modification of an active EPS bearer context. + // Procedure Transaction ID + *msg_ptr = pdn_con_rej->proc_transaction_id; + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.3.16 -*********************************************************************/ -// FIXME + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_PDN_CONNECTIVITY_REJECT; + msg_ptr++; -/********************************************************************* - Message Name: Modify EPS Bearer Context Reject + // ESM Cause + liblte_mme_pack_esm_cause_ie(pdn_con_rej->esm_cause, &msg_ptr); - Description: Sent by the UE or the network to reject a - modification of an active EPS bearer context. + // Protocol Configuration Options + if(pdn_con_rej->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&pdn_con_rej->protocol_cnfg_opts, &msg_ptr); + } - Document Reference: 24.301 v10.2.0 Section 8.3.17 -*********************************************************************/ -// FIXME + // T3496 Value + if(pdn_con_rej->t3496_present) + { + *msg_ptr = LIBLTE_MME_T3496_VALUE_IEI; + msg_ptr++; + liblte_mme_pack_gprs_timer_3_ie(&pdn_con_rej->t3496, &msg_ptr); + } -/********************************************************************* - Message Name: Modify EPS Bearer Context Request + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; - Description: Sent by the network to the UE to request modification - of an active EPS bearer context. + err = LIBLTE_SUCCESS; + } - Document Reference: 24.301 v10.2.0 Section 8.3.18 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_connectivity_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_PDN_CONNECTIVITY_REJECT_MSG_STRUCT *pdn_con_rej) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; -/********************************************************************* - Message Name: Notification + if(msg != NULL && + pdn_con_rej != NULL) + { + // EPS Bearer ID + pdn_con_rej->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; - Description: Sent by the network to inform the UE about events - which are relevant for the upper layer using an EPS - bearer context or having requested a procedure - transaction. + // Procedure Transaction ID + pdn_con_rej->proc_transaction_id = *msg_ptr; + msg_ptr++; - Document Reference: 24.301 v10.2.0 Section 8.3.18A -*********************************************************************/ -// FIXME + // Skip Message Type + msg_ptr++; -/********************************************************************* - Message Name: PDN Connectivity Reject + // ESM Cause + liblte_mme_unpack_esm_cause_ie(&msg_ptr, &pdn_con_rej->esm_cause); - Description: Sent by the network to the UE to reject establishment - of a PDN connection. + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &pdn_con_rej->protocol_cnfg_opts); + pdn_con_rej->protocol_cnfg_opts_present = true; + }else{ + pdn_con_rej->protocol_cnfg_opts_present = false; + } - Document Reference: 24.301 v10.2.0 Section 8.3.19 -*********************************************************************/ -// FIXME + // T3496 Value + if(LIBLTE_MME_T3496_VALUE_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_gprs_timer_3_ie(&msg_ptr, &pdn_con_rej->t3496); + pdn_con_rej->t3496_present = true; + }else{ + pdn_con_rej->t3496_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* Message Name: PDN Connectivity Request @@ -2929,7 +12142,7 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_connectivity_request_msg(LIBLTE_MME_PDN_CO // Protocol Configuration Options if(pdn_con_req->protocol_cnfg_opts_present) { - *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_IEI; + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; msg_ptr++; liblte_mme_pack_protocol_config_options_ie(&pdn_con_req->protocol_cnfg_opts, &msg_ptr); } @@ -2942,6 +12155,9 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_connectivity_request_msg(LIBLTE_MME_PDN_CO msg_ptr++; } + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + err = LIBLTE_SUCCESS; } @@ -2993,7 +12209,7 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_connectivity_request_msg(LIBLTE_BYTE_MSG } // Protocol Configuration Options - if(LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_IEI == *msg_ptr) + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) { msg_ptr++; liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &pdn_con_req->protocol_cnfg_opts); @@ -3026,7 +12242,84 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_connectivity_request_msg(LIBLTE_BYTE_MSG Document Reference: 24.301 v10.2.0 Section 8.3.21 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_disconnect_reject_msg(LIBLTE_MME_PDN_DISCONNECT_REJECT_MSG_STRUCT *pdn_discon_rej, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(pdn_discon_rej != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (pdn_discon_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = pdn_discon_rej->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_PDN_DISCONNECT_REJECT; + msg_ptr++; + + // ESM Cause + liblte_mme_pack_esm_cause_ie(pdn_discon_rej->esm_cause, &msg_ptr); + + // Protocol Configuration Options + if(pdn_discon_rej->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&pdn_discon_rej->protocol_cnfg_opts, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_disconnect_reject_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_PDN_DISCONNECT_REJECT_MSG_STRUCT *pdn_discon_rej) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + pdn_discon_rej != NULL) + { + // EPS Bearer ID + pdn_discon_rej->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + pdn_discon_rej->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // ESM Cause + liblte_mme_unpack_esm_cause_ie(&msg_ptr, &pdn_discon_rej->esm_cause); + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &pdn_discon_rej->protocol_cnfg_opts); + pdn_discon_rej->protocol_cnfg_opts_present = true; + }else{ + pdn_discon_rej->protocol_cnfg_opts_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* Message Name: PDN Disconnect Request @@ -3036,8 +12329,84 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_connectivity_request_msg(LIBLTE_BYTE_MSG Document Reference: 24.301 v10.2.0 Section 8.3.22 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_disconnect_request_msg(LIBLTE_MME_PDN_DISCONNECT_REQUEST_MSG_STRUCT *pdn_discon_req, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; -/******************************************************************************* - LOCAL FUNCTIONS -*******************************************************************************/ + if(pdn_discon_req != NULL && + msg != NULL) + { + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (pdn_discon_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = pdn_discon_req->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_PDN_DISCONNECT_REQUEST; + msg_ptr++; + + // Linked EPS Bearer Identity & Spare Half Octet + *msg_ptr = 0; + liblte_mme_pack_linked_eps_bearer_identity_ie(pdn_discon_req->linked_eps_bearer_id, 0, &msg_ptr); + msg_ptr++; + + // Protocol Configuration Options + if(pdn_discon_req->protocol_cnfg_opts_present) + { + *msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + msg_ptr++; + liblte_mme_pack_protocol_config_options_ie(&pdn_discon_req->protocol_cnfg_opts, &msg_ptr); + } + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_disconnect_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_PDN_DISCONNECT_REQUEST_MSG_STRUCT *pdn_discon_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + pdn_discon_req != NULL) + { + // EPS Bearer ID + pdn_discon_req->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + pdn_discon_req->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // Linked EPS Bearer Identity & Spare Half Octet + liblte_mme_unpack_linked_eps_bearer_identity_ie(&msg_ptr, 0, &pdn_discon_req->linked_eps_bearer_id); + msg_ptr++; + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &pdn_discon_req->protocol_cnfg_opts); + pdn_discon_req->protocol_cnfg_opts_present = true; + }else{ + pdn_discon_req->protocol_cnfg_opts_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} diff --git a/liblte/src/liblte_pdcp.cc b/liblte/src/liblte_pdcp.cc new file mode 100755 index 0000000..2c64bad --- /dev/null +++ b/liblte/src/liblte_pdcp.cc @@ -0,0 +1,503 @@ +/******************************************************************************* + + Copyright 2014-2015 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: liblte_pdcp.cc + + Description: Contains all the implementations for the LTE Packet Data + Convergence Protocol Layer library. + + Revision History + ---------- ------------- -------------------------------------------- + 08/03/2014 Ben Wojtowicz Created file. + 11/01/2014 Ben Wojtowicz Added integrity protection of messages. + 11/29/2014 Ben Wojtowicz Using the byte message struct for everything + except RRC SDUs and added user plane data + processing. + 03/11/2015 Ben Wojtowicz Added data PDU with short SN support. + 12/06/2015 Ben Wojtowicz Added control PDU for interspersed ROHC + feedback and RN user plane data PDU with + integrity protection support. + +*******************************************************************************/ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "liblte_pdcp.h" +#include "liblte_security.h" + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + GLOBAL VARIABLES +*******************************************************************************/ + + +/******************************************************************************* + PDU FUNCTIONS +*******************************************************************************/ + +/********************************************************************* + PDU Type: Control Plane PDCP Data PDU + + Document Reference: 36.323 v10.1.0 Section 6.2.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu(LIBLTE_PDCP_CONTROL_PDU_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + return(liblte_pdcp_pack_control_pdu(contents, &contents->data, pdu)); +} +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu(LIBLTE_PDCP_CONTROL_PDU_STRUCT *contents, + LIBLTE_BIT_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + return(liblte_pdcp_pack_control_pdu(contents, data, NULL, 0, 0, pdu)); +} +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu(LIBLTE_PDCP_CONTROL_PDU_STRUCT *contents, + uint8 *key_256, + uint8 direction, + uint8 rb_id, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + return(liblte_pdcp_pack_control_pdu(contents, &contents->data, key_256, direction, rb_id, pdu)); +} +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu(LIBLTE_PDCP_CONTROL_PDU_STRUCT *contents, + LIBLTE_BIT_MSG_STRUCT *data, + uint8 *key_256, + uint8 direction, + uint8 rb_id, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + uint8 *data_ptr; + uint32 i; + + if(contents != NULL && + data != NULL && + pdu != NULL) + { + // Header + *pdu_ptr = contents->count & 0x1F; + pdu_ptr++; + + // Byte align data + if((data->N_bits % 8) != 0) + { + for(i=0; i<8-(data->N_bits % 8); i++) + { + data->msg[data->N_bits + i] = 0; + } + data->N_bits += 8 - (data->N_bits % 8); + } + + // Data + data_ptr = data->msg; + for(i=0; iN_bits/8; i++) + { + *pdu_ptr = liblte_bits_2_value(&data_ptr, 8); + pdu_ptr++; + } + + // MAC + if(NULL == key_256) + { + *pdu_ptr = (LIBLTE_PDCP_CONTROL_MAC_I >> 24) & 0xFF; + pdu_ptr++; + *pdu_ptr = (LIBLTE_PDCP_CONTROL_MAC_I >> 16) & 0xFF; + pdu_ptr++; + *pdu_ptr = (LIBLTE_PDCP_CONTROL_MAC_I >> 8) & 0xFF; + pdu_ptr++; + *pdu_ptr = LIBLTE_PDCP_CONTROL_MAC_I & 0xFF; + pdu_ptr++; + }else{ + pdu->N_bytes = pdu_ptr - pdu->msg; + liblte_security_128_eia2(&key_256[16], + contents->count, + rb_id, + direction, + pdu->msg, + pdu->N_bytes, + pdu_ptr); + pdu_ptr += 4; + } + + // Fill in the number of bytes used + pdu->N_bytes = pdu_ptr - pdu->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_pdcp_unpack_control_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_PDCP_CONTROL_PDU_STRUCT *contents) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + uint8 *data_ptr; + uint32 i; + + if(pdu != NULL && + contents != NULL) + { + // Header + contents->count = *pdu_ptr & 0x1F; + pdu_ptr++; + + // Data + data_ptr = contents->data.msg; + for(i=0; iN_bytes-5; i++) + { + liblte_value_2_bits(*pdu_ptr, &data_ptr, 8); + pdu_ptr++; + } + contents->data.N_bits = data_ptr - contents->data.msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + PDU Type: User Plane PDCP Data PDU with long PDCP SN + + Document Reference: 36.323 v10.1.0 Section 6.2.3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_pdcp_pack_data_pdu_with_long_sn(LIBLTE_PDCP_DATA_PDU_WITH_LONG_SN_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + return(liblte_pdcp_pack_data_pdu_with_long_sn(contents, &contents->data, pdu)); +} +LIBLTE_ERROR_ENUM liblte_pdcp_pack_data_pdu_with_long_sn(LIBLTE_PDCP_DATA_PDU_WITH_LONG_SN_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + + if(contents != NULL && + data != NULL && + pdu != NULL) + { + // Header + *pdu_ptr = (LIBLTE_PDCP_D_C_DATA_PDU << 7) | ((contents->count >> 8) & 0x0F); + pdu_ptr++; + *pdu_ptr = contents->count & 0xFF; + pdu_ptr++; + + // Data + memcpy(pdu_ptr, data->msg, data->N_bytes); + pdu_ptr += data->N_bytes; + + // Fill in the number of bytes used + pdu->N_bytes = pdu_ptr - pdu->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_pdcp_unpack_data_pdu_with_long_sn(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_PDCP_DATA_PDU_WITH_LONG_SN_STRUCT *contents) +{ + LIBLTE_PDCP_D_C_ENUM d_c; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + + if(pdu != NULL && + contents != NULL) + { + // Header + d_c = (LIBLTE_PDCP_D_C_ENUM)((*pdu_ptr >> 7) & 0x01); + if(LIBLTE_PDCP_D_C_DATA_PDU == d_c) + { + contents->count = (*pdu_ptr & 0x0F) << 8; + pdu_ptr++; + contents->count |= *pdu_ptr; + pdu_ptr++; + + // Data + memcpy(contents->data.msg, pdu_ptr, pdu->N_bytes-2); + contents->data.N_bytes = pdu->N_bytes-2; + + err = LIBLTE_SUCCESS; + } + } + + return(err); +} + +/********************************************************************* + PDU Type: User Plane PDCP Data PDU with short PDCP SN + + Document Reference: 36.323 v10.1.0 Section 6.2.4 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_pdcp_pack_data_pdu_with_short_sn(LIBLTE_PDCP_DATA_PDU_WITH_SHORT_SN_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + return(liblte_pdcp_pack_data_pdu_with_short_sn(contents, &contents->data, pdu)); +} +LIBLTE_ERROR_ENUM liblte_pdcp_pack_data_pdu_with_short_sn(LIBLTE_PDCP_DATA_PDU_WITH_SHORT_SN_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + + if(contents != NULL && + data != NULL && + pdu != NULL) + { + // Header + *pdu_ptr = (LIBLTE_PDCP_D_C_DATA_PDU << 7) | (contents->count & 0x7F); + pdu_ptr++; + + // Data + memcpy(pdu_ptr, data->msg, data->N_bytes); + pdu_ptr += data->N_bytes; + + // Fill in the number of bytes used + pdu->N_bytes = pdu_ptr - pdu->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_pdcp_unpack_data_pdu_with_short_sn(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_PDCP_DATA_PDU_WITH_SHORT_SN_STRUCT *contents) +{ + LIBLTE_PDCP_D_C_ENUM d_c; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + + if(pdu != NULL && + contents != NULL) + { + // Header + d_c = (LIBLTE_PDCP_D_C_ENUM)((*pdu_ptr >> 7) & 0x01); + if(LIBLTE_PDCP_D_C_DATA_PDU == d_c) + { + contents->count = *pdu_ptr & 0x7F; + pdu_ptr++; + + // Data + memcpy(contents->data.msg, pdu_ptr, pdu->N_bytes-2); + contents->data.N_bytes = pdu->N_bytes-2; + + err = LIBLTE_SUCCESS; + } + } + + return(err); +} + +/********************************************************************* + PDU Type: PDCP Control PDU for interspersed ROHC feedback packet + + Document Reference: 36.323 v10.1.0 Section 6.2.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu_for_interspersed_rohc_feedback(LIBLTE_PDCP_CONTROL_PDU_FOR_INTERSPERSED_ROHC_FEEDBACK_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + return(liblte_pdcp_pack_control_pdu_for_interspersed_rohc_feedback(contents, &contents->rohc_feedback_packet, pdu)); +} +LIBLTE_ERROR_ENUM liblte_pdcp_pack_control_pdu_for_interspersed_rohc_feedback(LIBLTE_PDCP_CONTROL_PDU_FOR_INTERSPERSED_ROHC_FEEDBACK_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *rohc_feedback_packet, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + + if(contents != NULL && + rohc_feedback_packet != NULL && + pdu != NULL) + { + // Header + *pdu_ptr = (LIBLTE_PDCP_D_C_CONTROL_PDU << 7) | ((contents->pdu_type << 4) & 0x70); + pdu_ptr++; + + // Interspersed ROHC feedback packet + memcpy(pdu_ptr, rohc_feedback_packet->msg, rohc_feedback_packet->N_bytes); + pdu_ptr += rohc_feedback_packet->N_bytes; + + // Fill in the number of bytes used + pdu->N_bytes = pdu_ptr - pdu->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_pdcp_unpack_control_pdu_for_interspersed_rohc_feedback(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_PDCP_CONTROL_PDU_FOR_INTERSPERSED_ROHC_FEEDBACK_STRUCT *contents) +{ + LIBLTE_PDCP_D_C_ENUM d_c; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + + if(pdu != NULL && + contents != NULL) + { + // Header + d_c = (LIBLTE_PDCP_D_C_ENUM)((*pdu_ptr >> 7) & 0x01); + if(LIBLTE_PDCP_D_C_CONTROL_PDU == d_c) + { + contents->pdu_type = (*pdu_ptr >> 4) & 0x03; + pdu_ptr++; + + // Interspersed ROHC feedback packet + memcpy(contents->rohc_feedback_packet.msg, pdu_ptr, pdu->N_bytes-1); + contents->rohc_feedback_packet.N_bytes = pdu->N_bytes-1; + + err = LIBLTE_SUCCESS; + } + } + + return(err); +} + +/********************************************************************* + PDU Type: PDCP Control PDU for PDCP status report + + Document Reference: 36.323 v10.1.0 Section 6.2.6 +*********************************************************************/ +// FIXME + +/********************************************************************* + PDU Type: RN User Plane PDCP Data PDU with integrity protection + + Document Reference: 36.323 v10.1.0 Section 6.2.8 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_pdcp_pack_rn_user_plane_data_pdu(LIBLTE_PDCP_RN_USER_PLANE_DATA_PDU_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + return(liblte_pdcp_pack_rn_user_plane_data_pdu(contents, &contents->data, pdu)); +} +LIBLTE_ERROR_ENUM liblte_pdcp_pack_rn_user_plane_data_pdu(LIBLTE_PDCP_RN_USER_PLANE_DATA_PDU_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + return(liblte_pdcp_pack_rn_user_plane_data_pdu(contents, data, NULL, 0, 0, pdu)); +} +LIBLTE_ERROR_ENUM liblte_pdcp_pack_rn_user_plane_data_pdu(LIBLTE_PDCP_RN_USER_PLANE_DATA_PDU_STRUCT *contents, + uint8 *key_256, + uint8 direction, + uint8 rb_id, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + return(liblte_pdcp_pack_rn_user_plane_data_pdu(contents, &contents->data, key_256, direction, rb_id, pdu)); +} +LIBLTE_ERROR_ENUM liblte_pdcp_pack_rn_user_plane_data_pdu(LIBLTE_PDCP_RN_USER_PLANE_DATA_PDU_STRUCT *contents, + LIBLTE_BYTE_MSG_STRUCT *data, + uint8 *key_256, + uint8 direction, + uint8 rb_id, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + uint32 i; + + if(contents != NULL && + data != NULL && + pdu != NULL) + { + // Header + *pdu_ptr = (LIBLTE_PDCP_D_C_DATA_PDU << 7) | ((contents->count >> 8) & 0x0F); + pdu_ptr++; + *pdu_ptr = contents->count & 0xFF; + pdu_ptr++; + + // Data + memcpy(pdu_ptr, data->msg, data->N_bytes); + pdu_ptr += data->N_bytes; + + // MAC + if(NULL == key_256) + { + *pdu_ptr = (LIBLTE_PDCP_CONTROL_MAC_I >> 24) & 0xFF; + pdu_ptr++; + *pdu_ptr = (LIBLTE_PDCP_CONTROL_MAC_I >> 16) & 0xFF; + pdu_ptr++; + *pdu_ptr = (LIBLTE_PDCP_CONTROL_MAC_I >> 8) & 0xFF; + pdu_ptr++; + *pdu_ptr = LIBLTE_PDCP_CONTROL_MAC_I & 0xFF; + pdu_ptr++; + }else{ + pdu->N_bytes = pdu_ptr - pdu->msg; + liblte_security_128_eia2(&key_256[16], + contents->count, + rb_id, + direction, + pdu->msg, + pdu->N_bytes, + pdu_ptr); + pdu_ptr += 4; + } + + // Fill in the number of bytes used + pdu->N_bytes = pdu_ptr - pdu->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_pdcp_unpack_rn_user_plane_data_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_PDCP_RN_USER_PLANE_DATA_PDU_STRUCT *contents) +{ + LIBLTE_PDCP_D_C_ENUM d_c; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + uint32 i; + + if(pdu != NULL && + contents != NULL) + { + // Header + d_c = (LIBLTE_PDCP_D_C_ENUM)((*pdu_ptr >> 7) & 0x01); + if(LIBLTE_PDCP_D_C_DATA_PDU == d_c) + { + contents->count = (*pdu_ptr & 0x0F) << 8; + pdu_ptr++; + contents->count |= *pdu_ptr; + pdu_ptr++; + + // Data + memcpy(contents->data.msg, pdu_ptr, pdu->N_bytes-2); + contents->data.N_bytes = pdu->N_bytes-2; + + err = LIBLTE_SUCCESS; + } + } + + return(err); +} diff --git a/liblte/src/liblte_phy.cc b/liblte/src/liblte_phy.cc old mode 100644 new mode 100755 index 3a9820b..7ad73ef --- a/liblte/src/liblte_phy.cc +++ b/liblte/src/liblte_phy.cc @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2012-2014 Ben Wojtowicz + Copyright 2012-2017 Ben Wojtowicz Copyright 2014 Andrew Murphy (DCI 1C Unpack) This program is free software: you can redistribute it and/or modify @@ -95,6 +95,42 @@ PDCCH encode/decode. 06/15/2014 Ben Wojtowicz Added DCI 0 packing and proper support for transmission of more than one CCE in PDCCH. + 07/22/2014 Ben Wojtowicz Pulled in a patch from Mike Peters to fix + an uninitialized N_bits value. + 08/03/2014 Ben Wojtowicz Using the common value_2_bits and + bits_2_value functions. + 11/29/2014 Ben Wojtowicz Using the common liblte_value_2_bits and + liblte_bits_2_value functions. + 12/24/2014 Ben Wojtowicz Added C-RNTI support to + get_tbs_mcs_and_N_prb_for_dl. + 02/15/2015 Ben Wojtowicz Properly handling modulation schemes and + added 16QAM and 64QAM demapping. + 03/11/2015 Ben Wojtowicz Fixed I_tbs to mcs conversion for PUSCH. + 07/25/2015 Ben Wojtowicz Added an error return for dci_1a_unpack + (thanks to Joel Carlson for the suggestion), + properly initializing vd_w_metric (thanks + ziminghe for finding this), an changed the + upper limit of PUSCH allocations to 10 PRBs + for performance reasons. + 12/06/2015 Ben Wojtowicz Added a return to liblte_phy_get_n_cce, + thanks to Damian Jarek for reporting this. + 02/13/2016 Ben Wojtowicz Moved turbo coder rate match/unmatch and + code block segmentation/desegmentation to + globally available routines to support unit + tests and incorporated changes from Ziming + He for better PBCH detection. + 03/12/2016 Ben Wojtowicz Added PUCCH channel decode support. + 03/26/2016 Ben Wojtowicz Fixed the calculation of n_prime_p in + generate_dmrs_pucch. + 07/03/2016 Ben Wojtowicz Added an error return to dci_1c_unpack, using + new PDCCH size defines, and clearing + punctured turbo decode bits before decoding. + 12/18/2016 Ben Wojtowicz Fixed turbo encode tail bits (thanks to + Laurent Louf and Jeremy Quirke). + 07/29/2017 Ben Wojtowicz Added two codeword support, refactored PUCCH + channel decoding for PUCCH types, 1, 1A, and + 1B, and added a function to map SR + configuration index. *******************************************************************************/ @@ -121,6 +157,11 @@ GLOBAL VARIABLES *******************************************************************************/ +// Orthogonal sequences for PUCCH from 3GPP TS 36.211 v10.1.0 table 5.4.1-2 +int32 W_5_4_1_2[3][4] = {{ 1, 1, 1, 1}, + { 1, -1, 1, -1}, + { 1, -1, -1, 1}}; + // UL reference signal phi value for M_sc_rs = N_sc_rb_ul from 3GPP TS 36.211 v10.1.0 table 5.5.1.2-1 int32 UL_RS_5_5_1_2_1[30][12] = {{-1, 1, 3,-3, 3, 3, 1, 1, 3, 1,-3, 3}, { 1, 1, 3, 3, 3,-1, 1,-3,-3, 1,-3, 3}, @@ -242,6 +283,11 @@ int32 W_1_5_5_2_1_1_1[8][4] = {{ 1, 1,-1,-1}, // N_1_DMRS table from 3GPP TS 36.211 v10.1.0 table 5.5.2.1.1-2 uint32 N_1_DMRS_5_5_2_1_1_2[8] = {0,2,3,4,6,8,9,10}; +// W table from 3GPP TS 36.211 v10.1.0 table 5.5.2.2.1-2 +float W_5_5_2_2_1_2_phase[3][3] = {{0, 0, 0}, + {0, 2*M_PI/3, 4*M_PI/3}, + {0, 4*M_PI/3, 2*M_PI/3}}; + // PRACH N_cs unrestricted set values from 3GPP TS 36.211 v10.1.0 table 5.7.2-2 uint32 PRACH_5_7_2_2_URS[16] = {0,13,15,18,22,26,32,38,46,59,76,93,119,167,279,419}; @@ -895,6 +941,33 @@ void generate_dmrs_pusch(LIBLTE_PHY_STRUCT *phy_struct, float *dmrs_1_re, float *dmrs_1_im); +/********************************************************************* + Name: generate_dmrs_pucch + + Description: Generates demodulation reference signals for the + uplink control channel + + Document Reference: 3GPP TS 36.211 v10.1.0 section 5.5.2 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void generate_dmrs_pucch(LIBLTE_PHY_STRUCT *phy_struct, + uint32 N_subfr, + uint32 N_id_cell, + uint32 delta_ss, + bool group_hopping_enabled, + bool sequence_hopping_enabled, + uint8 N_cs_1, + uint8 N_1_p_pucch, + uint8 delta_pucch_shift, + uint8 N_ant, + float *dmrs_0_re, + float *dmrs_0_im, + float *dmrs_1_re, + float *dmrs_1_im); + /********************************************************************* Name: prach_preamble_seq_gen @@ -1044,7 +1117,8 @@ void pcfich_channel_demap(LIBLTE_PHY_STRUCT *phy_struct, LIBLTE_PHY_SUBFRAME_STRUCT *subframe, uint32 N_id_cell, uint8 N_ant, - LIBLTE_PHY_PCFICH_STRUCT *pcfich); + LIBLTE_PHY_PCFICH_STRUCT *pcfich, + uint32 *N_bits); /********************************************************************* Name: pdcch_permute_pre_calc @@ -1312,45 +1386,6 @@ void calc_crc(uint8 *a_bits, uint8 *p_bits, uint32 N_p_bits); -/********************************************************************* - Name: code_block_segmentation - - Description: Performs code block segmentation for turbo coded - channels - - Document Reference: 3GPP TS 36.212 v10.1.0 section 5.1.2 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void code_block_segmentation(uint8 *b_bits, - uint32 N_b_bits, - uint32 *N_codeblocks, - uint32 *N_filler_bits, - uint8 *c_bits, - uint32 N_c_bits_max, - uint32 *N_c_bits); - -/********************************************************************* - Name: code_block_desegmentation - - Description: Performs code block desegmentation for turbo coded - channels - - Document Reference: 3GPP TS 36.212 v10.1.0 section 5.1.2 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void code_block_desegmentation(uint8 *c_bits, - uint32 *N_c_bits, - uint32 N_c_bits_max, - uint32 tbs, - uint8 *b_bits, - uint32 N_b_bits); - /********************************************************************* Name: conv_encode @@ -1557,54 +1592,6 @@ void turbo_internal_deinterleaver(int8 *in_bits, uint32 N_in_bits, int8 *out_bits); -/********************************************************************* - Name: rate_match_turbo - - Description: Rate matches turbo encoded data - - Document Reference: 3GPP TS 36.212 v10.1.0 section 5.1.4.1 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void rate_match_turbo(LIBLTE_PHY_STRUCT *phy_struct, - uint8 *d_bits, - uint32 N_d_bits, - uint32 N_codeblocks, - uint32 tx_mode, - uint32 N_soft, - uint32 M_dl_harq, - LIBLTE_PHY_CHAN_TYPE_ENUM chan_type, - uint32 rv_idx, - uint32 N_e_bits, - uint8 *e_bits); - -/********************************************************************* - Name: rate_unmatch_turbo - - Description: Rate unmatches turbo encoded data - - Document Reference: 3GPP TS 36.212 v10.1.0 section 5.1.4.1 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void rate_unmatch_turbo(LIBLTE_PHY_STRUCT *phy_struct, - float *e_bits, - uint32 N_e_bits, - uint8 *dummy_bits, - uint32 N_dummy_bits, - uint32 N_codeblocks, - uint32 tx_mode, - uint32 N_soft, - uint32 M_dl_harq, - LIBLTE_PHY_CHAN_TYPE_ENUM chan_type, - uint32 rv_idx, - float *d_bits, - uint32 *N_d_bits); - /********************************************************************* Name: rate_match_conv @@ -1852,7 +1839,7 @@ void bch_channel_encode(LIBLTE_PHY_STRUCT *phy_struct, LIBLTE_ERROR_ENUM bch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, float *in_bits, uint32 N_in_bits, - uint8 *N_ant, + uint8 N_ant, uint8 *out_bits, uint32 *N_out_bits); @@ -2031,13 +2018,13 @@ void dci_1a_pack(LIBLTE_PHY_ALLOCATION_STRUCT *alloc, // Enums // Structs // Functions -void dci_1a_unpack(uint8 *in_bits, - uint32 N_in_bits, - LIBLTE_PHY_DCI_CA_PRESENCE_ENUM ca_presence, - uint16 rnti, - uint32 N_rb_dl, - uint8 N_ant, - LIBLTE_PHY_ALLOCATION_STRUCT *alloc); +LIBLTE_ERROR_ENUM dci_1a_unpack(uint8 *in_bits, + uint32 N_in_bits, + LIBLTE_PHY_DCI_CA_PRESENCE_ENUM ca_presence, + uint16 rnti, + uint32 N_rb_dl, + uint8 N_ant, + LIBLTE_PHY_ALLOCATION_STRUCT *alloc); /********************************************************************* Name: dci_1c_pack @@ -2071,12 +2058,12 @@ void dci_1a_unpack(uint8 *in_bits, // Enums // Structs // Functions -void dci_1c_unpack(uint8 *in_bits, - uint32 N_in_bits, - uint16 rnti, - uint32 N_rb_dl, - uint8 N_ant, - LIBLTE_PHY_ALLOCATION_STRUCT *alloc); +LIBLTE_ERROR_ENUM dci_1c_unpack(uint8 *in_bits, + uint32 N_in_bits, + uint16 rnti, + uint32 N_rb_dl, + uint8 N_ant, + LIBLTE_PHY_ALLOCATION_STRUCT *alloc); /********************************************************************* Name: cfi_channel_encode @@ -2112,9 +2099,10 @@ LIBLTE_ERROR_ENUM cfi_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, uint32 *cfi); /********************************************************************* - Name: get_ul_ce + Name: get_ulsch_ce - Description: Resolves channel estimates for the uplink + Description: Resolves channel estimates for the uplink shared + channel Document Reference: N/A *********************************************************************/ @@ -2122,15 +2110,37 @@ LIBLTE_ERROR_ENUM cfi_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, // Enums // Structs // Functions -void get_ul_ce(LIBLTE_PHY_STRUCT *phy_struct, - float *c_est_0_re, - float *c_est_0_im, - float *c_est_1_re, - float *c_est_1_im, - uint32 N_prb, - uint32 N_subfr, - float *c_est_re, - float *c_est_im); +void get_ulsch_ce(LIBLTE_PHY_STRUCT *phy_struct, + float *c_est_0_re, + float *c_est_0_im, + float *c_est_1_re, + float *c_est_1_im, + uint32 N_prb, + uint32 N_subfr, + float *c_est_re, + float *c_est_im); + +/********************************************************************* + Name: get_ulcch_ce + + Description: Resolves channel estimates for the uplink control + channel + + Document Reference: N/A +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void get_ulcch_ce(LIBLTE_PHY_STRUCT *phy_struct, + float *c_est_0_re, + float *c_est_0_im, + float *c_est_1_re, + float *c_est_1_im, + uint32 N_subfr, + uint32 N_1_p_pucch, + float *c_est_re, + float *c_est_im); /********************************************************************* Name: get_soft_decision @@ -2171,35 +2181,6 @@ uint32 get_num_bits_in_prb(uint32 N_subframe, uint8 N_ant, LIBLTE_PHY_MODULATION_TYPE_ENUM mod_type); -/********************************************************************* - Name: phy_value_2_bits - - Description: Converts a value to a bit string - - Document Reference: N/A -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void phy_value_2_bits(uint32 value, - uint8 **bits, - uint32 N_bits); - -/********************************************************************* - Name: phy_bits_2_value - - Description: Converts a bit string to a value - - Document Reference: N/A -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -uint32 phy_bits_2_value(uint8 **bits, - uint32 N_bits); - /********************************************************************* Name: wrap_phase @@ -2294,6 +2275,7 @@ LIBLTE_ERROR_ENUM liblte_phy_init(LIBLTE_PHY_STRUCT **phy_struct, (*phy_struct)->N_sc_rb_dl = N_sc_rb_dl; (*phy_struct)->N_sc_rb_ul = LIBLTE_PHY_N_SC_RB_UL; liblte_phy_update_n_rb_dl((*phy_struct), N_rb_dl); + (*phy_struct)->N_ant = N_ant; (*phy_struct)->ul_init = false; // PHICH @@ -2362,7 +2344,9 @@ LIBLTE_ERROR_ENUM liblte_phy_ul_init(LIBLTE_PHY_STRUCT *phy_struct, bool group_hopping_enabled, bool sequence_hopping_enabled, uint8 cyclic_shift, - uint8 cyclic_shift_dci) + uint8 cyclic_shift_dci, + uint8 N_cs_an, + uint8 delta_pucch_shift) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; @@ -2392,7 +2376,7 @@ LIBLTE_ERROR_ENUM liblte_phy_ul_init(LIBLTE_PHY_STRUCT *phy_struct, } } - // DMRS + // PUSCH DMRS for(i=0; idmrs_0_re[i][j], - phy_struct->dmrs_0_im[i][j], - phy_struct->dmrs_1_re[i][j], - phy_struct->dmrs_1_im[i][j]); + phy_struct->pusch_dmrs_0_re[i][j], + phy_struct->pusch_dmrs_0_im[i][j], + phy_struct->pusch_dmrs_1_re[i][j], + phy_struct->pusch_dmrs_1_im[i][j]); + } + } + + // PUCCH DMRS + for(i=0; iN_ant, + phy_struct->pucch_dmrs_0_re[i][j], + phy_struct->pucch_dmrs_0_im[i][j], + phy_struct->pucch_dmrs_1_re[i][j], + phy_struct->pucch_dmrs_1_im[i][j]); } } @@ -2694,8 +2700,8 @@ LIBLTE_ERROR_ENUM liblte_phy_pusch_channel_encode(LIBLTE_PHY_STRUCT * // Encode the PUSCH ulsch_channel_encode(phy_struct, - alloc->msg.msg, - alloc->msg.N_bits, + alloc->msg[0].msg, + alloc->msg[0].N_bits, alloc->tbs, alloc->tx_mode, alloc->N_prb*phy_struct->N_sc_rb_ul*(N_ul_symb-1)*2, @@ -2754,15 +2760,15 @@ LIBLTE_ERROR_ENUM liblte_phy_pusch_channel_encode(LIBLTE_PHY_STRUCT * // DMRS 0 for(j=0; jtx_symb_re[p][L][j] = phy_struct->dmrs_0_re[subframe->num][alloc->N_prb][j]; - subframe->tx_symb_im[p][L][j] = phy_struct->dmrs_0_im[subframe->num][alloc->N_prb][j]; + subframe->tx_symb_re[p][L][j] = phy_struct->pusch_dmrs_0_re[subframe->num][alloc->N_prb][j]; + subframe->tx_symb_im[p][L][j] = phy_struct->pusch_dmrs_0_im[subframe->num][alloc->N_prb][j]; } }else if(10 == L){ // DMRS 1 for(j=0; jtx_symb_re[p][L][j] = phy_struct->dmrs_1_re[subframe->num][alloc->N_prb][j]; - subframe->tx_symb_im[p][L][j] = phy_struct->dmrs_1_im[subframe->num][alloc->N_prb][j]; + subframe->tx_symb_re[p][L][j] = phy_struct->pusch_dmrs_1_re[subframe->num][alloc->N_prb][j]; + subframe->tx_symb_im[p][L][j] = phy_struct->pusch_dmrs_1_im[subframe->num][alloc->N_prb][j]; } }else{ // PUSCH @@ -2851,15 +2857,15 @@ LIBLTE_ERROR_ENUM liblte_phy_pusch_channel_decode(LIBLTE_PHY_STRUCT * } } } - get_ul_ce(phy_struct, - phy_struct->pusch_c_est_0_re, - phy_struct->pusch_c_est_0_im, - phy_struct->pusch_c_est_1_re, - phy_struct->pusch_c_est_1_im, - alloc->N_prb, - subframe->num, - phy_struct->pusch_c_est_re, - phy_struct->pusch_c_est_im); + get_ulsch_ce(phy_struct, + phy_struct->pusch_c_est_0_re, + phy_struct->pusch_c_est_0_im, + phy_struct->pusch_c_est_1_re, + phy_struct->pusch_c_est_1_im, + alloc->N_prb, + subframe->num, + phy_struct->pusch_c_est_re, + phy_struct->pusch_c_est_im); pre_decoder_and_matched_filter_ul(phy_struct->pusch_z_est_re, phy_struct->pusch_z_est_im, phy_struct->pusch_c_est_re, @@ -2928,6 +2934,281 @@ LIBLTE_ERROR_ENUM liblte_phy_pusch_channel_decode(LIBLTE_PHY_STRUCT * return(err); } +/********************************************************************* + Name: liblte_phy_pucch_format_1_1a_1b_channel_encode + + Description: Encodes and modulates the Physical Uplink Control + Channel for formats 1, 1a, and 1b + + Document Reference: 3GPP TS 36.211 v10.1.0 section 5.4.1 + 3GPP TS 36.212 v10.1.0 section 5.2.3 + + Notes: Only handling normal CP and N_ant=1 +*********************************************************************/ +// FIXME + +/********************************************************************* + Name: liblte_phy_pucch_format_1_1a_1b_channel_decode + + Description: Demodulates and decodes the Physical Uplink Control + Channel for formats 1, 1a, and 1b + + Document Reference: 3GPP TS 36.211 v10.1.0 section 5.4.1 + 3GPP TS 36.212 v10.1.0 section 5.2.3 + + Notes: Only handling normal CP and N_ant=1 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_phy_pucch_format_1_1a_1b_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, + LIBLTE_PHY_SUBFRAME_STRUCT *subframe, + LIBLTE_PHY_PUCCH_FORMAT_ENUM format, + uint32 N_id_cell, + uint8 N_ant, + uint32 N_1_p_pucch, + uint8 *out_bits, + uint32 *N_out_bits) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 m_prime; + uint32 i; + uint32 j; + uint32 L; + uint32 z_idx; + uint32 c_idx_0; + uint32 c_idx_1; + uint32 M_layer_symb; + uint32 idx; + uint32 symb_num; + uint32 N_pucch_sf = 4; + float s_ns_re[2]; + float s_ns_im[2]; + float s_w_re; + float s_w_im; + float s_w_r_re; + float s_w_r_im; + float denom; + float d_re; + float d_im; + float sd; + float r_u_v_re; + float r_u_v_im; + float ang; + + if(phy_struct != NULL && + subframe != NULL && + (format == LIBLTE_PHY_PUCCH_FORMAT_1 || + format == LIBLTE_PHY_PUCCH_FORMAT_1A || + format == LIBLTE_PHY_PUCCH_FORMAT_1B) && + out_bits != NULL && + N_out_bits != NULL) + { + // Extract resource elements and construct channel estimate + z_idx = 0; + c_idx_0 = 0; + c_idx_1 = 0; + for(L=0; L<14; L++) + { + if(7 > L) + { + i = N_1_p_pucch; + }else{ + i = phy_struct->N_rb_ul - N_1_p_pucch - 1; + } + for(j=0; jN_sc_rb_ul; j++) + { + if(2 == L || 3 == L || 4 == L) + { + phy_struct->pucch_c_est_0_re[c_idx_0] = subframe->rx_symb_re[L][i*phy_struct->N_sc_rb_ul+j]; + phy_struct->pucch_c_est_0_im[c_idx_0] = subframe->rx_symb_im[L][i*phy_struct->N_sc_rb_ul+j]; + c_idx_0++; + }else if(9 == L || 10 == L || 11 == L){ + phy_struct->pucch_c_est_1_re[c_idx_1] = subframe->rx_symb_re[L][i*phy_struct->N_sc_rb_ul+j]; + phy_struct->pucch_c_est_1_im[c_idx_1] = subframe->rx_symb_im[L][i*phy_struct->N_sc_rb_ul+j]; + c_idx_1++; + }else{ + phy_struct->pucch_z_est_re[z_idx] = subframe->rx_symb_re[L][i*phy_struct->N_sc_rb_ul+j]; + phy_struct->pucch_z_est_im[z_idx] = subframe->rx_symb_im[L][i*phy_struct->N_sc_rb_ul+j]; + z_idx++; + } + } + } + + // Recover z using the channel estimate + get_ulcch_ce(phy_struct, + phy_struct->pucch_c_est_0_re, + phy_struct->pucch_c_est_0_im, + phy_struct->pucch_c_est_1_re, + phy_struct->pucch_c_est_1_im, + subframe->num, + N_1_p_pucch, + phy_struct->pucch_c_est_re, + phy_struct->pucch_c_est_im); + pre_decoder_and_matched_filter_ul(phy_struct->pucch_z_est_re, + phy_struct->pucch_z_est_im, + phy_struct->pucch_c_est_re, + phy_struct->pucch_c_est_im, + z_idx, + N_ant, + 1, + phy_struct->pucch_z_re[0], + phy_struct->pucch_z_im[0], + &M_layer_symb); + + // Calculate s_ns + for(m_prime=0; m_prime<2; m_prime++) + { + if((phy_struct->pucch_n_prime_p[subframe->num][N_1_p_pucch][m_prime] % 2) == 0) + { + s_ns_re[m_prime] = 1; + s_ns_im[m_prime] = 0; + }else{ + s_ns_re[m_prime] = cos(M_PI/2); + s_ns_im[m_prime] = sin(M_PI/2); + } + } + + // Recover the bit that was sent + d_re = 0; + d_im = 0; + for(m_prime=0; m_prime<2; m_prime++) + { + for(i=0; ipucch_n_oc_p[subframe->num][N_1_p_pucch][m_prime]][i]; + s_w_im = s_ns_im[m_prime]*W_5_4_1_2[phy_struct->pucch_n_oc_p[subframe->num][N_1_p_pucch][m_prime]][i]; + for(j=0; jpucch_r_u_v_alpha_p_re[subframe->num][N_1_p_pucch][m_prime][symb_num][j]; + r_u_v_im = phy_struct->pucch_r_u_v_alpha_p_im[subframe->num][N_1_p_pucch][m_prime][symb_num][j]; + s_w_r_re = s_w_re*r_u_v_re - s_w_im*r_u_v_im; + s_w_r_im = s_w_re*r_u_v_im + s_w_im*r_u_v_re; + idx = m_prime*N_pucch_sf*LIBLTE_PHY_N_SC_RB_UL + i*LIBLTE_PHY_N_SC_RB_UL + j; + denom = s_w_r_re*s_w_r_re + s_w_r_im*s_w_r_im; + d_re += (1/denom)*(phy_struct->pucch_z_re[0][idx]*s_w_r_re + phy_struct->pucch_z_im[0][idx]*s_w_r_im); + d_im += (1/denom)*(-phy_struct->pucch_z_re[0][idx]*s_w_r_im + phy_struct->pucch_z_im[0][idx]*s_w_r_re); + } + } + } + d_re /= idx; + d_im /= idx; + d_re *= sqrt(N_ant); + d_im *= sqrt(N_ant); + + // Quantify the bits that were sent + if(format == LIBLTE_PHY_PUCCH_FORMAT_1 || + format == LIBLTE_PHY_PUCCH_FORMAT_1A) + { + if(d_re < 0) + { + sd = get_soft_decision(d_re, d_im, -1, 0, 1); + out_bits[0] = 1; + }else{ + sd = get_soft_decision(d_re, d_im, 1, 0, 1); + out_bits[0] = 0; + } + *N_out_bits = 1; + if(sd > 0.5) + { + err = LIBLTE_SUCCESS; + } + }else{ + ang = atan2f(d_im, d_re); + if((ang >= M_PI/4) && (ang < 3*M_PI/4)) + { + sd = get_soft_decision(d_re, d_im, 0, 1, 1); + out_bits[0] = 1; + out_bits[1] = 0; + }else if((ang >= -M_PI/4) && (ang < M_PI/4)){ + sd = get_soft_decision(d_re, d_im, 1, 0, 1); + out_bits[0] = 0; + out_bits[1] = 0; + }else if((ang >= -3*M_PI/4) && (ang < -M_PI/4)){ + sd = get_soft_decision(d_re, d_im, 0, -1, 1); + out_bits[0] = 0; + out_bits[1] = 1; + }else{ + sd = get_soft_decision(d_re, d_im, -1, 0, 1); + out_bits[0] = 1; + out_bits[1] = 1; + } + *N_out_bits = 2; + if(sd > 0.5) + { + err = LIBLTE_SUCCESS; + } + } + } + + return(err); +} + +/********************************************************************* + Name: liblte_phy_pucch_format_2_2a_2b_channel_encode + + Description: Encodes and modulates the Physical Uplink Control + Channel for formats 2, 2a, and 2b + + Document Reference: 3GPP TS 36.211 v10.1.0 section 5.4.2 + 3GPP TS 36.212 v10.1.0 section 5.2.3 + + Notes: Only handling normal CP and N_ant=1 +*********************************************************************/ +// FIXME + +/********************************************************************* + Name: liblte_phy_pucch_format_2_2a_2b_channel_decode + + Description: Demodulates and decodes the Physical Uplink Control + Channel for formats 2, 2a, and 2b + + Document Reference: 3GPP TS 36.211 v10.1.0 section 5.4.2 + 3GPP TS 36.212 v10.1.0 section 5.2.3 + + Notes: Only handling normal CP and N_ant=1 +*********************************************************************/ +// FIXME + +/********************************************************************* + Name: liblte_phy_pucch_map_sr_config_idx + + Description: Maps SR configuration index to SR periodicity and + SR subframe offset + + Document Reference: 3GPP TS 36.213 v10.3.0 table 10.1.5-1 +*********************************************************************/ +void liblte_phy_pucch_map_sr_config_idx(uint32 i_sr, + uint32 *sr_periodicity, + uint32 *N_offset_sr) +{ + if(i_sr < 5) + { + *sr_periodicity = 5; + *N_offset_sr = i_sr; + }else if(i_sr < 15){ + *sr_periodicity = 10; + *N_offset_sr = i_sr - 5; + }else if(i_sr < 35){ + *sr_periodicity = 20; + *N_offset_sr = i_sr - 15; + }else if(i_sr < 75){ + *sr_periodicity = 40; + *N_offset_sr = i_sr - 35; + }else if(i_sr < 155){ + *sr_periodicity = 80; + *N_offset_sr = i_sr - 75; + }else if(i_sr < 157){ + *sr_periodicity = 2; + *N_offset_sr = i_sr - 155; + }else{ + *sr_periodicity = 1; + *N_offset_sr = i_sr - 157; + } +} + /********************************************************************* Name: liblte_phy_generate_prach @@ -3179,8 +3460,14 @@ LIBLTE_ERROR_ENUM liblte_phy_detect_prach(LIBLTE_PHY_STRUCT *phy_struct, max_val != 0) { *N_det_pre = 1; - *det_pre = max_root*(v_max+1) + ((max_offset+N_cs)%phy_struct->prach_N_zc)/N_cs; - *det_ta = (((N_cs - ((max_offset+N_cs)%phy_struct->prach_N_zc))%N_cs)*29.155/16)-1; + if(0 == N_cs) + { + *det_pre = max_root*(v_max+1); + *det_ta = ((max_offset%phy_struct->prach_N_zc)*29.155/16)-1; + }else{ + *det_pre = max_root*(v_max+1) + ((max_offset+N_cs)%phy_struct->prach_N_zc)/N_cs; + *det_ta = (((N_cs - ((max_offset+N_cs)%phy_struct->prach_N_zc))%N_cs)*29.155/16)-1; + } }else{ *N_det_pre = 0; } @@ -3221,6 +3508,8 @@ LIBLTE_ERROR_ENUM liblte_phy_pdsch_channel_encode(LIBLTE_PHY_STRUCT *ph uint32 M_ap_symb; uint32 first_sc; uint32 last_sc; + uint32 Q_m; + uint32 scramb_bits_idx; if(phy_struct != NULL && pdcch != NULL && @@ -3265,26 +3554,40 @@ LIBLTE_ERROR_ENUM liblte_phy_pdsch_channel_encode(LIBLTE_PHY_STRUCT *ph N_ant, pdcch->alloc[alloc_idx].mod_type); } - // Encode the PDSCH - dlsch_channel_encode(phy_struct, - pdcch->alloc[alloc_idx].msg.msg, - pdcch->alloc[alloc_idx].msg.N_bits, - pdcch->alloc[alloc_idx].tbs, - pdcch->alloc[alloc_idx].tx_mode, - pdcch->alloc[alloc_idx].rv_idx, - N_bits_tot, - 2, - 2, - 8, - 250368, - phy_struct->pdsch_encode_bits, - &N_bits); - // FIXME: Only handling 1 codeword - c_init = (pdcch->alloc[alloc_idx].rnti << 14) | (0 << 13) | (subframe->num << 9) | N_id_cell; - generate_prs_c(c_init, N_bits, phy_struct->pdsch_c); - for(i=0; ialloc[alloc_idx].mod_type) + { + Q_m = 1; + }else if(LIBLTE_PHY_MODULATION_TYPE_QPSK == pdcch->alloc[alloc_idx].mod_type){ + Q_m = 2; + }else if(LIBLTE_PHY_MODULATION_TYPE_16QAM == pdcch->alloc[alloc_idx].mod_type){ + Q_m = 4; + }else{ // LIBLTE_PHY_MODULATION_TYPE_64QAM == pdcch->alloc[alloc_idx].mod_type + Q_m = 6; + } + scramb_bits_idx = 0; + for(i=0; ialloc[alloc_idx].N_codewords; i++) { - phy_struct->pdsch_scramb_bits[i] = phy_struct->pdsch_encode_bits[i] ^ phy_struct->pdsch_c[i]; + // Encode the PDSCH + dlsch_channel_encode(phy_struct, + pdcch->alloc[alloc_idx].msg[i].msg, + pdcch->alloc[alloc_idx].msg[i].N_bits, + pdcch->alloc[alloc_idx].tbs, + pdcch->alloc[alloc_idx].tx_mode, + pdcch->alloc[alloc_idx].rv_idx, + N_bits_tot, + 2, + Q_m, + 8, + 250368, + phy_struct->pdsch_encode_bits, + &N_bits); + c_init = (pdcch->alloc[alloc_idx].rnti << 14) | (i << 13) | (subframe->num << 9) | N_id_cell; + generate_prs_c(c_init, N_bits, phy_struct->pdsch_c); + for(j=0; jpdsch_scramb_bits[scramb_bits_idx++] = phy_struct->pdsch_encode_bits[j] ^ phy_struct->pdsch_c[j]; + } } modulation_mapper(phy_struct->pdsch_scramb_bits, N_bits, @@ -3296,7 +3599,7 @@ LIBLTE_ERROR_ENUM liblte_phy_pdsch_channel_encode(LIBLTE_PHY_STRUCT *ph phy_struct->pdsch_d_im, M_symb, N_ant, - 1, + pdcch->alloc[alloc_idx].N_codewords, pdcch->alloc[alloc_idx].pre_coder_type, phy_struct->pdsch_x_re, phy_struct->pdsch_x_im, @@ -3727,7 +4030,9 @@ LIBLTE_ERROR_ENUM liblte_phy_bch_channel_decode(LIBLTE_PHY_STRUCT *phy_ // Generate the scrambling sequence generate_prs_c(N_id_cell, 1920, phy_struct->bch_c); - // Try decoding with 1, 2, and 4 antennas + // Try decoding with 1, 2, and 4 antenna configs, + // and for each antenna config, try decoding with 0 to 3 offset + *N_ant = 0; for(p=1; p<5; p++) { if(p != 3) @@ -3760,7 +4065,6 @@ LIBLTE_ERROR_ENUM liblte_phy_bch_channel_decode(LIBLTE_PHY_STRUCT *phy_ &N_bits); // Try decoding at each offset - *N_ant = 0; for(i=0; i<4; i++) { for(j=0; j<1920; j++) @@ -3774,11 +4078,12 @@ LIBLTE_ERROR_ENUM liblte_phy_bch_channel_decode(LIBLTE_PHY_STRUCT *phy_ if(LIBLTE_SUCCESS == bch_channel_decode(phy_struct, phy_struct->bch_descramb_bits, 1920, - N_ant, + p, out_bits, N_out_bits)) { *offset = i; + *N_ant = p; break; } } @@ -3833,7 +4138,6 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_encode(LIBLTE_PHY_STRUCT uint32 N_reg_rb; uint32 N_reg_pdcch; uint32 N_cce_pdcch; - uint32 N_reg_cce; uint32 dci_size; uint32 N_dummy; uint32 C_cc_sb; @@ -3871,21 +4175,20 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_encode(LIBLTE_PHY_STRUCT } // Calculate resources, 3GPP TS 36.211 v10.1.0 section 6.8.1 N_reg_rb = 3; - N_reg_cce = 9; N_reg_pdcch = pdcch->N_symbs*(phy_struct->N_rb_dl*N_reg_rb) - phy_struct->N_rb_dl - pcfich->N_reg - phich->N_reg; if(N_ant == 4) { // Remove CRS N_reg_pdcch -= phy_struct->N_rb_dl; } - N_cce_pdcch = N_reg_pdcch/N_reg_cce; + N_cce_pdcch = N_reg_pdcch/LIBLTE_PHY_PDCCH_N_REG_CCE; // Initialize the search space for(p=0; ppdcch_cce_re[p][i][j] = 0; phy_struct->pdcch_cce_im[p][i][j] = 0; @@ -3896,7 +4199,7 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_encode(LIBLTE_PHY_STRUCT // Generate the scrambling sequence c_init = (subframe->num << 9) + N_id_cell; - generate_prs_c(c_init, 1152, phy_struct->pdcch_c); + generate_prs_c(c_init, LIBLTE_PHY_PDCCH_N_BITS_MAX * 2, phy_struct->pdcch_c); // Add the DCIs for(a_idx=0; a_idxN_alloc; a_idx++) @@ -3944,7 +4247,7 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_encode(LIBLTE_PHY_STRUCT { for(i=0; ipdcch_scramb_bits[i] = phy_struct->pdcch_encode_bits[i] ^ phy_struct->pdcch_c[4*css_idx*N_reg_cce*4*2 + i]; + phy_struct->pdcch_scramb_bits[i] = phy_struct->pdcch_encode_bits[i] ^ phy_struct->pdcch_c[4*css_idx*LIBLTE_PHY_PDCCH_N_REG_CCE*4*2 + i]; } modulation_mapper(phy_struct->pdcch_scramb_bits, N_bits, @@ -3975,7 +4278,7 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_encode(LIBLTE_PHY_STRUCT idx = 0; for(i=0; i<4; i++) { - for(j=0; j<(4*N_reg_cce); j++) + for(j=0; j<(4*LIBLTE_PHY_PDCCH_N_REG_CCE); j++) { phy_struct->pdcch_cce_re[p][4*css_idx+i][j] = phy_struct->pdcch_y_re[p][idx]; phy_struct->pdcch_cce_im[p][4*css_idx+i][j] = phy_struct->pdcch_y_im[p][idx]; @@ -4005,7 +4308,7 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_encode(LIBLTE_PHY_STRUCT // { // for(i=0; ipdcch_scramb_bits[i] = phy_struct->pdcch_encode_bits[i] ^ phy_struct->pdcch_c[4*actual_idx*N_reg_cce*4*2 + i]; +// phy_struct->pdcch_scramb_bits[i] = phy_struct->pdcch_encode_bits[i] ^ phy_struct->pdcch_c[4*actual_idx*LIBLTE_PHY_PDCCH_N_REG_CCE*4*2 + i]; // } // modulation_mapper(phy_struct->pdcch_scramb_bits, // N_bits, @@ -4036,7 +4339,7 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_encode(LIBLTE_PHY_STRUCT // idx = 0; // for(i=0; i<4; i++) // { -// for(j=0; j<(4*N_reg_cce); j++) +// for(j=0; j<(4*LIBLTE_PHY_PDCCH_N_REG_CCE); j++) // { // phy_struct->pdcch_cce_re[p][actual_idx+i][j] = phy_struct->pdcch_y_re[p][idx]; // phy_struct->pdcch_cce_im[p][actual_idx+i][j] = phy_struct->pdcch_y_im[p][idx]; @@ -4055,12 +4358,12 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_encode(LIBLTE_PHY_STRUCT { for(i=0; ipdcch_reg_re[p][i*N_reg_cce+j][k] = phy_struct->pdcch_cce_re[p][i][j*4+k]; - phy_struct->pdcch_reg_im[p][i*N_reg_cce+j][k] = phy_struct->pdcch_cce_im[p][i][j*4+k]; + phy_struct->pdcch_reg_re[p][i*LIBLTE_PHY_PDCCH_N_REG_CCE+j][k] = phy_struct->pdcch_cce_re[p][i][j*4+k]; + phy_struct->pdcch_reg_im[p][i*LIBLTE_PHY_PDCCH_N_REG_CCE+j][k] = phy_struct->pdcch_cce_im[p][i][j*4+k]; } } } @@ -4246,7 +4549,6 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_decode(LIBLTE_PHY_STRUCT uint32 N_dummy; uint32 N_reg_pdcch; uint32 N_cce_pdcch; - uint32 N_reg_cce; uint16 rnti = 0; bool valid_reg; @@ -4257,7 +4559,7 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_decode(LIBLTE_PHY_STRUCT pdcch != NULL) { // PCFICH - pcfich_channel_demap(phy_struct, subframe, N_id_cell, N_ant, pcfich); + pcfich_channel_demap(phy_struct, subframe, N_id_cell, N_ant, pcfich, &N_bits); if(LIBLTE_SUCCESS != cfi_channel_decode(phy_struct, phy_struct->pdcch_descramb_bits, N_bits, @@ -4521,19 +4823,18 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_decode(LIBLTE_PHY_STRUCT } } // Construct CCEs - N_reg_cce = 9; for(i=0; ipdcch_cce_y_est_re[i][j*4+k] = phy_struct->pdcch_perm_y_est_re[i*N_reg_cce+j][k]; - phy_struct->pdcch_cce_y_est_im[i][j*4+k] = phy_struct->pdcch_perm_y_est_im[i*N_reg_cce+j][k]; + phy_struct->pdcch_cce_y_est_re[i][j*4+k] = phy_struct->pdcch_perm_y_est_re[i*LIBLTE_PHY_PDCCH_N_REG_CCE+j][k]; + phy_struct->pdcch_cce_y_est_im[i][j*4+k] = phy_struct->pdcch_perm_y_est_im[i*LIBLTE_PHY_PDCCH_N_REG_CCE+j][k]; for(p=0; ppdcch_cce_c_est_re[p][i][j*4+k] = phy_struct->pdcch_perm_c_est_re[p][i*N_reg_cce+j][k]; - phy_struct->pdcch_cce_c_est_im[p][i][j*4+k] = phy_struct->pdcch_perm_c_est_im[p][i*N_reg_cce+j][k]; + phy_struct->pdcch_cce_c_est_re[p][i][j*4+k] = phy_struct->pdcch_perm_c_est_re[p][i*LIBLTE_PHY_PDCCH_N_REG_CCE+j][k]; + phy_struct->pdcch_cce_c_est_im[p][i][j*4+k] = phy_struct->pdcch_perm_c_est_im[p][i*LIBLTE_PHY_PDCCH_N_REG_CCE+j][k]; } } } @@ -4541,7 +4842,7 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_decode(LIBLTE_PHY_STRUCT // Generate the scrambling sequence c_init = (subframe->num << 9) + N_id_cell; - generate_prs_c(c_init, 1152, phy_struct->pdcch_c); + generate_prs_c(c_init, LIBLTE_PHY_PDCCH_N_BITS_MAX * 2, phy_struct->pdcch_c); // Determine the size of DCI 1A and 1C FIXME: Clean this up if(phy_struct->N_rb_dl == 6) @@ -4644,14 +4945,17 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_decode(LIBLTE_PHY_STRUCT dci_1a_size, &rnti))) { - err = LIBLTE_SUCCESS; - dci_1a_unpack(phy_struct->pdcch_dci, - dci_1a_size, - LIBLTE_PHY_DCI_CA_NOT_PRESENT, - rnti, - phy_struct->N_rb_dl, - N_ant, - &pdcch->alloc[pdcch->N_alloc++]); + err = dci_1a_unpack(phy_struct->pdcch_dci, + dci_1a_size, + LIBLTE_PHY_DCI_CA_NOT_PRESENT, + rnti, + phy_struct->N_rb_dl, + N_ant, + &pdcch->alloc[pdcch->N_alloc]); + if(LIBLTE_SUCCESS == err) + { + pdcch->N_alloc++; + } } if(pdcch->N_alloc < LIBLTE_PHY_PDCCH_MAX_ALLOC && (LIBLTE_SUCCESS == dci_channel_decode(phy_struct, @@ -4682,13 +4986,16 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_decode(LIBLTE_PHY_STRUCT dci_1c_size, &rnti))) { - err = LIBLTE_SUCCESS; - dci_1c_unpack(phy_struct->pdcch_dci, - dci_1c_size, - rnti, - phy_struct->N_rb_dl, - N_ant, - &pdcch->alloc[pdcch->N_alloc++]); + err = dci_1c_unpack(phy_struct->pdcch_dci, + dci_1c_size, + rnti, + phy_struct->N_rb_dl, + N_ant, + &pdcch->alloc[pdcch->N_alloc]); + if(LIBLTE_SUCCESS == err) + { + pdcch->N_alloc++; + } } } for(i=0; i<2; i++) @@ -4768,14 +5075,17 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_decode(LIBLTE_PHY_STRUCT dci_1a_size, &rnti))) { - err = LIBLTE_SUCCESS; - dci_1a_unpack(phy_struct->pdcch_dci, - dci_1a_size, - LIBLTE_PHY_DCI_CA_NOT_PRESENT, - rnti, - phy_struct->N_rb_dl, - N_ant, - &pdcch->alloc[pdcch->N_alloc++]); + err = dci_1a_unpack(phy_struct->pdcch_dci, + dci_1a_size, + LIBLTE_PHY_DCI_CA_NOT_PRESENT, + rnti, + phy_struct->N_rb_dl, + N_ant, + &pdcch->alloc[pdcch->N_alloc]); + if(LIBLTE_SUCCESS == err) + { + pdcch->N_alloc++; + } } if(pdcch->N_alloc < LIBLTE_PHY_PDCCH_MAX_ALLOC && (LIBLTE_SUCCESS == dci_channel_decode(phy_struct, @@ -4806,13 +5116,16 @@ LIBLTE_ERROR_ENUM liblte_phy_pdcch_channel_decode(LIBLTE_PHY_STRUCT dci_1c_size, &rnti))) { - err = LIBLTE_SUCCESS; - dci_1c_unpack(phy_struct->pdcch_dci, - dci_1c_size, - rnti, - phy_struct->N_rb_dl, - N_ant, - &pdcch->alloc[pdcch->N_alloc++]); + err = dci_1c_unpack(phy_struct->pdcch_dci, + dci_1c_size, + rnti, + phy_struct->N_rb_dl, + N_ant, + &pdcch->alloc[pdcch->N_alloc]); + if(LIBLTE_SUCCESS == err) + { + pdcch->N_alloc++; + } } } } @@ -5945,9 +6258,11 @@ LIBLTE_ERROR_ENUM liblte_phy_get_tbs_mcs_and_n_prb_for_dl(uint32 N_bits, { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; + uint32 j; uint32 code_rate; uint32 N_prb_tmp; uint32 N_bits_per_prb; + uint32 I_tbs; if(tbs != NULL && mcs != NULL && @@ -5993,7 +6308,36 @@ LIBLTE_ERROR_ENUM liblte_phy_get_tbs_mcs_and_n_prb_for_dl(uint32 N_bits, err = LIBLTE_SUCCESS; } }else{ - // FIXME: Add support for other RNTIs + *N_prb = 0; + for(i=0; i<27; i++) + { + for(j=0; j= I_tbs) + { + *mcs = I_tbs; + }else if(15 >= I_tbs){ + *mcs = I_tbs + 1; + }else{ + *mcs = I_tbs + 2; + } + break; + } + } + if(*N_prb != 0) + { + err = LIBLTE_SUCCESS; + } } } @@ -6080,7 +6424,9 @@ LIBLTE_ERROR_ENUM liblte_phy_get_tbs_mcs_and_n_prb_for_ul(uint32 N_bits, // Determine I_tbs and N_prb for(i=0; i<27; i++) { - for(j=0; jN_group_phich*3; N_reg_pdcch = N_pdcch_symbs*(phy_struct->N_rb_dl*N_reg_rb) - phy_struct->N_rb_dl - N_reg_pcfich - N_reg_phich; @@ -6147,7 +6492,9 @@ LIBLTE_ERROR_ENUM liblte_phy_get_n_cce(LIBLTE_PHY_STRUCT *phy_struct, N_reg_pdcch -= phy_struct->N_rb_dl; } - *N_cce = N_reg_pdcch/N_reg_cce; + *N_cce = N_reg_pdcch/LIBLTE_PHY_PDCCH_N_REG_CCE; + + return(LIBLTE_SUCCESS); } /******************************************************************************* @@ -6379,7 +6726,7 @@ void pre_decoder_and_matched_filter_ul(float *z_re, *M_layer_symb = M_ap_symb; for(i=0; idmrs_c); + generate_prs_c(((N_id_cell/30) << 5) + f_ss_pusch, 8*N_ul_symb*20, phy_struct->pusch_dmrs_c); // Calculate n_pn_ns n_pn_ns_1 = 0; n_pn_ns_2 = 0; for(i=0; i<8; i++) { - n_pn_ns_1 += phy_struct->dmrs_c[8*N_ul_symb*N_slot + i] << i; - n_pn_ns_2 += phy_struct->dmrs_c[8*N_ul_symb*(N_slot+1) + i] << i; + n_pn_ns_1 += phy_struct->pusch_dmrs_c[8*N_ul_symb*N_slot + i] << i; + n_pn_ns_2 += phy_struct->pusch_dmrs_c[8*N_ul_symb*(N_slot+1) + i] << i; } // Determine n_1_dmrs @@ -6628,6 +6975,157 @@ void generate_dmrs_pusch(LIBLTE_PHY_STRUCT *phy_struct, // FIXME: Add precoding to arrive at r_tilda } +/********************************************************************* + Name: generate_dmrs_pucch + + Description: Generates demodulation reference signals for the + uplink control channel + + Document Reference: 3GPP TS 36.211 v10.1.0 section 5.5.2 +*********************************************************************/ +void generate_dmrs_pucch(LIBLTE_PHY_STRUCT *phy_struct, + uint32 N_subfr, + uint32 N_id_cell, + uint32 delta_ss, + bool group_hopping_enabled, + bool sequence_hopping_enabled, + uint8 N_cs_1, + uint8 N_1_p_pucch, + uint8 delta_pucch_shift, + uint8 N_ant, + float *dmrs_0_re, + float *dmrs_0_im, + float *dmrs_1_re, + float *dmrs_1_im) +{ + uint32 N_slot; + uint32 i; + uint32 j; + uint32 k; + uint32 idx; + uint32 N_prime; + uint32 h_p; + uint32 N_ul_symb = 7; // FIXME: Only handling normal CP + uint32 n_cs_cell[2][N_ul_symb]; + uint32 n_cs_p[2][N_ul_symb]; + float alpha_p[2][N_ul_symb]; + float w_re; + float w_im; + float alpha_re; + float alpha_im; + float *dmrs_re; + float *dmrs_im; + + // Calculate N_slot + N_slot = N_subfr*2; + + // Calculate N_prime + if(N_1_p_pucch < (3*N_cs_1/delta_pucch_shift)) + { + N_prime = N_cs_1; + }else{ + N_prime = LIBLTE_PHY_N_SC_RB_UL; + } + + // Calculate n_prime_p + // FIXME: Only supporting normal cyclic prefix + if(N_1_p_pucch < (3*N_cs_1/delta_pucch_shift)) + { + phy_struct->pucch_n_prime_p[N_subfr][N_1_p_pucch][0] = N_1_p_pucch; + h_p = (phy_struct->pucch_n_prime_p[N_subfr][N_1_p_pucch][0] + 2) % (3*N_prime/delta_pucch_shift); + phy_struct->pucch_n_prime_p[N_subfr][N_1_p_pucch][1] = (h_p/3) + (h_p%3)*N_prime/delta_pucch_shift; + }else{ + phy_struct->pucch_n_prime_p[N_subfr][N_1_p_pucch][0] = (N_1_p_pucch - 3*N_cs_1/delta_pucch_shift) % (3*LIBLTE_PHY_N_SC_RB_UL/delta_pucch_shift); + phy_struct->pucch_n_prime_p[N_subfr][N_1_p_pucch][1] = ((3*(phy_struct->pucch_n_prime_p[N_subfr][N_1_p_pucch][0]+1)) % ((3*LIBLTE_PHY_N_SC_RB_UL/delta_pucch_shift)+1)) - 1; + } + + // Calculate N_oc_p + for(i=0; i<2; i++) + { + phy_struct->pucch_n_oc_p[N_subfr][N_1_p_pucch][i] = phy_struct->pucch_n_prime_p[N_subfr][N_1_p_pucch][i]*delta_pucch_shift/N_prime; + } + + // Generate c + generate_prs_c(N_id_cell, 8*N_ul_symb*20, phy_struct->pucch_dmrs_c); + + // Calculate N_cs_cell + for(i=0; i<2; i++) + { + for(j=0; jpucch_dmrs_c[8*N_ul_symb*(N_slot+i) + 8*j + idx] << idx; + } + } + } + + // Calculate N_cs_p + // FIXME: Only supporting normal cyclic prefix + for(i=0; i<2; i++) + { + for(j=0; jpucch_n_prime_p[N_subfr][N_1_p_pucch][i]*delta_pucch_shift + (phy_struct->pucch_n_oc_p[N_subfr][N_1_p_pucch][i] % delta_pucch_shift)) % N_prime)) % LIBLTE_PHY_N_SC_RB_UL; + } + } + + // Calculate alpha_p + for(i=0; i<2; i++) + { + for(j=0; jpucch_r_u_v_alpha_p_re[N_subfr][N_1_p_pucch][i][j], + phy_struct->pucch_r_u_v_alpha_p_im[N_subfr][N_1_p_pucch][i][j]); + } + } + + // Generate the PUCCH demodulation reference signal sequence + for(i=0; i<2; i++) + { + if(0 == i) + { + dmrs_re = dmrs_0_re; + dmrs_im = dmrs_0_im; + }else{ + dmrs_re = dmrs_1_re; + dmrs_im = dmrs_1_im; + } + for(j=0; jpucch_n_oc_p[N_subfr][N_1_p_pucch][i]][j]); + w_im = sin(W_5_5_2_2_1_2_phase[phy_struct->pucch_n_oc_p[N_subfr][N_1_p_pucch][i]][j]); + for(k=0; kpucch_r_u_v_alpha_p_re[N_subfr][N_1_p_pucch][i][j+2][k]; + alpha_im = phy_struct->pucch_r_u_v_alpha_p_im[N_subfr][N_1_p_pucch][i][j+2][k]; + // z(m) = 1 + dmrs_re[j*LIBLTE_PHY_N_SC_RB_UL + k] = (1/sqrt(N_ant))*(w_re*alpha_re - w_im*alpha_im); + dmrs_im[j*LIBLTE_PHY_N_SC_RB_UL + k] = (1/sqrt(N_ant))*(w_re*alpha_im + w_im*alpha_re); + } + } + } +} + /********************************************************************* Name: prach_preamble_seq_gen @@ -7390,11 +7888,11 @@ void pcfich_channel_demap(LIBLTE_PHY_STRUCT *phy_struct, LIBLTE_PHY_SUBFRAME_STRUCT *subframe, uint32 N_id_cell, uint8 N_ant, - LIBLTE_PHY_PCFICH_STRUCT *pcfich) + LIBLTE_PHY_PCFICH_STRUCT *pcfich, + uint32 *N_bits) { uint32 M_layer_symb; uint32 M_symb; - uint32 N_bits; uint32 c_init; uint32 k_hat; uint32 i; @@ -7455,8 +7953,8 @@ void pcfich_channel_demap(LIBLTE_PHY_STRUCT *phy_struct, M_symb, LIBLTE_PHY_MODULATION_TYPE_QPSK, phy_struct->pdcch_soft_bits, - &N_bits); - for(i=0; ipdcch_descramb_bits[i] = (float)phy_struct->pdcch_soft_bits[i]*(1-2*(float)phy_struct->pdcch_c[i]); } @@ -9012,7 +9510,11 @@ void modulation_demapper(float *d_re, float sd; float act_d_re; float act_d_im; - float one_over_sqrt_2 = 1/sqrt(2); + float one_over_sqrt_2 = 1/sqrt(2); + float two_over_sqrt_10 = 2/sqrt(10); + float two_over_sqrt_42 = 2/sqrt(42); + float four_over_sqrt_42 = 4/sqrt(42); + float six_over_sqrt_42 = 6/sqrt(42); uint32 i; if(LIBLTE_PHY_MODULATION_TYPE_BPSK == type) @@ -9035,7 +9537,7 @@ void modulation_demapper(float *d_re, bits[i] = -(int8)(127*sd); } } - }else{ // LIBLTE_PHY_MODULATION_TYPE_QPSK == type + }else if(LIBLTE_PHY_MODULATION_TYPE_QPSK == type){ // 3GPP TS 36.211 v10.1.0 section 7.1.2 *N_bits = M_symb*2; for(i=0; i 0) + { + bits[i*4+0] = +127; + }else{ + bits[i*4+0] = -127; + } + if(d_im[i] > 0) + { + bits[i*4+1] = +127; + }else{ + bits[i*4+1] = -127; + } + if(fabs(d_re[i]) < two_over_sqrt_10) + { + bits[i*4+2] = +127; + }else{ + bits[i*4+2] = -127; + } + if(fabs(d_im[i]) < two_over_sqrt_10) + { + bits[i*4+3] = +127; + }else{ + bits[i*4+3] = -127; + } + } + }else{ // LIBLTE_PHY_MODULATION_TYPE_64QAM == type + // 3GPP TS 36.211 v10.1.0 section 7.1.4 + *N_bits = M_symb*6; + // FIXME: Need to make soft decisions + for(i=0; i 0) + { + bits[i*6+0] = +127; + }else{ + bits[i*6+0] = -127; + } + if(d_im[i] > 0) + { + bits[i*6+1] = +127; + }else{ + bits[i*6+1] = -127; + } + if(fabs(d_re[i]) < four_over_sqrt_42) + { + bits[i*6+2] = +127; + if(fabs(d_re[i]) > two_over_sqrt_42) + { + bits[i*6+4] = +127; + }else{ + bits[i*6+4] = -127; + } + }else{ + bits[i*6+2] = -127; + if(fabs(d_re[i]) < six_over_sqrt_42) + { + bits[i*6+4] = +127; + }else{ + bits[i*6+4] = -127; + } + } + if(fabs(d_im[i]) < four_over_sqrt_42) + { + bits[i*6+3] = +127; + if(fabs(d_im[i]) > two_over_sqrt_42) + { + bits[i*6+5] = +127; + }else{ + bits[i*6+5] = -127; + } + }else{ + bits[i*6+3] = -127; + if(fabs(d_im[i]) < six_over_sqrt_42) + { + bits[i*6+5] = +127; + }else{ + bits[i*6+5] = -127; + } + } + } } } @@ -9155,20 +9743,20 @@ void calc_crc(uint8 *a_bits, } /********************************************************************* - Name: code_block_segmentation + Name: liblte_phy_code_block_segmentation Description: Performs code block segmentation for turbo coded channels Document Reference: 3GPP TS 36.212 v10.1.0 section 5.1.2 *********************************************************************/ -void code_block_segmentation(uint8 *b_bits, - uint32 N_b_bits, - uint32 *N_codeblocks, - uint32 *N_filler_bits, - uint8 *c_bits, - uint32 N_c_bits_max, - uint32 *N_c_bits) +void liblte_phy_code_block_segmentation(uint8 *b_bits, + uint32 N_b_bits, + uint32 *N_codeblocks, + uint32 *N_filler_bits, + uint8 *c_bits, + uint32 N_c_bits_max, + uint32 *N_c_bits) { uint32 Z = 6144; uint32 L; @@ -9277,19 +9865,19 @@ void code_block_segmentation(uint8 *b_bits, } /********************************************************************* - Name: code_block_desegmentation + Name: liblte_phy_code_block_desegmentation Description: Performs code block desegmentation for turbo coded channels Document Reference: 3GPP TS 36.212 v10.1.0 section 5.1.2 *********************************************************************/ -void code_block_desegmentation(uint8 *c_bits, - uint32 *N_c_bits, - uint32 N_c_bits_max, - uint32 tbs, - uint8 *b_bits, - uint32 N_b_bits) +void liblte_phy_code_block_desegmentation(uint8 *c_bits, + uint32 *N_c_bits, + uint32 N_c_bits_max, + uint32 tbs, + uint8 *b_bits, + uint32 N_b_bits) { uint32 Z = 6144; uint32 L; @@ -9825,6 +10413,7 @@ void viterbi_decode_siso(LIBLTE_PHY_STRUCT *phy_struct, for(j=0; j<(N_d_bits/rate)+10; j++) { phy_struct->vd_path_metric[i][j] = 0; + phy_struct->vd_w_metric[i][j] = 0; } } for(i=0; i<(int32)(N_d_bits/rate); i++) @@ -9983,16 +10572,16 @@ void turbo_encode(LIBLTE_PHY_STRUCT *phy_struct, d_bits[N_branch_bits+i] = phy_struct->te_z[i]; d_bits[2*N_branch_bits+i] = phy_struct->te_z_prime[i]; } - d_bits[N_c_bits] = phy_struct->te_fb1[N_c_bits-1]; + d_bits[N_c_bits] = phy_struct->te_fb1[N_c_bits]; d_bits[N_c_bits+1] = phy_struct->te_z[N_c_bits+1]; d_bits[N_c_bits+2] = phy_struct->te_x_prime[N_c_bits]; d_bits[N_c_bits+3] = phy_struct->te_z_prime[N_c_bits+1]; d_bits[N_branch_bits+N_c_bits] = phy_struct->te_z[N_c_bits]; - d_bits[N_branch_bits+N_c_bits+1] = phy_struct->te_fb1[N_c_bits+1]; + d_bits[N_branch_bits+N_c_bits+1] = phy_struct->te_fb1[N_c_bits+2]; d_bits[N_branch_bits+N_c_bits+2] = phy_struct->te_z_prime[N_c_bits]; d_bits[N_branch_bits+N_c_bits+3] = phy_struct->te_x_prime[N_c_bits+2]; - d_bits[2*N_branch_bits+N_c_bits] = phy_struct->te_fb1[N_c_bits]; - d_bits[2*N_branch_bits+N_c_bits+1] = phy_struct->te_z[N_c_bits+1]; + d_bits[2*N_branch_bits+N_c_bits] = phy_struct->te_fb1[N_c_bits+1]; + d_bits[2*N_branch_bits+N_c_bits+1] = phy_struct->te_z[N_c_bits+2]; d_bits[2*N_branch_bits+N_c_bits+2] = phy_struct->te_x_prime[N_c_bits+1]; d_bits[2*N_branch_bits+N_c_bits+3] = phy_struct->te_z_prime[N_c_bits+2]; @@ -10043,6 +10632,15 @@ void turbo_decode(LIBLTE_PHY_STRUCT *phy_struct, uint32 g_1 = 03; // Numbers are in octal uint32 g_2[2] = {015, 013}; // Numbers are in octal + // Step 0: Clear punctured bits + for(i=0; iulsch_b_bits, - tbs+24, - &N_codeblocks, - &N_fill_bits, - phy_struct->ulsch_c_bits[0], - 6144, - phy_struct->ulsch_N_c_bits); + liblte_phy_code_block_segmentation(phy_struct->ulsch_b_bits, + tbs+24, + &N_codeblocks, + &N_fill_bits, + phy_struct->ulsch_c_bits[0], + LIBLTE_PHY_MAX_CODE_BLOCK_SIZE, + phy_struct->ulsch_N_c_bits); for(cb=0; cbulsch_N_e_bits[cb] = N_l*Q_m*(uint32)ceilf((float)G_prime/(float)N_codeblocks); } - rate_match_turbo(phy_struct, - phy_struct->ulsch_tx_d_bits, - N_d_bits, - N_codeblocks, - tx_mode, - 1, - 1, - LIBLTE_PHY_CHAN_TYPE_ULSCH, - rv_idx, - phy_struct->ulsch_N_e_bits[cb], - phy_struct->ulsch_tx_e_bits[0]); + liblte_phy_rate_match_turbo(phy_struct, + phy_struct->ulsch_tx_d_bits, + N_d_bits, + N_codeblocks, + tx_mode, + 1, + 1, + LIBLTE_PHY_CHAN_TYPE_ULSCH, + rv_idx, + phy_struct->ulsch_N_e_bits[cb], + phy_struct->ulsch_tx_e_bits[0]); } // Determine f_bits @@ -11794,13 +12392,13 @@ LIBLTE_ERROR_ENUM ulsch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, // determined by encoding a sequence of zeros N_b_bits = tbs+24; memset(phy_struct->ulsch_b_bits, 0, sizeof(uint8)*N_b_bits); - code_block_segmentation(phy_struct->ulsch_b_bits, - N_b_bits, - &N_codeblocks, - &N_fill_bits, - phy_struct->ulsch_c_bits[0], - 6144, - phy_struct->ulsch_N_c_bits); + liblte_phy_code_block_segmentation(phy_struct->ulsch_b_bits, + N_b_bits, + &N_codeblocks, + &N_fill_bits, + phy_struct->ulsch_c_bits[0], + LIBLTE_PHY_MAX_CODE_BLOCK_SIZE, + phy_struct->ulsch_N_c_bits); // Determine g_bits ulsch_channel_deinterleaver(phy_struct, @@ -11845,19 +12443,19 @@ LIBLTE_ERROR_ENUM ulsch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, &N_d_bits); // Determine d_bits - rate_unmatch_turbo(phy_struct, - phy_struct->ulsch_rx_e_bits[cb], - phy_struct->ulsch_N_e_bits[cb], - phy_struct->ulsch_tx_d_bits, - N_d_bits/3, - N_codeblocks, - tx_mode, - 1, - 1, - LIBLTE_PHY_CHAN_TYPE_ULSCH, - rv_idx, - phy_struct->ulsch_rx_d_bits, - &N_d_bits); + liblte_phy_rate_unmatch_turbo(phy_struct, + phy_struct->ulsch_rx_e_bits[cb], + phy_struct->ulsch_N_e_bits[cb], + phy_struct->ulsch_tx_d_bits, + N_d_bits/3, + N_codeblocks, + tx_mode, + 1, + 1, + LIBLTE_PHY_CHAN_TYPE_ULSCH, + rv_idx, + phy_struct->ulsch_rx_d_bits, + &N_d_bits); // Determine c_bits turbo_decode(phy_struct, @@ -11869,12 +12467,12 @@ LIBLTE_ERROR_ENUM ulsch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, } // Determine b_bits - code_block_desegmentation(phy_struct->ulsch_c_bits[0], - phy_struct->ulsch_N_c_bits, - 6144, - tbs, - phy_struct->ulsch_b_bits, - N_b_bits); + liblte_phy_code_block_desegmentation(phy_struct->ulsch_c_bits[0], + phy_struct->ulsch_N_c_bits, + LIBLTE_PHY_MAX_CODE_BLOCK_SIZE, + tbs, + phy_struct->ulsch_b_bits, + N_b_bits); // Recover a_bits and p_bits a_bits = &phy_struct->ulsch_b_bits[0]; @@ -11983,14 +12581,12 @@ void bch_channel_encode(LIBLTE_PHY_STRUCT *phy_struct, LIBLTE_ERROR_ENUM bch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, float *in_bits, uint32 N_in_bits, - uint8 *N_ant, + uint8 N_ant, uint8 *out_bits, uint32 *N_out_bits) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_CRC; - uint32 ber_1; - uint32 ber_2; - uint32 ber_4; + uint32 ber; uint32 N_d_bits; uint32 N_c_bits; uint32 i; @@ -12001,6 +12597,17 @@ LIBLTE_ERROR_ENUM bch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, uint8 ant_mask_1[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8 ant_mask_2[16] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; uint8 ant_mask_4[16] = {0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}; + uint8 *ant_mask; + + // Choose the correct antenna mask + if(1 == N_ant) + { + ant_mask = ant_mask_1; + }else if(2 == N_ant){ + ant_mask = ant_mask_2; + }else{ // 4 == N_ant + ant_mask = ant_mask_4; + } // Rate unmatch to get the d_bits rate_unmatch_conv(phy_struct, @@ -12027,18 +12634,14 @@ LIBLTE_ERROR_ENUM bch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, // Calculate p_bits calc_crc(a_bits, 24, CRC16, calc_p_bits, 16); - // Try all p_bit masks - ber_1 = 0; - ber_2 = 0; - ber_4 = 0; + // Calculate the number of bit errors + ber = 0; for(i=0; i<16; i++) { - ber_1 += p_bits[i] ^ (calc_p_bits[i] ^ ant_mask_1[i]); - ber_2 += p_bits[i] ^ (calc_p_bits[i] ^ ant_mask_2[i]); - ber_4 += p_bits[i] ^ (calc_p_bits[i] ^ ant_mask_4[i]); + ber += p_bits[i] ^ (calc_p_bits[i] ^ ant_mask[i]); } - if(ber_1 == 0 || ber_2 == 0 || ber_4 == 0) + if(ber == 0) { for(i=0; i<24; i++) { @@ -12047,14 +12650,6 @@ LIBLTE_ERROR_ENUM bch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, *N_out_bits = 24; err = LIBLTE_SUCCESS; } - if(ber_1 == 0) - { - *N_ant = 1; - }else if(ber_2 == 0){ - *N_ant = 2; - }else if(ber_4 == 0){ - *N_ant = 4; - } return(err); } @@ -12109,13 +12704,13 @@ void dlsch_channel_encode(LIBLTE_PHY_STRUCT *phy_struct, } // Construct c_bits - code_block_segmentation(phy_struct->dlsch_b_bits, - tbs+24, - &N_codeblocks, - &N_fill_bits, - phy_struct->dlsch_c_bits[0], - 6144, - phy_struct->dlsch_N_c_bits); + liblte_phy_code_block_segmentation(phy_struct->dlsch_b_bits, + tbs+24, + &N_codeblocks, + &N_fill_bits, + phy_struct->dlsch_c_bits[0], + LIBLTE_PHY_MAX_CODE_BLOCK_SIZE, + phy_struct->dlsch_N_c_bits); for(cb=0; cbdlsch_N_e_bits[cb] = N_l*Q_m*(uint32)ceilf((float)G_prime/(float)N_codeblocks); } - rate_match_turbo(phy_struct, - phy_struct->dlsch_tx_d_bits, - N_d_bits, - N_codeblocks, - tx_mode, - N_soft, - M_dl_harq, - LIBLTE_PHY_CHAN_TYPE_DLSCH, - rv_idx, - phy_struct->dlsch_N_e_bits[cb], - phy_struct->dlsch_tx_e_bits[0]); + liblte_phy_rate_match_turbo(phy_struct, + phy_struct->dlsch_tx_d_bits, + N_d_bits, + N_codeblocks, + tx_mode, + N_soft, + M_dl_harq, + LIBLTE_PHY_CHAN_TYPE_DLSCH, + rv_idx, + phy_struct->dlsch_N_e_bits[cb], + phy_struct->dlsch_tx_e_bits[0]); } code_block_concatenation(phy_struct->dlsch_tx_e_bits[0], @@ -12191,13 +12786,13 @@ LIBLTE_ERROR_ENUM dlsch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, // determined by encoding a sequence of zeros N_b_bits = tbs+24; memset(phy_struct->dlsch_b_bits, 0, sizeof(uint8)*N_b_bits); - code_block_segmentation(phy_struct->dlsch_b_bits, - N_b_bits, - &N_codeblocks, - &N_fill_bits, - phy_struct->dlsch_c_bits[0], - 6144, - phy_struct->dlsch_N_c_bits); + liblte_phy_code_block_segmentation(phy_struct->dlsch_b_bits, + N_b_bits, + &N_codeblocks, + &N_fill_bits, + phy_struct->dlsch_c_bits[0], + LIBLTE_PHY_MAX_CODE_BLOCK_SIZE, + phy_struct->dlsch_N_c_bits); // Determine e_bits code_block_deconcatenation(in_bits, @@ -12219,19 +12814,19 @@ LIBLTE_ERROR_ENUM dlsch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, &N_d_bits); // Determine d_bits - rate_unmatch_turbo(phy_struct, - phy_struct->dlsch_rx_e_bits[cb], - phy_struct->dlsch_N_e_bits[cb], - phy_struct->dlsch_tx_d_bits, - N_d_bits/3, - N_codeblocks, - tx_mode, - N_soft, - M_dl_harq, - LIBLTE_PHY_CHAN_TYPE_DLSCH, - rv_idx, - phy_struct->dlsch_rx_d_bits, - &N_d_bits); + liblte_phy_rate_unmatch_turbo(phy_struct, + phy_struct->dlsch_rx_e_bits[cb], + phy_struct->dlsch_N_e_bits[cb], + phy_struct->dlsch_tx_d_bits, + N_d_bits/3, + N_codeblocks, + tx_mode, + N_soft, + M_dl_harq, + LIBLTE_PHY_CHAN_TYPE_DLSCH, + rv_idx, + phy_struct->dlsch_rx_d_bits, + &N_d_bits); // Determine c_bits turbo_decode(phy_struct, @@ -12243,12 +12838,12 @@ LIBLTE_ERROR_ENUM dlsch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, } // Determine b_bits - code_block_desegmentation(phy_struct->dlsch_c_bits[0], - phy_struct->dlsch_N_c_bits, - 6144, - tbs, - phy_struct->dlsch_b_bits, - N_b_bits); + liblte_phy_code_block_desegmentation(phy_struct->dlsch_c_bits[0], + phy_struct->dlsch_N_c_bits, + LIBLTE_PHY_MAX_CODE_BLOCK_SIZE, + tbs, + phy_struct->dlsch_b_bits, + N_b_bits); // Recover a_bits and p_bits a_bits = &phy_struct->dlsch_b_bits[0]; @@ -12472,14 +13067,14 @@ void dci_0_pack(LIBLTE_PHY_ALLOCATION_STRUCT *alloc, if(LIBLTE_PHY_DCI_CA_PRESENT == ca_presence) { printf("WARNING: Not handling carrier indicator\n"); - phy_value_2_bits(0, &dci, 3); + liblte_value_2_bits(0, &dci, 3); } // Format 0/1A flag is set to format 0 - phy_value_2_bits(DCI_0_1A_FLAG_0, &dci, 1); + liblte_value_2_bits(DCI_0_1A_FLAG_0, &dci, 1); // Frequency hopping flag - phy_value_2_bits(0, &dci, 1); + liblte_value_2_bits(0, &dci, 1); // RBA // FIXME: Only supporting non-hopping single-cluster @@ -12490,25 +13085,25 @@ void dci_0_pack(LIBLTE_PHY_ALLOCATION_STRUCT *alloc, }else{ RIV = N_rb_ul*(N_rb_ul - alloc->N_prb + 1) + (N_rb_ul - 1 - alloc->prb[0][0]); } - phy_value_2_bits(RIV, &dci, RIV_length); + liblte_value_2_bits(RIV, &dci, RIV_length); // Modulation and coding scheme and redundancy version - phy_value_2_bits(alloc->mcs, &dci, 5); + liblte_value_2_bits(alloc->mcs, &dci, 5); // New data indicator - phy_value_2_bits(alloc->ndi, &dci, 1); + liblte_value_2_bits(alloc->ndi, &dci, 1); // TPC command - phy_value_2_bits(alloc->tpc, &dci, 2); + liblte_value_2_bits(alloc->tpc, &dci, 2); // Cyclic shift - phy_value_2_bits(0, &dci, 3); + liblte_value_2_bits(0, &dci, 3); // CSI request - phy_value_2_bits(0, &dci, 1); + liblte_value_2_bits(0, &dci, 1); // Pad bit - phy_value_2_bits(0, &dci, 1); + liblte_value_2_bits(0, &dci, 1); // Pad if needed size = dci - out_bits; @@ -12524,7 +13119,7 @@ void dci_0_pack(LIBLTE_PHY_ALLOCATION_STRUCT *alloc, size == 56) { size++; - phy_value_2_bits(0, &dci, 1); + liblte_value_2_bits(0, &dci, 1); } *N_out_bits = size; } @@ -12572,11 +13167,11 @@ void dci_1a_pack(LIBLTE_PHY_ALLOCATION_STRUCT *alloc, if(LIBLTE_PHY_DCI_CA_PRESENT == ca_presence) { printf("WARNING: Not handling carrier indicator\n"); - phy_value_2_bits(0, &dci, 3); + liblte_value_2_bits(0, &dci, 3); } // Format 0/1A flag is set to format 1A - phy_value_2_bits(DCI_0_1A_FLAG_1A, &dci, 1); + liblte_value_2_bits(DCI_0_1A_FLAG_1A, &dci, 1); if(LIBLTE_MAC_SI_RNTI == alloc->rnti || LIBLTE_MAC_P_RNTI == alloc->rnti || @@ -12584,7 +13179,7 @@ void dci_1a_pack(LIBLTE_PHY_ALLOCATION_STRUCT *alloc, LIBLTE_MAC_RA_RNTI_END >= alloc->rnti)) { // FIXME: Only supporting localized VRBs - phy_value_2_bits(DCI_VRB_TYPE_LOCALIZED, &dci, 1); + liblte_value_2_bits(DCI_VRB_TYPE_LOCALIZED, &dci, 1); RIV_length = (uint32)ceilf(logf(N_rb_dl*(N_rb_dl+1)/2)/logf(2)); if((alloc->N_prb-1) <= (N_rb_dl/2)) { @@ -12592,29 +13187,29 @@ void dci_1a_pack(LIBLTE_PHY_ALLOCATION_STRUCT *alloc, }else{ RIV = N_rb_dl*(N_rb_dl-alloc->N_prb+1) + (N_rb_dl - 1 - alloc->prb[0][0]); } - phy_value_2_bits(RIV, &dci, RIV_length); + liblte_value_2_bits(RIV, &dci, RIV_length); // Modulation and coding scheme - phy_value_2_bits(alloc->mcs, &dci, 5); + liblte_value_2_bits(alloc->mcs, &dci, 5); // HARQ process number, FIXME: FDD only - phy_value_2_bits(0, &dci, 3); + liblte_value_2_bits(0, &dci, 3); // New data indicator - phy_value_2_bits(0, &dci, 1); + liblte_value_2_bits(0, &dci, 1); // Redundancy version - phy_value_2_bits(alloc->rv_idx, &dci, 2); + liblte_value_2_bits(alloc->rv_idx, &dci, 2); // TPC N_prb_1a = 3; - phy_value_2_bits(1, &dci, 2); + liblte_value_2_bits(1, &dci, 2); // Calculate the TBS alloc->tbs = TBS_71721[alloc->mcs][N_prb_1a-1]; }else{ // FIXME: Only supporting localized VRBs - phy_value_2_bits(DCI_VRB_TYPE_LOCALIZED, &dci, 1); + liblte_value_2_bits(DCI_VRB_TYPE_LOCALIZED, &dci, 1); RIV_length = (uint32)ceilf(logf(N_rb_dl*(N_rb_dl+1)/2)/logf(2)); if((alloc->N_prb-1) <= (N_rb_dl/2)) { @@ -12622,22 +13217,22 @@ void dci_1a_pack(LIBLTE_PHY_ALLOCATION_STRUCT *alloc, }else{ RIV = N_rb_dl*(N_rb_dl - alloc->N_prb + 1) + (N_rb_dl - 1 - alloc->prb[0][0]); } - phy_value_2_bits(RIV, &dci, RIV_length); + liblte_value_2_bits(RIV, &dci, RIV_length); // Modulation and coding scheme - phy_value_2_bits(alloc->mcs, &dci, 5); + liblte_value_2_bits(alloc->mcs, &dci, 5); // HARQ process number, FIXME: FDD only - phy_value_2_bits(0, &dci, 3); + liblte_value_2_bits(0, &dci, 3); // New data indicator - phy_value_2_bits(alloc->ndi, &dci, 1); + liblte_value_2_bits(alloc->ndi, &dci, 1); // Redundancy version - phy_value_2_bits(alloc->rv_idx, &dci, 2); + liblte_value_2_bits(alloc->rv_idx, &dci, 2); // TPC - phy_value_2_bits(alloc->tpc, &dci, 2); + liblte_value_2_bits(alloc->tpc, &dci, 2); // Calculate the TBS alloc->tbs = TBS_71721[alloc->mcs][alloc->N_prb-1]; @@ -12657,7 +13252,7 @@ void dci_1a_pack(LIBLTE_PHY_ALLOCATION_STRUCT *alloc, size == 56) { size++; - phy_value_2_bits(0, &dci, 1); + liblte_value_2_bits(0, &dci, 1); } *N_out_bits = size; } @@ -12675,41 +13270,42 @@ void dci_1a_pack(LIBLTE_PHY_ALLOCATION_STRUCT *alloc, Notes: Currently only handles SI-RNTI, P-RNTI, or RA-RNTI and localized virtual resource blocks *********************************************************************/ -void dci_1a_unpack(uint8 *in_bits, - uint32 N_in_bits, - LIBLTE_PHY_DCI_CA_PRESENCE_ENUM ca_presence, - uint16 rnti, - uint32 N_rb_dl, - uint8 N_ant, - LIBLTE_PHY_ALLOCATION_STRUCT *alloc) +LIBLTE_ERROR_ENUM dci_1a_unpack(uint8 *in_bits, + uint32 N_in_bits, + LIBLTE_PHY_DCI_CA_PRESENCE_ENUM ca_presence, + uint16 rnti, + uint32 N_rb_dl, + uint8 N_ant, + LIBLTE_PHY_ALLOCATION_STRUCT *alloc) { - uint32 RB_start = 0; - uint32 RIV; - uint32 RIV_length; - uint32 i; - uint32 j; - uint32 ca_ind; - uint32 N_prb_1a; - uint32 tpc; - uint32 dci_0_1a_flag; - uint32 loc_or_dist; - uint32 harq_process; - uint32 new_data_ind; - uint8 *dci = in_bits; + LIBLTE_ERROR_ENUM err = LIBLTE_SUCCESS; + uint32 RB_start = 0; + uint32 RIV; + uint32 RIV_length; + uint32 i; + uint32 j; + uint32 ca_ind; + uint32 N_prb_1a; + uint32 tpc; + uint32 dci_0_1a_flag; + uint32 loc_or_dist; + uint32 harq_process; + uint32 new_data_ind; + uint8 *dci = in_bits; // Carrier indicator if(LIBLTE_PHY_DCI_CA_PRESENT == ca_presence) { - ca_ind = phy_bits_2_value(&dci, 3); + ca_ind = liblte_bits_2_value(&dci, 3); printf("WARNING: Not handling carrier indicator\n"); } // Check DCI 0/1A flag 3GPP TS 36.212 v10.1.0 section 5.3.3.1.3 - dci_0_1a_flag = phy_bits_2_value(&dci, 1); + dci_0_1a_flag = liblte_bits_2_value(&dci, 1); if(DCI_0_1A_FLAG_0 == dci_0_1a_flag) { printf("ERROR: DCI 1A flagged as DCI 0\n"); - return; + return(LIBLTE_ERROR_INVALID_CONTENTS); } if(LIBLTE_MAC_SI_RNTI == rnti || @@ -12718,20 +13314,20 @@ void dci_1a_unpack(uint8 *in_bits, LIBLTE_MAC_RA_RNTI_END >= rnti)) { // Determine if RIV uses local or distributed VRBs - loc_or_dist = phy_bits_2_value(&dci, 1); + loc_or_dist = liblte_bits_2_value(&dci, 1); // Find the RIV that was sent 3GPP TS 36.213 v10.3.0 section 7.1.6.3 RIV_length = (uint32)ceilf(logf(N_rb_dl*(N_rb_dl+1)/2)/logf(2)); - RIV = phy_bits_2_value(&dci, RIV_length); + RIV = liblte_bits_2_value(&dci, RIV_length); alloc->N_prb = RIV/N_rb_dl + 1; RB_start = RIV % N_rb_dl; // Extract the rest of the fields - alloc->mcs = phy_bits_2_value(&dci, 5); - harq_process = phy_bits_2_value(&dci, 3); - new_data_ind = phy_bits_2_value(&dci, 1); - alloc->rv_idx = phy_bits_2_value(&dci, 2); - tpc = phy_bits_2_value(&dci, 2); + alloc->mcs = liblte_bits_2_value(&dci, 5); + harq_process = liblte_bits_2_value(&dci, 3); + new_data_ind = liblte_bits_2_value(&dci, 1); + alloc->rv_idx = liblte_bits_2_value(&dci, 2); + tpc = liblte_bits_2_value(&dci, 2); // Parse the data if((tpc % 2) == 0) @@ -12763,11 +13359,18 @@ void dci_1a_unpack(uint8 *in_bits, alloc->tx_mode = 2; } alloc->N_codewords = 1; - alloc->tbs = TBS_71721[alloc->mcs][N_prb_1a-1]; - alloc->rnti = rnti; + if(27 > alloc->mcs) + { + alloc->tbs = TBS_71721[alloc->mcs][N_prb_1a-1]; + }else{ + err = LIBLTE_ERROR_INVALID_CONTENTS; + } + alloc->rnti = rnti; }else{ printf("ERROR: Not handling DCI 1As for C-RNTI\n"); } + + return(err); } /********************************************************************* @@ -12794,47 +13397,48 @@ void dci_1a_unpack(uint8 *in_bits, Notes: Currently only handling SI-RNTI, P-RNTI, and RA-RNTI *********************************************************************/ -void dci_1c_unpack(uint8 *in_bits, - uint32 N_in_bits, - uint16 rnti, - uint32 N_rb_dl, - uint8 N_ant, - LIBLTE_PHY_ALLOCATION_STRUCT *alloc) +LIBLTE_ERROR_ENUM dci_1c_unpack(uint8 *in_bits, + uint32 N_in_bits, + uint16 rnti, + uint32 N_rb_dl, + uint8 N_ant, + LIBLTE_PHY_ALLOCATION_STRUCT *alloc) { - uint32 RB_start = 0; - uint32 RIV; - uint32 RIV_length; - uint32 i; - uint32 idash; - uint32 j; - uint32 jdash; - uint32 gap_ind; - uint32 N_gap; - uint32 N_vrb_gap1_dl; - uint32 N_vrb_gap2_dl; - uint32 N_vrb_dl; - uint32 Ndash_vrb_dl; - uint32 N_rb_step; - uint32 Ntilde_vrb_dl; - uint32 P; - uint32 N_row; - uint32 N_col; - uint32 N_null; - uint32 n_vrb; - uint32 ntilde_vrb; - uint32 ntildedash_prb; - uint32 ntildedashdash_prb; - uint32 ntilde_prb_even; - uint32 ntilde_prb_odd; - uint32 n_prb_even; - uint32 n_prb_odd; - uint8 *dci = in_bits; + LIBLTE_ERROR_ENUM err = LIBLTE_SUCCESS; + uint32 RB_start = 0; + uint32 RIV; + uint32 RIV_length; + uint32 i; + uint32 idash; + uint32 j; + uint32 jdash; + uint32 gap_ind; + uint32 N_gap; + uint32 N_vrb_gap1_dl; + uint32 N_vrb_gap2_dl; + uint32 N_vrb_dl; + uint32 Ndash_vrb_dl; + uint32 N_rb_step; + uint32 Ntilde_vrb_dl; + uint32 P; + uint32 N_row; + uint32 N_col; + uint32 N_null; + uint32 n_vrb; + uint32 ntilde_vrb; + uint32 ntildedash_prb; + uint32 ntildedashdash_prb; + uint32 ntilde_prb_even; + uint32 ntilde_prb_odd; + uint32 n_prb_even; + uint32 n_prb_odd; + uint8 *dci = in_bits; if(N_rb_dl < 50) { gap_ind = 0; }else{ - gap_ind = phy_bits_2_value(&dci, 1); + gap_ind = liblte_bits_2_value(&dci, 1); } if(N_rb_dl <= 10) @@ -12889,7 +13493,7 @@ void dci_1c_unpack(uint8 *in_bits, LIBLTE_MAC_RA_RNTI_END >= rnti)) { RIV_length = ceilf(logf((N_vrb_gap1_dl/N_rb_step) * ((N_vrb_gap1_dl/N_rb_step)+1) / 2.0)/logf(2)); - RIV = phy_bits_2_value(&dci, RIV_length); + RIV = liblte_bits_2_value(&dci, RIV_length); for(i=N_rb_step; i<=(N_vrb_dl/N_rb_step)*N_rb_step; i+=N_rb_step) // L_crb running variable N_rb_step to floor(N_vrb_dl/N_rb_step)*N_rb_step { @@ -12916,7 +13520,7 @@ void dci_1c_unpack(uint8 *in_bits, } } // Extract the rest of the fields - alloc->mcs = phy_bits_2_value(&dci, 5); + alloc->mcs = liblte_bits_2_value(&dci, 5); // Convert allocation into array of PRBs // Calculate Resource Block Group size (P) @@ -12987,11 +13591,19 @@ void dci_1c_unpack(uint8 *in_bits, alloc->tx_mode = 2; } alloc->N_codewords = 1; - alloc->tbs = TBS_71723[alloc->mcs]; - alloc->rnti = rnti; + if(32 > alloc->mcs) + { + alloc->tbs = TBS_71723[alloc->mcs]; + }else{ + err = LIBLTE_ERROR_INVALID_CONTENTS; + } + alloc->rnti = rnti; }else{ printf("ERROR: Not handling DCI 1Cs for C-RNTI\n"); + err = LIBLTE_ERROR_INVALID_CONTENTS; } + + return(err); } /********************************************************************* @@ -13096,21 +13708,22 @@ LIBLTE_ERROR_ENUM cfi_channel_decode(LIBLTE_PHY_STRUCT *phy_struct, } /********************************************************************* - Name: get_ul_ce + Name: get_ulsch_ce - Description: Resolves channel estimates for the uplink + Description: Resolves channel estimates for the uplink shared + channel Document Reference: N/A *********************************************************************/ -void get_ul_ce(LIBLTE_PHY_STRUCT *phy_struct, - float *c_est_0_re, - float *c_est_0_im, - float *c_est_1_re, - float *c_est_1_im, - uint32 N_prb, - uint32 N_subfr, - float *c_est_re, - float *c_est_im) +void get_ulsch_ce(LIBLTE_PHY_STRUCT *phy_struct, + float *c_est_0_re, + float *c_est_0_im, + float *c_est_1_re, + float *c_est_1_im, + uint32 N_prb, + uint32 N_subfr, + float *c_est_re, + float *c_est_im) { float *dmrs_0_re; float *dmrs_0_im; @@ -13130,10 +13743,10 @@ void get_ul_ce(LIBLTE_PHY_STRUCT *phy_struct, uint32 L; uint32 M_pusch_sc = N_prb * phy_struct->N_sc_rb_ul; - dmrs_0_re = phy_struct->dmrs_0_re[N_subfr][N_prb]; - dmrs_0_im = phy_struct->dmrs_0_im[N_subfr][N_prb]; - dmrs_1_re = phy_struct->dmrs_1_re[N_subfr][N_prb]; - dmrs_1_im = phy_struct->dmrs_1_im[N_subfr][N_prb]; + dmrs_0_re = phy_struct->pusch_dmrs_0_re[N_subfr][N_prb]; + dmrs_0_im = phy_struct->pusch_dmrs_0_im[N_subfr][N_prb]; + dmrs_1_re = phy_struct->pusch_dmrs_1_re[N_subfr][N_prb]; + dmrs_1_im = phy_struct->pusch_dmrs_1_im[N_subfr][N_prb]; for(i=0; ipucch_dmrs_0_re[N_subfr][N_1_p_pucch]; + dmrs_0_im = phy_struct->pucch_dmrs_0_im[N_subfr][N_1_p_pucch]; + dmrs_1_re = phy_struct->pucch_dmrs_1_re[N_subfr][N_1_p_pucch]; + dmrs_1_im = phy_struct->pucch_dmrs_1_im[N_subfr][N_1_p_pucch]; + + for(i=0; i> (N_bits-i-1)) & 0x1; - } - *bits += N_bits; -} - -/********************************************************************* - Name: phy_bits_2_value - - Description: Converts a bit string to a value - - Document Reference: N/A -*********************************************************************/ -uint32 phy_bits_2_value(uint8 **bits, - uint32 N_bits) -{ - uint32 value = 0; - uint32 i; - - for(i=0; imsg; + uint32 i; -/********************************************************************* - Name: rlc_bits_2_value + if(1 == umd->N_data) + { + err = liblte_rlc_pack_umd_pdu(umd, &umd->data[0], pdu); + }else{ + // Header + if(LIBLTE_RLC_UMD_SN_SIZE_5_BITS == umd->hdr.sn_size) + { + *pdu_ptr = (umd->hdr.fi & 0x03) << 6; + *pdu_ptr |= (LIBLTE_RLC_E_FIELD_HEADER_EXTENDED & 0x01) << 5; + *pdu_ptr |= umd->hdr.sn & 0x1F; + pdu_ptr++; + }else{ + *pdu_ptr = (umd->hdr.fi & 0x03) << 3; + *pdu_ptr |= (LIBLTE_RLC_E_FIELD_HEADER_EXTENDED & 0x01) << 2; + *pdu_ptr |= (umd->hdr.sn & 0x300) >> 8; + pdu_ptr++; + *pdu_ptr = umd->hdr.sn & 0xFF; + pdu_ptr++; + } + for(i=0; iN_data-1; i++) + { + if((i % 2) == 0) + { + if(i != umd->N_data-1) + { + *pdu_ptr = (LIBLTE_RLC_E_FIELD_HEADER_EXTENDED & 0x01) << 7; + }else{ + *pdu_ptr = (LIBLTE_RLC_E_FIELD_HEADER_NOT_EXTENDED & 0x01) << 7; + } + *pdu_ptr |= (umd->data[i].N_bytes & 0x7F0) >> 4; + pdu_ptr++; + *pdu_ptr = (umd->data[i].N_bytes & 0x00F) << 4; + }else{ + if(i != umd->N_data-1) + { + *pdu_ptr |= (LIBLTE_RLC_E_FIELD_HEADER_EXTENDED & 0x01) << 3; + }else{ + *pdu_ptr |= (LIBLTE_RLC_E_FIELD_HEADER_NOT_EXTENDED & 0x01) << 3; + } + *pdu_ptr |= (umd->data[i].N_bytes & 0x700) >> 8; + pdu_ptr++; + *pdu_ptr = umd->data[i].N_bytes & 0x0FF; + pdu_ptr++; + } + } + if((umd->N_data % 2) == 0) + { + pdu_ptr++; + } - Description: Converts a bit string to a value -*********************************************************************/ -uint32 rlc_bits_2_value(uint8 **bits, - uint32 N_bits); + // Data + for(i=0; iN_data; i++) + { + memcpy(pdu_ptr, umd->data[i].msg, umd->data[i].N_bytes); + pdu_ptr += umd->data[i].N_bytes; + } -/******************************************************************************* - PDU FUNCTIONS -*******************************************************************************/ + // Fill in the number of bytes used + pdu->N_bytes = pdu_ptr - pdu->msg; -/********************************************************************* - PDU Type: Unacknowledged Mode Data PDU + err = LIBLTE_SUCCESS; + } - Document Reference: 36.322 v10.0.0 Section 6.2.1.3 -*********************************************************************/ -// FIXME + return(err); +} +LIBLTE_ERROR_ENUM liblte_rlc_pack_umd_pdu(LIBLTE_RLC_UMD_PDU_STRUCT *umd, + LIBLTE_BYTE_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + + if(umd != NULL && + data != NULL && + pdu != NULL) + { + // Header + if(LIBLTE_RLC_UMD_SN_SIZE_5_BITS == umd->hdr.sn_size) + { + *pdu_ptr = (umd->hdr.fi & 0x03) << 6; + *pdu_ptr |= (LIBLTE_RLC_E_FIELD_HEADER_NOT_EXTENDED & 0x01) << 5; + *pdu_ptr |= umd->hdr.sn & 0x1F; + pdu_ptr++; + }else{ + *pdu_ptr = (umd->hdr.fi & 0x03) << 3; + *pdu_ptr |= (LIBLTE_RLC_E_FIELD_HEADER_NOT_EXTENDED & 0x01) << 2; + *pdu_ptr |= (umd->hdr.sn & 0x300) >> 8; + pdu_ptr++; + *pdu_ptr = umd->hdr.sn & 0xFF; + pdu_ptr++; + } + + // Data + memcpy(pdu_ptr, data->msg, data->N_bytes); + pdu_ptr += data->N_bytes; + + // Fill in the number of bytes used + pdu->N_bytes = pdu_ptr - pdu->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rlc_unpack_umd_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_RLC_UMD_PDU_STRUCT *umd) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + LIBLTE_RLC_E_FIELD_ENUM e; + uint32 data_len; + uint32 i; + + if(pdu != NULL && + umd != NULL) + { + // Header + if(LIBLTE_RLC_UMD_SN_SIZE_5_BITS == umd->hdr.sn_size) + { + umd->hdr.fi = (LIBLTE_RLC_FI_FIELD_ENUM)((*pdu_ptr >> 6) & 0x03); + e = (LIBLTE_RLC_E_FIELD_ENUM)((*pdu_ptr >> 5) & 0x01); + umd->hdr.sn = *pdu_ptr & 0x1F; + pdu_ptr++; + }else{ + umd->hdr.fi = (LIBLTE_RLC_FI_FIELD_ENUM)((*pdu_ptr >> 3) & 0x03); + e = (LIBLTE_RLC_E_FIELD_ENUM)((*pdu_ptr >> 2) & 0x01); + umd->hdr.sn = (*pdu_ptr & 0x03) << 8; + pdu_ptr++; + umd->hdr.sn |= *pdu_ptr; + pdu_ptr++; + } + + umd->N_data = 0; + data_len = 0; + while(LIBLTE_RLC_E_FIELD_HEADER_EXTENDED == e) + { + if(LIBLTE_RLC_UMD_MAX_N_DATA == umd->N_data) + { + printf("TOO MANY LI FIELDS\n"); + return(err); + } + if((umd->N_data % 2) == 0) + { + e = (LIBLTE_RLC_E_FIELD_ENUM)((*pdu_ptr >> 7) & 0x01); + umd->data[umd->N_data].N_bytes = (*pdu_ptr & 0x7F) << 4; + pdu_ptr++; + umd->data[umd->N_data].N_bytes |= (*pdu_ptr & 0xF0) >> 4; + }else{ + e = (LIBLTE_RLC_E_FIELD_ENUM)((*pdu_ptr >> 3) & 0x01); + umd->data[umd->N_data].N_bytes = (*pdu_ptr & 0x07) << 8; + pdu_ptr++; + umd->data[umd->N_data].N_bytes |= *pdu_ptr; + pdu_ptr++; + } + data_len += umd->data[umd->N_data].N_bytes; + umd->N_data++; + } + if(LIBLTE_RLC_UMD_MAX_N_DATA == umd->N_data) + { + printf("TOO MANY LI FIELDS\n"); + return(err); + } + umd->N_data++; + if((umd->N_data % 2) == 0) + { + pdu_ptr++; + } + umd->data[umd->N_data-1].N_bytes = pdu->N_bytes - (pdu_ptr - pdu->msg) - data_len; + + // Data + for(i=0; iN_data; i++) + { + memcpy(umd->data[i].msg, pdu_ptr, umd->data[i].N_bytes); + pdu_ptr += umd->data[i].N_bytes; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* PDU Type: Acknowledged Mode Data PDU Document Reference: 36.322 v10.0.0 Sections 6.2.1.4 & 6.2.1.5 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_rlc_pack_amd_pdu(LIBLTE_RLC_AMD_PDU_STRUCT *amd, - LIBLTE_BIT_MSG_STRUCT *pdu) +LIBLTE_ERROR_ENUM liblte_rlc_pack_amd_pdu(LIBLTE_RLC_AMD_PDUS_STRUCT *amd, + LIBLTE_BYTE_MSG_STRUCT *pdu) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + uint32 i; + + if(1 == amd->N_pdu) + { + err = liblte_rlc_pack_amd_pdu(&amd->pdu[0], &amd->pdu[0].data, pdu); + }else{ + // Header + *pdu_ptr = (amd->pdu[0].hdr.dc & 0x01) << 7; + *pdu_ptr |= (amd->pdu[0].hdr.rf & 0x01) << 6; + *pdu_ptr |= (amd->pdu[0].hdr.p & 0x01) << 5; + *pdu_ptr |= (amd->pdu[0].hdr.fi & 0x03) << 3; + *pdu_ptr |= (LIBLTE_RLC_E_FIELD_HEADER_EXTENDED & 0x01) << 2; + *pdu_ptr |= (amd->pdu[0].hdr.sn & 0x300) >> 8; + pdu_ptr++; + *pdu_ptr = amd->pdu[0].hdr.sn & 0xFF; + pdu_ptr++; + for(i=0; iN_pdu-1; i++) + { + if((i % 2) == 0) + { + if(i != amd->N_pdu-1) + { + *pdu_ptr = (LIBLTE_RLC_E_FIELD_HEADER_EXTENDED & 0x01) << 7; + }else{ + *pdu_ptr = (LIBLTE_RLC_E_FIELD_HEADER_NOT_EXTENDED & 0x01) << 7; + } + *pdu_ptr |= (amd->pdu[i].data.N_bytes & 0x7F0) >> 4; + pdu_ptr++; + *pdu_ptr = (amd->pdu[i].data.N_bytes & 0x00F) << 4; + }else{ + if(i != amd->N_pdu-1) + { + *pdu_ptr |= (LIBLTE_RLC_E_FIELD_HEADER_EXTENDED & 0x01) << 3; + }else{ + *pdu_ptr |= (LIBLTE_RLC_E_FIELD_HEADER_NOT_EXTENDED & 0x01) << 3; + } + *pdu_ptr |= (amd->pdu[i].data.N_bytes & 0x700) >> 8; + pdu_ptr++; + *pdu_ptr = amd->pdu[i].data.N_bytes & 0x0FF; + pdu_ptr++; + } + } + if((amd->N_pdu % 2) == 0) + { + pdu_ptr++; + } + + // Data + for(i=0; iN_pdu; i++) + { + memcpy(pdu_ptr, amd->pdu[i].data.msg, amd->pdu[i].data.N_bytes); + pdu_ptr += amd->pdu[i].data.N_bytes; + } + + // Fill in the number of bytes used + pdu->N_bytes = pdu_ptr - pdu->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rlc_pack_amd_pdu(LIBLTE_RLC_SINGLE_AMD_PDU_STRUCT *amd, + LIBLTE_BYTE_MSG_STRUCT *data, + LIBLTE_BYTE_MSG_STRUCT *pdu) { - // FIXME + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + + if(amd != NULL && + data != NULL && + pdu != NULL) + { + // Header + *pdu_ptr = (amd->hdr.dc & 0x01) << 7; + *pdu_ptr |= (amd->hdr.rf & 0x01) << 6; + *pdu_ptr |= (amd->hdr.p & 0x01) << 5; + *pdu_ptr |= (amd->hdr.fi & 0x03) << 3; + *pdu_ptr |= (LIBLTE_RLC_E_FIELD_HEADER_NOT_EXTENDED & 0x01) << 2; + *pdu_ptr |= (amd->hdr.sn & 0x300) >> 8; + pdu_ptr++; + *pdu_ptr = amd->hdr.sn & 0xFF; + pdu_ptr++; + if(LIBLTE_RLC_RF_FIELD_AMD_PDU_SEGMENT == amd->hdr.rf) + { + *pdu_ptr = (amd->hdr.lsf & 0x01) << 7; + *pdu_ptr |= (amd->hdr.so & 0x7F00) >> 8; + pdu_ptr++; + *pdu_ptr = amd->hdr.so & 0xFF; + } + + // Data + memcpy(pdu_ptr, data->msg, data->N_bytes); + pdu_ptr += data->N_bytes; + + // Fill in the number of bytes used + pdu->N_bytes = pdu_ptr - pdu->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); } -LIBLTE_ERROR_ENUM liblte_rlc_unpack_amd_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, - LIBLTE_RLC_AMD_PDU_STRUCT *amd) +LIBLTE_ERROR_ENUM liblte_rlc_unpack_amd_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, + LIBLTE_RLC_AMD_PDUS_STRUCT *amd) { - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - uint8 *pdu_ptr = pdu->msg; - LIBLTE_RLC_DC_FIELD_ENUM dc; - LIBLTE_RLC_E_FIELD_ENUM e; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *pdu_ptr = pdu->msg; + LIBLTE_RLC_E_FIELD_ENUM e; + uint32 data_len; + uint32 i; if(pdu != NULL && amd != NULL) { // Header - dc = (LIBLTE_RLC_DC_FIELD_ENUM)rlc_bits_2_value(&pdu_ptr, 1); + amd->pdu[0].hdr.dc = (LIBLTE_RLC_DC_FIELD_ENUM)((*pdu_ptr >> 7) & 0x01); - if(LIBLTE_RLC_DC_FIELD_DATA_PDU == dc) + if(LIBLTE_RLC_DC_FIELD_DATA_PDU == amd->pdu[0].hdr.dc) { // Header - amd->hdr.rf = (LIBLTE_RLC_RF_FIELD_ENUM)rlc_bits_2_value(&pdu_ptr, 1); - amd->hdr.p = (LIBLTE_RLC_P_FIELD_ENUM)rlc_bits_2_value(&pdu_ptr, 1); - amd->hdr.fi = (LIBLTE_RLC_FI_FIELD_ENUM)rlc_bits_2_value(&pdu_ptr, 2); - e = (LIBLTE_RLC_E_FIELD_ENUM)rlc_bits_2_value(&pdu_ptr, 1); - amd->hdr.sn = rlc_bits_2_value(&pdu_ptr, 10); - - if(LIBLTE_RLC_RF_FIELD_AMD_PDU_SEGMENT == amd->hdr.rf) + amd->pdu[0].hdr.rf = (LIBLTE_RLC_RF_FIELD_ENUM)((*pdu_ptr >> 6) & 0x01); + amd->pdu[0].hdr.p = (LIBLTE_RLC_P_FIELD_ENUM)((*pdu_ptr >> 5) & 0x01); + amd->pdu[0].hdr.fi = (LIBLTE_RLC_FI_FIELD_ENUM)((*pdu_ptr >> 3) & 0x03); + e = (LIBLTE_RLC_E_FIELD_ENUM)((*pdu_ptr >> 2) & 0x01); + amd->pdu[0].hdr.sn = (*pdu_ptr & 0x03) << 8; + pdu_ptr++; + amd->pdu[0].hdr.sn |= *pdu_ptr; + pdu_ptr++; + if(LIBLTE_RLC_RF_FIELD_AMD_PDU_SEGMENT == amd->pdu[0].hdr.rf) { - // FIXME - printf("Not handling AMD PDU SEGMENTS\n"); + amd->pdu[0].hdr.lsf = (LIBLTE_RLC_LSF_FIELD_ENUM)((*pdu_ptr >> 7) & 0x01); + amd->pdu[0].hdr.so = (*pdu_ptr & 0x7F) << 8; + pdu_ptr++; + amd->pdu[0].hdr.so |= *pdu_ptr; } - if(LIBLTE_RLC_E_FIELD_HEADER_EXTENDED == e) + amd->N_pdu = 0; + data_len = 0; + while(LIBLTE_RLC_E_FIELD_HEADER_EXTENDED == e) + { + if(LIBLTE_RLC_AMD_MAX_N_PDU == amd->N_pdu) + { + printf("TOO MANY LI FIELDS\n"); + return(err); + } + if((amd->N_pdu % 2) == 0) + { + e = (LIBLTE_RLC_E_FIELD_ENUM)((*pdu_ptr >> 7) & 0x01); + amd->pdu[amd->N_pdu].data.N_bytes = (*pdu_ptr & 0x7F) << 4; + pdu_ptr++; + amd->pdu[amd->N_pdu].data.N_bytes |= (*pdu_ptr & 0xF0) >> 4; + }else{ + e = (LIBLTE_RLC_E_FIELD_ENUM)((*pdu_ptr >> 3) & 0x01); + amd->pdu[amd->N_pdu].data.N_bytes = (*pdu_ptr & 0x07) << 8; + pdu_ptr++; + amd->pdu[amd->N_pdu].data.N_bytes |= *pdu_ptr; + pdu_ptr++; + } + data_len += amd->pdu[amd->N_pdu].data.N_bytes; + amd->N_pdu++; + } + if(LIBLTE_RLC_AMD_MAX_N_PDU == amd->N_pdu) + { + printf("TOO MANY LI FIELDS\n"); + return(err); + } + amd->N_pdu++; + if((amd->N_pdu % 2) == 0) { - // FIXME - printf("Not handling HEADER EXTENSION\n"); + pdu_ptr++; } + amd->pdu[amd->N_pdu-1].data.N_bytes = pdu->N_bytes - (pdu_ptr - pdu->msg) - data_len; // Data - amd->data.N_bits = pdu->N_bits - (pdu_ptr - pdu->msg); - memcpy(amd->data.msg, pdu_ptr, amd->data.N_bits); + for(i=0; iN_pdu; i++) + { + // Blindly copy the original header to all PDUs + if(0 != i) + { + memcpy(&amd->pdu[i].hdr, &amd->pdu[0].hdr, sizeof(amd->pdu[i].hdr)); + } + memcpy(amd->pdu[i].data.msg, pdu_ptr, amd->pdu[i].data.N_bytes); + pdu_ptr += amd->pdu[i].data.N_bytes; + } - err = LIBLTE_SUCCESS; + // Fix the FI field in all headers + if(1 != amd->N_pdu) + { + // Deal with the first PDU + if(LIBLTE_RLC_FI_FIELD_FIRST_SDU_SEGMENT == amd->pdu[0].hdr.fi || + LIBLTE_RLC_FI_FIELD_FULL_SDU == amd->pdu[0].hdr.fi) + { + // Change a first or full to a full + amd->pdu[0].hdr.fi = LIBLTE_RLC_FI_FIELD_FULL_SDU; + }else{ + // Change all others to a last + amd->pdu[0].hdr.fi = LIBLTE_RLC_FI_FIELD_LAST_SDU_SEGMENT; + } + + // Deal with the last PDU + if(LIBLTE_RLC_FI_FIELD_LAST_SDU_SEGMENT == amd->pdu[amd->N_pdu-1].hdr.fi || + LIBLTE_RLC_FI_FIELD_FULL_SDU == amd->pdu[amd->N_pdu-1].hdr.fi) + { + // Change a last or full to a full + amd->pdu[amd->N_pdu-1].hdr.fi = LIBLTE_RLC_FI_FIELD_FULL_SDU; + }else{ + // Change all others to a first + amd->pdu[amd->N_pdu-1].hdr.fi = LIBLTE_RLC_FI_FIELD_FIRST_SDU_SEGMENT; + } + + // Deal with all other PDUs + for(i=1; iN_pdu-1; i++) + { + // All others must be full + amd->pdu[i].hdr.fi = LIBLTE_RLC_FI_FIELD_FULL_SDU; + } + } } + + err = LIBLTE_SUCCESS; } return(err); @@ -143,80 +501,124 @@ LIBLTE_ERROR_ENUM liblte_rlc_unpack_amd_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, Document Reference: 36.322 v10.0.0 Section 6.2.1.6 *********************************************************************/ LIBLTE_ERROR_ENUM liblte_rlc_pack_status_pdu(LIBLTE_RLC_STATUS_PDU_STRUCT *status, - LIBLTE_BIT_MSG_STRUCT *pdu) + LIBLTE_BYTE_MSG_STRUCT *pdu) { - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - uint8 *pdu_ptr = pdu->msg; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_BIT_MSG_STRUCT tmp_pdu; + uint8 *pdu_ptr = tmp_pdu.msg; + uint32 i; if(status != NULL && pdu != NULL) { // D/C Field - rlc_value_2_bits(LIBLTE_RLC_DC_FIELD_CONTROL_PDU, &pdu_ptr, 1); + liblte_value_2_bits(LIBLTE_RLC_DC_FIELD_CONTROL_PDU, &pdu_ptr, 1); // CPT Field - rlc_value_2_bits(LIBLTE_RLC_CPT_FIELD_STATUS_PDU, &pdu_ptr, 3); + liblte_value_2_bits(LIBLTE_RLC_CPT_FIELD_STATUS_PDU, &pdu_ptr, 3); // ACK SN - rlc_value_2_bits(status->ack_sn, &pdu_ptr, 10); + liblte_value_2_bits(status->ack_sn, &pdu_ptr, 10); // E1 - rlc_value_2_bits(LIBLTE_RLC_E1_FIELD_NOT_EXTENDED, &pdu_ptr, 1); + if(status->N_nack == 0) + { + liblte_value_2_bits(LIBLTE_RLC_E1_FIELD_NOT_EXTENDED, &pdu_ptr, 1); + }else{ + liblte_value_2_bits(LIBLTE_RLC_E1_FIELD_EXTENDED, &pdu_ptr, 1); + } + + for(i=0; iN_nack; i++) + { + // NACK SN + liblte_value_2_bits(status->nack_sn[i], &pdu_ptr, 10); + + // E1 + if(i == (status->N_nack-1)) + { + liblte_value_2_bits(LIBLTE_RLC_E1_FIELD_NOT_EXTENDED, &pdu_ptr, 1); + }else{ + liblte_value_2_bits(LIBLTE_RLC_E1_FIELD_EXTENDED, &pdu_ptr, 1); + } + + // E2 + liblte_value_2_bits(LIBLTE_RLC_E2_FIELD_NOT_EXTENDED, &pdu_ptr, 1); + + // FIXME: Skipping SOstart and SOend + } + + tmp_pdu.N_bits = pdu_ptr - tmp_pdu.msg; // Padding - rlc_value_2_bits(0, &pdu_ptr, 1); + if((tmp_pdu.N_bits % 8) != 0) + { + for(i=0; i<(8 - (tmp_pdu.N_bits % 8)); i++) + { + liblte_value_2_bits(0, &pdu_ptr, 1); + } + tmp_pdu.N_bits = pdu_ptr - tmp_pdu.msg; + } - pdu->N_bits = pdu_ptr - pdu->msg; + // Convert from bit to byte struct + pdu_ptr = tmp_pdu.msg; + for(i=0; imsg[i] = liblte_bits_2_value(&pdu_ptr, 8); + } + pdu->N_bytes = tmp_pdu.N_bits/8; err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_rlc_unpack_status_pdu(LIBLTE_BIT_MSG_STRUCT *pdu, +LIBLTE_ERROR_ENUM liblte_rlc_unpack_status_pdu(LIBLTE_BYTE_MSG_STRUCT *pdu, LIBLTE_RLC_STATUS_PDU_STRUCT *status) { - // FIXME -} - -/******************************************************************************* - LOCAL FUNCTIONS -*******************************************************************************/ - -/********************************************************************* - Name: rlc_value_2_bits - - Description: Converts a value to a bit string -*********************************************************************/ -void rlc_value_2_bits(uint32 value, - uint8 **bits, - uint32 N_bits) -{ - uint32 i; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_BIT_MSG_STRUCT tmp_pdu; + uint8 *pdu_ptr = tmp_pdu.msg; + LIBLTE_RLC_DC_FIELD_ENUM dc; + LIBLTE_RLC_E1_FIELD_ENUM e; + uint32 i; + uint8 cpt; - for(i=0; i> (N_bits-i-1)) & 0x1; - } - *bits += N_bits; -} + // Convert from byte to bit struct + for(i=0; iN_bytes; i++) + { + liblte_value_2_bits(pdu->msg[i], &pdu_ptr, 8); + } + tmp_pdu.N_bits = pdu->N_bytes*8; + pdu_ptr = tmp_pdu.msg; -/********************************************************************* - Name: rlc_bits_2_value + // D/C Field + dc = (LIBLTE_RLC_DC_FIELD_ENUM)liblte_bits_2_value(&pdu_ptr, 1); - Description: Converts a bit string to a value -*********************************************************************/ -uint32 rlc_bits_2_value(uint8 **bits, - uint32 N_bits) -{ - uint32 value = 0; - uint32 i; + if(LIBLTE_RLC_DC_FIELD_CONTROL_PDU == dc) + { + cpt = liblte_bits_2_value(&pdu_ptr, 3); - for(i=0; iack_sn = liblte_bits_2_value(&pdu_ptr, 10); + e = (LIBLTE_RLC_E1_FIELD_ENUM)liblte_bits_2_value(&pdu_ptr, 1); + status->N_nack = 0; + while(LIBLTE_RLC_E1_FIELD_EXTENDED == e) + { + status->nack_sn[status->N_nack++] = liblte_bits_2_value(&pdu_ptr, 10); + e = (LIBLTE_RLC_E1_FIELD_ENUM)liblte_bits_2_value(&pdu_ptr, 1); + if(LIBLTE_RLC_E2_FIELD_EXTENDED == liblte_bits_2_value(&pdu_ptr, 1)) + { + // FIXME: Skipping SOstart and SOend + liblte_bits_2_value(&pdu_ptr, 29); + } + } + } + } } - *bits += N_bits; - return(value); + return(LIBLTE_SUCCESS); } diff --git a/liblte/src/liblte_rrc.cc b/liblte/src/liblte_rrc.cc old mode 100644 new mode 100755 index ddc2dde..1c82d4f --- a/liblte/src/liblte_rrc.cc +++ b/liblte/src/liblte_rrc.cc @@ -1,6 +1,10 @@ /******************************************************************************* - Copyright 2012-2014 Ben Wojtowicz + Copyright 2012-2016 Ben Wojtowicz + Copyright 2014 Andrew Murphy (SIB13 unpack) + Copyright 2016 Przemek Bereski (UE capability RAT container list IE, + UE capability information message, and + UE capability enquiry message pack/unpack) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -43,6 +47,27 @@ and UL CCCH Messages. 05/04/2014 Ben Wojtowicz Added support for DL CCCH Messages. 06/15/2014 Ben Wojtowicz Added support for UL DCCH Messages. + 08/03/2014 Ben Wojtowicz Added more decoding/encoding and using the + common value_2_bits and bits_2_value + functions. + 09/19/2014 Andrew Murphy Added SIB13 unpack. + 11/01/2014 Ben Wojtowicz Added more decoding/encoding. + 11/09/2014 Ben Wojtowicz Added SIB13 pack. + 11/29/2014 Ben Wojtowicz Fixed a bug in RRC connection reestablishment + UE identity. + 03/11/2015 Ben Wojtowicz Converting to/from actual hysteresis value. + 07/25/2015 Ben Wojtowicz Fixed a bug with the default value of + filter_coeff in + LIBLTE_RRC_UL_POWER_CONTROL_DEDICATED_STRUCT. + Thanks to Paul Sutton for finding this. + 07/03/2016 Ben Wojtowicz Added PMCH info list, PCI range UTRA FDD + list, system info list GERAN, cross carrier + scheduling config, CSI RS config, and RN + subframe config IE support. + 07/03/2016 Przemek Bereski Added UE capability RAT container list IE, + UE capability information message, and UE + capability enquiry message support. + 10/09/2016 Ben Wojtowicz Properly discarding sequence type extensions. *******************************************************************************/ @@ -73,21 +98,17 @@ LIBLTE_BIT_MSG_STRUCT global_msg; *******************************************************************************/ /********************************************************************* - Name: rrc_value_2_bits + Name: skip_sequence_type_extension - Description: Converts a value to a bit string -*********************************************************************/ -void rrc_value_2_bits(uint32 value, - uint8 **bits, - uint32 N_bits); - -/********************************************************************* - Name: rrc_bits_2_value + Description: Skips an ASN.1 sequence type extension - Description: Converts a bit string to a value + Document Reference: ITU X.691 Section 18 *********************************************************************/ -uint32 rrc_bits_2_value(uint8 **bits, - uint32 N_bits); +// Defines +// Enums +// Structs +// Functions +void skip_sequence_type_extension(bool ext_ind, uint8 **ptr); /******************************************************************************* INFORMATION ELEMENT FUNCTIONS @@ -109,9 +130,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_mbsfn_notification_config_ie(LIBLTE_RRC_MBSFN_ if(mbsfn_notification_cnfg != NULL && ie_ptr != NULL) { - rrc_value_2_bits(mbsfn_notification_cnfg->repetition_coeff, ie_ptr, 1); - rrc_value_2_bits(mbsfn_notification_cnfg->offset, ie_ptr, 4); - rrc_value_2_bits(mbsfn_notification_cnfg->sf_index - 1, ie_ptr, 3); + liblte_value_2_bits(mbsfn_notification_cnfg->repetition_coeff, ie_ptr, 1); + liblte_value_2_bits(mbsfn_notification_cnfg->offset, ie_ptr, 4); + liblte_value_2_bits(mbsfn_notification_cnfg->sf_index - 1, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -126,9 +147,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mbsfn_notification_config_ie(uint8 if(ie_ptr != NULL && mbsfn_notification_cnfg != NULL) { - mbsfn_notification_cnfg->repetition_coeff = (LIBLTE_RRC_NOTIFICATION_REPETITION_COEFF_R9_ENUM)rrc_bits_2_value(ie_ptr, 1); - mbsfn_notification_cnfg->offset = rrc_bits_2_value(ie_ptr, 4); - mbsfn_notification_cnfg->sf_index = rrc_bits_2_value(ie_ptr, 3) + 1; + mbsfn_notification_cnfg->repetition_coeff = (LIBLTE_RRC_NOTIFICATION_REPETITION_COEFF_R9_ENUM)liblte_bits_2_value(ie_ptr, 1); + mbsfn_notification_cnfg->offset = liblte_bits_2_value(ie_ptr, 4); + mbsfn_notification_cnfg->sf_index = liblte_bits_2_value(ie_ptr, 3) + 1; err = LIBLTE_SUCCESS; } @@ -145,7 +166,59 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mbsfn_notification_config_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.7 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_mbsfn_area_info_ie(LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *mbsfn_area_info, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(mbsfn_area_info != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + liblte_value_2_bits(mbsfn_area_info->mbsfn_area_id_r9, ie_ptr, 8); + liblte_value_2_bits(mbsfn_area_info->non_mbsfn_region_length, ie_ptr, 1); + liblte_value_2_bits(mbsfn_area_info->notification_indicator_r9, ie_ptr, 3); + liblte_value_2_bits(mbsfn_area_info->mcch_repetition_period_r9, ie_ptr, 2); + liblte_value_2_bits(mbsfn_area_info->mcch_offset_r9, ie_ptr, 4); + liblte_value_2_bits(mbsfn_area_info->mcch_modification_period_r9, ie_ptr, 1); + liblte_value_2_bits(mbsfn_area_info->sf_alloc_info_r9, ie_ptr, 6); + liblte_value_2_bits(mbsfn_area_info->signalling_mcs_r9, ie_ptr, 2); + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_mbsfn_area_info_ie(uint8 **ie_ptr, + LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *mbsfn_area_info) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; + + if(ie_ptr != NULL && + mbsfn_area_info != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + mbsfn_area_info->mbsfn_area_id_r9 = liblte_bits_2_value(ie_ptr, 8); + mbsfn_area_info->non_mbsfn_region_length = (LIBLTE_RRC_NON_MBSFN_REGION_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1); + mbsfn_area_info->notification_indicator_r9 = liblte_bits_2_value(ie_ptr, 3); + mbsfn_area_info->mcch_repetition_period_r9 = (LIBLTE_RRC_MCCH_REPETITION_PERIOD_ENUM)liblte_bits_2_value(ie_ptr, 2); + mbsfn_area_info->mcch_offset_r9 = liblte_bits_2_value(ie_ptr, 4); + mbsfn_area_info->mcch_modification_period_r9 = (LIBLTE_RRC_MCCH_MODIFICATION_PERIOD_ENUM)liblte_bits_2_value(ie_ptr, 1); + mbsfn_area_info->sf_alloc_info_r9 = liblte_bits_2_value(ie_ptr, 6); + mbsfn_area_info->signalling_mcs_r9 = (LIBLTE_RRC_MCCH_SIGNALLING_MCS_ENUM)liblte_bits_2_value(ie_ptr, 2); + + skip_sequence_type_extension(ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* IE Name: MBSFN Subframe Config @@ -163,14 +236,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_mbsfn_subframe_config_ie(LIBLTE_RRC_MBSFN_SUBF if(mbsfn_subfr_cnfg != NULL && ie_ptr != NULL) { - rrc_value_2_bits(mbsfn_subfr_cnfg->radio_fr_alloc_period, ie_ptr, 3); - rrc_value_2_bits(mbsfn_subfr_cnfg->radio_fr_alloc_offset, ie_ptr, 3); - rrc_value_2_bits(mbsfn_subfr_cnfg->subfr_alloc_num_frames, ie_ptr, 1); + liblte_value_2_bits(mbsfn_subfr_cnfg->radio_fr_alloc_period, ie_ptr, 3); + liblte_value_2_bits(mbsfn_subfr_cnfg->radio_fr_alloc_offset, ie_ptr, 3); + liblte_value_2_bits(mbsfn_subfr_cnfg->subfr_alloc_num_frames, ie_ptr, 1); if(LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE == mbsfn_subfr_cnfg->subfr_alloc_num_frames) { - rrc_value_2_bits(mbsfn_subfr_cnfg->subfr_alloc, ie_ptr, 6); + liblte_value_2_bits(mbsfn_subfr_cnfg->subfr_alloc, ie_ptr, 6); }else{ - rrc_value_2_bits(mbsfn_subfr_cnfg->subfr_alloc, ie_ptr, 24); + liblte_value_2_bits(mbsfn_subfr_cnfg->subfr_alloc, ie_ptr, 24); } err = LIBLTE_SUCCESS; @@ -186,14 +259,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mbsfn_subframe_config_ie(uint8 if(ie_ptr != NULL && mbsfn_subfr_cnfg != NULL) { - mbsfn_subfr_cnfg->radio_fr_alloc_period = (LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_ENUM)rrc_bits_2_value(ie_ptr, 3); - mbsfn_subfr_cnfg->radio_fr_alloc_offset = rrc_bits_2_value(ie_ptr, 3); - mbsfn_subfr_cnfg->subfr_alloc_num_frames = (LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ENUM)rrc_bits_2_value(ie_ptr, 1); + mbsfn_subfr_cnfg->radio_fr_alloc_period = (LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_ENUM)liblte_bits_2_value(ie_ptr, 3); + mbsfn_subfr_cnfg->radio_fr_alloc_offset = liblte_bits_2_value(ie_ptr, 3); + mbsfn_subfr_cnfg->subfr_alloc_num_frames = (LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ENUM)liblte_bits_2_value(ie_ptr, 1); if(LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE == mbsfn_subfr_cnfg->subfr_alloc_num_frames) { - mbsfn_subfr_cnfg->subfr_alloc = rrc_bits_2_value(ie_ptr, 6); + mbsfn_subfr_cnfg->subfr_alloc = liblte_bits_2_value(ie_ptr, 6); }else{ - mbsfn_subfr_cnfg->subfr_alloc = rrc_bits_2_value(ie_ptr, 24); + mbsfn_subfr_cnfg->subfr_alloc = liblte_bits_2_value(ie_ptr, 24); } err = LIBLTE_SUCCESS; @@ -209,7 +282,136 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mbsfn_subframe_config_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.7 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_pmch_info_list_ie(LIBLTE_RRC_PMCH_INFO_LIST_STRUCT *pmch_info_list, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + uint32 j; + + if(pmch_info_list != NULL && + ie_ptr != NULL) + { + liblte_value_2_bits(pmch_info_list->pmch_info_list_size, ie_ptr, 4); + for(i=0; ipmch_info_list_size; i++) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // PMCH Config + liblte_value_2_bits(0, ie_ptr, 1); // Extension indicator + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].pmch_config.sf_alloc_end, ie_ptr, 11); + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].pmch_config.data_mcs, ie_ptr, 5); + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].pmch_config.mch_scheduling_period, ie_ptr, 3); + + // MBMS Session Info List + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].mbms_session_info_list_size, ie_ptr, 5); + for(j=0; jpmch_info_list[i].mbms_session_info_list_size; j++) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Optional indicator + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].session_id_present, ie_ptr, 1); + + // TMGI + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.plmn_id_choice, ie_ptr, 1); + if(LIBLTE_RRC_PLMN_ID_CHOICE_INDEX == pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.plmn_id_choice) + { + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.plmn_idx - 1, ie_ptr, 3); + }else{ + liblte_rrc_pack_plmn_identity_ie(&pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.plmn_id, + ie_ptr); + } + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.service_id[0], ie_ptr, 8); + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.service_id[1], ie_ptr, 8); + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.service_id[2], ie_ptr, 8); + + // Session ID + if(pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].session_id_present) + { + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].session_id, ie_ptr, 8); + } + + // Logical Channel Identity + liblte_value_2_bits(pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].logical_channel_id, ie_ptr, 5); + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_pmch_info_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_PMCH_INFO_LIST_STRUCT *pmch_info_list) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + uint32 j; + bool pmch_info_ext_ind; + bool pmch_config_ext_ind; + bool mbms_session_info_ext_ind; + + if(ie_ptr != NULL && + pmch_info_list != NULL) + { + pmch_info_list->pmch_info_list_size = liblte_bits_2_value(ie_ptr, 4); + for(i=0; ipmch_info_list_size; i++) + { + // Extension indicator + pmch_info_ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // PMCH Config + pmch_config_ext_ind = liblte_bits_2_value(ie_ptr, 1); + pmch_info_list->pmch_info_list[i].pmch_config.sf_alloc_end = liblte_bits_2_value(ie_ptr, 11); + pmch_info_list->pmch_info_list[i].pmch_config.data_mcs = liblte_bits_2_value(ie_ptr, 5); + pmch_info_list->pmch_info_list[i].pmch_config.mch_scheduling_period = (LIBLTE_RRC_MCH_SCHEDULING_PERIOD_ENUM)liblte_bits_2_value(ie_ptr, 3); + skip_sequence_type_extension(pmch_config_ext_ind, ie_ptr); + + // MBMS Session Info List + pmch_info_list->pmch_info_list[i].mbms_session_info_list_size = liblte_bits_2_value(ie_ptr, 5); + for(j=0; jpmch_info_list[i].mbms_session_info_list_size; j++) + { + // Extension indicator + mbms_session_info_ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Optional indicator + pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].session_id_present = liblte_bits_2_value(ie_ptr, 1); + + // TMGI + pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.plmn_id_choice = (LIBLTE_RRC_PLMN_ID_CHOICE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_PLMN_ID_CHOICE_INDEX == pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.plmn_id_choice) + { + pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.plmn_idx = liblte_bits_2_value(ie_ptr, 3) + 1; + }else{ + liblte_rrc_unpack_plmn_identity_ie(ie_ptr, + &pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.plmn_id); + } + pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.service_id[0] = liblte_bits_2_value(ie_ptr, 8); + pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.service_id[1] = liblte_bits_2_value(ie_ptr, 8); + pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].tmgi.service_id[2] = liblte_bits_2_value(ie_ptr, 8); + + // Session ID + if(pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].session_id_present) + { + pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].session_id = liblte_bits_2_value(ie_ptr, 8); + } + + // Logical Channel Identity + pmch_info_list->pmch_info_list[i].mbms_session_info_list[j].logical_channel_id = liblte_bits_2_value(ie_ptr, 5); + + skip_sequence_type_extension(mbms_session_info_ext_ind, ie_ptr); + } + + skip_sequence_type_extension(pmch_info_ext_ind, ie_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* IE Name: C-RNTI @@ -225,7 +427,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_c_rnti_ie(uint16 rnti, if(ie_ptr != NULL) { - rrc_value_2_bits(rnti, ie_ptr, 16); + liblte_value_2_bits(rnti, ie_ptr, 16); err = LIBLTE_SUCCESS; } @@ -240,7 +442,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_c_rnti_ie(uint8 **ie_ptr, if(ie_ptr != NULL && rnti != NULL) { - *rnti = rrc_bits_2_value(ie_ptr, 16); + *rnti = liblte_bits_2_value(ie_ptr, 16); err = LIBLTE_SUCCESS; } @@ -256,9 +458,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_c_rnti_ie(uint8 **ie_ptr, Document Reference: 36.331 v10.0.0 Section 6.3.6 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(uint8 *ded_info_cdma2000, - uint32 length, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(LIBLTE_BYTE_MSG_STRUCT *ded_info_cdma2000, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; @@ -266,21 +467,21 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(uint8 *ded_info_c if(ded_info_cdma2000 != NULL && ie_ptr != NULL) { - if(length < 128) + if(ded_info_cdma2000->N_bytes < 128) { - rrc_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(length, ie_ptr, 7); - }else if(length < 16383){ - rrc_value_2_bits(1, ie_ptr, 1); - rrc_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(length, ie_ptr, 14); + liblte_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(ded_info_cdma2000->N_bytes, ie_ptr, 7); + }else if(ded_info_cdma2000->N_bytes < 16383){ + liblte_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(ded_info_cdma2000->N_bytes, ie_ptr, 14); }else{ // FIXME: Unlikely to have more than 16K of octets } - for(i=0; iN_bytes; i++) { - rrc_value_2_bits(ded_info_cdma2000[i], ie_ptr, 8); + liblte_value_2_bits(ded_info_cdma2000->msg[i], ie_ptr, 8); } err = LIBLTE_SUCCESS; @@ -288,9 +489,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(uint8 *ded_info_c return(err); } -LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_cdma2000_ie(uint8 **ie_ptr, - uint8 *ded_info_cdma2000, - uint32 *length) +LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_cdma2000_ie(uint8 **ie_ptr, + LIBLTE_BYTE_MSG_STRUCT *ded_info_cdma2000) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; @@ -298,22 +498,22 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_cdma2000_ie(uint8 **ie_ptr, if(ie_ptr != NULL && ded_info_cdma2000 != NULL) { - if(0 == rrc_bits_2_value(ie_ptr, 1)) + if(0 == liblte_bits_2_value(ie_ptr, 1)) { - *length = rrc_bits_2_value(ie_ptr, 7); + ded_info_cdma2000->N_bytes = liblte_bits_2_value(ie_ptr, 7); }else{ - if(0 == rrc_bits_2_value(ie_ptr, 1)) + if(0 == liblte_bits_2_value(ie_ptr, 1)) { - *length = rrc_bits_2_value(ie_ptr, 14); + ded_info_cdma2000->N_bytes = liblte_bits_2_value(ie_ptr, 14); }else{ // FIXME: Unlikely to have more than 16K of octets - *length = 0; + ded_info_cdma2000->N_bytes = 0; } } - for(i=0; i<*length; i++) + for(i=0; iN_bytes; i++) { - ded_info_cdma2000[i] = rrc_bits_2_value(ie_ptr, 8); + ded_info_cdma2000->msg[i] = liblte_bits_2_value(ie_ptr, 8); } err = LIBLTE_SUCCESS; @@ -341,19 +541,19 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_nas_ie(LIBLTE_BYTE_MSG_STRUCT { if(ded_info_nas->N_bytes < 128) { - rrc_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(ded_info_nas->N_bytes, ie_ptr, 7); + liblte_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(ded_info_nas->N_bytes, ie_ptr, 7); }else if(ded_info_nas->N_bytes < 16383){ - rrc_value_2_bits(1, ie_ptr, 1); - rrc_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(ded_info_nas->N_bytes, ie_ptr, 14); + liblte_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(ded_info_nas->N_bytes, ie_ptr, 14); }else{ // FIXME: Unlikely to have more than 16K of octets } for(i=0; iN_bytes; i++) { - rrc_value_2_bits(ded_info_nas->msg[i], ie_ptr, 8); + liblte_value_2_bits(ded_info_nas->msg[i], ie_ptr, 8); } err = LIBLTE_SUCCESS; @@ -370,13 +570,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_nas_ie(uint8 if(ie_ptr != NULL && ded_info_nas != NULL) { - if(0 == rrc_bits_2_value(ie_ptr, 1)) + if(0 == liblte_bits_2_value(ie_ptr, 1)) { - ded_info_nas->N_bytes = rrc_bits_2_value(ie_ptr, 7); + ded_info_nas->N_bytes = liblte_bits_2_value(ie_ptr, 7); }else{ - if(0 == rrc_bits_2_value(ie_ptr, 1)) + if(0 == liblte_bits_2_value(ie_ptr, 1)) { - ded_info_nas->N_bytes = rrc_bits_2_value(ie_ptr, 14); + ded_info_nas->N_bytes = liblte_bits_2_value(ie_ptr, 14); }else{ // FIXME: Unlikely to have more than 16K of octets ded_info_nas->N_bytes = 0; @@ -385,7 +585,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_nas_ie(uint8 for(i=0; iN_bytes; i++) { - ded_info_nas->msg[i] = rrc_bits_2_value(ie_ptr, 8); + ded_info_nas->msg[i] = liblte_bits_2_value(ie_ptr, 8); } err = LIBLTE_SUCCESS; @@ -409,9 +609,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_filter_coefficient_ie(LIBLTE_RRC_FILTER_COEFFI if(ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(filter_coeff, ie_ptr, 4); + liblte_value_2_bits(filter_coeff, ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -427,9 +627,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_filter_coefficient_ie(uint8 filter_coeff != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + liblte_bits_2_value(ie_ptr, 1); - *filter_coeff = (LIBLTE_RRC_FILTER_COEFFICIENT_ENUM)rrc_bits_2_value(ie_ptr, 4); + *filter_coeff = (LIBLTE_RRC_FILTER_COEFFICIENT_ENUM)liblte_bits_2_value(ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -452,7 +652,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_mmec_ie(uint8 mmec, if(ie_ptr != NULL) { - rrc_value_2_bits(mmec, ie_ptr, 8); + liblte_value_2_bits(mmec, ie_ptr, 8); err = LIBLTE_SUCCESS; } @@ -467,7 +667,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mmec_ie(uint8 **ie_ptr, if(ie_ptr != NULL && mmec != NULL) { - *mmec = rrc_bits_2_value(ie_ptr, 8); + *mmec = liblte_bits_2_value(ie_ptr, 8); err = LIBLTE_SUCCESS; } @@ -490,7 +690,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_neigh_cell_config_ie(uint8 neigh_cell_config if(ie_ptr != NULL) { - rrc_value_2_bits(neigh_cell_config, ie_ptr, 2); + liblte_value_2_bits(neigh_cell_config, ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -505,7 +705,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_neigh_cell_config_ie(uint8 **ie_ptr, if(ie_ptr != NULL && neigh_cell_config != NULL) { - *neigh_cell_config = rrc_bits_2_value(ie_ptr, 2); + *neigh_cell_config = liblte_bits_2_value(ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -529,25 +729,25 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_other_config_ie(LIBLTE_RRC_OTHER_CONFIG_R9_STR ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicator - rrc_value_2_bits(other_cnfg->report_proximity_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(other_cnfg->report_proximity_cnfg_present, ie_ptr, 1); if(true == other_cnfg->report_proximity_cnfg_present) { // Optional indicators - rrc_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra_present, ie_ptr, 1); - rrc_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_utra_present, ie_ptr, 1); + liblte_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra_present, ie_ptr, 1); + liblte_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_utra_present, ie_ptr, 1); if(true == other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra_present) { - rrc_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra, ie_ptr, 1); + liblte_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra, ie_ptr, 1); } if(true == other_cnfg->report_proximity_cnfg.report_proximity_ind_utra_present) { - rrc_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_utra, ie_ptr, 1); + liblte_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_utra, ie_ptr, 1); } } @@ -560,33 +760,36 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_other_config_ie(uint8 LIBLTE_RRC_OTHER_CONFIG_R9_STRUCT *other_cnfg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; if(ie_ptr != NULL && other_cnfg != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicator - other_cnfg->report_proximity_cnfg_present = rrc_bits_2_value(ie_ptr, 1); + other_cnfg->report_proximity_cnfg_present = liblte_bits_2_value(ie_ptr, 1); if(true == other_cnfg->report_proximity_cnfg_present) { // Optional indicators - other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra_present = rrc_bits_2_value(ie_ptr, 1); - other_cnfg->report_proximity_cnfg.report_proximity_ind_utra_present = rrc_bits_2_value(ie_ptr, 1); + other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra_present = liblte_bits_2_value(ie_ptr, 1); + other_cnfg->report_proximity_cnfg.report_proximity_ind_utra_present = liblte_bits_2_value(ie_ptr, 1); if(true == other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra_present) { - other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra = (LIBLTE_RRC_REPORT_PROXIMITY_INDICATION_EUTRA_R9_ENUM)rrc_bits_2_value(ie_ptr, 1); + other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra = (LIBLTE_RRC_REPORT_PROXIMITY_INDICATION_EUTRA_R9_ENUM)liblte_bits_2_value(ie_ptr, 1); } if(true == other_cnfg->report_proximity_cnfg.report_proximity_ind_utra_present) { - other_cnfg->report_proximity_cnfg.report_proximity_ind_utra = (LIBLTE_RRC_REPORT_PROXIMITY_INDICATION_UTRA_R9_ENUM)rrc_bits_2_value(ie_ptr, 1); + other_cnfg->report_proximity_cnfg.report_proximity_ind_utra = (LIBLTE_RRC_REPORT_PROXIMITY_INDICATION_UTRA_R9_ENUM)liblte_bits_2_value(ie_ptr, 1); } } + skip_sequence_type_extension(ext_ind, ie_ptr); + err = LIBLTE_SUCCESS; } @@ -608,7 +811,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rand_cdma2000_1xrtt_ie(uint32 rand, if(ie_ptr != NULL) { - rrc_value_2_bits(rand, ie_ptr, 32); + liblte_value_2_bits(rand, ie_ptr, 32); err = LIBLTE_SUCCESS; } @@ -623,7 +826,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rand_cdma2000_1xrtt_ie(uint8 **ie_ptr, if(ie_ptr != NULL && rand != NULL) { - *rand = rrc_bits_2_value(ie_ptr, 32); + *rand = liblte_bits_2_value(ie_ptr, 32); err = LIBLTE_SUCCESS; } @@ -648,9 +851,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rat_type_ie(LIBLTE_RRC_RAT_TYPE_ENUM rat_typ if(ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(rat_type, ie_ptr, 3); + liblte_value_2_bits(rat_type, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -666,9 +869,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rat_type_ie(uint8 **ie_pt rat_type != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + liblte_bits_2_value(ie_ptr, 1); - *rat_type = (LIBLTE_RRC_RAT_TYPE_ENUM)rrc_bits_2_value(ie_ptr, 3); + *rat_type = (LIBLTE_RRC_RAT_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -691,7 +894,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_transaction_identifier_ie(uint8 rrc_tran if(ie_ptr != NULL) { - rrc_value_2_bits(rrc_transaction_id, ie_ptr, 2); + liblte_value_2_bits(rrc_transaction_id, ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -706,7 +909,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_transaction_identifier_ie(uint8 **ie_ptr if(ie_ptr != NULL && rrc_transaction_id != NULL) { - *rrc_transaction_id = rrc_bits_2_value(ie_ptr, 2); + *rrc_transaction_id = liblte_bits_2_value(ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -732,7 +935,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_s_tmsi_ie(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi, ie_ptr != NULL) { liblte_rrc_pack_mmec_ie(s_tmsi->mmec, ie_ptr); - rrc_value_2_bits(s_tmsi->m_tmsi, ie_ptr, 32); + liblte_value_2_bits(s_tmsi->m_tmsi, ie_ptr, 32); err = LIBLTE_SUCCESS; } @@ -748,7 +951,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_s_tmsi_ie(uint8 **ie_ptr, s_tmsi != NULL) { liblte_rrc_unpack_mmec_ie(ie_ptr, &s_tmsi->mmec); - s_tmsi->m_tmsi = rrc_bits_2_value(ie_ptr, 32); + s_tmsi->m_tmsi = liblte_bits_2_value(ie_ptr, 32); err = LIBLTE_SUCCESS; } @@ -764,7 +967,118 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_s_tmsi_ie(uint8 **ie_ptr, Document Reference: 36.331 v10.0.0 Section 6.3.6 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_octet_string_ie(LIBLTE_BYTE_MSG_STRUCT *octet_string, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(octet_string != NULL && + ie_ptr != NULL) + { + if(octet_string->N_bytes < 128) + { + liblte_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(octet_string->N_bytes, ie_ptr, 7); + }else if(octet_string->N_bytes < 16383){ + liblte_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(octet_string->N_bytes, ie_ptr, 14); + }else{ + // FIXME: Unlikely to have more than 16K of octets + } + + for(i=0; iN_bytes; i++) + { + liblte_value_2_bits(octet_string->msg[i], ie_ptr, 8); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_octet_string_ie(uint8 **ie_ptr, + LIBLTE_BYTE_MSG_STRUCT *octet_string) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ie_ptr != NULL && + octet_string != NULL) + { + if(0 == liblte_bits_2_value(ie_ptr, 1)) + { + octet_string->N_bytes = liblte_bits_2_value(ie_ptr, 7); + }else{ + if(0 == liblte_bits_2_value(ie_ptr, 1)) + { + octet_string->N_bytes = liblte_bits_2_value(ie_ptr, 14); + }else{ + // FIXME: Unlikely to have more than 16K of octets + octet_string->N_bytes = 0; + } + } + + for(i=0; iN_bytes; i++) + { + octet_string->msg[i] = liblte_bits_2_value(ie_ptr, 8); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_capability_rat_container_list_ie(LIBLTE_RRC_UE_CAPABILITY_RAT_CONTAINER_LIST_STRUCT *ue_capability_rat_container_list, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ue_capability_rat_container_list != NULL && + ie_ptr != NULL && + ue_capability_rat_container_list->N_rat_container <= LIBLTE_RRC_MAX_RAT_CAPABILITIES) + { + liblte_value_2_bits(ue_capability_rat_container_list->N_rat_container, ie_ptr, 4); + for(i=0; iN_rat_container; i++) + { + // RAT-Type + liblte_rrc_pack_rat_type_ie(ue_capability_rat_container_list->rat_container_list[i].rat_type, ie_ptr); + + // ueCapabilityRAT-Container - OCTET STRING + liblte_rrc_pack_octet_string_ie(&ue_capability_rat_container_list->rat_container_list[i].ue_capability_rat_container, ie_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_capability_rat_container_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_UE_CAPABILITY_RAT_CONTAINER_LIST_STRUCT *ue_capability_rat_container_list) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ie_ptr != NULL && + ue_capability_rat_container_list != NULL) + { + ue_capability_rat_container_list->N_rat_container = liblte_bits_2_value(ie_ptr, 4); + for(i=0; iN_rat_container; i++) + { + // RAT-Type + liblte_rrc_unpack_rat_type_ie(ie_ptr, &ue_capability_rat_container_list->rat_container_list[i].rat_type); + + // ueCapabilityRAT-Container - OCTET STRING + liblte_rrc_unpack_octet_string_ie(ie_ptr, &ue_capability_rat_container_list->rat_container_list[i].ue_capability_rat_container); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* IE Name: UE EUTRA Capability @@ -793,14 +1107,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_timers_and_constants_ie(LIBLTE_RRC_UE_TIMER ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(ue_timers_and_constants->t300, ie_ptr, 3); - rrc_value_2_bits(ue_timers_and_constants->t301, ie_ptr, 3); - rrc_value_2_bits(ue_timers_and_constants->t310, ie_ptr, 3); - rrc_value_2_bits(ue_timers_and_constants->n310, ie_ptr, 3); - rrc_value_2_bits(ue_timers_and_constants->t311, ie_ptr, 3); - rrc_value_2_bits(ue_timers_and_constants->n311, ie_ptr, 3); + liblte_value_2_bits(ue_timers_and_constants->t300, ie_ptr, 3); + liblte_value_2_bits(ue_timers_and_constants->t301, ie_ptr, 3); + liblte_value_2_bits(ue_timers_and_constants->t310, ie_ptr, 3); + liblte_value_2_bits(ue_timers_and_constants->n310, ie_ptr, 3); + liblte_value_2_bits(ue_timers_and_constants->t311, ie_ptr, 3); + liblte_value_2_bits(ue_timers_and_constants->n311, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -811,19 +1125,22 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_timers_and_constants_ie(uint8 LIBLTE_RRC_UE_TIMERS_AND_CONSTANTS_STRUCT *ue_timers_and_constants) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; if(ie_ptr != NULL && ue_timers_and_constants != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + ue_timers_and_constants->t300 = (LIBLTE_RRC_T300_ENUM)liblte_bits_2_value(ie_ptr, 3); + ue_timers_and_constants->t301 = (LIBLTE_RRC_T301_ENUM)liblte_bits_2_value(ie_ptr, 3); + ue_timers_and_constants->t310 = (LIBLTE_RRC_T310_ENUM)liblte_bits_2_value(ie_ptr, 3); + ue_timers_and_constants->n310 = (LIBLTE_RRC_N310_ENUM)liblte_bits_2_value(ie_ptr, 3); + ue_timers_and_constants->t311 = (LIBLTE_RRC_T311_ENUM)liblte_bits_2_value(ie_ptr, 3); + ue_timers_and_constants->n311 = (LIBLTE_RRC_N311_ENUM)liblte_bits_2_value(ie_ptr, 3); - ue_timers_and_constants->t300 = (LIBLTE_RRC_T300_ENUM)rrc_bits_2_value(ie_ptr, 3); - ue_timers_and_constants->t301 = (LIBLTE_RRC_T301_ENUM)rrc_bits_2_value(ie_ptr, 3); - ue_timers_and_constants->t310 = (LIBLTE_RRC_T310_ENUM)rrc_bits_2_value(ie_ptr, 3); - ue_timers_and_constants->n310 = (LIBLTE_RRC_N310_ENUM)rrc_bits_2_value(ie_ptr, 3); - ue_timers_and_constants->t311 = (LIBLTE_RRC_T311_ENUM)rrc_bits_2_value(ie_ptr, 3); - ue_timers_and_constants->n311 = (LIBLTE_RRC_N311_ENUM)rrc_bits_2_value(ie_ptr, 3); + skip_sequence_type_extension(ext_ind, ie_ptr); err = LIBLTE_SUCCESS; } @@ -847,7 +1164,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_allowed_meas_bandwidth_ie(LIBLTE_RRC_ALLOWED_M if(ie_ptr != NULL) { - rrc_value_2_bits(allowed_meas_bw, ie_ptr, 3); + liblte_value_2_bits(allowed_meas_bw, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -862,7 +1179,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_allowed_meas_bandwidth_ie(uint8 if(ie_ptr != NULL && allowed_meas_bw != NULL) { - *allowed_meas_bw = (LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_ENUM)rrc_bits_2_value(ie_ptr, 3); + *allowed_meas_bw = (LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_ENUM)liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -878,15 +1195,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_allowed_meas_bandwidth_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_rrc_pack_hysteresis_ie(uint8 hysteresis, +LIBLTE_ERROR_ENUM liblte_rrc_pack_hysteresis_ie(float hysteresis, uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; if(ie_ptr != NULL) { - // FIXME: Convert from actual value - rrc_value_2_bits(hysteresis, ie_ptr, 5); + liblte_value_2_bits(hysteresis*2, ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -894,15 +1210,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_hysteresis_ie(uint8 hysteresis, return(err); } LIBLTE_ERROR_ENUM liblte_rrc_unpack_hysteresis_ie(uint8 **ie_ptr, - uint8 *hysteresis) + float *hysteresis) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; if(ie_ptr != NULL && hysteresis != NULL) { - // FIXME: Convert to actual value - *hysteresis = rrc_bits_2_value(ie_ptr, 5); + *hysteresis = liblte_bits_2_value(ie_ptr, 5) / 2; err = LIBLTE_SUCCESS; } @@ -930,118 +1245,1529 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_hysteresis_ie(uint8 **ie_ptr, Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ -// FIXME - -/********************************************************************* - IE Name: Meas ID - - Description: Identifies a measurement configuration, i.e. linking - of a measurement object and a reporting configuration - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_id_ie(uint8 meas_id, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_config_ie(LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_cnfg, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; - if(ie_ptr != NULL) + if(meas_cnfg != NULL && + ie_ptr != NULL) { - rrc_value_2_bits(meas_id - 1, ie_ptr, 5); + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); - err = LIBLTE_SUCCESS; - } + // Optional indicators + if(meas_cnfg->N_meas_obj_to_remove) + { + liblte_value_2_bits(1, ie_ptr, 1); + }else{ + liblte_value_2_bits(0, ie_ptr, 1); + } + liblte_value_2_bits(meas_cnfg->meas_obj_to_add_mod_list_present, ie_ptr, 1); + if(meas_cnfg->N_rep_cnfg_to_remove) + { + liblte_value_2_bits(1, ie_ptr, 1); + }else{ + liblte_value_2_bits(0, ie_ptr, 1); + } + liblte_value_2_bits(meas_cnfg->rep_cnfg_to_add_mod_list_present, ie_ptr, 1); + if(meas_cnfg->N_meas_id_to_remove) + { + liblte_value_2_bits(1, ie_ptr, 1); + }else{ + liblte_value_2_bits(0, ie_ptr, 1); + } + liblte_value_2_bits(meas_cnfg->meas_id_to_add_mod_list_present, ie_ptr, 1); + liblte_value_2_bits(meas_cnfg->quantity_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(meas_cnfg->meas_gap_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(meas_cnfg->s_meas_present, ie_ptr, 1); + liblte_value_2_bits(meas_cnfg->pre_reg_info_hrpd_present, ie_ptr, 1); + liblte_value_2_bits(meas_cnfg->speed_state_params_present, ie_ptr, 1); - return(err); -} -LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_id_ie(uint8 **ie_ptr, - uint8 *meas_id) -{ - LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + // Meas Object To Remove List + if(0 != meas_cnfg->N_meas_obj_to_remove) + { + liblte_value_2_bits(meas_cnfg->N_meas_obj_to_remove - 1, ie_ptr, 5); + } + for(i=0; iN_meas_obj_to_remove; i++) + { + liblte_rrc_pack_meas_object_id_ie(meas_cnfg->meas_obj_to_remove_list[i], ie_ptr); + } - if(ie_ptr != NULL && - meas_id != NULL) - { - *meas_id = rrc_bits_2_value(ie_ptr, 5) + 1; + // Meas Object To Add Mod List + if(meas_cnfg->meas_obj_to_add_mod_list_present) + { + liblte_rrc_pack_meas_object_to_add_mod_list_ie(&meas_cnfg->meas_obj_to_add_mod_list, ie_ptr); + } - err = LIBLTE_SUCCESS; - } + // Report Config To Remove List + if(0 != meas_cnfg->N_rep_cnfg_to_remove) + { + liblte_value_2_bits(meas_cnfg->N_rep_cnfg_to_remove - 1, ie_ptr, 5); + } + for(i=0; iN_rep_cnfg_to_remove; i++) + { + liblte_rrc_pack_report_config_id_ie(meas_cnfg->rep_cnfg_to_remove_list[i], ie_ptr); + } - return(err); -} + // Report Config To Add Mod List + if(meas_cnfg->rep_cnfg_to_add_mod_list_present) + { + liblte_rrc_pack_report_config_to_add_mod_list_ie(&meas_cnfg->rep_cnfg_to_add_mod_list, ie_ptr); + } -/********************************************************************* - IE Name: Meas Id To Add Mod List + // Meas ID To Remove List + if(0 != meas_cnfg->N_meas_id_to_remove) + { + liblte_value_2_bits(meas_cnfg->N_meas_id_to_remove - 1, ie_ptr, 5); + } + for(i=0; iN_meas_id_to_remove; i++) + { + liblte_rrc_pack_meas_id_ie(meas_cnfg->meas_id_to_remove_list[i], ie_ptr); + } - Description: Concerns a list of measurement identities to add or - modify, with for each entry the meas ID, the - associated meas object ID and the associated report - config ID + // Meas ID To Add Mod List + if(meas_cnfg->meas_id_to_add_mod_list_present) + { + liblte_rrc_pack_meas_id_to_add_mod_list_ie(&meas_cnfg->meas_id_to_add_mod_list, ie_ptr); + } - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// FIXME + // Quantity Config + if(meas_cnfg->quantity_cnfg_present) + { + liblte_rrc_pack_quantity_config_ie(&meas_cnfg->quantity_cnfg, ie_ptr); + } -/********************************************************************* - IE Name: Meas Object CDMA2000 + // Meas Gap Config + if(meas_cnfg->meas_gap_cnfg_present) + { + liblte_rrc_pack_meas_gap_config_ie(&meas_cnfg->meas_gap_cnfg, ie_ptr); + } - Description: Specifies information applicable for inter-RAT - CDMA2000 neighboring cells + // S Measure + if(meas_cnfg->s_meas_present) + { + liblte_rrc_pack_rsrp_range_ie(meas_cnfg->s_meas, ie_ptr); + } - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// FIXME + // Pre Registration Info HRPD + if(meas_cnfg->pre_reg_info_hrpd_present) + { + liblte_rrc_pack_pre_registration_info_hrpd_ie(&meas_cnfg->pre_reg_info_hrpd, ie_ptr); + } + + // Speed State Pars + if(meas_cnfg->speed_state_params_present) + { + // Release choice + liblte_value_2_bits(1, ie_ptr, 1); + + // Mobility State Parameters + liblte_rrc_pack_mobility_state_parameters_ie(&meas_cnfg->speed_state_params.mob_state_params, ie_ptr); + + // Time To Trigger SF + liblte_rrc_pack_speed_state_scale_factors_ie(&meas_cnfg->speed_state_params.time_to_trig_sf, ie_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_cnfg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + bool ext_ind; + bool meas_obj_to_remove_present; + bool rep_cnfg_to_remove_present; + bool meas_id_to_remove_present; + + if(ie_ptr != NULL && + meas_cnfg != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Optional indicators + meas_obj_to_remove_present = liblte_bits_2_value(ie_ptr, 1); + meas_cnfg->meas_obj_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1); + rep_cnfg_to_remove_present = liblte_bits_2_value(ie_ptr, 1); + meas_cnfg->rep_cnfg_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1); + meas_id_to_remove_present = liblte_bits_2_value(ie_ptr, 1); + meas_cnfg->meas_id_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1); + meas_cnfg->quantity_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + meas_cnfg->meas_gap_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + meas_cnfg->s_meas_present = liblte_bits_2_value(ie_ptr, 1); + meas_cnfg->pre_reg_info_hrpd_present = liblte_bits_2_value(ie_ptr, 1); + meas_cnfg->speed_state_params_present = liblte_bits_2_value(ie_ptr, 1); + + // Meas Object To Remove List + if(meas_obj_to_remove_present) + { + meas_cnfg->N_meas_obj_to_remove = liblte_bits_2_value(ie_ptr, 5) + 1; + for(i=0; iN_meas_obj_to_remove; i++) + { + liblte_rrc_unpack_meas_object_id_ie(ie_ptr, &meas_cnfg->meas_obj_to_remove_list[i]); + } + }else{ + meas_cnfg->N_meas_obj_to_remove = 0; + } + + // Meas Object To Add Mod List + if(meas_cnfg->meas_obj_to_add_mod_list_present) + { + liblte_rrc_unpack_meas_object_to_add_mod_list_ie(ie_ptr, &meas_cnfg->meas_obj_to_add_mod_list); + } + + // Report Config To Remove List + if(rep_cnfg_to_remove_present) + { + meas_cnfg->N_rep_cnfg_to_remove = liblte_bits_2_value(ie_ptr, 5) + 1; + for(i=0; iN_rep_cnfg_to_remove; i++) + { + liblte_rrc_unpack_report_config_id_ie(ie_ptr, &meas_cnfg->rep_cnfg_to_remove_list[i]); + } + }else{ + meas_cnfg->N_rep_cnfg_to_remove = 0; + } + + // Report Config To Add Mod List + if(meas_cnfg->rep_cnfg_to_add_mod_list_present) + { + liblte_rrc_unpack_report_config_to_add_mod_list_ie(ie_ptr, &meas_cnfg->rep_cnfg_to_add_mod_list); + } + + // Meas ID To Remove List + if(meas_id_to_remove_present) + { + meas_cnfg->N_meas_id_to_remove = liblte_bits_2_value(ie_ptr, 5) + 1; + for(i=0; iN_meas_id_to_remove; i++) + { + liblte_rrc_unpack_meas_id_ie(ie_ptr, &meas_cnfg->meas_id_to_remove_list[i]); + } + }else{ + meas_cnfg->N_meas_id_to_remove = 0; + } + + // Meas ID To Add Mod List + if(meas_cnfg->meas_id_to_add_mod_list_present) + { + liblte_rrc_unpack_meas_id_to_add_mod_list_ie(ie_ptr, &meas_cnfg->meas_id_to_add_mod_list); + } + + // Quantity Config + if(meas_cnfg->quantity_cnfg_present) + { + liblte_rrc_unpack_quantity_config_ie(ie_ptr, &meas_cnfg->quantity_cnfg); + } + + // Meas Gap Config + if(meas_cnfg->meas_gap_cnfg_present) + { + liblte_rrc_unpack_meas_gap_config_ie(ie_ptr, &meas_cnfg->meas_gap_cnfg); + } + + // S Measure + if(meas_cnfg->s_meas_present) + { + liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &meas_cnfg->s_meas); + } + + // Pre Registration Info HRPD + if(meas_cnfg->pre_reg_info_hrpd_present) + { + liblte_rrc_unpack_pre_registration_info_hrpd_ie(ie_ptr, &meas_cnfg->pre_reg_info_hrpd); + } + + // Speed State Pars + if(meas_cnfg->speed_state_params_present) + { + // Release choice + meas_cnfg->speed_state_params_present = liblte_bits_2_value(ie_ptr, 1); + + if(meas_cnfg->speed_state_params_present) + { + // Mobility State Parameters + liblte_rrc_unpack_mobility_state_parameters_ie(ie_ptr, &meas_cnfg->speed_state_params.mob_state_params); + + // Time To Trigger SF + liblte_rrc_unpack_speed_state_scale_factors_ie(ie_ptr, &meas_cnfg->speed_state_params.time_to_trig_sf); + } + } + + skip_sequence_type_extension(ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Meas Gap Config + + Description: Specifies the measurement gap configuration and + controls setup/release of measurement gaps + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_gap_config_ie(LIBLTE_RRC_MEAS_GAP_CONFIG_STRUCT *meas_gap_cnfg, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(meas_gap_cnfg != NULL && + ie_ptr != NULL) + { + // Gap Offset Type + liblte_value_2_bits(meas_gap_cnfg->gap_offset_type, ie_ptr, 1); + + // Gap Offset + if(LIBLTE_RRC_GAP_OFFSET_TYPE_GP0 == meas_gap_cnfg->gap_offset_type) + { + liblte_value_2_bits(meas_gap_cnfg->gap_offset, ie_ptr, 6); + }else{ + liblte_value_2_bits(meas_gap_cnfg->gap_offset, ie_ptr, 7); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_gap_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_GAP_CONFIG_STRUCT *meas_gap_cnfg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + meas_gap_cnfg != NULL) + { + // Gap Offset Type + meas_gap_cnfg->gap_offset_type = (LIBLTE_RRC_GAP_OFFSET_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + + // Gap Offset + if(LIBLTE_RRC_GAP_OFFSET_TYPE_GP0 == meas_gap_cnfg->gap_offset_type) + { + meas_gap_cnfg->gap_offset = liblte_bits_2_value(ie_ptr, 6); + }else{ + meas_gap_cnfg->gap_offset = liblte_bits_2_value(ie_ptr, 7); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Meas ID + + Description: Identifies a measurement configuration, i.e. linking + of a measurement object and a reporting configuration + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_id_ie(uint8 meas_id, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + liblte_value_2_bits(meas_id - 1, ie_ptr, 5); + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_id_ie(uint8 **ie_ptr, + uint8 *meas_id) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + meas_id != NULL) + { + *meas_id = liblte_bits_2_value(ie_ptr, 5) + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Meas Id To Add Mod List + + Description: Concerns a list of measurement identities to add or + modify, with for each entry the meas ID, the + associated meas object ID and the associated report + config ID + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_id_to_add_mod_list_ie(LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_LIST_STRUCT *list, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(list != NULL && + ie_ptr != NULL) + { + // List Size + liblte_value_2_bits(list->N_meas_id - 1, ie_ptr, 5); + + for(i=0; iN_meas_id; i++) + { + // Meas ID + liblte_rrc_pack_meas_id_ie(list->meas_id_list[i].meas_id, ie_ptr); + + // Meas Object ID + liblte_rrc_pack_meas_object_id_ie(list->meas_id_list[i].meas_obj_id, ie_ptr); + + // Report Config ID + liblte_rrc_pack_report_config_id_ie(list->meas_id_list[i].rep_cnfg_id, ie_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_id_to_add_mod_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_LIST_STRUCT *list) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ie_ptr != NULL && + list != NULL) + { + // List Size + list->N_meas_id = liblte_bits_2_value(ie_ptr, 5) + 1; + + for(i=0; iN_meas_id; i++) + { + // Meas ID + liblte_rrc_unpack_meas_id_ie(ie_ptr, &list->meas_id_list[i].meas_id); + + // Meas Object ID + liblte_rrc_unpack_meas_object_id_ie(ie_ptr, &list->meas_id_list[i].meas_obj_id); + + // Report Config ID + liblte_rrc_unpack_report_config_id_ie(ie_ptr, &list->meas_id_list[i].rep_cnfg_id); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Meas Object CDMA2000 + + Description: Specifies information applicable for inter-RAT + CDMA2000 neighboring cells + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_cdma2000_ie(LIBLTE_RRC_MEAS_OBJECT_CDMA2000_STRUCT *meas_obj_cdma2000, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(meas_obj_cdma2000 != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Optional indicators + liblte_value_2_bits(meas_obj_cdma2000->search_win_size_present, ie_ptr, 1); + liblte_value_2_bits(meas_obj_cdma2000->cells_to_remove_list_present, ie_ptr, 1); + if(0 != meas_obj_cdma2000->N_cells_to_add_mod) + { + liblte_value_2_bits(1, ie_ptr, 1); + }else{ + liblte_value_2_bits(0, ie_ptr, 1); + } + liblte_value_2_bits(meas_obj_cdma2000->cell_for_which_to_rep_cgi_present, ie_ptr, 1); + + // CDMA2000 Type + liblte_rrc_pack_cdma2000_type_ie(meas_obj_cdma2000->cdma2000_type, ie_ptr); + + // Carrier Freq + liblte_rrc_pack_carrier_freq_cdma2000_ie(&meas_obj_cdma2000->carrier_freq, ie_ptr); + + // Search Window Size + if(meas_obj_cdma2000->search_win_size_present) + { + liblte_value_2_bits(meas_obj_cdma2000->search_win_size, ie_ptr, 4); + } + + // Offset Freq + liblte_rrc_pack_q_offset_range_inter_rat_ie(meas_obj_cdma2000->offset_freq, ie_ptr); + + // Cells To Remove List + if(meas_obj_cdma2000->cells_to_remove_list_present) + { + liblte_rrc_pack_cell_index_list_ie(&meas_obj_cdma2000->cells_to_remove_list, ie_ptr); + } + + // Cells To Add Mod List + if(0 != meas_obj_cdma2000->N_cells_to_add_mod) + { + liblte_value_2_bits(meas_obj_cdma2000->N_cells_to_add_mod - 1, ie_ptr, 5); + } + for(i=0; iN_cells_to_add_mod; i++) + { + // Cell Index + liblte_value_2_bits(meas_obj_cdma2000->cells_to_add_mod_list[i].cell_idx - 1, ie_ptr, 5); + + // Phys Cell ID + liblte_rrc_pack_phys_cell_id_cdma2000_ie(meas_obj_cdma2000->cells_to_add_mod_list[i].pci, ie_ptr); + } + + // Cell For Which To Report CGI + if(meas_obj_cdma2000->cell_for_which_to_rep_cgi_present) + { + liblte_rrc_pack_phys_cell_id_cdma2000_ie(meas_obj_cdma2000->cell_for_which_to_rep_cgi_present, ie_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_cdma2000_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_OBJECT_CDMA2000_STRUCT *meas_obj_cdma2000) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + bool ext_ind; + bool cells_to_add_mod_present; + + if(ie_ptr != NULL && + meas_obj_cdma2000 != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Optional indicators + meas_obj_cdma2000->search_win_size_present = liblte_bits_2_value(ie_ptr, 1); + meas_obj_cdma2000->cells_to_remove_list_present = liblte_bits_2_value(ie_ptr, 1); + cells_to_add_mod_present = liblte_bits_2_value(ie_ptr, 1); + meas_obj_cdma2000->cell_for_which_to_rep_cgi_present = liblte_bits_2_value(ie_ptr, 1); + + // CDMA2000 Type + liblte_rrc_unpack_cdma2000_type_ie(ie_ptr, &meas_obj_cdma2000->cdma2000_type); + + // Carrier Freq + liblte_rrc_unpack_carrier_freq_cdma2000_ie(ie_ptr, &meas_obj_cdma2000->carrier_freq); + + // Search Window Size + if(meas_obj_cdma2000->search_win_size_present) + { + meas_obj_cdma2000->search_win_size = liblte_bits_2_value(ie_ptr, 4); + } + + // Offset Freq + liblte_rrc_unpack_q_offset_range_inter_rat_ie(ie_ptr, &meas_obj_cdma2000->offset_freq); + + // Cells To Remove List + if(meas_obj_cdma2000->cells_to_remove_list_present) + { + liblte_rrc_unpack_cell_index_list_ie(ie_ptr, &meas_obj_cdma2000->cells_to_remove_list); + } + + // Cells To Add Mod List + if(cells_to_add_mod_present) + { + meas_obj_cdma2000->N_cells_to_add_mod = liblte_bits_2_value(ie_ptr, 5) + 1; + for(i=0; iN_cells_to_add_mod; i++) + { + // Cell Index + meas_obj_cdma2000->cells_to_add_mod_list[i].cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1; + + // Phys Cell ID + liblte_rrc_unpack_phys_cell_id_cdma2000_ie(ie_ptr, &meas_obj_cdma2000->cells_to_add_mod_list[i].pci); + } + }else{ + meas_obj_cdma2000->N_cells_to_add_mod = 0; + } + + // Cell For Which To Report CGI + if(meas_obj_cdma2000->cell_for_which_to_rep_cgi_present) + { + liblte_rrc_unpack_phys_cell_id_cdma2000_ie(ie_ptr, &meas_obj_cdma2000->cell_for_which_to_rep_cgi); + } + + skip_sequence_type_extension(ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Meas Object EUTRA + + Description: Specifies information applicable for intra-frequency + or inter-frequency E-UTRA cells + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_eutra_ie(LIBLTE_RRC_MEAS_OBJECT_EUTRA_STRUCT *meas_obj_eutra, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(meas_obj_eutra != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Optional indicators + liblte_value_2_bits(meas_obj_eutra->cells_to_remove_list_present, ie_ptr, 1); + if(0 != meas_obj_eutra->N_cells_to_add_mod) + { + liblte_value_2_bits(1, ie_ptr, 1); + }else{ + liblte_value_2_bits(0, ie_ptr, 1); + } + liblte_value_2_bits(meas_obj_eutra->black_cells_to_remove_list_present, ie_ptr, 1); + if(0 != meas_obj_eutra->N_black_cells_to_add_mod) + { + liblte_value_2_bits(1, ie_ptr, 1); + }else{ + liblte_value_2_bits(0, ie_ptr, 1); + } + liblte_value_2_bits(meas_obj_eutra->cell_for_which_to_rep_cgi_present, ie_ptr, 1); + + // Carrier Freq + liblte_rrc_pack_arfcn_value_eutra_ie(meas_obj_eutra->carrier_freq, ie_ptr); + + // Allowed Meas Bandwidth + liblte_rrc_pack_allowed_meas_bandwidth_ie(meas_obj_eutra->allowed_meas_bw, ie_ptr); + + // Presence Antenna Port 1 + liblte_rrc_pack_presence_antenna_port_1_ie(meas_obj_eutra->presence_ant_port_1, ie_ptr); + + // Neigh Cell Config + liblte_rrc_pack_neigh_cell_config_ie(meas_obj_eutra->neigh_cell_cnfg, ie_ptr); + + // Offset Freq + liblte_rrc_pack_q_offset_range_ie(meas_obj_eutra->offset_freq, ie_ptr); + + // Cells To Remove List + if(meas_obj_eutra->cells_to_remove_list_present) + { + liblte_rrc_pack_cell_index_list_ie(&meas_obj_eutra->cells_to_remove_list, ie_ptr); + } + + // Cells To Add Mod List + if(0 != meas_obj_eutra->N_cells_to_add_mod) + { + liblte_value_2_bits(meas_obj_eutra->N_cells_to_add_mod - 1, ie_ptr, 5); + } + for(i=0; iN_cells_to_add_mod; i++) + { + // Cell Index + liblte_value_2_bits(meas_obj_eutra->cells_to_add_mod_list[i].cell_idx - 1, ie_ptr, 5); + + // Phys Cell ID + liblte_rrc_pack_phys_cell_id_ie(meas_obj_eutra->cells_to_add_mod_list[i].pci, ie_ptr); + + // Cell Individual Offset + liblte_rrc_pack_q_offset_range_ie(meas_obj_eutra->cells_to_add_mod_list[i].cell_offset, ie_ptr); + } + + // Black Cells To Remove List + if(meas_obj_eutra->black_cells_to_remove_list_present) + { + liblte_rrc_pack_cell_index_list_ie(&meas_obj_eutra->black_cells_to_remove_list, ie_ptr); + } + + // Black Cells To Add Mod List + if(0 != meas_obj_eutra->N_black_cells_to_add_mod) + { + liblte_value_2_bits(meas_obj_eutra->N_black_cells_to_add_mod - 1, ie_ptr, 5); + } + for(i=0; iN_black_cells_to_add_mod; i++) + { + // Cell Index + liblte_value_2_bits(meas_obj_eutra->black_cells_to_add_mod_list[i].cell_idx - 1, ie_ptr, 5); + + // Phys Cell ID Range + liblte_rrc_pack_phys_cell_id_range_ie(&meas_obj_eutra->black_cells_to_add_mod_list[i].pci_range, ie_ptr); + } + + // Cell For Which To Report CGI + if(meas_obj_eutra->cell_for_which_to_rep_cgi_present) + { + liblte_rrc_pack_phys_cell_id_ie(meas_obj_eutra->cell_for_which_to_rep_cgi, ie_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_eutra_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_OBJECT_EUTRA_STRUCT *meas_obj_eutra) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + bool ext_ind; + bool cells_to_add_mod_list_present; + bool black_cells_to_add_mod_list_present; + + if(ie_ptr != NULL && + meas_obj_eutra != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Optional indicators + meas_obj_eutra->cells_to_remove_list_present = liblte_bits_2_value(ie_ptr, 1); + cells_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1); + meas_obj_eutra->black_cells_to_remove_list_present = liblte_bits_2_value(ie_ptr, 1); + black_cells_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1); + meas_obj_eutra->cell_for_which_to_rep_cgi_present = liblte_bits_2_value(ie_ptr, 1); + + // Carrier Freq + liblte_rrc_unpack_arfcn_value_eutra_ie(ie_ptr, &meas_obj_eutra->carrier_freq); + + // Allowed Meas Bandwidth + liblte_rrc_unpack_allowed_meas_bandwidth_ie(ie_ptr, &meas_obj_eutra->allowed_meas_bw); + + // Presence Antenna Port 1 + liblte_rrc_unpack_presence_antenna_port_1_ie(ie_ptr, &meas_obj_eutra->presence_ant_port_1); + + // Neigh Cell Config + liblte_rrc_unpack_neigh_cell_config_ie(ie_ptr, &meas_obj_eutra->neigh_cell_cnfg); + + // Offset Freq + liblte_rrc_unpack_q_offset_range_ie(ie_ptr, &meas_obj_eutra->offset_freq); + + // Cells To Remove List + if(meas_obj_eutra->cells_to_remove_list_present) + { + liblte_rrc_unpack_cell_index_list_ie(ie_ptr, &meas_obj_eutra->cells_to_remove_list); + } + + // Cells To Add Mod List + if(cells_to_add_mod_list_present) + { + meas_obj_eutra->N_cells_to_add_mod = liblte_bits_2_value(ie_ptr, 5) + 1; + for(i=0; iN_cells_to_add_mod; i++) + { + // Cell Index + meas_obj_eutra->cells_to_add_mod_list[i].cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1; + + // Phys Cell ID + liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &meas_obj_eutra->cells_to_add_mod_list[i].pci); + + // Cell Individual Offset + liblte_rrc_unpack_q_offset_range_ie(ie_ptr, &meas_obj_eutra->cells_to_add_mod_list[i].cell_offset); + } + }else{ + meas_obj_eutra->N_cells_to_add_mod = 0; + } + + // Black Cells To Remove List + if(meas_obj_eutra->black_cells_to_remove_list_present) + { + liblte_rrc_unpack_cell_index_list_ie(ie_ptr, &meas_obj_eutra->black_cells_to_remove_list); + } + + // Black Cells To Add Mod List + if(black_cells_to_add_mod_list_present) + { + meas_obj_eutra->N_black_cells_to_add_mod = liblte_bits_2_value(ie_ptr, 5) + 1; + for(i=0; iN_black_cells_to_add_mod; i++) + { + // Cell Index + meas_obj_eutra->black_cells_to_add_mod_list[i].cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1; + + // Phys Cell ID Range + liblte_rrc_unpack_phys_cell_id_range_ie(ie_ptr, &meas_obj_eutra->black_cells_to_add_mod_list[i].pci_range); + } + }else{ + meas_obj_eutra->N_black_cells_to_add_mod = 0; + } + + // Cell For Which To Report CGI + if(meas_obj_eutra->cell_for_which_to_rep_cgi_present) + { + liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &meas_obj_eutra->cell_for_which_to_rep_cgi); + } + + skip_sequence_type_extension(ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Meas Object GERAN + + Description: Specifies information applicable for inter-RAT + GERAN neighboring frequencies + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_geran_ie(LIBLTE_RRC_MEAS_OBJECT_GERAN_STRUCT *meas_obj_geran, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(meas_obj_geran != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Optional indicator + liblte_value_2_bits(meas_obj_geran->cell_for_which_to_rep_cgi_present, ie_ptr, 1); + + // Carrier Freqs + liblte_rrc_pack_carrier_freqs_geran_ie(&meas_obj_geran->carrier_freqs, ie_ptr); + + // Offset Freq + liblte_rrc_pack_q_offset_range_inter_rat_ie(meas_obj_geran->offset_freq, ie_ptr); + + // NCC Permitted + liblte_value_2_bits(meas_obj_geran->ncc_permitted, ie_ptr, 8); + + // Cell For Which To Report CGI + if(meas_obj_geran->cell_for_which_to_rep_cgi_present) + { + liblte_rrc_pack_phys_cell_id_geran_ie(&meas_obj_geran->cell_for_which_to_rep_cgi, ie_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_geran_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_OBJECT_GERAN_STRUCT *meas_obj_geran) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; + + if(ie_ptr != NULL && + meas_obj_geran != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Optional indicator + meas_obj_geran->cell_for_which_to_rep_cgi_present = liblte_bits_2_value(ie_ptr, 1); + + // Carrier Freqs + liblte_rrc_unpack_carrier_freqs_geran_ie(ie_ptr, &meas_obj_geran->carrier_freqs); + + // Offset Freq + liblte_rrc_unpack_q_offset_range_inter_rat_ie(ie_ptr, &meas_obj_geran->offset_freq); + + // NCC Permitted + meas_obj_geran->ncc_permitted = liblte_bits_2_value(ie_ptr, 8); + + // Cell For Which To Report CGI + if(meas_obj_geran->cell_for_which_to_rep_cgi_present) + { + liblte_rrc_unpack_phys_cell_id_geran_ie(ie_ptr, &meas_obj_geran->cell_for_which_to_rep_cgi); + } + + skip_sequence_type_extension(ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Meas Object ID + + Description: Identifies a measurement object configuration + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_id_ie(uint8 meas_object_id, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL) + { + liblte_value_2_bits(meas_object_id - 1, ie_ptr, 5); + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_id_ie(uint8 **ie_ptr, + uint8 *meas_object_id) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + meas_object_id != NULL) + { + *meas_object_id = liblte_bits_2_value(ie_ptr, 5) + 1; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Meas Object To Add Mod List + + Description: Concerns a list of measurement objects to add or + modify + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_to_add_mod_list_ie(LIBLTE_RRC_MEAS_OBJECT_TO_ADD_MOD_LIST_STRUCT *list, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(list != NULL && + ie_ptr != NULL) + { + // List Size + liblte_value_2_bits(list->N_meas_obj - 1, ie_ptr, 5); + + for(i=0; iN_meas_obj; i++) + { + // Meas Object ID + liblte_rrc_pack_meas_object_id_ie(list->meas_obj_list[i].meas_obj_id, ie_ptr); + + // Meas Object Choice + liblte_value_2_bits(list->meas_obj_list[i].meas_obj_type, ie_ptr, 2); + + // Meas Object + if(LIBLTE_RRC_MEAS_OBJECT_TYPE_EUTRA == list->meas_obj_list[i].meas_obj_type) + { + liblte_rrc_pack_meas_object_eutra_ie(&list->meas_obj_list[i].meas_obj_eutra, ie_ptr); + }else if(LIBLTE_RRC_MEAS_OBJECT_TYPE_UTRA == list->meas_obj_list[i].meas_obj_type){ + liblte_rrc_pack_meas_object_utra_ie(&list->meas_obj_list[i].meas_obj_utra, ie_ptr); + }else if(LIBLTE_RRC_MEAS_OBJECT_TYPE_GERAN == list->meas_obj_list[i].meas_obj_type){ + liblte_rrc_pack_meas_object_geran_ie(&list->meas_obj_list[i].meas_obj_geran, ie_ptr); + }else{ + liblte_rrc_pack_meas_object_cdma2000_ie(&list->meas_obj_list[i].meas_obj_cdma2000, ie_ptr); + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_to_add_mod_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_OBJECT_TO_ADD_MOD_LIST_STRUCT *list) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ie_ptr != NULL && + list != NULL) + { + // List Size + list->N_meas_obj = liblte_bits_2_value(ie_ptr, 5) + 1; + + for(i=0; iN_meas_obj; i++) + { + // Meas Object ID + liblte_rrc_unpack_meas_object_id_ie(ie_ptr, &list->meas_obj_list[i].meas_obj_id); + + // Meas Object Choice + list->meas_obj_list[i].meas_obj_type = (LIBLTE_RRC_MEAS_OBJECT_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 2); + + // Meas Object + if(LIBLTE_RRC_MEAS_OBJECT_TYPE_EUTRA == list->meas_obj_list[i].meas_obj_type) + { + liblte_rrc_unpack_meas_object_eutra_ie(ie_ptr, &list->meas_obj_list[i].meas_obj_eutra); + }else if(LIBLTE_RRC_MEAS_OBJECT_TYPE_UTRA == list->meas_obj_list[i].meas_obj_type){ + liblte_rrc_unpack_meas_object_utra_ie(ie_ptr, &list->meas_obj_list[i].meas_obj_utra); + }else if(LIBLTE_RRC_MEAS_OBJECT_TYPE_GERAN == list->meas_obj_list[i].meas_obj_type){ + liblte_rrc_unpack_meas_object_geran_ie(ie_ptr, &list->meas_obj_list[i].meas_obj_geran); + }else{ + liblte_rrc_unpack_meas_object_cdma2000_ie(ie_ptr, &list->meas_obj_list[i].meas_obj_cdma2000); + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Meas Object UTRA + + Description: Specifies information applicable for inter-RAT UTRA + neighboring cells + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_utra_ie(LIBLTE_RRC_MEAS_OBJECT_UTRA_STRUCT *meas_obj_utra, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(meas_obj_utra != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Optional indicators + liblte_value_2_bits(meas_obj_utra->cells_to_remove_list_present, ie_ptr, 1); + liblte_value_2_bits(meas_obj_utra->cells_to_add_mod_list_present, ie_ptr, 1); + liblte_value_2_bits(meas_obj_utra->cells_for_which_to_rep_cgi_present, ie_ptr, 1); + + // Carrier Freq + liblte_rrc_pack_arfcn_value_utra_ie(meas_obj_utra->carrier_freq, ie_ptr); + + // Offset Freq + liblte_rrc_pack_q_offset_range_inter_rat_ie(meas_obj_utra->offset_freq, ie_ptr); + + // Cells To Remove List + if(meas_obj_utra->cells_to_remove_list_present) + { + liblte_rrc_pack_cell_index_list_ie(&meas_obj_utra->cells_to_remove_list, ie_ptr); + } + + // Cells To Add Mod List + if(meas_obj_utra->cells_to_add_mod_list_present) + { + // UTRA System Type + liblte_value_2_bits(meas_obj_utra->cells_to_add_mod_list.type, ie_ptr, 1); + + liblte_value_2_bits(meas_obj_utra->cells_to_add_mod_list.N_cells - 1, ie_ptr, 5); + for(i=0; icells_to_add_mod_list.N_cells; i++) + { + if(LIBLTE_RRC_UTRA_SYSTEM_TYPE_FDD == meas_obj_utra->cells_to_add_mod_list.type) + { + // Cell Index + liblte_value_2_bits(meas_obj_utra->cells_to_add_mod_list.cells_fdd[i].cell_idx - 1, ie_ptr, 5); + + // Phys Cell ID + liblte_rrc_pack_phys_cell_id_utra_fdd_ie(meas_obj_utra->cells_to_add_mod_list.cells_fdd[i].pci, ie_ptr); + }else{ + // Cell Index + liblte_value_2_bits(meas_obj_utra->cells_to_add_mod_list.cells_tdd[i].cell_idx - 1, ie_ptr, 5); + + // Phys Cell ID + liblte_rrc_pack_phys_cell_id_utra_tdd_ie(meas_obj_utra->cells_to_add_mod_list.cells_tdd[i].pci, ie_ptr); + } + } + } + + // Cells For Which To Report CGI + if(meas_obj_utra->cells_for_which_to_rep_cgi_present) + { + // UTRA System Type + liblte_value_2_bits(meas_obj_utra->cells_for_which_to_rep_cgi.type, ie_ptr, 1); + + if(LIBLTE_RRC_UTRA_SYSTEM_TYPE_FDD == meas_obj_utra->cells_for_which_to_rep_cgi.type) + { + // Phys Cell ID + liblte_rrc_pack_phys_cell_id_utra_fdd_ie(meas_obj_utra->cells_for_which_to_rep_cgi.pci_fdd, ie_ptr); + }else{ + // Phys Cell ID + liblte_rrc_pack_phys_cell_id_utra_tdd_ie(meas_obj_utra->cells_for_which_to_rep_cgi.pci_tdd, ie_ptr); + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_utra_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_OBJECT_UTRA_STRUCT *meas_obj_utra) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + bool ext_ind; + + if(ie_ptr != NULL && + meas_obj_utra != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Optional indicators + meas_obj_utra->cells_to_remove_list_present = liblte_bits_2_value(ie_ptr, 1); + meas_obj_utra->cells_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1); + meas_obj_utra->cells_for_which_to_rep_cgi_present = liblte_bits_2_value(ie_ptr, 1); + + // Carrier Freq + liblte_rrc_unpack_arfcn_value_utra_ie(ie_ptr, &meas_obj_utra->carrier_freq); + + // Offset Freq + liblte_rrc_unpack_q_offset_range_inter_rat_ie(ie_ptr, &meas_obj_utra->offset_freq); + + // Cells To Remove List + if(meas_obj_utra->cells_to_remove_list_present) + { + liblte_rrc_unpack_cell_index_list_ie(ie_ptr, &meas_obj_utra->cells_to_remove_list); + } + + // Cells To Add Mod List + if(meas_obj_utra->cells_to_add_mod_list_present) + { + // UTRA System Type + meas_obj_utra->cells_to_add_mod_list.type = (LIBLTE_RRC_UTRA_SYSTEM_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + + meas_obj_utra->cells_to_add_mod_list.N_cells = liblte_bits_2_value(ie_ptr, 5) + 1; + for(i=0; icells_to_add_mod_list.N_cells; i++) + { + if(LIBLTE_RRC_UTRA_SYSTEM_TYPE_FDD == meas_obj_utra->cells_to_add_mod_list.type) + { + // Cell Index + meas_obj_utra->cells_to_add_mod_list.cells_fdd[i].cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1; + + // Phys Cell ID + liblte_rrc_unpack_phys_cell_id_utra_fdd_ie(ie_ptr, &meas_obj_utra->cells_to_add_mod_list.cells_fdd[i].pci); + }else{ + // Cell Index + meas_obj_utra->cells_to_add_mod_list.cells_tdd[i].cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1; + + // Phys Cell ID + liblte_rrc_unpack_phys_cell_id_utra_tdd_ie(ie_ptr, &meas_obj_utra->cells_to_add_mod_list.cells_tdd[i].pci); + } + } + } + + // Cells For Which To Report CGI + if(meas_obj_utra->cells_for_which_to_rep_cgi_present) + { + // UTRA System Type + meas_obj_utra->cells_for_which_to_rep_cgi.type = (LIBLTE_RRC_UTRA_SYSTEM_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + + if(LIBLTE_RRC_UTRA_SYSTEM_TYPE_FDD == meas_obj_utra->cells_for_which_to_rep_cgi.type) + { + // Phys Cell ID + liblte_rrc_unpack_phys_cell_id_utra_fdd_ie(ie_ptr, &meas_obj_utra->cells_for_which_to_rep_cgi.pci_fdd); + }else{ + // Phys Cell ID + liblte_rrc_unpack_phys_cell_id_utra_tdd_ie(ie_ptr, &meas_obj_utra->cells_for_which_to_rep_cgi.pci_tdd); + } + } + + skip_sequence_type_extension(ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Meas Results + + Description: Covers measured results for intra-frequency, + inter-frequency and inter-RAT mobility + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +// FIXME + +/********************************************************************* + IE Name: Quantity Config + + Description: Specifies the measurement quantities and layer 3 + filtering coefficients for E-UTRA and inter-RAT + measurements + + Document Reference: 36.331 v10.0.0 Section 6.3.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_quantity_config_ie(LIBLTE_RRC_QUANTITY_CONFIG_STRUCT *qc, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(qc != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Optional indicators + liblte_value_2_bits(qc->qc_eutra_present, ie_ptr, 1); + liblte_value_2_bits(qc->qc_utra_present, ie_ptr, 1); + liblte_value_2_bits(qc->qc_geran_present, ie_ptr, 1); + liblte_value_2_bits(qc->qc_cdma2000_present, ie_ptr, 1); + + // Quality Config EUTRA + if(qc->qc_eutra_present) + { + liblte_rrc_pack_filter_coefficient_ie(qc->qc_eutra.fc_rsrp, ie_ptr); + liblte_rrc_pack_filter_coefficient_ie(qc->qc_eutra.fc_rsrq, ie_ptr); + } + + // Quality Config UTRA + if(qc->qc_utra_present) + { + liblte_value_2_bits(qc->qc_utra.mq_fdd, ie_ptr, 1); + liblte_value_2_bits(qc->qc_utra.mq_tdd, ie_ptr, 1); + liblte_rrc_pack_filter_coefficient_ie(qc->qc_utra.fc, ie_ptr); + } + + // Quality Config GERAN + if(qc->qc_geran_present) + { + liblte_value_2_bits(qc->qc_geran.mq, ie_ptr, 1); + liblte_rrc_pack_filter_coefficient_ie(qc->qc_geran.fc, ie_ptr); + } + + // Quality Config CDMA2000 + if(qc->qc_cdma2000_present) + { + liblte_value_2_bits(qc->qc_cdma2000.mq, ie_ptr, 1); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_quantity_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_QUANTITY_CONFIG_STRUCT *qc) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; + + if(ie_ptr != NULL && + qc != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Optional indicators + qc->qc_eutra_present = liblte_bits_2_value(ie_ptr, 1); + qc->qc_utra_present = liblte_bits_2_value(ie_ptr, 1); + qc->qc_geran_present = liblte_bits_2_value(ie_ptr, 1); + qc->qc_cdma2000_present = liblte_bits_2_value(ie_ptr, 1); + + // Quality Config EUTRA + if(qc->qc_eutra_present) + { + liblte_rrc_unpack_filter_coefficient_ie(ie_ptr, &qc->qc_eutra.fc_rsrp); + liblte_rrc_unpack_filter_coefficient_ie(ie_ptr, &qc->qc_eutra.fc_rsrq); + } + + // Quality Config UTRA + if(qc->qc_utra_present) + { + qc->qc_utra.mq_fdd = (LIBLTE_RRC_MEAS_QUANTITY_UTRA_FDD_ENUM)liblte_bits_2_value(ie_ptr, 1); + qc->qc_utra.mq_tdd = (LIBLTE_RRC_MEAS_QUANTITY_UTRA_TDD_ENUM)liblte_bits_2_value(ie_ptr, 1); + liblte_rrc_unpack_filter_coefficient_ie(ie_ptr, &qc->qc_utra.fc); + } + + // Quality Config GERAN + if(qc->qc_geran_present) + { + qc->qc_geran.mq = (LIBLTE_RRC_MEAS_QUANTITY_GERAN_ENUM)liblte_bits_2_value(ie_ptr, 1); + liblte_rrc_unpack_filter_coefficient_ie(ie_ptr, &qc->qc_geran.fc); + } + + // Quality Config CDMA2000 + if(qc->qc_cdma2000_present) + { + qc->qc_cdma2000.mq = (LIBLTE_RRC_MEAS_QUANTITY_CDMA2000_ENUM)liblte_bits_2_value(ie_ptr, 1); + } + + skip_sequence_type_extension(ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - IE Name: Meas Object EUTRA + IE Name: Report Config EUTRA - Description: Specifies information applicable for intra-frequency - or inter-frequency E-UTRA cells + Description: Specifies criteria for triggering of an E-UTRA + measurement reporting event Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_eutra_ie(LIBLTE_RRC_REPORT_CONFIG_EUTRA_STRUCT *rep_cnfg_eutra, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: Meas Object GERAN + if(rep_cnfg_eutra != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); - Description: Specifies information applicable for inter-RAT - GERAN neighboring frequencies + // Trigger Type + liblte_value_2_bits(rep_cnfg_eutra->trigger_type, ie_ptr, 1); + if(LIBLTE_RRC_TRIGGER_TYPE_EUTRA_EVENT == rep_cnfg_eutra->trigger_type) + { + // Event ID + // FIXME: Handle extension properly + liblte_value_2_bits(rep_cnfg_eutra->event.event_id, ie_ptr, 3); + if(LIBLTE_RRC_EVENT_ID_EUTRA_A1 == rep_cnfg_eutra->event.event_id) + { + // Threshold Type + liblte_value_2_bits(rep_cnfg_eutra->event.event_a1.eutra.type, ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a1.eutra.type) + { + liblte_rrc_pack_rsrp_range_ie(rep_cnfg_eutra->event.event_a1.eutra.range, ie_ptr); + }else{ + liblte_rrc_pack_rsrq_range_ie(rep_cnfg_eutra->event.event_a1.eutra.range, ie_ptr); + } + }else if(LIBLTE_RRC_EVENT_ID_EUTRA_A2 == rep_cnfg_eutra->event.event_id){ + // Threshold Type + liblte_value_2_bits(rep_cnfg_eutra->event.event_a2.eutra.type, ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a2.eutra.type) + { + liblte_rrc_pack_rsrp_range_ie(rep_cnfg_eutra->event.event_a2.eutra.range, ie_ptr); + }else{ + liblte_rrc_pack_rsrq_range_ie(rep_cnfg_eutra->event.event_a2.eutra.range, ie_ptr); + } + }else if(LIBLTE_RRC_EVENT_ID_EUTRA_A3 == rep_cnfg_eutra->event.event_id){ + // Offset + liblte_value_2_bits(rep_cnfg_eutra->event.event_a3.offset + 30, ie_ptr, 6); + + // Report On Leave + liblte_value_2_bits(rep_cnfg_eutra->event.event_a3.report_on_leave, ie_ptr, 1); + }else if(LIBLTE_RRC_EVENT_ID_EUTRA_A4 == rep_cnfg_eutra->event.event_id){ + // Threshold Type + liblte_value_2_bits(rep_cnfg_eutra->event.event_a4.eutra.type, ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a4.eutra.type) + { + liblte_rrc_pack_rsrp_range_ie(rep_cnfg_eutra->event.event_a4.eutra.range, ie_ptr); + }else{ + liblte_rrc_pack_rsrq_range_ie(rep_cnfg_eutra->event.event_a4.eutra.range, ie_ptr); + } + }else if(LIBLTE_RRC_EVENT_ID_EUTRA_A5 == rep_cnfg_eutra->event.event_id){ + // Threshold1 Type + liblte_value_2_bits(rep_cnfg_eutra->event.event_a5.eutra1.type, ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a5.eutra1.type) + { + liblte_rrc_pack_rsrp_range_ie(rep_cnfg_eutra->event.event_a5.eutra1.range, ie_ptr); + }else{ + liblte_rrc_pack_rsrq_range_ie(rep_cnfg_eutra->event.event_a5.eutra1.range, ie_ptr); + } - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// FIXME + // Threshold2 Type + liblte_value_2_bits(rep_cnfg_eutra->event.event_a5.eutra2.type, ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a5.eutra2.type) + { + liblte_rrc_pack_rsrp_range_ie(rep_cnfg_eutra->event.event_a5.eutra2.range, ie_ptr); + }else{ + liblte_rrc_pack_rsrq_range_ie(rep_cnfg_eutra->event.event_a5.eutra2.range, ie_ptr); + } + }else{ + // Offset + liblte_value_2_bits(rep_cnfg_eutra->event.event_a6.offset + 30, ie_ptr, 6); + + // Report On Leave + liblte_value_2_bits(rep_cnfg_eutra->event.event_a6.report_on_leave, ie_ptr, 1); + } + + // Hysteresis + liblte_rrc_pack_hysteresis_ie(rep_cnfg_eutra->event.hysteresis, ie_ptr); + + // Time To Trigger + liblte_rrc_pack_time_to_trigger_ie(rep_cnfg_eutra->event.time_to_trigger, ie_ptr); + }else{ + // Purpose + liblte_value_2_bits(rep_cnfg_eutra->periodical.purpose, ie_ptr, 1); + } + + // Trigger Quantity + liblte_value_2_bits(rep_cnfg_eutra->trigger_quantity, ie_ptr, 1); + + // Report Quantity + liblte_value_2_bits(rep_cnfg_eutra->report_quantity, ie_ptr, 1); + + // Max Report Cells + liblte_value_2_bits(rep_cnfg_eutra->max_report_cells - 1, ie_ptr, 3); + + // Report Interval + liblte_rrc_pack_report_interval_ie(rep_cnfg_eutra->report_interval, ie_ptr); + + // Report Amount + liblte_value_2_bits(rep_cnfg_eutra->report_amount, ie_ptr, 3); + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_eutra_ie(uint8 **ie_ptr, + LIBLTE_RRC_REPORT_CONFIG_EUTRA_STRUCT *rep_cnfg_eutra) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool report_cnfg_ext_ind; + + if(ie_ptr != NULL && + rep_cnfg_eutra != NULL) + { + // Extension indicator + report_cnfg_ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Trigger Type + rep_cnfg_eutra->trigger_type = (LIBLTE_RRC_TRIGGER_TYPE_EUTRA_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_TRIGGER_TYPE_EUTRA_EVENT == rep_cnfg_eutra->trigger_type) + { + // Event ID + // FIXME: Handle extension properly + if(LIBLTE_RRC_EVENT_ID_EUTRA_A1 == rep_cnfg_eutra->event.event_id) + { + // Threshold Type + rep_cnfg_eutra->event.event_a1.eutra.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a1.eutra.type) + { + liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a1.eutra.range); + }else{ + liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a1.eutra.range); + } + }else if(LIBLTE_RRC_EVENT_ID_EUTRA_A2 == rep_cnfg_eutra->event.event_id){ + // Threshold Type + rep_cnfg_eutra->event.event_a2.eutra.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a2.eutra.type) + { + liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a2.eutra.range); + }else{ + liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a2.eutra.range); + } + }else if(LIBLTE_RRC_EVENT_ID_EUTRA_A3 == rep_cnfg_eutra->event.event_id){ + // Offset + rep_cnfg_eutra->event.event_a3.offset = liblte_bits_2_value(ie_ptr, 6) - 30; + + // Report On Leave + rep_cnfg_eutra->event.event_a3.report_on_leave = liblte_bits_2_value(ie_ptr, 1); + }else if(LIBLTE_RRC_EVENT_ID_EUTRA_A4 == rep_cnfg_eutra->event.event_id){ + // Threshold Type + rep_cnfg_eutra->event.event_a4.eutra.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a4.eutra.type) + { + liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a4.eutra.range); + }else{ + liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a4.eutra.range); + } + }else if(LIBLTE_RRC_EVENT_ID_EUTRA_A5 == rep_cnfg_eutra->event.event_id){ + // Threshold1 Type + rep_cnfg_eutra->event.event_a5.eutra1.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a5.eutra1.type) + { + liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a5.eutra1.range); + }else{ + liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a5.eutra1.range); + } + + // Threshold2 Type + rep_cnfg_eutra->event.event_a5.eutra2.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a5.eutra2.type) + { + liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a5.eutra2.range); + }else{ + liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a5.eutra2.range); + } + }else{ + // Offset + rep_cnfg_eutra->event.event_a6.offset = liblte_bits_2_value(ie_ptr, 6) - 30; + + // Report On Leave + rep_cnfg_eutra->event.event_a6.report_on_leave = liblte_bits_2_value(ie_ptr, 1); + } + + // Hysteresis + liblte_rrc_unpack_hysteresis_ie(ie_ptr, &rep_cnfg_eutra->event.hysteresis); + + // Time To Trigger + liblte_rrc_unpack_time_to_trigger_ie(ie_ptr, &rep_cnfg_eutra->event.time_to_trigger); + }else{ + // Purpose + rep_cnfg_eutra->periodical.purpose = (LIBLTE_RRC_PURPOSE_EUTRA_ENUM)liblte_bits_2_value(ie_ptr, 1); + } + + // Trigger Quantity + rep_cnfg_eutra->trigger_quantity = (LIBLTE_RRC_TRIGGER_QUANTITY_ENUM)liblte_bits_2_value(ie_ptr, 1); + + // Report Quantity + rep_cnfg_eutra->report_quantity = (LIBLTE_RRC_REPORT_QUANTITY_ENUM)liblte_bits_2_value(ie_ptr, 1); + + // Max Report Cells + rep_cnfg_eutra->max_report_cells = liblte_bits_2_value(ie_ptr, 3) - 1; + + // Report Interval + liblte_rrc_unpack_report_interval_ie(ie_ptr, &rep_cnfg_eutra->report_interval); + + // Report Amount + rep_cnfg_eutra->report_amount = (LIBLTE_RRC_REPORT_AMOUNT_ENUM)liblte_bits_2_value(ie_ptr, 3); + + skip_sequence_type_extension(report_cnfg_ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - IE Name: Meas Object ID + IE Name: Report Config ID - Description: Identifies a measurement object configuration + Description: Identifies a measurement reporting configuration Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_id_ie(uint8 meas_object_id, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_id_ie(uint8 report_cnfg_id, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; if(ie_ptr != NULL) { - rrc_value_2_bits(meas_object_id - 1, ie_ptr, 5); + liblte_value_2_bits(report_cnfg_id - 1, ie_ptr, 5); err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_id_ie(uint8 **ie_ptr, - uint8 *meas_object_id) +LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_id_ie(uint8 **ie_ptr, + uint8 *report_cnfg_id) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; if(ie_ptr != NULL && - meas_object_id != NULL) + report_cnfg_id != NULL) { - *meas_object_id = rrc_bits_2_value(ie_ptr, 5) + 1; + *report_cnfg_id = liblte_bits_2_value(ie_ptr, 5) + 1; err = LIBLTE_SUCCESS; } @@ -1050,86 +2776,263 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_id_ie(uint8 **ie_ptr, } /********************************************************************* - IE Name: Meas Object To Add Mod List + IE Name: Report Config Inter RAT - Description: Concerns a list of measurement objects to add or - modify + Description: Specifies criteria for triggering of an inter-RAT + measurement reporting event Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_inter_rat_ie(LIBLTE_RRC_REPORT_CONFIG_INTER_RAT_STRUCT *rep_cnfg_inter_rat, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; -/********************************************************************* - IE Name: Meas Object UTRA + if(rep_cnfg_inter_rat != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); - Description: Specifies information applicable for inter-RAT UTRA - neighboring cells + // Trigger Type + liblte_value_2_bits(rep_cnfg_inter_rat->trigger_type, ie_ptr, 1); + if(LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_EVENT == rep_cnfg_inter_rat->trigger_type) + { + // Event ID + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_id, ie_ptr, 1); + if(LIBLTE_RRC_EVENT_ID_INTER_RAT_B1 == rep_cnfg_inter_rat->event.event_id) + { + // Threshold Type + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.type, ie_ptr, 2); + if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_UTRA == rep_cnfg_inter_rat->event.event_b1.type) + { + // Type + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.utra.type, ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_UTRA_TYPE_RSCP == rep_cnfg_inter_rat->event.event_b1.utra.type) + { + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.utra.value + 5, ie_ptr, 7); + }else{ + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.utra.value, ie_ptr, 6); + } + }else if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_GERAN == rep_cnfg_inter_rat->event.event_b1.type){ + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.geran, ie_ptr, 6); + }else{ + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.cdma2000, ie_ptr, 6); + } + }else{ + // Threshold1 Type + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.eutra.type, ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_inter_rat->event.event_b2.eutra.type) + { + liblte_rrc_pack_rsrp_range_ie(rep_cnfg_inter_rat->event.event_b2.eutra.range, ie_ptr); + }else{ + liblte_rrc_pack_rsrq_range_ie(rep_cnfg_inter_rat->event.event_b2.eutra.range, ie_ptr); + } - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// FIXME + // Threshold2 Type + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.type2, ie_ptr, 2); + if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_UTRA == rep_cnfg_inter_rat->event.event_b2.type2) + { + // Type + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.utra.type, ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_UTRA_TYPE_RSCP == rep_cnfg_inter_rat->event.event_b2.utra.type) + { + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.utra.value + 5, ie_ptr, 7); + }else{ + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.utra.value, ie_ptr, 6); + } + }else if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_GERAN == rep_cnfg_inter_rat->event.event_b2.type2){ + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.geran, ie_ptr, 6); + }else{ + liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.cdma2000, ie_ptr, 6); + } + } -/********************************************************************* - IE Name: Meas Results + // Hysteresis + liblte_rrc_pack_hysteresis_ie(rep_cnfg_inter_rat->event.hysteresis, ie_ptr); - Description: Covers measured results for intra-frequency, - inter-frequency and inter-RAT mobility + // Time To Trigger + liblte_rrc_pack_time_to_trigger_ie(rep_cnfg_inter_rat->event.time_to_trigger, ie_ptr); + }else{ + // Purpose + liblte_value_2_bits(rep_cnfg_inter_rat->periodical.purpose, ie_ptr, 2); + } - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// FIXME + // Max Report Cells + liblte_value_2_bits(rep_cnfg_inter_rat->max_report_cells - 1, ie_ptr, 3); -/********************************************************************* - IE Name: Quantity Config + // Report Interval + liblte_rrc_pack_report_interval_ie(rep_cnfg_inter_rat->report_interval, ie_ptr); - Description: Specifies the measurement quantities and layer 3 - filtering coefficients for E-UTRA and inter-RAT - measurements + // Report Amount + liblte_value_2_bits(rep_cnfg_inter_rat->report_amount, ie_ptr, 3); - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } -/********************************************************************* - IE Name: Report Config EUTRA + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_inter_rat_ie(uint8 **ie_ptr, + LIBLTE_RRC_REPORT_CONFIG_INTER_RAT_STRUCT *rep_cnfg_inter_rat) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; - Description: Specifies criteria for triggering of an E-UTRA - measurement reporting event + if(ie_ptr != NULL && + rep_cnfg_inter_rat != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// FIXME + // Trigger Type + rep_cnfg_inter_rat->trigger_type = (LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_EVENT == rep_cnfg_inter_rat->trigger_type) + { + // Event ID + rep_cnfg_inter_rat->event.event_id = (LIBLTE_RRC_EVENT_ID_INTER_RAT_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_EVENT_ID_INTER_RAT_B1 == rep_cnfg_inter_rat->event.event_id) + { + // Threshold Type + rep_cnfg_inter_rat->event.event_b1.type = (LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 2); + if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_UTRA == rep_cnfg_inter_rat->event.event_b1.type) + { + // Type + rep_cnfg_inter_rat->event.event_b1.utra.type = (LIBLTE_RRC_THRESHOLD_UTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_UTRA_TYPE_RSCP == rep_cnfg_inter_rat->event.event_b1.utra.type) + { + rep_cnfg_inter_rat->event.event_b1.utra.value = liblte_bits_2_value(ie_ptr, 7) - 5; + }else{ + rep_cnfg_inter_rat->event.event_b1.utra.value = liblte_bits_2_value(ie_ptr, 6); + } + }else if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_GERAN == rep_cnfg_inter_rat->event.event_b1.type){ + rep_cnfg_inter_rat->event.event_b1.geran = liblte_bits_2_value(ie_ptr, 6); + }else{ + rep_cnfg_inter_rat->event.event_b1.cdma2000 = liblte_bits_2_value(ie_ptr, 6); + } + }else{ + // Threshold1 Type + rep_cnfg_inter_rat->event.event_b2.eutra.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_inter_rat->event.event_b2.eutra.type) + { + liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_inter_rat->event.event_b2.eutra.range); + }else{ + liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_inter_rat->event.event_b2.eutra.range); + } + + // Threshold2 Type + rep_cnfg_inter_rat->event.event_b2.type2 = (LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 2); + if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_UTRA == rep_cnfg_inter_rat->event.event_b2.type2) + { + // Type + rep_cnfg_inter_rat->event.event_b2.utra.type = (LIBLTE_RRC_THRESHOLD_UTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_THRESHOLD_UTRA_TYPE_RSCP == rep_cnfg_inter_rat->event.event_b2.utra.type) + { + rep_cnfg_inter_rat->event.event_b2.utra.value = liblte_bits_2_value(ie_ptr, 7) - 5; + }else{ + rep_cnfg_inter_rat->event.event_b2.utra.value = liblte_bits_2_value(ie_ptr, 6); + } + }else if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_GERAN == rep_cnfg_inter_rat->event.event_b2.type2){ + rep_cnfg_inter_rat->event.event_b2.geran = liblte_bits_2_value(ie_ptr, 6); + }else{ + rep_cnfg_inter_rat->event.event_b2.cdma2000 = liblte_bits_2_value(ie_ptr, 6); + } + } + + // Hysteresis + liblte_rrc_unpack_hysteresis_ie(ie_ptr, &rep_cnfg_inter_rat->event.hysteresis); + + // Time To Trigger + liblte_rrc_unpack_time_to_trigger_ie(ie_ptr, &rep_cnfg_inter_rat->event.time_to_trigger); + }else{ + // Purpose + rep_cnfg_inter_rat->periodical.purpose = (LIBLTE_RRC_PURPOSE_INTER_RAT_ENUM)liblte_bits_2_value(ie_ptr, 2); + } + + // Max Report Cells + rep_cnfg_inter_rat->max_report_cells = liblte_bits_2_value(ie_ptr, 3) + 1; + + // Report Interval + liblte_rrc_unpack_report_interval_ie(ie_ptr, &rep_cnfg_inter_rat->report_interval); + + // Report Amount + rep_cnfg_inter_rat->report_amount = (LIBLTE_RRC_REPORT_AMOUNT_ENUM)liblte_bits_2_value(ie_ptr, 3); + + skip_sequence_type_extension(ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* - IE Name: Report Config ID + IE Name: Report Config To Add Mod List - Description: Identifies a measurement reporting configuration + Description: Concerns a list of reporting configurations to add + or modify Document Reference: 36.331 v10.0.0 Section 6.3.5 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_id_ie(uint8 report_cnfg_id, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_to_add_mod_list_ie(LIBLTE_RRC_REPORT_CONFIG_TO_ADD_MOD_LIST_STRUCT *list, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; - if(ie_ptr != NULL) + if(list != NULL && + ie_ptr != NULL) { - rrc_value_2_bits(report_cnfg_id - 1, ie_ptr, 5); + // List Size + liblte_value_2_bits(list->N_rep_cnfg - 1, ie_ptr, 5); + + for(i=0; iN_rep_cnfg; i++) + { + // Report Config ID + liblte_rrc_pack_report_config_id_ie(list->rep_cnfg_list[i].rep_cnfg_id, ie_ptr); + + // Report Config Choice + liblte_value_2_bits(list->rep_cnfg_list[i].rep_cnfg_type, ie_ptr, 1); + + if(LIBLTE_RRC_REPORT_CONFIG_TYPE_EUTRA == list->rep_cnfg_list[i].rep_cnfg_type) + { + liblte_rrc_pack_report_config_eutra_ie(&list->rep_cnfg_list[i].rep_cnfg_eutra, ie_ptr); + }else{ + liblte_rrc_pack_report_config_inter_rat_ie(&list->rep_cnfg_list[i].rep_cnfg_inter_rat, ie_ptr); + } + } err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_id_ie(uint8 **ie_ptr, - uint8 *report_cnfg_id) +LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_to_add_mod_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_REPORT_CONFIG_TO_ADD_MOD_LIST_STRUCT *list) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; - if(ie_ptr != NULL && - report_cnfg_id != NULL) + if(ie_ptr != NULL && + list != NULL) { - *report_cnfg_id = rrc_bits_2_value(ie_ptr, 5) + 1; + // List Size + list->N_rep_cnfg = liblte_bits_2_value(ie_ptr, 5) + 1; + + for(i=0; iN_rep_cnfg; i++) + { + // Report Config ID + liblte_rrc_unpack_report_config_id_ie(ie_ptr, &list->rep_cnfg_list[i].rep_cnfg_id); + + // Report Config Choice + list->rep_cnfg_list[i].rep_cnfg_type = (LIBLTE_RRC_REPORT_CONFIG_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + + if(LIBLTE_RRC_REPORT_CONFIG_TYPE_EUTRA == list->rep_cnfg_list[i].rep_cnfg_type) + { + liblte_rrc_unpack_report_config_eutra_ie(ie_ptr, &list->rep_cnfg_list[i].rep_cnfg_eutra); + }else{ + liblte_rrc_unpack_report_config_inter_rat_ie(ie_ptr, &list->rep_cnfg_list[i].rep_cnfg_inter_rat); + } + } err = LIBLTE_SUCCESS; } @@ -1137,26 +3040,6 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_id_ie(uint8 **ie_ptr, return(err); } -/********************************************************************* - IE Name: Report Config Inter RAT - - Description: Specifies criteria for triggering of an inter-RAT - measurement reporting event - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// FIXME - -/********************************************************************* - IE Name: Report Config To Add Mod List - - Description: Concerns a list of reporting configurations to add - or modify - - Document Reference: 36.331 v10.0.0 Section 6.3.5 -*********************************************************************/ -// FIXME - /********************************************************************* IE Name: Report Interval @@ -1171,7 +3054,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_report_interval_ie(LIBLTE_RRC_REPORT_INTERVAL_ if(ie_ptr != NULL) { - rrc_value_2_bits(report_int, ie_ptr, 4); + liblte_value_2_bits(report_int, ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -1186,7 +3069,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_interval_ie(uint8 if(ie_ptr != NULL && report_int != NULL) { - *report_int = (LIBLTE_RRC_REPORT_INTERVAL_ENUM)rrc_bits_2_value(ie_ptr, 4); + *report_int = (LIBLTE_RRC_REPORT_INTERVAL_ENUM)liblte_bits_2_value(ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -1209,7 +3092,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rsrp_range_ie(uint8 rsrp_range, if(ie_ptr != NULL) { - rrc_value_2_bits(rsrp_range, ie_ptr, 7); + liblte_value_2_bits(rsrp_range, ie_ptr, 7); err = LIBLTE_SUCCESS; } @@ -1224,7 +3107,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rsrp_range_ie(uint8 **ie_ptr, if(ie_ptr != NULL && rsrp_range != NULL) { - *rsrp_range = rrc_bits_2_value(ie_ptr, 7); + *rsrp_range = liblte_bits_2_value(ie_ptr, 7); err = LIBLTE_SUCCESS; } @@ -1247,7 +3130,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rsrq_range_ie(uint8 rsrq_range, if(ie_ptr != NULL) { - rrc_value_2_bits(rsrq_range, ie_ptr, 6); + liblte_value_2_bits(rsrq_range, ie_ptr, 6); err = LIBLTE_SUCCESS; } @@ -1262,7 +3145,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rsrq_range_ie(uint8 **ie_ptr, if(ie_ptr != NULL && rsrq_range != NULL) { - *rsrq_range = rrc_bits_2_value(ie_ptr, 6); + *rsrq_range = liblte_bits_2_value(ie_ptr, 6); err = LIBLTE_SUCCESS; } @@ -1287,7 +3170,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_time_to_trigger_ie(LIBLTE_RRC_TIME_TO_TRIGGER_ if(ie_ptr != NULL) { - rrc_value_2_bits(time_to_trigger, ie_ptr, 4); + liblte_value_2_bits(time_to_trigger, ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -1302,7 +3185,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_time_to_trigger_ie(uint8 if(ie_ptr != NULL && time_to_trigger != NULL) { - *time_to_trigger = (LIBLTE_RRC_TIME_TO_TRIGGER_ENUM)rrc_bits_2_value(ie_ptr, 4); + *time_to_trigger = (LIBLTE_RRC_TIME_TO_TRIGGER_ENUM)liblte_bits_2_value(ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -1324,7 +3207,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_additional_spectrum_emission_ie(uint8 add_sp if(ie_ptr != NULL) { - rrc_value_2_bits(add_spect_em - 1, ie_ptr, 5); + liblte_value_2_bits(add_spect_em - 1, ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -1339,7 +3222,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_additional_spectrum_emission_ie(uint8 **ie_p if(ie_ptr != NULL && add_spect_em != NULL) { - *add_spect_em = rrc_bits_2_value(ie_ptr, 5) + 1; + *add_spect_em = liblte_bits_2_value(ie_ptr, 5) + 1; err = LIBLTE_SUCCESS; } @@ -1362,7 +3245,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_cdma2000_ie(uint16 arfcn, if(ie_ptr != NULL) { - rrc_value_2_bits(arfcn, ie_ptr, 11); + liblte_value_2_bits(arfcn, ie_ptr, 11); err = LIBLTE_SUCCESS; } @@ -1377,7 +3260,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_cdma2000_ie(uint8 **ie_ptr, if(ie_ptr != NULL && arfcn != NULL) { - *arfcn = rrc_bits_2_value(ie_ptr, 11); + *arfcn = liblte_bits_2_value(ie_ptr, 11); err = LIBLTE_SUCCESS; } @@ -1401,7 +3284,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_eutra_ie(uint16 arfcn, if(ie_ptr != NULL) { - rrc_value_2_bits(arfcn, ie_ptr, 16); + liblte_value_2_bits(arfcn, ie_ptr, 16); err = LIBLTE_SUCCESS; } @@ -1416,7 +3299,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_eutra_ie(uint8 **ie_ptr, if(ie_ptr != NULL && arfcn != NULL) { - *arfcn = rrc_bits_2_value(ie_ptr, 16); + *arfcn = liblte_bits_2_value(ie_ptr, 16); err = LIBLTE_SUCCESS; } @@ -1439,7 +3322,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_geran_ie(uint16 arfcn, if(ie_ptr != NULL) { - rrc_value_2_bits(arfcn, ie_ptr, 10); + liblte_value_2_bits(arfcn, ie_ptr, 10); err = LIBLTE_SUCCESS; } @@ -1454,7 +3337,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_geran_ie(uint8 **ie_ptr, if(ie_ptr != NULL && arfcn != NULL) { - *arfcn = rrc_bits_2_value(ie_ptr, 10); + *arfcn = liblte_bits_2_value(ie_ptr, 10); err = LIBLTE_SUCCESS; } @@ -1478,7 +3361,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_utra_ie(uint16 arfcn, if(ie_ptr != NULL) { - rrc_value_2_bits(arfcn, ie_ptr, 14); + liblte_value_2_bits(arfcn, ie_ptr, 14); err = LIBLTE_SUCCESS; } @@ -1493,7 +3376,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_utra_ie(uint8 **ie_ptr, if(ie_ptr != NULL && arfcn != NULL) { - *arfcn = rrc_bits_2_value(ie_ptr, 14); + *arfcn = liblte_bits_2_value(ie_ptr, 14); err = LIBLTE_SUCCESS; } @@ -1517,9 +3400,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_band_class_cdma2000_ie(LIBLTE_RRC_BAND_CLASS_C if(ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(bc_cdma2000, ie_ptr, 5); + liblte_value_2_bits(bc_cdma2000, ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -1535,9 +3418,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_band_class_cdma2000_ie(uint8 bc_cdma2000 != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + liblte_bits_2_value(ie_ptr, 1); - *bc_cdma2000 = (LIBLTE_RRC_BAND_CLASS_CDMA2000_ENUM)rrc_bits_2_value(ie_ptr, 5); + *bc_cdma2000 = (LIBLTE_RRC_BAND_CLASS_CDMA2000_ENUM)liblte_bits_2_value(ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -1560,7 +3443,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_band_indicator_geran_ie(LIBLTE_RRC_BAND_INDICA if(ie_ptr != NULL) { - rrc_value_2_bits(bi_geran, ie_ptr, 1); + liblte_value_2_bits(bi_geran, ie_ptr, 1); err = LIBLTE_SUCCESS; } @@ -1575,7 +3458,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_band_indicator_geran_ie(uint8 if(ie_ptr != NULL && bi_geran != NULL) { - *bi_geran = (LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM)rrc_bits_2_value(ie_ptr, 1); + *bi_geran = (LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM)liblte_bits_2_value(ie_ptr, 1); err = LIBLTE_SUCCESS; } @@ -1683,19 +3566,19 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_carrier_freqs_geran_ie(LIBLTE_RRC_CARRIER_FREQ { liblte_rrc_pack_arfcn_value_geran_ie(carrier_freqs->starting_arfcn, ie_ptr); liblte_rrc_pack_band_indicator_geran_ie(carrier_freqs->band_indicator, ie_ptr); - rrc_value_2_bits(carrier_freqs->following_arfcns, ie_ptr, 2); + liblte_value_2_bits(carrier_freqs->following_arfcns, ie_ptr, 2); if(LIBLTE_RRC_FOLLOWING_ARFCNS_EXPLICIT_LIST == carrier_freqs->following_arfcns) { - rrc_value_2_bits(carrier_freqs->explicit_list_of_arfcns_size, ie_ptr, 5); + liblte_value_2_bits(carrier_freqs->explicit_list_of_arfcns_size, ie_ptr, 5); for(i=0; iexplicit_list_of_arfcns_size; i++) { liblte_rrc_pack_arfcn_value_geran_ie(carrier_freqs->explicit_list_of_arfcns[i], ie_ptr); } }else if(LIBLTE_RRC_FOLLOWING_ARFCNS_EQUALLY_SPACED == carrier_freqs->following_arfcns){ - rrc_value_2_bits(carrier_freqs->equally_spaced_arfcns.arfcn_spacing - 1, ie_ptr, 3); - rrc_value_2_bits(carrier_freqs->equally_spaced_arfcns.number_of_arfcns, ie_ptr, 5); + liblte_value_2_bits(carrier_freqs->equally_spaced_arfcns.arfcn_spacing - 1, ie_ptr, 3); + liblte_value_2_bits(carrier_freqs->equally_spaced_arfcns.number_of_arfcns, ie_ptr, 5); }else{ // LIBLTE_RRC_FOLLOWING_ARFCNS_VARIABLE_BIT_MAP == carrier_freqs->following_arfcns - rrc_value_2_bits(carrier_freqs->variable_bit_map_of_arfcns, ie_ptr, 16); + liblte_value_2_bits(carrier_freqs->variable_bit_map_of_arfcns, ie_ptr, 16); } err = LIBLTE_SUCCESS; @@ -1714,19 +3597,19 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_carrier_freqs_geran_ie(uint8 { liblte_rrc_unpack_arfcn_value_geran_ie(ie_ptr, &carrier_freqs->starting_arfcn); liblte_rrc_unpack_band_indicator_geran_ie(ie_ptr, &carrier_freqs->band_indicator); - carrier_freqs->following_arfcns = (LIBLTE_RRC_FOLLOWING_ARFCNS_ENUM)rrc_bits_2_value(ie_ptr, 2); + carrier_freqs->following_arfcns = (LIBLTE_RRC_FOLLOWING_ARFCNS_ENUM)liblte_bits_2_value(ie_ptr, 2); if(LIBLTE_RRC_FOLLOWING_ARFCNS_EXPLICIT_LIST == carrier_freqs->following_arfcns) { - carrier_freqs->explicit_list_of_arfcns_size = rrc_bits_2_value(ie_ptr, 5); + carrier_freqs->explicit_list_of_arfcns_size = liblte_bits_2_value(ie_ptr, 5); for(i=0; iexplicit_list_of_arfcns_size; i++) { liblte_rrc_unpack_arfcn_value_geran_ie(ie_ptr, &carrier_freqs->explicit_list_of_arfcns[i]); } }else if(LIBLTE_RRC_FOLLOWING_ARFCNS_EQUALLY_SPACED == carrier_freqs->following_arfcns){ - carrier_freqs->equally_spaced_arfcns.arfcn_spacing = rrc_bits_2_value(ie_ptr, 3) + 1; - carrier_freqs->equally_spaced_arfcns.number_of_arfcns = rrc_bits_2_value(ie_ptr, 5); + carrier_freqs->equally_spaced_arfcns.arfcn_spacing = liblte_bits_2_value(ie_ptr, 3) + 1; + carrier_freqs->equally_spaced_arfcns.number_of_arfcns = liblte_bits_2_value(ie_ptr, 5); }else{ // LIBLTE_RRC_FOLLOWING_ARFCNS_VARIABLE_BIT_MAP == carrier_freqs->following_arfcns - carrier_freqs->variable_bit_map_of_arfcns = rrc_bits_2_value(ie_ptr, 16); + carrier_freqs->variable_bit_map_of_arfcns = liblte_bits_2_value(ie_ptr, 16); } err = LIBLTE_SUCCESS; @@ -1749,7 +3632,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_cdma2000_type_ie(LIBLTE_RRC_CDMA2000_TYPE_ENUM if(ie_ptr != NULL) { - rrc_value_2_bits(cdma2000_type, ie_ptr, 1); + liblte_value_2_bits(cdma2000_type, ie_ptr, 1); err = LIBLTE_SUCCESS; } @@ -1764,7 +3647,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_cdma2000_type_ie(uint8 if(ie_ptr != NULL && cdma2000_type != NULL) { - *cdma2000_type = (LIBLTE_RRC_CDMA2000_TYPE_ENUM)rrc_bits_2_value(ie_ptr, 1); + *cdma2000_type = (LIBLTE_RRC_CDMA2000_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); err = LIBLTE_SUCCESS; } @@ -1786,7 +3669,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_identity_ie(uint32 cell_id, if(ie_ptr != NULL) { - rrc_value_2_bits(cell_id, ie_ptr, 28); + liblte_value_2_bits(cell_id, ie_ptr, 28); err = LIBLTE_SUCCESS; } @@ -1801,7 +3684,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_identity_ie(uint8 **ie_ptr, if(ie_ptr != NULL && cell_id != NULL) { - *cell_id = rrc_bits_2_value(ie_ptr, 28); + *cell_id = liblte_bits_2_value(ie_ptr, 28); err = LIBLTE_SUCCESS; } @@ -1817,7 +3700,52 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_identity_ie(uint8 **ie_ptr, Document Reference: 36.331 v10.0.0 Section 6.3.4 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_index_list_ie(LIBLTE_RRC_CELL_INDEX_LIST_STRUCT *cell_idx_list, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(cell_idx_list != NULL && + ie_ptr != NULL) + { + // List Size + liblte_value_2_bits(cell_idx_list->N_cell_idx - 1, ie_ptr, 5); + + for(i=0; iN_cell_idx; i++) + { + // Cell Index + liblte_value_2_bits(cell_idx_list->cell_idx[i] - 1, ie_ptr, 5); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_index_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_CELL_INDEX_LIST_STRUCT *cell_idx_list) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ie_ptr != NULL && + cell_idx_list != NULL) + { + // List Size + cell_idx_list->N_cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1; + + for(i=0; iN_cell_idx; i++) + { + // Cell Index + cell_idx_list->cell_idx[i] = liblte_bits_2_value(ie_ptr, 5) + 1; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* IE Name: Cell Reselection Priority @@ -1836,7 +3764,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_reselection_priority_ie(uint8 cell_rese if(ie_ptr != NULL) { - rrc_value_2_bits(cell_resel_prio, ie_ptr, 3); + liblte_value_2_bits(cell_resel_prio, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -1851,7 +3779,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_reselection_priority_ie(uint8 **ie_ptr, if(ie_ptr != NULL && cell_resel_prio != NULL) { - *cell_resel_prio = rrc_bits_2_value(ie_ptr, 3); + *cell_resel_prio = liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -1876,19 +3804,19 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_csfb_registration_param_1xrtt_ie(LIBLTE_RRC_CS if(csfb_reg_param != NULL && ie_ptr != NULL) { - rrc_value_2_bits(csfb_reg_param->sid, ie_ptr, 15); - rrc_value_2_bits(csfb_reg_param->nid, ie_ptr, 16); - rrc_value_2_bits(csfb_reg_param->multiple_sid, ie_ptr, 1); - rrc_value_2_bits(csfb_reg_param->multiple_nid, ie_ptr, 1); - rrc_value_2_bits(csfb_reg_param->home_reg, ie_ptr, 1); - rrc_value_2_bits(csfb_reg_param->foreign_sid_reg, ie_ptr, 1); - rrc_value_2_bits(csfb_reg_param->foreign_nid_reg, ie_ptr, 1); - rrc_value_2_bits(csfb_reg_param->param_reg, ie_ptr, 1); - rrc_value_2_bits(csfb_reg_param->power_up_reg, ie_ptr, 1); - rrc_value_2_bits(csfb_reg_param->reg_period, ie_ptr, 7); - rrc_value_2_bits(csfb_reg_param->reg_zone, ie_ptr, 12); - rrc_value_2_bits(csfb_reg_param->total_zone, ie_ptr, 3); - rrc_value_2_bits(csfb_reg_param->zone_timer, ie_ptr, 3); + liblte_value_2_bits(csfb_reg_param->sid, ie_ptr, 15); + liblte_value_2_bits(csfb_reg_param->nid, ie_ptr, 16); + liblte_value_2_bits(csfb_reg_param->multiple_sid, ie_ptr, 1); + liblte_value_2_bits(csfb_reg_param->multiple_nid, ie_ptr, 1); + liblte_value_2_bits(csfb_reg_param->home_reg, ie_ptr, 1); + liblte_value_2_bits(csfb_reg_param->foreign_sid_reg, ie_ptr, 1); + liblte_value_2_bits(csfb_reg_param->foreign_nid_reg, ie_ptr, 1); + liblte_value_2_bits(csfb_reg_param->param_reg, ie_ptr, 1); + liblte_value_2_bits(csfb_reg_param->power_up_reg, ie_ptr, 1); + liblte_value_2_bits(csfb_reg_param->reg_period, ie_ptr, 7); + liblte_value_2_bits(csfb_reg_param->reg_zone, ie_ptr, 12); + liblte_value_2_bits(csfb_reg_param->total_zone, ie_ptr, 3); + liblte_value_2_bits(csfb_reg_param->zone_timer, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -1903,19 +3831,19 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_csfb_registration_param_1xrtt_ie(uint8 if(ie_ptr != NULL && csfb_reg_param != NULL) { - csfb_reg_param->sid = rrc_bits_2_value(ie_ptr, 15); - csfb_reg_param->nid = rrc_bits_2_value(ie_ptr, 16); - csfb_reg_param->multiple_sid = rrc_bits_2_value(ie_ptr, 1); - csfb_reg_param->multiple_nid = rrc_bits_2_value(ie_ptr, 1); - csfb_reg_param->home_reg = rrc_bits_2_value(ie_ptr, 1); - csfb_reg_param->foreign_sid_reg = rrc_bits_2_value(ie_ptr, 1); - csfb_reg_param->foreign_nid_reg = rrc_bits_2_value(ie_ptr, 1); - csfb_reg_param->param_reg = rrc_bits_2_value(ie_ptr, 1); - csfb_reg_param->power_up_reg = rrc_bits_2_value(ie_ptr, 1); - csfb_reg_param->reg_period = rrc_bits_2_value(ie_ptr, 7); - csfb_reg_param->reg_zone = rrc_bits_2_value(ie_ptr, 12); - csfb_reg_param->total_zone = rrc_bits_2_value(ie_ptr, 3); - csfb_reg_param->zone_timer = rrc_bits_2_value(ie_ptr, 3); + csfb_reg_param->sid = liblte_bits_2_value(ie_ptr, 15); + csfb_reg_param->nid = liblte_bits_2_value(ie_ptr, 16); + csfb_reg_param->multiple_sid = liblte_bits_2_value(ie_ptr, 1); + csfb_reg_param->multiple_nid = liblte_bits_2_value(ie_ptr, 1); + csfb_reg_param->home_reg = liblte_bits_2_value(ie_ptr, 1); + csfb_reg_param->foreign_sid_reg = liblte_bits_2_value(ie_ptr, 1); + csfb_reg_param->foreign_nid_reg = liblte_bits_2_value(ie_ptr, 1); + csfb_reg_param->param_reg = liblte_bits_2_value(ie_ptr, 1); + csfb_reg_param->power_up_reg = liblte_bits_2_value(ie_ptr, 1); + csfb_reg_param->reg_period = liblte_bits_2_value(ie_ptr, 7); + csfb_reg_param->reg_zone = liblte_bits_2_value(ie_ptr, 12); + csfb_reg_param->total_zone = liblte_bits_2_value(ie_ptr, 3); + csfb_reg_param->zone_timer = liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -1930,7 +3858,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_csfb_registration_param_1xrtt_v920_ie(LIBLTE_R if(csfb_reg_param != NULL && ie_ptr != NULL) { - rrc_value_2_bits(csfb_reg_param->power_down_reg, ie_ptr, 1); + liblte_value_2_bits(csfb_reg_param->power_down_reg, ie_ptr, 1); err = LIBLTE_SUCCESS; } @@ -1945,7 +3873,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_csfb_registration_param_1xrtt_v920_ie(uint8 if(ie_ptr != NULL && csfb_reg_param != NULL) { - csfb_reg_param->power_down_reg = (LIBLTE_RRC_POWER_DOWN_REG_R9_ENUM)rrc_bits_2_value(ie_ptr, 1); + csfb_reg_param->power_down_reg = (LIBLTE_RRC_POWER_DOWN_REG_R9_ENUM)liblte_bits_2_value(ie_ptr, 1); err = LIBLTE_SUCCESS; } @@ -2011,7 +3939,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_utra_ie(LIBLTE_RRC_CELL_GLOBAL_ ie_ptr != NULL) { liblte_rrc_pack_plmn_identity_ie(&cell_global_id->plmn_id, ie_ptr); - rrc_value_2_bits(cell_global_id->cell_id, ie_ptr, 28); + liblte_value_2_bits(cell_global_id->cell_id, ie_ptr, 28); err = LIBLTE_SUCCESS; } @@ -2027,7 +3955,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_utra_ie(uint8 cell_global_id != NULL) { liblte_rrc_unpack_plmn_identity_ie(ie_ptr, &cell_global_id->plmn_id); - cell_global_id->cell_id = rrc_bits_2_value(ie_ptr, 28); + cell_global_id->cell_id = liblte_bits_2_value(ie_ptr, 28); err = LIBLTE_SUCCESS; } @@ -2052,8 +3980,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_geran_ie(LIBLTE_RRC_CELL_GLOBAL ie_ptr != NULL) { liblte_rrc_pack_plmn_identity_ie(&cell_global_id->plmn_id, ie_ptr); - rrc_value_2_bits(cell_global_id->lac, ie_ptr, 16); - rrc_value_2_bits(cell_global_id->cell_id, ie_ptr, 16); + liblte_value_2_bits(cell_global_id->lac, ie_ptr, 16); + liblte_value_2_bits(cell_global_id->cell_id, ie_ptr, 16); err = LIBLTE_SUCCESS; } @@ -2069,8 +3997,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_geran_ie(uint8 cell_global_id != NULL) { liblte_rrc_unpack_plmn_identity_ie(ie_ptr, &cell_global_id->plmn_id); - cell_global_id->lac = rrc_bits_2_value(ie_ptr, 16); - cell_global_id->cell_id = rrc_bits_2_value(ie_ptr, 16); + cell_global_id->lac = liblte_bits_2_value(ie_ptr, 16); + cell_global_id->cell_id = liblte_bits_2_value(ie_ptr, 16); err = LIBLTE_SUCCESS; } @@ -2094,12 +4022,12 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_cdma2000_ie(LIBLTE_RRC_CELL_GLO if(cell_global_id != NULL && ie_ptr != NULL) { - rrc_value_2_bits((uint32)(cell_global_id->onexrtt >> 15), ie_ptr, 32); - rrc_value_2_bits((uint32)(cell_global_id->onexrtt & 0x7FFFULL), ie_ptr, 15); - rrc_value_2_bits(cell_global_id->hrpd[0], ie_ptr, 32); - rrc_value_2_bits(cell_global_id->hrpd[1], ie_ptr, 32); - rrc_value_2_bits(cell_global_id->hrpd[2], ie_ptr, 32); - rrc_value_2_bits(cell_global_id->hrpd[3], ie_ptr, 32); + liblte_value_2_bits((uint32)(cell_global_id->onexrtt >> 15), ie_ptr, 32); + liblte_value_2_bits((uint32)(cell_global_id->onexrtt & 0x7FFFULL), ie_ptr, 15); + liblte_value_2_bits(cell_global_id->hrpd[0], ie_ptr, 32); + liblte_value_2_bits(cell_global_id->hrpd[1], ie_ptr, 32); + liblte_value_2_bits(cell_global_id->hrpd[2], ie_ptr, 32); + liblte_value_2_bits(cell_global_id->hrpd[3], ie_ptr, 32); err = LIBLTE_SUCCESS; } @@ -2114,12 +4042,12 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_cdma2000_ie(uint8 if(ie_ptr != NULL && cell_global_id != NULL) { - cell_global_id->onexrtt = (uint64)rrc_bits_2_value(ie_ptr, 32) << 15; - cell_global_id->onexrtt |= (uint64)rrc_bits_2_value(ie_ptr, 15); - cell_global_id->hrpd[0] = rrc_bits_2_value(ie_ptr, 32); - cell_global_id->hrpd[1] = rrc_bits_2_value(ie_ptr, 32); - cell_global_id->hrpd[2] = rrc_bits_2_value(ie_ptr, 32); - cell_global_id->hrpd[3] = rrc_bits_2_value(ie_ptr, 32); + cell_global_id->onexrtt = (uint64)liblte_bits_2_value(ie_ptr, 32) << 15; + cell_global_id->onexrtt |= (uint64)liblte_bits_2_value(ie_ptr, 15); + cell_global_id->hrpd[0] = liblte_bits_2_value(ie_ptr, 32); + cell_global_id->hrpd[1] = liblte_bits_2_value(ie_ptr, 32); + cell_global_id->hrpd[2] = liblte_bits_2_value(ie_ptr, 32); + cell_global_id->hrpd[3] = liblte_bits_2_value(ie_ptr, 32); err = LIBLTE_SUCCESS; } @@ -2141,7 +4069,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_csg_identity_ie(uint32 csg_id, if(ie_ptr != NULL) { - rrc_value_2_bits(csg_id, ie_ptr, 27); + liblte_value_2_bits(csg_id, ie_ptr, 27); err = LIBLTE_SUCCESS; } @@ -2156,7 +4084,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_csg_identity_ie(uint8 **ie_ptr, if(ie_ptr != NULL && csg_id != NULL) { - *csg_id = rrc_bits_2_value(ie_ptr, 27); + *csg_id = liblte_bits_2_value(ie_ptr, 27); err = LIBLTE_SUCCESS; } @@ -2172,7 +4100,165 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_csg_identity_ie(uint8 **ie_ptr, Document Reference: 36.331 v10.0.0 Section 6.3.4 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_mobility_control_info_ie(LIBLTE_RRC_MOBILITY_CONTROL_INFO_STRUCT *mob_ctrl_info, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(mob_ctrl_info != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Optional indicators + liblte_value_2_bits(mob_ctrl_info->carrier_freq_eutra_present, ie_ptr, 1); + liblte_value_2_bits(mob_ctrl_info->carrier_bw_eutra_present, ie_ptr, 1); + liblte_value_2_bits(mob_ctrl_info->add_spect_em_present, ie_ptr, 1); + liblte_value_2_bits(mob_ctrl_info->rach_cnfg_ded_present, ie_ptr, 1); + + // Target Phys Cell ID + liblte_rrc_pack_phys_cell_id_ie(mob_ctrl_info->target_pci, ie_ptr); + + // Carrier Freq + if(mob_ctrl_info->carrier_freq_eutra_present) + { + // Optional indicator + liblte_value_2_bits(mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq_present, ie_ptr, 1); + + // DL Carrier Freq + liblte_rrc_pack_arfcn_value_eutra_ie(mob_ctrl_info->carrier_freq_eutra.dl_carrier_freq, ie_ptr); + + // UL Carrier Freq + if(mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq_present) + { + liblte_rrc_pack_arfcn_value_eutra_ie(mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq, ie_ptr); + } + } + + // Carrier Bandwidth + if(mob_ctrl_info->carrier_bw_eutra_present) + { + // Optional indicator + liblte_value_2_bits(mob_ctrl_info->carrier_bw_eutra.ul_bw_present, ie_ptr, 1); + + // DL Bandwidth + liblte_value_2_bits(mob_ctrl_info->carrier_bw_eutra.dl_bw, ie_ptr, 4); + + // UL Bandwidth + if(mob_ctrl_info->carrier_bw_eutra.ul_bw_present) + { + liblte_value_2_bits(mob_ctrl_info->carrier_bw_eutra.ul_bw, ie_ptr, 4); + } + } + + // Additional Spectrum Emission + if(mob_ctrl_info->add_spect_em_present) + { + liblte_rrc_pack_additional_spectrum_emission_ie(mob_ctrl_info->add_spect_em, ie_ptr); + } + + // T304 + liblte_value_2_bits(mob_ctrl_info->t304, ie_ptr, 3); + + // New UE Identity + liblte_rrc_pack_c_rnti_ie(mob_ctrl_info->new_ue_id, ie_ptr); + + // Radio Resource Config Common + liblte_rrc_pack_rr_config_common_ie(&mob_ctrl_info->rr_cnfg_common, ie_ptr); + + // RACH Config Dedicated + if(mob_ctrl_info->rach_cnfg_ded_present) + { + liblte_rrc_pack_rach_config_dedicated_ie(&mob_ctrl_info->rach_cnfg_ded, ie_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_mobility_control_info_ie(uint8 **ie_ptr, + LIBLTE_RRC_MOBILITY_CONTROL_INFO_STRUCT *mob_ctrl_info) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; + + if(ie_ptr != NULL && + mob_ctrl_info != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Optional indicators + mob_ctrl_info->carrier_freq_eutra_present = liblte_bits_2_value(ie_ptr, 1); + mob_ctrl_info->carrier_bw_eutra_present = liblte_bits_2_value(ie_ptr, 1); + mob_ctrl_info->add_spect_em_present = liblte_bits_2_value(ie_ptr, 1); + mob_ctrl_info->rach_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1); + + // Target Phys Cell ID + liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &mob_ctrl_info->target_pci); + + // Carrier Freq + if(mob_ctrl_info->carrier_freq_eutra_present) + { + // Optional indicator + mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq_present = liblte_bits_2_value(ie_ptr, 1); + + // DL Carrier Freq + liblte_rrc_unpack_arfcn_value_eutra_ie(ie_ptr, &mob_ctrl_info->carrier_freq_eutra.dl_carrier_freq); + + // UL Carrier Freq + if(mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq_present) + { + liblte_rrc_unpack_arfcn_value_eutra_ie(ie_ptr, &mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq); + } + } + + // Carrier Bandwidth + if(mob_ctrl_info->carrier_bw_eutra_present) + { + // Optional indicator + mob_ctrl_info->carrier_bw_eutra.ul_bw_present = liblte_bits_2_value(ie_ptr, 1); + + // DL Bandwidth + mob_ctrl_info->carrier_bw_eutra.dl_bw = (LIBLTE_RRC_BANDWIDTH_ENUM)liblte_bits_2_value(ie_ptr, 4); + + // UL Bandwidth + if(mob_ctrl_info->carrier_bw_eutra.ul_bw_present) + { + mob_ctrl_info->carrier_bw_eutra.ul_bw = (LIBLTE_RRC_BANDWIDTH_ENUM)liblte_bits_2_value(ie_ptr, 4); + } + } + + // Additional Spectrum Emission + if(mob_ctrl_info->add_spect_em_present) + { + liblte_rrc_unpack_additional_spectrum_emission_ie(ie_ptr, &mob_ctrl_info->add_spect_em); + } + + // T304 + mob_ctrl_info->t304 = (LIBLTE_RRC_T304_ENUM)liblte_bits_2_value(ie_ptr, 3); + + // New UE Identity + liblte_rrc_unpack_c_rnti_ie(ie_ptr, &mob_ctrl_info->new_ue_id); + + // Radio Resource Config Common + liblte_rrc_unpack_rr_config_common_ie(ie_ptr, &mob_ctrl_info->rr_cnfg_common); + + // RACH Config Dedicated + if(mob_ctrl_info->rach_cnfg_ded_present) + { + liblte_rrc_unpack_rach_config_dedicated_ie(ie_ptr, &mob_ctrl_info->rach_cnfg_ded); + } + + skip_sequence_type_extension(ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* IE Name: Mobility Parameters CDMA2000 (1xRTT) @@ -2199,10 +4285,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_mobility_state_parameters_ie(LIBLTE_RRC_MOBILI if(mobility_state_params != NULL && ie_ptr != NULL) { - rrc_value_2_bits(mobility_state_params->t_eval, ie_ptr, 3); - rrc_value_2_bits(mobility_state_params->t_hyst_normal, ie_ptr, 3); - rrc_value_2_bits(mobility_state_params->n_cell_change_medium - 1, ie_ptr, 4); - rrc_value_2_bits(mobility_state_params->n_cell_change_high - 1, ie_ptr, 4); + liblte_value_2_bits(mobility_state_params->t_eval, ie_ptr, 3); + liblte_value_2_bits(mobility_state_params->t_hyst_normal, ie_ptr, 3); + liblte_value_2_bits(mobility_state_params->n_cell_change_medium - 1, ie_ptr, 4); + liblte_value_2_bits(mobility_state_params->n_cell_change_high - 1, ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -2217,10 +4303,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mobility_state_parameters_ie(uint8 if(ie_ptr != NULL && mobility_state_params != NULL) { - mobility_state_params->t_eval = (LIBLTE_RRC_T_EVALUATION_ENUM)rrc_bits_2_value(ie_ptr, 3); - mobility_state_params->t_hyst_normal = (LIBLTE_RRC_T_HYST_NORMAL_ENUM)rrc_bits_2_value(ie_ptr, 3); - mobility_state_params->n_cell_change_medium = rrc_bits_2_value(ie_ptr, 4) + 1; - mobility_state_params->n_cell_change_high = rrc_bits_2_value(ie_ptr, 4) + 1; + mobility_state_params->t_eval = (LIBLTE_RRC_T_EVALUATION_ENUM)liblte_bits_2_value(ie_ptr, 3); + mobility_state_params->t_hyst_normal = (LIBLTE_RRC_T_HYST_NORMAL_ENUM)liblte_bits_2_value(ie_ptr, 3); + mobility_state_params->n_cell_change_medium = liblte_bits_2_value(ie_ptr, 4) + 1; + mobility_state_params->n_cell_change_high = liblte_bits_2_value(ie_ptr, 4) + 1; err = LIBLTE_SUCCESS; } @@ -2242,7 +4328,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_ie(uint16 phys_cell_id, if(ie_ptr != NULL) { - rrc_value_2_bits(phys_cell_id, ie_ptr, 9); + liblte_value_2_bits(phys_cell_id, ie_ptr, 9); err = LIBLTE_SUCCESS; } @@ -2257,7 +4343,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_ie(uint8 **ie_ptr, if(ie_ptr != NULL && phys_cell_id != NULL) { - *phys_cell_id = rrc_bits_2_value(ie_ptr, 9); + *phys_cell_id = liblte_bits_2_value(ie_ptr, 9); err = LIBLTE_SUCCESS; } @@ -2285,10 +4371,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_range_ie(LIBLTE_RRC_PHYS_CELL_ID_ if(LIBLTE_RRC_PHYS_CELL_ID_RANGE_N1 != phys_cell_id_range->range) { - rrc_value_2_bits(1, ie_ptr, 1); - rrc_value_2_bits(phys_cell_id_range->range, ie_ptr, 4); + liblte_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(phys_cell_id_range->range, ie_ptr, 4); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } err = LIBLTE_SUCCESS; @@ -2307,10 +4393,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_range_ie(uint8 { liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &phys_cell_id_range->start); - opt = rrc_bits_2_value(ie_ptr, 1); + opt = liblte_bits_2_value(ie_ptr, 1); if(true == opt) { - phys_cell_id_range->range = (LIBLTE_RRC_PHYS_CELL_ID_RANGE_ENUM)rrc_bits_2_value(ie_ptr, 4); + phys_cell_id_range->range = (LIBLTE_RRC_PHYS_CELL_ID_RANGE_ENUM)liblte_bits_2_value(ie_ptr, 4); }else{ phys_cell_id_range->range = LIBLTE_RRC_PHYS_CELL_ID_RANGE_N1; } @@ -2328,7 +4414,66 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_range_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.4 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_range_utra_fdd_list_ie(LIBLTE_RRC_PHYS_CELL_ID_RANGE_UTRA_FDD_LIST_STRUCT *list, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(list != NULL && + ie_ptr != NULL) + { + liblte_value_2_bits(list->phys_cell_id_range_list_size - 1, ie_ptr, 2); + for(i=0; iphys_cell_id_range_list_size; i++) + { + // Optional indicator + liblte_value_2_bits(list->phys_cell_id_range_list[i].range_present, ie_ptr, 1); + + // Start + liblte_rrc_pack_phys_cell_id_utra_fdd_ie(list->phys_cell_id_range_list[i].start, ie_ptr); + + // Range + if(list->phys_cell_id_range_list[i].range_present) + { + liblte_value_2_bits(list->phys_cell_id_range_list[i].range - 2, ie_ptr, 9); + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_range_utra_fdd_list_ie(uint8 **ie_ptr, + LIBLTE_RRC_PHYS_CELL_ID_RANGE_UTRA_FDD_LIST_STRUCT *list) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(ie_ptr != NULL && + list != NULL) + { + list->phys_cell_id_range_list_size = liblte_bits_2_value(ie_ptr, 2) + 1; + for(i=0; iphys_cell_id_range_list_size; i++) + { + // Optional indicator + list->phys_cell_id_range_list[i].range_present = liblte_bits_2_value(ie_ptr, 1); + + // Start + liblte_rrc_unpack_phys_cell_id_utra_fdd_ie(ie_ptr, &list->phys_cell_id_range_list[i].start); + + // Range + if(list->phys_cell_id_range_list[i].range_present) + { + list->phys_cell_id_range_list[i].range = liblte_bits_2_value(ie_ptr, 9) + 2; + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* IE Name: Phys Cell ID CDMA2000 @@ -2345,7 +4490,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_cdma2000_ie(uint16 phys_cell_id if(ie_ptr != NULL) { - rrc_value_2_bits(phys_cell_id, ie_ptr, 9); + liblte_value_2_bits(phys_cell_id, ie_ptr, 9); err = LIBLTE_SUCCESS; } @@ -2360,7 +4505,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_cdma2000_ie(uint8 **ie_ptr, if(ie_ptr != NULL && phys_cell_id != NULL) { - *phys_cell_id = rrc_bits_2_value(ie_ptr, 9); + *phys_cell_id = liblte_bits_2_value(ie_ptr, 9); err = LIBLTE_SUCCESS; } @@ -2383,8 +4528,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_geran_ie(LIBLTE_RRC_PHYS_CELL_ID_ if(phys_cell_id != NULL && ie_ptr != NULL) { - rrc_value_2_bits(phys_cell_id->ncc, ie_ptr, 3); - rrc_value_2_bits(phys_cell_id->bcc, ie_ptr, 3); + liblte_value_2_bits(phys_cell_id->ncc, ie_ptr, 3); + liblte_value_2_bits(phys_cell_id->bcc, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -2399,8 +4544,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_geran_ie(uint8 if(ie_ptr != NULL && phys_cell_id != NULL) { - phys_cell_id->ncc = rrc_bits_2_value(ie_ptr, 3); - phys_cell_id->bcc = rrc_bits_2_value(ie_ptr, 3); + phys_cell_id->ncc = liblte_bits_2_value(ie_ptr, 3); + phys_cell_id->bcc = liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -2422,7 +4567,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_utra_fdd_ie(uint16 phys_cell_id if(ie_ptr != NULL) { - rrc_value_2_bits(phys_cell_id, ie_ptr, 9); + liblte_value_2_bits(phys_cell_id, ie_ptr, 9); err = LIBLTE_SUCCESS; } @@ -2437,7 +4582,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_utra_fdd_ie(uint8 **ie_ptr, if(ie_ptr != NULL && phys_cell_id != NULL) { - *phys_cell_id = rrc_bits_2_value(ie_ptr, 9); + *phys_cell_id = liblte_bits_2_value(ie_ptr, 9); err = LIBLTE_SUCCESS; } @@ -2459,7 +4604,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_utra_tdd_ie(uint8 phys_cell_id, if(ie_ptr != NULL) { - rrc_value_2_bits(phys_cell_id, ie_ptr, 7); + liblte_value_2_bits(phys_cell_id, ie_ptr, 7); err = LIBLTE_SUCCESS; } @@ -2474,7 +4619,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_utra_tdd_ie(uint8 **ie_ptr, if(ie_ptr != NULL && phys_cell_id != NULL) { - *phys_cell_id = rrc_bits_2_value(ie_ptr, 7); + *phys_cell_id = liblte_bits_2_value(ie_ptr, 7); err = LIBLTE_SUCCESS; } @@ -2500,11 +4645,11 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_plmn_identity_ie(LIBLTE_RRC_PLMN_IDENTITY_STRU if(plmn_id != NULL && ie_ptr != NULL) { - rrc_value_2_bits(mcc_opt, ie_ptr, 1); + liblte_value_2_bits(mcc_opt, ie_ptr, 1); if(true == mcc_opt) { - rrc_value_2_bits(plmn_id->mcc, ie_ptr, 12); + liblte_value_2_bits(plmn_id->mcc, ie_ptr, 12); } if((plmn_id->mnc & 0xFF00) == 0xFF00) @@ -2515,8 +4660,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_plmn_identity_ie(LIBLTE_RRC_PLMN_IDENTITY_STRU mnc_size = 12; mnc = plmn_id->mnc & 0x0FFF; } - rrc_value_2_bits((mnc_size/4)-2, ie_ptr, 1); - rrc_value_2_bits(mnc, ie_ptr, mnc_size); + liblte_value_2_bits((mnc_size/4)-2, ie_ptr, 1); + liblte_value_2_bits(mnc, ie_ptr, mnc_size); err = LIBLTE_SUCCESS; } @@ -2533,17 +4678,17 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_plmn_identity_ie(uint8 if(ie_ptr != NULL && plmn_id != NULL) { - mcc_opt = rrc_bits_2_value(ie_ptr, 1); + mcc_opt = liblte_bits_2_value(ie_ptr, 1); if(true == mcc_opt) { - plmn_id->mcc = rrc_bits_2_value(ie_ptr, 12); + plmn_id->mcc = liblte_bits_2_value(ie_ptr, 12); }else{ plmn_id->mcc = LIBLTE_RRC_MCC_NOT_PRESENT; } - mnc_size = (rrc_bits_2_value(ie_ptr, 1) + 2)*4; - plmn_id->mnc = rrc_bits_2_value(ie_ptr, mnc_size); + mnc_size = (liblte_bits_2_value(ie_ptr, 1) + 2)*4; + plmn_id->mnc = liblte_bits_2_value(ie_ptr, mnc_size); if(8 == mnc_size) { plmn_id->mnc |= 0xFF00; @@ -2574,27 +4719,27 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_pre_registration_info_hrpd_ie(LIBLTE_RRC_PRE_R ie_ptr != NULL) { // Optional indicators - rrc_value_2_bits(pre_reg_info_hrpd->pre_reg_zone_id_present, ie_ptr, 1); + liblte_value_2_bits(pre_reg_info_hrpd->pre_reg_zone_id_present, ie_ptr, 1); if(0 != pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } - rrc_value_2_bits(pre_reg_info_hrpd->pre_reg_allowed, ie_ptr, 1); + liblte_value_2_bits(pre_reg_info_hrpd->pre_reg_allowed, ie_ptr, 1); if(true == pre_reg_info_hrpd->pre_reg_zone_id_present) { - rrc_value_2_bits(pre_reg_info_hrpd->pre_reg_zone_id, ie_ptr, 8); + liblte_value_2_bits(pre_reg_info_hrpd->pre_reg_zone_id, ie_ptr, 8); } if(0 != pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size) { - rrc_value_2_bits(pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size - 1, ie_ptr, 1); + liblte_value_2_bits(pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size - 1, ie_ptr, 1); for(i=0; isecondary_pre_reg_zone_id_list_size; i++) { - rrc_value_2_bits(pre_reg_info_hrpd->secondary_pre_reg_zone_id_list[i], ie_ptr, 8); + liblte_value_2_bits(pre_reg_info_hrpd->secondary_pre_reg_zone_id_list[i], ie_ptr, 8); } } @@ -2614,22 +4759,22 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_pre_registration_info_hrpd_ie(uint8 pre_reg_info_hrpd != NULL) { // Optional indicators - pre_reg_info_hrpd->pre_reg_zone_id_present = rrc_bits_2_value(ie_ptr, 1); - secondary_pre_reg_zone_id_opt = rrc_bits_2_value(ie_ptr, 1); + pre_reg_info_hrpd->pre_reg_zone_id_present = liblte_bits_2_value(ie_ptr, 1); + secondary_pre_reg_zone_id_opt = liblte_bits_2_value(ie_ptr, 1); - pre_reg_info_hrpd->pre_reg_allowed = rrc_bits_2_value(ie_ptr, 1); + pre_reg_info_hrpd->pre_reg_allowed = liblte_bits_2_value(ie_ptr, 1); if(true == pre_reg_info_hrpd->pre_reg_zone_id_present) { - pre_reg_info_hrpd->pre_reg_zone_id = rrc_bits_2_value(ie_ptr, 8); + pre_reg_info_hrpd->pre_reg_zone_id = liblte_bits_2_value(ie_ptr, 8); } if(true == secondary_pre_reg_zone_id_opt) { - pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size = rrc_bits_2_value(ie_ptr, 1) + 1; + pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size = liblte_bits_2_value(ie_ptr, 1) + 1; for(i=0; isecondary_pre_reg_zone_id_list_size; i++) { - pre_reg_info_hrpd->secondary_pre_reg_zone_id_list[i] = rrc_bits_2_value(ie_ptr, 8); + pre_reg_info_hrpd->secondary_pre_reg_zone_id_list[i] = liblte_bits_2_value(ie_ptr, 8); } }else{ pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size = 0; @@ -2657,7 +4802,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_q_qual_min_ie(int8 q_qual_min, if(ie_ptr != NULL) { - rrc_value_2_bits(q_qual_min + 34, ie_ptr, 5); + liblte_value_2_bits(q_qual_min + 34, ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -2672,7 +4817,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_q_qual_min_ie(uint8 **ie_ptr, if(ie_ptr != NULL && q_qual_min != NULL) { - *q_qual_min = (int8)rrc_bits_2_value(ie_ptr, 5) - 34; + *q_qual_min = (int8)liblte_bits_2_value(ie_ptr, 5) - 34; err = LIBLTE_SUCCESS; } @@ -2695,7 +4840,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_q_rx_lev_min_ie(int16 q_rx_lev_min, if(ie_ptr != NULL) { - rrc_value_2_bits((q_rx_lev_min / 2) + 70, ie_ptr, 6); + liblte_value_2_bits((q_rx_lev_min / 2) + 70, ie_ptr, 6); err = LIBLTE_SUCCESS; } @@ -2710,7 +4855,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_q_rx_lev_min_ie(uint8 **ie_ptr, if(ie_ptr != NULL && q_rx_lev_min != NULL) { - *q_rx_lev_min = ((int16)rrc_bits_2_value(ie_ptr, 6) - 70) * 2; + *q_rx_lev_min = ((int16)liblte_bits_2_value(ie_ptr, 6) - 70) * 2; err = LIBLTE_SUCCESS; } @@ -2735,7 +4880,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_q_offset_range_ie(LIBLTE_RRC_Q_OFFSET_RANGE_EN if(ie_ptr != NULL) { - rrc_value_2_bits(q_offset_range, ie_ptr, 5); + liblte_value_2_bits(q_offset_range, ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -2750,7 +4895,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_q_offset_range_ie(uint8 if(ie_ptr != NULL && q_offset_range != NULL) { - *q_offset_range = (LIBLTE_RRC_Q_OFFSET_RANGE_ENUM)rrc_bits_2_value(ie_ptr, 5); + *q_offset_range = (LIBLTE_RRC_Q_OFFSET_RANGE_ENUM)liblte_bits_2_value(ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -2774,7 +4919,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_q_offset_range_inter_rat_ie(int8 q_offset_r if(ie_ptr != NULL) { - rrc_value_2_bits(q_offset_range_inter_rat + 15, ie_ptr, 5); + liblte_value_2_bits(q_offset_range_inter_rat + 15, ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -2789,7 +4934,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_q_offset_range_inter_rat_ie(uint8 **ie_ptr, if(ie_ptr != NULL && q_offset_range_inter_rat != NULL) { - *q_offset_range_inter_rat = (int8)(rrc_bits_2_value(ie_ptr, 5)) - 15; + *q_offset_range_inter_rat = (int8)(liblte_bits_2_value(ie_ptr, 5)) - 15; err = LIBLTE_SUCCESS; } @@ -2811,7 +4956,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_reselection_threshold_ie(uint8 resel_thresh, if(ie_ptr != NULL) { - rrc_value_2_bits(resel_thresh / 2, ie_ptr, 5); + liblte_value_2_bits(resel_thresh / 2, ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -2826,7 +4971,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_reselection_threshold_ie(uint8 **ie_ptr, if(ie_ptr != NULL && resel_thresh != NULL) { - *resel_thresh = rrc_bits_2_value(ie_ptr, 5) * 2; + *resel_thresh = liblte_bits_2_value(ie_ptr, 5) * 2; err = LIBLTE_SUCCESS; } @@ -2849,7 +4994,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_reselection_threshold_q_ie(uint8 resel_thres if(ie_ptr != NULL) { - rrc_value_2_bits(resel_thresh_q, ie_ptr, 5); + liblte_value_2_bits(resel_thresh_q, ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -2864,7 +5009,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_reselection_threshold_q_ie(uint8 **ie_ptr, if(ie_ptr != NULL && resel_thresh_q != NULL) { - *resel_thresh_q = rrc_bits_2_value(ie_ptr, 5); + *resel_thresh_q = liblte_bits_2_value(ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -2887,7 +5032,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_s_cell_index_ie(uint8 s_cell_idx, if(ie_ptr != NULL) { - rrc_value_2_bits(s_cell_idx - 1, ie_ptr, 3); + liblte_value_2_bits(s_cell_idx - 1, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -2902,7 +5047,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_s_cell_index_ie(uint8 **ie_ptr, if(ie_ptr != NULL && s_cell_idx != NULL) { - *s_cell_idx = rrc_bits_2_value(ie_ptr, 3) + 1; + *s_cell_idx = liblte_bits_2_value(ie_ptr, 3) + 1; err = LIBLTE_SUCCESS; } @@ -2925,7 +5070,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_serv_cell_index_ie(uint8 serv_cell_idx, if(ie_ptr != NULL) { - rrc_value_2_bits(serv_cell_idx, ie_ptr, 3); + liblte_value_2_bits(serv_cell_idx, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -2940,7 +5085,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_serv_cell_index_ie(uint8 **ie_ptr, if(ie_ptr != NULL && serv_cell_idx != NULL) { - *serv_cell_idx = rrc_bits_2_value(ie_ptr, 3); + *serv_cell_idx = liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -2965,8 +5110,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_speed_state_scale_factors_ie(LIBLTE_RRC_SPEED_ if(speed_state_scale_factors != NULL && ie_ptr != NULL) { - rrc_value_2_bits(speed_state_scale_factors->sf_medium, ie_ptr, 2); - rrc_value_2_bits(speed_state_scale_factors->sf_high, ie_ptr, 2); + liblte_value_2_bits(speed_state_scale_factors->sf_medium, ie_ptr, 2); + liblte_value_2_bits(speed_state_scale_factors->sf_high, ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -2981,8 +5126,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_speed_state_scale_factors_ie(uint8 if(ie_ptr != NULL && speed_state_scale_factors != NULL) { - speed_state_scale_factors->sf_medium = (LIBLTE_RRC_SSSF_MEDIUM_ENUM)rrc_bits_2_value(ie_ptr, 2); - speed_state_scale_factors->sf_high = (LIBLTE_RRC_SSSF_HIGH_ENUM)rrc_bits_2_value(ie_ptr, 2); + speed_state_scale_factors->sf_medium = (LIBLTE_RRC_SSSF_MEDIUM_ENUM)liblte_bits_2_value(ie_ptr, 2); + speed_state_scale_factors->sf_high = (LIBLTE_RRC_SSSF_HIGH_ENUM)liblte_bits_2_value(ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -2997,7 +5142,56 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_speed_state_scale_factors_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.4 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_system_info_list_geran_ie(LIBLTE_RRC_SYSTEM_INFO_LIST_GERAN_STRUCT *list, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + uint32 j; + + if(list != NULL && + ie_ptr != NULL) + { + liblte_value_2_bits(list->system_info_list_geran_size - 1, ie_ptr, 4); + for(i=0; isystem_info_list_geran_size; i++) + { + liblte_value_2_bits(list->system_info_list_geran[i].system_info_size - 1, ie_ptr, 8); + for(j=0; jsystem_info_list_geran[i].system_info_size; j++) + { + liblte_value_2_bits(list->system_info_list_geran[i].system_info[j], ie_ptr, 8); + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_system_info_list_geran_ie(uint8 **ie_ptr, + LIBLTE_RRC_SYSTEM_INFO_LIST_GERAN_STRUCT *list) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + uint32 j; + + if(ie_ptr != NULL && + list != NULL) + { + list->system_info_list_geran_size = liblte_bits_2_value(ie_ptr, 4) + 1; + for(i=0; isystem_info_list_geran_size; i++) + { + list->system_info_list_geran[i].system_info_size = liblte_bits_2_value(ie_ptr, 8) + 1; + for(j=0; jsystem_info_list_geran[i].system_info_size; j++) + { + list->system_info_list_geran[i].system_info[j] = liblte_bits_2_value(ie_ptr, 8); + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* IE Name: System Time Info CDMA2000 @@ -3015,15 +5209,15 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_system_time_info_cdma2000_ie(LIBLTE_RRC_SYSTEM if(sys_time_info_cdma2000 != NULL && ie_ptr != NULL) { - rrc_value_2_bits(sys_time_info_cdma2000->cdma_eutra_sync, ie_ptr, 1); - rrc_value_2_bits(sys_time_info_cdma2000->system_time_async, ie_ptr, 1); + liblte_value_2_bits(sys_time_info_cdma2000->cdma_eutra_sync, ie_ptr, 1); + liblte_value_2_bits(sys_time_info_cdma2000->system_time_async, ie_ptr, 1); if(true == sys_time_info_cdma2000->system_time_async) { - rrc_value_2_bits((uint32)(sys_time_info_cdma2000->system_time >> 17), ie_ptr, 32); - rrc_value_2_bits((uint32)(sys_time_info_cdma2000->system_time & 0x1FFFF), ie_ptr, 17); + liblte_value_2_bits((uint32)(sys_time_info_cdma2000->system_time >> 17), ie_ptr, 32); + liblte_value_2_bits((uint32)(sys_time_info_cdma2000->system_time & 0x1FFFF), ie_ptr, 17); }else{ - rrc_value_2_bits((uint32)(sys_time_info_cdma2000->system_time >> 7), ie_ptr, 32); - rrc_value_2_bits((uint32)(sys_time_info_cdma2000->system_time & 0x7F), ie_ptr, 7); + liblte_value_2_bits((uint32)(sys_time_info_cdma2000->system_time >> 7), ie_ptr, 32); + liblte_value_2_bits((uint32)(sys_time_info_cdma2000->system_time & 0x7F), ie_ptr, 7); } err = LIBLTE_SUCCESS; @@ -3039,15 +5233,15 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_system_time_info_cdma2000_ie(uint8 if(ie_ptr != NULL && sys_time_info_cdma2000 != NULL) { - sys_time_info_cdma2000->cdma_eutra_sync = rrc_bits_2_value(ie_ptr, 1); - sys_time_info_cdma2000->system_time_async = rrc_bits_2_value(ie_ptr, 1); + sys_time_info_cdma2000->cdma_eutra_sync = liblte_bits_2_value(ie_ptr, 1); + sys_time_info_cdma2000->system_time_async = liblte_bits_2_value(ie_ptr, 1); if(true == sys_time_info_cdma2000->system_time_async) { - sys_time_info_cdma2000->system_time = (uint64)rrc_bits_2_value(ie_ptr, 32) << 17; - sys_time_info_cdma2000->system_time |= (uint64)rrc_bits_2_value(ie_ptr, 17); + sys_time_info_cdma2000->system_time = (uint64)liblte_bits_2_value(ie_ptr, 32) << 17; + sys_time_info_cdma2000->system_time |= (uint64)liblte_bits_2_value(ie_ptr, 17); }else{ - sys_time_info_cdma2000->system_time = (uint64)rrc_bits_2_value(ie_ptr, 32) << 7; - sys_time_info_cdma2000->system_time |= (uint64)rrc_bits_2_value(ie_ptr, 7); + sys_time_info_cdma2000->system_time = (uint64)liblte_bits_2_value(ie_ptr, 32) << 7; + sys_time_info_cdma2000->system_time |= (uint64)liblte_bits_2_value(ie_ptr, 7); } err = LIBLTE_SUCCESS; @@ -3071,7 +5265,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_tracking_area_code_ie(uint16 tac, if(ie_ptr != NULL) { - rrc_value_2_bits(tac, ie_ptr, 16); + liblte_value_2_bits(tac, ie_ptr, 16); err = LIBLTE_SUCCESS; } @@ -3086,7 +5280,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_tracking_area_code_ie(uint8 **ie_ptr, if(ie_ptr != NULL && tac != NULL) { - *tac = rrc_bits_2_value(ie_ptr, 16); + *tac = liblte_bits_2_value(ie_ptr, 16); err = LIBLTE_SUCCESS; } @@ -3109,7 +5303,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_t_reselection_ie(uint8 t_resel, if(ie_ptr != NULL) { - rrc_value_2_bits(t_resel, ie_ptr, 3); + liblte_value_2_bits(t_resel, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -3124,7 +5318,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_t_reselection_ie(uint8 **ie_ptr, if(ie_ptr != NULL && t_resel != NULL) { - *t_resel = rrc_bits_2_value(ie_ptr, 3); + *t_resel = liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -3147,7 +5341,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_next_hop_chaining_count_ie(uint8 next_hop_ch if(ie_ptr != NULL) { - rrc_value_2_bits(next_hop_chaining_count, ie_ptr, 3); + liblte_value_2_bits(next_hop_chaining_count, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -3162,7 +5356,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_next_hop_chaining_count_ie(uint8 **ie_ptr, if(ie_ptr != NULL && next_hop_chaining_count != NULL) { - *next_hop_chaining_count = rrc_bits_2_value(ie_ptr, 3); + *next_hop_chaining_count = liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -3187,14 +5381,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_security_algorithm_config_ie(LIBLTE_RRC_SECURI ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(sec_alg_cnfg->cipher_alg, ie_ptr, 3); + liblte_value_2_bits(sec_alg_cnfg->cipher_alg, ie_ptr, 3); // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(sec_alg_cnfg->int_alg, ie_ptr, 3); + liblte_value_2_bits(sec_alg_cnfg->int_alg, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -3210,14 +5404,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_security_algorithm_config_ie(uint8 sec_alg_cnfg != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + liblte_bits_2_value(ie_ptr, 1); - sec_alg_cnfg->cipher_alg = (LIBLTE_RRC_CIPHERING_ALGORITHM_ENUM)rrc_bits_2_value(ie_ptr, 3); + sec_alg_cnfg->cipher_alg = (LIBLTE_RRC_CIPHERING_ALGORITHM_ENUM)liblte_bits_2_value(ie_ptr, 3); // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + liblte_bits_2_value(ie_ptr, 1); - sec_alg_cnfg->int_alg = (LIBLTE_RRC_INTEGRITY_PROT_ALGORITHM_ENUM)rrc_bits_2_value(ie_ptr, 3); + sec_alg_cnfg->int_alg = (LIBLTE_RRC_INTEGRITY_PROT_ALGORITHM_ENUM)liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -3240,7 +5434,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_short_mac_i_ie(uint16 short_mac_i, if(ie_ptr != NULL) { - rrc_value_2_bits(short_mac_i, ie_ptr, 16); + liblte_value_2_bits(short_mac_i, ie_ptr, 16); err = LIBLTE_SUCCESS; } @@ -3255,7 +5449,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_short_mac_i_ie(uint8 **ie_ptr, if(ie_ptr != NULL && short_mac_i != NULL) { - *short_mac_i = rrc_bits_2_value(ie_ptr, 16); + *short_mac_i = liblte_bits_2_value(ie_ptr, 16); err = LIBLTE_SUCCESS; } @@ -3278,7 +5472,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_antenna_info_common_ie(LIBLTE_RRC_ANTENNA_PORT if(ie_ptr != NULL) { - rrc_value_2_bits(antenna_ports_cnt, ie_ptr, 2); + liblte_value_2_bits(antenna_ports_cnt, ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -3293,7 +5487,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_antenna_info_common_ie(uint8 if(ie_ptr != NULL && antenna_ports_cnt != NULL) { - *antenna_ports_cnt = (LIBLTE_RRC_ANTENNA_PORTS_COUNT_ENUM)rrc_bits_2_value(ie_ptr, 2); + *antenna_ports_cnt = (LIBLTE_RRC_ANTENNA_PORTS_COUNT_ENUM)liblte_bits_2_value(ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -3309,44 +5503,44 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_antenna_info_dedicated_ie(LIBLTE_RRC_ANTENNA_I ie_ptr != NULL) { // Optional indicator - rrc_value_2_bits(antenna_info->codebook_subset_restriction_present, ie_ptr, 1); + liblte_value_2_bits(antenna_info->codebook_subset_restriction_present, ie_ptr, 1); // Transmission Mode - rrc_value_2_bits(antenna_info->tx_mode, ie_ptr, 3); + liblte_value_2_bits(antenna_info->tx_mode, ie_ptr, 3); // Codebook Subset Restriction if(antenna_info->codebook_subset_restriction_present) { - rrc_value_2_bits(antenna_info->codebook_subset_restriction_choice, ie_ptr, 3); + liblte_value_2_bits(antenna_info->codebook_subset_restriction_choice, ie_ptr, 3); switch(antenna_info->codebook_subset_restriction_choice) { case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM3: - rrc_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 2); + liblte_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 2); break; case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM3: case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM5: case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM6: - rrc_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 4); + liblte_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 4); break; case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM4: - rrc_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 6); + liblte_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 6); break; case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM4: - rrc_value_2_bits(antenna_info->codebook_subset_restriction >> 32, ie_ptr, 32); - rrc_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 32); + liblte_value_2_bits(antenna_info->codebook_subset_restriction >> 32, ie_ptr, 32); + liblte_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 32); break; case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM5: case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM6: - rrc_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 16); + liblte_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 16); break; } } // UE Transmit Antenna Selection - rrc_value_2_bits(antenna_info->ue_tx_antenna_selection_setup_present, ie_ptr, 1); + liblte_value_2_bits(antenna_info->ue_tx_antenna_selection_setup_present, ie_ptr, 1); if(antenna_info->ue_tx_antenna_selection_setup_present) { - rrc_value_2_bits(antenna_info->ue_tx_antenna_selection_setup, ie_ptr, 1); + liblte_value_2_bits(antenna_info->ue_tx_antenna_selection_setup, ie_ptr, 1); } err = LIBLTE_SUCCESS; @@ -3363,44 +5557,44 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_antenna_info_dedicated_ie(uint8 antenna_info != NULL) { // Optional indicator - antenna_info->codebook_subset_restriction_present = rrc_bits_2_value(ie_ptr, 1); + antenna_info->codebook_subset_restriction_present = liblte_bits_2_value(ie_ptr, 1); // Transmission Mode - antenna_info->tx_mode = (LIBLTE_RRC_TRANSMISSION_MODE_ENUM)rrc_bits_2_value(ie_ptr, 3); + antenna_info->tx_mode = (LIBLTE_RRC_TRANSMISSION_MODE_ENUM)liblte_bits_2_value(ie_ptr, 3); // Codebook Subset Restriction if(antenna_info->codebook_subset_restriction_present) { - antenna_info->codebook_subset_restriction_choice = (LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_CHOICE_ENUM)rrc_bits_2_value(ie_ptr, 3); + antenna_info->codebook_subset_restriction_choice = (LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_CHOICE_ENUM)liblte_bits_2_value(ie_ptr, 3); switch(antenna_info->codebook_subset_restriction_choice) { case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM3: - antenna_info->codebook_subset_restriction = rrc_bits_2_value(ie_ptr, 2); + antenna_info->codebook_subset_restriction = liblte_bits_2_value(ie_ptr, 2); break; case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM3: case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM5: case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM6: - antenna_info->codebook_subset_restriction = rrc_bits_2_value(ie_ptr, 4); + antenna_info->codebook_subset_restriction = liblte_bits_2_value(ie_ptr, 4); break; case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM4: - antenna_info->codebook_subset_restriction = rrc_bits_2_value(ie_ptr, 6); + antenna_info->codebook_subset_restriction = liblte_bits_2_value(ie_ptr, 6); break; case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM4: - antenna_info->codebook_subset_restriction = (uint64)(rrc_bits_2_value(ie_ptr, 32)) << 32; - antenna_info->codebook_subset_restriction |= rrc_bits_2_value(ie_ptr, 32); + antenna_info->codebook_subset_restriction = (uint64)(liblte_bits_2_value(ie_ptr, 32)) << 32; + antenna_info->codebook_subset_restriction |= liblte_bits_2_value(ie_ptr, 32); break; case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM5: case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM6: - antenna_info->codebook_subset_restriction = rrc_bits_2_value(ie_ptr, 16); + antenna_info->codebook_subset_restriction = liblte_bits_2_value(ie_ptr, 16); break; } } // UE Transmit Antenna Selection - antenna_info->ue_tx_antenna_selection_setup_present = rrc_bits_2_value(ie_ptr, 1); + antenna_info->ue_tx_antenna_selection_setup_present = liblte_bits_2_value(ie_ptr, 1); if(antenna_info->ue_tx_antenna_selection_setup_present) { - antenna_info->ue_tx_antenna_selection_setup = (LIBLTE_RRC_UE_TX_ANTENNA_SELECTION_ENUM)rrc_bits_2_value(ie_ptr, 1); + antenna_info->ue_tx_antenna_selection_setup = (LIBLTE_RRC_UE_TX_ANTENNA_SELECTION_ENUM)liblte_bits_2_value(ie_ptr, 1); } err = LIBLTE_SUCCESS; @@ -3425,48 +5619,48 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_cqi_report_config_ie(LIBLTE_RRC_CQI_REPORT_CON ie_ptr != NULL) { // Optional indicators - rrc_value_2_bits(cqi_report_cnfg->report_mode_aperiodic_present, ie_ptr, 1); - rrc_value_2_bits(cqi_report_cnfg->report_periodic_present, ie_ptr, 1); + liblte_value_2_bits(cqi_report_cnfg->report_mode_aperiodic_present, ie_ptr, 1); + liblte_value_2_bits(cqi_report_cnfg->report_periodic_present, ie_ptr, 1); // CQI Report Mode Aperiodic if(cqi_report_cnfg->report_mode_aperiodic_present) { - rrc_value_2_bits(cqi_report_cnfg->report_mode_aperiodic, ie_ptr, 3); + liblte_value_2_bits(cqi_report_cnfg->report_mode_aperiodic, ie_ptr, 3); } // Nom PDSCH RS EPRE Offset - rrc_value_2_bits(cqi_report_cnfg->nom_pdsch_rs_epre_offset + 1, ie_ptr, 3); + liblte_value_2_bits(cqi_report_cnfg->nom_pdsch_rs_epre_offset + 1, ie_ptr, 3); // CQI Report Periodic if(cqi_report_cnfg->report_periodic_present) { - rrc_value_2_bits(cqi_report_cnfg->report_periodic_setup_present, ie_ptr, 1); + liblte_value_2_bits(cqi_report_cnfg->report_periodic_setup_present, ie_ptr, 1); if(cqi_report_cnfg->report_periodic_setup_present) { // Optional indicator - rrc_value_2_bits(cqi_report_cnfg->report_periodic.ri_cnfg_idx_present, ie_ptr, 1); + liblte_value_2_bits(cqi_report_cnfg->report_periodic.ri_cnfg_idx_present, ie_ptr, 1); // CQI PUCCH Resource Index - rrc_value_2_bits(cqi_report_cnfg->report_periodic.pucch_resource_idx, ie_ptr, 11); + liblte_value_2_bits(cqi_report_cnfg->report_periodic.pucch_resource_idx, ie_ptr, 11); // CQI PMI Config Index - rrc_value_2_bits(cqi_report_cnfg->report_periodic.pmi_cnfg_idx, ie_ptr, 10); + liblte_value_2_bits(cqi_report_cnfg->report_periodic.pmi_cnfg_idx, ie_ptr, 10); // CQI Format Indicator Periodic - rrc_value_2_bits(cqi_report_cnfg->report_periodic.format_ind_periodic, ie_ptr, 1); + liblte_value_2_bits(cqi_report_cnfg->report_periodic.format_ind_periodic, ie_ptr, 1); if(LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_SUBBAND_CQI == cqi_report_cnfg->report_periodic.format_ind_periodic) { - rrc_value_2_bits(cqi_report_cnfg->report_periodic.format_ind_periodic_subband_k - 1, ie_ptr, 2); + liblte_value_2_bits(cqi_report_cnfg->report_periodic.format_ind_periodic_subband_k - 1, ie_ptr, 2); } // RI Config Index if(cqi_report_cnfg->report_periodic.ri_cnfg_idx_present) { - rrc_value_2_bits(cqi_report_cnfg->report_periodic.ri_cnfg_idx, ie_ptr, 10); + liblte_value_2_bits(cqi_report_cnfg->report_periodic.ri_cnfg_idx, ie_ptr, 10); } // Simultaneous Ack/Nack and CQI - rrc_value_2_bits(cqi_report_cnfg->report_periodic.simult_ack_nack_and_cqi, ie_ptr, 1); + liblte_value_2_bits(cqi_report_cnfg->report_periodic.simult_ack_nack_and_cqi, ie_ptr, 1); } } @@ -3484,67 +5678,121 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_cqi_report_config_ie(uint8 cqi_report_cnfg != NULL) { // Optional indicators - cqi_report_cnfg->report_mode_aperiodic_present = rrc_bits_2_value(ie_ptr, 1); - cqi_report_cnfg->report_periodic_present = rrc_bits_2_value(ie_ptr, 1); + cqi_report_cnfg->report_mode_aperiodic_present = liblte_bits_2_value(ie_ptr, 1); + cqi_report_cnfg->report_periodic_present = liblte_bits_2_value(ie_ptr, 1); // CQI Report Mode Aperiodic if(cqi_report_cnfg->report_mode_aperiodic_present) { - cqi_report_cnfg->report_mode_aperiodic = (LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_ENUM)rrc_bits_2_value(ie_ptr, 3); + cqi_report_cnfg->report_mode_aperiodic = (LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_ENUM)liblte_bits_2_value(ie_ptr, 3); } // Nom PDSCH RS EPRE Offset - cqi_report_cnfg->nom_pdsch_rs_epre_offset = rrc_bits_2_value(ie_ptr, 3) - 1; + cqi_report_cnfg->nom_pdsch_rs_epre_offset = liblte_bits_2_value(ie_ptr, 3) - 1; // CQI Report Periodic if(cqi_report_cnfg->report_periodic_present) { - cqi_report_cnfg->report_periodic_setup_present = rrc_bits_2_value(ie_ptr, 1); + cqi_report_cnfg->report_periodic_setup_present = liblte_bits_2_value(ie_ptr, 1); if(cqi_report_cnfg->report_periodic_setup_present) { // Optional indicator - cqi_report_cnfg->report_periodic.ri_cnfg_idx_present = rrc_bits_2_value(ie_ptr, 1); + cqi_report_cnfg->report_periodic.ri_cnfg_idx_present = liblte_bits_2_value(ie_ptr, 1); // CQI PUCCH Resource Index - cqi_report_cnfg->report_periodic.pucch_resource_idx = rrc_bits_2_value(ie_ptr, 11); + cqi_report_cnfg->report_periodic.pucch_resource_idx = liblte_bits_2_value(ie_ptr, 11); // CQI PMI Config Index - cqi_report_cnfg->report_periodic.pmi_cnfg_idx = rrc_bits_2_value(ie_ptr, 10); + cqi_report_cnfg->report_periodic.pmi_cnfg_idx = liblte_bits_2_value(ie_ptr, 10); // CQI Format Indicator Periodic - cqi_report_cnfg->report_periodic.format_ind_periodic = (LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_ENUM)rrc_bits_2_value(ie_ptr, 1); + cqi_report_cnfg->report_periodic.format_ind_periodic = (LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_ENUM)liblte_bits_2_value(ie_ptr, 1); if(LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_SUBBAND_CQI == cqi_report_cnfg->report_periodic.format_ind_periodic) { - cqi_report_cnfg->report_periodic.format_ind_periodic_subband_k = rrc_bits_2_value(ie_ptr, 2) + 1; + cqi_report_cnfg->report_periodic.format_ind_periodic_subband_k = liblte_bits_2_value(ie_ptr, 2) + 1; } // RI Config Index if(cqi_report_cnfg->report_periodic.ri_cnfg_idx_present) { - cqi_report_cnfg->report_periodic.ri_cnfg_idx = rrc_bits_2_value(ie_ptr, 10); + cqi_report_cnfg->report_periodic.ri_cnfg_idx = liblte_bits_2_value(ie_ptr, 10); } - // Simultaneous Ack/Nack and CQI - cqi_report_cnfg->report_periodic.simult_ack_nack_and_cqi = rrc_bits_2_value(ie_ptr, 1); - } + // Simultaneous Ack/Nack and CQI + cqi_report_cnfg->report_periodic.simult_ack_nack_and_cqi = liblte_bits_2_value(ie_ptr, 1); + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + IE Name: Cross Carrier Scheduling Config + + Description: Specifies the configuration when the cross carrier + scheduling is used in a cell + + Document Reference: 36.331 v10.0.0 Section 6.3.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_cross_carrier_scheduling_config_ie(LIBLTE_RRC_CROSS_CARRIER_SCHEDULING_CONFIG_STRUCT *cross_carrier_sched_cnfg, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(cross_carrier_sched_cnfg != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Choice + liblte_value_2_bits(cross_carrier_sched_cnfg->sched_cnfg_info_choice, ie_ptr, 1); + if(LIBLTE_RRC_SCHEDULING_CONFIG_INFO_CHOICE_OWN == cross_carrier_sched_cnfg->sched_cnfg_info_choice) + { + liblte_value_2_bits(cross_carrier_sched_cnfg->own_cif_presence, ie_ptr, 1); + }else{ + liblte_rrc_pack_serv_cell_index_ie(cross_carrier_sched_cnfg->other_serv_cell_idx, ie_ptr); + liblte_value_2_bits(cross_carrier_sched_cnfg->other_pdsch_start - 1, ie_ptr, 2); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cross_carrier_scheduling_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_CROSS_CARRIER_SCHEDULING_CONFIG_STRUCT *cross_carrier_sched_cnfg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; + + if(ie_ptr != NULL && + cross_carrier_sched_cnfg != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Choice + cross_carrier_sched_cnfg->sched_cnfg_info_choice = (LIBLTE_RRC_SCHEDULING_CONFIG_INFO_CHOICE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_SCHEDULING_CONFIG_INFO_CHOICE_OWN == cross_carrier_sched_cnfg->sched_cnfg_info_choice) + { + cross_carrier_sched_cnfg->own_cif_presence = liblte_bits_2_value(ie_ptr, 1); + }else{ + liblte_rrc_unpack_serv_cell_index_ie(ie_ptr, &cross_carrier_sched_cnfg->other_serv_cell_idx); + cross_carrier_sched_cnfg->other_pdsch_start = liblte_bits_2_value(ie_ptr, 2) + 1; } + skip_sequence_type_extension(ext_ind, ie_ptr); + err = LIBLTE_SUCCESS; } return(err); } -/********************************************************************* - IE Name: Cross Carrier Scheduling Config - - Description: Specifies the configuration when the cross carrier - scheduling is used in a cell - - Document Reference: 36.331 v10.0.0 Section 6.3.2 -*********************************************************************/ -// FIXME - /********************************************************************* IE Name: CSI RS Config @@ -3553,7 +5801,54 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_cqi_report_config_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.2 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_csi_rs_config_ie(LIBLTE_RRC_CSI_RS_CONFIG_STRUCT *csi_rs_cnfg, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(csi_rs_cnfg != NULL && + ie_ptr != NULL) + { + // Choice + liblte_value_2_bits(csi_rs_cnfg->choice, ie_ptr, 1); + if(LIBLTE_RRC_CSI_RS_CONFIG_CHOICE_SETUP == csi_rs_cnfg->choice) + { + liblte_value_2_bits(csi_rs_cnfg->csi_rs_ports, ie_ptr, 2); + liblte_value_2_bits(csi_rs_cnfg->location_idx, ie_ptr, 5); + liblte_value_2_bits(csi_rs_cnfg->csi_rs_subfr_cnfg, ie_ptr, 8); + liblte_value_2_bits(csi_rs_cnfg->rho_c, ie_ptr, 16); + liblte_value_2_bits(csi_rs_cnfg->csi_rs_w_zero_tx_power, ie_ptr, 16); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_csi_rs_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_CSI_RS_CONFIG_STRUCT *csi_rs_cnfg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + csi_rs_cnfg != NULL) + { + // Choice + csi_rs_cnfg->choice = (LIBLTE_RRC_CSI_RS_CONFIG_CHOICE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_CSI_RS_CONFIG_CHOICE_SETUP == csi_rs_cnfg->choice) + { + csi_rs_cnfg->csi_rs_ports = (LIBLTE_RRC_CSI_RS_PORTS_ENUM)liblte_bits_2_value(ie_ptr, 2); + csi_rs_cnfg->location_idx = liblte_bits_2_value(ie_ptr, 5); + csi_rs_cnfg->csi_rs_subfr_cnfg = liblte_bits_2_value(ie_ptr, 8); + csi_rs_cnfg->rho_c = liblte_bits_2_value(ie_ptr, 16); + csi_rs_cnfg->csi_rs_w_zero_tx_power = liblte_bits_2_value(ie_ptr, 16); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* IE Name: DRB Identity @@ -3569,7 +5864,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_drb_identity_ie(uint8 drb_id, if(ie_ptr != NULL) { - rrc_value_2_bits(drb_id - 1, ie_ptr, 5); + liblte_value_2_bits(drb_id - 1, ie_ptr, 5); err = LIBLTE_SUCCESS; } @@ -3584,7 +5879,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_drb_identity_ie(uint8 **ie_ptr, if(ie_ptr != NULL && drb_id != NULL) { - *drb_id = rrc_bits_2_value(ie_ptr, 5) + 1; + *drb_id = liblte_bits_2_value(ie_ptr, 5) + 1; err = LIBLTE_SUCCESS; } @@ -3608,23 +5903,23 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_logical_channel_config_ie(LIBLTE_RRC_LOGICAL_C ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); // FIXME: Handle extension + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicator - rrc_value_2_bits(log_chan_cnfg->ul_specific_params_present, ie_ptr, 1); + liblte_value_2_bits(log_chan_cnfg->ul_specific_params_present, ie_ptr, 1); if(true == log_chan_cnfg->ul_specific_params_present) { // Optional indicator - rrc_value_2_bits(log_chan_cnfg->ul_specific_params.log_chan_group_present, ie_ptr, 1); + liblte_value_2_bits(log_chan_cnfg->ul_specific_params.log_chan_group_present, ie_ptr, 1); - rrc_value_2_bits(log_chan_cnfg->ul_specific_params.priority - 1, ie_ptr, 4); - rrc_value_2_bits(log_chan_cnfg->ul_specific_params.prioritized_bit_rate, ie_ptr, 4); - rrc_value_2_bits(log_chan_cnfg->ul_specific_params.bucket_size_duration, ie_ptr, 3); + liblte_value_2_bits(log_chan_cnfg->ul_specific_params.priority - 1, ie_ptr, 4); + liblte_value_2_bits(log_chan_cnfg->ul_specific_params.prioritized_bit_rate, ie_ptr, 4); + liblte_value_2_bits(log_chan_cnfg->ul_specific_params.bucket_size_duration, ie_ptr, 3); if(true == log_chan_cnfg->ul_specific_params.log_chan_group_present) { - rrc_value_2_bits(log_chan_cnfg->ul_specific_params.log_chan_group, ie_ptr, 2); + liblte_value_2_bits(log_chan_cnfg->ul_specific_params.log_chan_group, ie_ptr, 2); } } @@ -3637,31 +5932,34 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_logical_channel_config_ie(uint8 LIBLTE_RRC_LOGICAL_CHANNEL_CONFIG_STRUCT *log_chan_cnfg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; if(ie_ptr != NULL && log_chan_cnfg != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); // FIXME: Handle extension + ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicator - log_chan_cnfg->ul_specific_params_present = rrc_bits_2_value(ie_ptr, 1); + log_chan_cnfg->ul_specific_params_present = liblte_bits_2_value(ie_ptr, 1); if(true == log_chan_cnfg->ul_specific_params_present) { // Optional indicator - log_chan_cnfg->ul_specific_params.log_chan_group_present = rrc_bits_2_value(ie_ptr, 1); + log_chan_cnfg->ul_specific_params.log_chan_group_present = liblte_bits_2_value(ie_ptr, 1); - log_chan_cnfg->ul_specific_params.priority = rrc_bits_2_value(ie_ptr, 4) + 1; - log_chan_cnfg->ul_specific_params.prioritized_bit_rate = (LIBLTE_RRC_PRIORITIZED_BIT_RATE_ENUM)rrc_bits_2_value(ie_ptr, 4); - log_chan_cnfg->ul_specific_params.bucket_size_duration = (LIBLTE_RRC_BUCKET_SIZE_DURATION_ENUM)rrc_bits_2_value(ie_ptr, 3); + log_chan_cnfg->ul_specific_params.priority = liblte_bits_2_value(ie_ptr, 4) + 1; + log_chan_cnfg->ul_specific_params.prioritized_bit_rate = (LIBLTE_RRC_PRIORITIZED_BIT_RATE_ENUM)liblte_bits_2_value(ie_ptr, 4); + log_chan_cnfg->ul_specific_params.bucket_size_duration = (LIBLTE_RRC_BUCKET_SIZE_DURATION_ENUM)liblte_bits_2_value(ie_ptr, 3); if(true == log_chan_cnfg->ul_specific_params.log_chan_group_present) { - log_chan_cnfg->ul_specific_params.log_chan_group = rrc_bits_2_value(ie_ptr, 2); + log_chan_cnfg->ul_specific_params.log_chan_group = liblte_bits_2_value(ie_ptr, 2); } } + skip_sequence_type_extension(ext_ind, ie_ptr); + err = LIBLTE_SUCCESS; } @@ -3686,94 +5984,94 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_mac_main_config_ie(LIBLTE_RRC_MAC_MAIN_CONFIG_ ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(ext, ie_ptr, 1); + liblte_value_2_bits(ext, ie_ptr, 1); // Optional indicators - rrc_value_2_bits(mac_main_cnfg->ulsch_cnfg_present, ie_ptr, 1); - rrc_value_2_bits(mac_main_cnfg->drx_cnfg_present, ie_ptr, 1); - rrc_value_2_bits(mac_main_cnfg->phr_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(mac_main_cnfg->phr_cnfg_present, ie_ptr, 1); // ULSCH Config if(mac_main_cnfg->ulsch_cnfg_present) { // Optional indicators - rrc_value_2_bits(mac_main_cnfg->ulsch_cnfg.max_harq_tx_present, ie_ptr, 1); - rrc_value_2_bits(mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer_present, ie_ptr, 1); + liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.max_harq_tx_present, ie_ptr, 1); + liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer_present, ie_ptr, 1); // Max HARQ TX if(mac_main_cnfg->ulsch_cnfg.max_harq_tx_present) { - rrc_value_2_bits(mac_main_cnfg->ulsch_cnfg.max_harq_tx, ie_ptr, 4); + liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.max_harq_tx, ie_ptr, 4); } // Periodic BSR Timer if(mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer_present) { - rrc_value_2_bits(mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer, ie_ptr, 4); + liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer, ie_ptr, 4); } // Re-TX BSR Timer - rrc_value_2_bits(mac_main_cnfg->ulsch_cnfg.retx_bsr_timer, ie_ptr, 3); + liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.retx_bsr_timer, ie_ptr, 3); // TTI Bundling - rrc_value_2_bits(mac_main_cnfg->ulsch_cnfg.tti_bundling, ie_ptr, 1); + liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.tti_bundling, ie_ptr, 1); } // DRX Config if(mac_main_cnfg->drx_cnfg_present) { - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.setup_present, ie_ptr, 1); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.setup_present, ie_ptr, 1); if(mac_main_cnfg->drx_cnfg.setup_present) { // Optional indicators - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.short_drx_present, ie_ptr, 1); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.short_drx_present, ie_ptr, 1); // On Duration Timer - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.on_duration_timer, ie_ptr, 4); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.on_duration_timer, ie_ptr, 4); // DRX Inactivity Timer - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.drx_inactivity_timer, ie_ptr, 5); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.drx_inactivity_timer, ie_ptr, 5); // DRX Retransmission Timer - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.drx_retx_timer, ie_ptr, 3); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.drx_retx_timer, ie_ptr, 3); // Long DRX Cycle Start Offset - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset_choice, ie_ptr, 4); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset_choice, ie_ptr, 4); switch(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset_choice) { case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF10: - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 4); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 4); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF20: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF32: - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 5); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 5); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF40: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF64: - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 6); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 6); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF80: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF128: - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 7); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 7); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF160: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF256: - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 8); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 8); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF320: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF512: - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 9); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 9); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF640: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF1024: - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 10); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 10); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF1280: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF2048: - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 11); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 11); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF2560: - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 12); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 12); break; } @@ -3781,10 +6079,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_mac_main_config_ie(LIBLTE_RRC_MAC_MAIN_CONFIG_ if(mac_main_cnfg->drx_cnfg.short_drx_present) { // Short DRX Cycle - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.short_drx_cycle, ie_ptr, 4); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.short_drx_cycle, ie_ptr, 4); // DRX Short Cycle Timer - rrc_value_2_bits(mac_main_cnfg->drx_cnfg.short_drx_cycle_timer - 1, ie_ptr, 4); + liblte_value_2_bits(mac_main_cnfg->drx_cnfg.short_drx_cycle_timer - 1, ie_ptr, 4); } } } @@ -3795,17 +6093,17 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_mac_main_config_ie(LIBLTE_RRC_MAC_MAIN_CONFIG_ // PHR Config if(mac_main_cnfg->phr_cnfg_present) { - rrc_value_2_bits(mac_main_cnfg->phr_cnfg.setup_present, ie_ptr, 1); + liblte_value_2_bits(mac_main_cnfg->phr_cnfg.setup_present, ie_ptr, 1); if(mac_main_cnfg->phr_cnfg.setup_present) { // Periodic PHR Timer - rrc_value_2_bits(mac_main_cnfg->phr_cnfg.periodic_phr_timer, ie_ptr, 3); + liblte_value_2_bits(mac_main_cnfg->phr_cnfg.periodic_phr_timer, ie_ptr, 3); // Prohibit PHR Timer - rrc_value_2_bits(mac_main_cnfg->phr_cnfg.prohibit_phr_timer, ie_ptr, 3); + liblte_value_2_bits(mac_main_cnfg->phr_cnfg.prohibit_phr_timer, ie_ptr, 3); // DL Pathloss Change - rrc_value_2_bits(mac_main_cnfg->phr_cnfg.dl_pathloss_change, ie_ptr, 2); + liblte_value_2_bits(mac_main_cnfg->phr_cnfg.dl_pathloss_change, ie_ptr, 2); } } @@ -3818,100 +6116,100 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mac_main_config_ie(uint8 LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_main_cnfg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - bool ext; + bool ext_ind; if(ie_ptr != NULL && mac_main_cnfg != NULL) { // Extension indicator - ext = rrc_bits_2_value(ie_ptr, 1); + ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - mac_main_cnfg->ulsch_cnfg_present = rrc_bits_2_value(ie_ptr, 1); - mac_main_cnfg->drx_cnfg_present = rrc_bits_2_value(ie_ptr, 1); - mac_main_cnfg->phr_cnfg_present = rrc_bits_2_value(ie_ptr, 1); + mac_main_cnfg->ulsch_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + mac_main_cnfg->drx_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + mac_main_cnfg->phr_cnfg_present = liblte_bits_2_value(ie_ptr, 1); // ULSCH Config if(mac_main_cnfg->ulsch_cnfg_present) { // Optional indicators - mac_main_cnfg->ulsch_cnfg.max_harq_tx_present = rrc_bits_2_value(ie_ptr, 1); - mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer_present = rrc_bits_2_value(ie_ptr, 1); + mac_main_cnfg->ulsch_cnfg.max_harq_tx_present = liblte_bits_2_value(ie_ptr, 1); + mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer_present = liblte_bits_2_value(ie_ptr, 1); // Max HARQ TX if(mac_main_cnfg->ulsch_cnfg.max_harq_tx_present) { - mac_main_cnfg->ulsch_cnfg.max_harq_tx = (LIBLTE_RRC_MAX_HARQ_TX_ENUM)rrc_bits_2_value(ie_ptr, 4); + mac_main_cnfg->ulsch_cnfg.max_harq_tx = (LIBLTE_RRC_MAX_HARQ_TX_ENUM)liblte_bits_2_value(ie_ptr, 4); } // Periodic BSR Timer if(mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer_present) { - mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer = (LIBLTE_RRC_PERIODIC_BSR_TIMER_ENUM)rrc_bits_2_value(ie_ptr, 4); + mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer = (LIBLTE_RRC_PERIODIC_BSR_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 4); } // Re-TX BSR Timer - mac_main_cnfg->ulsch_cnfg.retx_bsr_timer = (LIBLTE_RRC_RETRANSMISSION_BSR_TIMER_ENUM)rrc_bits_2_value(ie_ptr, 3); + mac_main_cnfg->ulsch_cnfg.retx_bsr_timer = (LIBLTE_RRC_RETRANSMISSION_BSR_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3); // TTI Bundling - mac_main_cnfg->ulsch_cnfg.tti_bundling = rrc_bits_2_value(ie_ptr, 1); + mac_main_cnfg->ulsch_cnfg.tti_bundling = liblte_bits_2_value(ie_ptr, 1); } // DRX Config if(mac_main_cnfg->drx_cnfg_present) { - mac_main_cnfg->drx_cnfg.setup_present = rrc_bits_2_value(ie_ptr, 1); + mac_main_cnfg->drx_cnfg.setup_present = liblte_bits_2_value(ie_ptr, 1); if(mac_main_cnfg->drx_cnfg.setup_present) { // Optional indicators - mac_main_cnfg->drx_cnfg.short_drx_present = rrc_bits_2_value(ie_ptr, 1); + mac_main_cnfg->drx_cnfg.short_drx_present = liblte_bits_2_value(ie_ptr, 1); // On Duration Timer - mac_main_cnfg->drx_cnfg.on_duration_timer = (LIBLTE_RRC_ON_DURATION_TIMER_ENUM)rrc_bits_2_value(ie_ptr, 4); + mac_main_cnfg->drx_cnfg.on_duration_timer = (LIBLTE_RRC_ON_DURATION_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 4); // DRX Inactivity Timer - mac_main_cnfg->drx_cnfg.drx_inactivity_timer = (LIBLTE_RRC_DRX_INACTIVITY_TIMER_ENUM)rrc_bits_2_value(ie_ptr, 5); + mac_main_cnfg->drx_cnfg.drx_inactivity_timer = (LIBLTE_RRC_DRX_INACTIVITY_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 5); // DRX Retransmission Timer - mac_main_cnfg->drx_cnfg.drx_retx_timer = (LIBLTE_RRC_DRX_RETRANSMISSION_TIMER_ENUM)rrc_bits_2_value(ie_ptr, 3); + mac_main_cnfg->drx_cnfg.drx_retx_timer = (LIBLTE_RRC_DRX_RETRANSMISSION_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3); // Long DRX Cycle Short Offset - mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset_choice = (LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_CHOICE_ENUM)rrc_bits_2_value(ie_ptr, 4); + mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset_choice = (LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_CHOICE_ENUM)liblte_bits_2_value(ie_ptr, 4); switch(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset_choice) { case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF10: - mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = rrc_bits_2_value(ie_ptr, 4); + mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 4); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF20: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF32: - mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = rrc_bits_2_value(ie_ptr, 5); + mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 5); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF40: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF64: - mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = rrc_bits_2_value(ie_ptr, 6); + mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 6); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF80: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF128: - mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = rrc_bits_2_value(ie_ptr, 7); + mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 7); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF160: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF256: - mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = rrc_bits_2_value(ie_ptr, 8); + mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 8); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF320: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF512: - mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = rrc_bits_2_value(ie_ptr, 9); + mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 9); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF640: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF1024: - mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = rrc_bits_2_value(ie_ptr, 10); + mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 10); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF1280: case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF2048: - mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = rrc_bits_2_value(ie_ptr, 11); + mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 11); break; case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF2560: - mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = rrc_bits_2_value(ie_ptr, 12); + mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 12); break; } @@ -3919,10 +6217,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mac_main_config_ie(uint8 if(mac_main_cnfg->drx_cnfg.short_drx_present) { // Short DRX Cycle - mac_main_cnfg->drx_cnfg.short_drx_cycle = (LIBLTE_RRC_SHORT_DRX_CYCLE_ENUM)rrc_bits_2_value(ie_ptr, 4); + mac_main_cnfg->drx_cnfg.short_drx_cycle = (LIBLTE_RRC_SHORT_DRX_CYCLE_ENUM)liblte_bits_2_value(ie_ptr, 4); // DRX Short Cycle Timer - mac_main_cnfg->drx_cnfg.short_drx_cycle_timer = rrc_bits_2_value(ie_ptr, 4) + 1; + mac_main_cnfg->drx_cnfg.short_drx_cycle_timer = liblte_bits_2_value(ie_ptr, 4) + 1; } } } @@ -3933,20 +6231,22 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mac_main_config_ie(uint8 // PHR Config if(mac_main_cnfg->phr_cnfg_present) { - mac_main_cnfg->phr_cnfg.setup_present = rrc_bits_2_value(ie_ptr, 1); + mac_main_cnfg->phr_cnfg.setup_present = liblte_bits_2_value(ie_ptr, 1); if(mac_main_cnfg->phr_cnfg.setup_present) { // Periodic PHR Timer - mac_main_cnfg->phr_cnfg.periodic_phr_timer = (LIBLTE_RRC_PERIODIC_PHR_TIMER_ENUM)rrc_bits_2_value(ie_ptr, 3); + mac_main_cnfg->phr_cnfg.periodic_phr_timer = (LIBLTE_RRC_PERIODIC_PHR_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3); // Prohibit PHR Timer - mac_main_cnfg->phr_cnfg.prohibit_phr_timer = (LIBLTE_RRC_PROHIBIT_PHR_TIMER_ENUM)rrc_bits_2_value(ie_ptr, 3); + mac_main_cnfg->phr_cnfg.prohibit_phr_timer = (LIBLTE_RRC_PROHIBIT_PHR_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3); // DL Pathloss Change - mac_main_cnfg->phr_cnfg.dl_pathloss_change = (LIBLTE_RRC_DL_PATHLOSS_CHANGE_ENUM)rrc_bits_2_value(ie_ptr, 2); + mac_main_cnfg->phr_cnfg.dl_pathloss_change = (LIBLTE_RRC_DL_PATHLOSS_CHANGE_ENUM)liblte_bits_2_value(ie_ptr, 2); } } + skip_sequence_type_extension(ext_ind, ie_ptr); + err = LIBLTE_SUCCESS; } @@ -3970,51 +6270,51 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_pdcp_config_ie(LIBLTE_RRC_PDCP_CONFIG_STRUCT ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicators - rrc_value_2_bits(pdcp_cnfg->discard_timer_present, ie_ptr, 1); - rrc_value_2_bits(pdcp_cnfg->rlc_am_status_report_required_present, ie_ptr, 1); - rrc_value_2_bits(pdcp_cnfg->rlc_um_pdcp_sn_size_present, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->discard_timer_present, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->rlc_am_status_report_required_present, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->rlc_um_pdcp_sn_size_present, ie_ptr, 1); // Discard Timer if(pdcp_cnfg->discard_timer_present) { - rrc_value_2_bits(pdcp_cnfg->discard_timer, ie_ptr, 3); + liblte_value_2_bits(pdcp_cnfg->discard_timer, ie_ptr, 3); } // RLC AM if(pdcp_cnfg->rlc_am_status_report_required_present) { - rrc_value_2_bits(pdcp_cnfg->rlc_am_status_report_required, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->rlc_am_status_report_required, ie_ptr, 1); } // RLC UM if(pdcp_cnfg->rlc_um_pdcp_sn_size_present) { - rrc_value_2_bits(pdcp_cnfg->rlc_um_pdcp_sn_size, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->rlc_um_pdcp_sn_size, ie_ptr, 1); } // Header Compression - rrc_value_2_bits(pdcp_cnfg->hdr_compression_rohc, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->hdr_compression_rohc, ie_ptr, 1); if(pdcp_cnfg->hdr_compression_rohc) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Max CID - rrc_value_2_bits(pdcp_cnfg->hdr_compression_max_cid - 1, ie_ptr, 14); + liblte_value_2_bits(pdcp_cnfg->hdr_compression_max_cid - 1, ie_ptr, 14); // Profiles - rrc_value_2_bits(pdcp_cnfg->hdr_compression_profile_0001, ie_ptr, 1); - rrc_value_2_bits(pdcp_cnfg->hdr_compression_profile_0002, ie_ptr, 1); - rrc_value_2_bits(pdcp_cnfg->hdr_compression_profile_0003, ie_ptr, 1); - rrc_value_2_bits(pdcp_cnfg->hdr_compression_profile_0004, ie_ptr, 1); - rrc_value_2_bits(pdcp_cnfg->hdr_compression_profile_0006, ie_ptr, 1); - rrc_value_2_bits(pdcp_cnfg->hdr_compression_profile_0101, ie_ptr, 1); - rrc_value_2_bits(pdcp_cnfg->hdr_compression_profile_0102, ie_ptr, 1); - rrc_value_2_bits(pdcp_cnfg->hdr_compression_profile_0103, ie_ptr, 1); - rrc_value_2_bits(pdcp_cnfg->hdr_compression_profile_0104, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0001, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0002, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0003, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0004, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0006, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0101, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0102, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0103, ie_ptr, 1); + liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0104, ie_ptr, 1); } err = LIBLTE_SUCCESS; @@ -4026,58 +6326,64 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_pdcp_config_ie(uint8 LIBLTE_RRC_PDCP_CONFIG_STRUCT *pdcp_cnfg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool pdcp_cnfg_ext_ind; + bool rohc_ext_ind; if(ie_ptr != NULL && pdcp_cnfg != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + pdcp_cnfg_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - pdcp_cnfg->discard_timer_present = rrc_bits_2_value(ie_ptr, 1); - pdcp_cnfg->rlc_am_status_report_required_present = rrc_bits_2_value(ie_ptr, 1); - pdcp_cnfg->rlc_um_pdcp_sn_size_present = rrc_bits_2_value(ie_ptr, 1); + pdcp_cnfg->discard_timer_present = liblte_bits_2_value(ie_ptr, 1); + pdcp_cnfg->rlc_am_status_report_required_present = liblte_bits_2_value(ie_ptr, 1); + pdcp_cnfg->rlc_um_pdcp_sn_size_present = liblte_bits_2_value(ie_ptr, 1); // Discard Timer if(pdcp_cnfg->discard_timer_present) { - pdcp_cnfg->discard_timer = (LIBLTE_RRC_DISCARD_TIMER_ENUM)rrc_bits_2_value(ie_ptr, 3); + pdcp_cnfg->discard_timer = (LIBLTE_RRC_DISCARD_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3); } // RLC AM if(pdcp_cnfg->rlc_am_status_report_required_present) { - pdcp_cnfg->rlc_am_status_report_required = rrc_bits_2_value(ie_ptr, 1); + pdcp_cnfg->rlc_am_status_report_required = liblte_bits_2_value(ie_ptr, 1); } // RLC UM if(pdcp_cnfg->rlc_um_pdcp_sn_size_present) { - pdcp_cnfg->rlc_um_pdcp_sn_size = (LIBLTE_RRC_PDCP_SN_SIZE_ENUM)rrc_bits_2_value(ie_ptr, 1); + pdcp_cnfg->rlc_um_pdcp_sn_size = (LIBLTE_RRC_PDCP_SN_SIZE_ENUM)liblte_bits_2_value(ie_ptr, 1); } // Header Compression - pdcp_cnfg->hdr_compression_rohc = rrc_bits_2_value(ie_ptr, 1); + pdcp_cnfg->hdr_compression_rohc = liblte_bits_2_value(ie_ptr, 1); if(pdcp_cnfg->hdr_compression_rohc) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + rohc_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Max CID - pdcp_cnfg->hdr_compression_max_cid = rrc_bits_2_value(ie_ptr, 14) + 1; + pdcp_cnfg->hdr_compression_max_cid = liblte_bits_2_value(ie_ptr, 14) + 1; // Profiles - pdcp_cnfg->hdr_compression_profile_0001 = rrc_bits_2_value(ie_ptr, 1); - pdcp_cnfg->hdr_compression_profile_0002 = rrc_bits_2_value(ie_ptr, 1); - pdcp_cnfg->hdr_compression_profile_0003 = rrc_bits_2_value(ie_ptr, 1); - pdcp_cnfg->hdr_compression_profile_0004 = rrc_bits_2_value(ie_ptr, 1); - pdcp_cnfg->hdr_compression_profile_0006 = rrc_bits_2_value(ie_ptr, 1); - pdcp_cnfg->hdr_compression_profile_0101 = rrc_bits_2_value(ie_ptr, 1); - pdcp_cnfg->hdr_compression_profile_0102 = rrc_bits_2_value(ie_ptr, 1); - pdcp_cnfg->hdr_compression_profile_0103 = rrc_bits_2_value(ie_ptr, 1); - pdcp_cnfg->hdr_compression_profile_0104 = rrc_bits_2_value(ie_ptr, 1); + pdcp_cnfg->hdr_compression_profile_0001 = liblte_bits_2_value(ie_ptr, 1); + pdcp_cnfg->hdr_compression_profile_0002 = liblte_bits_2_value(ie_ptr, 1); + pdcp_cnfg->hdr_compression_profile_0003 = liblte_bits_2_value(ie_ptr, 1); + pdcp_cnfg->hdr_compression_profile_0004 = liblte_bits_2_value(ie_ptr, 1); + pdcp_cnfg->hdr_compression_profile_0006 = liblte_bits_2_value(ie_ptr, 1); + pdcp_cnfg->hdr_compression_profile_0101 = liblte_bits_2_value(ie_ptr, 1); + pdcp_cnfg->hdr_compression_profile_0102 = liblte_bits_2_value(ie_ptr, 1); + pdcp_cnfg->hdr_compression_profile_0103 = liblte_bits_2_value(ie_ptr, 1); + pdcp_cnfg->hdr_compression_profile_0104 = liblte_bits_2_value(ie_ptr, 1); + + skip_sequence_type_extension(rohc_ext_ind, ie_ptr); } + skip_sequence_type_extension(pdcp_cnfg_ext_ind, ie_ptr); + err = LIBLTE_SUCCESS; } @@ -4100,8 +6406,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_pdsch_config_common_ie(LIBLTE_RRC_PDSCH_CONFIG if(pdsch_config != NULL && ie_ptr != NULL) { - rrc_value_2_bits(pdsch_config->rs_power + 60, ie_ptr, 7); - rrc_value_2_bits(pdsch_config->p_b, ie_ptr, 2); + liblte_value_2_bits(pdsch_config->rs_power + 60, ie_ptr, 7); + liblte_value_2_bits(pdsch_config->p_b, ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -4116,8 +6422,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_pdsch_config_common_ie(uint8 if(ie_ptr != NULL && pdsch_config != NULL) { - pdsch_config->rs_power = rrc_bits_2_value(ie_ptr, 7) - 60; - pdsch_config->p_b = rrc_bits_2_value(ie_ptr, 2); + pdsch_config->rs_power = liblte_bits_2_value(ie_ptr, 7) - 60; + pdsch_config->p_b = liblte_bits_2_value(ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -4131,7 +6437,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_pdsch_config_dedicated_ie(LIBLTE_RRC_PDSCH_CON if(ie_ptr != NULL) { - rrc_value_2_bits(p_a, ie_ptr, 3); + liblte_value_2_bits(p_a, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -4146,7 +6452,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_pdsch_config_dedicated_ie(uint8 if(p_a != NULL && ie_ptr != NULL) { - *p_a = (LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM)rrc_bits_2_value(ie_ptr, 3); + *p_a = (LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM)liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -4169,8 +6475,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_phich_config_ie(LIBLTE_RRC_PHICH_CONFIG_STRUCT if(phich_config != NULL && ie_ptr != NULL) { - rrc_value_2_bits(phich_config->dur, ie_ptr, 1); - rrc_value_2_bits(phich_config->res, ie_ptr, 2); + liblte_value_2_bits(phich_config->dur, ie_ptr, 1); + liblte_value_2_bits(phich_config->res, ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -4185,8 +6491,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_phich_config_ie(uint8 if(ie_ptr != NULL && phich_config != NULL) { - phich_config->dur = (LIBLTE_RRC_PHICH_DURATION_ENUM)rrc_bits_2_value(ie_ptr, 1); - phich_config->res = (LIBLTE_RRC_PHICH_RESOURCE_ENUM)rrc_bits_2_value(ie_ptr, 2); + phich_config->dur = (LIBLTE_RRC_PHICH_DURATION_ENUM)liblte_bits_2_value(ie_ptr, 1); + phich_config->res = (LIBLTE_RRC_PHICH_RESOURCE_ENUM)liblte_bits_2_value(ie_ptr, 2); err = LIBLTE_SUCCESS; } @@ -4212,19 +6518,19 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_physical_config_dedicated_ie(LIBLTE_RRC_PHYSIC ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(ext, ie_ptr, 1); + liblte_value_2_bits(ext, ie_ptr, 1); // Optional indicators - rrc_value_2_bits(phy_cnfg_ded->pdsch_cnfg_ded_present, ie_ptr, 1); - rrc_value_2_bits(phy_cnfg_ded->pucch_cnfg_ded_present, ie_ptr, 1); - rrc_value_2_bits(phy_cnfg_ded->pusch_cnfg_ded_present, ie_ptr, 1); - rrc_value_2_bits(phy_cnfg_ded->ul_pwr_ctrl_ded_present, ie_ptr, 1); - rrc_value_2_bits(phy_cnfg_ded->tpc_pdcch_cnfg_pucch_present, ie_ptr, 1); - rrc_value_2_bits(phy_cnfg_ded->tpc_pdcch_cnfg_pusch_present, ie_ptr, 1); - rrc_value_2_bits(phy_cnfg_ded->cqi_report_cnfg_present, ie_ptr, 1); - rrc_value_2_bits(phy_cnfg_ded->srs_ul_cnfg_ded_present, ie_ptr, 1); - rrc_value_2_bits(phy_cnfg_ded->antenna_info_present, ie_ptr, 1); - rrc_value_2_bits(phy_cnfg_ded->sched_request_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(phy_cnfg_ded->pdsch_cnfg_ded_present, ie_ptr, 1); + liblte_value_2_bits(phy_cnfg_ded->pucch_cnfg_ded_present, ie_ptr, 1); + liblte_value_2_bits(phy_cnfg_ded->pusch_cnfg_ded_present, ie_ptr, 1); + liblte_value_2_bits(phy_cnfg_ded->ul_pwr_ctrl_ded_present, ie_ptr, 1); + liblte_value_2_bits(phy_cnfg_ded->tpc_pdcch_cnfg_pucch_present, ie_ptr, 1); + liblte_value_2_bits(phy_cnfg_ded->tpc_pdcch_cnfg_pusch_present, ie_ptr, 1); + liblte_value_2_bits(phy_cnfg_ded->cqi_report_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(phy_cnfg_ded->srs_ul_cnfg_ded_present, ie_ptr, 1); + liblte_value_2_bits(phy_cnfg_ded->antenna_info_present, ie_ptr, 1); + liblte_value_2_bits(phy_cnfg_ded->sched_request_cnfg_present, ie_ptr, 1); // PDSCH Config if(phy_cnfg_ded->pdsch_cnfg_ded_present) @@ -4277,7 +6583,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_physical_config_dedicated_ie(LIBLTE_RRC_PHYSIC // Antenna Info if(phy_cnfg_ded->antenna_info_present) { - rrc_value_2_bits(phy_cnfg_ded->antenna_info_default_value, ie_ptr, 1); + liblte_value_2_bits(phy_cnfg_ded->antenna_info_default_value, ie_ptr, 1); if(!phy_cnfg_ded->antenna_info_default_value) { liblte_rrc_pack_antenna_info_dedicated_ie(&phy_cnfg_ded->antenna_info_explicit_value, ie_ptr); @@ -4299,25 +6605,25 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_physical_config_dedicated_ie(uint8 LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg_ded) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - bool ext; + bool ext_ind; if(ie_ptr != NULL && phy_cnfg_ded != NULL) { // Extension indicator - ext = rrc_bits_2_value(ie_ptr, 1); + ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - phy_cnfg_ded->pdsch_cnfg_ded_present = rrc_bits_2_value(ie_ptr, 1); - phy_cnfg_ded->pucch_cnfg_ded_present = rrc_bits_2_value(ie_ptr, 1); - phy_cnfg_ded->pusch_cnfg_ded_present = rrc_bits_2_value(ie_ptr, 1); - phy_cnfg_ded->ul_pwr_ctrl_ded_present = rrc_bits_2_value(ie_ptr, 1); - phy_cnfg_ded->tpc_pdcch_cnfg_pucch_present = rrc_bits_2_value(ie_ptr, 1); - phy_cnfg_ded->tpc_pdcch_cnfg_pusch_present = rrc_bits_2_value(ie_ptr, 1); - phy_cnfg_ded->cqi_report_cnfg_present = rrc_bits_2_value(ie_ptr, 1); - phy_cnfg_ded->srs_ul_cnfg_ded_present = rrc_bits_2_value(ie_ptr, 1); - phy_cnfg_ded->antenna_info_present = rrc_bits_2_value(ie_ptr, 1); - phy_cnfg_ded->sched_request_cnfg_present = rrc_bits_2_value(ie_ptr, 1); + phy_cnfg_ded->pdsch_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1); + phy_cnfg_ded->pucch_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1); + phy_cnfg_ded->pusch_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1); + phy_cnfg_ded->ul_pwr_ctrl_ded_present = liblte_bits_2_value(ie_ptr, 1); + phy_cnfg_ded->tpc_pdcch_cnfg_pucch_present = liblte_bits_2_value(ie_ptr, 1); + phy_cnfg_ded->tpc_pdcch_cnfg_pusch_present = liblte_bits_2_value(ie_ptr, 1); + phy_cnfg_ded->cqi_report_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + phy_cnfg_ded->srs_ul_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1); + phy_cnfg_ded->antenna_info_present = liblte_bits_2_value(ie_ptr, 1); + phy_cnfg_ded->sched_request_cnfg_present = liblte_bits_2_value(ie_ptr, 1); // PDSCH Config if(phy_cnfg_ded->pdsch_cnfg_ded_present) @@ -4370,7 +6676,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_physical_config_dedicated_ie(uint8 // Antenna Info if(phy_cnfg_ded->antenna_info_present) { - phy_cnfg_ded->antenna_info_default_value = rrc_bits_2_value(ie_ptr, 1); + phy_cnfg_ded->antenna_info_default_value = liblte_bits_2_value(ie_ptr, 1); if(!phy_cnfg_ded->antenna_info_default_value) { liblte_rrc_unpack_antenna_info_dedicated_ie(ie_ptr, &phy_cnfg_ded->antenna_info_explicit_value); @@ -4383,6 +6689,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_physical_config_dedicated_ie(uint8 liblte_rrc_unpack_scheduling_request_config_ie(ie_ptr, &phy_cnfg_ded->sched_request_cnfg); } + skip_sequence_type_extension(ext_ind, ie_ptr); + err = LIBLTE_SUCCESS; } @@ -4405,7 +6713,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_p_max_ie(int8 p_max, if(ie_ptr != NULL) { - rrc_value_2_bits(p_max + 30, ie_ptr, 6); + liblte_value_2_bits(p_max + 30, ie_ptr, 6); err = LIBLTE_SUCCESS; } @@ -4420,7 +6728,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_p_max_ie(uint8 **ie_ptr, if(ie_ptr != NULL && p_max != NULL) { - *p_max = (int8)rrc_bits_2_value(ie_ptr, 6) - 30; + *p_max = (int8)liblte_bits_2_value(ie_ptr, 6) - 30; err = LIBLTE_SUCCESS; } @@ -4444,11 +6752,11 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_prach_config_sib_ie(LIBLTE_RRC_PRACH_CONFIG_SI if(prach_cnfg != NULL && ie_ptr != NULL) { - rrc_value_2_bits(prach_cnfg->root_sequence_index, ie_ptr, 10); - rrc_value_2_bits(prach_cnfg->prach_cnfg_info.prach_config_index, ie_ptr, 6); - rrc_value_2_bits(prach_cnfg->prach_cnfg_info.high_speed_flag, ie_ptr, 1); - rrc_value_2_bits(prach_cnfg->prach_cnfg_info.zero_correlation_zone_config, ie_ptr, 4); - rrc_value_2_bits(prach_cnfg->prach_cnfg_info.prach_freq_offset, ie_ptr, 7); + liblte_value_2_bits(prach_cnfg->root_sequence_index, ie_ptr, 10); + liblte_value_2_bits(prach_cnfg->prach_cnfg_info.prach_config_index, ie_ptr, 6); + liblte_value_2_bits(prach_cnfg->prach_cnfg_info.high_speed_flag, ie_ptr, 1); + liblte_value_2_bits(prach_cnfg->prach_cnfg_info.zero_correlation_zone_config, ie_ptr, 4); + liblte_value_2_bits(prach_cnfg->prach_cnfg_info.prach_freq_offset, ie_ptr, 7); err = LIBLTE_SUCCESS; } @@ -4463,11 +6771,11 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_prach_config_sib_ie(uint8 if(ie_ptr != NULL && prach_cnfg != NULL) { - prach_cnfg->root_sequence_index = rrc_bits_2_value(ie_ptr, 10); - prach_cnfg->prach_cnfg_info.prach_config_index = rrc_bits_2_value(ie_ptr, 6); - prach_cnfg->prach_cnfg_info.high_speed_flag = rrc_bits_2_value(ie_ptr, 1); - prach_cnfg->prach_cnfg_info.zero_correlation_zone_config = rrc_bits_2_value(ie_ptr, 4); - prach_cnfg->prach_cnfg_info.prach_freq_offset = rrc_bits_2_value(ie_ptr, 7); + prach_cnfg->root_sequence_index = liblte_bits_2_value(ie_ptr, 10); + prach_cnfg->prach_cnfg_info.prach_config_index = liblte_bits_2_value(ie_ptr, 6); + prach_cnfg->prach_cnfg_info.high_speed_flag = liblte_bits_2_value(ie_ptr, 1); + prach_cnfg->prach_cnfg_info.zero_correlation_zone_config = liblte_bits_2_value(ie_ptr, 4); + prach_cnfg->prach_cnfg_info.prach_freq_offset = liblte_bits_2_value(ie_ptr, 7); err = LIBLTE_SUCCESS; } @@ -4483,16 +6791,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_prach_config_ie(LIBLTE_RRC_PRACH_CONFIG_STRUCT ie_ptr != NULL) { // Optional indicator - rrc_value_2_bits(prach_cnfg->prach_cnfg_info_present, ie_ptr, 1); + liblte_value_2_bits(prach_cnfg->prach_cnfg_info_present, ie_ptr, 1); - rrc_value_2_bits(prach_cnfg->root_sequence_index, ie_ptr, 10); + liblte_value_2_bits(prach_cnfg->root_sequence_index, ie_ptr, 10); if(true == prach_cnfg->prach_cnfg_info_present) { - rrc_value_2_bits(prach_cnfg->prach_cnfg_info.prach_config_index, ie_ptr, 6); - rrc_value_2_bits(prach_cnfg->prach_cnfg_info.high_speed_flag, ie_ptr, 1); - rrc_value_2_bits(prach_cnfg->prach_cnfg_info.zero_correlation_zone_config, ie_ptr, 4); - rrc_value_2_bits(prach_cnfg->prach_cnfg_info.prach_freq_offset, ie_ptr, 7); + liblte_value_2_bits(prach_cnfg->prach_cnfg_info.prach_config_index, ie_ptr, 6); + liblte_value_2_bits(prach_cnfg->prach_cnfg_info.high_speed_flag, ie_ptr, 1); + liblte_value_2_bits(prach_cnfg->prach_cnfg_info.zero_correlation_zone_config, ie_ptr, 4); + liblte_value_2_bits(prach_cnfg->prach_cnfg_info.prach_freq_offset, ie_ptr, 7); } err = LIBLTE_SUCCESS; @@ -4509,16 +6817,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_prach_config_ie(uint8 prach_cnfg != NULL) { // Optional indicator - prach_cnfg->prach_cnfg_info_present = rrc_bits_2_value(ie_ptr, 1); + prach_cnfg->prach_cnfg_info_present = liblte_bits_2_value(ie_ptr, 1); - prach_cnfg->root_sequence_index = rrc_bits_2_value(ie_ptr, 10); + prach_cnfg->root_sequence_index = liblte_bits_2_value(ie_ptr, 10); if(true == prach_cnfg->prach_cnfg_info_present) { - prach_cnfg->prach_cnfg_info.prach_config_index = rrc_bits_2_value(ie_ptr, 6); - prach_cnfg->prach_cnfg_info.high_speed_flag = rrc_bits_2_value(ie_ptr, 1); - prach_cnfg->prach_cnfg_info.zero_correlation_zone_config = rrc_bits_2_value(ie_ptr, 4); - prach_cnfg->prach_cnfg_info.prach_freq_offset = rrc_bits_2_value(ie_ptr, 7); + prach_cnfg->prach_cnfg_info.prach_config_index = liblte_bits_2_value(ie_ptr, 6); + prach_cnfg->prach_cnfg_info.high_speed_flag = liblte_bits_2_value(ie_ptr, 1); + prach_cnfg->prach_cnfg_info.zero_correlation_zone_config = liblte_bits_2_value(ie_ptr, 4); + prach_cnfg->prach_cnfg_info.prach_freq_offset = liblte_bits_2_value(ie_ptr, 7); } err = LIBLTE_SUCCESS; @@ -4533,7 +6841,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_prach_config_scell_r10_ie(uint8 prach_cnfg_i if(ie_ptr != NULL) { - rrc_value_2_bits(prach_cnfg_idx, ie_ptr, 6); + liblte_value_2_bits(prach_cnfg_idx, ie_ptr, 6); err = LIBLTE_SUCCESS; } @@ -4548,7 +6856,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_prach_config_scell_r10_ie(uint8 **ie_ptr, if(ie_ptr != NULL && prach_cnfg_idx != NULL) { - *prach_cnfg_idx = rrc_bits_2_value(ie_ptr, 6); + *prach_cnfg_idx = liblte_bits_2_value(ie_ptr, 6); err = LIBLTE_SUCCESS; } @@ -4571,7 +6879,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_presence_antenna_port_1_ie(bool presence_an if(ie_ptr != NULL) { - rrc_value_2_bits(presence_ant_port_1, ie_ptr, 1); + liblte_value_2_bits(presence_ant_port_1, ie_ptr, 1); err = LIBLTE_SUCCESS; } @@ -4586,7 +6894,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_presence_antenna_port_1_ie(uint8 **ie_ptr, if(ie_ptr != NULL && presence_ant_port_1 != NULL) { - *presence_ant_port_1 = rrc_bits_2_value(ie_ptr, 1); + *presence_ant_port_1 = liblte_bits_2_value(ie_ptr, 1); err = LIBLTE_SUCCESS; } @@ -4610,10 +6918,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_pucch_config_common_ie(LIBLTE_RRC_PUCCH_CONFIG if(pucch_cnfg != NULL && ie_ptr != NULL) { - rrc_value_2_bits(pucch_cnfg->delta_pucch_shift, ie_ptr, 2); - rrc_value_2_bits(pucch_cnfg->n_rb_cqi, ie_ptr, 7); - rrc_value_2_bits(pucch_cnfg->n_cs_an, ie_ptr, 3); - rrc_value_2_bits(pucch_cnfg->n1_pucch_an, ie_ptr, 11); + liblte_value_2_bits(pucch_cnfg->delta_pucch_shift, ie_ptr, 2); + liblte_value_2_bits(pucch_cnfg->n_rb_cqi, ie_ptr, 7); + liblte_value_2_bits(pucch_cnfg->n_cs_an, ie_ptr, 3); + liblte_value_2_bits(pucch_cnfg->n1_pucch_an, ie_ptr, 11); err = LIBLTE_SUCCESS; } @@ -4628,10 +6936,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_pucch_config_common_ie(uint8 if(ie_ptr != NULL && pucch_cnfg != NULL) { - pucch_cnfg->delta_pucch_shift = (LIBLTE_RRC_DELTA_PUCCH_SHIFT_ENUM)rrc_bits_2_value(ie_ptr, 2); - pucch_cnfg->n_rb_cqi = rrc_bits_2_value(ie_ptr, 7); - pucch_cnfg->n_cs_an = rrc_bits_2_value(ie_ptr, 3); - pucch_cnfg->n1_pucch_an = rrc_bits_2_value(ie_ptr, 11); + pucch_cnfg->delta_pucch_shift = (LIBLTE_RRC_DELTA_PUCCH_SHIFT_ENUM)liblte_bits_2_value(ie_ptr, 2); + pucch_cnfg->n_rb_cqi = liblte_bits_2_value(ie_ptr, 7); + pucch_cnfg->n_cs_an = liblte_bits_2_value(ie_ptr, 3); + pucch_cnfg->n1_pucch_an = liblte_bits_2_value(ie_ptr, 11); err = LIBLTE_SUCCESS; } @@ -4647,23 +6955,23 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_pucch_config_dedicated_ie(LIBLTE_RRC_PUCCH_CON ie_ptr != NULL) { // Optional indicator - rrc_value_2_bits(pucch_cnfg->tdd_ack_nack_feedback_mode_present, ie_ptr, 1); + liblte_value_2_bits(pucch_cnfg->tdd_ack_nack_feedback_mode_present, ie_ptr, 1); // Ack/Nack Repetition - rrc_value_2_bits(pucch_cnfg->ack_nack_repetition_setup_present, ie_ptr, 1); + liblte_value_2_bits(pucch_cnfg->ack_nack_repetition_setup_present, ie_ptr, 1); if(pucch_cnfg->ack_nack_repetition_setup_present) { // Repetition Factor - rrc_value_2_bits(pucch_cnfg->ack_nack_repetition_factor, ie_ptr, 2); + liblte_value_2_bits(pucch_cnfg->ack_nack_repetition_factor, ie_ptr, 2); // N1 PUCCH AN Repetition - rrc_value_2_bits(pucch_cnfg->ack_nack_repetition_n1_pucch_an, ie_ptr, 11); + liblte_value_2_bits(pucch_cnfg->ack_nack_repetition_n1_pucch_an, ie_ptr, 11); } // TDD Ack/Nack Feedback Mode if(pucch_cnfg->tdd_ack_nack_feedback_mode_present) { - rrc_value_2_bits(pucch_cnfg->tdd_ack_nack_feedback_mode, ie_ptr, 1); + liblte_value_2_bits(pucch_cnfg->tdd_ack_nack_feedback_mode, ie_ptr, 1); } err = LIBLTE_SUCCESS; @@ -4680,23 +6988,23 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_pucch_config_dedicated_ie(uint8 pucch_cnfg != NULL) { // Optional indicator - pucch_cnfg->tdd_ack_nack_feedback_mode_present = rrc_bits_2_value(ie_ptr, 1); + pucch_cnfg->tdd_ack_nack_feedback_mode_present = liblte_bits_2_value(ie_ptr, 1); // Ack/Nack Repetition - pucch_cnfg->ack_nack_repetition_setup_present = rrc_bits_2_value(ie_ptr, 1); + pucch_cnfg->ack_nack_repetition_setup_present = liblte_bits_2_value(ie_ptr, 1); if(pucch_cnfg->ack_nack_repetition_setup_present) { // Repetition Factor - pucch_cnfg->ack_nack_repetition_factor = (LIBLTE_RRC_ACK_NACK_REPETITION_FACTOR_ENUM)rrc_bits_2_value(ie_ptr, 2); + pucch_cnfg->ack_nack_repetition_factor = (LIBLTE_RRC_ACK_NACK_REPETITION_FACTOR_ENUM)liblte_bits_2_value(ie_ptr, 2); // N1 PUCCH AN Repetition - pucch_cnfg->ack_nack_repetition_n1_pucch_an = rrc_bits_2_value(ie_ptr, 11); + pucch_cnfg->ack_nack_repetition_n1_pucch_an = liblte_bits_2_value(ie_ptr, 11); } // TDD Ack/Nack Feedback Mode if(pucch_cnfg->tdd_ack_nack_feedback_mode_present) { - pucch_cnfg->tdd_ack_nack_feedback_mode = (LIBLTE_RRC_TDD_ACK_NACK_FEEDBACK_MODE_ENUM)rrc_bits_2_value(ie_ptr, 1); + pucch_cnfg->tdd_ack_nack_feedback_mode = (LIBLTE_RRC_TDD_ACK_NACK_FEEDBACK_MODE_ENUM)liblte_bits_2_value(ie_ptr, 1); } err = LIBLTE_SUCCESS; @@ -4723,16 +7031,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_pusch_config_common_ie(LIBLTE_RRC_PUSCH_CONFIG ie_ptr != NULL) { // PUSCH Config Basic - rrc_value_2_bits(pusch_cnfg->n_sb - 1, ie_ptr, 2); - rrc_value_2_bits(pusch_cnfg->hopping_mode, ie_ptr, 1); - rrc_value_2_bits(pusch_cnfg->pusch_hopping_offset, ie_ptr, 7); - rrc_value_2_bits(pusch_cnfg->enable_64_qam, ie_ptr, 1); + liblte_value_2_bits(pusch_cnfg->n_sb - 1, ie_ptr, 2); + liblte_value_2_bits(pusch_cnfg->hopping_mode, ie_ptr, 1); + liblte_value_2_bits(pusch_cnfg->pusch_hopping_offset, ie_ptr, 7); + liblte_value_2_bits(pusch_cnfg->enable_64_qam, ie_ptr, 1); // UL Reference Signals PUSCH - rrc_value_2_bits(pusch_cnfg->ul_rs.group_hopping_enabled, ie_ptr, 1); - rrc_value_2_bits(pusch_cnfg->ul_rs.group_assignment_pusch, ie_ptr, 5); - rrc_value_2_bits(pusch_cnfg->ul_rs.sequence_hopping_enabled, ie_ptr, 1); - rrc_value_2_bits(pusch_cnfg->ul_rs.cyclic_shift, ie_ptr, 3); + liblte_value_2_bits(pusch_cnfg->ul_rs.group_hopping_enabled, ie_ptr, 1); + liblte_value_2_bits(pusch_cnfg->ul_rs.group_assignment_pusch, ie_ptr, 5); + liblte_value_2_bits(pusch_cnfg->ul_rs.sequence_hopping_enabled, ie_ptr, 1); + liblte_value_2_bits(pusch_cnfg->ul_rs.cyclic_shift, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -4748,16 +7056,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_pusch_config_common_ie(uint8 pusch_cnfg != NULL) { // PUSCH Config Basic - pusch_cnfg->n_sb = rrc_bits_2_value(ie_ptr, 2) + 1; - pusch_cnfg->hopping_mode = (LIBLTE_RRC_HOPPING_MODE_ENUM)rrc_bits_2_value(ie_ptr, 1); - pusch_cnfg->pusch_hopping_offset = rrc_bits_2_value(ie_ptr, 7); - pusch_cnfg->enable_64_qam = rrc_bits_2_value(ie_ptr, 1); + pusch_cnfg->n_sb = liblte_bits_2_value(ie_ptr, 2) + 1; + pusch_cnfg->hopping_mode = (LIBLTE_RRC_HOPPING_MODE_ENUM)liblte_bits_2_value(ie_ptr, 1); + pusch_cnfg->pusch_hopping_offset = liblte_bits_2_value(ie_ptr, 7); + pusch_cnfg->enable_64_qam = liblte_bits_2_value(ie_ptr, 1); // UL Reference Signals PUSCH - pusch_cnfg->ul_rs.group_hopping_enabled = rrc_bits_2_value(ie_ptr, 1); - pusch_cnfg->ul_rs.group_assignment_pusch = rrc_bits_2_value(ie_ptr, 5); - pusch_cnfg->ul_rs.sequence_hopping_enabled = rrc_bits_2_value(ie_ptr, 1); - pusch_cnfg->ul_rs.cyclic_shift = rrc_bits_2_value(ie_ptr, 3); + pusch_cnfg->ul_rs.group_hopping_enabled = liblte_bits_2_value(ie_ptr, 1); + pusch_cnfg->ul_rs.group_assignment_pusch = liblte_bits_2_value(ie_ptr, 5); + pusch_cnfg->ul_rs.sequence_hopping_enabled = liblte_bits_2_value(ie_ptr, 1); + pusch_cnfg->ul_rs.cyclic_shift = liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -4773,13 +7081,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_pusch_config_dedicated_ie(LIBLTE_RRC_PUSCH_CON ie_ptr != NULL) { // Beta Offset ACK Index - rrc_value_2_bits(pusch_cnfg->beta_offset_ack_idx, ie_ptr, 4); + liblte_value_2_bits(pusch_cnfg->beta_offset_ack_idx, ie_ptr, 4); // Beta Offset RI Index - rrc_value_2_bits(pusch_cnfg->beta_offset_ri_idx, ie_ptr, 4); + liblte_value_2_bits(pusch_cnfg->beta_offset_ri_idx, ie_ptr, 4); // Beta Offset CQI Index - rrc_value_2_bits(pusch_cnfg->beta_offset_cqi_idx, ie_ptr, 4); + liblte_value_2_bits(pusch_cnfg->beta_offset_cqi_idx, ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -4795,13 +7103,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_pusch_config_dedicated_ie(uint8 pusch_cnfg != NULL) { // Beta Offset ACK Index - pusch_cnfg->beta_offset_ack_idx = rrc_bits_2_value(ie_ptr, 4); + pusch_cnfg->beta_offset_ack_idx = liblte_bits_2_value(ie_ptr, 4); // Beta Offset RI Index - pusch_cnfg->beta_offset_ri_idx = rrc_bits_2_value(ie_ptr, 4); + pusch_cnfg->beta_offset_ri_idx = liblte_bits_2_value(ie_ptr, 4); // Beta Offset CQI Index - pusch_cnfg->beta_offset_cqi_idx = rrc_bits_2_value(ie_ptr, 4); + pusch_cnfg->beta_offset_cqi_idx = liblte_bits_2_value(ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -4825,31 +7133,31 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rach_config_common_ie(LIBLTE_RRC_RACH_CONFIG_C ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Preamble Info - rrc_value_2_bits(rach_cnfg->preambles_group_a_cnfg.present, ie_ptr, 1); - rrc_value_2_bits(rach_cnfg->num_ra_preambles, ie_ptr, 4); + liblte_value_2_bits(rach_cnfg->preambles_group_a_cnfg.present, ie_ptr, 1); + liblte_value_2_bits(rach_cnfg->num_ra_preambles, ie_ptr, 4); if(true == rach_cnfg->preambles_group_a_cnfg.present) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(rach_cnfg->preambles_group_a_cnfg.size_of_ra, ie_ptr, 4); - rrc_value_2_bits(rach_cnfg->preambles_group_a_cnfg.msg_size, ie_ptr, 2); - rrc_value_2_bits(rach_cnfg->preambles_group_a_cnfg.msg_pwr_offset_group_b, ie_ptr, 3); + liblte_value_2_bits(rach_cnfg->preambles_group_a_cnfg.size_of_ra, ie_ptr, 4); + liblte_value_2_bits(rach_cnfg->preambles_group_a_cnfg.msg_size, ie_ptr, 2); + liblte_value_2_bits(rach_cnfg->preambles_group_a_cnfg.msg_pwr_offset_group_b, ie_ptr, 3); } // Power Ramping Parameters - rrc_value_2_bits(rach_cnfg->pwr_ramping_step, ie_ptr, 2); - rrc_value_2_bits(rach_cnfg->preamble_init_rx_target_pwr, ie_ptr, 4); + liblte_value_2_bits(rach_cnfg->pwr_ramping_step, ie_ptr, 2); + liblte_value_2_bits(rach_cnfg->preamble_init_rx_target_pwr, ie_ptr, 4); // RA Supervision Info - rrc_value_2_bits(rach_cnfg->preamble_trans_max, ie_ptr, 4); - rrc_value_2_bits(rach_cnfg->ra_resp_win_size, ie_ptr, 3); - rrc_value_2_bits(rach_cnfg->mac_con_res_timer, ie_ptr, 3); + liblte_value_2_bits(rach_cnfg->preamble_trans_max, ie_ptr, 4); + liblte_value_2_bits(rach_cnfg->ra_resp_win_size, ie_ptr, 3); + liblte_value_2_bits(rach_cnfg->mac_con_res_timer, ie_ptr, 3); - rrc_value_2_bits(rach_cnfg->max_harq_msg3_tx - 1, ie_ptr, 3); + liblte_value_2_bits(rach_cnfg->max_harq_msg3_tx - 1, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -4860,38 +7168,44 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rach_config_common_ie(uint8 LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT *rach_cnfg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool rach_cnfg_cmn_ext_ind; + bool preamble_info_ext_ind; if(ie_ptr != NULL && rach_cnfg != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + rach_cnfg_cmn_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Preamble Info - rach_cnfg->preambles_group_a_cnfg.present = rrc_bits_2_value(ie_ptr, 1); - rach_cnfg->num_ra_preambles = (LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_ENUM)rrc_bits_2_value(ie_ptr, 4); + rach_cnfg->preambles_group_a_cnfg.present = liblte_bits_2_value(ie_ptr, 1); + rach_cnfg->num_ra_preambles = (LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_ENUM)liblte_bits_2_value(ie_ptr, 4); if(true == rach_cnfg->preambles_group_a_cnfg.present) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + preamble_info_ext_ind = liblte_bits_2_value(ie_ptr, 1); + + rach_cnfg->preambles_group_a_cnfg.size_of_ra = (LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_ENUM)liblte_bits_2_value(ie_ptr, 4); + rach_cnfg->preambles_group_a_cnfg.msg_size = (LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_ENUM)liblte_bits_2_value(ie_ptr, 2); + rach_cnfg->preambles_group_a_cnfg.msg_pwr_offset_group_b = (LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_ENUM)liblte_bits_2_value(ie_ptr, 3); - rach_cnfg->preambles_group_a_cnfg.size_of_ra = (LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_ENUM)rrc_bits_2_value(ie_ptr, 4); - rach_cnfg->preambles_group_a_cnfg.msg_size = (LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_ENUM)rrc_bits_2_value(ie_ptr, 2); - rach_cnfg->preambles_group_a_cnfg.msg_pwr_offset_group_b = (LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_ENUM)rrc_bits_2_value(ie_ptr, 3); + skip_sequence_type_extension(preamble_info_ext_ind, ie_ptr); }else{ rach_cnfg->preambles_group_a_cnfg.size_of_ra = (LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_ENUM)rach_cnfg->num_ra_preambles; } // Power Ramping Parameters - rach_cnfg->pwr_ramping_step = (LIBLTE_RRC_POWER_RAMPING_STEP_ENUM)rrc_bits_2_value(ie_ptr, 2); - rach_cnfg->preamble_init_rx_target_pwr = (LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_ENUM)rrc_bits_2_value(ie_ptr, 4); + rach_cnfg->pwr_ramping_step = (LIBLTE_RRC_POWER_RAMPING_STEP_ENUM)liblte_bits_2_value(ie_ptr, 2); + rach_cnfg->preamble_init_rx_target_pwr = (LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_ENUM)liblte_bits_2_value(ie_ptr, 4); // RA Supervision Info - rach_cnfg->preamble_trans_max = (LIBLTE_RRC_PREAMBLE_TRANS_MAX_ENUM)rrc_bits_2_value(ie_ptr, 4); - rach_cnfg->ra_resp_win_size = (LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_ENUM)rrc_bits_2_value(ie_ptr, 3); - rach_cnfg->mac_con_res_timer = (LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_ENUM)rrc_bits_2_value(ie_ptr, 3); + rach_cnfg->preamble_trans_max = (LIBLTE_RRC_PREAMBLE_TRANS_MAX_ENUM)liblte_bits_2_value(ie_ptr, 4); + rach_cnfg->ra_resp_win_size = (LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_ENUM)liblte_bits_2_value(ie_ptr, 3); + rach_cnfg->mac_con_res_timer = (LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3); - rach_cnfg->max_harq_msg3_tx = rrc_bits_2_value(ie_ptr, 3) + 1; + rach_cnfg->max_harq_msg3_tx = liblte_bits_2_value(ie_ptr, 3) + 1; + + skip_sequence_type_extension(rach_cnfg_cmn_ext_ind, ie_ptr); err = LIBLTE_SUCCESS; } @@ -4914,8 +7228,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rach_config_dedicated_ie(LIBLTE_RRC_RACH_CONFI if(rach_cnfg != NULL && ie_ptr != NULL) { - rrc_value_2_bits(rach_cnfg->preamble_index, ie_ptr, 6); - rrc_value_2_bits(rach_cnfg->prach_mask_index, ie_ptr, 4); + liblte_value_2_bits(rach_cnfg->preamble_index, ie_ptr, 6); + liblte_value_2_bits(rach_cnfg->prach_mask_index, ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -4930,8 +7244,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rach_config_dedicated_ie(uint8 if(ie_ptr != NULL && rach_cnfg != NULL) { - rach_cnfg->preamble_index = rrc_bits_2_value(ie_ptr, 6); - rach_cnfg->prach_mask_index = rrc_bits_2_value(ie_ptr, 4); + rach_cnfg->preamble_index = liblte_bits_2_value(ie_ptr, 6); + rach_cnfg->prach_mask_index = liblte_bits_2_value(ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -4958,16 +7272,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_common_sib_ie(LIBLTE_RRC_RR_CONFIG_C ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); liblte_rrc_pack_rach_config_common_ie(&rr_cnfg->rach_cnfg, ie_ptr); // BCCH Config - rrc_value_2_bits(rr_cnfg->bcch_cnfg.modification_period_coeff, ie_ptr, 2); + liblte_value_2_bits(rr_cnfg->bcch_cnfg.modification_period_coeff, ie_ptr, 2); // PCCH Config - rrc_value_2_bits(rr_cnfg->pcch_cnfg.default_paging_cycle, ie_ptr, 2); - rrc_value_2_bits(rr_cnfg->pcch_cnfg.nB, ie_ptr, 3); + liblte_value_2_bits(rr_cnfg->pcch_cnfg.default_paging_cycle, ie_ptr, 2); + liblte_value_2_bits(rr_cnfg->pcch_cnfg.nB, ie_ptr, 3); liblte_rrc_pack_prach_config_sib_ie(&rr_cnfg->prach_cnfg, ie_ptr); liblte_rrc_pack_pdsch_config_common_ie(&rr_cnfg->pdsch_cnfg, ie_ptr); @@ -4977,7 +7291,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_common_sib_ie(LIBLTE_RRC_RR_CONFIG_C liblte_rrc_pack_ul_power_control_common_ie(&rr_cnfg->ul_pwr_ctrl, ie_ptr); // UL CP Length - rrc_value_2_bits(rr_cnfg->ul_cp_length, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->ul_cp_length, ie_ptr, 1); err = LIBLTE_SUCCESS; } @@ -4988,21 +7302,22 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_common_sib_ie(uint8 LIBLTE_RRC_RR_CONFIG_COMMON_SIB_STRUCT *rr_cnfg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; if(ie_ptr != NULL && rr_cnfg != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + ext_ind = liblte_bits_2_value(ie_ptr, 1); liblte_rrc_unpack_rach_config_common_ie(ie_ptr, &rr_cnfg->rach_cnfg); // BCCH Config - rr_cnfg->bcch_cnfg.modification_period_coeff = (LIBLTE_RRC_MODIFICATION_PERIOD_COEFF_ENUM)rrc_bits_2_value(ie_ptr, 2); + rr_cnfg->bcch_cnfg.modification_period_coeff = (LIBLTE_RRC_MODIFICATION_PERIOD_COEFF_ENUM)liblte_bits_2_value(ie_ptr, 2); // PCCH Config - rr_cnfg->pcch_cnfg.default_paging_cycle = (LIBLTE_RRC_DEFAULT_PAGING_CYCLE_ENUM)rrc_bits_2_value(ie_ptr, 2); - rr_cnfg->pcch_cnfg.nB = (LIBLTE_RRC_NB_ENUM)rrc_bits_2_value(ie_ptr, 3); + rr_cnfg->pcch_cnfg.default_paging_cycle = (LIBLTE_RRC_DEFAULT_PAGING_CYCLE_ENUM)liblte_bits_2_value(ie_ptr, 2); + rr_cnfg->pcch_cnfg.nB = (LIBLTE_RRC_NB_ENUM)liblte_bits_2_value(ie_ptr, 3); liblte_rrc_unpack_prach_config_sib_ie(ie_ptr, &rr_cnfg->prach_cnfg); liblte_rrc_unpack_pdsch_config_common_ie(ie_ptr, &rr_cnfg->pdsch_cnfg); @@ -5012,14 +7327,186 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_common_sib_ie(uint8 liblte_rrc_unpack_ul_power_control_common_ie(ie_ptr, &rr_cnfg->ul_pwr_ctrl); // UL CP Length - rr_cnfg->ul_cp_length = (LIBLTE_RRC_UL_CP_LENGTH_ENUM)rrc_bits_2_value(ie_ptr, 1); + rr_cnfg->ul_cp_length = (LIBLTE_RRC_UL_CP_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1); + + skip_sequence_type_extension(ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_common_ie(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *rr_cnfg, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(rr_cnfg != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Optional indicators + liblte_value_2_bits(rr_cnfg->rach_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->pdsch_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->phich_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->pucch_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->srs_ul_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->ul_pwr_ctrl_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->ant_info_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->p_max_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->tdd_cnfg_present, ie_ptr, 1); + + // RACH Config Common + if(rr_cnfg->rach_cnfg_present) + { + liblte_rrc_pack_rach_config_common_ie(&rr_cnfg->rach_cnfg, ie_ptr); + } + + // PRACH Config + liblte_rrc_pack_prach_config_ie(&rr_cnfg->prach_cnfg, ie_ptr); + + // PDSCH Config Common + if(rr_cnfg->pdsch_cnfg_present) + { + liblte_rrc_pack_pdsch_config_common_ie(&rr_cnfg->pdsch_cnfg, ie_ptr); + } + + // PUSCH Config Common + liblte_rrc_pack_pusch_config_common_ie(&rr_cnfg->pusch_cnfg, ie_ptr); + + // PHICH Config + if(rr_cnfg->phich_cnfg_present) + { + liblte_rrc_pack_phich_config_ie(&rr_cnfg->phich_cnfg, ie_ptr); + } + + // PUCCH Config Common + if(rr_cnfg->pucch_cnfg_present) + { + liblte_rrc_pack_pucch_config_common_ie(&rr_cnfg->pucch_cnfg, ie_ptr); + } + + // Sounding RS UL Config Common + if(rr_cnfg->srs_ul_cnfg_present) + { + liblte_rrc_pack_srs_ul_config_common_ie(&rr_cnfg->srs_ul_cnfg, ie_ptr); + } + + // Antenna Info Common + if(rr_cnfg->ant_info_present) + { + liblte_rrc_pack_antenna_info_common_ie(rr_cnfg->ant_info, ie_ptr); + } + + // P Max + if(rr_cnfg->p_max_present) + { + liblte_rrc_pack_p_max_ie(rr_cnfg->p_max, ie_ptr); + } + + // TDD Config + if(rr_cnfg->tdd_cnfg_present) + { + liblte_rrc_pack_tdd_config_ie(&rr_cnfg->tdd_cnfg, ie_ptr); + } + + // UL CP Length + liblte_value_2_bits(rr_cnfg->ul_cp_length, ie_ptr, 1); + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_common_ie(uint8 **ie_ptr, + LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *rr_cnfg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; + + if(ie_ptr != NULL && + rr_cnfg != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Optional indicators + rr_cnfg->rach_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->pdsch_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->phich_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->pucch_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->srs_ul_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->ul_pwr_ctrl_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->ant_info_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->p_max_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->tdd_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + + // RACH Config Common + if(rr_cnfg->rach_cnfg_present) + { + liblte_rrc_unpack_rach_config_common_ie(ie_ptr, &rr_cnfg->rach_cnfg); + } + + // PRACH Config + liblte_rrc_unpack_prach_config_ie(ie_ptr, &rr_cnfg->prach_cnfg); + + // PDSCH Config Common + if(rr_cnfg->pdsch_cnfg_present) + { + liblte_rrc_unpack_pdsch_config_common_ie(ie_ptr, &rr_cnfg->pdsch_cnfg); + } + + // PUSCH Config Common + liblte_rrc_unpack_pusch_config_common_ie(ie_ptr, &rr_cnfg->pusch_cnfg); + + // PHICH Config + if(rr_cnfg->phich_cnfg_present) + { + liblte_rrc_unpack_phich_config_ie(ie_ptr, &rr_cnfg->phich_cnfg); + } + + // PUCCH Config Common + if(rr_cnfg->pucch_cnfg_present) + { + liblte_rrc_unpack_pucch_config_common_ie(ie_ptr, &rr_cnfg->pucch_cnfg); + } + + // Sounding RS UL Config Common + if(rr_cnfg->srs_ul_cnfg_present) + { + liblte_rrc_unpack_srs_ul_config_common_ie(ie_ptr, &rr_cnfg->srs_ul_cnfg); + } + + // Antenna Info Common + if(rr_cnfg->ant_info_present) + { + liblte_rrc_unpack_antenna_info_common_ie(ie_ptr, &rr_cnfg->ant_info); + } + + // P Max + if(rr_cnfg->p_max_present) + { + liblte_rrc_unpack_p_max_ie(ie_ptr, &rr_cnfg->p_max); + } + + // TDD Config + if(rr_cnfg->tdd_cnfg_present) + { + liblte_rrc_unpack_tdd_config_ie(ie_ptr, &rr_cnfg->tdd_cnfg); + } + + // UL CP Length + rr_cnfg->ul_cp_length = (LIBLTE_RRC_UL_CP_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1); + + skip_sequence_type_extension(ext_ind, ie_ptr); err = LIBLTE_SUCCESS; } return(err); } -// FIXME /********************************************************************* IE Name: Radio Resource Config Dedicated @@ -5040,53 +7527,53 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_dedicated_ie(LIBLTE_RRC_RR_CONFIG_DE ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(rr_cnfg->rlf_timers_and_constants_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->rlf_timers_and_constants_present, ie_ptr, 1); // Optional indicators if(rr_cnfg->srb_to_add_mod_list_size != 0) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } if(rr_cnfg->drb_to_add_mod_list_size != 0) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } if(rr_cnfg->drb_to_release_list_size != 0) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } - rrc_value_2_bits(rr_cnfg->mac_main_cnfg_present, ie_ptr, 1); - rrc_value_2_bits(rr_cnfg->sps_cnfg_present, ie_ptr, 1); - rrc_value_2_bits(rr_cnfg->phy_cnfg_ded_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->mac_main_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->sps_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->phy_cnfg_ded_present, ie_ptr, 1); // SRB To Add Mod List if(rr_cnfg->srb_to_add_mod_list_size != 0) { - rrc_value_2_bits(rr_cnfg->srb_to_add_mod_list_size - 1, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list_size - 1, ie_ptr, 1); } for(i=0; isrb_to_add_mod_list_size; i++) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicators - rrc_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].rlc_cnfg_present, ie_ptr, 1); - rrc_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].lc_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].rlc_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].lc_cnfg_present, ie_ptr, 1); // SRB Identity - rrc_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].srb_id - 1, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].srb_id - 1, ie_ptr, 1); // RLC Config if(rr_cnfg->srb_to_add_mod_list[i].rlc_cnfg_present) { // Choice - rrc_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].rlc_default_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].rlc_default_cnfg_present, ie_ptr, 1); // Explicit Config if(!rr_cnfg->srb_to_add_mod_list[i].rlc_default_cnfg_present) @@ -5099,7 +7586,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_dedicated_ie(LIBLTE_RRC_RR_CONFIG_DE if(rr_cnfg->srb_to_add_mod_list[i].lc_cnfg_present) { // Choice - rrc_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].lc_default_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].lc_default_cnfg_present, ie_ptr, 1); // Explicit Config if(!rr_cnfg->srb_to_add_mod_list[i].lc_default_cnfg_present) @@ -5112,24 +7599,24 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_dedicated_ie(LIBLTE_RRC_RR_CONFIG_DE // DRB To Add Mod List if(rr_cnfg->drb_to_add_mod_list_size != 0) { - rrc_value_2_bits(rr_cnfg->drb_to_add_mod_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list_size - 1, ie_ptr, 4); } for(i=0; idrb_to_add_mod_list_size; i++) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicators - rrc_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id_present, ie_ptr, 1); - rrc_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].pdcp_cnfg_present, ie_ptr, 1); - rrc_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].rlc_cnfg_present, ie_ptr, 1); - rrc_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].lc_id_present, ie_ptr, 1); - rrc_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].lc_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].pdcp_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].rlc_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].lc_id_present, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].lc_cnfg_present, ie_ptr, 1); // EPS Bearer Identity if(rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id_present) { - rrc_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id, ie_ptr, 4); + liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id, ie_ptr, 4); } // DRB Identity @@ -5150,7 +7637,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_dedicated_ie(LIBLTE_RRC_RR_CONFIG_DE // Logical Channel Identity if(rr_cnfg->drb_to_add_mod_list[i].lc_id_present) { - rrc_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].lc_id - 3, ie_ptr, 3); + liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].lc_id - 3, ie_ptr, 3); } // Logical Channel Configuration @@ -5163,7 +7650,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_dedicated_ie(LIBLTE_RRC_RR_CONFIG_DE // DRB To Release List if(rr_cnfg->drb_to_release_list_size != 0) { - rrc_value_2_bits(rr_cnfg->drb_to_release_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(rr_cnfg->drb_to_release_list_size - 1, ie_ptr, 4); } for(i=0; idrb_to_release_list_size; i++) { @@ -5173,7 +7660,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_dedicated_ie(LIBLTE_RRC_RR_CONFIG_DE // MAC Main Config if(rr_cnfg->mac_main_cnfg_present) { - rrc_value_2_bits(rr_cnfg->mac_main_cnfg.default_value, ie_ptr, 1); + liblte_value_2_bits(rr_cnfg->mac_main_cnfg.default_value, ie_ptr, 1); if(!rr_cnfg->mac_main_cnfg.default_value) { liblte_rrc_pack_mac_main_config_ie(&rr_cnfg->mac_main_cnfg.explicit_value, ie_ptr); @@ -5193,14 +7680,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_dedicated_ie(LIBLTE_RRC_RR_CONFIG_DE } // Extension - // Optional indicators - rrc_value_2_bits(rr_cnfg->rlf_timers_and_constants_present, ie_ptr, 1); - - // RLF Timers and Constants - if(rr_cnfg->rlf_timers_and_constants_present) - { - liblte_rrc_pack_rlf_timers_and_constants_ie(&rr_cnfg->rlf_timers_and_constants, ie_ptr); - } + // FIXME err = LIBLTE_SUCCESS; } @@ -5212,46 +7692,48 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_dedicated_ie(uint8 { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; - bool ext; + bool rr_cnfg_ded_ext_ind; bool srb_to_add_mod_list_present; + bool srb_to_add_mod_ext_ind; bool drb_to_add_mod_list_present; + bool drb_to_add_mod_ext_ind; bool drb_to_release_list_present; if(ie_ptr != NULL && rr_cnfg != NULL) { // Extension indicator - ext = rrc_bits_2_value(ie_ptr, 1); + rr_cnfg_ded_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - srb_to_add_mod_list_present = rrc_bits_2_value(ie_ptr, 1); - drb_to_add_mod_list_present = rrc_bits_2_value(ie_ptr, 1); - drb_to_release_list_present = rrc_bits_2_value(ie_ptr, 1); - rr_cnfg->mac_main_cnfg_present = rrc_bits_2_value(ie_ptr, 1); - rr_cnfg->sps_cnfg_present = rrc_bits_2_value(ie_ptr, 1); - rr_cnfg->phy_cnfg_ded_present = rrc_bits_2_value(ie_ptr, 1); + srb_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1); + drb_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1); + drb_to_release_list_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->mac_main_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->sps_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->phy_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1); // SRB To Add Mod List if(srb_to_add_mod_list_present) { - rr_cnfg->srb_to_add_mod_list_size = rrc_bits_2_value(ie_ptr, 1) + 1; + rr_cnfg->srb_to_add_mod_list_size = liblte_bits_2_value(ie_ptr, 1) + 1; for(i=0; isrb_to_add_mod_list_size; i++) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + srb_to_add_mod_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - rr_cnfg->srb_to_add_mod_list[i].rlc_cnfg_present = rrc_bits_2_value(ie_ptr, 1); - rr_cnfg->srb_to_add_mod_list[i].lc_cnfg_present = rrc_bits_2_value(ie_ptr, 1); + rr_cnfg->srb_to_add_mod_list[i].rlc_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->srb_to_add_mod_list[i].lc_cnfg_present = liblte_bits_2_value(ie_ptr, 1); // SRB Identity - rr_cnfg->srb_to_add_mod_list[i].srb_id = rrc_bits_2_value(ie_ptr, 1) + 1; + rr_cnfg->srb_to_add_mod_list[i].srb_id = liblte_bits_2_value(ie_ptr, 1) + 1; // RLC Config if(rr_cnfg->srb_to_add_mod_list[i].rlc_cnfg_present) { // Choice - rr_cnfg->srb_to_add_mod_list[i].rlc_default_cnfg_present = rrc_bits_2_value(ie_ptr, 1); + rr_cnfg->srb_to_add_mod_list[i].rlc_default_cnfg_present = liblte_bits_2_value(ie_ptr, 1); // Explicit Config if(!rr_cnfg->srb_to_add_mod_list[i].rlc_default_cnfg_present) @@ -5264,7 +7746,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_dedicated_ie(uint8 if(rr_cnfg->srb_to_add_mod_list[i].lc_cnfg_present) { // Choice - rr_cnfg->srb_to_add_mod_list[i].lc_default_cnfg_present = rrc_bits_2_value(ie_ptr, 1); + rr_cnfg->srb_to_add_mod_list[i].lc_default_cnfg_present = liblte_bits_2_value(ie_ptr, 1); // Explicit Config if(!rr_cnfg->srb_to_add_mod_list[i].lc_default_cnfg_present) @@ -5272,29 +7754,31 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_dedicated_ie(uint8 liblte_rrc_unpack_logical_channel_config_ie(ie_ptr, &rr_cnfg->srb_to_add_mod_list[i].lc_explicit_cnfg); } } + + skip_sequence_type_extension(srb_to_add_mod_ext_ind, ie_ptr); } } // DRB To Add Mod List if(drb_to_add_mod_list_present) { - rr_cnfg->drb_to_add_mod_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + rr_cnfg->drb_to_add_mod_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(i=0; idrb_to_add_mod_list_size; i++) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + drb_to_add_mod_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id_present = rrc_bits_2_value(ie_ptr, 1); - rr_cnfg->drb_to_add_mod_list[i].pdcp_cnfg_present = rrc_bits_2_value(ie_ptr, 1); - rr_cnfg->drb_to_add_mod_list[i].rlc_cnfg_present = rrc_bits_2_value(ie_ptr, 1); - rr_cnfg->drb_to_add_mod_list[i].lc_id_present = rrc_bits_2_value(ie_ptr, 1); - rr_cnfg->drb_to_add_mod_list[i].lc_cnfg_present = rrc_bits_2_value(ie_ptr, 1); + rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->drb_to_add_mod_list[i].pdcp_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->drb_to_add_mod_list[i].rlc_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->drb_to_add_mod_list[i].lc_id_present = liblte_bits_2_value(ie_ptr, 1); + rr_cnfg->drb_to_add_mod_list[i].lc_cnfg_present = liblte_bits_2_value(ie_ptr, 1); // EPS Bearer Identity if(rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id_present) { - rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id = rrc_bits_2_value(ie_ptr, 4); + rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id = liblte_bits_2_value(ie_ptr, 4); } // DRB Identity @@ -5315,7 +7799,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_dedicated_ie(uint8 // Logical Channel Identity if(rr_cnfg->drb_to_add_mod_list[i].lc_id_present) { - rr_cnfg->drb_to_add_mod_list[i].lc_id = rrc_bits_2_value(ie_ptr, 3) + 3; + rr_cnfg->drb_to_add_mod_list[i].lc_id = liblte_bits_2_value(ie_ptr, 3) + 3; } // Logical Channel Configuration @@ -5323,13 +7807,15 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_dedicated_ie(uint8 { liblte_rrc_unpack_logical_channel_config_ie(ie_ptr, &rr_cnfg->drb_to_add_mod_list[i].lc_cnfg); } + + skip_sequence_type_extension(drb_to_add_mod_ext_ind, ie_ptr); } } // DRB To Release List if(drb_to_release_list_present) { - rr_cnfg->drb_to_release_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + rr_cnfg->drb_to_release_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(i=0; idrb_to_release_list_size; i++) { liblte_rrc_unpack_drb_identity_ie(ie_ptr, &rr_cnfg->drb_to_release_list[i]); @@ -5339,7 +7825,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_dedicated_ie(uint8 // MAC Main Config if(rr_cnfg->mac_main_cnfg_present) { - rr_cnfg->mac_main_cnfg.default_value = rrc_bits_2_value(ie_ptr, 1); + rr_cnfg->mac_main_cnfg.default_value = liblte_bits_2_value(ie_ptr, 1); if(!rr_cnfg->mac_main_cnfg.default_value) { liblte_rrc_unpack_mac_main_config_ie(ie_ptr, &rr_cnfg->mac_main_cnfg.explicit_value); @@ -5359,17 +7845,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_dedicated_ie(uint8 } // Extension - if(ext) - { - // Optional indicators - rr_cnfg->rlf_timers_and_constants_present = rrc_bits_2_value(ie_ptr, 1); - - // RLF Timers and Constants - if(rr_cnfg->rlf_timers_and_constants_present) - { - liblte_rrc_unpack_rlf_timers_and_constants_ie(ie_ptr, &rr_cnfg->rlf_timers_and_constants); - } - } + skip_sequence_type_extension(rr_cnfg_ded_ext_ind, ie_ptr); + rr_cnfg->rlf_timers_and_constants_present = false; err = LIBLTE_SUCCESS; } @@ -5393,66 +7870,60 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rlc_config_ie(LIBLTE_RRC_RLC_CONFIG_STRUCT *r ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); - // AM + // Mode Choice + liblte_value_2_bits(rlc_cnfg->rlc_mode, ie_ptr, 2); + + if(LIBLTE_RRC_RLC_MODE_AM == rlc_cnfg->rlc_mode) { // UL AM RLC { // T Poll Retransmit - rrc_value_2_bits(rlc_cnfg->ul_am_rlc.t_poll_retx, ie_ptr, 6); + liblte_value_2_bits(rlc_cnfg->ul_am_rlc.t_poll_retx, ie_ptr, 6); // Poll PDU - rrc_value_2_bits(rlc_cnfg->ul_am_rlc.poll_pdu, ie_ptr, 3); + liblte_value_2_bits(rlc_cnfg->ul_am_rlc.poll_pdu, ie_ptr, 3); // Poll Byte - rrc_value_2_bits(rlc_cnfg->ul_am_rlc.poll_byte, ie_ptr, 4); + liblte_value_2_bits(rlc_cnfg->ul_am_rlc.poll_byte, ie_ptr, 4); // Max Retransmission Threshold - rrc_value_2_bits(rlc_cnfg->ul_am_rlc.max_retx_thresh, ie_ptr, 3); + liblte_value_2_bits(rlc_cnfg->ul_am_rlc.max_retx_thresh, ie_ptr, 3); } // DL AM RLC { // T Reordering - rrc_value_2_bits(rlc_cnfg->dl_am_rlc.t_reordering, ie_ptr, 5); + liblte_value_2_bits(rlc_cnfg->dl_am_rlc.t_reordering, ie_ptr, 5); // T Status Prohibit - rrc_value_2_bits(rlc_cnfg->dl_am_rlc.t_status_prohibit, ie_ptr, 6); + liblte_value_2_bits(rlc_cnfg->dl_am_rlc.t_status_prohibit, ie_ptr, 6); } - } - - // UM Bi Directional - { + }else if(LIBLTE_RRC_RLC_MODE_UM_BI == rlc_cnfg->rlc_mode){ // UL UM RLC { // SN Field Length - rrc_value_2_bits(rlc_cnfg->ul_um_bi_rlc.sn_field_len, ie_ptr, 1); + liblte_value_2_bits(rlc_cnfg->ul_um_bi_rlc.sn_field_len, ie_ptr, 1); } // DL UM RLC { // SN Field Length - rrc_value_2_bits(rlc_cnfg->dl_um_bi_rlc.sn_field_len, ie_ptr, 1); + liblte_value_2_bits(rlc_cnfg->dl_um_bi_rlc.sn_field_len, ie_ptr, 1); // T Reordering - rrc_value_2_bits(rlc_cnfg->dl_um_bi_rlc.t_reordering, ie_ptr, 5); + liblte_value_2_bits(rlc_cnfg->dl_um_bi_rlc.t_reordering, ie_ptr, 5); } - } - - // UM Uni Directional UL - { + }else if(LIBLTE_RRC_RLC_MODE_UM_UNI_UL == rlc_cnfg->rlc_mode){ // SN Field Length - rrc_value_2_bits(rlc_cnfg->ul_um_uni_rlc.sn_field_len, ie_ptr, 1); - } - - // UM Uni Directional DL - { + liblte_value_2_bits(rlc_cnfg->ul_um_uni_rlc.sn_field_len, ie_ptr, 1); + }else{ // LIBLTE_RRC_RLC_MODE_UM_UNI_DL == rlc_cnfg->rlc_mode // SN Field Length - rrc_value_2_bits(rlc_cnfg->dl_um_uni_rlc.sn_field_len, ie_ptr, 1); + liblte_value_2_bits(rlc_cnfg->dl_um_uni_rlc.sn_field_len, ie_ptr, 1); // T Reordering - rrc_value_2_bits(rlc_cnfg->dl_um_uni_rlc.t_reordering, ie_ptr, 5); + liblte_value_2_bits(rlc_cnfg->dl_um_uni_rlc.t_reordering, ie_ptr, 5); } err = LIBLTE_SUCCESS; @@ -5464,73 +7935,70 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rlc_config_ie(uint8 * LIBLTE_RRC_RLC_CONFIG_STRUCT *rlc_cnfg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; if(ie_ptr != NULL && rlc_cnfg != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Mode Choice + rlc_cnfg->rlc_mode = (LIBLTE_RRC_RLC_MODE_ENUM)liblte_bits_2_value(ie_ptr, 2); - // AM + if(LIBLTE_RRC_RLC_MODE_AM == rlc_cnfg->rlc_mode) { // UL AM RLC { // T Poll Retransmit - rlc_cnfg->ul_am_rlc.t_poll_retx = (LIBLTE_RRC_T_POLL_RETRANSMIT_ENUM)rrc_bits_2_value(ie_ptr, 6); + rlc_cnfg->ul_am_rlc.t_poll_retx = (LIBLTE_RRC_T_POLL_RETRANSMIT_ENUM)liblte_bits_2_value(ie_ptr, 6); // Poll PDU - rlc_cnfg->ul_am_rlc.poll_pdu = (LIBLTE_RRC_POLL_PDU_ENUM)rrc_bits_2_value(ie_ptr, 3); + rlc_cnfg->ul_am_rlc.poll_pdu = (LIBLTE_RRC_POLL_PDU_ENUM)liblte_bits_2_value(ie_ptr, 3); // Poll Byte - rlc_cnfg->ul_am_rlc.poll_byte = (LIBLTE_RRC_POLL_BYTE_ENUM)rrc_bits_2_value(ie_ptr, 4); + rlc_cnfg->ul_am_rlc.poll_byte = (LIBLTE_RRC_POLL_BYTE_ENUM)liblte_bits_2_value(ie_ptr, 4); // Max Retransmission Threshold - rlc_cnfg->ul_am_rlc.max_retx_thresh = (LIBLTE_RRC_MAX_RETX_THRESHOLD_ENUM)rrc_bits_2_value(ie_ptr, 3); + rlc_cnfg->ul_am_rlc.max_retx_thresh = (LIBLTE_RRC_MAX_RETX_THRESHOLD_ENUM)liblte_bits_2_value(ie_ptr, 3); } // DL AM RLC { // T Reordering - rlc_cnfg->dl_am_rlc.t_reordering = (LIBLTE_RRC_T_REORDERING_ENUM)rrc_bits_2_value(ie_ptr, 5); + rlc_cnfg->dl_am_rlc.t_reordering = (LIBLTE_RRC_T_REORDERING_ENUM)liblte_bits_2_value(ie_ptr, 5); // T Status Prohibit - rlc_cnfg->dl_am_rlc.t_status_prohibit = (LIBLTE_RRC_T_STATUS_PROHIBIT_ENUM)rrc_bits_2_value(ie_ptr, 6); + rlc_cnfg->dl_am_rlc.t_status_prohibit = (LIBLTE_RRC_T_STATUS_PROHIBIT_ENUM)liblte_bits_2_value(ie_ptr, 6); } - } - - // UM Bi Directional - { + }else if(LIBLTE_RRC_RLC_MODE_UM_BI == rlc_cnfg->rlc_mode){ // UL UM RLC { // SN Field Length - rlc_cnfg->ul_um_bi_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)rrc_bits_2_value(ie_ptr, 1); + rlc_cnfg->ul_um_bi_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1); } // DL UM RLC { // SN Field Length - rlc_cnfg->dl_um_bi_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)rrc_bits_2_value(ie_ptr, 1); + rlc_cnfg->dl_um_bi_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1); // T Reordering - rlc_cnfg->dl_um_bi_rlc.t_reordering = (LIBLTE_RRC_T_REORDERING_ENUM)rrc_bits_2_value(ie_ptr, 5); + rlc_cnfg->dl_um_bi_rlc.t_reordering = (LIBLTE_RRC_T_REORDERING_ENUM)liblte_bits_2_value(ie_ptr, 5); } - } - - // UM Uni Directional UL - { + }else if(LIBLTE_RRC_RLC_MODE_UM_UNI_UL == rlc_cnfg->rlc_mode){ // SN Field Length - rlc_cnfg->ul_um_uni_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)rrc_bits_2_value(ie_ptr, 1); - } - - // UM Uni Directional DL - { + rlc_cnfg->ul_um_uni_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1); + }else{ // LIBLTE_RRC_RLC_MODE_UM_UNI_DL == rlc_cnfg->rlc_mode // SN Field Length - rlc_cnfg->dl_um_uni_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)rrc_bits_2_value(ie_ptr, 1); + rlc_cnfg->dl_um_uni_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1); // T Reordering - rlc_cnfg->dl_um_uni_rlc.t_reordering = (LIBLTE_RRC_T_REORDERING_ENUM)rrc_bits_2_value(ie_ptr, 5); + rlc_cnfg->dl_um_uni_rlc.t_reordering = (LIBLTE_RRC_T_REORDERING_ENUM)liblte_bits_2_value(ie_ptr, 5); } + skip_sequence_type_extension(ext_ind, ie_ptr); + err = LIBLTE_SUCCESS; } @@ -5554,16 +8022,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rlf_timers_and_constants_ie(LIBLTE_RRC_RLF_TIM ie_ptr != NULL) { // Release choice - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); // Extension - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(rlf_timers_and_constants->t301, ie_ptr, 3); - rrc_value_2_bits(rlf_timers_and_constants->t310, ie_ptr, 3); - rrc_value_2_bits(rlf_timers_and_constants->n310, ie_ptr, 3); - rrc_value_2_bits(rlf_timers_and_constants->t311, ie_ptr, 3); - rrc_value_2_bits(rlf_timers_and_constants->n311, ie_ptr, 3); + liblte_value_2_bits(rlf_timers_and_constants->t301, ie_ptr, 3); + liblte_value_2_bits(rlf_timers_and_constants->t310, ie_ptr, 3); + liblte_value_2_bits(rlf_timers_and_constants->n310, ie_ptr, 3); + liblte_value_2_bits(rlf_timers_and_constants->t311, ie_ptr, 3); + liblte_value_2_bits(rlf_timers_and_constants->n311, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -5574,21 +8042,24 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rlf_timers_and_constants_ie(uint8 LIBLTE_RRC_RLF_TIMERS_AND_CONSTANTS_STRUCT *rlf_timers_and_constants) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; if(ie_ptr != NULL && rlf_timers_and_constants != NULL) { // Release choice - rrc_bits_2_value(ie_ptr, 1); + liblte_bits_2_value(ie_ptr, 1); // Extension - rrc_bits_2_value(ie_ptr, 1); + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + rlf_timers_and_constants->t301 = (LIBLTE_RRC_T301_ENUM)liblte_bits_2_value(ie_ptr, 3); + rlf_timers_and_constants->t310 = (LIBLTE_RRC_T310_ENUM)liblte_bits_2_value(ie_ptr, 3); + rlf_timers_and_constants->n310 = (LIBLTE_RRC_N310_ENUM)liblte_bits_2_value(ie_ptr, 3); + rlf_timers_and_constants->t311 = (LIBLTE_RRC_T311_ENUM)liblte_bits_2_value(ie_ptr, 3); + rlf_timers_and_constants->n311 = (LIBLTE_RRC_N311_ENUM)liblte_bits_2_value(ie_ptr, 3); - rlf_timers_and_constants->t301 = (LIBLTE_RRC_T301_ENUM)rrc_bits_2_value(ie_ptr, 3); - rlf_timers_and_constants->t310 = (LIBLTE_RRC_T310_ENUM)rrc_bits_2_value(ie_ptr, 3); - rlf_timers_and_constants->n310 = (LIBLTE_RRC_N310_ENUM)rrc_bits_2_value(ie_ptr, 3); - rlf_timers_and_constants->t311 = (LIBLTE_RRC_T311_ENUM)rrc_bits_2_value(ie_ptr, 3); - rlf_timers_and_constants->n311 = (LIBLTE_RRC_N311_ENUM)rrc_bits_2_value(ie_ptr, 3); + skip_sequence_type_extension(ext_ind, ie_ptr); err = LIBLTE_SUCCESS; } @@ -5603,7 +8074,148 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rlf_timers_and_constants_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.2 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_rn_subframe_config_ie(LIBLTE_RRC_RN_SUBFRAME_CONFIG_STRUCT *rn_subfr_cnfg, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(rn_subfr_cnfg != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Optional indicator + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg_present, ie_ptr, 1); + + // Frame structure type + liblte_value_2_bits(rn_subfr_cnfg->fr_struct_type, ie_ptr, 1); + if(LIBLTE_RRC_FRAME_STRUCTURE_TYPE_FDD == rn_subfr_cnfg->fr_struct_type) + { + liblte_value_2_bits(rn_subfr_cnfg->subfr_cnfg_pattern, ie_ptr, 8); + }else{ + liblte_value_2_bits(rn_subfr_cnfg->subfr_cnfg_pattern, ie_ptr, 5); + } + + // RPDCCH Config + if(rn_subfr_cnfg->rpdcch_cnfg_present) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Resource allocation type + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.resource_alloc_type, ie_ptr, 2); + + // Resource block assignment + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.resource_block_assignment_choice, ie_ptr, 1); + if(LIBLTE_RRC_RESOURCE_BLOCK_ASSIGNMENT_CHOICE_TYPE_0 == rn_subfr_cnfg->rpdcch_cnfg.resource_block_assignment_choice) + { + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb6, ie_ptr, 6); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb15, ie_ptr, 8); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb25, ie_ptr, 13); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb50, ie_ptr, 17); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb75, ie_ptr, 19); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb100, ie_ptr, 25); + }else{ + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb6, ie_ptr, 5); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb15, ie_ptr, 7); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb25, ie_ptr, 9); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb50, ie_ptr, 11); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb75, ie_ptr, 12); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.rba_nrb100, ie_ptr, 13); + } + + // Demodulation RS choice and type + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.demod_rs_choice, ie_ptr, 1); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.demod_rs_type, ie_ptr, 1); + + // PDSCH start + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.pdsch_start - 1, ie_ptr, 2); + + // PUCCH Config + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.n1_pucch_an_port_0, ie_ptr, 11); + liblte_value_2_bits(rn_subfr_cnfg->rpdcch_cnfg.n1_pucch_an_port_1, ie_ptr, 11); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_rn_subframe_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_RN_SUBFRAME_CONFIG_STRUCT *rn_subfr_cnfg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool rn_subfr_cnfg_ext_ind; + bool rpdcch_cnfg_ext_ind; + + if(ie_ptr != NULL && + rn_subfr_cnfg != NULL) + { + // Extension indicator + rn_subfr_cnfg_ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Optional indicator + rn_subfr_cnfg->rpdcch_cnfg_present = liblte_bits_2_value(ie_ptr, 1); + + // Frame structure type + rn_subfr_cnfg->rpdcch_cnfg_present = (LIBLTE_RRC_FRAME_STRUCTURE_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_FRAME_STRUCTURE_TYPE_FDD == rn_subfr_cnfg->fr_struct_type) + { + rn_subfr_cnfg->subfr_cnfg_pattern = liblte_bits_2_value(ie_ptr, 8); + }else{ + rn_subfr_cnfg->subfr_cnfg_pattern = liblte_bits_2_value(ie_ptr, 5); + } + + // RPDCCH Config + if(rn_subfr_cnfg->rpdcch_cnfg_present) + { + // Extension indicator + rpdcch_cnfg_ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Resource allocation type + rn_subfr_cnfg->rpdcch_cnfg.resource_alloc_type = (LIBLTE_RRC_RESOURCE_ALLOCATION_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 2); + + // Resource block assignment + rn_subfr_cnfg->rpdcch_cnfg.resource_block_assignment_choice = (LIBLTE_RRC_RESOURCE_BLOCK_ASSIGNMENT_CHOICE_ENUM)liblte_bits_2_value(ie_ptr, 1); + if(LIBLTE_RRC_RESOURCE_BLOCK_ASSIGNMENT_CHOICE_TYPE_0 == rn_subfr_cnfg->rpdcch_cnfg.resource_block_assignment_choice) + { + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb6 = liblte_bits_2_value(ie_ptr, 6); + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb15 = liblte_bits_2_value(ie_ptr, 8); + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb25 = liblte_bits_2_value(ie_ptr, 13); + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb50 = liblte_bits_2_value(ie_ptr, 17); + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb75 = liblte_bits_2_value(ie_ptr, 19); + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb100 = liblte_bits_2_value(ie_ptr, 25); + }else{ + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb6 = liblte_bits_2_value(ie_ptr, 5); + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb15 = liblte_bits_2_value(ie_ptr, 7); + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb25 = liblte_bits_2_value(ie_ptr, 9); + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb50 = liblte_bits_2_value(ie_ptr, 11); + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb75 = liblte_bits_2_value(ie_ptr, 12); + rn_subfr_cnfg->rpdcch_cnfg.rba_nrb100 = liblte_bits_2_value(ie_ptr, 13); + } + + // Demodulation RS choice and type + rn_subfr_cnfg->rpdcch_cnfg.demod_rs_choice = (LIBLTE_RRC_DEMODULATION_RS_CHOICE_ENUM)liblte_bits_2_value(ie_ptr, 1); + rn_subfr_cnfg->rpdcch_cnfg.demod_rs_type = (LIBLTE_RRC_DEMODULATION_RS_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1); + + // PDSCH start + rn_subfr_cnfg->rpdcch_cnfg.pdsch_start = liblte_bits_2_value(ie_ptr, 2) + 1; + + // PUCCH Config + rn_subfr_cnfg->rpdcch_cnfg.n1_pucch_an_port_0 = liblte_bits_2_value(ie_ptr, 11); + rn_subfr_cnfg->rpdcch_cnfg.n1_pucch_an_port_1 = liblte_bits_2_value(ie_ptr, 11); + + skip_sequence_type_extension(rpdcch_cnfg_ext_ind, ie_ptr); + } + + skip_sequence_type_extension(rn_subfr_cnfg_ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* IE Name: Scheduling Request Config @@ -5621,17 +8233,17 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_scheduling_request_config_ie(LIBLTE_RRC_SCHEDU ie_ptr != NULL) { // Setup - rrc_value_2_bits(sched_request_cnfg->setup_present, ie_ptr, 1); + liblte_value_2_bits(sched_request_cnfg->setup_present, ie_ptr, 1); if(sched_request_cnfg->setup_present) { // SR PUCCH Resource Index - rrc_value_2_bits(sched_request_cnfg->sr_pucch_resource_idx, ie_ptr, 11); + liblte_value_2_bits(sched_request_cnfg->sr_pucch_resource_idx, ie_ptr, 11); // SR Config Index - rrc_value_2_bits(sched_request_cnfg->sr_cnfg_idx, ie_ptr, 8); + liblte_value_2_bits(sched_request_cnfg->sr_cnfg_idx, ie_ptr, 8); // DRS Trans Max - rrc_value_2_bits(sched_request_cnfg->dsr_trans_max, ie_ptr, 3); + liblte_value_2_bits(sched_request_cnfg->dsr_trans_max, ie_ptr, 3); } err = LIBLTE_SUCCESS; @@ -5648,17 +8260,17 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_scheduling_request_config_ie(uint8 sched_request_cnfg != NULL) { // Setup - sched_request_cnfg->setup_present = rrc_bits_2_value(ie_ptr, 1); + sched_request_cnfg->setup_present = liblte_bits_2_value(ie_ptr, 1); if(sched_request_cnfg->setup_present) { // SR PUCCH Resource Index - sched_request_cnfg->sr_pucch_resource_idx = rrc_bits_2_value(ie_ptr, 11); + sched_request_cnfg->sr_pucch_resource_idx = liblte_bits_2_value(ie_ptr, 11); // SR Config Index - sched_request_cnfg->sr_cnfg_idx = rrc_bits_2_value(ie_ptr, 8); + sched_request_cnfg->sr_cnfg_idx = liblte_bits_2_value(ie_ptr, 8); // DRS Trans Max - sched_request_cnfg->dsr_trans_max = (LIBLTE_RRC_DSR_TRANS_MAX_ENUM)rrc_bits_2_value(ie_ptr, 3); + sched_request_cnfg->dsr_trans_max = (LIBLTE_RRC_DSR_TRANS_MAX_ENUM)liblte_bits_2_value(ie_ptr, 3); } err = LIBLTE_SUCCESS; @@ -5683,19 +8295,19 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_srs_ul_config_common_ie(LIBLTE_RRC_SRS_UL_CONF if(srs_ul_cnfg != NULL && ie_ptr != NULL) { - rrc_value_2_bits(srs_ul_cnfg->present, ie_ptr, 1); + liblte_value_2_bits(srs_ul_cnfg->present, ie_ptr, 1); if(true == srs_ul_cnfg->present) { - rrc_value_2_bits(srs_ul_cnfg->max_up_pts_present, ie_ptr, 1); + liblte_value_2_bits(srs_ul_cnfg->max_up_pts_present, ie_ptr, 1); - rrc_value_2_bits(srs_ul_cnfg->bw_cnfg, ie_ptr, 3); - rrc_value_2_bits(srs_ul_cnfg->subfr_cnfg, ie_ptr, 4); - rrc_value_2_bits(srs_ul_cnfg->ack_nack_simul_tx, ie_ptr, 1); + liblte_value_2_bits(srs_ul_cnfg->bw_cnfg, ie_ptr, 3); + liblte_value_2_bits(srs_ul_cnfg->subfr_cnfg, ie_ptr, 4); + liblte_value_2_bits(srs_ul_cnfg->ack_nack_simul_tx, ie_ptr, 1); if(true == srs_ul_cnfg->max_up_pts_present) { - rrc_value_2_bits(srs_ul_cnfg->max_up_pts, ie_ptr, 1); + liblte_value_2_bits(srs_ul_cnfg->max_up_pts, ie_ptr, 1); } } @@ -5712,19 +8324,19 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_srs_ul_config_common_ie(uint8 if(ie_ptr != NULL && srs_ul_cnfg != NULL) { - srs_ul_cnfg->present = rrc_bits_2_value(ie_ptr, 1); + srs_ul_cnfg->present = liblte_bits_2_value(ie_ptr, 1); if(true == srs_ul_cnfg->present) { - srs_ul_cnfg->max_up_pts_present = rrc_bits_2_value(ie_ptr, 1); + srs_ul_cnfg->max_up_pts_present = liblte_bits_2_value(ie_ptr, 1); - srs_ul_cnfg->bw_cnfg = (LIBLTE_RRC_SRS_BW_CONFIG_ENUM)rrc_bits_2_value(ie_ptr, 3); - srs_ul_cnfg->subfr_cnfg = (LIBLTE_RRC_SRS_SUBFR_CONFIG_ENUM)rrc_bits_2_value(ie_ptr, 4); - srs_ul_cnfg->ack_nack_simul_tx = rrc_bits_2_value(ie_ptr, 1); + srs_ul_cnfg->bw_cnfg = (LIBLTE_RRC_SRS_BW_CONFIG_ENUM)liblte_bits_2_value(ie_ptr, 3); + srs_ul_cnfg->subfr_cnfg = (LIBLTE_RRC_SRS_SUBFR_CONFIG_ENUM)liblte_bits_2_value(ie_ptr, 4); + srs_ul_cnfg->ack_nack_simul_tx = liblte_bits_2_value(ie_ptr, 1); if(true == srs_ul_cnfg->max_up_pts_present) { - srs_ul_cnfg->max_up_pts = rrc_bits_2_value(ie_ptr, 1); + srs_ul_cnfg->max_up_pts = liblte_bits_2_value(ie_ptr, 1); } } @@ -5742,29 +8354,29 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_srs_ul_config_dedicated_ie(LIBLTE_RRC_SRS_UL_C ie_ptr != NULL) { // Setup - rrc_value_2_bits(srs_ul_cnfg->setup_present, ie_ptr, 1); + liblte_value_2_bits(srs_ul_cnfg->setup_present, ie_ptr, 1); if(srs_ul_cnfg->setup_present) { // SRS Bandwidth - rrc_value_2_bits(srs_ul_cnfg->srs_bandwidth, ie_ptr, 2); + liblte_value_2_bits(srs_ul_cnfg->srs_bandwidth, ie_ptr, 2); // SRS Hopping Bandwidth - rrc_value_2_bits(srs_ul_cnfg->srs_hopping_bandwidth, ie_ptr, 2); + liblte_value_2_bits(srs_ul_cnfg->srs_hopping_bandwidth, ie_ptr, 2); // Frequency Domain Position - rrc_value_2_bits(srs_ul_cnfg->freq_domain_pos, ie_ptr, 5); + liblte_value_2_bits(srs_ul_cnfg->freq_domain_pos, ie_ptr, 5); // Duration - rrc_value_2_bits(srs_ul_cnfg->duration, ie_ptr, 1); + liblte_value_2_bits(srs_ul_cnfg->duration, ie_ptr, 1); // SRS Config Index - rrc_value_2_bits(srs_ul_cnfg->srs_cnfg_idx, ie_ptr, 10); + liblte_value_2_bits(srs_ul_cnfg->srs_cnfg_idx, ie_ptr, 10); // Transmission Comb - rrc_value_2_bits(srs_ul_cnfg->tx_comb, ie_ptr, 1); + liblte_value_2_bits(srs_ul_cnfg->tx_comb, ie_ptr, 1); // Cyclic Shift - rrc_value_2_bits(srs_ul_cnfg->cyclic_shift, ie_ptr, 3); + liblte_value_2_bits(srs_ul_cnfg->cyclic_shift, ie_ptr, 3); } err = LIBLTE_SUCCESS; @@ -5781,29 +8393,29 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_srs_ul_config_dedicated_ie(uint8 srs_ul_cnfg != NULL) { // Setup - srs_ul_cnfg->setup_present = rrc_bits_2_value(ie_ptr, 1); + srs_ul_cnfg->setup_present = liblte_bits_2_value(ie_ptr, 1); if(srs_ul_cnfg->setup_present) { // SRS Bandwidth - srs_ul_cnfg->srs_bandwidth = (LIBLTE_RRC_SRS_BANDWIDTH_ENUM)rrc_bits_2_value(ie_ptr, 2); + srs_ul_cnfg->srs_bandwidth = (LIBLTE_RRC_SRS_BANDWIDTH_ENUM)liblte_bits_2_value(ie_ptr, 2); // SRS Hopping Bandwidth - srs_ul_cnfg->srs_hopping_bandwidth = (LIBLTE_RRC_SRS_HOPPING_BANDWIDTH_ENUM)rrc_bits_2_value(ie_ptr, 2); + srs_ul_cnfg->srs_hopping_bandwidth = (LIBLTE_RRC_SRS_HOPPING_BANDWIDTH_ENUM)liblte_bits_2_value(ie_ptr, 2); // Frequency Domain Position - srs_ul_cnfg->freq_domain_pos = rrc_bits_2_value(ie_ptr, 5); + srs_ul_cnfg->freq_domain_pos = liblte_bits_2_value(ie_ptr, 5); // Duration - srs_ul_cnfg->duration = rrc_bits_2_value(ie_ptr, 1); + srs_ul_cnfg->duration = liblte_bits_2_value(ie_ptr, 1); // SRS Config Index - srs_ul_cnfg->srs_cnfg_idx = rrc_bits_2_value(ie_ptr, 10); + srs_ul_cnfg->srs_cnfg_idx = liblte_bits_2_value(ie_ptr, 10); // Transmission Comb - srs_ul_cnfg->tx_comb = rrc_bits_2_value(ie_ptr, 1); + srs_ul_cnfg->tx_comb = liblte_bits_2_value(ie_ptr, 1); // Cyclic Shift - srs_ul_cnfg->cyclic_shift = (LIBLTE_RRC_CYCLIC_SHIFT_ENUM)rrc_bits_2_value(ie_ptr, 3); + srs_ul_cnfg->cyclic_shift = (LIBLTE_RRC_CYCLIC_SHIFT_ENUM)liblte_bits_2_value(ie_ptr, 3); } err = LIBLTE_SUCCESS; @@ -5830,9 +8442,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sps_config_ie(LIBLTE_RRC_SPS_CONFIG_STRUCT *s ie_ptr != NULL) { // Optional indicators - rrc_value_2_bits(sps_cnfg->sps_c_rnti_present, ie_ptr, 1); - rrc_value_2_bits(sps_cnfg->sps_cnfg_dl_present, ie_ptr, 1); - rrc_value_2_bits(sps_cnfg->sps_cnfg_ul_present, ie_ptr, 1); + liblte_value_2_bits(sps_cnfg->sps_c_rnti_present, ie_ptr, 1); + liblte_value_2_bits(sps_cnfg->sps_cnfg_dl_present, ie_ptr, 1); + liblte_value_2_bits(sps_cnfg->sps_cnfg_ul_present, ie_ptr, 1); // SPS C-RNTI if(sps_cnfg->sps_c_rnti_present) @@ -5843,23 +8455,23 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sps_config_ie(LIBLTE_RRC_SPS_CONFIG_STRUCT *s // SPS Config DL if(sps_cnfg->sps_cnfg_dl_present) { - rrc_value_2_bits(sps_cnfg->sps_cnfg_dl.setup_present, ie_ptr, 1); + liblte_value_2_bits(sps_cnfg->sps_cnfg_dl.setup_present, ie_ptr, 1); if(sps_cnfg->sps_cnfg_dl.setup_present) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // SPS Interval DL - rrc_value_2_bits(sps_cnfg->sps_cnfg_dl.sps_interval_dl, ie_ptr, 4); + liblte_value_2_bits(sps_cnfg->sps_cnfg_dl.sps_interval_dl, ie_ptr, 4); // Number of Configured SPS Processes - rrc_value_2_bits(sps_cnfg->sps_cnfg_dl.N_sps_processes - 1, ie_ptr, 3); + liblte_value_2_bits(sps_cnfg->sps_cnfg_dl.N_sps_processes - 1, ie_ptr, 3); // N1 PUCCH AN Persistent List - rrc_value_2_bits(sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list_size - 1, ie_ptr, 2); + liblte_value_2_bits(sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list_size - 1, ie_ptr, 2); for(i=0; isps_cnfg_dl.n1_pucch_an_persistent_list_size; i++) { - rrc_value_2_bits(sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list[i], ie_ptr, 11); + liblte_value_2_bits(sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list[i], ie_ptr, 11); } } } @@ -5867,36 +8479,36 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sps_config_ie(LIBLTE_RRC_SPS_CONFIG_STRUCT *s // SPS Config UL if(sps_cnfg->sps_cnfg_ul_present) { - rrc_value_2_bits(sps_cnfg->sps_cnfg_ul.setup_present, ie_ptr, 1); + liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.setup_present, ie_ptr, 1); if(sps_cnfg->sps_cnfg_ul.setup_present) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicators - rrc_value_2_bits(sps_cnfg->sps_cnfg_ul.p0_persistent_present, ie_ptr, 1); - rrc_value_2_bits(sps_cnfg->sps_cnfg_ul.two_intervals_cnfg_present, ie_ptr, 1); + liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.p0_persistent_present, ie_ptr, 1); + liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.two_intervals_cnfg_present, ie_ptr, 1); // SPS Interval UL - rrc_value_2_bits(sps_cnfg->sps_cnfg_ul.sps_interval_ul, ie_ptr, 4); + liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.sps_interval_ul, ie_ptr, 4); // Implicit Release After - rrc_value_2_bits(sps_cnfg->sps_cnfg_ul.implicit_release_after, ie_ptr, 2); + liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.implicit_release_after, ie_ptr, 2); // P0 Persistent if(sps_cnfg->sps_cnfg_ul.p0_persistent_present) { // P0 Nominal PUSCH Persistent - rrc_value_2_bits(sps_cnfg->sps_cnfg_ul.p0_nominal_pusch + 126, ie_ptr, 8); + liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.p0_nominal_pusch + 126, ie_ptr, 8); // P0 UE PUSCH Persistent - rrc_value_2_bits(sps_cnfg->sps_cnfg_ul.p0_ue_pusch + 8, ie_ptr, 4); + liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.p0_ue_pusch + 8, ie_ptr, 4); } // Two Intervals Config if(sps_cnfg->sps_cnfg_ul.two_intervals_cnfg_present) { - rrc_value_2_bits(sps_cnfg->sps_cnfg_ul.two_intervals_cnfg, ie_ptr, 1); + liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.two_intervals_cnfg, ie_ptr, 1); } } } @@ -5911,14 +8523,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sps_config_ie(uint8 * { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; + bool dl_ext_ind; + bool ul_ext_ind; if(ie_ptr != NULL && sps_cnfg != NULL) { // Optional indicators - sps_cnfg->sps_c_rnti_present = rrc_bits_2_value(ie_ptr, 1); - sps_cnfg->sps_cnfg_dl_present = rrc_bits_2_value(ie_ptr, 1); - sps_cnfg->sps_cnfg_ul_present = rrc_bits_2_value(ie_ptr, 1); + sps_cnfg->sps_c_rnti_present = liblte_bits_2_value(ie_ptr, 1); + sps_cnfg->sps_cnfg_dl_present = liblte_bits_2_value(ie_ptr, 1); + sps_cnfg->sps_cnfg_ul_present = liblte_bits_2_value(ie_ptr, 1); // SPS C-RNTI if(sps_cnfg->sps_c_rnti_present) @@ -5929,61 +8543,65 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sps_config_ie(uint8 * // SPS Config DL if(sps_cnfg->sps_cnfg_dl_present) { - sps_cnfg->sps_cnfg_dl.setup_present = rrc_bits_2_value(ie_ptr, 1); + sps_cnfg->sps_cnfg_dl.setup_present = liblte_bits_2_value(ie_ptr, 1); if(sps_cnfg->sps_cnfg_dl.setup_present) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + dl_ext_ind = liblte_bits_2_value(ie_ptr, 1); // SPS Interval DL - sps_cnfg->sps_cnfg_dl.sps_interval_dl = (LIBLTE_RRC_SPS_INTERVAL_DL_ENUM)rrc_bits_2_value(ie_ptr, 4); + sps_cnfg->sps_cnfg_dl.sps_interval_dl = (LIBLTE_RRC_SPS_INTERVAL_DL_ENUM)liblte_bits_2_value(ie_ptr, 4); // Number of Configured SPS Processes - sps_cnfg->sps_cnfg_dl.N_sps_processes = rrc_bits_2_value(ie_ptr, 3) + 1; + sps_cnfg->sps_cnfg_dl.N_sps_processes = liblte_bits_2_value(ie_ptr, 3) + 1; // N1 PUCCH AN Persistent List - sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list_size = rrc_bits_2_value(ie_ptr, 2) + 1; + sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list_size = liblte_bits_2_value(ie_ptr, 2) + 1; for(i=0; isps_cnfg_dl.n1_pucch_an_persistent_list_size; i++) { - sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list[i] = rrc_bits_2_value(ie_ptr, 11); + sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list[i] = liblte_bits_2_value(ie_ptr, 11); } + + skip_sequence_type_extension(dl_ext_ind, ie_ptr); } } // SPS Config UL if(sps_cnfg->sps_cnfg_ul_present) { - sps_cnfg->sps_cnfg_ul.setup_present = rrc_bits_2_value(ie_ptr, 1); + sps_cnfg->sps_cnfg_ul.setup_present = liblte_bits_2_value(ie_ptr, 1); if(sps_cnfg->sps_cnfg_ul.setup_present) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + ul_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - sps_cnfg->sps_cnfg_ul.p0_persistent_present = rrc_bits_2_value(ie_ptr, 1); - sps_cnfg->sps_cnfg_ul.two_intervals_cnfg_present = rrc_bits_2_value(ie_ptr, 1); + sps_cnfg->sps_cnfg_ul.p0_persistent_present = liblte_bits_2_value(ie_ptr, 1); + sps_cnfg->sps_cnfg_ul.two_intervals_cnfg_present = liblte_bits_2_value(ie_ptr, 1); // SPS Interval UL - sps_cnfg->sps_cnfg_ul.sps_interval_ul = (LIBLTE_RRC_SPS_INTERVAL_UL_ENUM)rrc_bits_2_value(ie_ptr, 4); + sps_cnfg->sps_cnfg_ul.sps_interval_ul = (LIBLTE_RRC_SPS_INTERVAL_UL_ENUM)liblte_bits_2_value(ie_ptr, 4); // Implicit Release After - sps_cnfg->sps_cnfg_ul.implicit_release_after = (LIBLTE_RRC_IMPLICIT_RELEASE_AFTER_ENUM)rrc_bits_2_value(ie_ptr, 2); + sps_cnfg->sps_cnfg_ul.implicit_release_after = (LIBLTE_RRC_IMPLICIT_RELEASE_AFTER_ENUM)liblte_bits_2_value(ie_ptr, 2); // P0 Persistent if(sps_cnfg->sps_cnfg_ul.p0_persistent_present) { // P0 Nominal PUSCH Persistent - sps_cnfg->sps_cnfg_ul.p0_nominal_pusch = rrc_bits_2_value(ie_ptr, 8) - 126; + sps_cnfg->sps_cnfg_ul.p0_nominal_pusch = liblte_bits_2_value(ie_ptr, 8) - 126; // P0 UE PUSCH Persistent - sps_cnfg->sps_cnfg_ul.p0_ue_pusch = rrc_bits_2_value(ie_ptr, 4) - 8; + sps_cnfg->sps_cnfg_ul.p0_ue_pusch = liblte_bits_2_value(ie_ptr, 4) - 8; } // Two Intervals Config if(sps_cnfg->sps_cnfg_ul.two_intervals_cnfg_present) { - sps_cnfg->sps_cnfg_ul.two_intervals_cnfg = (LIBLTE_RRC_TWO_INTERVALS_CONFIG_ENUM)rrc_bits_2_value(ie_ptr, 1); + sps_cnfg->sps_cnfg_ul.two_intervals_cnfg = (LIBLTE_RRC_TWO_INTERVALS_CONFIG_ENUM)liblte_bits_2_value(ie_ptr, 1); } + + skip_sequence_type_extension(ul_ext_ind, ie_ptr); } } @@ -6001,34 +8619,32 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sps_config_ie(uint8 * Document Reference: 36.331 v10.0.0 Section 6.3.2 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_rrc_pack_tdd_config_ie(LIBLTE_RRC_SUBFRAME_ASSIGNMENT_ENUM sa, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_ENUM ssp, - uint8 **ie_ptr) +LIBLTE_ERROR_ENUM liblte_rrc_pack_tdd_config_ie(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd_cnfg, + uint8 **ie_ptr) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL) + if(tdd_cnfg != NULL && + ie_ptr != NULL) { - rrc_value_2_bits(sa, ie_ptr, 3); - rrc_value_2_bits(ssp, ie_ptr, 4); + liblte_value_2_bits(tdd_cnfg->sf_assignment, ie_ptr, 3); + liblte_value_2_bits(tdd_cnfg->special_sf_patterns, ie_ptr, 4); err = LIBLTE_SUCCESS; } return(err); } -LIBLTE_ERROR_ENUM liblte_rrc_unpack_tdd_config_ie(uint8 **ie_ptr, - LIBLTE_RRC_SUBFRAME_ASSIGNMENT_ENUM *sa, - LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_ENUM *ssp) +LIBLTE_ERROR_ENUM liblte_rrc_unpack_tdd_config_ie(uint8 **ie_ptr, + LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd_cnfg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - if(ie_ptr != NULL && - sa != NULL && - ssp != NULL) + if(ie_ptr != NULL && + tdd_cnfg != NULL) { - *sa = (LIBLTE_RRC_SUBFRAME_ASSIGNMENT_ENUM)rrc_bits_2_value(ie_ptr, 3); - *ssp = (LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_ENUM)rrc_bits_2_value(ie_ptr, 4); + tdd_cnfg->sf_assignment = (LIBLTE_RRC_SUBFRAME_ASSIGNMENT_ENUM)liblte_bits_2_value(ie_ptr, 3); + tdd_cnfg->special_sf_patterns = (LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_ENUM)liblte_bits_2_value(ie_ptr, 4); err = LIBLTE_SUCCESS; } @@ -6051,7 +8667,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_time_alignment_timer_ie(LIBLTE_RRC_TIME_ALIGNM if(ie_ptr != NULL) { - rrc_value_2_bits(time_alignment_timer, ie_ptr, 3); + liblte_value_2_bits(time_alignment_timer, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -6066,7 +8682,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_time_alignment_timer_ie(uint8 if(ie_ptr != NULL && time_alignment_timer != NULL) { - *time_alignment_timer = (LIBLTE_RRC_TIME_ALIGNMENT_TIMER_ENUM)rrc_bits_2_value(ie_ptr, 3); + *time_alignment_timer = (LIBLTE_RRC_TIME_ALIGNMENT_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -6091,19 +8707,19 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_tpc_pdcch_config_ie(LIBLTE_RRC_TPC_PDCCH_CONFI ie_ptr != NULL) { // Setup - rrc_value_2_bits(tpc_pdcch_cnfg->setup_present, ie_ptr, 1); + liblte_value_2_bits(tpc_pdcch_cnfg->setup_present, ie_ptr, 1); if(tpc_pdcch_cnfg->setup_present) { // TPC RNTI - rrc_value_2_bits(tpc_pdcch_cnfg->tpc_rnti, ie_ptr, 16); + liblte_value_2_bits(tpc_pdcch_cnfg->tpc_rnti, ie_ptr, 16); // TPC Index - rrc_value_2_bits(tpc_pdcch_cnfg->tpc_idx_choice, ie_ptr, 1); + liblte_value_2_bits(tpc_pdcch_cnfg->tpc_idx_choice, ie_ptr, 1); if(LIBLTE_RRC_TPC_INDEX_FORMAT_3 == tpc_pdcch_cnfg->tpc_idx_choice) { - rrc_value_2_bits(tpc_pdcch_cnfg->tpc_idx - 1, ie_ptr, 4); + liblte_value_2_bits(tpc_pdcch_cnfg->tpc_idx - 1, ie_ptr, 4); }else{ - rrc_value_2_bits(tpc_pdcch_cnfg->tpc_idx - 1, ie_ptr, 5); + liblte_value_2_bits(tpc_pdcch_cnfg->tpc_idx - 1, ie_ptr, 5); } } @@ -6121,19 +8737,19 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_tpc_pdcch_config_ie(uint8 tpc_pdcch_cnfg != NULL) { // Setup - tpc_pdcch_cnfg->setup_present = rrc_bits_2_value(ie_ptr, 1); + tpc_pdcch_cnfg->setup_present = liblte_bits_2_value(ie_ptr, 1); if(tpc_pdcch_cnfg->setup_present) { // TPC RNTI - tpc_pdcch_cnfg->tpc_rnti = rrc_bits_2_value(ie_ptr, 16); + tpc_pdcch_cnfg->tpc_rnti = liblte_bits_2_value(ie_ptr, 16); // TPC Index - tpc_pdcch_cnfg->tpc_idx_choice = (LIBLTE_RRC_TPC_INDEX_ENUM)rrc_bits_2_value(ie_ptr, 1); + tpc_pdcch_cnfg->tpc_idx_choice = (LIBLTE_RRC_TPC_INDEX_ENUM)liblte_bits_2_value(ie_ptr, 1); if(LIBLTE_RRC_TPC_INDEX_FORMAT_3 == tpc_pdcch_cnfg->tpc_idx_choice) { - tpc_pdcch_cnfg->tpc_idx = rrc_bits_2_value(ie_ptr, 4) + 1; + tpc_pdcch_cnfg->tpc_idx = liblte_bits_2_value(ie_ptr, 4) + 1; }else{ - tpc_pdcch_cnfg->tpc_idx = rrc_bits_2_value(ie_ptr, 5) + 1; + tpc_pdcch_cnfg->tpc_idx = liblte_bits_2_value(ie_ptr, 5) + 1; } } @@ -6159,10 +8775,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_antenna_info_ie(LIBLTE_RRC_UL_ANTENNA_INFO_ ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(ul_ant_info->ul_tx_mode, ie_ptr, 3); - rrc_value_2_bits(ul_ant_info->four_ant_port_activated, ie_ptr, 1); + liblte_value_2_bits(ul_ant_info->ul_tx_mode, ie_ptr, 3); + liblte_value_2_bits(ul_ant_info->four_ant_port_activated, ie_ptr, 1); err = LIBLTE_SUCCESS; } @@ -6173,15 +8789,18 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_antenna_info_ie(uint8 LIBLTE_RRC_UL_ANTENNA_INFO_STRUCT *ul_ant_info) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + bool ext_ind; if(ie_ptr != NULL && ul_ant_info != NULL) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + ext_ind = liblte_bits_2_value(ie_ptr, 1); - ul_ant_info->ul_tx_mode = (LIBLTE_RRC_UL_TRANSMISSION_MODE_R10_ENUM)rrc_bits_2_value(ie_ptr, 3); - ul_ant_info->four_ant_port_activated = rrc_bits_2_value(ie_ptr, 1); + ul_ant_info->ul_tx_mode = (LIBLTE_RRC_UL_TRANSMISSION_MODE_R10_ENUM)liblte_bits_2_value(ie_ptr, 3); + ul_ant_info->four_ant_port_activated = liblte_bits_2_value(ie_ptr, 1); + + skip_sequence_type_extension(ext_ind, ie_ptr); err = LIBLTE_SUCCESS; } @@ -6206,18 +8825,18 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_power_control_common_ie(LIBLTE_RRC_UL_POWER if(ul_pwr_ctrl != NULL && ie_ptr != NULL) { - rrc_value_2_bits(ul_pwr_ctrl->p0_nominal_pusch + 126, ie_ptr, 8); - rrc_value_2_bits(ul_pwr_ctrl->alpha, ie_ptr, 3); - rrc_value_2_bits(ul_pwr_ctrl->p0_nominal_pucch + 127, ie_ptr, 5); + liblte_value_2_bits(ul_pwr_ctrl->p0_nominal_pusch + 126, ie_ptr, 8); + liblte_value_2_bits(ul_pwr_ctrl->alpha, ie_ptr, 3); + liblte_value_2_bits(ul_pwr_ctrl->p0_nominal_pucch + 127, ie_ptr, 5); // Delta F List - rrc_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_1, ie_ptr, 2); - rrc_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_1b, ie_ptr, 2); - rrc_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_2, ie_ptr, 2); - rrc_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_2a, ie_ptr, 2); - rrc_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_2b, ie_ptr, 2); + liblte_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_1, ie_ptr, 2); + liblte_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_1b, ie_ptr, 2); + liblte_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_2, ie_ptr, 2); + liblte_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_2a, ie_ptr, 2); + liblte_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_2b, ie_ptr, 2); - rrc_value_2_bits((ul_pwr_ctrl->delta_preamble_msg3 / 2) + 1, ie_ptr, 3); + liblte_value_2_bits((ul_pwr_ctrl->delta_preamble_msg3 / 2) + 1, ie_ptr, 3); err = LIBLTE_SUCCESS; } @@ -6232,18 +8851,18 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_power_control_common_ie(uint8 if(ie_ptr != NULL && ul_pwr_ctrl != NULL) { - ul_pwr_ctrl->p0_nominal_pusch = rrc_bits_2_value(ie_ptr, 8) - 126; - ul_pwr_ctrl->alpha = (LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_ENUM)rrc_bits_2_value(ie_ptr, 3); - ul_pwr_ctrl->p0_nominal_pucch = rrc_bits_2_value(ie_ptr, 5) - 127; + ul_pwr_ctrl->p0_nominal_pusch = liblte_bits_2_value(ie_ptr, 8) - 126; + ul_pwr_ctrl->alpha = (LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_ENUM)liblte_bits_2_value(ie_ptr, 3); + ul_pwr_ctrl->p0_nominal_pucch = liblte_bits_2_value(ie_ptr, 5) - 127; // Delta F List - ul_pwr_ctrl->delta_flist_pucch.format_1 = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_ENUM)rrc_bits_2_value(ie_ptr, 2); - ul_pwr_ctrl->delta_flist_pucch.format_1b = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_ENUM)rrc_bits_2_value(ie_ptr, 2); - ul_pwr_ctrl->delta_flist_pucch.format_2 = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_ENUM)rrc_bits_2_value(ie_ptr, 2); - ul_pwr_ctrl->delta_flist_pucch.format_2a = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_ENUM)rrc_bits_2_value(ie_ptr, 2); - ul_pwr_ctrl->delta_flist_pucch.format_2b = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_ENUM)rrc_bits_2_value(ie_ptr, 2); + ul_pwr_ctrl->delta_flist_pucch.format_1 = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_ENUM)liblte_bits_2_value(ie_ptr, 2); + ul_pwr_ctrl->delta_flist_pucch.format_1b = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_ENUM)liblte_bits_2_value(ie_ptr, 2); + ul_pwr_ctrl->delta_flist_pucch.format_2 = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_ENUM)liblte_bits_2_value(ie_ptr, 2); + ul_pwr_ctrl->delta_flist_pucch.format_2a = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_ENUM)liblte_bits_2_value(ie_ptr, 2); + ul_pwr_ctrl->delta_flist_pucch.format_2b = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_ENUM)liblte_bits_2_value(ie_ptr, 2); - ul_pwr_ctrl->delta_preamble_msg3 = (rrc_bits_2_value(ie_ptr, 3) - 1) * 2; + ul_pwr_ctrl->delta_preamble_msg3 = (liblte_bits_2_value(ie_ptr, 3) - 1) * 2; err = LIBLTE_SUCCESS; } @@ -6258,23 +8877,29 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_power_control_dedicated_ie(LIBLTE_RRC_UL_PO if(ul_pwr_ctrl != NULL && ie_ptr != NULL) { + // Default indicators + liblte_value_2_bits(ul_pwr_ctrl->filter_coeff_present, ie_ptr, 1); + // P0 UE PUSCH - rrc_value_2_bits(ul_pwr_ctrl->p0_ue_pusch + 8, ie_ptr, 4); + liblte_value_2_bits(ul_pwr_ctrl->p0_ue_pusch + 8, ie_ptr, 4); // Delta MCS Enabled - rrc_value_2_bits(ul_pwr_ctrl->delta_mcs_en, ie_ptr, 1); + liblte_value_2_bits(ul_pwr_ctrl->delta_mcs_en, ie_ptr, 1); // Accumulation Enabled - rrc_value_2_bits(ul_pwr_ctrl->accumulation_en, ie_ptr, 1); + liblte_value_2_bits(ul_pwr_ctrl->accumulation_en, ie_ptr, 1); // P0 UE PUCCH - rrc_value_2_bits(ul_pwr_ctrl->p0_ue_pucch + 8, ie_ptr, 4); + liblte_value_2_bits(ul_pwr_ctrl->p0_ue_pucch + 8, ie_ptr, 4); // P SRS Offset - rrc_value_2_bits(ul_pwr_ctrl->p_srs_offset, ie_ptr, 4); + liblte_value_2_bits(ul_pwr_ctrl->p_srs_offset, ie_ptr, 4); // Filter Coefficient - liblte_rrc_pack_filter_coefficient_ie(ul_pwr_ctrl->filter_coeff, ie_ptr); + if(ul_pwr_ctrl->filter_coeff_present) + { + liblte_rrc_pack_filter_coefficient_ie(ul_pwr_ctrl->filter_coeff, ie_ptr); + } err = LIBLTE_SUCCESS; } @@ -6289,23 +8914,29 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_power_control_dedicated_ie(uint8 if(ie_ptr != NULL && ul_pwr_ctrl != NULL) { + // Default indicators + ul_pwr_ctrl->filter_coeff_present = liblte_bits_2_value(ie_ptr, 1); + // P0 UE PUSCH - ul_pwr_ctrl->p0_ue_pusch = rrc_bits_2_value(ie_ptr, 4) - 8; + ul_pwr_ctrl->p0_ue_pusch = liblte_bits_2_value(ie_ptr, 4) - 8; // Delta MCS Enabled - ul_pwr_ctrl->delta_mcs_en = (LIBLTE_RRC_DELTA_MCS_ENABLED_ENUM)rrc_bits_2_value(ie_ptr, 1); + ul_pwr_ctrl->delta_mcs_en = (LIBLTE_RRC_DELTA_MCS_ENABLED_ENUM)liblte_bits_2_value(ie_ptr, 1); // Accumulation Enabled - ul_pwr_ctrl->accumulation_en = rrc_bits_2_value(ie_ptr, 1); + ul_pwr_ctrl->accumulation_en = liblte_bits_2_value(ie_ptr, 1); // P0 UE PUCCH - ul_pwr_ctrl->p0_ue_pucch = rrc_bits_2_value(ie_ptr, 4) - 8; + ul_pwr_ctrl->p0_ue_pucch = liblte_bits_2_value(ie_ptr, 4) - 8; // P SRS Offset - ul_pwr_ctrl->p_srs_offset = rrc_bits_2_value(ie_ptr, 4); + ul_pwr_ctrl->p_srs_offset = liblte_bits_2_value(ie_ptr, 4); // Filter Coefficient - liblte_rrc_unpack_filter_coefficient_ie(ie_ptr, &ul_pwr_ctrl->filter_coeff); + if(ul_pwr_ctrl->filter_coeff_present) + { + liblte_rrc_unpack_filter_coefficient_ie(ie_ptr, &ul_pwr_ctrl->filter_coeff); + } err = LIBLTE_SUCCESS; } @@ -6332,42 +8963,42 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_2_ie(LIBLTE_RRC_SYS_INFO_B ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicators - rrc_value_2_bits(sib2->ac_barring_info_present, ie_ptr, 1); + liblte_value_2_bits(sib2->ac_barring_info_present, ie_ptr, 1); if(0 != sib2->mbsfn_subfr_cnfg_list_size) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); mbsfn_subfr_cnfg_list_opt = true; }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); mbsfn_subfr_cnfg_list_opt = false; } // AC Barring if(true == sib2->ac_barring_info_present) { - rrc_value_2_bits(sib2->ac_barring_for_mo_signalling.enabled, ie_ptr, 1); - rrc_value_2_bits(sib2->ac_barring_for_mo_data.enabled, ie_ptr, 1); + liblte_value_2_bits(sib2->ac_barring_for_mo_signalling.enabled, ie_ptr, 1); + liblte_value_2_bits(sib2->ac_barring_for_mo_data.enabled, ie_ptr, 1); // AC Barring for emergency - rrc_value_2_bits(sib2->ac_barring_for_emergency, ie_ptr, 1); + liblte_value_2_bits(sib2->ac_barring_for_emergency, ie_ptr, 1); // AC Barring for MO signalling if(true == sib2->ac_barring_for_mo_signalling.enabled) { - rrc_value_2_bits(sib2->ac_barring_for_mo_signalling.factor, ie_ptr, 4); - rrc_value_2_bits(sib2->ac_barring_for_mo_signalling.time, ie_ptr, 3); - rrc_value_2_bits(sib2->ac_barring_for_mo_signalling.for_special_ac, ie_ptr, 5); + liblte_value_2_bits(sib2->ac_barring_for_mo_signalling.factor, ie_ptr, 4); + liblte_value_2_bits(sib2->ac_barring_for_mo_signalling.time, ie_ptr, 3); + liblte_value_2_bits(sib2->ac_barring_for_mo_signalling.for_special_ac, ie_ptr, 5); } // AC Barring for MO data if(true == sib2->ac_barring_for_mo_data.enabled) { - rrc_value_2_bits(sib2->ac_barring_for_mo_data.factor, ie_ptr, 4); - rrc_value_2_bits(sib2->ac_barring_for_mo_data.time, ie_ptr, 3); - rrc_value_2_bits(sib2->ac_barring_for_mo_data.for_special_ac, ie_ptr, 5); + liblte_value_2_bits(sib2->ac_barring_for_mo_data.factor, ie_ptr, 4); + liblte_value_2_bits(sib2->ac_barring_for_mo_data.time, ie_ptr, 3); + liblte_value_2_bits(sib2->ac_barring_for_mo_data.for_special_ac, ie_ptr, 5); } } @@ -6380,8 +9011,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_2_ie(LIBLTE_RRC_SYS_INFO_B // Frequency information { // Optional indicators - rrc_value_2_bits(sib2->arfcn_value_eutra.present, ie_ptr, 1); - rrc_value_2_bits(sib2->ul_bw.present, ie_ptr, 1); + liblte_value_2_bits(sib2->arfcn_value_eutra.present, ie_ptr, 1); + liblte_value_2_bits(sib2->ul_bw.present, ie_ptr, 1); // UL Carrier Frequency if(true == sib2->arfcn_value_eutra.present) @@ -6392,7 +9023,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_2_ie(LIBLTE_RRC_SYS_INFO_B // UL Bandwidth if(true == sib2->ul_bw.present) { - rrc_value_2_bits(sib2->ul_bw.bw, ie_ptr, 3); + liblte_value_2_bits(sib2->ul_bw.bw, ie_ptr, 3); } // Additional Spectrum Emission @@ -6403,7 +9034,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_2_ie(LIBLTE_RRC_SYS_INFO_B // MBSFN Subframe Config List if(true == mbsfn_subfr_cnfg_list_opt) { - rrc_value_2_bits(sib2->mbsfn_subfr_cnfg_list_size - 1, ie_ptr, 3); + liblte_value_2_bits(sib2->mbsfn_subfr_cnfg_list_size - 1, ie_ptr, 3); for(i=0; imbsfn_subfr_cnfg_list_size; i++) { liblte_rrc_pack_mbsfn_subframe_config_ie(&sib2->mbsfn_subfr_cnfg[i], ie_ptr); @@ -6413,8 +9044,6 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_2_ie(LIBLTE_RRC_SYS_INFO_B // Time Alignment Timer Common liblte_rrc_pack_time_alignment_timer_ie(sib2->time_alignment_timer, ie_ptr); - // FIXME: Not handling extensions - err = LIBLTE_SUCCESS; } @@ -6432,36 +9061,36 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_2_ie(uint8 sib2 != NULL) { // Extension indicator - ext_ind = rrc_bits_2_value(ie_ptr, 1); + ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - sib2->ac_barring_info_present = rrc_bits_2_value(ie_ptr, 1); - mbsfn_subfr_cnfg_list_opt = rrc_bits_2_value(ie_ptr, 1); + sib2->ac_barring_info_present = liblte_bits_2_value(ie_ptr, 1); + mbsfn_subfr_cnfg_list_opt = liblte_bits_2_value(ie_ptr, 1); // AC Barring if(true == sib2->ac_barring_info_present) { // Optional indicators - sib2->ac_barring_for_mo_signalling.enabled = rrc_bits_2_value(ie_ptr, 1); - sib2->ac_barring_for_mo_data.enabled = rrc_bits_2_value(ie_ptr, 1); + sib2->ac_barring_for_mo_signalling.enabled = liblte_bits_2_value(ie_ptr, 1); + sib2->ac_barring_for_mo_data.enabled = liblte_bits_2_value(ie_ptr, 1); // AC Barring for emergency - sib2->ac_barring_for_emergency = rrc_bits_2_value(ie_ptr, 1); + sib2->ac_barring_for_emergency = liblte_bits_2_value(ie_ptr, 1); // AC Barring for MO signalling if(true == sib2->ac_barring_for_mo_signalling.enabled) { - sib2->ac_barring_for_mo_signalling.factor = (LIBLTE_RRC_AC_BARRING_FACTOR_ENUM)rrc_bits_2_value(ie_ptr, 4); - sib2->ac_barring_for_mo_signalling.time = (LIBLTE_RRC_AC_BARRING_TIME_ENUM)rrc_bits_2_value(ie_ptr, 3); - sib2->ac_barring_for_mo_signalling.for_special_ac = rrc_bits_2_value(ie_ptr, 5); + sib2->ac_barring_for_mo_signalling.factor = (LIBLTE_RRC_AC_BARRING_FACTOR_ENUM)liblte_bits_2_value(ie_ptr, 4); + sib2->ac_barring_for_mo_signalling.time = (LIBLTE_RRC_AC_BARRING_TIME_ENUM)liblte_bits_2_value(ie_ptr, 3); + sib2->ac_barring_for_mo_signalling.for_special_ac = liblte_bits_2_value(ie_ptr, 5); } // AC Barring for MO data if(true == sib2->ac_barring_for_mo_data.enabled) { - sib2->ac_barring_for_mo_data.factor = (LIBLTE_RRC_AC_BARRING_FACTOR_ENUM)rrc_bits_2_value(ie_ptr, 4); - sib2->ac_barring_for_mo_data.time = (LIBLTE_RRC_AC_BARRING_TIME_ENUM)rrc_bits_2_value(ie_ptr, 3); - sib2->ac_barring_for_mo_data.for_special_ac = rrc_bits_2_value(ie_ptr, 5); + sib2->ac_barring_for_mo_data.factor = (LIBLTE_RRC_AC_BARRING_FACTOR_ENUM)liblte_bits_2_value(ie_ptr, 4); + sib2->ac_barring_for_mo_data.time = (LIBLTE_RRC_AC_BARRING_TIME_ENUM)liblte_bits_2_value(ie_ptr, 3); + sib2->ac_barring_for_mo_data.for_special_ac = liblte_bits_2_value(ie_ptr, 5); } }else{ sib2->ac_barring_for_emergency = false; @@ -6478,8 +9107,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_2_ie(uint8 // Frequency information { // Optional indicators - sib2->arfcn_value_eutra.present = rrc_bits_2_value(ie_ptr, 1); - sib2->ul_bw.present = rrc_bits_2_value(ie_ptr, 1); + sib2->arfcn_value_eutra.present = liblte_bits_2_value(ie_ptr, 1); + sib2->ul_bw.present = liblte_bits_2_value(ie_ptr, 1); // UL Carrier Frequency if(true == sib2->arfcn_value_eutra.present) @@ -6490,7 +9119,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_2_ie(uint8 // UL Bandwidth if(true == sib2->ul_bw.present) { - sib2->ul_bw.bw = (LIBLTE_RRC_UL_BW_ENUM)rrc_bits_2_value(ie_ptr, 3); + sib2->ul_bw.bw = (LIBLTE_RRC_UL_BW_ENUM)liblte_bits_2_value(ie_ptr, 3); } // Additional Spectrum Emission @@ -6501,7 +9130,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_2_ie(uint8 // MBSFN Subframe Config List if(true == mbsfn_subfr_cnfg_list_opt) { - sib2->mbsfn_subfr_cnfg_list_size = rrc_bits_2_value(ie_ptr, 3) + 1; + sib2->mbsfn_subfr_cnfg_list_size = liblte_bits_2_value(ie_ptr, 3) + 1; for(i=0; imbsfn_subfr_cnfg_list_size; i++) { liblte_rrc_unpack_mbsfn_subframe_config_ie(ie_ptr, &sib2->mbsfn_subfr_cnfg[i]); @@ -6513,11 +9142,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_2_ie(uint8 // Time Alignment Timer Common liblte_rrc_unpack_time_alignment_timer_ie(ie_ptr, &sib2->time_alignment_timer); - // Extensions - if(true == ext_ind) - { - // FIXME - } + skip_sequence_type_extension(ext_ind, ie_ptr); err = LIBLTE_SUCCESS; } @@ -6545,29 +9170,29 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_3_ie(LIBLTE_RRC_SYS_INFO_B ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Cell reselection info common { // Optional indicator - rrc_value_2_bits(sib3->speed_state_resel_params.present, ie_ptr, 1); + liblte_value_2_bits(sib3->speed_state_resel_params.present, ie_ptr, 1); - rrc_value_2_bits(sib3->q_hyst, ie_ptr, 4); + liblte_value_2_bits(sib3->q_hyst, ie_ptr, 4); // Speed state reselection parameters if(true == sib3->speed_state_resel_params.present) { liblte_rrc_pack_mobility_state_parameters_ie(&sib3->speed_state_resel_params.mobility_state_params, ie_ptr); - rrc_value_2_bits(sib3->speed_state_resel_params.q_hyst_sf.medium, ie_ptr, 2); - rrc_value_2_bits(sib3->speed_state_resel_params.q_hyst_sf.high, ie_ptr, 2); + liblte_value_2_bits(sib3->speed_state_resel_params.q_hyst_sf.medium, ie_ptr, 2); + liblte_value_2_bits(sib3->speed_state_resel_params.q_hyst_sf.high, ie_ptr, 2); } } // Cell reselection serving frequency information { // Optional indicators - rrc_value_2_bits(sib3->s_non_intra_search_present, ie_ptr, 1); + liblte_value_2_bits(sib3->s_non_intra_search_present, ie_ptr, 1); if(true == sib3->s_non_intra_search_present) { @@ -6582,10 +9207,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_3_ie(LIBLTE_RRC_SYS_INFO_B // Intra frequency cell reselection information { // Optional indicators - rrc_value_2_bits(sib3->p_max_present, ie_ptr, 1); - rrc_value_2_bits(sib3->s_intra_search_present, ie_ptr, 1); - rrc_value_2_bits(sib3->allowed_meas_bw_present, ie_ptr, 1); - rrc_value_2_bits(sib3->t_resel_eutra_sf_present, ie_ptr, 1); + liblte_value_2_bits(sib3->p_max_present, ie_ptr, 1); + liblte_value_2_bits(sib3->s_intra_search_present, ie_ptr, 1); + liblte_value_2_bits(sib3->allowed_meas_bw_present, ie_ptr, 1); + liblte_value_2_bits(sib3->t_resel_eutra_sf_present, ie_ptr, 1); liblte_rrc_pack_q_rx_lev_min_ie(sib3->q_rx_lev_min, ie_ptr); @@ -6631,29 +9256,29 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_3_ie(uint8 sib3 != NULL) { // Extension indicator - ext_ind = rrc_bits_2_value(ie_ptr, 1); + ext_ind = liblte_bits_2_value(ie_ptr, 1); // Cell reselection info common { // Optional indicator - sib3->speed_state_resel_params.present = rrc_bits_2_value(ie_ptr, 1); + sib3->speed_state_resel_params.present = liblte_bits_2_value(ie_ptr, 1); - sib3->q_hyst = (LIBLTE_RRC_Q_HYST_ENUM)rrc_bits_2_value(ie_ptr, 4); + sib3->q_hyst = (LIBLTE_RRC_Q_HYST_ENUM)liblte_bits_2_value(ie_ptr, 4); // Speed state reselection parameters if(true == sib3->speed_state_resel_params.present) { liblte_rrc_unpack_mobility_state_parameters_ie(ie_ptr, &sib3->speed_state_resel_params.mobility_state_params); - sib3->speed_state_resel_params.q_hyst_sf.medium = (LIBLTE_RRC_SF_MEDIUM_ENUM)rrc_bits_2_value(ie_ptr, 2); - sib3->speed_state_resel_params.q_hyst_sf.high = (LIBLTE_RRC_SF_HIGH_ENUM)rrc_bits_2_value(ie_ptr, 2); + sib3->speed_state_resel_params.q_hyst_sf.medium = (LIBLTE_RRC_SF_MEDIUM_ENUM)liblte_bits_2_value(ie_ptr, 2); + sib3->speed_state_resel_params.q_hyst_sf.high = (LIBLTE_RRC_SF_HIGH_ENUM)liblte_bits_2_value(ie_ptr, 2); } } // Cell reselection serving frequency information { // Optional indicators - sib3->s_non_intra_search_present = rrc_bits_2_value(ie_ptr, 1); + sib3->s_non_intra_search_present = liblte_bits_2_value(ie_ptr, 1); if(true == sib3->s_non_intra_search_present) { @@ -6668,10 +9293,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_3_ie(uint8 // Intra frequency cell reselection information { // Optional indicators - sib3->p_max_present = rrc_bits_2_value(ie_ptr, 1); - sib3->s_intra_search_present = rrc_bits_2_value(ie_ptr, 1); - sib3->allowed_meas_bw_present = rrc_bits_2_value(ie_ptr, 1); - sib3->t_resel_eutra_sf_present = rrc_bits_2_value(ie_ptr, 1); + sib3->p_max_present = liblte_bits_2_value(ie_ptr, 1); + sib3->s_intra_search_present = liblte_bits_2_value(ie_ptr, 1); + sib3->allowed_meas_bw_present = liblte_bits_2_value(ie_ptr, 1); + sib3->t_resel_eutra_sf_present = liblte_bits_2_value(ie_ptr, 1); liblte_rrc_unpack_q_rx_lev_min_ie(ie_ptr, &sib3->q_rx_lev_min); @@ -6702,11 +9327,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_3_ie(uint8 } } - // Extensions - if(true == ext_ind) - { - // FIXME - } + skip_sequence_type_extension(ext_ind, ie_ptr); err = LIBLTE_SUCCESS; } @@ -6732,30 +9353,30 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_4_ie(LIBLTE_RRC_SYS_INFO_B ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicators if(0 != sib4->intra_freq_neigh_cell_list_size) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } if(0 != sib4->intra_freq_black_cell_list_size) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } - rrc_value_2_bits(sib4->csg_phys_cell_id_range_present, ie_ptr, 1); + liblte_value_2_bits(sib4->csg_phys_cell_id_range_present, ie_ptr, 1); if(0 != sib4->intra_freq_neigh_cell_list_size) { - rrc_value_2_bits(sib4->intra_freq_neigh_cell_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(sib4->intra_freq_neigh_cell_list_size - 1, ie_ptr, 4); for(i=0; iintra_freq_neigh_cell_list_size; i++) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); liblte_rrc_pack_phys_cell_id_ie(sib4->intra_freq_neigh_cell_list[i].phys_cell_id, ie_ptr); liblte_rrc_pack_q_offset_range_ie(sib4->intra_freq_neigh_cell_list[i].q_offset_range, ie_ptr); @@ -6764,7 +9385,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_4_ie(LIBLTE_RRC_SYS_INFO_B if(0 != sib4->intra_freq_black_cell_list_size) { - rrc_value_2_bits(sib4->intra_freq_black_cell_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(sib4->intra_freq_black_cell_list_size - 1, ie_ptr, 4); for(i=0; iintra_freq_black_cell_list_size; i++) { liblte_rrc_pack_phys_cell_id_range_ie(&sib4->intra_freq_black_cell_list[i], ie_ptr); @@ -6786,31 +9407,34 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_4_ie(uint8 { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; - bool ext_ind; + bool sib4_ext_ind; bool intra_freq_neigh_cell_list_opt; + bool intra_freq_neigh_cell_ext_ind; bool intra_freq_black_cell_list_opt; if(ie_ptr != NULL && sib4 != NULL) { // Extension indicator - ext_ind = rrc_bits_2_value(ie_ptr, 1); + sib4_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - intra_freq_neigh_cell_list_opt = rrc_bits_2_value(ie_ptr, 1); - intra_freq_black_cell_list_opt = rrc_bits_2_value(ie_ptr, 1); - sib4->csg_phys_cell_id_range_present = rrc_bits_2_value(ie_ptr, 1); + intra_freq_neigh_cell_list_opt = liblte_bits_2_value(ie_ptr, 1); + intra_freq_black_cell_list_opt = liblte_bits_2_value(ie_ptr, 1); + sib4->csg_phys_cell_id_range_present = liblte_bits_2_value(ie_ptr, 1); if(true == intra_freq_neigh_cell_list_opt) { - sib4->intra_freq_neigh_cell_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + sib4->intra_freq_neigh_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(i=0; iintra_freq_neigh_cell_list_size; i++) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + intra_freq_neigh_cell_ext_ind = liblte_bits_2_value(ie_ptr, 1); liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &sib4->intra_freq_neigh_cell_list[i].phys_cell_id); liblte_rrc_unpack_q_offset_range_ie(ie_ptr, &sib4->intra_freq_neigh_cell_list[i].q_offset_range); + + skip_sequence_type_extension(intra_freq_neigh_cell_ext_ind, ie_ptr); } }else{ sib4->intra_freq_neigh_cell_list_size = 0; @@ -6818,7 +9442,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_4_ie(uint8 if(true == intra_freq_black_cell_list_opt) { - sib4->intra_freq_black_cell_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + sib4->intra_freq_black_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(i=0; iintra_freq_black_cell_list_size; i++) { liblte_rrc_unpack_phys_cell_id_range_ie(ie_ptr, &sib4->intra_freq_black_cell_list[i]); @@ -6832,11 +9456,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_4_ie(uint8 liblte_rrc_unpack_phys_cell_id_range_ie(ie_ptr, &sib4->csg_phys_cell_id_range); } - // Extension - if(true == ext_ind) - { - // FIXME - } + skip_sequence_type_extension(sib4_ext_ind, ie_ptr); err = LIBLTE_SUCCESS; } @@ -6865,29 +9485,29 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_5_ie(LIBLTE_RRC_SYS_INFO_B ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); - rrc_value_2_bits(sib5->inter_freq_carrier_freq_list_size - 1, ie_ptr, 3); + liblte_value_2_bits(sib5->inter_freq_carrier_freq_list_size - 1, ie_ptr, 3); for(i=0; iinter_freq_carrier_freq_list_size; i++) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicators - rrc_value_2_bits(sib5->inter_freq_carrier_freq_list[i].p_max_present, ie_ptr, 1); - rrc_value_2_bits(sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf_present, ie_ptr, 1); - rrc_value_2_bits(sib5->inter_freq_carrier_freq_list[i].cell_resel_prio_present, ie_ptr, 1); + liblte_value_2_bits(sib5->inter_freq_carrier_freq_list[i].p_max_present, ie_ptr, 1); + liblte_value_2_bits(sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf_present, ie_ptr, 1); + liblte_value_2_bits(sib5->inter_freq_carrier_freq_list[i].cell_resel_prio_present, ie_ptr, 1); if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } liblte_rrc_pack_arfcn_value_eutra_ie(sib5->inter_freq_carrier_freq_list[i].dl_carrier_freq, ie_ptr); @@ -6913,7 +9533,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_5_ie(LIBLTE_RRC_SYS_INFO_B liblte_rrc_pack_q_offset_range_ie(sib5->inter_freq_carrier_freq_list[i].q_offset_freq, ie_ptr); if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size) { - rrc_value_2_bits(sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size - 1, ie_ptr, 4); for(j=0; jinter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size; j++) { liblte_rrc_pack_phys_cell_id_ie(sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list[j].phys_cell_id, ie_ptr); @@ -6922,7 +9542,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_5_ie(LIBLTE_RRC_SYS_INFO_B } if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size) { - rrc_value_2_bits(sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size - 1, ie_ptr, 4); for(j=0; jinter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size; j++) { liblte_rrc_pack_phys_cell_id_range_ie(&sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list[j], ie_ptr); @@ -6941,7 +9561,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_5_ie(uint8 LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; uint32 j; - bool ext_ind; + bool sib5_ext_ind; bool inter_freq_carrier_freq_list_ext_ind; bool q_offset_freq_opt; bool inter_freq_neigh_cell_list_opt; @@ -6951,21 +9571,21 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_5_ie(uint8 sib5 != NULL) { // Extension indicator - ext_ind = rrc_bits_2_value(ie_ptr, 1); + sib5_ext_ind = liblte_bits_2_value(ie_ptr, 1); - sib5->inter_freq_carrier_freq_list_size = rrc_bits_2_value(ie_ptr, 3) + 1; + sib5->inter_freq_carrier_freq_list_size = liblte_bits_2_value(ie_ptr, 3) + 1; for(i=0; iinter_freq_carrier_freq_list_size; i++) { // Extension indicator - inter_freq_carrier_freq_list_ext_ind = rrc_bits_2_value(ie_ptr, 1); + inter_freq_carrier_freq_list_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - sib5->inter_freq_carrier_freq_list[i].p_max_present = rrc_bits_2_value(ie_ptr, 1); - sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf_present = rrc_bits_2_value(ie_ptr, 1); - sib5->inter_freq_carrier_freq_list[i].cell_resel_prio_present = rrc_bits_2_value(ie_ptr, 1); - q_offset_freq_opt = rrc_bits_2_value(ie_ptr, 1); - inter_freq_neigh_cell_list_opt = rrc_bits_2_value(ie_ptr, 1); - inter_freq_black_cell_list_opt = rrc_bits_2_value(ie_ptr, 1); + sib5->inter_freq_carrier_freq_list[i].p_max_present = liblte_bits_2_value(ie_ptr, 1); + sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf_present = liblte_bits_2_value(ie_ptr, 1); + sib5->inter_freq_carrier_freq_list[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1); + q_offset_freq_opt = liblte_bits_2_value(ie_ptr, 1); + inter_freq_neigh_cell_list_opt = liblte_bits_2_value(ie_ptr, 1); + inter_freq_black_cell_list_opt = liblte_bits_2_value(ie_ptr, 1); liblte_rrc_unpack_arfcn_value_eutra_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].dl_carrier_freq); liblte_rrc_unpack_q_rx_lev_min_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].q_rx_lev_min); @@ -6995,7 +9615,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_5_ie(uint8 } if(true == inter_freq_neigh_cell_list_opt) { - sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(j=0; jinter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size; j++) { liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list[j].phys_cell_id); @@ -7006,7 +9626,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_5_ie(uint8 } if(true == inter_freq_black_cell_list_opt) { - sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(j=0; jinter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size; j++) { liblte_rrc_unpack_phys_cell_id_range_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list[j]); @@ -7014,8 +9634,12 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_5_ie(uint8 }else{ sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size = 0; } + + skip_sequence_type_extension(inter_freq_carrier_freq_list_ext_ind, ie_ptr); } + skip_sequence_type_extension(sib5_ext_ind, ie_ptr); + err = LIBLTE_SUCCESS; } @@ -7042,33 +9666,33 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_6_ie(LIBLTE_RRC_SYS_INFO_B ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicators if(0 != sib6->carrier_freq_list_utra_fdd_size) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } if(0 != sib6->carrier_freq_list_utra_tdd_size) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } - rrc_value_2_bits(sib6->t_resel_utra_sf_present, ie_ptr, 1); + liblte_value_2_bits(sib6->t_resel_utra_sf_present, ie_ptr, 1); if(0 != sib6->carrier_freq_list_utra_fdd_size) { - rrc_value_2_bits(sib6->carrier_freq_list_utra_fdd_size - 1, ie_ptr, 4); + liblte_value_2_bits(sib6->carrier_freq_list_utra_fdd_size - 1, ie_ptr, 4); for(i=0; icarrier_freq_list_utra_fdd_size; i++) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicator - rrc_value_2_bits(sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present, ie_ptr, 1); + liblte_value_2_bits(sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present, ie_ptr, 1); liblte_rrc_pack_arfcn_value_utra_ie(sib6->carrier_freq_list_utra_fdd[i].carrier_freq, ie_ptr); if(true == sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present) @@ -7077,21 +9701,21 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_6_ie(LIBLTE_RRC_SYS_INFO_B } liblte_rrc_pack_reselection_threshold_ie(sib6->carrier_freq_list_utra_fdd[i].threshx_high, ie_ptr); liblte_rrc_pack_reselection_threshold_ie(sib6->carrier_freq_list_utra_fdd[i].threshx_low, ie_ptr); - rrc_value_2_bits(((sib6->carrier_freq_list_utra_fdd[i].q_rx_lev_min - 1) / 2) + 60, ie_ptr, 6); - rrc_value_2_bits(sib6->carrier_freq_list_utra_fdd[i].p_max_utra + 50, ie_ptr, 7); - rrc_value_2_bits(sib6->carrier_freq_list_utra_fdd[i].q_qual_min + 24, ie_ptr, 5); + liblte_value_2_bits(((sib6->carrier_freq_list_utra_fdd[i].q_rx_lev_min - 1) / 2) + 60, ie_ptr, 6); + liblte_value_2_bits(sib6->carrier_freq_list_utra_fdd[i].p_max_utra + 50, ie_ptr, 7); + liblte_value_2_bits(sib6->carrier_freq_list_utra_fdd[i].q_qual_min + 24, ie_ptr, 5); } } if(0 != sib6->carrier_freq_list_utra_tdd_size) { - rrc_value_2_bits(sib6->carrier_freq_list_utra_tdd_size - 1, ie_ptr, 4); + liblte_value_2_bits(sib6->carrier_freq_list_utra_tdd_size - 1, ie_ptr, 4); for(i=0; icarrier_freq_list_utra_tdd_size; i++) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicator - rrc_value_2_bits(sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present, ie_ptr, 1); + liblte_value_2_bits(sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present, ie_ptr, 1); liblte_rrc_pack_arfcn_value_utra_ie(sib6->carrier_freq_list_utra_tdd[i].carrier_freq, ie_ptr); if(true == sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present) @@ -7100,8 +9724,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_6_ie(LIBLTE_RRC_SYS_INFO_B } liblte_rrc_pack_reselection_threshold_ie(sib6->carrier_freq_list_utra_tdd[i].threshx_high, ie_ptr); liblte_rrc_pack_reselection_threshold_ie(sib6->carrier_freq_list_utra_tdd[i].threshx_low, ie_ptr); - rrc_value_2_bits(((sib6->carrier_freq_list_utra_tdd[i].q_rx_lev_min - 1) / 2) + 60, ie_ptr, 6); - rrc_value_2_bits(sib6->carrier_freq_list_utra_tdd[i].p_max_utra + 50, ie_ptr, 7); + liblte_value_2_bits(((sib6->carrier_freq_list_utra_tdd[i].q_rx_lev_min - 1) / 2) + 60, ie_ptr, 6); + liblte_value_2_bits(sib6->carrier_freq_list_utra_tdd[i].p_max_utra + 50, ie_ptr, 7); } } liblte_rrc_pack_t_reselection_ie(sib6->t_resel_utra, ie_ptr); @@ -7120,7 +9744,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_6_ie(uint8 { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; - bool ext_ind; + bool sib6_ext_ind; bool carrier_freq_list_utra_fdd_opt; bool carrier_freq_list_utra_fdd_ext_ind; bool carrier_freq_list_utra_tdd_opt; @@ -7130,23 +9754,23 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_6_ie(uint8 sib6 != NULL) { // Extension indicator - ext_ind = rrc_bits_2_value(ie_ptr, 1); + sib6_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - carrier_freq_list_utra_fdd_opt = rrc_bits_2_value(ie_ptr, 1); - carrier_freq_list_utra_tdd_opt = rrc_bits_2_value(ie_ptr, 1); - sib6->t_resel_utra_sf_present = rrc_bits_2_value(ie_ptr, 1); + carrier_freq_list_utra_fdd_opt = liblte_bits_2_value(ie_ptr, 1); + carrier_freq_list_utra_tdd_opt = liblte_bits_2_value(ie_ptr, 1); + sib6->t_resel_utra_sf_present = liblte_bits_2_value(ie_ptr, 1); if(true == carrier_freq_list_utra_fdd_opt) { - sib6->carrier_freq_list_utra_fdd_size = rrc_bits_2_value(ie_ptr, 4) + 1; + sib6->carrier_freq_list_utra_fdd_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(i=0; icarrier_freq_list_utra_fdd_size; i++) { // Extension indicator - carrier_freq_list_utra_fdd_ext_ind = rrc_bits_2_value(ie_ptr, 1); + carrier_freq_list_utra_fdd_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicator - sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present = rrc_bits_2_value(ie_ptr, 1); + sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1); liblte_rrc_unpack_arfcn_value_utra_ie(ie_ptr, &sib6->carrier_freq_list_utra_fdd[i].carrier_freq); if(true == sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present) @@ -7155,23 +9779,25 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_6_ie(uint8 } liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib6->carrier_freq_list_utra_fdd[i].threshx_high); liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib6->carrier_freq_list_utra_fdd[i].threshx_low); - sib6->carrier_freq_list_utra_fdd[i].q_rx_lev_min = (int8)((rrc_bits_2_value(ie_ptr, 6) - 60) * 2) + 1; - sib6->carrier_freq_list_utra_fdd[i].p_max_utra = (int8)rrc_bits_2_value(ie_ptr, 7) - 50; - sib6->carrier_freq_list_utra_fdd[i].q_qual_min = (int8)rrc_bits_2_value(ie_ptr, 5) - 24; + sib6->carrier_freq_list_utra_fdd[i].q_rx_lev_min = (int8)((liblte_bits_2_value(ie_ptr, 6) - 60) * 2) + 1; + sib6->carrier_freq_list_utra_fdd[i].p_max_utra = (int8)liblte_bits_2_value(ie_ptr, 7) - 50; + sib6->carrier_freq_list_utra_fdd[i].q_qual_min = (int8)liblte_bits_2_value(ie_ptr, 5) - 24; + + skip_sequence_type_extension(carrier_freq_list_utra_fdd_ext_ind, ie_ptr); } }else{ sib6->carrier_freq_list_utra_fdd_size = 0; } if(true == carrier_freq_list_utra_tdd_opt) { - sib6->carrier_freq_list_utra_tdd_size = rrc_bits_2_value(ie_ptr, 4) + 1; + sib6->carrier_freq_list_utra_tdd_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(i=0; icarrier_freq_list_utra_tdd_size; i++) { // Extension indicator - carrier_freq_list_utra_tdd_ext_ind = rrc_bits_2_value(ie_ptr, 1); + carrier_freq_list_utra_tdd_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicator - sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present = rrc_bits_2_value(ie_ptr, 1); + sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1); liblte_rrc_unpack_arfcn_value_utra_ie(ie_ptr, &sib6->carrier_freq_list_utra_tdd[i].carrier_freq); if(true == sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present) @@ -7180,8 +9806,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_6_ie(uint8 } liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib6->carrier_freq_list_utra_tdd[i].threshx_high); liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib6->carrier_freq_list_utra_tdd[i].threshx_low); - sib6->carrier_freq_list_utra_tdd[i].q_rx_lev_min = (int8)((rrc_bits_2_value(ie_ptr, 6) * 2) + 1) - 60; - sib6->carrier_freq_list_utra_tdd[i].p_max_utra = (int8)rrc_bits_2_value(ie_ptr, 7) - 50; + sib6->carrier_freq_list_utra_tdd[i].q_rx_lev_min = (int8)((liblte_bits_2_value(ie_ptr, 6) * 2) + 1) - 60; + sib6->carrier_freq_list_utra_tdd[i].p_max_utra = (int8)liblte_bits_2_value(ie_ptr, 7) - 50; + + skip_sequence_type_extension(carrier_freq_list_utra_tdd_ext_ind, ie_ptr); } }else{ sib6->carrier_freq_list_utra_tdd_size = 0; @@ -7191,6 +9819,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_6_ie(uint8 { liblte_rrc_unpack_speed_state_scale_factors_ie(ie_ptr, &sib6->t_resel_utra_sf); } + + skip_sequence_type_extension(sib6_ext_ind, ie_ptr); + err = LIBLTE_SUCCESS; } @@ -7216,15 +9847,15 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_7_ie(LIBLTE_RRC_SYS_INFO_B ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicators - rrc_value_2_bits(sib7->t_resel_geran_sf_present, ie_ptr, 1); + liblte_value_2_bits(sib7->t_resel_geran_sf_present, ie_ptr, 1); if(0 != sib7->carrier_freqs_info_list_size) { - rrc_value_2_bits(1, ie_ptr, 1); + liblte_value_2_bits(1, ie_ptr, 1); }else{ - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); } liblte_rrc_pack_t_reselection_ie(sib7->t_resel_geran, ie_ptr); @@ -7234,29 +9865,29 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_7_ie(LIBLTE_RRC_SYS_INFO_B } if(0 != sib7->carrier_freqs_info_list_size) { - rrc_value_2_bits(sib7->carrier_freqs_info_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(sib7->carrier_freqs_info_list_size - 1, ie_ptr, 4); for(i=0; icarrier_freqs_info_list_size; i++) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); liblte_rrc_pack_carrier_freqs_geran_ie(&sib7->carrier_freqs_info_list[i].carrier_freqs, ie_ptr); // Common Info { // Optional indicators - rrc_value_2_bits(sib7->carrier_freqs_info_list[i].cell_resel_prio_present, ie_ptr, 1); - rrc_value_2_bits(sib7->carrier_freqs_info_list[i].p_max_geran_present, ie_ptr, 1); + liblte_value_2_bits(sib7->carrier_freqs_info_list[i].cell_resel_prio_present, ie_ptr, 1); + liblte_value_2_bits(sib7->carrier_freqs_info_list[i].p_max_geran_present, ie_ptr, 1); if(true == sib7->carrier_freqs_info_list[i].cell_resel_prio_present) { liblte_rrc_pack_cell_reselection_priority_ie(sib7->carrier_freqs_info_list[i].cell_resel_prio, ie_ptr); } - rrc_value_2_bits(sib7->carrier_freqs_info_list[i].ncc_permitted, ie_ptr, 8); - rrc_value_2_bits((sib7->carrier_freqs_info_list[i].q_rx_lev_min + 115) / 2, ie_ptr, 6); + liblte_value_2_bits(sib7->carrier_freqs_info_list[i].ncc_permitted, ie_ptr, 8); + liblte_value_2_bits((sib7->carrier_freqs_info_list[i].q_rx_lev_min + 115) / 2, ie_ptr, 6); if(true == sib7->carrier_freqs_info_list[i].p_max_geran_present) { - rrc_value_2_bits(sib7->carrier_freqs_info_list[i].p_max_geran, ie_ptr, 6); + liblte_value_2_bits(sib7->carrier_freqs_info_list[i].p_max_geran, ie_ptr, 6); } liblte_rrc_pack_reselection_threshold_ie(sib7->carrier_freqs_info_list[i].threshx_high, ie_ptr); liblte_rrc_pack_reselection_threshold_ie(sib7->carrier_freqs_info_list[i].threshx_low, ie_ptr); @@ -7274,7 +9905,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_7_ie(uint8 { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint32 i; - bool ext_ind; + bool sib7_ext_ind; bool carrier_freqs_info_list_opt; bool carrier_freqs_info_list_ext_ind; @@ -7282,11 +9913,11 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_7_ie(uint8 sib7 != NULL) { // Extension indicator - ext_ind = rrc_bits_2_value(ie_ptr, 1); + sib7_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - sib7->t_resel_geran_sf_present = rrc_bits_2_value(ie_ptr, 1); - carrier_freqs_info_list_opt = rrc_bits_2_value(ie_ptr, 1); + sib7->t_resel_geran_sf_present = liblte_bits_2_value(ie_ptr, 1); + carrier_freqs_info_list_opt = liblte_bits_2_value(ie_ptr, 1); liblte_rrc_unpack_t_reselection_ie(ie_ptr, &sib7->t_resel_geran); if(true == sib7->t_resel_geran_sf_present) @@ -7295,38 +9926,42 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_7_ie(uint8 } if(true == carrier_freqs_info_list_opt) { - sib7->carrier_freqs_info_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + sib7->carrier_freqs_info_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(i=0; icarrier_freqs_info_list_size; i++) { // Extension indicator - carrier_freqs_info_list_ext_ind = rrc_bits_2_value(ie_ptr, 1); + carrier_freqs_info_list_ext_ind = liblte_bits_2_value(ie_ptr, 1); liblte_rrc_unpack_carrier_freqs_geran_ie(ie_ptr, &sib7->carrier_freqs_info_list[i].carrier_freqs); // Common Info { // Optional indicators - sib7->carrier_freqs_info_list[i].cell_resel_prio_present = rrc_bits_2_value(ie_ptr, 1); - sib7->carrier_freqs_info_list[i].p_max_geran_present = rrc_bits_2_value(ie_ptr, 1); + sib7->carrier_freqs_info_list[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1); + sib7->carrier_freqs_info_list[i].p_max_geran_present = liblte_bits_2_value(ie_ptr, 1); if(true == sib7->carrier_freqs_info_list[i].cell_resel_prio_present) { liblte_rrc_unpack_cell_reselection_priority_ie(ie_ptr, &sib7->carrier_freqs_info_list[i].cell_resel_prio); } - sib7->carrier_freqs_info_list[i].ncc_permitted = rrc_bits_2_value(ie_ptr, 8); - sib7->carrier_freqs_info_list[i].q_rx_lev_min = (rrc_bits_2_value(ie_ptr, 6) * 2) - 115; + sib7->carrier_freqs_info_list[i].ncc_permitted = liblte_bits_2_value(ie_ptr, 8); + sib7->carrier_freqs_info_list[i].q_rx_lev_min = (liblte_bits_2_value(ie_ptr, 6) * 2) - 115; if(true == sib7->carrier_freqs_info_list[i].p_max_geran_present) { - sib7->carrier_freqs_info_list[i].p_max_geran = rrc_bits_2_value(ie_ptr, 6); + sib7->carrier_freqs_info_list[i].p_max_geran = liblte_bits_2_value(ie_ptr, 6); } liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib7->carrier_freqs_info_list[i].threshx_high); liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib7->carrier_freqs_info_list[i].threshx_low); } + + skip_sequence_type_extension(carrier_freqs_info_list_ext_ind, ie_ptr); } }else{ sib7->carrier_freqs_info_list_size = 0; } + skip_sequence_type_extension(sib7_ext_ind, ie_ptr); + err = LIBLTE_SUCCESS; } @@ -7356,13 +9991,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_8_ie(LIBLTE_RRC_SYS_INFO_B ie_ptr != NULL) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicators - rrc_value_2_bits(sib8->sys_time_info_present, ie_ptr, 1); - rrc_value_2_bits(sib8->search_win_size_present, ie_ptr, 1); - rrc_value_2_bits(sib8->params_hrpd_present, ie_ptr, 1); - rrc_value_2_bits(sib8->params_1xrtt_present, ie_ptr, 1); + liblte_value_2_bits(sib8->sys_time_info_present, ie_ptr, 1); + liblte_value_2_bits(sib8->search_win_size_present, ie_ptr, 1); + liblte_value_2_bits(sib8->params_hrpd_present, ie_ptr, 1); + liblte_value_2_bits(sib8->params_1xrtt_present, ie_ptr, 1); if(true == sib8->sys_time_info_present) { @@ -7371,49 +10006,49 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_8_ie(LIBLTE_RRC_SYS_INFO_B if(true == sib8->search_win_size_present) { - rrc_value_2_bits(sib8->search_win_size, ie_ptr, 4); + liblte_value_2_bits(sib8->search_win_size, ie_ptr, 4); } if(true == sib8->params_hrpd_present) { // Optional indicator - rrc_value_2_bits(sib8->cell_resel_params_hrpd_present, ie_ptr, 1); + liblte_value_2_bits(sib8->cell_resel_params_hrpd_present, ie_ptr, 1); liblte_rrc_pack_pre_registration_info_hrpd_ie(&sib8->pre_reg_info_hrpd, ie_ptr); if(true == sib8->cell_resel_params_hrpd_present) { // Optional indicator - rrc_value_2_bits(sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf_present, ie_ptr, 1); + liblte_value_2_bits(sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf_present, ie_ptr, 1); - rrc_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list_size - 1, ie_ptr, 5); + liblte_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list_size - 1, ie_ptr, 5); for(i=0; icell_resel_params_hrpd.band_class_list_size; i++) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicator - rrc_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present, ie_ptr, 1); + liblte_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present, ie_ptr, 1); liblte_rrc_pack_band_class_cdma2000_ie(sib8->cell_resel_params_hrpd.band_class_list[i].band_class, ie_ptr); if(true == sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present) { liblte_rrc_pack_cell_reselection_priority_ie(sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio, ie_ptr); } - rrc_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_high, ie_ptr, 6); - rrc_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_low, ie_ptr, 6); + liblte_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_high, ie_ptr, 6); + liblte_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_low, ie_ptr, 6); } - rrc_value_2_bits(sib8->cell_resel_params_hrpd.neigh_cell_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(sib8->cell_resel_params_hrpd.neigh_cell_list_size - 1, ie_ptr, 4); for(i=0; icell_resel_params_hrpd.neigh_cell_list_size; i++) { neigh_cell_list = &sib8->cell_resel_params_hrpd.neigh_cell_list[i]; liblte_rrc_pack_band_class_cdma2000_ie(neigh_cell_list->band_class, ie_ptr); - rrc_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list_size - 1, ie_ptr, 4); for(j=0; jneigh_cells_per_freq_list_size; j++) { liblte_rrc_pack_arfcn_value_cdma2000_ie(neigh_cell_list->neigh_cells_per_freq_list[j].arfcn, ie_ptr); - rrc_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size - 1, ie_ptr, 4); for(k=0; kneigh_cells_per_freq_list[j].phys_cell_id_list_size; k++) { liblte_rrc_pack_phys_cell_id_cdma2000_ie(neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list[k], ie_ptr); @@ -7432,9 +10067,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_8_ie(LIBLTE_RRC_SYS_INFO_B if(true == sib8->params_1xrtt_present) { // Optional indicators - rrc_value_2_bits(sib8->csfb_reg_param_1xrtt_present, ie_ptr, 1); - rrc_value_2_bits(sib8->long_code_state_1xrtt_present, ie_ptr, 1); - rrc_value_2_bits(sib8->cell_resel_params_1xrtt_present, ie_ptr, 1); + liblte_value_2_bits(sib8->csfb_reg_param_1xrtt_present, ie_ptr, 1); + liblte_value_2_bits(sib8->long_code_state_1xrtt_present, ie_ptr, 1); + liblte_value_2_bits(sib8->cell_resel_params_1xrtt_present, ie_ptr, 1); if(true == sib8->csfb_reg_param_1xrtt_present) { @@ -7443,43 +10078,43 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_8_ie(LIBLTE_RRC_SYS_INFO_B if(true == sib8->long_code_state_1xrtt_present) { - rrc_value_2_bits((uint32)(sib8->long_code_state_1xrtt >> 10), ie_ptr, 32); - rrc_value_2_bits((uint32)(sib8->long_code_state_1xrtt & 0x3FF), ie_ptr, 10); + liblte_value_2_bits((uint32)(sib8->long_code_state_1xrtt >> 10), ie_ptr, 32); + liblte_value_2_bits((uint32)(sib8->long_code_state_1xrtt & 0x3FF), ie_ptr, 10); } if(true == sib8->cell_resel_params_1xrtt_present) { // Optional indicator - rrc_value_2_bits(sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf_present, ie_ptr, 1); + liblte_value_2_bits(sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf_present, ie_ptr, 1); - rrc_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list_size - 1, ie_ptr, 5); + liblte_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list_size - 1, ie_ptr, 5); for(i=0; icell_resel_params_1xrtt.band_class_list_size; i++) { // Extension indicator - rrc_value_2_bits(0, ie_ptr, 1); + liblte_value_2_bits(0, ie_ptr, 1); // Optional indicator - rrc_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present, ie_ptr, 1); + liblte_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present, ie_ptr, 1); liblte_rrc_pack_band_class_cdma2000_ie(sib8->cell_resel_params_1xrtt.band_class_list[i].band_class, ie_ptr); if(true == sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present) { liblte_rrc_pack_cell_reselection_priority_ie(sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio, ie_ptr); } - rrc_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_high, ie_ptr, 6); - rrc_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_low, ie_ptr, 6); + liblte_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_high, ie_ptr, 6); + liblte_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_low, ie_ptr, 6); } - rrc_value_2_bits(sib8->cell_resel_params_1xrtt.neigh_cell_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(sib8->cell_resel_params_1xrtt.neigh_cell_list_size - 1, ie_ptr, 4); for(i=0; icell_resel_params_1xrtt.neigh_cell_list_size; i++) { neigh_cell_list = &sib8->cell_resel_params_1xrtt.neigh_cell_list[i]; liblte_rrc_pack_band_class_cdma2000_ie(neigh_cell_list->band_class, ie_ptr); - rrc_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list_size - 1, ie_ptr, 4); for(j=0; jneigh_cells_per_freq_list_size; j++) { liblte_rrc_pack_arfcn_value_cdma2000_ie(neigh_cell_list->neigh_cells_per_freq_list[j].arfcn, ie_ptr); - rrc_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size - 1, ie_ptr, 4); + liblte_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size - 1, ie_ptr, 4); for(k=0; kneigh_cells_per_freq_list[j].phys_cell_id_list_size; k++) { liblte_rrc_pack_phys_cell_id_cdma2000_ie(neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list[k], ie_ptr); @@ -7508,19 +10143,21 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_8_ie(uint8 uint32 i; uint32 j; uint32 k; - bool ext_ind; + bool sib8_ext_ind; + bool hrpd_band_class_info_ext_ind; + bool onexrtt_band_class_info_ext_ind; if(ie_ptr != NULL && sib8 != NULL) { // Extension indicator - ext_ind = rrc_bits_2_value(ie_ptr, 1); + sib8_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicators - sib8->sys_time_info_present = rrc_bits_2_value(ie_ptr, 1); - sib8->search_win_size_present = rrc_bits_2_value(ie_ptr, 1); - sib8->params_hrpd_present = rrc_bits_2_value(ie_ptr, 1); - sib8->params_1xrtt_present = rrc_bits_2_value(ie_ptr, 1); + sib8->sys_time_info_present = liblte_bits_2_value(ie_ptr, 1); + sib8->search_win_size_present = liblte_bits_2_value(ie_ptr, 1); + sib8->params_hrpd_present = liblte_bits_2_value(ie_ptr, 1); + sib8->params_1xrtt_present = liblte_bits_2_value(ie_ptr, 1); if(true == sib8->sys_time_info_present) { @@ -7529,49 +10166,51 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_8_ie(uint8 if(true == sib8->search_win_size_present) { - sib8->search_win_size = rrc_bits_2_value(ie_ptr, 4); + sib8->search_win_size = liblte_bits_2_value(ie_ptr, 4); } if(true == sib8->params_hrpd_present) { // Optional indicator - sib8->cell_resel_params_hrpd_present = rrc_bits_2_value(ie_ptr, 1); + sib8->cell_resel_params_hrpd_present = liblte_bits_2_value(ie_ptr, 1); liblte_rrc_unpack_pre_registration_info_hrpd_ie(ie_ptr, &sib8->pre_reg_info_hrpd); if(true == sib8->cell_resel_params_hrpd_present) { // Optional indicator - sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf_present = rrc_bits_2_value(ie_ptr, 1); + sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf_present = liblte_bits_2_value(ie_ptr, 1); - sib8->cell_resel_params_hrpd.band_class_list_size = rrc_bits_2_value(ie_ptr, 5) + 1; + sib8->cell_resel_params_hrpd.band_class_list_size = liblte_bits_2_value(ie_ptr, 5) + 1; for(i=0; icell_resel_params_hrpd.band_class_list_size; i++) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + hrpd_band_class_info_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicator - sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present = rrc_bits_2_value(ie_ptr, 1); + sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1); liblte_rrc_unpack_band_class_cdma2000_ie(ie_ptr, &sib8->cell_resel_params_hrpd.band_class_list[i].band_class); if(true == sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present) { liblte_rrc_unpack_cell_reselection_priority_ie(ie_ptr, &sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio); } - sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_high = rrc_bits_2_value(ie_ptr, 6); - sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_low = rrc_bits_2_value(ie_ptr, 6); + sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_high = liblte_bits_2_value(ie_ptr, 6); + sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_low = liblte_bits_2_value(ie_ptr, 6); + + skip_sequence_type_extension(hrpd_band_class_info_ext_ind, ie_ptr); } - sib8->cell_resel_params_hrpd.neigh_cell_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + sib8->cell_resel_params_hrpd.neigh_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(i=0; icell_resel_params_hrpd.neigh_cell_list_size; i++) { neigh_cell_list = &sib8->cell_resel_params_hrpd.neigh_cell_list[i]; liblte_rrc_unpack_band_class_cdma2000_ie(ie_ptr, &neigh_cell_list->band_class); - neigh_cell_list->neigh_cells_per_freq_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + neigh_cell_list->neigh_cells_per_freq_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(j=0; jneigh_cells_per_freq_list_size; j++) { liblte_rrc_unpack_arfcn_value_cdma2000_ie(ie_ptr, &neigh_cell_list->neigh_cells_per_freq_list[j].arfcn); - neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(k=0; kneigh_cells_per_freq_list[j].phys_cell_id_list_size; k++) { liblte_rrc_unpack_phys_cell_id_cdma2000_ie(ie_ptr, &neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list[k]); @@ -7592,9 +10231,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_8_ie(uint8 if(true == sib8->params_1xrtt_present) { // Optional indicators - sib8->csfb_reg_param_1xrtt_present = rrc_bits_2_value(ie_ptr, 1); - sib8->long_code_state_1xrtt_present = rrc_bits_2_value(ie_ptr, 1); - sib8->cell_resel_params_1xrtt_present = rrc_bits_2_value(ie_ptr, 1); + sib8->csfb_reg_param_1xrtt_present = liblte_bits_2_value(ie_ptr, 1); + sib8->long_code_state_1xrtt_present = liblte_bits_2_value(ie_ptr, 1); + sib8->cell_resel_params_1xrtt_present = liblte_bits_2_value(ie_ptr, 1); if(true == sib8->csfb_reg_param_1xrtt_present) { @@ -7603,43 +10242,45 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_8_ie(uint8 if(true == sib8->long_code_state_1xrtt_present) { - sib8->long_code_state_1xrtt = (uint64)rrc_bits_2_value(ie_ptr, 32) << 10; - sib8->long_code_state_1xrtt |= (uint64)rrc_bits_2_value(ie_ptr, 10); + sib8->long_code_state_1xrtt = (uint64)liblte_bits_2_value(ie_ptr, 32) << 10; + sib8->long_code_state_1xrtt |= (uint64)liblte_bits_2_value(ie_ptr, 10); } if(true == sib8->cell_resel_params_1xrtt_present) { // Optional indicator - sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf_present = rrc_bits_2_value(ie_ptr, 1); + sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf_present = liblte_bits_2_value(ie_ptr, 1); - sib8->cell_resel_params_1xrtt.band_class_list_size = rrc_bits_2_value(ie_ptr, 5) + 1; + sib8->cell_resel_params_1xrtt.band_class_list_size = liblte_bits_2_value(ie_ptr, 5) + 1; for(i=0; icell_resel_params_1xrtt.band_class_list_size; i++) { // Extension indicator - rrc_bits_2_value(ie_ptr, 1); + onexrtt_band_class_info_ext_ind = liblte_bits_2_value(ie_ptr, 1); // Optional indicator - sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present = rrc_bits_2_value(ie_ptr, 1); + sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1); liblte_rrc_unpack_band_class_cdma2000_ie(ie_ptr, &sib8->cell_resel_params_1xrtt.band_class_list[i].band_class); if(true == sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present) { liblte_rrc_unpack_cell_reselection_priority_ie(ie_ptr, &sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio); } - sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_high = rrc_bits_2_value(ie_ptr, 6); - sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_low = rrc_bits_2_value(ie_ptr, 6); + sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_high = liblte_bits_2_value(ie_ptr, 6); + sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_low = liblte_bits_2_value(ie_ptr, 6); + + skip_sequence_type_extension(onexrtt_band_class_info_ext_ind, ie_ptr); } - sib8->cell_resel_params_1xrtt.neigh_cell_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + sib8->cell_resel_params_1xrtt.neigh_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(i=0; icell_resel_params_1xrtt.neigh_cell_list_size; i++) { neigh_cell_list = &sib8->cell_resel_params_1xrtt.neigh_cell_list[i]; liblte_rrc_unpack_band_class_cdma2000_ie(ie_ptr, &neigh_cell_list->band_class); - neigh_cell_list->neigh_cells_per_freq_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + neigh_cell_list->neigh_cells_per_freq_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(j=0; jneigh_cells_per_freq_list_size; j++) { liblte_rrc_unpack_arfcn_value_cdma2000_ie(ie_ptr, &neigh_cell_list->neigh_cells_per_freq_list[j].arfcn); - neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size = rrc_bits_2_value(ie_ptr, 4) + 1; + neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size = liblte_bits_2_value(ie_ptr, 4) + 1; for(k=0; kneigh_cells_per_freq_list[j].phys_cell_id_list_size; k++) { liblte_rrc_unpack_phys_cell_id_cdma2000_ie(ie_ptr, &neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list[k]); @@ -7659,6 +10300,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_8_ie(uint8 sib8->cell_resel_params_1xrtt_present = false; } + skip_sequence_type_extension(sib8_ext_ind, ie_ptr); + err = LIBLTE_SUCCESS; } @@ -7710,7 +10353,68 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_8_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.3.1 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_13_ie(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + + if(sib13 != NULL && + ie_ptr != NULL) + { + // Extension indicator + liblte_value_2_bits(0, ie_ptr, 1); + + // Optional indicators + liblte_value_2_bits(0, ie_ptr, 1); + + liblte_value_2_bits(sib13->mbsfn_area_info_list_r9_size - 1, ie_ptr, 3); + for(i=0; imbsfn_area_info_list_r9_size; i++) + { + liblte_rrc_pack_mbsfn_area_info_ie(&sib13->mbsfn_area_info_list_r9[i], ie_ptr); + } + liblte_rrc_pack_mbsfn_notification_config_ie(&sib13->mbms_notification_config, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_13_ie(uint8 **ie_ptr, + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + bool ext_ind; + + if(ie_ptr != NULL && + sib13 != NULL) + { + // Extension indicator + ext_ind = liblte_bits_2_value(ie_ptr, 1); + + // Optional indicators + sib13->non_crit_ext_present = liblte_bits_2_value(ie_ptr, 1); + + sib13->mbsfn_area_info_list_r9_size = liblte_bits_2_value(ie_ptr, 3) + 1; + for(i=0; imbsfn_area_info_list_r9_size; i++) + { + liblte_rrc_unpack_mbsfn_area_info_ie(ie_ptr, &sib13->mbsfn_area_info_list_r9[i]); + } + liblte_rrc_unpack_mbsfn_notification_config_ie(ie_ptr, &sib13->mbms_notification_config); + + if(sib13->non_crit_ext_present) + { + liblte_rrc_unpack_octet_string_ie(ie_ptr, &sib13->non_crit_ext); + } + + skip_sequence_type_extension(ext_ind, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /******************************************************************************* MESSAGE FUNCTIONS @@ -7724,57 +10428,323 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_8_ie(uint8 Document Reference: 36.331 v10.0.0 Section 6.2.2 *********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_information_transfer_msg(LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT *ul_info_transfer, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(ul_info_transfer != NULL && + msg != NULL) + { + // Extension choice + liblte_value_2_bits(0, &msg_ptr, 1); + + // C1 choice + liblte_value_2_bits(0, &msg_ptr, 2); + + // Optional indicator + liblte_value_2_bits(0, &msg_ptr, 1); + + // Dedicated info type choice + liblte_value_2_bits(ul_info_transfer->dedicated_info_type, &msg_ptr, 2); + + if(LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_NAS == ul_info_transfer->dedicated_info_type) + { + liblte_rrc_pack_dedicated_info_nas_ie(&ul_info_transfer->dedicated_info, + &msg_ptr); + }else{ + liblte_rrc_pack_dedicated_info_cdma2000_ie(&ul_info_transfer->dedicated_info, + &msg_ptr); + } + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_information_transfer_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT *ul_info_transfer) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + ul_info_transfer != NULL) + { + // Extension choice + liblte_bits_2_value(&msg_ptr, 1); + + // C1 choice + liblte_bits_2_value(&msg_ptr, 2); + + // Optional indicator + liblte_bits_2_value(&msg_ptr, 1); + + // Dedicated info type choice + ul_info_transfer->dedicated_info_type = (LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 2); + + if(LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_NAS == ul_info_transfer->dedicated_info_type) + { + liblte_rrc_unpack_dedicated_info_nas_ie(&msg_ptr, + &ul_info_transfer->dedicated_info); + }else{ + liblte_rrc_unpack_dedicated_info_cdma2000_ie(&msg_ptr, + &ul_info_transfer->dedicated_info); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: UL Handover Preparation Transfer (CDMA2000) + + Description: Used for the uplink transfer of handover related + CDMA2000 information when requested by the higher + layers + + Document Reference: 36.331 v10.0.0 Section 6.2.2 +*********************************************************************/ +// FIXME + +/********************************************************************* + Message Name: UE Information Response + + Description: Used by the UE to transfer the information requested + by the E-UTRAN + + Document Reference: 36.331 v10.0.0 Section 6.2.2 +*********************************************************************/ // FIXME /********************************************************************* - Message Name: UL Handover Preparation Transfer (CDMA2000) + Message Name: UE Information Request + + Description: Used by E-UTRAN to retrieve information from the UE + + Document Reference: 36.331 v10.0.0 Section 6.2.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_information_request_msg(LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT *ue_info_req, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(ue_info_req != NULL && + msg != NULL) + { + // RRC Transaction ID + liblte_rrc_pack_rrc_transaction_identifier_ie(ue_info_req->rrc_transaction_id, + &msg_ptr); + + // Extension choice + liblte_value_2_bits(0, &msg_ptr, 1); + + // C1 choice + liblte_value_2_bits(0, &msg_ptr, 2); + + // Optional indicator + liblte_value_2_bits(0, &msg_ptr, 1); + + // RACH report required + liblte_value_2_bits(ue_info_req->rach_report_req, &msg_ptr, 1); + + // RLF report required + liblte_value_2_bits(ue_info_req->rlf_report_req, &msg_ptr, 1); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_information_request_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT *ue_info_req) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + ue_info_req != NULL) + { + // RRC Transaction ID + liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, + &ue_info_req->rrc_transaction_id); + + // Extension choice + liblte_bits_2_value(&msg_ptr, 1); + + // C1 choice + liblte_bits_2_value(&msg_ptr, 2); + + // Optional indicator + liblte_bits_2_value(&msg_ptr, 1); + + // RACH report required + ue_info_req->rach_report_req = liblte_bits_2_value(&msg_ptr, 1); + + // RLF report required + ue_info_req->rlf_report_req = liblte_bits_2_value(&msg_ptr, 1); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: UE Capability Information + + Description: Used to transfer UE radio access capabilities + requested by the E-UTRAN + + Document Reference: 36.331 v10.0.0 Section 6.2.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_capability_information_msg(LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *ue_capability_info, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(ue_capability_info != NULL && + msg != NULL) + { + // RRC Transaction ID + liblte_rrc_pack_rrc_transaction_identifier_ie(ue_capability_info->rrc_transaction_id, &msg_ptr); + + // Extension choice + liblte_value_2_bits(0, &msg_ptr, 1); + + // C1 choice + liblte_value_2_bits(0, &msg_ptr, 3); + + // Optional indicator + liblte_value_2_bits(0, &msg_ptr, 1); + + // ue-CapabilityRAT-ContainerList + liblte_rrc_pack_ue_capability_rat_container_list_ie(&ue_capability_info->ue_capability_rat_container_list, &msg_ptr); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_capability_information_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *ue_capability_info) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + ue_capability_info != NULL) + { + // RRC Transaction ID + liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, &ue_capability_info->rrc_transaction_id); + + // Extension choice + liblte_bits_2_value(&msg_ptr, 1); + + // C1 choice + liblte_bits_2_value(&msg_ptr, 3); + + // Optional indicator + liblte_bits_2_value(&msg_ptr, 1); + + // ue-CapabilityRAT-ContainerList + liblte_rrc_unpack_ue_capability_rat_container_list_ie(&msg_ptr, &ue_capability_info->ue_capability_rat_container_list); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Message Name: UE Capability Enquiry - Description: Used for the uplink transfer of handover related - CDMA2000 information when requested by the higher - layers + Description: Used to request the transfer of UE radio access + capabilities for E-UTRA as well as for other RATs Document Reference: 36.331 v10.0.0 Section 6.2.2 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_capability_enquiry_msg(LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT *ue_capability_enquiry, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint32 i; -/********************************************************************* - Message Name: UE Information Response + if(ue_capability_enquiry != NULL && + msg != NULL && + ue_capability_enquiry->rat_type_list_size >= 1 && + ue_capability_enquiry->rat_type_list_size <= LIBLTE_RRC_MAX_RAT_CAPABILITIES) + { + // RRC Transaction ID + liblte_rrc_pack_rrc_transaction_identifier_ie(ue_capability_enquiry->rrc_transaction_id, &msg_ptr); - Description: Used by the UE to transfer the information requested - by the E-UTRAN + // Extension choice + liblte_value_2_bits(0, &msg_ptr, 1); - Document Reference: 36.331 v10.0.0 Section 6.2.2 -*********************************************************************/ -// FIXME + // C1 choice + liblte_value_2_bits(0, &msg_ptr, 2); -/********************************************************************* - Message Name: UE Information Request + // RAT-Type sequence + liblte_value_2_bits(ue_capability_enquiry->rat_type_list_size - 1, &msg_ptr, 3); + for(i=0; irat_type_list_size; i++) + { + liblte_rrc_pack_rat_type_ie(ue_capability_enquiry->rat_type_list[i], &msg_ptr); + } - Description: Used by E-UTRAN to retrieve information from the UE + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; - Document Reference: 36.331 v10.0.0 Section 6.2.2 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } -/********************************************************************* - Message Name: UE Capability Information + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_capability_enquiry_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT *ue_capability_enquiry) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint32 i; - Description: Used to transfer UE radio access capabilities - requested by the E-UTRAN + if(msg != NULL && + ue_capability_enquiry != NULL) + { + // RRC Transaction ID + liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, &ue_capability_enquiry->rrc_transaction_id); - Document Reference: 36.331 v10.0.0 Section 6.2.2 -*********************************************************************/ -// FIXME + // Extension choice + liblte_bits_2_value(&msg_ptr, 1); -/********************************************************************* - Message Name: UE Capability Enquiry + // C1 choice + liblte_bits_2_value(&msg_ptr, 2); - Description: Used to request the transfer of UE radio access - capabilities for E-UTRA as well as for other RATs + // RAT-Type sequence + ue_capability_enquiry->rat_type_list_size = liblte_bits_2_value(&msg_ptr, 3) + 1; + for(i=0; irat_type_list_size; i++) + { + liblte_rrc_unpack_rat_type_ie(&msg_ptr, &ue_capability_enquiry->rat_type_list[i]); + } - Document Reference: 36.331 v10.0.0 Section 6.2.2 -*********************************************************************/ -// FIXME + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* Message Name: System Information Block Type 1 @@ -7801,34 +10771,34 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_1_msg(LIBLTE_RRC_SYS_INFO_ msg != NULL) { // Optional indicators - rrc_value_2_bits(sib1->p_max_present, &msg_ptr, 1); - rrc_value_2_bits(sib1->tdd, &msg_ptr, 1); - rrc_value_2_bits(non_crit_ext_opt, &msg_ptr, 1); + liblte_value_2_bits(sib1->p_max_present, &msg_ptr, 1); + liblte_value_2_bits(sib1->tdd, &msg_ptr, 1); + liblte_value_2_bits(non_crit_ext_opt, &msg_ptr, 1); // Cell Access Related Info - rrc_value_2_bits(csg_id_opt, &msg_ptr, 1); - rrc_value_2_bits(sib1->N_plmn_ids - 1, &msg_ptr, 3); + liblte_value_2_bits(csg_id_opt, &msg_ptr, 1); + liblte_value_2_bits(sib1->N_plmn_ids - 1, &msg_ptr, 3); for(i=0; iN_plmn_ids; i++) { liblte_rrc_pack_plmn_identity_ie(&sib1->plmn_id[i].id, &msg_ptr); - rrc_value_2_bits(sib1->plmn_id[i].resv_for_oper, &msg_ptr, 1); + liblte_value_2_bits(sib1->plmn_id[i].resv_for_oper, &msg_ptr, 1); } liblte_rrc_pack_tracking_area_code_ie(sib1->tracking_area_code, &msg_ptr); liblte_rrc_pack_cell_identity_ie(sib1->cell_id, &msg_ptr); - rrc_value_2_bits(sib1->cell_barred, &msg_ptr, 1); - rrc_value_2_bits(sib1->intra_freq_reselection, &msg_ptr, 1); - rrc_value_2_bits(sib1->csg_indication, &msg_ptr, 1); + liblte_value_2_bits(sib1->cell_barred, &msg_ptr, 1); + liblte_value_2_bits(sib1->intra_freq_reselection, &msg_ptr, 1); + liblte_value_2_bits(sib1->csg_indication, &msg_ptr, 1); if(true == csg_id_opt) { liblte_rrc_pack_csg_identity_ie(sib1->csg_id, &msg_ptr); } // Cell Selection Info - rrc_value_2_bits(q_rx_lev_min_offset_opt, &msg_ptr, 1); + liblte_value_2_bits(q_rx_lev_min_offset_opt, &msg_ptr, 1); liblte_rrc_pack_q_rx_lev_min_ie(sib1->q_rx_lev_min, &msg_ptr); if(true == q_rx_lev_min_offset_opt) { - rrc_value_2_bits((sib1->q_rx_lev_min_offset / 2) - 1, &msg_ptr, 3); + liblte_value_2_bits((sib1->q_rx_lev_min_offset / 2) - 1, &msg_ptr, 3); } // P Max @@ -7838,32 +10808,32 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_1_msg(LIBLTE_RRC_SYS_INFO_ } // Freq Band Indicator - rrc_value_2_bits(sib1->freq_band_indicator - 1, &msg_ptr, 6); + liblte_value_2_bits(sib1->freq_band_indicator - 1, &msg_ptr, 6); // Scheduling Info List - rrc_value_2_bits(sib1->N_sched_info - 1, &msg_ptr, 5); + liblte_value_2_bits(sib1->N_sched_info - 1, &msg_ptr, 5); for(i=0; iN_sched_info; i++) { - rrc_value_2_bits(sib1->sched_info[i].si_periodicity, &msg_ptr, 3); - rrc_value_2_bits(sib1->sched_info[i].N_sib_mapping_info, &msg_ptr, 5); + liblte_value_2_bits(sib1->sched_info[i].si_periodicity, &msg_ptr, 3); + liblte_value_2_bits(sib1->sched_info[i].N_sib_mapping_info, &msg_ptr, 5); for(j=0; jsched_info[i].N_sib_mapping_info; j++) { - rrc_value_2_bits(extension, &msg_ptr, 1); - rrc_value_2_bits(sib1->sched_info[i].sib_mapping_info[j].sib_type, &msg_ptr, 4); + liblte_value_2_bits(extension, &msg_ptr, 1); + liblte_value_2_bits(sib1->sched_info[i].sib_mapping_info[j].sib_type, &msg_ptr, 4); } } // TDD Config if(true == sib1->tdd) { - liblte_rrc_pack_tdd_config_ie(sib1->sf_assignment, sib1->special_sf_patterns, &msg_ptr); + liblte_rrc_pack_tdd_config_ie(&sib1->tdd_cnfg, &msg_ptr); } // SI Window Length - rrc_value_2_bits(sib1->si_window_length, &msg_ptr, 3); + liblte_value_2_bits(sib1->si_window_length, &msg_ptr, 3); // System Info Value Tag - rrc_value_2_bits(sib1->system_info_value_tag, &msg_ptr, 5); + liblte_value_2_bits(sib1->system_info_value_tag, &msg_ptr, 5); // Non Critical Extension // FIXME @@ -7895,13 +10865,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_1_msg(LIBLTE_BIT_MSG_STR N_bits_used != NULL) { // Optional indicators - sib1->p_max_present = rrc_bits_2_value(&msg_ptr, 1); - tdd_config_opt = rrc_bits_2_value(&msg_ptr, 1); - non_crit_ext_opt = rrc_bits_2_value(&msg_ptr, 1); + sib1->p_max_present = liblte_bits_2_value(&msg_ptr, 1); + tdd_config_opt = liblte_bits_2_value(&msg_ptr, 1); + non_crit_ext_opt = liblte_bits_2_value(&msg_ptr, 1); // Cell Access Related Info - csg_id_opt = rrc_bits_2_value(&msg_ptr, 1); - sib1->N_plmn_ids = rrc_bits_2_value(&msg_ptr, 3) + 1; + csg_id_opt = liblte_bits_2_value(&msg_ptr, 1); + sib1->N_plmn_ids = liblte_bits_2_value(&msg_ptr, 3) + 1; for(i=0; iN_plmn_ids; i++) { liblte_rrc_unpack_plmn_identity_ie(&msg_ptr, &sib1->plmn_id[i].id); @@ -7910,13 +10880,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_1_msg(LIBLTE_BIT_MSG_STR { sib1->plmn_id[i].id.mcc = sib1->plmn_id[i-1].id.mcc; } - sib1->plmn_id[i].resv_for_oper = (LIBLTE_RRC_RESV_FOR_OPER_ENUM)rrc_bits_2_value(&msg_ptr, 1); + sib1->plmn_id[i].resv_for_oper = (LIBLTE_RRC_RESV_FOR_OPER_ENUM)liblte_bits_2_value(&msg_ptr, 1); } liblte_rrc_unpack_tracking_area_code_ie(&msg_ptr, &sib1->tracking_area_code); liblte_rrc_unpack_cell_identity_ie(&msg_ptr, &sib1->cell_id); - sib1->cell_barred = (LIBLTE_RRC_CELL_BARRED_ENUM)rrc_bits_2_value(&msg_ptr, 1); - sib1->intra_freq_reselection = (LIBLTE_RRC_INTRA_FREQ_RESELECTION_ENUM)rrc_bits_2_value(&msg_ptr, 1); - sib1->csg_indication = rrc_bits_2_value(&msg_ptr, 1); + sib1->cell_barred = (LIBLTE_RRC_CELL_BARRED_ENUM)liblte_bits_2_value(&msg_ptr, 1); + sib1->intra_freq_reselection = (LIBLTE_RRC_INTRA_FREQ_RESELECTION_ENUM)liblte_bits_2_value(&msg_ptr, 1); + sib1->csg_indication = liblte_bits_2_value(&msg_ptr, 1); if(true == csg_id_opt) { liblte_rrc_unpack_csg_identity_ie(&msg_ptr, &sib1->csg_id); @@ -7925,11 +10895,11 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_1_msg(LIBLTE_BIT_MSG_STR } // Cell Selection Info - q_rx_lev_min_offset_opt = rrc_bits_2_value(&msg_ptr, 1); + q_rx_lev_min_offset_opt = liblte_bits_2_value(&msg_ptr, 1); liblte_rrc_unpack_q_rx_lev_min_ie(&msg_ptr, &sib1->q_rx_lev_min); if(true == q_rx_lev_min_offset_opt) { - sib1->q_rx_lev_min_offset = (rrc_bits_2_value(&msg_ptr, 3) + 1) * 2; + sib1->q_rx_lev_min_offset = (liblte_bits_2_value(&msg_ptr, 3) + 1) * 2; }else{ sib1->q_rx_lev_min_offset = 0; } @@ -7941,18 +10911,18 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_1_msg(LIBLTE_BIT_MSG_STR } // Freq Band Indicator - sib1->freq_band_indicator = rrc_bits_2_value(&msg_ptr, 6) + 1; + sib1->freq_band_indicator = liblte_bits_2_value(&msg_ptr, 6) + 1; // Scheduling Info List - sib1->N_sched_info = rrc_bits_2_value(&msg_ptr, 5) + 1; + sib1->N_sched_info = liblte_bits_2_value(&msg_ptr, 5) + 1; for(i=0; iN_sched_info; i++) { - sib1->sched_info[i].si_periodicity = (LIBLTE_RRC_SI_PERIODICITY_ENUM)rrc_bits_2_value(&msg_ptr, 3); - sib1->sched_info[i].N_sib_mapping_info = rrc_bits_2_value(&msg_ptr, 5); + sib1->sched_info[i].si_periodicity = (LIBLTE_RRC_SI_PERIODICITY_ENUM)liblte_bits_2_value(&msg_ptr, 3); + sib1->sched_info[i].N_sib_mapping_info = liblte_bits_2_value(&msg_ptr, 5); for(j=0; jsched_info[i].N_sib_mapping_info; j++) { - extension = rrc_bits_2_value(&msg_ptr, 1); - sib1->sched_info[i].sib_mapping_info[j].sib_type = (LIBLTE_RRC_SIB_TYPE_ENUM)rrc_bits_2_value(&msg_ptr, 4); + extension = liblte_bits_2_value(&msg_ptr, 1); + sib1->sched_info[i].sib_mapping_info[j].sib_type = (LIBLTE_RRC_SIB_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 4); } } @@ -7960,16 +10930,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_1_msg(LIBLTE_BIT_MSG_STR if(true == tdd_config_opt) { sib1->tdd = true; - liblte_rrc_unpack_tdd_config_ie(&msg_ptr, &sib1->sf_assignment, &sib1->special_sf_patterns); + liblte_rrc_unpack_tdd_config_ie(&msg_ptr, &sib1->tdd_cnfg); }else{ sib1->tdd = false; } // SI Window Length - sib1->si_window_length = (LIBLTE_RRC_SI_WINDOW_LENGTH_ENUM)rrc_bits_2_value(&msg_ptr, 3); + sib1->si_window_length = (LIBLTE_RRC_SI_WINDOW_LENGTH_ENUM)liblte_bits_2_value(&msg_ptr, 3); // System Info Value Tag - sib1->system_info_value_tag = rrc_bits_2_value(&msg_ptr, 5); + sib1->system_info_value_tag = liblte_bits_2_value(&msg_ptr, 5); // Non Critical Extension if(true == non_crit_ext_opt) @@ -7998,54 +10968,107 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_msg(LIBLTE_RRC_SYS_INFO_MSG_STRUCT *s { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint8 *msg_ptr = msg->msg; + uint8 *length_ptr; + uint32 length; + uint32 pad_bits; uint32 i; if(sibs != NULL && msg != NULL) { // Critical extensions choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Optional indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Number of SIBs present - rrc_value_2_bits(sibs->N_sibs - 1, &msg_ptr, 5); + liblte_value_2_bits(sibs->N_sibs - 1, &msg_ptr, 5); for(i=0; iN_sibs; i++) { - // Extension indicator - rrc_value_2_bits(0, &msg_ptr, 1); - - rrc_value_2_bits(sibs->sibs[i].sib_type, &msg_ptr, 4); - switch(sibs->sibs[i].sib_type) + if(sibs->sibs[i].sib_type < LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_12) { - case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2: - err = liblte_rrc_pack_sys_info_block_type_2_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *)&sibs->sibs[i].sib, - &msg_ptr); - break; - case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3: - err = liblte_rrc_pack_sys_info_block_type_3_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *)&sibs->sibs[i].sib, - &msg_ptr); - break; - case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4: - err = liblte_rrc_pack_sys_info_block_type_4_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *)&sibs->sibs[i].sib, - &msg_ptr); - break; - case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8: - err = liblte_rrc_pack_sys_info_block_type_8_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT *)&sibs->sibs[i].sib, - &msg_ptr); - break; - case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_5: - case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_6: - case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7: - case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9: - case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_10: - case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_11: - default: - printf("ERROR: Not handling sib type %u\n", sibs->sibs[i].sib_type); - err = LIBLTE_ERROR_INVALID_INPUTS; - break; + // Extension indicator + liblte_value_2_bits(0, &msg_ptr, 1); + + liblte_value_2_bits(sibs->sibs[i].sib_type, &msg_ptr, 4); + switch(sibs->sibs[i].sib_type) + { + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2: + err = liblte_rrc_pack_sys_info_block_type_2_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *)&sibs->sibs[i].sib, + &msg_ptr); + break; + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3: + err = liblte_rrc_pack_sys_info_block_type_3_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *)&sibs->sibs[i].sib, + &msg_ptr); + break; + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4: + err = liblte_rrc_pack_sys_info_block_type_4_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *)&sibs->sibs[i].sib, + &msg_ptr); + break; + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8: + err = liblte_rrc_pack_sys_info_block_type_8_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT *)&sibs->sibs[i].sib, + &msg_ptr); + break; + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_5: + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_6: + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7: + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9: + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_10: + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_11: + default: + printf("ERROR: Not handling sib type %u\n", sibs->sibs[i].sib_type); + err = LIBLTE_ERROR_INVALID_INPUTS; + break; + } + }else{ + // Extension indicator + liblte_value_2_bits(1, &msg_ptr, 1); + + liblte_value_2_bits(sibs->sibs[i].sib_type - 10, &msg_ptr, 7); + length_ptr = msg_ptr; + liblte_value_2_bits(0, &msg_ptr, 8); + switch(sibs->sibs[i].sib_type) + { + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13: + err = liblte_rrc_pack_sys_info_block_type_13_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *)&sibs->sibs[i].sib, + &msg_ptr); + break; + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_12: + default: + printf("ERROR: Not handling extended sib type %s\n", liblte_rrc_sys_info_block_type_text[sibs->sibs[i].sib_type]); + err = LIBLTE_ERROR_INVALID_INPUTS; + break; + } + length = ((msg_ptr - length_ptr) / 8) - 1; + pad_bits = (msg_ptr - length_ptr) % 8; + if(0 != pad_bits) + { + length++; + } + if(length < 128) + { + liblte_value_2_bits(0, &length_ptr, 1); + liblte_value_2_bits(length, &length_ptr, 7); + }else{ + msg_ptr = length_ptr; + liblte_value_2_bits(0, &msg_ptr, 2); + liblte_value_2_bits(length, &msg_ptr, 14); + switch(sibs->sibs[i].sib_type) + { + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13: + err = liblte_rrc_pack_sys_info_block_type_13_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *)&sibs->sibs[i].sib, + &msg_ptr); + break; + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_12: + default: + printf("ERROR: Not handling extended sib type %s\n", liblte_rrc_sys_info_block_type_text[sibs->sibs[i].sib_type]); + err = LIBLTE_ERROR_INVALID_INPUTS; + break; + } + } + liblte_value_2_bits(0, &msg_ptr, pad_bits); } if(LIBLTE_SUCCESS != err) @@ -8065,27 +11088,29 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_msg(LIBLTE_BIT_MSG_STRUCT { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint8 *msg_ptr = msg->msg; + uint8 *head_ptr; uint32 i; + uint32 length_determinant_octets; uint8 non_crit_ext_opt; if(msg != NULL && sibs != NULL) { // Critical extensions choice - if(0 == rrc_bits_2_value(&msg_ptr, 1)) + if(0 == liblte_bits_2_value(&msg_ptr, 1)) { // Optional indicator - non_crit_ext_opt = rrc_bits_2_value(&msg_ptr, 1); + non_crit_ext_opt = liblte_bits_2_value(&msg_ptr, 1); // Number of SIBs present - sibs->N_sibs = rrc_bits_2_value(&msg_ptr, 5) + 1; + sibs->N_sibs = liblte_bits_2_value(&msg_ptr, 5) + 1; for(i=0; iN_sibs; i++) { // Extension indicator - if(0 == rrc_bits_2_value(&msg_ptr, 1)) + if(0 == liblte_bits_2_value(&msg_ptr, 1)) { - sibs->sibs[i].sib_type = (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_ENUM)rrc_bits_2_value(&msg_ptr, 4); + sibs->sibs[i].sib_type = (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 4); switch(sibs->sibs[i].sib_type) { case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2: @@ -8125,8 +11150,33 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_msg(LIBLTE_BIT_MSG_STRUCT break; } }else{ - printf("ERROR: Not handling extended SIB type and info\n"); - err = LIBLTE_ERROR_INVALID_INPUTS; + sibs->sibs[i].sib_type = (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_ENUM)(liblte_bits_2_value(&msg_ptr, 7) + 10); + length_determinant_octets = 0; + if(0 == liblte_bits_2_value(&msg_ptr, 1)) + { + length_determinant_octets = liblte_bits_2_value(&msg_ptr, 7); + }else{ + if(0 == liblte_bits_2_value(&msg_ptr, 1)) + { + length_determinant_octets = liblte_bits_2_value(&msg_ptr, 14); + }else{ + printf("ERROR: Not handling fragmented length determinants\n"); + } + } + head_ptr = msg_ptr; + switch(sibs->sibs[i].sib_type) + { + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13: + err = liblte_rrc_unpack_sys_info_block_type_13_ie(&msg_ptr, + (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *)&sibs->sibs[i].sib); + break; + case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_12: + default: + printf("ERROR: Not handling extended sib type %s\n", liblte_rrc_sys_info_block_type_text[sibs->sibs[i].sib_type]); + err = LIBLTE_ERROR_INVALID_INPUTS; + break; + } + liblte_bits_2_value(&msg_ptr, (msg_ptr - head_ptr) % 8); } if(LIBLTE_SUCCESS != err) @@ -8164,10 +11214,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_security_mode_failure_msg(LIBLTE_RRC_SECURITY_ &msg_ptr); // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Optional indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; err = LIBLTE_SUCCESS; } @@ -8188,10 +11241,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_security_mode_failure_msg(LIBLTE_BIT_MSG_STR &security_mode_failure->rrc_transaction_id); // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Optional indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); err = LIBLTE_SUCCESS; } @@ -8221,10 +11274,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_security_mode_complete_msg(LIBLTE_RRC_SECURITY &msg_ptr); // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Optional indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; err = LIBLTE_SUCCESS; } @@ -8245,10 +11301,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_security_mode_complete_msg(LIBLTE_BIT_MSG_ST &security_mode_complete->rrc_transaction_id); // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Optional indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); err = LIBLTE_SUCCESS; } @@ -8263,7 +11319,80 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_security_mode_complete_msg(LIBLTE_BIT_MSG_ST Document Reference: 36.331 v10.0.0 Section 6.2.2 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_security_mode_command_msg(LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT *security_mode_cmd, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(security_mode_cmd != NULL && + msg != NULL) + { + // RRC Transaction ID + liblte_rrc_pack_rrc_transaction_identifier_ie(security_mode_cmd->rrc_transaction_id, + &msg_ptr); + + // Extension choice + liblte_value_2_bits(0, &msg_ptr, 1); + + // C1 choice + liblte_value_2_bits(0, &msg_ptr, 2); + + // Optional indicator + liblte_value_2_bits(0, &msg_ptr, 1); + + // Extension indicator + liblte_value_2_bits(0, &msg_ptr, 1); + + // Security Algorithms Config + liblte_rrc_pack_security_algorithm_config_ie(&security_mode_cmd->sec_algs, + &msg_ptr); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_security_mode_command_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT *security_mode_cmd) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + bool ext_ind; + + if(msg_ptr != NULL && + security_mode_cmd != NULL) + { + // RRC Transaction ID + liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, + &security_mode_cmd->rrc_transaction_id); + + // Extension choice + liblte_bits_2_value(&msg_ptr, 1); + + // C1 choice + liblte_bits_2_value(&msg_ptr, 2); + + // Optional indicator + liblte_bits_2_value(&msg_ptr, 1); + + // Extension indicator + ext_ind = liblte_bits_2_value(&msg_ptr, 1); + + // Security Algorithms Config + liblte_rrc_unpack_security_algorithm_config_ie(&msg_ptr, + &security_mode_cmd->sec_algs); + + skip_sequence_type_extension(ext_ind, &msg_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* Message Name: RRC Connection Setup Complete @@ -8283,26 +11412,27 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_setup_complete_msg(LIBLTE_RRC_C msg != NULL) { // RRC Transaction ID - liblte_rrc_pack_rrc_transaction_identifier_ie(con_setup_complete->transaction_id, &msg_ptr); + liblte_rrc_pack_rrc_transaction_identifier_ie(con_setup_complete->rrc_transaction_id, + &msg_ptr); // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // C1 choice - rrc_value_2_bits(0, &msg_ptr, 2); + liblte_value_2_bits(0, &msg_ptr, 2); // Optional indicators - rrc_value_2_bits(con_setup_complete->registered_mme_present, &msg_ptr, 1); - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(con_setup_complete->registered_mme_present, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Selected PLMN identity - rrc_value_2_bits(con_setup_complete->selected_plmn_id - 1, &msg_ptr, 3); + liblte_value_2_bits(con_setup_complete->selected_plmn_id - 1, &msg_ptr, 3); // Registered MME if(con_setup_complete->registered_mme_present) { // Optional indicator - rrc_value_2_bits(con_setup_complete->registered_mme.plmn_id_present, &msg_ptr, 1); + liblte_value_2_bits(con_setup_complete->registered_mme.plmn_id_present, &msg_ptr, 1); // PLMN identity if(con_setup_complete->registered_mme.plmn_id_present) @@ -8311,7 +11441,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_setup_complete_msg(LIBLTE_RRC_C } // MMEGI - rrc_value_2_bits(con_setup_complete->registered_mme.mmegi, &msg_ptr, 16); + liblte_value_2_bits(con_setup_complete->registered_mme.mmegi, &msg_ptr, 16); // MMEC liblte_rrc_pack_mmec_ie(con_setup_complete->registered_mme.mmec, &msg_ptr); @@ -8321,6 +11451,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_setup_complete_msg(LIBLTE_RRC_C liblte_rrc_pack_dedicated_info_nas_ie(&con_setup_complete->dedicated_info_nas, &msg_ptr); + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + err = LIBLTE_SUCCESS; } @@ -8336,26 +11469,27 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_setup_complete_msg(LIBLTE_BIT con_setup_complete != NULL) { // RRC Transaction ID - liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, &con_setup_complete->transaction_id); + liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, + &con_setup_complete->rrc_transaction_id); // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // C1 choice - rrc_bits_2_value(&msg_ptr, 2); + liblte_bits_2_value(&msg_ptr, 2); // Optional indicators - con_setup_complete->registered_mme_present = rrc_bits_2_value(&msg_ptr, 1); - rrc_bits_2_value(&msg_ptr, 1); + con_setup_complete->registered_mme_present = liblte_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Selected PLMN identity - con_setup_complete->selected_plmn_id = rrc_bits_2_value(&msg_ptr, 3) + 1; + con_setup_complete->selected_plmn_id = liblte_bits_2_value(&msg_ptr, 3) + 1; // Registered MME if(con_setup_complete->registered_mme_present) { // Optional indicator - con_setup_complete->registered_mme.plmn_id_present = rrc_bits_2_value(&msg_ptr, 1); + con_setup_complete->registered_mme.plmn_id_present = liblte_bits_2_value(&msg_ptr, 1); // PLMN identity if(con_setup_complete->registered_mme.plmn_id_present) @@ -8364,7 +11498,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_setup_complete_msg(LIBLTE_BIT } // MMEGI - con_setup_complete->registered_mme.mmegi = rrc_bits_2_value(&msg_ptr, 16); + con_setup_complete->registered_mme.mmegi = liblte_bits_2_value(&msg_ptr, 16); // MMEC liblte_rrc_unpack_mmec_ie(&msg_ptr, &con_setup_complete->registered_mme.mmec); @@ -8397,20 +11531,24 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_setup_msg(LIBLTE_RRC_CONNECTION msg != NULL) { // RRC Transaction ID - liblte_rrc_pack_rrc_transaction_identifier_ie(con_setup->transaction_id, &msg_ptr); + liblte_rrc_pack_rrc_transaction_identifier_ie(con_setup->rrc_transaction_id, + &msg_ptr); // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // C1 choice - rrc_value_2_bits(0, &msg_ptr, 3); + liblte_value_2_bits(0, &msg_ptr, 3); // Optional indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Radio Resource Config Dedicated liblte_rrc_pack_rr_config_dedicated_ie(&con_setup->rr_cnfg, &msg_ptr); + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + err = LIBLTE_SUCCESS; } @@ -8426,16 +11564,17 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_setup_msg(LIBLTE_BIT_MSG_STRU con_setup != NULL) { // RRC Transaction ID - liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, &con_setup->transaction_id); + liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, + &con_setup->rrc_transaction_id); // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // C1 choice - rrc_bits_2_value(&msg_ptr, 3); + liblte_bits_2_value(&msg_ptr, 3); // Optional indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Radio Resource Config Dedicated liblte_rrc_unpack_rr_config_dedicated_ie(&msg_ptr, &con_setup->rr_cnfg); @@ -8465,12 +11604,12 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_request_msg(LIBLTE_RRC_CONNECTI msg != NULL) { // Extension choice - rrc_value_2_bits(ext, &msg_ptr, 1); + liblte_value_2_bits(ext, &msg_ptr, 1); if(!ext) { // UE Identity Type - rrc_value_2_bits(con_req->ue_id_type, &msg_ptr, 1); + liblte_value_2_bits(con_req->ue_id_type, &msg_ptr, 1); // UE Identity if(LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI == con_req->ue_id_type) @@ -8478,15 +11617,18 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_request_msg(LIBLTE_RRC_CONNECTI liblte_rrc_pack_s_tmsi_ie((LIBLTE_RRC_S_TMSI_STRUCT *)&con_req->ue_id, &msg_ptr); }else{ // LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE == con_req->ue_id_type - rrc_value_2_bits((uint32)(con_req->ue_id.random >> 32), &msg_ptr, 8); - rrc_value_2_bits((uint32)(con_req->ue_id.random), &msg_ptr, 32); + liblte_value_2_bits((uint32)(con_req->ue_id.random >> 32), &msg_ptr, 8); + liblte_value_2_bits((uint32)(con_req->ue_id.random), &msg_ptr, 32); } // Establishment Cause - rrc_value_2_bits(con_req->cause, &msg_ptr, 3); + liblte_value_2_bits(con_req->cause, &msg_ptr, 3); // Spare - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; err = LIBLTE_SUCCESS; } @@ -8504,10 +11646,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_request_msg(LIBLTE_BIT_MSG_ST con_req != NULL) { // Extension Choice - if(!rrc_bits_2_value(&msg_ptr, 1)) + if(!liblte_bits_2_value(&msg_ptr, 1)) { // UE Identity Type - con_req->ue_id_type = (LIBLTE_RRC_CON_REQ_UE_ID_TYPE_ENUM)rrc_bits_2_value(&msg_ptr, 1); + con_req->ue_id_type = (LIBLTE_RRC_CON_REQ_UE_ID_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1); // UE Identity if(LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI == con_req->ue_id_type) @@ -8515,12 +11657,12 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_request_msg(LIBLTE_BIT_MSG_ST liblte_rrc_unpack_s_tmsi_ie(&msg_ptr, (LIBLTE_RRC_S_TMSI_STRUCT *)&con_req->ue_id); }else{ // LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE == con_req->ue_id_type - con_req->ue_id.random = (uint64)rrc_bits_2_value(&msg_ptr, 8) << 32; - con_req->ue_id.random |= rrc_bits_2_value(&msg_ptr, 32); + con_req->ue_id.random = (uint64)liblte_bits_2_value(&msg_ptr, 8) << 32; + con_req->ue_id.random |= liblte_bits_2_value(&msg_ptr, 32); } // Establishment Cause - con_req->cause = (LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM)rrc_bits_2_value(&msg_ptr, 3); + con_req->cause = (LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM)liblte_bits_2_value(&msg_ptr, 3); err = LIBLTE_SUCCESS; } @@ -8536,7 +11678,73 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_request_msg(LIBLTE_BIT_MSG_ST Document Reference: 36.331 v10.0.0 Section 6.2.2 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_release_msg(LIBLTE_RRC_CONNECTION_RELEASE_STRUCT *con_release, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(con_release != NULL && + msg != NULL) + { + // RRC Transaction ID + liblte_rrc_pack_rrc_transaction_identifier_ie(con_release->rrc_transaction_id, + &msg_ptr); + + // Extension choice + liblte_value_2_bits(0, &msg_ptr, 1); + + // C1 choice + liblte_value_2_bits(0, &msg_ptr, 2); + + // Optional indicators + liblte_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + + // Release cause + liblte_value_2_bits(con_release->release_cause, &msg_ptr, 2); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_release_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_CONNECTION_RELEASE_STRUCT *con_release) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + con_release != NULL) + { + // RRC Transaction ID + liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, + &con_release->rrc_transaction_id); + + // Extension choice + liblte_bits_2_value(&msg_ptr, 1); + + // C1 choice + liblte_bits_2_value(&msg_ptr, 2); + + // Optional indicators + liblte_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); + + // Release cause + con_release->release_cause = (LIBLTE_RRC_RELEASE_CAUSE_ENUM)liblte_bits_2_value(&msg_ptr, 2); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* Message Name: RRC Connection Reject @@ -8555,16 +11763,19 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reject_msg(LIBLTE_RRC_CONNECTIO msg != NULL) { // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // C1 choice - rrc_value_2_bits(0, &msg_ptr, 2); + liblte_value_2_bits(0, &msg_ptr, 2); // Optional indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Wait Time - rrc_value_2_bits(con_rej->wait_time, &msg_ptr, 4); + liblte_value_2_bits(con_rej->wait_time, &msg_ptr, 4); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; err = LIBLTE_SUCCESS; } @@ -8581,16 +11792,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reject_msg(LIBLTE_BIT_MSG_STR con_rej != NULL) { // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // C1 choice - rrc_bits_2_value(&msg_ptr, 2); + liblte_bits_2_value(&msg_ptr, 2); // Optional indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Wait Time - con_rej->wait_time = rrc_bits_2_value(&msg_ptr, 4); + con_rej->wait_time = liblte_bits_2_value(&msg_ptr, 4); err = LIBLTE_SUCCESS; } @@ -8617,28 +11828,23 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reestablishment_request_msg(LIB msg != NULL) { // Extension choice - rrc_value_2_bits(ext, &msg_ptr, 1); + liblte_value_2_bits(ext, &msg_ptr, 1); if(!ext) { - // UE Identity Type - rrc_value_2_bits(con_reest_req->ue_id_type, &msg_ptr, 2); - // UE Identity - if(LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_C_RNTI == con_reest_req->ue_id_type) - { - liblte_rrc_pack_c_rnti_ie((uint16)con_reest_req->ue_id.c_rnti, &msg_ptr); - }else if(LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_PHYS_CELL_ID == con_reest_req->ue_id_type){ - liblte_rrc_pack_phys_cell_id_ie((uint16)con_reest_req->ue_id.phys_cell_id, &msg_ptr); - }else{ // LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_SHORT_MAC_I == con_reest_req->ue_id_type - liblte_rrc_pack_short_mac_i_ie((uint16)con_reest_req->ue_id.short_mac_i, &msg_ptr); - } + liblte_rrc_pack_c_rnti_ie((uint16)con_reest_req->ue_id.c_rnti, &msg_ptr); + liblte_rrc_pack_phys_cell_id_ie((uint16)con_reest_req->ue_id.phys_cell_id, &msg_ptr); + liblte_rrc_pack_short_mac_i_ie((uint16)con_reest_req->ue_id.short_mac_i, &msg_ptr); // Reestablishment Cause - rrc_value_2_bits(con_reest_req->cause, &msg_ptr, 2); + liblte_value_2_bits(con_reest_req->cause, &msg_ptr, 2); // Spare - rrc_value_2_bits(0, &msg_ptr, 2); + liblte_value_2_bits(0, &msg_ptr, 2); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; err = LIBLTE_SUCCESS; } @@ -8656,23 +11862,15 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reestablishment_request_msg(L con_reest_req != NULL) { // Extension Choice - if(!rrc_bits_2_value(&msg_ptr, 1)) + if(!liblte_bits_2_value(&msg_ptr, 1)) { - // UE Identity Type - con_reest_req->ue_id_type = (LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_ENUM)rrc_bits_2_value(&msg_ptr, 2); - // UE Identity - if(LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_C_RNTI == con_reest_req->ue_id_type) - { - liblte_rrc_unpack_c_rnti_ie(&msg_ptr, (uint16 *)&con_reest_req->ue_id); - }else if(LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_PHYS_CELL_ID == con_reest_req->ue_id_type){ - liblte_rrc_unpack_phys_cell_id_ie(&msg_ptr, (uint16 *)&con_reest_req->ue_id); - }else{ // LIBLTE_RRC_CON_REEST_REQ_UE_ID_TYPE_SHORT_MAC_I == con_reest_req->ue_id_type - liblte_rrc_unpack_short_mac_i_ie(&msg_ptr, (uint16 *)&con_reest_req->ue_id); - } + liblte_rrc_unpack_c_rnti_ie(&msg_ptr, (uint16 *)&con_reest_req->ue_id); + liblte_rrc_unpack_phys_cell_id_ie(&msg_ptr, (uint16 *)&con_reest_req->ue_id); + liblte_rrc_unpack_short_mac_i_ie(&msg_ptr, (uint16 *)&con_reest_req->ue_id); // Reestablishment Cause - con_reest_req->cause = (LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM)rrc_bits_2_value(&msg_ptr, 2); + con_reest_req->cause = (LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM)liblte_bits_2_value(&msg_ptr, 2); err = LIBLTE_SUCCESS; } @@ -8699,10 +11897,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reestablishment_reject_msg(LIBL msg != NULL) { // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Optional indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; err = LIBLTE_SUCCESS; } @@ -8719,10 +11920,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reestablishment_reject_msg(LI con_reest_rej != NULL) { // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Optional indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); err = LIBLTE_SUCCESS; } @@ -8752,10 +11953,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reestablishment_complete_msg(LI &msg_ptr); // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Optional indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; err = LIBLTE_SUCCESS; } @@ -8776,10 +11980,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reestablishment_complete_msg( &con_reest_complete->rrc_transaction_id); // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Optional indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); err = LIBLTE_SUCCESS; } @@ -8804,16 +12008,17 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reestablishment_msg(LIBLTE_RRC_ msg != NULL) { // RRC Transaction ID - liblte_rrc_pack_rrc_transaction_identifier_ie(con_reest->transaction_id, &msg_ptr); + liblte_rrc_pack_rrc_transaction_identifier_ie(con_reest->rrc_transaction_id, + &msg_ptr); // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // C1 choice - rrc_value_2_bits(0, &msg_ptr, 3); + liblte_value_2_bits(0, &msg_ptr, 3); // Optional indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Radio Resource Config Dedicated liblte_rrc_pack_rr_config_dedicated_ie(&con_reest->rr_cnfg, &msg_ptr); @@ -8821,6 +12026,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reestablishment_msg(LIBLTE_RRC_ // Next Hop Chaining Count liblte_rrc_pack_next_hop_chaining_count_ie(con_reest->next_hop_chaining_count, &msg_ptr); + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + err = LIBLTE_SUCCESS; } @@ -8836,16 +12044,17 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reestablishment_msg(LIBLTE_BI con_reest != NULL) { // RRC Transaction ID - liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, &con_reest->transaction_id); + liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, + &con_reest->rrc_transaction_id); // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // C1 choice - rrc_bits_2_value(&msg_ptr, 3); + liblte_bits_2_value(&msg_ptr, 3); // Optional indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Radio Resource Config Dedicated liblte_rrc_unpack_rr_config_dedicated_ie(&msg_ptr, &con_reest->rr_cnfg); @@ -8881,10 +12090,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reconfiguration_complete_msg(LI &msg_ptr); // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Optional indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; err = LIBLTE_SUCCESS; } @@ -8905,10 +12117,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reconfiguration_complete_msg( &con_reconfig_complete->rrc_transaction_id); // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Optional indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); err = LIBLTE_SUCCESS; } @@ -8923,7 +12135,214 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reconfiguration_complete_msg( Document Reference: 36.331 v10.0.0 Section 6.2.2 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reconfiguration_msg(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *con_reconfig, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint32 i; + + if(con_reconfig != NULL && + msg != NULL) + { + // RRC Transaction ID + liblte_rrc_pack_rrc_transaction_identifier_ie(con_reconfig->rrc_transaction_id, &msg_ptr); + + // Extension choice + liblte_value_2_bits(0, &msg_ptr, 1); + + // C1 choice + liblte_value_2_bits(0, &msg_ptr, 3); + + // Optional indicators + liblte_value_2_bits(con_reconfig->meas_cnfg_present, &msg_ptr, 1); + liblte_value_2_bits(con_reconfig->mob_ctrl_info_present, &msg_ptr, 1); + if(0 == con_reconfig->N_ded_info_nas) + { + liblte_value_2_bits(0, &msg_ptr, 1); + }else{ + liblte_value_2_bits(1, &msg_ptr, 1); + } + liblte_value_2_bits(con_reconfig->rr_cnfg_ded_present, &msg_ptr, 1); + liblte_value_2_bits(con_reconfig->sec_cnfg_ho_present, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + + // Meas Config + if(con_reconfig->meas_cnfg_present) + { + liblte_rrc_pack_meas_config_ie(&con_reconfig->meas_cnfg, &msg_ptr); + } + + // Mobility Control Info + if(con_reconfig->mob_ctrl_info_present) + { + liblte_rrc_pack_mobility_control_info_ie(&con_reconfig->mob_ctrl_info, &msg_ptr); + } + + // Dedicated Info NAS List + if(0 != con_reconfig->N_ded_info_nas) + { + liblte_value_2_bits(con_reconfig->N_ded_info_nas - 1, &msg_ptr, 4); + } + for(i=0; iN_ded_info_nas; i++) + { + liblte_rrc_pack_dedicated_info_nas_ie(&con_reconfig->ded_info_nas_list[i], &msg_ptr); + } + + // Radio Resource Config Dedicated + if(con_reconfig->rr_cnfg_ded_present) + { + liblte_rrc_pack_rr_config_dedicated_ie(&con_reconfig->rr_cnfg_ded, &msg_ptr); + } + + // Security Config HO + if(con_reconfig->sec_cnfg_ho_present) + { + // Extension indicator + liblte_value_2_bits(0, &msg_ptr, 1); + + // Handover Type + liblte_value_2_bits(con_reconfig->sec_cnfg_ho.ho_type, &msg_ptr, 1); + + if(LIBLTE_RRC_HANDOVER_TYPE_INTRA_LTE == con_reconfig->sec_cnfg_ho.ho_type) + { + // Optional indicator + liblte_value_2_bits(con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg_present, &msg_ptr, 1); + + // Security Algorithm Config + if(con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg_present) + { + liblte_rrc_pack_security_algorithm_config_ie(&con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg, &msg_ptr); + } + + // Key Change Indicator + liblte_value_2_bits(con_reconfig->sec_cnfg_ho.intra_lte.key_change_ind, &msg_ptr, 1); + + // Next Hop Chaining Count + liblte_rrc_pack_next_hop_chaining_count_ie(con_reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count, &msg_ptr); + }else{ + // Security Algorithm Config + liblte_rrc_pack_security_algorithm_config_ie(&con_reconfig->sec_cnfg_ho.inter_rat.sec_alg_cnfg, &msg_ptr); + + // NAS Security Params To EUTRA + for(i=0; i<6; i++) + { + liblte_value_2_bits(con_reconfig->sec_cnfg_ho.inter_rat.nas_sec_param_to_eutra[i], &msg_ptr, 8); + } + } + } + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reconfiguration_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *con_reconfig) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint32 i; + bool ded_info_nas_list_present; + bool sec_cnfg_ho_ext_ind; + + if(msg != NULL && + con_reconfig != NULL) + { + // RRC Transaction ID + liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, &con_reconfig->rrc_transaction_id); + + // Extension choice + liblte_bits_2_value(&msg_ptr, 1); + + // C1 choice + liblte_bits_2_value(&msg_ptr, 3); + + // Optional indicators + con_reconfig->meas_cnfg_present = liblte_bits_2_value(&msg_ptr, 1); + con_reconfig->mob_ctrl_info_present = liblte_bits_2_value(&msg_ptr, 1); + ded_info_nas_list_present = liblte_bits_2_value(&msg_ptr, 1); + con_reconfig->rr_cnfg_ded_present = liblte_bits_2_value(&msg_ptr, 1); + con_reconfig->sec_cnfg_ho_present = liblte_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); + + // Meas Config + if(con_reconfig->meas_cnfg_present) + { + liblte_rrc_unpack_meas_config_ie(&msg_ptr, &con_reconfig->meas_cnfg); + } + + // Mobility Control Info + if(con_reconfig->mob_ctrl_info_present) + { + liblte_rrc_unpack_mobility_control_info_ie(&msg_ptr, &con_reconfig->mob_ctrl_info); + } + + // Dedicated Info NAS List + if(ded_info_nas_list_present) + { + con_reconfig->N_ded_info_nas = liblte_bits_2_value(&msg_ptr, 4) + 1; + for(i=0; iN_ded_info_nas; i++) + { + liblte_rrc_unpack_dedicated_info_nas_ie(&msg_ptr, &con_reconfig->ded_info_nas_list[i]); + } + }else{ + con_reconfig->N_ded_info_nas = 0; + } + + // Radio Resource Config Dedicated + if(con_reconfig->rr_cnfg_ded_present) + { + liblte_rrc_unpack_rr_config_dedicated_ie(&msg_ptr, &con_reconfig->rr_cnfg_ded); + } + + // Security Config HO + if(con_reconfig->sec_cnfg_ho_present) + { + // Extension indicator + sec_cnfg_ho_ext_ind = liblte_bits_2_value(&msg_ptr, 1); + + // Handover Type + con_reconfig->sec_cnfg_ho.ho_type = (LIBLTE_RRC_HANDOVER_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1); + + if(LIBLTE_RRC_HANDOVER_TYPE_INTRA_LTE == con_reconfig->sec_cnfg_ho.ho_type) + { + // Optional indicator + con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg_present = liblte_bits_2_value(&msg_ptr, 1); + + // Security Algorithm Config + if(con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg_present) + { + liblte_rrc_unpack_security_algorithm_config_ie(&msg_ptr, &con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg); + } + + // Key Change Indicator + con_reconfig->sec_cnfg_ho.intra_lte.key_change_ind = liblte_bits_2_value(&msg_ptr, 1); + + // Next Hop Chaining Count + liblte_rrc_unpack_next_hop_chaining_count_ie(&msg_ptr, &con_reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count); + }else{ + // Security Algorithm Config + liblte_rrc_unpack_security_algorithm_config_ie(&msg_ptr, &con_reconfig->sec_cnfg_ho.inter_rat.sec_alg_cnfg); + + // NAS Security Params To EUTRA + for(i=0; i<6; i++) + { + con_reconfig->sec_cnfg_ho.inter_rat.nas_sec_param_to_eutra[i] = liblte_bits_2_value(&msg_ptr, 8); + } + } + + skip_sequence_type_extension(sec_cnfg_ho_ext_ind, &msg_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* Message Name: RN Reconfiguration Complete @@ -8947,14 +12366,17 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_rn_reconfiguration_complete_msg(LIBLTE_RRC_RN_ &msg_ptr); // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // C1 choice - rrc_value_2_bits(0, &msg_ptr, 2); + liblte_value_2_bits(0, &msg_ptr, 2); // Optional indicators - rrc_value_2_bits(0, &msg_ptr, 1); - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; err = LIBLTE_SUCCESS; } @@ -8975,14 +12397,14 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_rn_reconfiguration_complete_msg(LIBLTE_BIT_M &rn_reconfig_complete->rrc_transaction_id); // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // C1 choice - rrc_bits_2_value(&msg_ptr, 2); + liblte_bits_2_value(&msg_ptr, 2); // Optional indicators - rrc_bits_2_value(&msg_ptr, 1); - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); err = LIBLTE_SUCCESS; } @@ -9019,22 +12441,22 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_proximity_indication_msg(LIBLTE_RRC_PROXIMITY_ msg != NULL) { // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // C1 choice - rrc_value_2_bits(0, &msg_ptr, 2); + liblte_value_2_bits(0, &msg_ptr, 2); // Optional indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Proximity indication type - rrc_value_2_bits(proximity_ind->type, &msg_ptr, 1); + liblte_value_2_bits(proximity_ind->type, &msg_ptr, 1); // Carrier frequency type extension indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Carrier frequency choice - rrc_value_2_bits(proximity_ind->carrier_freq_type, &msg_ptr, 1); + liblte_value_2_bits(proximity_ind->carrier_freq_type, &msg_ptr, 1); // Carrier frequency if(LIBLTE_RRC_PROXIMITY_INDICATION_CARRIER_FREQ_TYPE_EUTRA == proximity_ind->carrier_freq_type) @@ -9046,6 +12468,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_proximity_indication_msg(LIBLTE_RRC_PROXIMITY_ &msg_ptr); } + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + err = LIBLTE_SUCCESS; } @@ -9061,22 +12486,22 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_proximity_indication_msg(LIBLTE_BIT_MSG_STRU proximity_ind != NULL) { // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // C1 choice - rrc_bits_2_value(&msg_ptr, 2); + liblte_bits_2_value(&msg_ptr, 2); // Optional indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Proximity indication type - proximity_ind->type = (LIBLTE_RRC_PROXIMITY_INDICATION_TYPE_ENUM)rrc_bits_2_value(&msg_ptr, 1); + proximity_ind->type = (LIBLTE_RRC_PROXIMITY_INDICATION_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1); // Carrier frequency type extension indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Carrier frequency type - proximity_ind->carrier_freq_type = (LIBLTE_RRC_PROXIMITY_INDICATION_CARRIER_FREQ_TYPE_ENUM)rrc_bits_2_value(&msg_ptr, 1); + proximity_ind->carrier_freq_type = (LIBLTE_RRC_PROXIMITY_INDICATION_CARRIER_FREQ_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1); // Carrier frequency if(LIBLTE_RRC_PROXIMITY_INDICATION_CARRIER_FREQ_TYPE_EUTRA == proximity_ind->carrier_freq) @@ -9115,60 +12540,60 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_paging_msg(LIBLTE_RRC_PAGING_STRUCT *page, // Optional indicators if(page->paging_record_list_size != 0) { - rrc_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(1, &msg_ptr, 1); }else{ - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); } - rrc_value_2_bits(page->system_info_modification_present, &msg_ptr, 1); - rrc_value_2_bits(page->etws_indication_present, &msg_ptr, 1); - rrc_value_2_bits(page->non_crit_ext_present, &msg_ptr, 1); + liblte_value_2_bits(page->system_info_modification_present, &msg_ptr, 1); + liblte_value_2_bits(page->etws_indication_present, &msg_ptr, 1); + liblte_value_2_bits(page->non_crit_ext_present, &msg_ptr, 1); if(page->paging_record_list_size != 0) { - rrc_value_2_bits(page->paging_record_list_size - 1, &msg_ptr, 4); + liblte_value_2_bits(page->paging_record_list_size - 1, &msg_ptr, 4); for(i=0; ipaging_record_list_size; i++) { // Extension indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Paging UE identity { // Extension indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); - rrc_value_2_bits(page->paging_record_list[i].ue_identity.ue_identity_type, &msg_ptr, 1); + liblte_value_2_bits(page->paging_record_list[i].ue_identity.ue_identity_type, &msg_ptr, 1); if(LIBLTE_RRC_PAGING_UE_IDENTITY_TYPE_S_TMSI == page->paging_record_list[i].ue_identity.ue_identity_type) { liblte_rrc_pack_s_tmsi_ie(&page->paging_record_list[i].ue_identity.s_tmsi, &msg_ptr); }else{ - rrc_value_2_bits(page->paging_record_list[i].ue_identity.imsi_size - 6, &msg_ptr, 4); + liblte_value_2_bits(page->paging_record_list[i].ue_identity.imsi_size - 6, &msg_ptr, 4); for(j=0; jpaging_record_list[i].ue_identity.imsi_size; j++) { - rrc_value_2_bits(page->paging_record_list[i].ue_identity.imsi[j], &msg_ptr, 4); + liblte_value_2_bits(page->paging_record_list[i].ue_identity.imsi[j], &msg_ptr, 4); } } } - rrc_value_2_bits(page->paging_record_list[i].cn_domain, &msg_ptr, 1); + liblte_value_2_bits(page->paging_record_list[i].cn_domain, &msg_ptr, 1); } } if(page->system_info_modification_present) { - rrc_value_2_bits(page->system_info_modification, &msg_ptr, 1); + liblte_value_2_bits(page->system_info_modification, &msg_ptr, 1); } if(page->etws_indication_present) { - rrc_value_2_bits(page->etws_indication, &msg_ptr, 1); + liblte_value_2_bits(page->etws_indication, &msg_ptr, 1); } if(page->non_crit_ext_present) { // Optional indicators - rrc_value_2_bits(page->non_crit_ext.late_non_crit_ext_present, &msg_ptr, 1); - rrc_value_2_bits(page->non_crit_ext.non_crit_ext_present, &msg_ptr, 1); + liblte_value_2_bits(page->non_crit_ext.late_non_crit_ext_present, &msg_ptr, 1); + liblte_value_2_bits(page->non_crit_ext.non_crit_ext_present, &msg_ptr, 1); if(page->non_crit_ext.late_non_crit_ext_present) { @@ -9178,12 +12603,12 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_paging_msg(LIBLTE_RRC_PAGING_STRUCT *page, if(page->non_crit_ext.non_crit_ext_present) { // Optional indicators - rrc_value_2_bits(page->non_crit_ext.non_crit_ext.cmas_ind_present, &msg_ptr, 1); - rrc_value_2_bits(page->non_crit_ext.non_crit_ext.non_crit_ext_present, &msg_ptr, 1); + liblte_value_2_bits(page->non_crit_ext.non_crit_ext.cmas_ind_present, &msg_ptr, 1); + liblte_value_2_bits(page->non_crit_ext.non_crit_ext.non_crit_ext_present, &msg_ptr, 1); if(page->non_crit_ext.non_crit_ext.cmas_ind_present) { - rrc_value_2_bits(page->non_crit_ext.non_crit_ext.cmas_ind_r9, &msg_ptr, 1); + liblte_value_2_bits(page->non_crit_ext.non_crit_ext.cmas_ind_r9, &msg_ptr, 1); } if(page->non_crit_ext.non_crit_ext.non_crit_ext_present) @@ -9207,62 +12632,65 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_paging_msg(LIBLTE_BIT_MSG_STRUCT *msg, uint32 i; uint32 j; uint8 paging_record_list_present; + bool paging_record_ext_ind; if(msg != NULL && page != NULL) { // Optional indicators - paging_record_list_present = rrc_bits_2_value(&msg_ptr, 1); - page->system_info_modification_present = rrc_bits_2_value(&msg_ptr, 1); - page->etws_indication_present = rrc_bits_2_value(&msg_ptr, 1); - page->non_crit_ext_present = rrc_bits_2_value(&msg_ptr, 1); + paging_record_list_present = liblte_bits_2_value(&msg_ptr, 1); + page->system_info_modification_present = liblte_bits_2_value(&msg_ptr, 1); + page->etws_indication_present = liblte_bits_2_value(&msg_ptr, 1); + page->non_crit_ext_present = liblte_bits_2_value(&msg_ptr, 1); if(paging_record_list_present) { - page->paging_record_list_size = rrc_bits_2_value(&msg_ptr, 4) + 1; + page->paging_record_list_size = liblte_bits_2_value(&msg_ptr, 4) + 1; for(i=0; ipaging_record_list_size; i++) { // Extension indicator - rrc_bits_2_value(&msg_ptr, 1); + paging_record_ext_ind = liblte_bits_2_value(&msg_ptr, 1); // Paging UE identity { // Extension indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); - page->paging_record_list[i].ue_identity.ue_identity_type = (LIBLTE_RRC_PAGING_UE_IDENTITY_TYPE_ENUM)rrc_bits_2_value(&msg_ptr, 1); + page->paging_record_list[i].ue_identity.ue_identity_type = (LIBLTE_RRC_PAGING_UE_IDENTITY_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1); if(LIBLTE_RRC_PAGING_UE_IDENTITY_TYPE_S_TMSI == page->paging_record_list[i].ue_identity.ue_identity_type) { liblte_rrc_unpack_s_tmsi_ie(&msg_ptr, &page->paging_record_list[i].ue_identity.s_tmsi); }else{ - page->paging_record_list[i].ue_identity.imsi_size = rrc_bits_2_value(&msg_ptr, 4) + 6; + page->paging_record_list[i].ue_identity.imsi_size = liblte_bits_2_value(&msg_ptr, 4) + 6; for(j=0; jpaging_record_list[i].ue_identity.imsi_size; j++) { - page->paging_record_list[i].ue_identity.imsi[j] = rrc_bits_2_value(&msg_ptr, 4); + page->paging_record_list[i].ue_identity.imsi[j] = liblte_bits_2_value(&msg_ptr, 4); } } } - page->paging_record_list[i].cn_domain = (LIBLTE_RRC_CN_DOMAIN_ENUM)rrc_bits_2_value(&msg_ptr, 1); + page->paging_record_list[i].cn_domain = (LIBLTE_RRC_CN_DOMAIN_ENUM)liblte_bits_2_value(&msg_ptr, 1); + + skip_sequence_type_extension(paging_record_ext_ind, &msg_ptr); } } if(page->system_info_modification_present) { - page->system_info_modification = (LIBLTE_RRC_SYSTEM_INFO_MODIFICATION_ENUM)rrc_bits_2_value(&msg_ptr, 1); + page->system_info_modification = (LIBLTE_RRC_SYSTEM_INFO_MODIFICATION_ENUM)liblte_bits_2_value(&msg_ptr, 1); } if(page->etws_indication_present) { - page->etws_indication = (LIBLTE_RRC_ETWS_INDICATION_ENUM)rrc_bits_2_value(&msg_ptr, 1); + page->etws_indication = (LIBLTE_RRC_ETWS_INDICATION_ENUM)liblte_bits_2_value(&msg_ptr, 1); } if(page->non_crit_ext_present) { // Optional indicators - page->non_crit_ext.late_non_crit_ext_present = rrc_bits_2_value(&msg_ptr, 1); - page->non_crit_ext.non_crit_ext_present = rrc_bits_2_value(&msg_ptr, 1); + page->non_crit_ext.late_non_crit_ext_present = liblte_bits_2_value(&msg_ptr, 1); + page->non_crit_ext.non_crit_ext_present = liblte_bits_2_value(&msg_ptr, 1); if(page->non_crit_ext.late_non_crit_ext_present) { @@ -9272,12 +12700,12 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_paging_msg(LIBLTE_BIT_MSG_STRUCT *msg, if(page->non_crit_ext.non_crit_ext_present) { // Optional indicators - page->non_crit_ext.non_crit_ext.cmas_ind_present = rrc_bits_2_value(&msg_ptr, 1); - page->non_crit_ext.non_crit_ext.non_crit_ext_present = rrc_bits_2_value(&msg_ptr, 1); + page->non_crit_ext.non_crit_ext.cmas_ind_present = liblte_bits_2_value(&msg_ptr, 1); + page->non_crit_ext.non_crit_ext.non_crit_ext_present = liblte_bits_2_value(&msg_ptr, 1); if(page->non_crit_ext.non_crit_ext.cmas_ind_present) { - page->non_crit_ext.non_crit_ext.cmas_ind_r9 = (LIBLTE_RRC_CMAS_INDICATION_R9_ENUM)rrc_bits_2_value(&msg_ptr, 1); + page->non_crit_ext.non_crit_ext.cmas_ind_r9 = (LIBLTE_RRC_CMAS_INDICATION_R9_ENUM)liblte_bits_2_value(&msg_ptr, 1); } if(page->non_crit_ext.non_crit_ext.non_crit_ext_present) @@ -9360,7 +12788,87 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_paging_msg(LIBLTE_BIT_MSG_STRUCT *msg, Document Reference: 36.331 v10.0.0 Section 6.2.2 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_dl_information_transfer_msg(LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT *dl_info_transfer, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(dl_info_transfer != NULL && + msg != NULL) + { + // RRC Transaction ID + liblte_rrc_pack_rrc_transaction_identifier_ie(dl_info_transfer->rrc_transaction_id, + &msg_ptr); + + // Extension choice + liblte_value_2_bits(0, &msg_ptr, 1); + + // C1 choice + liblte_value_2_bits(0, &msg_ptr, 2); + + // Optional indicator + liblte_value_2_bits(0, &msg_ptr, 1); + + // Dedicated info type choice + liblte_value_2_bits(dl_info_transfer->dedicated_info_type, &msg_ptr, 2); + + if(LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_NAS == dl_info_transfer->dedicated_info_type) + { + liblte_rrc_pack_dedicated_info_nas_ie(&dl_info_transfer->dedicated_info, + &msg_ptr); + }else{ + liblte_rrc_pack_dedicated_info_cdma2000_ie(&dl_info_transfer->dedicated_info, + &msg_ptr); + } + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_dl_information_transfer_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT *dl_info_transfer) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + dl_info_transfer != NULL) + { + // RRC Transaction ID + liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, + &dl_info_transfer->rrc_transaction_id); + + // Extension choice + liblte_bits_2_value(&msg_ptr, 1); + + // C1 choice + liblte_bits_2_value(&msg_ptr, 2); + + // Optional indicator + liblte_bits_2_value(&msg_ptr, 1); + + // Dedicated info type choice + dl_info_transfer->dedicated_info_type = (LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 2); + + if(LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_NAS == dl_info_transfer->dedicated_info_type) + { + liblte_rrc_unpack_dedicated_info_nas_ie(&msg_ptr, + &dl_info_transfer->dedicated_info); + }else{ + liblte_rrc_unpack_dedicated_info_cdma2000_ie(&msg_ptr, + &dl_info_transfer->dedicated_info); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* Message Name: CSFB Parameters Response CDMA2000 @@ -9391,10 +12899,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_csfb_parameters_request_cdma2000_msg(LIBLTE_RR msg != NULL) { // Extension choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); // Optional indicator - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; err = LIBLTE_SUCCESS; } @@ -9411,10 +12922,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_csfb_parameters_request_cdma2000_msg(LIBLTE_ csfb_params_req_cdma2000 != NULL) { // Extension choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); // Optional indicator - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); err = LIBLTE_SUCCESS; } @@ -9462,16 +12973,16 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_bcch_bch_msg(LIBLTE_RRC_MIB_STRUCT *mib, msg != NULL) { // DL Bandwidth - rrc_value_2_bits(mib->dl_bw, &msg_ptr, 3); + liblte_value_2_bits(mib->dl_bw, &msg_ptr, 3); // PHICH Config liblte_rrc_pack_phich_config_ie(&mib->phich_config, &msg_ptr); // SFN/4 - rrc_value_2_bits(mib->sfn_div_4, &msg_ptr, 8); + liblte_value_2_bits(mib->sfn_div_4, &msg_ptr, 8); // Spare - rrc_value_2_bits(0, &msg_ptr, 10); + liblte_value_2_bits(0, &msg_ptr, 10); // Fill in the number of bits used msg->N_bits = msg_ptr - msg->msg; @@ -9491,13 +13002,13 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_bcch_bch_msg(LIBLTE_BIT_MSG_STRUCT *msg, mib != NULL) { // DL Bandwidth - mib->dl_bw = (LIBLTE_RRC_DL_BANDWIDTH_ENUM)rrc_bits_2_value(&msg_ptr, 3); + mib->dl_bw = (LIBLTE_RRC_DL_BANDWIDTH_ENUM)liblte_bits_2_value(&msg_ptr, 3); // PHICH Config liblte_rrc_unpack_phich_config_ie(&msg_ptr, &mib->phich_config); // SFN/4 - mib->sfn_div_4 = rrc_bits_2_value(&msg_ptr, 8); + mib->sfn_div_4 = liblte_bits_2_value(&msg_ptr, 8); err = LIBLTE_SUCCESS; } @@ -9525,12 +13036,12 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_bcch_dlsch_msg(LIBLTE_RRC_BCCH_DLSCH_MSG_STRUC msg != NULL) { // Extension indicator - rrc_value_2_bits(ext, &msg_ptr, 1); + liblte_value_2_bits(ext, &msg_ptr, 1); if(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == bcch_dlsch_msg->sibs[0].sib_type) { // SIB1 Choice - rrc_value_2_bits(1, &msg_ptr, 1); + liblte_value_2_bits(1, &msg_ptr, 1); err = liblte_rrc_pack_sys_info_block_type_1_msg((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *)&bcch_dlsch_msg->sibs[0].sib, &global_msg); @@ -9544,7 +13055,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_bcch_dlsch_msg(LIBLTE_RRC_BCCH_DLSCH_MSG_STRUC } }else{ // SIB1 Choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); err = liblte_rrc_pack_sys_info_msg(bcch_dlsch_msg, &global_msg); @@ -9573,10 +13084,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_bcch_dlsch_msg(LIBLTE_BIT_MSG_STRUCT bcch_dlsch_msg != NULL) { // Extension indicator - ext = rrc_bits_2_value(&msg_ptr, 1); + ext = liblte_bits_2_value(&msg_ptr, 1); // SIB1 Choice - if(true == rrc_bits_2_value(&msg_ptr, 1)) + if(true == liblte_bits_2_value(&msg_ptr, 1)) { bcch_dlsch_msg->N_sibs = 1; bcch_dlsch_msg->sibs[0].sib_type = LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1; @@ -9622,7 +13133,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_pcch_msg(LIBLTE_RRC_PCCH_MSG_STRUCT *pcch_msg, msg != NULL) { // Paging choice - rrc_value_2_bits(0, &msg_ptr, 1); + liblte_value_2_bits(0, &msg_ptr, 1); err = liblte_rrc_pack_paging_msg(pcch_msg, &global_msg); @@ -9649,7 +13160,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_pcch_msg(LIBLTE_BIT_MSG_STRUCT *msg, pcch_msg != NULL) { // Paging choice - rrc_bits_2_value(&msg_ptr, 1); + liblte_bits_2_value(&msg_ptr, 1); if((msg->N_bits-(msg_ptr-msg->msg)) <= (LIBLTE_MAX_MSG_SIZE - 1)) { @@ -9682,10 +13193,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_dl_ccch_msg(LIBLTE_RRC_DL_CCCH_MSG_STRUCT *dl_ msg != NULL) { // Extension indicator - rrc_value_2_bits(ext, &msg_ptr, 1); + liblte_value_2_bits(ext, &msg_ptr, 1); // Message type choice - rrc_value_2_bits(dl_ccch_msg->msg_type, &msg_ptr, 2); + liblte_value_2_bits(dl_ccch_msg->msg_type, &msg_ptr, 2); if(LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST == dl_ccch_msg->msg_type) { @@ -9725,10 +13236,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_dl_ccch_msg(LIBLTE_BIT_MSG_STRUCT *m dl_ccch_msg != NULL) { // Extension indicator - ext = rrc_bits_2_value(&msg_ptr, 1); + ext = liblte_bits_2_value(&msg_ptr, 1); // Message type choice - dl_ccch_msg->msg_type = (LIBLTE_RRC_DL_CCCH_MSG_TYPE_ENUM)rrc_bits_2_value(&msg_ptr, 2); + dl_ccch_msg->msg_type = (LIBLTE_RRC_DL_CCCH_MSG_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 2); // Message memcpy(global_msg.msg, msg_ptr, msg->N_bits-(msg_ptr-msg->msg)); @@ -9761,7 +13272,147 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_dl_ccch_msg(LIBLTE_BIT_MSG_STRUCT *m Document Reference: 36.331 v10.0.0 Section 6.2.1 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_dl_dcch_msg(LIBLTE_RRC_DL_DCCH_MSG_STRUCT *dl_dcch_msg, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 ext = false; + + if(dl_dcch_msg != NULL && + msg != NULL) + { + // Extension indicator + liblte_value_2_bits(ext, &msg_ptr, 1); + + // Message type choice + liblte_value_2_bits(dl_dcch_msg->msg_type, &msg_ptr, 4); + + // Message + if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_CSFB_PARAMS_RESP_CDMA2000 == dl_dcch_msg->msg_type) + { + printf("NOT HANDLING CSFB PARAMETERS RESPONSE CDMA2000\n"); +// err = liblte_rrc_pack_csfb_parameters_response_cdma2000_msg((LIBLTE_RRC_CSFB_PARAMETERS_RESPONSE_CDMA2000_STRUCT *)&dl_dcch_msg->msg, +// &global_msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_DL_INFO_TRANSFER == dl_dcch_msg->msg_type){ + err = liblte_rrc_pack_dl_information_transfer_msg((LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT *)&dl_dcch_msg->msg, + &global_msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_HANDOVER_FROM_EUTRA_PREP_REQ == dl_dcch_msg->msg_type){ + printf("NOT HANDLING HANDOVER FROM EUTRA PREPARATION REQUEST\n"); +// err = liblte_rrc_pack_handover_from_eutra_preparation_request_msg((LIBLTE_RRC_HANDOVER_FROM_EUTRA_PREPARATION_REQUEST_STRUCT *)&dl_dcch_msg->msg, +// &global_msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_MOBILITY_FROM_EUTRA_COMMAND == dl_dcch_msg->msg_type){ + printf("NOT HANDLING MOBILITY FROM EUTRA COMMAND\n"); +// err = liblte_rrc_pack_mobility_from_eutra_command_msg((LIBLTE_RRC_MOBILITY_FROM_EUTRA_COMMAND_STRUCT *)&dl_dcch_msg->msg, +// &global_msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RECONFIG == dl_dcch_msg->msg_type){ + err = liblte_rrc_pack_rrc_connection_reconfiguration_msg((LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *)&dl_dcch_msg->msg, + &global_msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RELEASE == dl_dcch_msg->msg_type){ + err = liblte_rrc_pack_rrc_connection_release_msg((LIBLTE_RRC_CONNECTION_RELEASE_STRUCT *)&dl_dcch_msg->msg, + &global_msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_SECURITY_MODE_COMMAND == dl_dcch_msg->msg_type){ + err = liblte_rrc_pack_security_mode_command_msg((LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT *)&dl_dcch_msg->msg, + &global_msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_CAPABILITY_ENQUIRY == dl_dcch_msg->msg_type){ + err = liblte_rrc_pack_ue_capability_enquiry_msg((LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT *)&dl_dcch_msg->msg, + &global_msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_COUNTER_CHECK == dl_dcch_msg->msg_type){ + printf("NOT HANDLING COUNTER CHECK\n"); +// err = liblte_rrc_pack_counter_check_msg((LIBLTE_RRC_COUNTER_CHECK_STRUCT *)&dl_dcch_msg->msg, +// &global_msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_INFO_REQ == dl_dcch_msg->msg_type){ + err = liblte_rrc_pack_ue_information_request_msg((LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT *)&dl_dcch_msg->msg, + &global_msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_LOGGED_MEASUREMENTS_CONFIG == dl_dcch_msg->msg_type){ + printf("NOT HANDLING LOGGED MEASUREMENTS CONFIGURATION\n"); +// err = liblte_rrc_pack_logged_measurements_configuration_msg((LIBLTE_RRC_LOGGED_MEASUREMENTS_CONFIGURATION_STRUCT *)&dl_dcch_msg->msg, +// &global_msg); + }else{ // LIBLTE_RRC_DL_DCCH_MSG_TYPE_RN_RECONFIG == dl_dcch_msg->msg_type + printf("NOT HANDLING RN RECONFIGURATION\n"); +// err = liblte_rrc_pack_rn_reconfiguration_msg((LIBLTE_RRC_RN_RECONFIGURATION_STRUCT *)&dl_dcch_msg->msg, +// &global_msg); + } + + if(global_msg.N_bits <= (LIBLTE_MAX_MSG_SIZE - 5)) + { + memcpy(msg_ptr, global_msg.msg, global_msg.N_bits); + msg->N_bits = global_msg.N_bits + 5; + }else{ + msg->N_bits = 0; + err = LIBLTE_ERROR_INVALID_INPUTS; + } + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_dl_dcch_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_DL_DCCH_MSG_STRUCT *dl_dcch_msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 ext; + + if(msg != NULL && + dl_dcch_msg != NULL) + { + // Extension indicator + ext = liblte_bits_2_value(&msg_ptr, 1); + + // Message type choice + dl_dcch_msg->msg_type = (LIBLTE_RRC_DL_DCCH_MSG_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 4); + + // Message + memcpy(global_msg.msg, msg_ptr, msg->N_bits-(msg_ptr-msg->msg)); + global_msg.N_bits = msg->N_bits-(msg_ptr-msg->msg); + if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_CSFB_PARAMS_RESP_CDMA2000 == dl_dcch_msg->msg_type) + { + printf("NOT HANDLING CSFB PARAMETERS RESPONSE CDMA2000\n"); +// err = liblte_rrc_unpack_csfb_parameters_response_cdma2000_msg(&global_msg, +// (LIBLTE_RRC_CSFB_PARAMETERS_RESPONSE_CDMA2000_STRUCT *)&dl_dcch_msg->msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_DL_INFO_TRANSFER == dl_dcch_msg->msg_type){ + err = liblte_rrc_unpack_dl_information_transfer_msg(&global_msg, + (LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT *)&dl_dcch_msg->msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_HANDOVER_FROM_EUTRA_PREP_REQ == dl_dcch_msg->msg_type){ + printf("NOT HANDLING HANDOVER FROM EUTRA PREPARATION REQUEST\n"); +// err = liblte_rrc_unpack_handover_from_eutra_preparation_request_msg(&global_msg, +// (LIBLTE_RRC_HANDOVER_FROM_EUTRA_PREPARATION_REQUEST_STRUCT *)&dl_dcch_msg->msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_MOBILITY_FROM_EUTRA_COMMAND == dl_dcch_msg->msg_type){ + printf("NOT HANDLING MOBILITY FROM EUTRA COMMAND\n"); +// err = liblte_rrc_unpack_mobility_from_eutra_command_msg(&global_msg, +// (LIBLTE_RRC_MOBILITY_FROM_EUTRA_COMMAND_STRUCT *)&dl_dcch_msg->msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RECONFIG == dl_dcch_msg->msg_type){ + err = liblte_rrc_unpack_rrc_connection_reconfiguration_msg(&global_msg, + (LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *)&dl_dcch_msg->msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RELEASE == dl_dcch_msg->msg_type){ + err = liblte_rrc_unpack_rrc_connection_release_msg(&global_msg, + (LIBLTE_RRC_CONNECTION_RELEASE_STRUCT *)&dl_dcch_msg->msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_SECURITY_MODE_COMMAND == dl_dcch_msg->msg_type){ + err = liblte_rrc_unpack_security_mode_command_msg(&global_msg, + (LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT *)&dl_dcch_msg->msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_CAPABILITY_ENQUIRY == dl_dcch_msg->msg_type){ + err = liblte_rrc_unpack_ue_capability_enquiry_msg(&global_msg, + (LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT *)&dl_dcch_msg->msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_COUNTER_CHECK == dl_dcch_msg->msg_type){ + printf("NOT HANDLING COUNTER CHECK\n"); +// err = liblte_rrc_unpack_counter_check_msg(&global_msg, +// (LIBLTE_RRC_COUNTER_CHECK_STRUCT *)&dl_dcch_msg->msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_INFO_REQ == dl_dcch_msg->msg_type){ + err = liblte_rrc_unpack_ue_information_request_msg(&global_msg, + (LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT *)&dl_dcch_msg->msg); + }else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_LOGGED_MEASUREMENTS_CONFIG == dl_dcch_msg->msg_type){ + printf("NOT HANDLING LOGGED MEASUREMENTS CONFIGURATION\n"); +// err = liblte_rrc_unpack_logged_measurements_configuration_msg(&global_msg, +// (LIBLTE_RRC_LOGGED_MEASUREMENTS_CONFIGURATION_STRUCT *)&dl_dcch_msg->msg); + }else{ // LIBLTE_RRC_DL_DCCH_MSG_TYPE_RN_RECONFIG == dl_dcch_msg->msg_type + printf("NOT HANDLING RN RECONFIGURATION\n"); +// err = liblte_rrc_unpack_rn_reconfiguration_msg(&global_msg, +// (LIBLTE_RRC_RN_RECONFIGURATION_STRUCT *)&dl_dcch_msg->msg); + } + } + + return(err); +} /********************************************************************* Message Name: UL CCCH Message @@ -9783,10 +13434,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_ccch_msg(LIBLTE_RRC_UL_CCCH_MSG_STRUCT *ul_ msg != NULL) { // Extension indicator - rrc_value_2_bits(ext, &msg_ptr, 1); + liblte_value_2_bits(ext, &msg_ptr, 1); // Message type choice - rrc_value_2_bits(ul_ccch_msg->msg_type, &msg_ptr, 1); + liblte_value_2_bits(ul_ccch_msg->msg_type, &msg_ptr, 1); if(LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REEST_REQ == ul_ccch_msg->msg_type) { @@ -9820,10 +13471,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_ccch_msg(LIBLTE_BIT_MSG_STRUCT *m ul_ccch_msg != NULL) { // Extension indicator - ext = rrc_bits_2_value(&msg_ptr, 1); + ext = liblte_bits_2_value(&msg_ptr, 1); // Message type choice - ul_ccch_msg->msg_type = (LIBLTE_RRC_UL_CCCH_MSG_TYPE_ENUM)rrc_bits_2_value(&msg_ptr, 1); + ul_ccch_msg->msg_type = (LIBLTE_RRC_UL_CCCH_MSG_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1); // Message memcpy(global_msg.msg, msg_ptr, msg->N_bits-(msg_ptr-msg->msg)); @@ -9861,10 +13512,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_dcch_msg(LIBLTE_RRC_UL_DCCH_MSG_STRUCT *ul_ msg != NULL) { // Extension indicator - rrc_value_2_bits(ext, &msg_ptr, 1); + liblte_value_2_bits(ext, &msg_ptr, 1); // Message type choice - rrc_value_2_bits(ul_dcch_msg->msg_type, &msg_ptr, 4); + liblte_value_2_bits(ul_dcch_msg->msg_type, &msg_ptr, 4); // Message if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_CSFB_PARAMS_REQ_CDMA2000 == ul_dcch_msg->msg_type) @@ -9891,17 +13542,15 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_dcch_msg(LIBLTE_RRC_UL_DCCH_MSG_STRUCT *ul_ err = liblte_rrc_pack_security_mode_failure_msg((LIBLTE_RRC_SECURITY_MODE_FAILURE_STRUCT *)&ul_dcch_msg->msg, &global_msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UE_CAPABILITY_INFO == ul_dcch_msg->msg_type){ - printf("NOT HANDLING UE CAPABILITY INFO\n"); -// err = liblte_rrc_pack_ue_capability_information_msg((LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *)&ul_dcch_msg->msg, -// &global_msg); + err = liblte_rrc_pack_ue_capability_information_msg((LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *)&ul_dcch_msg->msg, + &global_msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UL_HANDOVER_PREP_TRANSFER == ul_dcch_msg->msg_type){ printf("NOT HANDLING UL HANDOVER PREPARATION TRANSFER\n"); // err = liblte_rrc_pack_ul_handover_preparation_transfer_msg((LIBLTE_RRC_UL_HANDOVER_PREPARATION_TRANSFER_STRUCT *)&ul_dcch_msg->msg, // &global_msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UL_INFO_TRANSFER == ul_dcch_msg->msg_type){ - printf("NOT HANDLING UL INFORMATION TRANSFER\n"); -// err = liblte_rrc_pack_ul_information_transfer_msg((LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT *)&ul_dcch_msg->msg, -// &global_msg); + err = liblte_rrc_pack_ul_information_transfer_msg((LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT *)&ul_dcch_msg->msg, + &global_msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_COUNTER_CHECK_RESP == ul_dcch_msg->msg_type){ printf("NOT HANDLING COUNTER CHECK RESPONSE\n"); // err = liblte_rrc_pack_counter_check_response_msg((LIBLTE_RRC_COUNTER_CHECK_RESPONSE_STRUCT *)&ul_dcch_msg->msg, @@ -9941,10 +13590,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_dcch_msg(LIBLTE_BIT_MSG_STRUCT *m ul_dcch_msg != NULL) { // Extension indicator - ext = rrc_bits_2_value(&msg_ptr, 1); + ext = liblte_bits_2_value(&msg_ptr, 1); // Message type choice - ul_dcch_msg->msg_type = (LIBLTE_RRC_UL_DCCH_MSG_TYPE_ENUM)rrc_bits_2_value(&msg_ptr, 4); + ul_dcch_msg->msg_type = (LIBLTE_RRC_UL_DCCH_MSG_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 4); // Message memcpy(global_msg.msg, msg_ptr, msg->N_bits-(msg_ptr-msg->msg)); @@ -9973,17 +13622,15 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_dcch_msg(LIBLTE_BIT_MSG_STRUCT *m err = liblte_rrc_unpack_security_mode_failure_msg(&global_msg, (LIBLTE_RRC_SECURITY_MODE_FAILURE_STRUCT *)&ul_dcch_msg->msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UE_CAPABILITY_INFO == ul_dcch_msg->msg_type){ - printf("NOT HANDLING UE CAPABILITY INFO\n"); -// err = liblte_rrc_unpack_ue_capability_information_msg(&global_msg, -// (LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *)&ul_dcch_msg->msg); + err = liblte_rrc_unpack_ue_capability_information_msg(&global_msg, + (LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *)&ul_dcch_msg->msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UL_HANDOVER_PREP_TRANSFER == ul_dcch_msg->msg_type){ printf("NOT HANDLING UL HANDOVER PREPARATION TRANSFER\n"); // err = liblte_rrc_unpack_ul_handover_preparation_transfer_msg(&global_msg, // (LIBLTE_RRC_UL_HANDOVER_PREPARATION_TRANSFER_STRUCT *)&ul_dcch_msg->msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UL_INFO_TRANSFER == ul_dcch_msg->msg_type){ - printf("NOT HANDLING UL INFORMATION TRANSFER\n"); -// err = liblte_rrc_unpack_ul_information_transfer_msg(&global_msg, -// (LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT *)&ul_dcch_msg->msg); + err = liblte_rrc_unpack_ul_information_transfer_msg(&global_msg, + (LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT *)&ul_dcch_msg->msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_COUNTER_CHECK_RESP == ul_dcch_msg->msg_type){ printf("NOT HANDLING COUNTER CHECK RESPONSE\n"); // err = liblte_rrc_unpack_counter_check_response_msg(&global_msg, @@ -10009,39 +13656,47 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_dcch_msg(LIBLTE_BIT_MSG_STRUCT *m *******************************************************************************/ /********************************************************************* - Name: rrc_value_2_bits + Name: skip_sequence_type_extension - Description: Converts a value to a bit string + Description: Skips an ASN.1 sequence type extension + + Document Reference: ITU X.691 Section 18 *********************************************************************/ -void rrc_value_2_bits(uint32 value, - uint8 **bits, - uint32 N_bits) +void skip_sequence_type_extension(bool ext_ind, uint8 **ptr) { + uint32 num_extension_fields; + uint32 bits_to_skip; uint32 i; + uint32 ext_field_presence; - for(i=0; i> (N_bits-i-1)) & 0x1; - } - *bits += N_bits; -} - -/********************************************************************* - Name: rrc_bits_2_value + num_extension_fields = liblte_bits_2_value(ptr, 7) + 1; - Description: Converts a bit string to a value -*********************************************************************/ -uint32 rrc_bits_2_value(uint8 **bits, - uint32 N_bits) -{ - uint32 value = 0; - uint32 i; + ext_field_presence = liblte_bits_2_value(ptr, num_extension_fields); - for(i=0; i> (num_extension_fields - i - 1)) & 0x1) + { + if(0 == liblte_bits_2_value(ptr, 1)) + { + bits_to_skip = liblte_bits_2_value(ptr, 7) * 8; + }else{ + if(0 == liblte_bits_2_value(ptr, 1)) + { + bits_to_skip = liblte_bits_2_value(ptr, 14) * 8; + }else{ + // FIXME: Unlikely to have more than 16K bytes + } + } + while(bits_to_skip > 32) + { + liblte_bits_2_value(ptr, 32); + bits_to_skip -= 32; + } + liblte_bits_2_value(ptr, bits_to_skip); + } + } } - *bits += N_bits; - - return(value); } diff --git a/liblte/src/liblte_security.cc b/liblte/src/liblte_security.cc new file mode 100755 index 0000000..2b320e5 --- /dev/null +++ b/liblte/src/liblte_security.cc @@ -0,0 +1,1252 @@ +/******************************************************************************* + + Copyright 2014 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: liblte_security.cc + + Description: Contains all the implementations for the LTE security + algorithm library. + + Revision History + ---------- ------------- -------------------------------------------- + 08/03/2014 Ben Wojtowicz Created file. + 09/03/2014 Ben Wojtowicz Added key generation and EIA2 and fixed MCC + and MNC packing. + +*******************************************************************************/ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "liblte_security.h" +#include "mbedtls/aes.h" +#include "mbedtls/compat-1.3.h" +#include "mbedtls/ssl.h" +#include "math.h" + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + +typedef struct{ + uint8 rk[11][4][4]; +}ROUND_KEY_STRUCT; + +typedef struct{ + uint8 state[4][4]; +}STATE_STRUCT; + +/******************************************************************************* + GLOBAL VARIABLES +*******************************************************************************/ + +static const uint8 OP[16] = {0x63,0xBF,0xA5,0x0E,0xE6,0x52,0x33,0x65, + 0xFF,0x14,0xC1,0xF4,0x5F,0x88,0x73,0x7D}; + +static const uint8 S[256] = { 99,124,119,123,242,107,111,197, 48, 1,103, 43,254,215,171,118, + 202,130,201,125,250, 89, 71,240,173,212,162,175,156,164,114,192, + 183,253,147, 38, 54, 63,247,204, 52,165,229,241,113,216, 49, 21, + 4,199, 35,195, 24,150, 5,154, 7, 18,128,226,235, 39,178,117, + 9,131, 44, 26, 27,110, 90,160, 82, 59,214,179, 41,227, 47,132, + 83,209, 0,237, 32,252,177, 91,106,203,190, 57, 74, 76, 88,207, + 208,239,170,251, 67, 77, 51,133, 69,249, 2,127, 80, 60,159,168, + 81,163, 64,143,146,157, 56,245,188,182,218, 33, 16,255,243,210, + 205, 12, 19,236, 95,151, 68, 23,196,167,126, 61,100, 93, 25,115, + 96,129, 79,220, 34, 42,144,136, 70,238,184, 20,222, 94, 11,219, + 224, 50, 58, 10, 73, 6, 36, 92,194,211,172, 98,145,149,228,121, + 231,200, 55,109,141,213, 78,169,108, 86,244,234,101,122,174, 8, + 186,120, 37, 46, 28,166,180,198,232,221,116, 31, 75,189,139,138, + 112, 62,181,102, 72, 3,246, 14, 97, 53, 87,185,134,193, 29,158, + 225,248,152, 17,105,217,142,148,155, 30,135,233,206, 85, 40,223, + 140,161,137, 13,191,230, 66,104, 65,153, 45, 15,176, 84,187, 22}; + +static const uint8 X_TIME[256] = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, + 96, 98,100,102,104,106,108,110,112,114,116,118,120,122,124,126, + 128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158, + 160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190, + 192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222, + 224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254, + 27, 25, 31, 29, 19, 17, 23, 21, 11, 9, 15, 13, 3, 1, 7, 5, + 59, 57, 63, 61, 51, 49, 55, 53, 43, 41, 47, 45, 35, 33, 39, 37, + 91, 89, 95, 93, 83, 81, 87, 85, 75, 73, 79, 77, 67, 65, 71, 69, + 123,121,127,125,115,113,119,117,107,105,111,109, 99, 97,103,101, + 155,153,159,157,147,145,151,149,139,137,143,141,131,129,135,133, + 187,185,191,189,179,177,183,181,171,169,175,173,163,161,167,165, + 219,217,223,221,211,209,215,213,203,201,207,205,195,193,199,197, + 251,249,255,253,243,241,247,245,235,233,239,237,227,225,231,229}; + +/******************************************************************************* + LOCAL FUNCTION PROTOTYPES +*******************************************************************************/ + +/********************************************************************* + Name: compute_OPc + + Description: Computes OPc from OP and K. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void compute_OPc(ROUND_KEY_STRUCT *rk, + uint8 *op, + uint8 *op_c); + +/********************************************************************* + Name: rijndael_key_schedule + + Description: Computes all Rijndael's internal subkeys from key. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void rijndael_key_schedule(uint8 *key, + ROUND_KEY_STRUCT *rk); + +/********************************************************************* + Name: rijndael_encrypt + + Description: Computes output using input and round keys. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void rijndael_encrypt(uint8 *input, + ROUND_KEY_STRUCT *rk, + uint8 *output); + +/********************************************************************* + Name: key_add + + Description: Round key addition function. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void key_add(STATE_STRUCT *state, + ROUND_KEY_STRUCT *rk, + uint32 round); + +/********************************************************************* + Name: byte_sub + + Description: Byte substitution transformation. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void byte_sub(STATE_STRUCT *state); + +/********************************************************************* + Name: shift_row + + Description: Row shift transformation. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void shift_row(STATE_STRUCT *state); + +/********************************************************************* + Name: mix_column + + Description: Mix column transformation. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +// Defines +// Enums +// Structs +// Functions +void mix_column(STATE_STRUCT *state); + +/******************************************************************************* + FUNCTIONS +*******************************************************************************/ + +/********************************************************************* + Name: liblte_security_generate_k_asme + + Description: Generate the security key Kasme. + + Document Reference: 33.401 v10.0.0 Annex A.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_generate_k_asme(uint8 *ck, + uint8 *ik, + uint8 *ak, + uint8 *sqn, + uint16 mcc, + uint16 mnc, + uint8 *k_asme) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint32 i; + uint8 s[14]; + uint8 key[32]; + + if(ck != NULL && + ik != NULL && + ak != NULL && + sqn != NULL && + k_asme != NULL) + { + // Construct S + s[0] = 0x10; // FC + s[1] = (((mcc/10) % 10) << 4) | ((mcc/100) % 10); // First byte of P0 + if(mnc < 100) + { + s[2] = 0xF0 | (mcc % 10); // Second byte of P0 + s[3] = ((mnc % 10) << 4) | ((mnc/10) % 10); // Third byte of P0 + }else{ + s[2] = ((mnc % 10) << 4) | (mcc % 10); // Second byte of P0 + s[3] = (((mnc/10) % 10) << 4) | ((mnc/100) % 10); // Third byte of P0 + } + s[4] = 0x00; // First byte of L0 + s[5] = 0x03; // Second byte of L0 + for(i=0; i<6; i++) + { + s[6+i] = sqn[i] ^ ak[i]; // P1 + } + s[12] = 0x00; // First byte of L1 + s[13] = 0x06; // Second byte of L1 + + // Construct Key + for(i=0; i<16; i++) + { + key[i] = ck[i]; + key[16+i] = ik[i]; + } + + // Derive Kasme + //sha2_hmac(key, 32, s, 14, k_asme, 0); + md_hmac(md_info_from_type(MBEDTLS_MD_SHA256), key, 32, s, 14, k_asme); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Name: liblte_security_generate_k_enb + + Description: Generate the security key Kenb. + + Document Reference: 33.401 v10.0.0 Annex A.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_generate_k_enb(uint8 *k_asme, + uint32 nas_count, + uint8 *k_enb) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 s[7]; + + if(k_asme != NULL && + k_enb != NULL) + { + // Construct S + s[0] = 0x11; // FC + s[1] = (nas_count >> 24) & 0xFF; // First byte of P0 + s[2] = (nas_count >> 16) & 0xFF; // Second byte of P0 + s[3] = (nas_count >> 8) & 0xFF; // Third byte of P0 + s[4] = nas_count & 0xFF; // Fourth byte of P0 + s[5] = 0x00; // First byte of L0 + s[6] = 0x04; // Second byte of L0 + + // Derive Kenb + //sha2_hmac(k_asme, 32, s, 7, k_enb, 0); + md_hmac(md_info_from_type(MBEDTLS_MD_SHA256), k_asme, 32, s, 7, k_enb); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Name: liblte_security_generate_k_nas + + Description: Generate the NAS security keys KNASenc and KNASint. + + Document Reference: 33.401 v10.0.0 Annex A.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_generate_k_nas(uint8 *k_asme, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8 *k_nas_enc, + uint8 *k_nas_int) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 s[7]; + + if(k_asme != NULL && + k_nas_enc != NULL && + k_nas_int != NULL) + { + // Construct S for KNASenc + s[0] = 0x15; // FC + s[1] = 0x01; // P0 + s[2] = 0x00; // First byte of L0 + s[3] = 0x01; // Second byte of L0 + s[4] = enc_alg_id; // P1 + s[5] = 0x00; // First byte of L1 + s[6] = 0x01; // Second byte of L1 + + // Derive KNASenc + //sha2_hmac(k_asme, 32, s, 7, k_nas_enc, 0); + md_hmac(md_info_from_type(MBEDTLS_MD_SHA256), k_asme, 32, s, 7, k_nas_enc); + + // Construct S for KNASint + s[0] = 0x15; // FC + s[1] = 0x02; // P0 + s[2] = 0x00; // First byte of L0 + s[3] = 0x01; // Second byte of L0 + s[4] = int_alg_id; // P1 + s[5] = 0x00; // First byte of L1 + s[6] = 0x01; // Second byte of L1 + + // Derive KNASint + //sha2_hmac(k_asme, 32, s, 7, k_nas_int, 0); + md_hmac(md_info_from_type(MBEDTLS_MD_SHA256), k_asme, 32, s, 7, k_nas_int); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Name: liblte_security_generate_k_rrc + + Description: Generate the RRC security keys KRRCenc and KRRCint. + + Document Reference: 33.401 v10.0.0 Annex A.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_generate_k_rrc(uint8 *k_enb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8 *k_rrc_enc, + uint8 *k_rrc_int) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 s[7]; + + if(k_enb != NULL && + k_rrc_enc != NULL && + k_rrc_int != NULL) + { + // Construct S for KRRCenc + s[0] = 0x15; // FC + s[1] = 0x03; // P0 + s[2] = 0x00; // First byte of L0 + s[3] = 0x01; // Second byte of L0 + s[4] = enc_alg_id; // P1 + s[5] = 0x00; // First byte of L1 + s[6] = 0x01; // Second byte of L1 + + // Derive KRRCenc + //sha2_hmac(k_enb, 32, s, 7, k_rrc_enc, 0); + md_hmac(md_info_from_type(MBEDTLS_MD_SHA256), k_enb, 32, s, 7, k_rrc_enc); + + // Construct S for KRRCint + s[0] = 0x15; // FC + s[1] = 0x04; // P0 + s[2] = 0x00; // First byte of L0 + s[3] = 0x01; // Second byte of L0 + s[4] = int_alg_id; // P1 + s[5] = 0x00; // First byte of L1 + s[6] = 0x01; // Second byte of L1 + + // Derive KRRCint + //sha2_hmac(k_enb, 32, s, 7, k_rrc_int, 0); + md_hmac(md_info_from_type(MBEDTLS_MD_SHA256), k_enb, 32, s, 7, k_rrc_int); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Name: liblte_security_generate_k_up + + Description: Generate the user plane security keys KUPenc and + KUPint. + + Document Reference: 33.401 v10.0.0 Annex A.2 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_generate_k_up(uint8 *k_enb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8 *k_up_enc, + uint8 *k_up_int) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 s[7]; + + if(k_enb != NULL && + k_up_enc != NULL && + k_up_int != NULL) + { + // Construct S for KUPenc + s[0] = 0x15; // FC + s[1] = 0x05; // P0 + s[2] = 0x00; // First byte of L0 + s[3] = 0x01; // Second byte of L0 + s[4] = enc_alg_id; // P1 + s[5] = 0x00; // First byte of L1 + s[6] = 0x01; // Second byte of L1 + + // Derive KUPenc + //sha2_hmac(k_enb, 32, s, 7, k_up_enc, 0); + md_hmac(md_info_from_type(MBEDTLS_MD_SHA256), k_enb, 32, s, 7, k_up_enc); + + // Construct S for KUPint + s[0] = 0x15; // FC + s[1] = 0x06; // P0 + s[2] = 0x00; // First byte of L0 + s[3] = 0x01; // Second byte of L0 + s[4] = int_alg_id; // P1 + s[5] = 0x00; // First byte of L1 + s[6] = 0x01; // Second byte of L1 + + // Derive KUPint + //sha2_hmac(k_enb, 32, s, 7, k_up_int, 0); + md_hmac(md_info_from_type(MBEDTLS_MD_SHA256), k_enb, 32, s, 7, k_up_int); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Name: liblte_security_128_eia2 + + Description: 128-bit integrity algorithm EIA2. + + Document Reference: 33.401 v10.0.0 Annex B.2.3 + 33.102 v10.0.0 Section 6.5.4 + RFC4493 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_128_eia2(uint8 *key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8 *msg, + uint32 msg_len, + uint8 *mac) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 M[msg_len+8+16]; + aes_context ctx; + uint32 i; + uint32 j; + uint32 n; + uint32 pad_bits; + uint8 const_zero[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint8 L[16]; + uint8 K1[16]; + uint8 K2[16]; + uint8 T[16]; + uint8 tmp[16]; + + if(key != NULL && + msg != NULL && + mac != NULL) + { + // Subkey L generation + aes_setkey_enc(&ctx, key, 128); + aes_crypt_ecb(&ctx, AES_ENCRYPT, const_zero, L); + + // Subkey K1 generation + for(i=0; i<15; i++) + { + K1[i] = (L[i] << 1) | ((L[i+1] >> 7) & 0x01); + } + K1[15] = L[15] << 1; + if(L[0] & 0x80) + { + K1[15] ^= 0x87; + } + + // Subkey K2 generation + for(i=0; i<15; i++) + { + K2[i] = (K1[i] << 1) | ((K1[i+1] >> 7) & 0x01); + } + K2[15] = K1[15] << 1; + if(K1[0] & 0x80) + { + K2[15] ^= 0x87; + } + + // Construct M + memset(M, 0, msg_len+8+16); + M[0] = (count >> 24) & 0xFF; + M[1] = (count >> 16) & 0xFF; + M[2] = (count >> 8) & 0xFF; + M[3] = count & 0xFF; + M[4] = (bearer << 3) | (direction << 2); + for(i=0; iN_bits*8+8+16]; + aes_context ctx; + uint32 i; + uint32 j; + uint32 n; + uint32 pad_bits; + uint8 const_zero[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint8 L[16]; + uint8 K1[16]; + uint8 K2[16]; + uint8 T[16]; + uint8 tmp[16]; + + if(key != NULL && + msg != NULL && + mac != NULL) + { + // Subkey L generation + aes_setkey_enc(&ctx, key, 128); + aes_crypt_ecb(&ctx, AES_ENCRYPT, const_zero, L); + + // Subkey K1 generation + for(i=0; i<15; i++) + { + K1[i] = (L[i] << 1) | ((L[i+1] >> 7) & 0x01); + } + K1[15] = L[15] << 1; + if(L[0] & 0x80) + { + K1[15] ^= 0x87; + } + + // Subkey K2 generation + for(i=0; i<15; i++) + { + K2[i] = (K1[i] << 1) | ((K1[i+1] >> 7) & 0x01); + } + K2[15] = K1[15] << 1; + if(K1[0] & 0x80) + { + K2[15] ^= 0x87; + } + + // Construct M + memset(M, 0, msg->N_bits*8+8+16); + M[0] = (count >> 24) & 0xFF; + M[1] = (count >> 16) & 0xFF; + M[2] = (count >> 8) & 0xFF; + M[3] = count & 0xFF; + M[4] = (bearer << 3) | (direction << 2); + for(i=0; iN_bits/8; i++) + { + M[8+i] = 0; + for(j=0; j<8; j++) + { + M[8+i] |= msg->msg[i*8+j] << (7-j); + } + } + if((msg->N_bits % 8) != 0) + { + M[8+i] = 0; + for(j=0; jN_bits % 8; j++) + { + M[8+i] |= msg->msg[i*8+j] << (7-j); + } + } + + // MAC generation + n = (uint32)(ceilf((float)(msg->N_bits+64)/(float)(128))); + for(i=0; i<16; i++) + { + T[i] = 0; + } + for(i=0; iN_bits + 64) % 128; + if(pad_bits == 0) + { + for(j=0; j<16; j++) + { + tmp[j] = T[j] ^ K1[j] ^ M[i*16 + j]; + } + aes_crypt_ecb(&ctx, AES_ENCRYPT, tmp, T); + }else{ + pad_bits = (128 - pad_bits) - 1; + M[i*16 + (15 - (pad_bits/8))] |= 0x1 << (pad_bits % 8); + for(j=0; j<16; j++) + { + tmp[j] = T[j] ^ K2[j] ^ M[i*16 + j]; + } + aes_crypt_ecb(&ctx, AES_ENCRYPT, tmp, T); + } + + for(i=0; i<4; i++) + { + mac[i] = T[i]; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Name: liblte_security_milenage_f1 + + Description: Milenage security function F1. Computes network + authentication code MAC-A from key K, random + challenge RAND, sequence number SQN, and + authentication management field AMF. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8 *k, + uint8 *rand, + uint8 *sqn, + uint8 *amf, + uint8 *mac_a) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + ROUND_KEY_STRUCT round_keys; + uint32 i; + uint8 op_c[16]; + uint8 temp[16]; + uint8 in1[16]; + uint8 out1[16]; + uint8 rijndael_input[16]; + + if(k != NULL && + rand != NULL && + sqn != NULL && + amf != NULL && + mac_a != NULL) + { + // Initialize the round keys + rijndael_key_schedule(k, &round_keys); + + // Compute OPc + compute_OPc(&round_keys, (uint8 *)OP, op_c); + + // Compute temp + for(i=0; i<16; i++) + { + rijndael_input[i] = rand[i] ^ op_c[i]; + } + rijndael_encrypt(rijndael_input, &round_keys, temp); + + // Construct in1 + for(i=0; i<6; i++) + { + in1[i] = sqn[i]; + in1[i+8] = sqn[i]; + } + for(i=0; i<2; i++) + { + in1[i+6] = amf[i]; + in1[i+14] = amf[i]; + } + + // Compute out1 + for(i=0; i<16; i++) + { + rijndael_input[(i+8) % 16] = in1[i] ^ op_c[i]; + } + for(i=0; i<16; i++) + { + rijndael_input[i] ^= temp[i]; + } + rijndael_encrypt(rijndael_input, &round_keys, out1); + for(i=0; i<16; i++) + { + out1[i] ^= op_c[i]; + } + + // Return MAC-A + for(i=0; i<8; i++) + { + mac_a[i] = out1[i]; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Name: liblte_security_milenage_f1_star + + Description: Milenage security function F1*. Computes resynch + authentication code MAC-S from key K, random + challenge RAND, sequence number SQN, and + authentication management field AMF. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_milenage_f1_star(uint8 *k, + uint8 *rand, + uint8 *sqn, + uint8 *amf, + uint8 *mac_s) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + ROUND_KEY_STRUCT round_keys; + uint32 i; + uint8 op_c[16]; + uint8 temp[16]; + uint8 in1[16]; + uint8 out1[16]; + uint8 rijndael_input[16]; + + if(k != NULL && + rand != NULL && + sqn != NULL && + amf != NULL && + mac_s != NULL) + { + // Initialize the round keys + rijndael_key_schedule(k, &round_keys); + + // Compute OPc + compute_OPc(&round_keys, (uint8 *)OP, op_c); + + // Compute temp + for(i=0; i<16; i++) + { + rijndael_input[i] = rand[i] ^ op_c[i]; + } + rijndael_encrypt(rijndael_input, &round_keys, temp); + + // Construct in1 + for(i=0; i<6; i++) + { + in1[i] = sqn[i]; + in1[i+8] = sqn[i]; + } + for(i=0; i<2; i++) + { + in1[i+6] = amf[i]; + in1[i+14] = amf[i]; + } + + // Compute out1 + for(i=0; i<16; i++) + { + rijndael_input[(i+8) % 16] = in1[i] ^ op_c[i]; + } + for(i=0; i<16; i++) + { + rijndael_input[i] ^= temp[i]; + } + rijndael_encrypt(rijndael_input, &round_keys, out1); + for(i=0; i<16; i++) + { + out1[i] ^= op_c[i]; + } + + // Return MAC-S + for(i=0; i<8; i++) + { + mac_s[i] = out1[i+8]; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Name: liblte_security_milenage_f2345 + + Description: Milenage security functions F2, F3, F4, and F5. + Computes response RES, confidentiality key CK, + integrity key IK, and anonymity key AK from random + challenge RAND. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_milenage_f2345(uint8 *k, + uint8 *rand, + uint8 *res, + uint8 *ck, + uint8 *ik, + uint8 *ak) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + ROUND_KEY_STRUCT round_keys; + uint32 i; + uint8 op_c[16]; + uint8 temp[16]; + uint8 out[16]; + uint8 rijndael_input[16]; + + if(k != NULL && + rand != NULL && + res != NULL && + ck != NULL && + ik != NULL && + ak != NULL) + { + // Initialize the round keys + rijndael_key_schedule(k, &round_keys); + + // Compute OPc + compute_OPc(&round_keys, (uint8 *)OP, op_c); + + // Compute temp + for(i=0; i<16; i++) + { + rijndael_input[i] = rand[i] ^ op_c[i]; + } + rijndael_encrypt(rijndael_input, &round_keys, temp); + + // Compute out for RES and AK + for(i=0; i<16; i++) + { + rijndael_input[i] = temp[i] ^ op_c[i]; + } + rijndael_input[15] ^= 1; + rijndael_encrypt(rijndael_input, &round_keys, out); + for(i=0; i<16; i++) + { + out[i] ^= op_c[i]; + } + + // Return RES + for(i=0; i<8; i++) + { + res[i] = out[i+8]; + } + + // Return AK + for(i=0; i<6; i++) + { + ak[i] = out[i]; + } + + // Compute out for CK + for(i=0; i<16; i++) + { + rijndael_input[(i+12) % 16] = temp[i] ^ op_c[i]; + } + rijndael_input[15] ^= 2; + rijndael_encrypt(rijndael_input, &round_keys, out); + for(i=0; i<16; i++) + { + out[i] ^= op_c[i]; + } + + // Return CK + for(i=0; i<16; i++) + { + ck[i] = out[i]; + } + + // Compute out for IK + for(i=0; i<16; i++) + { + rijndael_input[(i+8) % 16] = temp[i] ^ op_c[i]; + } + rijndael_input[15] ^= 4; + rijndael_encrypt(rijndael_input, &round_keys, out); + for(i=0; i<16; i++) + { + out[i] ^= op_c[i]; + } + + // Return IK + for(i=0; i<16; i++) + { + ik[i] = out[i]; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Name: liblte_security_milenage_f5_star + + Description: Milenage security function F5*. Computes resynch + anonymity key AK from key K and random challenge + RAND. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_milenage_f5_star(uint8 *k, + uint8 *rand, + uint8 *ak) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + ROUND_KEY_STRUCT round_keys; + uint32 i; + uint8 op_c[16]; + uint8 temp[16]; + uint8 out[16]; + uint8 rijndael_input[16]; + + if(k != NULL && + rand != NULL && + ak != NULL) + { + // Initialize the round keys + rijndael_key_schedule(k, &round_keys); + + // Compute OPc + compute_OPc(&round_keys, (uint8 *)OP, op_c); + + // Compute temp + for(i=0; i<16; i++) + { + rijndael_input[i] = rand[i] ^ op_c[i]; + } + rijndael_encrypt(rijndael_input, &round_keys, temp); + + // Compute out + for(i=0; i<16; i++) + { + rijndael_input[(i+4) % 16] = temp[i] ^ op_c[i]; + } + rijndael_input[15] ^= 8; + rijndael_encrypt(rijndael_input, &round_keys, out); + for(i=0; i<16; i++) + { + out[i] ^= op_c[i]; + } + + // Return AK + for(i=0; i<6; i++) + { + ak[i] = out[i]; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/******************************************************************************* + LOCAL FUNCTIONS +*******************************************************************************/ + +/********************************************************************* + Name: compute_OPc + + Description: Computes OPc from OP and K. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +void compute_OPc(ROUND_KEY_STRUCT *rk, + uint8 *op, + uint8 *op_c) +{ + uint32 i; + + rijndael_encrypt(op, rk, op_c); + for(i=0; i<16; i++) + { + op_c[i] ^= op[i]; + } +} + +/********************************************************************* + Name: rijndael_key_schedule + + Description: Computes all Rijndael's internal subkeys from key. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +void rijndael_key_schedule(uint8 *key, + ROUND_KEY_STRUCT *rk) +{ + uint32 i; + uint32 j; + uint8 round_const; + + // Set first round key to key + for(i=0; i<16; i++) + { + rk->rk[0][i & 0x03][i >> 2] = key[i]; + } + + round_const = 1; + + // Compute the remaining round keys + for(i=1; i<11; i++) + { + rk->rk[i][0][0] = S[rk->rk[i-1][1][3]] ^ rk->rk[i-1][0][0] ^ round_const; + rk->rk[i][1][0] = S[rk->rk[i-1][2][3]] ^ rk->rk[i-1][1][0]; + rk->rk[i][2][0] = S[rk->rk[i-1][3][3]] ^ rk->rk[i-1][2][0]; + rk->rk[i][3][0] = S[rk->rk[i-1][0][3]] ^ rk->rk[i-1][3][0]; + + for(j=0; j<4; j++) + { + rk->rk[i][j][1] = rk->rk[i-1][j][1] ^ rk->rk[i][j][0]; + rk->rk[i][j][2] = rk->rk[i-1][j][2] ^ rk->rk[i][j][1]; + rk->rk[i][j][3] = rk->rk[i-1][j][3] ^ rk->rk[i][j][2]; + } + + round_const = X_TIME[round_const]; + } +} + +/********************************************************************* + Name: rijndael_encrypt + + Description: Computes output using input and round keys. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +void rijndael_encrypt(uint8 *input, + ROUND_KEY_STRUCT *rk, + uint8 *output) +{ + STATE_STRUCT state; + uint32 i; + uint32 r; + + // Initialize and perform round 0 + for(i=0; i<16; i++) + { + state.state[i & 0x03][i >> 2] = input[i]; + } + key_add(&state, rk, 0); + + // Perform rounds 1 through 9 + for(r=1; r<=9; r++) + { + byte_sub(&state); + shift_row(&state); + mix_column(&state); + key_add(&state, rk, r); + } + + // Perform round 10 + byte_sub(&state); + shift_row(&state); + key_add(&state, rk, r); + + // Return output + for(i=0; i<16; i++) + { + output[i] = state.state[i & 0x03][i >> 2]; + } +} + +/********************************************************************* + Name: key_add + + Description: Round key addition function. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +void key_add(STATE_STRUCT *state, + ROUND_KEY_STRUCT *rk, + uint32 round) +{ + uint32 i; + uint32 j; + + for(i=0; i<4; i++) + { + for(j=0; j<4; j++) + { + state->state[i][j] ^= rk->rk[round][i][j]; + } + } +} + +/********************************************************************* + Name: byte_sub + + Description: Byte substitution transformation. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +void byte_sub(STATE_STRUCT *state) +{ + uint32 i; + uint32 j; + + for(i=0; i<4; i++) + { + for(j=0; j<4; j++) + { + state->state[i][j] = S[state->state[i][j]]; + } + } +} + +/********************************************************************* + Name: shift_row + + Description: Row shift transformation. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +void shift_row(STATE_STRUCT *state) +{ + uint8 temp; + + // Left rotate row 1 by 1 + temp = state->state[1][0]; + state->state[1][0] = state->state[1][1]; + state->state[1][1] = state->state[1][2]; + state->state[1][2] = state->state[1][3]; + state->state[1][3] = temp; + + // Left rotate row 2 by 2 + temp = state->state[2][0]; + state->state[2][0] = state->state[2][2]; + state->state[2][2] = temp; + temp = state->state[2][1]; + state->state[2][1] = state->state[2][3]; + state->state[2][3] = temp; + + // Left rotate row 3 by 3 + temp = state->state[3][0]; + state->state[3][0] = state->state[3][3]; + state->state[3][3] = state->state[3][2]; + state->state[3][2] = state->state[3][1]; + state->state[3][1] = temp; +} + +/********************************************************************* + Name: mix_column + + Description: Mix column transformation. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +void mix_column(STATE_STRUCT *state) +{ + uint32 i; + uint8 temp; + uint8 tmp0; + uint8 tmp; + + for(i=0; i<4; i++) + { + temp = state->state[0][i] ^ state->state[1][i] ^ state->state[2][i] ^ state->state[3][i]; + tmp0 = state->state[0][i]; + + tmp = X_TIME[state->state[0][i] ^ state->state[1][i]]; + state->state[0][i] ^= temp ^ tmp; + + tmp = X_TIME[state->state[1][i] ^ state->state[2][i]]; + state->state[1][i] ^= temp ^ tmp; + + tmp = X_TIME[state->state[2][i] ^ state->state[3][i]]; + state->state[2][i] ^= temp ^ tmp; + + tmp = X_TIME[state->state[3][i] ^ tmp0]; + state->state[3][i] ^= temp ^ tmp; + } +} diff --git a/liblte/tests/liblte_common_tests.cc b/liblte/tests/liblte_common_tests.cc new file mode 100755 index 0000000..a665dc2 --- /dev/null +++ b/liblte/tests/liblte_common_tests.cc @@ -0,0 +1,99 @@ +/******************************************************************************* + + Copyright 2017 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: liblte_common_tests.cc + + Description: Contains all the tests for the LTE common library. + + Revision History + ---------- ------------- -------------------------------------------- + 07/29/2017 Ben Wojtowicz Created file. + +*******************************************************************************/ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "liblte_common.h" + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + GLOBAL VARIABLES +*******************************************************************************/ + + +/******************************************************************************* + FUNCTIONS +*******************************************************************************/ + +int main(int argc, char *argv[]) +{ + uint32 i; + uint32 j; + uint32 value; + uint8 bits[32]; + uint8 *bits_ptr; + + // Check liblte_value_2_bits with single bit values + for(i=0; i<32; i++) + { + bits_ptr = &bits[0]; + liblte_value_2_bits(1<. + +******************************************************************************* + + File: libtools_helpers.h + + Description: Contains all the definitions for helper functions. + + Revision History + ---------- ------------- -------------------------------------------- + 07/29/2017 Ben Wojtowicz Created file + +*******************************************************************************/ + +#ifndef __LIBTOOLS_HELPERS_H__ +#define __LIBTOOLS_HELPERS_H__ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "typedefs.h" +#include + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + FORWARD DECLARATIONS +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + FUNCTION DECLARATIONS +*******************************************************************************/ + +/********************************************************************* + Name: to_string + + Description: Converts various types to a string. +*********************************************************************/ +std::string to_string(int32 value); +std::string to_string(uint32 value); +std::string to_string(int64 value); +std::string to_string(uint64 value); +std::string to_string(uint64 value, uint32 num_digits); +std::string to_string(uint8 *value, uint32 num_bytes); +std::string to_string(double value); +std::string to_string(const char *value); + +/********************************************************************* + Name: to_number + + Description: Converts a string to various types. +*********************************************************************/ +// FIXME: Use template +bool to_number(std::string str, uint16 *number); +bool to_number(std::string str, uint64 *number); +bool to_number(std::string str, uint32 num_digits, uint16 *number); +bool to_number(std::string str, uint32 num_digits, uint64 *number); +bool to_number(std::string str, uint32 num_bytes, uint8 *number); + +/********************************************************************* + Name: get_formatted_time + + Description: Populates a string with a formatted time. +*********************************************************************/ +void get_formatted_time(std::string &time_string); + +/********************************************************************* + Name: is_string_valid_as_number + + Description: Checks if the string is valid as a number (base 10 + or 16) and is of a specific number of digits. +*********************************************************************/ +bool is_string_valid_as_number(std::string str, uint32 num_digits, uint8 base); + +#endif /* __LIBTOOLS_HELPERS_H__ */ diff --git a/libtools/hdr/libtools_ipc_msgq.h b/libtools/hdr/libtools_ipc_msgq.h new file mode 100755 index 0000000..c0144d6 --- /dev/null +++ b/libtools/hdr/libtools_ipc_msgq.h @@ -0,0 +1,154 @@ +/******************************************************************************* + + Copyright 2017 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: libtools_ipc_msgq.h + + Description: Contains all the definitions for the interprocess message + queue abstraction tool. + + Revision History + ---------- ------------- -------------------------------------------- + 07/29/2017 Ben Wojtowicz Created file + +*******************************************************************************/ + +#ifndef __LIBTOOLS_IPC_MSGQ_H__ +#define __LIBTOOLS_IPC_MSGQ_H__ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "typedefs.h" +#include "liblte_phy.h" +#include + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + FORWARD DECLARATIONS +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +typedef enum{ + LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_KILL = 0, + LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_RACH, + LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_MAC_PDU, + LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_RAR_PDU, + LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_UL_ALLOC, + LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_PHY_SAMPS, + LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_N_ITEMS, +}LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_ENUM; +static const char libtools_ipc_msgq_message_type_text[LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_N_ITEMS][100] = {"Kill", + "RACH", + "MAC PDU", + "RAR PDU", + "UL ALLOC", + "PHY SAMPS"}; + +typedef struct{ + uint32 preamble; +}LIBTOOLS_IPC_MSGQ_RACH_MSG_STRUCT; + +typedef struct{ + LIBLTE_BIT_MSG_STRUCT msg; + uint16 rnti; +}LIBTOOLS_IPC_MSGQ_MAC_PDU_MSG_STRUCT; + +typedef struct{ + LIBLTE_BIT_MSG_STRUCT msg; + uint32 tti; +}LIBTOOLS_IPC_MSGQ_RAR_PDU_MSG_STRUCT; + +typedef struct{ + uint32 size; + uint32 tti; +}LIBTOOLS_IPC_MSGQ_UL_ALLOC_MSG_STRUCT; + +typedef struct{ + float i_buf[4][LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ]; + float q_buf[4][LIBLTE_PHY_N_SAMPS_PER_SUBFR_30_72MHZ]; + uint32 N_samps_per_ant; + uint16 current_tti; + uint8 N_ant; +}LIBTOOLS_IPC_MSGQ_PHY_SAMPS_MSG_STRUCT; + +typedef union{ + LIBTOOLS_IPC_MSGQ_RACH_MSG_STRUCT rach; + LIBTOOLS_IPC_MSGQ_MAC_PDU_MSG_STRUCT mac_pdu_msg; + LIBTOOLS_IPC_MSGQ_RAR_PDU_MSG_STRUCT rar_pdu_msg; + LIBTOOLS_IPC_MSGQ_UL_ALLOC_MSG_STRUCT ul_alloc_msg; + LIBTOOLS_IPC_MSGQ_PHY_SAMPS_MSG_STRUCT phy_samps_msg; +}LIBTOOLS_IPC_MSGQ_MESSAGE_UNION; + +typedef struct{ + LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_ENUM type; + LIBTOOLS_IPC_MSGQ_MESSAGE_UNION msg; +}LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT; + +/******************************************************************************* + CLASS DECLARATIONS +*******************************************************************************/ + +// Message queue callback +class libtools_ipc_msgq_cb +{ +public: + typedef void (*FuncType)(void*, LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT*); + libtools_ipc_msgq_cb(); + libtools_ipc_msgq_cb(FuncType f, void* o); + void operator()(LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT *msg); +private: + FuncType func; + void *obj; +}; +template + void libtools_ipc_msgq_cb_wrapper(void *o, LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT *msg) +{ + return (static_cast(o)->*Func)(msg); +} + +class libtools_ipc_msgq +{ +public: + libtools_ipc_msgq(std::string _msgq_name, + libtools_ipc_msgq_cb cb); + ~libtools_ipc_msgq(); + + // Send/Receive + void send(LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_ENUM type, LIBTOOLS_IPC_MSGQ_MESSAGE_UNION *msg_content, uint32 msg_content_size); +private: + // Send/Receive + static void* receive_thread(void *inputs); + + // Variables + libtools_ipc_msgq_cb callback; + std::string msgq_name; + pthread_t rx_thread; +}; + +#endif /* __LIBTOOLS_IPC_MSGQ_H__ */ diff --git a/libtools/hdr/libtools_scoped_lock.h b/libtools/hdr/libtools_scoped_lock.h new file mode 100755 index 0000000..b22ffdf --- /dev/null +++ b/libtools/hdr/libtools_scoped_lock.h @@ -0,0 +1,73 @@ +/******************************************************************************* + + Copyright 2015 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: libtools_scoped_lock.h + + Description: Contains all the definitions for the RAII class for sem_t and + pthread_mutex_t. + + Revision History + ---------- ------------- -------------------------------------------- + 12/05/2015 Ben Wojtowicz Created file + +*******************************************************************************/ + +#ifndef __LIBTOOLS_SCOPED_LOCK_H__ +#define __LIBTOOLS_SCOPED_LOCK_H__ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include +#include + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + FORWARD DECLARATIONS +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + CLASS DECLARATIONS +*******************************************************************************/ + +class libtools_scoped_lock +{ +public: + libtools_scoped_lock(sem_t &sem); + libtools_scoped_lock(pthread_mutex_t &mutex); + ~libtools_scoped_lock(); + +private: + sem_t *sem_; + pthread_mutex_t *mutex_; + bool use_sem; +}; + +#endif /* __LIBTOOLS_SCOPED_LOCK_H__ */ diff --git a/libtools/hdr/libtools_socket_wrap.h b/libtools/hdr/libtools_socket_wrap.h old mode 100644 new mode 100755 index 8975465..7a3369b --- a/libtools/hdr/libtools_socket_wrap.h +++ b/libtools/hdr/libtools_socket_wrap.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013 Ben Wojtowicz + Copyright 2013,2015 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -26,6 +26,7 @@ ---------- ------------- -------------------------------------------- 02/26/2013 Ben Wojtowicz Created file 07/21/2013 Ben Wojtowicz Added enum to text conversion + 12/06/2015 Ben Wojtowicz Change from boost::mutex to sem_t. *******************************************************************************/ @@ -37,9 +38,9 @@ *******************************************************************************/ #include "typedefs.h" -#include #include #include +#include /******************************************************************************* DEFINES @@ -119,7 +120,7 @@ class libtools_socket_wrap LIBTOOLS_SOCKET_WRAP_THREAD_INPUTS_STRUCT thread_inputs; LIBTOOLS_SOCKET_WRAP_STATE_ENUM socket_state; pthread_t socket_thread; - boost::mutex socket_mutex; + sem_t socket_sem; uint32 socket_ip_addr; int32 socket_fd; int32 sock; diff --git a/libtools/src/libtools_helpers.cc b/libtools/src/libtools_helpers.cc new file mode 100755 index 0000000..d43672f --- /dev/null +++ b/libtools/src/libtools_helpers.cc @@ -0,0 +1,304 @@ +/******************************************************************************* + + Copyright 2017 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: libtools_helpers.cc + + Description: Contains all the implementations for helper functions. + + Revision History + ---------- ------------- -------------------------------------------- + 07/29/2017 Ben Wojtowicz Created file + +*******************************************************************************/ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "libtools_helpers.h" +#include +#include +#include + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + GLOBAL VARIABLES +*******************************************************************************/ + + +/******************************************************************************* + FUNCTIONS +*******************************************************************************/ + +/********************************************************************* + Name: to_string + + Description: Converts various types to a string. +*********************************************************************/ +std::string to_string(int32 value) +{ + std::stringstream tmp_ss; + std::string str; + + tmp_ss << value; + str = tmp_ss.str(); + + return(str); +} +std::string to_string(uint32 value) +{ + std::stringstream tmp_ss; + std::string str; + + tmp_ss << value; + str = tmp_ss.str(); + + return(str); +} +std::string to_string(int64 value) +{ + std::stringstream tmp_ss; + std::string str; + + tmp_ss << value; + str = tmp_ss.str(); + + return(str); +} +std::string to_string(uint64 value) +{ + std::stringstream tmp_ss; + std::string str; + + tmp_ss << value; + str = tmp_ss.str(); + + return(str); +} +std::string to_string(uint64 value, + uint32 num_digits) +{ + std::stringstream tmp_ss; + std::string str; + + tmp_ss << std::setw(num_digits) << std::setfill('0') << value; + str = tmp_ss.str(); + + return(str); +} +std::string to_string(uint8 *value, + uint32 num_bytes) +{ + std::string str; + uint32 i; + char tmp_buf[10]; + + for(i=0; i= '0' && char_str[i] <= '9') + { + num = char_str[i] - '0'; + }else if(char_str[i] >= 'A' && char_str[i] <= 'F'){ + num = (char_str[i] - 'A') + 0xA; + }else{ + num = (char_str[i] - 'a') + 0xA; + } + + if((i % 2) == 0) + { + num <<= 4; + } + + number[i/2] |= num; + } + error = false; + } + + return(error); +} + +/********************************************************************* + Name: get_formatted_time + + Description: Populates a string with a formatted time. +*********************************************************************/ +void get_formatted_time(std::string &time_string) +{ + struct timeval tv; + struct tm *local_time; + time_t tmp_time; + + tmp_time = time(NULL); + local_time = localtime(&tmp_time); + gettimeofday(&tv, NULL); + time_string += to_string(local_time->tm_mon + 1, 2) + "/"; + time_string += to_string(local_time->tm_mday, 2) + "/"; + time_string += to_string(local_time->tm_year + 1900, 4) + " "; + time_string += to_string(local_time->tm_hour, 2) + ":"; + time_string += to_string((tv.tv_sec / 60) % 60, 2) + ":"; + time_string += to_string(tv.tv_sec % 60, 2) + "."; + time_string += to_string(tv.tv_usec, 6); +} + +/********************************************************************* + Name: is_string_valid_as_number + + Description: Checks if the string is valid as a number (base 10 + or 16) and is of a specific number of digits. +*********************************************************************/ +bool is_string_valid_as_number(std::string str, + uint32 num_digits, + uint8 base) +{ + uint32 i; + const char *c_str = str.c_str(); + bool valid = false; + + if(str.length() == num_digits) + { + valid = true; + + if(10 == base) + { + for(i=0; i= '0' && c_str[i] <= '9')) + { + valid = false; + } + } + }else if(16 == base){ + for(i=0; i= '0' && c_str[i] <= '9') || + (c_str[i] >= 'a' && c_str[i] <= 'f') || + (c_str[i] >= 'A' && c_str[i] <= 'F'))) + { + valid = false; + } + } + }else{ + valid = false; + } + } + + return(valid); +} + diff --git a/libtools/src/libtools_ipc_msgq.cc b/libtools/src/libtools_ipc_msgq.cc new file mode 100755 index 0000000..b44b41f --- /dev/null +++ b/libtools/src/libtools_ipc_msgq.cc @@ -0,0 +1,150 @@ +/******************************************************************************* + + Copyright 2017 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: libtools_ipc_msgq.cc + + Description: Contains all the implementations for the interprocess message + queue abstraction tool. + + Revision History + ---------- ------------- -------------------------------------------- + 07/29/2017 Ben Wojtowicz Created file + +*******************************************************************************/ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "libtools_ipc_msgq.h" +#include + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + GLOBAL VARIABLES +*******************************************************************************/ + + +/******************************************************************************* + CLASS IMPLEMENTATIONS +*******************************************************************************/ + +/******************/ +/* Callback */ +/******************/ +libtools_ipc_msgq_cb::libtools_ipc_msgq_cb() +{ +} +libtools_ipc_msgq_cb::libtools_ipc_msgq_cb(FuncType f, void* o) +{ + func = f; + obj = o; +} +void libtools_ipc_msgq_cb::operator()(LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT *msg) +{ + return (*func)(obj, msg); +} + +/********************************/ +/* Constructor/Destructor */ +/********************************/ +libtools_ipc_msgq::libtools_ipc_msgq(std::string _msgq_name, + libtools_ipc_msgq_cb cb) +{ + msgq_name = _msgq_name; + callback = cb; + pthread_create(&rx_thread, NULL, &receive_thread, this); +} +libtools_ipc_msgq::~libtools_ipc_msgq() +{ + send(LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_KILL, NULL, 0); + + // Cleanup thread + pthread_cancel(rx_thread); + pthread_join(rx_thread, NULL); +} + +/**********************/ +/* Send/Receive */ +/**********************/ +void libtools_ipc_msgq::send(LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_ENUM type, + LIBTOOLS_IPC_MSGQ_MESSAGE_UNION *msg_content, + uint32 msg_content_size) +{ + LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT msg; + boost::interprocess::message_queue mq(boost::interprocess::open_only, + msgq_name.c_str()); + + msg.type = type; + if(msg_content != NULL) + { + memcpy(&msg.msg, msg_content, msg_content_size); + } + + mq.try_send(&msg, sizeof(LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT), 0); +} +void* libtools_ipc_msgq::receive_thread(void *inputs) +{ + libtools_ipc_msgq *msgq = (libtools_ipc_msgq *)inputs; + LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT msg; + std::size_t rx_size; + uint32 prio; + bool not_done = true; + + // Open the message_queue + boost::interprocess::message_queue mq(boost::interprocess::open_or_create, + msgq->msgq_name.c_str(), + 100, + sizeof(LIBTOOLS_IPC_MSGQ_MESSAGE_STRUCT)); + + while(not_done) + { + // FIXME: SET A TIMEOUT + + // Wait for a message + mq.receive(&msg, sizeof(msg), rx_size, prio); + + // Process message + if(sizeof(msg) == rx_size) + { + msgq->callback(&msg); + + if(LIBTOOLS_IPC_MSGQ_MESSAGE_TYPE_KILL == msg.type) + { + not_done = false; + } + }else{ + // FIXME + printf("ERROR %s Invalid message size received: %u\n", + msgq->msgq_name.c_str(), + (uint32)rx_size); + } + } + + return(NULL); +} diff --git a/libtools/src/libtools_scoped_lock.cc b/libtools/src/libtools_scoped_lock.cc new file mode 100755 index 0000000..3702622 --- /dev/null +++ b/libtools/src/libtools_scoped_lock.cc @@ -0,0 +1,77 @@ +/******************************************************************************* + + Copyright 2015 Ben Wojtowicz + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +******************************************************************************* + + File: libtools_scoped_lock.cc + + Description: Contains all the implementations for the RAII class for sem_t + and pthread_mutex_t. + + Revision History + ---------- ------------- -------------------------------------------- + 12/05/2015 Ben Wojtowicz Created file + +*******************************************************************************/ + +/******************************************************************************* + INCLUDES +*******************************************************************************/ + +#include "libtools_scoped_lock.h" + +/******************************************************************************* + DEFINES +*******************************************************************************/ + + +/******************************************************************************* + TYPEDEFS +*******************************************************************************/ + + +/******************************************************************************* + GLOBAL VARIABLES +*******************************************************************************/ + + +/******************************************************************************* + CLASS IMPLEMENTATIONS +*******************************************************************************/ + +// Constructor/Destructor +libtools_scoped_lock::libtools_scoped_lock(sem_t &sem) +{ + sem_ = &sem; + use_sem = true; + sem_wait(sem_); +} +libtools_scoped_lock::libtools_scoped_lock(pthread_mutex_t &mutex) +{ + mutex_ = &mutex; + use_sem = false; + pthread_mutex_lock(mutex_); +} +libtools_scoped_lock::~libtools_scoped_lock() +{ + if(use_sem) + { + sem_post(sem_); + }else{ + pthread_mutex_unlock(mutex_); + } +} diff --git a/libtools/src/libtools_socket_wrap.cc b/libtools/src/libtools_socket_wrap.cc old mode 100644 new mode 100755 index 81ac323..d22bc87 --- a/libtools/src/libtools_socket_wrap.cc +++ b/libtools/src/libtools_socket_wrap.cc @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright 2013 Ben Wojtowicz + Copyright 2013-2015 Ben Wojtowicz This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -27,6 +27,9 @@ 02/26/2013 Ben Wojtowicz Created file 08/26/2013 Ben Wojtowicz Moved to using select with a timeout for socket management. + 07/22/2014 Ben Wojtowicz Pulled in a patch from Jeff Long to fix + double unlocking of mutex. + 12/06/2015 Ben Wojtowicz Change from boost::mutex to sem_t. *******************************************************************************/ @@ -35,6 +38,7 @@ *******************************************************************************/ #include "libtools_socket_wrap.h" +#include "libtools_scoped_lock.h" #include #include #include @@ -71,9 +75,11 @@ libtools_socket_wrap::libtools_socket_wrap(uint32 *ip_a void (*handle_error)(LIBTOOLS_SOCKET_WRAP_ERROR_ENUM err), LIBTOOLS_SOCKET_WRAP_ERROR_ENUM *error) { - boost::mutex::scoped_lock lock(socket_mutex); - struct sockaddr_in s_addr; - struct linger linger; + sem_init(&socket_sem, 0, 1); + + libtools_scoped_lock lock(socket_sem); + struct sockaddr_in s_addr; + struct linger linger; if(handle_msg == NULL || handle_connect == NULL || @@ -150,7 +156,7 @@ libtools_socket_wrap::libtools_socket_wrap(uint32 *ip_a } libtools_socket_wrap::~libtools_socket_wrap() { - boost::mutex::scoped_lock lock(socket_mutex); + libtools_scoped_lock lock(socket_sem); if(LIBTOOLS_SOCKET_WRAP_STATE_DISCONNECTED != socket_state) { @@ -166,7 +172,7 @@ libtools_socket_wrap::~libtools_socket_wrap() // Send LIBTOOLS_SOCKET_WRAP_ERROR_ENUM libtools_socket_wrap::send(std::string msg) { - boost::mutex::scoped_lock lock(socket_mutex); + libtools_scoped_lock lock(socket_sem); LIBTOOLS_SOCKET_WRAP_ERROR_ENUM err = LIBTOOLS_SOCKET_WRAP_ERROR_SOCKET; if(LIBTOOLS_SOCKET_WRAP_STATE_CONNECTED == socket_state) @@ -230,20 +236,21 @@ void* libtools_socket_wrap::server_thread(void *inputs) if(i == act_inputs->sock) { // Accept connections - act_inputs->socket_wrap->socket_mutex.lock(); + sem_wait(&act_inputs->socket_wrap->socket_sem); if(act_inputs->socket_wrap->socket_state != LIBTOOLS_SOCKET_WRAP_STATE_CONNECTED) { sock_fd = accept(act_inputs->sock, (struct sockaddr *)&c_addr, &c_addr_len); if(0 > sock_fd) { act_inputs->handle_error(LIBTOOLS_SOCKET_WRAP_ERROR_SOCKET); + sem_post(&act_inputs->socket_wrap->socket_sem); return(NULL); } // Finish setup act_inputs->socket_wrap->socket_fd = sock_fd; act_inputs->socket_wrap->socket_state = LIBTOOLS_SOCKET_WRAP_STATE_CONNECTED; - act_inputs->socket_wrap->socket_mutex.unlock(); + sem_post(&act_inputs->socket_wrap->socket_sem); act_inputs->handle_connect(); // Finish FD_SET setup @@ -252,8 +259,9 @@ void* libtools_socket_wrap::server_thread(void *inputs) { fd_max = sock_fd; } + }else{ + sem_post(&act_inputs->socket_wrap->socket_sem); } - act_inputs->socket_wrap->socket_mutex.unlock(); }else{ memset(read_buf, '\0', LINE_MAX); nbytes = read(sock_fd, read_buf, LINE_MAX); @@ -261,28 +269,30 @@ void* libtools_socket_wrap::server_thread(void *inputs) // Check the return if(-1 == nbytes) { - act_inputs->socket_wrap->socket_mutex.lock(); + sem_wait(&act_inputs->socket_wrap->socket_sem); if(LIBTOOLS_SOCKET_WRAP_STATE_CONNECTED == act_inputs->socket_wrap->socket_state) { - act_inputs->socket_wrap->socket_mutex.unlock(); + sem_post(&act_inputs->socket_wrap->socket_sem); act_inputs->handle_disconnect(); + }else{ + sem_post(&act_inputs->socket_wrap->socket_sem); } - act_inputs->socket_wrap->socket_mutex.unlock(); - act_inputs->socket_wrap->socket_mutex.lock(); + sem_wait(&act_inputs->socket_wrap->socket_sem); act_inputs->socket_wrap->socket_state = LIBTOOLS_SOCKET_WRAP_STATE_CLOSED; - act_inputs->socket_wrap->socket_mutex.unlock(); + sem_post(&act_inputs->socket_wrap->socket_sem); break; }else if(0 == nbytes){ - act_inputs->socket_wrap->socket_mutex.lock(); + sem_wait(&act_inputs->socket_wrap->socket_sem); if(LIBTOOLS_SOCKET_WRAP_STATE_CONNECTED == act_inputs->socket_wrap->socket_state) { - act_inputs->socket_wrap->socket_mutex.unlock(); + sem_post(&act_inputs->socket_wrap->socket_sem); act_inputs->handle_disconnect(); + }else{ + sem_post(&act_inputs->socket_wrap->socket_sem); } - act_inputs->socket_wrap->socket_mutex.unlock(); - act_inputs->socket_wrap->socket_mutex.lock(); + sem_wait(&act_inputs->socket_wrap->socket_sem); act_inputs->socket_wrap->socket_state = LIBTOOLS_SOCKET_WRAP_STATE_THREADED; - act_inputs->socket_wrap->socket_mutex.unlock(); + sem_post(&act_inputs->socket_wrap->socket_sem); break; }else{ // Remove \n diff --git a/octave/cmn_bin2dec.m b/octave/cmn_bin2dec.m old mode 100644 new mode 100755 diff --git a/octave/cmn_conv_encode.m b/octave/cmn_conv_encode.m old mode 100644 new mode 100755 diff --git a/octave/cmn_dec2bin.m b/octave/cmn_dec2bin.m old mode 100644 new mode 100755 diff --git a/octave/cmn_oct2bin.m b/octave/cmn_oct2bin.m old mode 100644 new mode 100755 diff --git a/octave/cmn_viterbi_decode.m b/octave/cmn_viterbi_decode.m old mode 100644 new mode 100755 diff --git a/octave/lte_bcch_bch_msg_pack.m b/octave/lte_bcch_bch_msg_pack.m old mode 100644 new mode 100755 diff --git a/octave/lte_bcch_bch_msg_unpack.m b/octave/lte_bcch_bch_msg_unpack.m old mode 100644 new mode 100755 diff --git a/octave/lte_bcch_dlsch_msg_pack.m b/octave/lte_bcch_dlsch_msg_pack.m old mode 100644 new mode 100755 diff --git a/octave/lte_bcch_dlsch_msg_unpack.m b/octave/lte_bcch_dlsch_msg_unpack.m old mode 100644 new mode 100755 diff --git a/octave/lte_bch_channel_decode.m b/octave/lte_bch_channel_decode.m old mode 100644 new mode 100755 diff --git a/octave/lte_bch_channel_encode.m b/octave/lte_bch_channel_encode.m old mode 100644 new mode 100755 diff --git a/octave/lte_calc_crc.m b/octave/lte_calc_crc.m old mode 100644 new mode 100755 diff --git a/octave/lte_cfi_channel_decode.m b/octave/lte_cfi_channel_decode.m old mode 100644 new mode 100755 diff --git a/octave/lte_cfi_channel_encode.m b/octave/lte_cfi_channel_encode.m old mode 100644 new mode 100755 diff --git a/octave/lte_code_block_concatenation.m b/octave/lte_code_block_concatenation.m old mode 100644 new mode 100755 diff --git a/octave/lte_code_block_deconcatenation.m b/octave/lte_code_block_deconcatenation.m old mode 100644 new mode 100755 diff --git a/octave/lte_code_block_desegmentation.m b/octave/lte_code_block_desegmentation.m old mode 100644 new mode 100755 diff --git a/octave/lte_code_block_segmentation.m b/octave/lte_code_block_segmentation.m old mode 100644 new mode 100755 diff --git a/octave/lte_dci_1a_pack.m b/octave/lte_dci_1a_pack.m old mode 100644 new mode 100755 diff --git a/octave/lte_dci_1a_unpack.m b/octave/lte_dci_1a_unpack.m old mode 100644 new mode 100755 diff --git a/octave/lte_dci_channel_decode.m b/octave/lte_dci_channel_decode.m old mode 100644 new mode 100755 diff --git a/octave/lte_dci_channel_encode.m b/octave/lte_dci_channel_encode.m old mode 100644 new mode 100755 diff --git a/octave/lte_dlsch_channel_decode.m b/octave/lte_dlsch_channel_decode.m old mode 100644 new mode 100755 diff --git a/octave/lte_dlsch_channel_encode.m b/octave/lte_dlsch_channel_encode.m old mode 100644 new mode 100755 diff --git a/octave/lte_fdd_dl_receive.m b/octave/lte_fdd_dl_receive.m old mode 100644 new mode 100755 diff --git a/octave/lte_fdd_dl_transmit.m b/octave/lte_fdd_dl_transmit.m old mode 100644 new mode 100755 diff --git a/octave/lte_generate_crs.m b/octave/lte_generate_crs.m old mode 100644 new mode 100755 diff --git a/octave/lte_generate_dmrs_pucch_format1_1a_1b.m b/octave/lte_generate_dmrs_pucch_format1_1a_1b.m new file mode 100755 index 0000000..24fa772 --- /dev/null +++ b/octave/lte_generate_dmrs_pucch_format1_1a_1b.m @@ -0,0 +1,176 @@ +% +% Copyright 2016 Ben Wojtowicz +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU Affero General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU Affero General Public License for more details. +% +% You should have received a copy of the GNU Affero General Public License +% along with this program. If not, see . +% +% Function: lte_generate_dmrs_pucch_format1_1a_1b +% Description: Generates LTE demodulation reference signal for PUCCH formats 1, 1A, and 1B +% Inputs: N_subfr - Subframe number within a radio frame +% N_id_cell - Physical layer cell identity +% delta_ss - Configurable portion of the sequence-shift pattern for PUSCH (sib2 groupAssignmentPUSCH) +% group_hopping_enabled - Boolean value determining if group hopping is enabled (sib2 groupHoppingEnabled) +% sequence_hopping_enabled - Boolean value determining if sequence hopping is enabled (sib2 sequenceHoppingEnabled) +% N_cs_1 - Number of cyclic shifts used (sib2 nCS-AN) +% N_1_p_pucch - Resource index +% delta_pucch_shift - Controls the amount of multiplexing on PUCCH (sib2 deltaPUCCH-Shift) +% N_ant - Number of antennas +% Outputs: r - Demodulation reference signal for PUCCH format 1, 1A, and 1B +% Spec: 3GPP TS 36.211 section 5.5.2.2 v10.1.0 +% Notes: Currently only handles normal CP and 1 antenna +% Rev History: Ben Wojtowicz 03/12/2016 Created +% +function [r] = lte_generate_dmrs_pucch_format1_1a_1b(N_subfr, N_id_cell, delta_ss, group_hopping_enabled, sequence_hopping_enabled, N_cs_1, N_1_p_pucch, delta_pucch_shift, N_ant) + + % Defines + N_ul_symb = 7; % Only dealing with normal cp at this time + N_sc_rb = 12; + M_pucch_rs = 3; + w_vector(0+1,:) = [1, 1, 1]; + w_vector(1+1,:) = [1, exp(j*2*pi/3), exp(j*4*pi/3)]; + w_vector(2+1,:) = [1, exp(j*4*pi/3), exp(j*2*pi/3)]; + + % Validate N_subfr + if(~(N_subfr >= 0 && N_subfr <= 9)) + printf("ERROR: Invalid N_subfr (%u)\n", N_subfr); + r = 0; + return; + endif + + % Validate N_id_cell + if(~(N_id_cell >= 0 && N_id_cell <= 503)) + printf("ERROR: Invalid N_id_cell (%u)\n", N_id_cell); + r = 0; + return; + endif + + % Validate delta_ss + if(~(delta_ss >= 0 && delta_ss <= 29)) + printf("ERROR: Invalid delta_ss (%u)\n", delta_ss); + r = 0; + return; + endif + + % Validate group_hopping_enabled + if(~(group_hopping_enabled == 1 || group_hopping_enabled == 0)) + printf("ERROR: Invalid group_hopping_enabled (%u)\n", group_hopping_enabled); + r = 0; + return; + endif + + % Validate sequence_hopping_enabled + if(~(sequence_hopping_enabled == 1 || sequence_hopping_enabled == 0)) + printf("ERROR: Invalid sequence_hopping_enabled (%u)\n", sequence_hopping_enabled); + r = 0; + return; + endif + + % Validate N_cs_1 + if(~(N_cs_1 >= 0 && N_cs_1 <= 7)) + printf("ERROR: Invalid N_cs_1 (%u)\n", N_cs_1); + r = 0; + return; + endif + + % Validate N_1_p_pucch + if(~(N_1_p_pucch >= 0 && N_1_p_pucch < 50)) + printf("ERROR: Invalid N_1_p_pucch (%u)\n", N_1_p_pucch); + r = 0; + return; + endif + + % Validate delta_pucch_shift + if(~(delta_pucch_shift >= 0 && delta_pucch_shift <= 2)) + printf("ERROR: Invalid delta_pucch_shift (%u)\n", delta_pucch_shift); + r = 0; + return; + endif + + % Validate N_ant + if(~(N_ant == 1)) + printf("ERROR: Invalid N_ant (%u)\n", N_ant); + r = 0; + return; + endif + + % Calculate N_s + N_s = N_subfr*2; + + % Calculate N_prime + if(N_1_p_pucch < 3*N_cs_1/delta_pucch_shift) + N_prime = N_cs_1; + else + N_prime = N_sc_rb; + endif + + % Calculate n_prime_p + % FIXME: Only supporting normal cyclic prefix + if(N_1_p_pucch < (3*N_cs_1/delta_pucch_shift)) + n_prime_p(1) = N_1_p_pucch; + h_p = mod(n_prime_p(1) + 2, 3*N_prime/delta_pucch_shift); + n_prime_p(2) = floor(h_p/3) + mod(h_p, 3)*N_prime/delta_pucch_shift; + else + n_prime_p(1) = mod(N_1_p_pucch - 3*N_cs_1/delta_pucch_shift, 3*N_sc_rb/delta_pucch_shift); + n_prime_p(2) = mod(3*(n_prime_p(1)+1), 3*N_sc_rb/delta_pucch_shift+1) - 1; + endif + + % Calculate N_oc_p + for(m=0:1) + n_oc_p(m+1) = floor(n_prime_p(m+1)*delta_pucch_shift/N_prime); + endfor + + % Generate c + c = lte_generate_prs_c(N_id_cell, 8*N_ul_symb*20); + + % Calculate N_cs_cell + for(m=0:1) + for(n=0:M_pucch_rs-1) + sum = 0; + for(idx=0:7) + sum = sum + c(8*N_ul_symb*(N_s+m) + 8*(2+n) + idx + 1) * 2^idx; + endfor + n_cs_cell(m+1, n+1) = sum; + endfor + endfor + + % Calculate N_cs_p + % FIXME: Only supporting normal cyclic prefix + for(m=0:1) + for(n=0:M_pucch_rs-1) + n_cs_p(m+1, n+1) = mod(n_cs_cell(m+1, n+1) + mod(n_prime_p(m+1)*delta_pucch_shift + mod(n_oc_p(m+1), delta_pucch_shift), N_prime), N_sc_rb); + endfor + endfor + + % Calculate alpha_p + for(m=0:1) + for(n=0:M_pucch_rs-1) + alpha_p(m+1, n+1) = 2*pi*n_cs_p(m+1, n+1)/N_sc_rb; + endfor + endfor + + % Generate the base reference signal + for(m=0:1) + for(n=0:M_pucch_rs-1) + r_u_v_alpha_p(m*M_pucch_rs + n + 1, :) = lte_generate_ul_rs(N_s + m, N_id_cell, "pucch", delta_ss, group_hopping_enabled, sequence_hopping_enabled, alpha_p(m+1, n+1), 1); + endfor + endfor + + % Generate the PUCCH demodulation reference signal sequence + for(m_prime=0:1) + for(m=0:M_pucch_rs-1) + for(n=0:N_sc_rb-1) + r(m_prime*M_pucch_rs*N_sc_rb + m*N_sc_rb + n + 1) = (1/sqrt(N_ant))*w_vector(n_oc_p(m_prime+1)+1, m+1)*r_u_v_alpha_p(m_prime*M_pucch_rs + m + 1, n + 1); + endfor + endfor + endfor +endfunction diff --git a/octave/lte_generate_dmrs_pusch.m b/octave/lte_generate_dmrs_pusch.m old mode 100644 new mode 100755 diff --git a/octave/lte_generate_prs_c.m b/octave/lte_generate_prs_c.m old mode 100644 new mode 100755 diff --git a/octave/lte_generate_pss.m b/octave/lte_generate_pss.m old mode 100644 new mode 100755 diff --git a/octave/lte_generate_sss.m b/octave/lte_generate_sss.m old mode 100644 new mode 100755 diff --git a/octave/lte_generate_ul_rs.m b/octave/lte_generate_ul_rs.m old mode 100644 new mode 100755 diff --git a/octave/lte_get_tbs_7_1_7_2_1.m b/octave/lte_get_tbs_7_1_7_2_1.m old mode 100644 new mode 100755 diff --git a/octave/lte_layer_demapper_dl.m b/octave/lte_layer_demapper_dl.m old mode 100644 new mode 100755 diff --git a/octave/lte_layer_demapper_ul.m b/octave/lte_layer_demapper_ul.m old mode 100644 new mode 100755 diff --git a/octave/lte_layer_mapper_dl.m b/octave/lte_layer_mapper_dl.m old mode 100644 new mode 100755 diff --git a/octave/lte_layer_mapper_ul.m b/octave/lte_layer_mapper_ul.m old mode 100644 new mode 100755 diff --git a/octave/lte_modulation_demapper.m b/octave/lte_modulation_demapper.m old mode 100644 new mode 100755 diff --git a/octave/lte_modulation_mapper.m b/octave/lte_modulation_mapper.m old mode 100644 new mode 100755 diff --git a/octave/lte_prach_bb_gen.m b/octave/lte_prach_bb_gen.m old mode 100644 new mode 100755 diff --git a/octave/lte_prach_detector.m b/octave/lte_prach_detector.m old mode 100644 new mode 100755 diff --git a/octave/lte_prach_preamble_seq_gen.m b/octave/lte_prach_preamble_seq_gen.m old mode 100644 new mode 100755 diff --git a/octave/lte_pre_coder_dl.m b/octave/lte_pre_coder_dl.m old mode 100644 new mode 100755 diff --git a/octave/lte_pre_coder_ul.m b/octave/lte_pre_coder_ul.m old mode 100644 new mode 100755 diff --git a/octave/lte_pre_decoder_and_matched_filter_dl.m b/octave/lte_pre_decoder_and_matched_filter_dl.m old mode 100644 new mode 100755 diff --git a/octave/lte_pre_decoder_and_matched_filter_ul.m b/octave/lte_pre_decoder_and_matched_filter_ul.m old mode 100644 new mode 100755 diff --git a/octave/lte_pucch_demod.m b/octave/lte_pucch_demod.m new file mode 100755 index 0000000..db7d342 --- /dev/null +++ b/octave/lte_pucch_demod.m @@ -0,0 +1,294 @@ +% +% Copyright 2016-2017 Ben Wojtowicz +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU Affero General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU Affero General Public License for more details. +% +% You should have received a copy of the GNU Affero General Public License +% along with this program. If not, see . +% +% Function: lte_pucch_demod +% Description: Demodulates PUCCH +% Inputs: pucch_bb - PUCCH baseband I/Q +% N_1_p_pucch - Resource index +% N_id_cell - Physical layer cell identity for the eNodeB +% N_subfr - Subframe number of the PUSCH +% delta_ss - Configurable portion of the sequence-shift pattern for PUSCH (sib2 groupAssignmentPUSCH) +% group_hop_en - Boolean value determining if group hopping is enabled (sib2 groupHoppingEnabled) +% seq_hop_en - Boolean value determining if sequence hopping is enabled (sib2 sequenceHoppingEnabled) +% N_cs_1 - Number of cyclic shifts used (sib2 nCS-AN) +% delta_pucch_shift - Controls the amount of multiplexing on PUCCH (sib2 deltaPUCCH-Shift) +% N_ul_rb - Number of PRBs available in the uplink +% fs - Sampling rate +% N_ant - Number of antennas +% Outputs: soft_bit - Demodulated PUCCH soft bit +% Spec: 3GPP TS 36.211 section 5.4, 5.5, and 5.6 v10.1.0 +% Notes: Only handling normal CP and 1 antenna +% Rev History: Ben Wojtowicz 03/12/2016 Created +% Ben Wojtowicz 07/29/2017 Fixed a typo +% +function [soft_bit] = lte_pucch_demod(pucch_bb, N_1_p_pucch, N_id_cell, N_subfr, delta_ss, group_hop_en, seq_hop_en, N_cs_1, delta_pucch_shift, N_ul_rb, fs, N_ant) + + % Definitions + N_cp_L_0 = 160; % FIXME: Only handling normal CP + N_cp_L_else = 144; % FIXME: Only handling normal CP + N_symbs_per_slot = 7; % FIXME: Only handling normal CP + N_sc_rb = 12; + N_ul_symb = 7; + N_pucch_seq = 12; + N_pucch_sf = 4; + w_vector(0+1,:) = [1, 1, 1, 1]; + w_vector(1+1,:) = [1, -1, 1, -1]; + w_vector(2+1,:) = [1, -1, -1, 1]; + + % Determine FFT size and FFT pad size + if(fs == 1920000) + FFT_size = 128; + downsample = 16; + if(N_ul_rb == 6) + FFT_pad_size = 28; + else + printf("ERROR: Invalid N_ul_rb (%u)\n", N_ul_rb); + return + endif + elseif(fs == 3840000) + FFT_size = 256; + downsample = 8; + if(N_ul_rb == 6) + FFT_pad_size = 92; + elseif(N_ul_rb == 15) + FFT_pad_size = 38; + else + printf("ERROR: Invalid N_ul_rb (%u)\n", N_ul_rb); + return + endif + elseif(fs == 7680000) + FFT_size = 512; + downsample = 4; + if(N_ul_rb == 6) + FFT_pad_size = 220; + elseif(N_ul_rb == 15) + FFT_pad_size = 166; + elseif(N_ul_rb == 25) + FFT_pad_size = 106; + else + printf("ERROR: Invalid N_ul_rb (%u)\n", N_ul_rb); + return + endif + elseif(fs == 15360000) + FFT_size = 1024; + downsample = 2; + if(N_ul_rb == 6) + FFT_pad_size = 476; + elseif(N_ul_rb == 15) + FFT_pad_size = 422; + elseif(N_ul_rb == 25) + FFT_pad_size = 362; + elseif(N_ul_rb == 50) + FFT_pad_size = 212; + else + printf("ERROR: Invalid N_ul_rb (%u)\n", N_ul_rb); + return + endif + elseif(fs == 30720000) + FFT_size = 2048; + downsample = 1; + if(N_ul_rb == 6) + FFT_pad_size = 988; + elseif(N_ul_rb == 15) + FFT_pad_size = 934; + elseif(N_ul_rb == 25) + FFT_pad_size = 874; + elseif(N_ul_rb == 50) + FFT_pad_size = 724; + elseif(N_ul_rb == 75) + FFT_pad_size = 574; + elseif(N_ul_rb == 100) + FFT_pad_size = 424; + else + printf("ERROR: Invalid N_ul_rb (%u)\n", N_ul_rb); + return + endif + else + printf("ERROR: Invalid fs (%u)\n", fs); + return + endif + + % Extract symbols + N_prb = 1; + for(L=0:(N_symbs_per_slot*2)-1) + if(L < 7) + prb_offset = N_1_p_pucch; + else + prb_offset = N_ul_rb-N_1_p_pucch-1; + endif + if(mod(L, 7) == 0) + N_cp = N_cp_L_0 / downsample; + else + N_cp = N_cp_L_else / downsample; + endif + index = (FFT_size + (N_cp_L_else / downsample)) * L; + if(L > 7) + index = index + (32 / downsample); + elseif(L > 0) + index = index + (16 / downsample); + endif + + tmp = fftshift(fft(pucch_bb(index+N_cp+1:index+N_cp+FFT_size), FFT_size*2)); + tmp = tmp(2:2:end); + + tmp_symbs = tmp(FFT_pad_size+1:FFT_size-FFT_pad_size); + + symbs(L+1,:) = tmp_symbs(prb_offset*12+1:prb_offset*12+(N_prb*12)); + endfor + + % Generate DMRS + dmrs = lte_generate_dmrs_pucch_format1_1a_1b(N_subfr, N_id_cell, delta_ss, group_hop_en, seq_hop_en, N_cs_1, N_1_p_pucch, delta_pucch_shift, N_ant); + + % Determine channel estimates + for(n=0:5) + if(n < 3) + symb_num = 2+n; + else + symb_num = 9+n-3; + endif + for(m=0:N_sc_rb-1) + tmp = symbs(symb_num+1,m+1)/dmrs(n*N_sc_rb+m+1); + mag(n+1,m+1) = abs(tmp); + ang(n+1,m+1) = angle(tmp); + endfor + endfor + + % Average channel estimates + ave_ang = zeros(2, N_sc_rb); + ave_mag = zeros(2, N_sc_rb); + for(n=0:2) + for(m=0:N_sc_rb-1) + ave_ang(1, m+1) = ave_ang(1, m+1) + (ang(n+1, m+1) / 3); + ave_mag(1, m+1) = ave_mag(1, m+1) + (mag(n+1, m+1) / 3); + ave_ang(2, m+1) = ave_ang(2, m+1) + (ang(n+3+1, m+1) / 3); + ave_mag(2, m+1) = ave_mag(2, m+1) + (mag(n+3+1, m+1) / 3); + endfor + endfor + + % Construct full channel estimates + for(L=0:(N_symbs_per_slot*2)-1) + idx = floor(L/7); + for(m=0:N_sc_rb-1) + ce(L+1,m+1) = ave_mag(idx+1, m+1)*(cos(ave_ang(idx+1, m+1)) + j*sin(ave_ang(idx+1, m+1))); + endfor + endfor + + % Apply channel estimate to recover signal + z_est = [symbs(0+1,:), symbs(1+1,:), symbs(5+1,:), symbs(6+1,:), symbs(7+1,:), symbs(8+1,:), symbs(12+1,:), symbs(13+1,:)]; + ce_tot = [ce(0+1,:), ce(1+1,:), ce(5+1,:), ce(6+1,:), ce(7+1,:), ce(8+1,:), ce(12+1,:), ce(13+1,:)]; + z = lte_pre_decoder_and_matched_filter_ul(z_est, ce_tot, 1); + + % Calculate n_prime_p + % FIXME: Only supporting normal cyclic prefix + if(N_1_p_pucch < (3*N_cs_1/delta_pucch_shift)) + n_prime_p(1) = N_1_p_pucch; + h_p = mod(n_prime_p(1) + 2, 3*N_prime/delta_pucch_shift); + n_prime_p(2) = floor(h_p/3) + mod(h_p, 3)*N_prime/delta_pucch_shift; + else + n_prime_p(1) = mod(N_1_p_pucch - 3*N_cs_1/delta_pucch_shift, 3*N_sc_rb/delta_pucch_shift); + n_prime_p(2) = mod(3*(n_prime_p(1)+1), 3*N_sc_rb/delta_pucch_shift+1) - 1; + endif + + % Calculate s_ns + for(m=0:1) + if(mod(n_prime_p(m+1), 2) == 0) + s_ns(m+1) = 1; + else + s_ns(m+1) = exp(j*pi/2); + endif + endfor + + % Calculate N_prime + if(N_1_p_pucch < 3*N_cs_1/delta_pucch_shift) + N_prime = N_cs_1; + else + N_prime = N_sc_rb; + endif + + % Calculate n_oc_p + for(m=0:1) + n_oc_p(m+1) = floor(n_prime_p(m+1)*delta_pucch_shift/N_prime); + endfor + + % Recover yp from z + for(m_prime=0:1) + for(m=0:N_pucch_sf-1) + for(n=0:N_pucch_seq-1) + yp_est(m_prime*N_pucch_sf*N_pucch_seq + m*N_pucch_seq + n+1) = z(m_prime*N_pucch_sf*N_pucch_seq + m*N_pucch_seq + n + 1) / (s_ns(m_prime+1)*w_vector(n_oc_p(m_prime+1)+1, m+1)); + endfor + endfor + endfor + + % Calculate N_s + N_s = N_subfr*2; + + % Generate c + c = lte_generate_prs_c(N_id_cell, 8*N_ul_symb*20); + + % Calculate N_cs_cell + for(m=0:1) + for(n=0:N_symbs_per_slot-1) + sum = 0; + for(idx=0:7) + sum = sum + c(8*N_ul_symb*(N_s+m) + 8*n + idx + 1) * 2^idx; + endfor + n_cs_cell(m+1, n+1) = sum; + endfor + endfor + + % Calculate N_cs_p + % FIXME: Only supporting normal cyclic prefix + for(m=0:1) + for(n=0:N_symbs_per_slot-1) + n_cs_p(m+1, n+1) = mod(n_cs_cell(m+1, n+1) + mod(n_prime_p(m+1)*delta_pucch_shift + mod(n_oc_p(m+1), delta_pucch_shift), N_prime), N_sc_rb); + endfor + endfor + + % Calculate alpha_p + for(m=0:1) + for(n=0:N_symbs_per_slot-1) + alpha_p(m+1, n+1) = 2*pi*n_cs_p(m+1, n+1)/N_sc_rb; + endfor + endfor + + % Generate r_u_v_alpha_p + for(m=0:1) + for(n=0:N_symbs_per_slot-1) + r_u_v_alpha_p(m*N_symbs_per_slot + n + 1, :) = lte_generate_ul_rs(N_s + m, N_id_cell, "pucch", delta_ss, group_hop_en, seq_hop_en, alpha_p(m+1, n+1), 1); + endfor + endfor + + % Recover d as a vector from yp + for(m_prime=0:1) + for(m=0:N_pucch_sf-1) + symb_num = m; + if(symb_num > 1) + symb_num = m + 3; + endif + for(n=0:N_pucch_seq-1) + d_est(m_prime*N_pucch_sf*N_pucch_seq + m*N_pucch_seq + n+1) = yp_est(m_prime*N_pucch_sf*N_pucch_seq + m*N_pucch_seq + n+1) / r_u_v_alpha_p(m_prime*N_symbs_per_slot + symb_num + 1, n+1); + endfor + endfor + endfor + + % Collapse into the soft bit + soft_bit = 0; + for(n=0:length(d_est)-1) + soft_bit = soft_bit + d_est(n+1); + endfor + soft_bit = soft_bit / length(d_est); + soft_bit = soft_bit / (1 / sqrt(N_ant)); +endfunction diff --git a/octave/lte_pusch_demod.m b/octave/lte_pusch_demod.m old mode 100644 new mode 100755 diff --git a/octave/lte_pusch_mod.m b/octave/lte_pusch_mod.m old mode 100644 new mode 100755 diff --git a/octave/lte_rate_match_conv.m b/octave/lte_rate_match_conv.m old mode 100644 new mode 100755 diff --git a/octave/lte_rate_match_turbo.m b/octave/lte_rate_match_turbo.m old mode 100644 new mode 100755 diff --git a/octave/lte_rate_unmatch_conv.m b/octave/lte_rate_unmatch_conv.m old mode 100644 new mode 100755 diff --git a/octave/lte_rate_unmatch_turbo.m b/octave/lte_rate_unmatch_turbo.m old mode 100644 new mode 100755 diff --git a/octave/lte_sib1_pack.m b/octave/lte_sib1_pack.m old mode 100644 new mode 100755 diff --git a/octave/lte_sib1_unpack.m b/octave/lte_sib1_unpack.m old mode 100644 new mode 100755 diff --git a/octave/lte_turbo_decode.m b/octave/lte_turbo_decode.m old mode 100644 new mode 100755 diff --git a/octave/lte_turbo_encode.m b/octave/lte_turbo_encode.m old mode 100644 new mode 100755 diff --git a/octave/lte_ulsch_channel_decode.m b/octave/lte_ulsch_channel_decode.m old mode 100644 new mode 100755 diff --git a/octave/lte_ulsch_channel_deinterleaver.m b/octave/lte_ulsch_channel_deinterleaver.m old mode 100644 new mode 100755 diff --git a/octave/lte_ulsch_channel_encode.m b/octave/lte_ulsch_channel_encode.m old mode 100644 new mode 100755 diff --git a/octave/lte_ulsch_channel_interleaver.m b/octave/lte_ulsch_channel_interleaver.m old mode 100644 new mode 100755 diff --git a/octave/lte_ulsch_control_data_demultiplexing.m b/octave/lte_ulsch_control_data_demultiplexing.m old mode 100644 new mode 100755 diff --git a/octave/lte_ulsch_control_data_multiplexing.m b/octave/lte_ulsch_control_data_multiplexing.m old mode 100644 new mode 100755