From 6f6c9a5ccb4f0983973aa19e343f8455fbbb2ab3 Mon Sep 17 00:00:00 2001 From: chliny Date: Wed, 16 Aug 2017 01:15:28 +0800 Subject: [PATCH 1/2] Version 0.20.5: 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 --- AUTHORS | 4 +- CMakeLists.txt | 8 +- COPYING | 0 ChangeLog | 161 + LTE_fdd_dl_file_gen/CMakeLists.txt | 0 LTE_fdd_dl_file_gen/hdr/LTE_fdd_dl_fg_api.h | 0 .../hdr/LTE_fdd_dl_fg_samp_buf.h | 0 LTE_fdd_dl_file_gen/src/LTE_fdd_dl_fg.i | 0 .../src/LTE_fdd_dl_fg_samp_buf.cc | 32 +- LTE_fdd_dl_file_gen/src/__init__.py | 0 LTE_fdd_dl_file_scan/CMakeLists.txt | 0 LTE_fdd_dl_file_scan/hdr/LTE_fdd_dl_fs_api.h | 0 .../hdr/LTE_fdd_dl_fs_samp_buf.h | 4 + LTE_fdd_dl_file_scan/src/LTE_fdd_dl_fs.i | 0 .../src/LTE_fdd_dl_fs_samp_buf.cc | 79 +- LTE_fdd_dl_file_scan/src/__init__.py | 0 LTE_fdd_dl_scan/CMakeLists.txt | 0 .../hdr/LTE_fdd_dl_scan_flowgraph.h | 15 +- .../hdr/LTE_fdd_dl_scan_interface.h | 11 +- .../hdr/LTE_fdd_dl_scan_state_machine.h | 0 .../hdr/LTE_fdd_dl_scan_state_machine_api.h | 0 .../src/LTE_fdd_dl_scan_flowgraph.cc | 114 +- .../src/LTE_fdd_dl_scan_interface.cc | 1956 ++- LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_main.cc | 0 .../src/LTE_fdd_dl_scan_state_machine.cc | 31 +- LTE_fdd_enodeb/CMakeLists.txt | 5 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_cnfg_db.h | 33 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_common.h | 109 + LTE_fdd_enodeb/hdr/LTE_fdd_enb_gw.h | 98 + LTE_fdd_enodeb/hdr/LTE_fdd_enb_hss.h | 58 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_interface.h | 180 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_mac.h | 76 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_mme.h | 84 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_msgq.h | 191 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_pdcp.h | 48 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_phy.h | 31 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_radio.h | 174 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_rb.h | 281 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_rlc.h | 50 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_rrc.h | 54 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer.h | 2 + LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer_mgr.h | 27 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_user.h | 174 +- LTE_fdd_enodeb/hdr/LTE_fdd_enb_user_mgr.h | 47 +- LTE_fdd_enodeb/src/LTE_fdd_enb_cnfg_db.cc | 357 +- LTE_fdd_enodeb/src/LTE_fdd_enb_gw.cc | 323 + LTE_fdd_enodeb/src/LTE_fdd_enb_hss.cc | 468 +- LTE_fdd_enodeb/src/LTE_fdd_enb_interface.cc | 1132 +- LTE_fdd_enodeb/src/LTE_fdd_enb_mac.cc | 1218 +- LTE_fdd_enodeb/src/LTE_fdd_enb_main.cc | 9 + LTE_fdd_enodeb/src/LTE_fdd_enb_mme.cc | 1845 ++- LTE_fdd_enodeb/src/LTE_fdd_enb_msgq.cc | 188 +- LTE_fdd_enodeb/src/LTE_fdd_enb_pdcp.cc | 389 +- LTE_fdd_enodeb/src/LTE_fdd_enb_phy.cc | 494 +- LTE_fdd_enodeb/src/LTE_fdd_enb_radio.cc | 1670 +- LTE_fdd_enodeb/src/LTE_fdd_enb_rb.cc | 859 +- LTE_fdd_enodeb/src/LTE_fdd_enb_rlc.cc | 782 +- LTE_fdd_enodeb/src/LTE_fdd_enb_rrc.cc | 839 +- LTE_fdd_enodeb/src/LTE_fdd_enb_timer.cc | 5 + LTE_fdd_enodeb/src/LTE_fdd_enb_timer_mgr.cc | 121 +- LTE_fdd_enodeb/src/LTE_fdd_enb_user.cc | 587 +- LTE_fdd_enodeb/src/LTE_fdd_enb_user_mgr.cc | 542 +- LTE_file_recorder/CMakeLists.txt | 0 .../hdr/LTE_file_recorder_flowgraph.h | 10 +- .../hdr/LTE_file_recorder_interface.h | 6 +- .../src/LTE_file_recorder_flowgraph.cc | 24 +- .../src/LTE_file_recorder_interface.cc | 70 +- .../src/LTE_file_recorder_main.cc | 0 NEWS | 0 README | 16 +- cmake/Modules/CMakeParseArgumentsCopy.cmake | 0 cmake/Modules/FindFFTW3F.cmake | 0 cmake/Modules/FindGnuradioOsmosdr.cmake | 0 cmake/Modules/FindLibbladeRF.cmake | 27 + cmake/Modules/FindPolarssl.cmake | 32 + cmake/Modules/FindUhd.cmake | 0 cmake/Modules/GrMiscUtils.cmake | 0 cmake/Modules/GrPlatform.cmake | 0 cmake/Modules/GrPython.cmake | 0 cmake/Modules/GrSwig.cmake | 0 cmake/cmake_uninstall.cmake.in | 0 enodeb_nat_script.sh | 41 + liblte/CMakeLists.txt | 9 + liblte/hdr/liblte_common.h | 28 +- liblte/hdr/liblte_interface.h | 85 +- liblte/hdr/liblte_mac.h | 40 +- liblte/hdr/liblte_mcc_mnc_list.h | 0 liblte/hdr/liblte_mme.h | 2174 ++- liblte/hdr/liblte_pdcp.h | 262 + liblte/hdr/liblte_phy.h | 473 +- liblte/hdr/liblte_rlc.h | 71 +- liblte/hdr/liblte_rrc.h | 3817 +++-- liblte/hdr/liblte_security.h | 266 + liblte/manual_tests/Makefile | 2 + liblte/manual_tests/ratematch_test.cc | 251 + liblte/src/liblte_common.cc | 93 + liblte/src/liblte_interface.cc | 38 +- liblte/src/liblte_mac.cc | 629 +- liblte/src/liblte_mme.cc | 12751 ++++++++++++++-- liblte/src/liblte_pdcp.cc | 503 + liblte/src/liblte_phy.cc | 1779 ++- liblte/src/liblte_rlc.cc | 588 +- liblte/src/liblte_rrc.cc | 6851 +++++++-- liblte/src/liblte_security.cc | 1243 ++ liblte/tests/liblte_common_tests.cc | 99 + libtools/CMakeLists.txt | 5 +- libtools/hdr/libtools_helpers.h | 100 + libtools/hdr/libtools_ipc_msgq.h | 154 + libtools/hdr/libtools_scoped_lock.h | 73 + libtools/hdr/libtools_socket_wrap.h | 7 +- libtools/src/libtools_helpers.cc | 304 + libtools/src/libtools_ipc_msgq.cc | 150 + libtools/src/libtools_scoped_lock.cc | 77 + libtools/src/libtools_socket_wrap.cc | 48 +- octave/cmn_bin2dec.m | 0 octave/cmn_conv_encode.m | 0 octave/cmn_dec2bin.m | 0 octave/cmn_oct2bin.m | 0 octave/cmn_viterbi_decode.m | 0 octave/lte_bcch_bch_msg_pack.m | 0 octave/lte_bcch_bch_msg_unpack.m | 0 octave/lte_bcch_dlsch_msg_pack.m | 0 octave/lte_bcch_dlsch_msg_unpack.m | 0 octave/lte_bch_channel_decode.m | 0 octave/lte_bch_channel_encode.m | 0 octave/lte_calc_crc.m | 0 octave/lte_cfi_channel_decode.m | 0 octave/lte_cfi_channel_encode.m | 0 octave/lte_code_block_concatenation.m | 0 octave/lte_code_block_deconcatenation.m | 0 octave/lte_code_block_desegmentation.m | 0 octave/lte_code_block_segmentation.m | 0 octave/lte_dci_1a_pack.m | 0 octave/lte_dci_1a_unpack.m | 0 octave/lte_dci_channel_decode.m | 0 octave/lte_dci_channel_encode.m | 0 octave/lte_dlsch_channel_decode.m | 0 octave/lte_dlsch_channel_encode.m | 0 octave/lte_fdd_dl_receive.m | 0 octave/lte_fdd_dl_transmit.m | 0 octave/lte_generate_crs.m | 0 .../lte_generate_dmrs_pucch_format1_1a_1b.m | 176 + octave/lte_generate_dmrs_pusch.m | 0 octave/lte_generate_prs_c.m | 0 octave/lte_generate_pss.m | 0 octave/lte_generate_sss.m | 0 octave/lte_generate_ul_rs.m | 0 octave/lte_get_tbs_7_1_7_2_1.m | 0 octave/lte_layer_demapper_dl.m | 0 octave/lte_layer_demapper_ul.m | 0 octave/lte_layer_mapper_dl.m | 0 octave/lte_layer_mapper_ul.m | 0 octave/lte_modulation_demapper.m | 0 octave/lte_modulation_mapper.m | 0 octave/lte_prach_bb_gen.m | 0 octave/lte_prach_detector.m | 0 octave/lte_prach_preamble_seq_gen.m | 0 octave/lte_pre_coder_dl.m | 0 octave/lte_pre_coder_ul.m | 0 .../lte_pre_decoder_and_matched_filter_dl.m | 0 .../lte_pre_decoder_and_matched_filter_ul.m | 0 octave/lte_pucch_demod.m | 294 + octave/lte_pusch_demod.m | 0 octave/lte_pusch_mod.m | 0 octave/lte_rate_match_conv.m | 0 octave/lte_rate_match_turbo.m | 0 octave/lte_rate_unmatch_conv.m | 0 octave/lte_rate_unmatch_turbo.m | 0 octave/lte_sib1_pack.m | 0 octave/lte_sib1_unpack.m | 0 octave/lte_turbo_decode.m | 0 octave/lte_turbo_encode.m | 0 octave/lte_ulsch_channel_decode.m | 0 octave/lte_ulsch_channel_deinterleaver.m | 0 octave/lte_ulsch_channel_encode.m | 0 octave/lte_ulsch_channel_interleaver.m | 0 .../lte_ulsch_control_data_demultiplexing.m | 0 octave/lte_ulsch_control_data_multiplexing.m | 0 178 files changed, 39775 insertions(+), 9856 deletions(-) mode change 100644 => 100755 AUTHORS mode change 100644 => 100755 CMakeLists.txt mode change 100644 => 100755 COPYING mode change 100644 => 100755 ChangeLog mode change 100644 => 100755 LTE_fdd_dl_file_gen/CMakeLists.txt mode change 100644 => 100755 LTE_fdd_dl_file_gen/hdr/LTE_fdd_dl_fg_api.h mode change 100644 => 100755 LTE_fdd_dl_file_gen/hdr/LTE_fdd_dl_fg_samp_buf.h mode change 100644 => 100755 LTE_fdd_dl_file_gen/src/LTE_fdd_dl_fg.i mode change 100644 => 100755 LTE_fdd_dl_file_gen/src/LTE_fdd_dl_fg_samp_buf.cc mode change 100644 => 100755 LTE_fdd_dl_file_gen/src/__init__.py mode change 100644 => 100755 LTE_fdd_dl_file_scan/CMakeLists.txt mode change 100644 => 100755 LTE_fdd_dl_file_scan/hdr/LTE_fdd_dl_fs_api.h mode change 100644 => 100755 LTE_fdd_dl_file_scan/hdr/LTE_fdd_dl_fs_samp_buf.h mode change 100644 => 100755 LTE_fdd_dl_file_scan/src/LTE_fdd_dl_fs.i mode change 100644 => 100755 LTE_fdd_dl_file_scan/src/LTE_fdd_dl_fs_samp_buf.cc mode change 100644 => 100755 LTE_fdd_dl_file_scan/src/__init__.py mode change 100644 => 100755 LTE_fdd_dl_scan/CMakeLists.txt mode change 100644 => 100755 LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_flowgraph.h mode change 100644 => 100755 LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_interface.h mode change 100644 => 100755 LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_state_machine.h mode change 100644 => 100755 LTE_fdd_dl_scan/hdr/LTE_fdd_dl_scan_state_machine_api.h mode change 100644 => 100755 LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_flowgraph.cc mode change 100644 => 100755 LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_interface.cc mode change 100644 => 100755 LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_main.cc mode change 100644 => 100755 LTE_fdd_dl_scan/src/LTE_fdd_dl_scan_state_machine.cc mode change 100644 => 100755 LTE_fdd_enodeb/CMakeLists.txt mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_cnfg_db.h create mode 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_common.h create mode 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_gw.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_hss.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_interface.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_mac.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_mme.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_msgq.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_pdcp.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_phy.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_radio.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_rb.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_rlc.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_rrc.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_timer_mgr.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_user.h mode change 100644 => 100755 LTE_fdd_enodeb/hdr/LTE_fdd_enb_user_mgr.h mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_cnfg_db.cc create mode 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_gw.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_hss.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_interface.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_mac.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_main.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_mme.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_msgq.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_pdcp.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_phy.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_radio.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_rb.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_rlc.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_rrc.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_timer.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_timer_mgr.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_user.cc mode change 100644 => 100755 LTE_fdd_enodeb/src/LTE_fdd_enb_user_mgr.cc mode change 100644 => 100755 LTE_file_recorder/CMakeLists.txt mode change 100644 => 100755 LTE_file_recorder/hdr/LTE_file_recorder_flowgraph.h mode change 100644 => 100755 LTE_file_recorder/hdr/LTE_file_recorder_interface.h mode change 100644 => 100755 LTE_file_recorder/src/LTE_file_recorder_flowgraph.cc mode change 100644 => 100755 LTE_file_recorder/src/LTE_file_recorder_interface.cc mode change 100644 => 100755 LTE_file_recorder/src/LTE_file_recorder_main.cc mode change 100644 => 100755 NEWS mode change 100644 => 100755 README mode change 100644 => 100755 cmake/Modules/CMakeParseArgumentsCopy.cmake mode change 100644 => 100755 cmake/Modules/FindFFTW3F.cmake mode change 100644 => 100755 cmake/Modules/FindGnuradioOsmosdr.cmake create mode 100755 cmake/Modules/FindLibbladeRF.cmake create mode 100755 cmake/Modules/FindPolarssl.cmake mode change 100644 => 100755 cmake/Modules/FindUhd.cmake mode change 100644 => 100755 cmake/Modules/GrMiscUtils.cmake mode change 100644 => 100755 cmake/Modules/GrPlatform.cmake mode change 100644 => 100755 cmake/Modules/GrPython.cmake mode change 100644 => 100755 cmake/Modules/GrSwig.cmake mode change 100644 => 100755 cmake/cmake_uninstall.cmake.in create mode 100755 enodeb_nat_script.sh mode change 100644 => 100755 liblte/CMakeLists.txt mode change 100644 => 100755 liblte/hdr/liblte_common.h mode change 100644 => 100755 liblte/hdr/liblte_interface.h mode change 100644 => 100755 liblte/hdr/liblte_mac.h mode change 100644 => 100755 liblte/hdr/liblte_mcc_mnc_list.h mode change 100644 => 100755 liblte/hdr/liblte_mme.h create mode 100755 liblte/hdr/liblte_pdcp.h mode change 100644 => 100755 liblte/hdr/liblte_phy.h mode change 100644 => 100755 liblte/hdr/liblte_rlc.h mode change 100644 => 100755 liblte/hdr/liblte_rrc.h create mode 100755 liblte/hdr/liblte_security.h create mode 100755 liblte/manual_tests/Makefile create mode 100755 liblte/manual_tests/ratematch_test.cc create mode 100755 liblte/src/liblte_common.cc mode change 100644 => 100755 liblte/src/liblte_interface.cc mode change 100644 => 100755 liblte/src/liblte_mac.cc mode change 100644 => 100755 liblte/src/liblte_mme.cc create mode 100755 liblte/src/liblte_pdcp.cc mode change 100644 => 100755 liblte/src/liblte_phy.cc mode change 100644 => 100755 liblte/src/liblte_rlc.cc mode change 100644 => 100755 liblte/src/liblte_rrc.cc create mode 100755 liblte/src/liblte_security.cc create mode 100755 liblte/tests/liblte_common_tests.cc mode change 100644 => 100755 libtools/CMakeLists.txt create mode 100755 libtools/hdr/libtools_helpers.h create mode 100755 libtools/hdr/libtools_ipc_msgq.h create mode 100755 libtools/hdr/libtools_scoped_lock.h mode change 100644 => 100755 libtools/hdr/libtools_socket_wrap.h create mode 100755 libtools/src/libtools_helpers.cc create mode 100755 libtools/src/libtools_ipc_msgq.cc create mode 100755 libtools/src/libtools_scoped_lock.cc mode change 100644 => 100755 libtools/src/libtools_socket_wrap.cc mode change 100644 => 100755 octave/cmn_bin2dec.m mode change 100644 => 100755 octave/cmn_conv_encode.m mode change 100644 => 100755 octave/cmn_dec2bin.m mode change 100644 => 100755 octave/cmn_oct2bin.m mode change 100644 => 100755 octave/cmn_viterbi_decode.m mode change 100644 => 100755 octave/lte_bcch_bch_msg_pack.m mode change 100644 => 100755 octave/lte_bcch_bch_msg_unpack.m mode change 100644 => 100755 octave/lte_bcch_dlsch_msg_pack.m mode change 100644 => 100755 octave/lte_bcch_dlsch_msg_unpack.m mode change 100644 => 100755 octave/lte_bch_channel_decode.m mode change 100644 => 100755 octave/lte_bch_channel_encode.m mode change 100644 => 100755 octave/lte_calc_crc.m mode change 100644 => 100755 octave/lte_cfi_channel_decode.m mode change 100644 => 100755 octave/lte_cfi_channel_encode.m mode change 100644 => 100755 octave/lte_code_block_concatenation.m mode change 100644 => 100755 octave/lte_code_block_deconcatenation.m mode change 100644 => 100755 octave/lte_code_block_desegmentation.m mode change 100644 => 100755 octave/lte_code_block_segmentation.m mode change 100644 => 100755 octave/lte_dci_1a_pack.m mode change 100644 => 100755 octave/lte_dci_1a_unpack.m mode change 100644 => 100755 octave/lte_dci_channel_decode.m mode change 100644 => 100755 octave/lte_dci_channel_encode.m mode change 100644 => 100755 octave/lte_dlsch_channel_decode.m mode change 100644 => 100755 octave/lte_dlsch_channel_encode.m mode change 100644 => 100755 octave/lte_fdd_dl_receive.m mode change 100644 => 100755 octave/lte_fdd_dl_transmit.m mode change 100644 => 100755 octave/lte_generate_crs.m create mode 100755 octave/lte_generate_dmrs_pucch_format1_1a_1b.m mode change 100644 => 100755 octave/lte_generate_dmrs_pusch.m mode change 100644 => 100755 octave/lte_generate_prs_c.m mode change 100644 => 100755 octave/lte_generate_pss.m mode change 100644 => 100755 octave/lte_generate_sss.m mode change 100644 => 100755 octave/lte_generate_ul_rs.m mode change 100644 => 100755 octave/lte_get_tbs_7_1_7_2_1.m mode change 100644 => 100755 octave/lte_layer_demapper_dl.m mode change 100644 => 100755 octave/lte_layer_demapper_ul.m mode change 100644 => 100755 octave/lte_layer_mapper_dl.m mode change 100644 => 100755 octave/lte_layer_mapper_ul.m mode change 100644 => 100755 octave/lte_modulation_demapper.m mode change 100644 => 100755 octave/lte_modulation_mapper.m mode change 100644 => 100755 octave/lte_prach_bb_gen.m mode change 100644 => 100755 octave/lte_prach_detector.m mode change 100644 => 100755 octave/lte_prach_preamble_seq_gen.m mode change 100644 => 100755 octave/lte_pre_coder_dl.m mode change 100644 => 100755 octave/lte_pre_coder_ul.m mode change 100644 => 100755 octave/lte_pre_decoder_and_matched_filter_dl.m mode change 100644 => 100755 octave/lte_pre_decoder_and_matched_filter_ul.m create mode 100755 octave/lte_pucch_demod.m mode change 100644 => 100755 octave/lte_pusch_demod.m mode change 100644 => 100755 octave/lte_pusch_mod.m mode change 100644 => 100755 octave/lte_rate_match_conv.m mode change 100644 => 100755 octave/lte_rate_match_turbo.m mode change 100644 => 100755 octave/lte_rate_unmatch_conv.m mode change 100644 => 100755 octave/lte_rate_unmatch_turbo.m mode change 100644 => 100755 octave/lte_sib1_pack.m mode change 100644 => 100755 octave/lte_sib1_unpack.m mode change 100644 => 100755 octave/lte_turbo_decode.m mode change 100644 => 100755 octave/lte_turbo_encode.m mode change 100644 => 100755 octave/lte_ulsch_channel_decode.m mode change 100644 => 100755 octave/lte_ulsch_channel_deinterleaver.m mode change 100644 => 100755 octave/lte_ulsch_channel_encode.m mode change 100644 => 100755 octave/lte_ulsch_channel_interleaver.m mode change 100644 => 100755 octave/lte_ulsch_control_data_demultiplexing.m mode change 100644 => 100755 octave/lte_ulsch_control_data_multiplexing.m 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..1526670 --- 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(Polarssl) 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..176bac2 --- 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 ${POLARSSL_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..169e9ad --- a/README +++ b/README @@ -25,6 +25,8 @@ openLTE is dependant on the following: 4) UHD 5) HackRF 6) bladeRF +7) polarssl +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/FindPolarssl.cmake b/cmake/Modules/FindPolarssl.cmake new file mode 100755 index 0000000..40f1f7b --- /dev/null +++ b/cmake/Modules/FindPolarssl.cmake @@ -0,0 +1,32 @@ +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_POLARSSL polarssl) + +FIND_PATH( + POLARSSL_INCLUDE_DIRS + NAMES polarssl/version.h + HINTS $ENV{POLARSSL_DIR}/include + ${PC_POLARSSL_INCLUDEDIR} + ${CMAKE_INSTALL_PREFIX}/include + PATHS /usr/local/include + /usr/include +) + +FIND_LIBRARY( + POLARSSL_LIBRARIES + NAMES polarssl + HINTS $ENV{POLARSSL_DIR}/lib + ${PC_POLARSSL_LIBDIR} + ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib64 + PATHS /usr/local/lib + /usr/local/lib64 + /usr/lib + /usr/lib64 +) + +message(STATUS "POLARSSL LIBRARIES " ${POLARSSL_LIBRARIES}) +message(STATUS "POLARSSL INCLUDE DIRS " ${POLARSSL_INCLUDE_DIRS}) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(POLARSSL DEFAULT_MSG POLARSSL_LIBRARIES POLARSSL_INCLUDE_DIRS) +MARK_AS_ADVANCED(POLARSSL_LIBRARIES POLARSSL_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..7f968b8 --- /dev/null +++ b/liblte/src/liblte_security.cc @@ -0,0 +1,1243 @@ +/******************************************************************************* + + 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 "polarssl/compat-1.2.h" +#include "polarssl/aes.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); + + 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); + + 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); + + // 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); + + 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); + + // 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); + + 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); + + // 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); + + 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 From 664f88682081663cef92630878bdf58000efe06a Mon Sep 17 00:00:00 2001 From: chliny Date: Wed, 16 Aug 2017 01:28:14 +0800 Subject: [PATCH 2/2] polarssl is out of date, update to mbedtls --- CMakeLists.txt | 2 +- LTE_fdd_enodeb/CMakeLists.txt | 4 +-- README | 2 +- cmake/Modules/FindMbedTLS.cmake | 47 ++++++++++++++++++++++++++++++++ cmake/Modules/FindPolarssl.cmake | 32 ---------------------- liblte/src/liblte_security.cc | 29 +++++++++++++------- 6 files changed, 70 insertions(+), 46 deletions(-) create mode 100755 cmake/Modules/FindMbedTLS.cmake delete mode 100755 cmake/Modules/FindPolarssl.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 1526670..48e7880 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,7 @@ find_package(GnuradioOsmosdr) find_package(Uhd) find_package(LibbladeRF) find_package(FFTW3F) -find_package(Polarssl) +find_package(MbedTLS) if(NOT GNURADIO_RUNTIME_FOUND) message(FATAL_ERROR "GNURadio required to compile openLTE") diff --git a/LTE_fdd_enodeb/CMakeLists.txt b/LTE_fdd_enodeb/CMakeLists.txt index 176bac2..ac71479 100755 --- a/LTE_fdd_enodeb/CMakeLists.txt +++ b/LTE_fdd_enodeb/CMakeLists.txt @@ -24,7 +24,7 @@ add_executable(LTE_fdd_enodeb src/LTE_fdd_enb_mme.cc src/LTE_fdd_enb_gw.cc ) -target_link_libraries(LTE_fdd_enodeb lte fftw3f tools pthread rt ${POLARSSL_LIBRARIES} ${UHD_LIBRARIES} ${LIBBLADERF_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\")") +#install(CODE "execute_process(COMMAND \"${CMAKE_SOURCE_DIR}/enodeb_nat_script.sh\")") diff --git a/README b/README index 169e9ad..81ff3d3 100755 --- a/README +++ b/README @@ -25,7 +25,7 @@ openLTE is dependant on the following: 4) UHD 5) HackRF 6) bladeRF -7) polarssl +7) mbedtls 8) iptables To build the C++ and python code use the following: 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/FindPolarssl.cmake b/cmake/Modules/FindPolarssl.cmake deleted file mode 100755 index 40f1f7b..0000000 --- a/cmake/Modules/FindPolarssl.cmake +++ /dev/null @@ -1,32 +0,0 @@ -INCLUDE(FindPkgConfig) -PKG_CHECK_MODULES(PC_POLARSSL polarssl) - -FIND_PATH( - POLARSSL_INCLUDE_DIRS - NAMES polarssl/version.h - HINTS $ENV{POLARSSL_DIR}/include - ${PC_POLARSSL_INCLUDEDIR} - ${CMAKE_INSTALL_PREFIX}/include - PATHS /usr/local/include - /usr/include -) - -FIND_LIBRARY( - POLARSSL_LIBRARIES - NAMES polarssl - HINTS $ENV{POLARSSL_DIR}/lib - ${PC_POLARSSL_LIBDIR} - ${CMAKE_INSTALL_PREFIX}/lib - ${CMAKE_INSTALL_PREFIX}/lib64 - PATHS /usr/local/lib - /usr/local/lib64 - /usr/lib - /usr/lib64 -) - -message(STATUS "POLARSSL LIBRARIES " ${POLARSSL_LIBRARIES}) -message(STATUS "POLARSSL INCLUDE DIRS " ${POLARSSL_INCLUDE_DIRS}) - -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(POLARSSL DEFAULT_MSG POLARSSL_LIBRARIES POLARSSL_INCLUDE_DIRS) -MARK_AS_ADVANCED(POLARSSL_LIBRARIES POLARSSL_INCLUDE_DIRS) diff --git a/liblte/src/liblte_security.cc b/liblte/src/liblte_security.cc index 7f968b8..2b320e5 100755 --- a/liblte/src/liblte_security.cc +++ b/liblte/src/liblte_security.cc @@ -35,8 +35,9 @@ *******************************************************************************/ #include "liblte_security.h" -#include "polarssl/compat-1.2.h" -#include "polarssl/aes.h" +#include "mbedtls/aes.h" +#include "mbedtls/compat-1.3.h" +#include "mbedtls/ssl.h" #include "math.h" /******************************************************************************* @@ -257,7 +258,8 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_asme(uint8 *ck, } // Derive Kasme - sha2_hmac(key, 32, s, 14, k_asme, 0); + //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; } @@ -292,7 +294,8 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_enb(uint8 *k_asme, s[6] = 0x04; // Second byte of L0 // Derive Kenb - sha2_hmac(k_asme, 32, s, 7, k_enb, 0); + //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; } @@ -330,7 +333,8 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_nas(uint8 s[6] = 0x01; // Second byte of L1 // Derive KNASenc - sha2_hmac(k_asme, 32, s, 7, k_nas_enc, 0); + //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 @@ -342,7 +346,8 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_nas(uint8 s[6] = 0x01; // Second byte of L1 // Derive KNASint - sha2_hmac(k_asme, 32, s, 7, k_nas_int, 0); + //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; } @@ -380,7 +385,8 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_rrc(uint8 s[6] = 0x01; // Second byte of L1 // Derive KRRCenc - sha2_hmac(k_enb, 32, s, 7, k_rrc_enc, 0); + //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 @@ -392,7 +398,8 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_rrc(uint8 s[6] = 0x01; // Second byte of L1 // Derive KRRCint - sha2_hmac(k_enb, 32, s, 7, k_rrc_int, 0); + //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; } @@ -431,7 +438,8 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_up(uint8 s[6] = 0x01; // Second byte of L1 // Derive KUPenc - sha2_hmac(k_enb, 32, s, 7, k_up_enc, 0); + //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 @@ -443,7 +451,8 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_up(uint8 s[6] = 0x01; // Second byte of L1 // Derive KUPint - sha2_hmac(k_enb, 32, s, 7, k_up_int, 0); + //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; }