/* * Copyright 2013-2020 Software Radio Systems Limited * * This file is part of srsLTE. * * srsLTE 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. * * srsLTE 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. * * A copy of the GNU Affero General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. * */ #include "srslte/asn1/rrc_asn1_utils.h" #include "srslte/asn1/rrc_asn1.h" #include "srslte/config.h" #include #include namespace srslte { using namespace asn1::rrc; /*************************** * PLMN ID **************************/ bool plmn_is_valid(const asn1::rrc::plmn_id_s& asn1_type) { return asn1_type.mcc_present and (asn1_type.mnc.size() == 3 or asn1_type.mnc.size() == 2); } plmn_id_t make_plmn_id_t(const asn1::rrc::plmn_id_s& asn1_type) { if (not plmn_is_valid(asn1_type)) { return {}; } plmn_id_t plmn; std::copy(&asn1_type.mcc[0], &asn1_type.mcc[3], &plmn.mcc[0]); plmn.nof_mnc_digits = asn1_type.mnc.size(); std::copy(&asn1_type.mnc[0], &asn1_type.mnc[plmn.nof_mnc_digits], &plmn.mnc[0]); return plmn; } void to_asn1(asn1::rrc::plmn_id_s* asn1_type, const plmn_id_t& cfg) { asn1_type->mcc_present = true; std::copy(&cfg.mcc[0], &cfg.mcc[3], &asn1_type->mcc[0]); asn1_type->mnc.resize(cfg.nof_mnc_digits); std::copy(&cfg.mnc[0], &cfg.mnc[cfg.nof_mnc_digits], &asn1_type->mnc[0]); } plmn_id_t make_plmn_id_t(const asn1::fixed_octstring<3, true>& asn1_type) // used for NGAP/S1AP { plmn_id_t plmn; uint16_t mcc, mnc; uint32_t encoded_plmn = asn1_type.to_number(); s1ap_plmn_to_mccmnc(encoded_plmn, &mcc, &mnc); plmn.from_number(mcc, mnc); return plmn; } void to_asn1(asn1::fixed_octstring<3, true>* asn1_type, const plmn_id_t& cfg) { uint16_t mcc, mnc; cfg.to_number(&mcc, &mnc); uint32_t encoded_plmn; s1ap_mccmnc_to_plmn(mcc, mnc, &encoded_plmn); asn1_type->from_number(encoded_plmn); } /*************************** * s-TMSI **************************/ s_tmsi_t make_s_tmsi_t(const asn1::rrc::s_tmsi_s& asn1_type) { s_tmsi_t tmsi; tmsi.mmec = asn1_type.mmec.to_number(); tmsi.m_tmsi = asn1_type.m_tmsi.to_number(); return tmsi; } void to_asn1(asn1::rrc::s_tmsi_s* asn1_type, const s_tmsi_t& cfg) { asn1_type->mmec.from_number(cfg.mmec); asn1_type->m_tmsi.from_number(cfg.m_tmsi); } /*************************** * CQI Report Aperiodic **************************/ srslte_cqi_report_mode_t make_aperiodic_mode(const asn1::rrc::cqi_report_mode_aperiodic_e asn_mode) { switch (asn_mode) { case asn1::rrc::cqi_report_mode_aperiodic_e::rm12: return SRSLTE_CQI_MODE_12; case asn1::rrc::cqi_report_mode_aperiodic_e::rm20: return SRSLTE_CQI_MODE_20; case asn1::rrc::cqi_report_mode_aperiodic_e::rm22: return SRSLTE_CQI_MODE_22; case asn1::rrc::cqi_report_mode_aperiodic_e::rm30: return SRSLTE_CQI_MODE_30; case asn1::rrc::cqi_report_mode_aperiodic_e::rm31: return SRSLTE_CQI_MODE_31; case asn1::rrc::cqi_report_mode_aperiodic_e::rm10_v1310: case asn1::rrc::cqi_report_mode_aperiodic_e::rm11_v1310: case asn1::rrc::cqi_report_mode_aperiodic_e::rm32_v1250: fprintf(stderr, "Aperiodic mode %s not handled\n", asn_mode.to_string().c_str()); default: return SRSLTE_CQI_MODE_NA; } } /*************************** * Establishment Cause **************************/ static_assert((int)establishment_cause_t::nulltype == (int)asn1::rrc::establishment_cause_opts::nulltype, "Failed conversion of ASN1 type"); /*************************** * RLC Config **************************/ srslte::rlc_config_t make_rlc_config_t(const asn1::rrc::rlc_cfg_c& asn1_type) { srslte::rlc_config_t rlc_cfg; switch (asn1_type.type().value) { case asn1::rrc::rlc_cfg_c::types_opts::am: rlc_cfg.rlc_mode = rlc_mode_t::am; rlc_cfg.am.t_poll_retx = asn1_type.am().ul_am_rlc.t_poll_retx.to_number(); rlc_cfg.am.poll_pdu = asn1_type.am().ul_am_rlc.poll_pdu.to_number(); rlc_cfg.am.poll_byte = asn1_type.am().ul_am_rlc.poll_byte.to_number() * 1000; // KB rlc_cfg.am.max_retx_thresh = asn1_type.am().ul_am_rlc.max_retx_thres.to_number(); rlc_cfg.am.t_reordering = asn1_type.am().dl_am_rlc.t_reordering.to_number(); rlc_cfg.am.t_status_prohibit = asn1_type.am().dl_am_rlc.t_status_prohibit.to_number(); break; case asn1::rrc::rlc_cfg_c::types_opts::um_bi_dir: case asn1::rrc::rlc_cfg_c::types_opts::um_uni_dir_dl: case asn1::rrc::rlc_cfg_c::types_opts::um_uni_dir_ul: rlc_cfg.rlc_mode = rlc_mode_t::um; rlc_cfg.um.t_reordering = asn1_type.um_bi_dir().dl_um_rlc.t_reordering.to_number(); rlc_cfg.um.rx_sn_field_length = (rlc_umd_sn_size_t)asn1_type.um_bi_dir().dl_um_rlc.sn_field_len.value; rlc_cfg.um.rx_window_size = (rlc_cfg.um.rx_sn_field_length == rlc_umd_sn_size_t::size5bits) ? 16 : 512; rlc_cfg.um.rx_mod = (rlc_cfg.um.rx_sn_field_length == rlc_umd_sn_size_t::size5bits) ? 32 : 1024; rlc_cfg.um.tx_sn_field_length = (rlc_umd_sn_size_t)asn1_type.um_bi_dir().ul_um_rlc.sn_field_len.value; rlc_cfg.um.tx_mod = (rlc_cfg.um.tx_sn_field_length == rlc_umd_sn_size_t::size5bits) ? 32 : 1024; break; default: break; } return rlc_cfg; } srslte::rlc_config_t make_rlc_config_t(const asn1::rrc::srb_to_add_mod_s& asn1_type) { if (asn1_type.rlc_cfg.type().value == asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_::types_opts::explicit_value) { return make_rlc_config_t(asn1_type.rlc_cfg.explicit_value()); } if (asn1_type.srb_id <= 2) { return rlc_config_t::srb_config(asn1_type.srb_id); } else { asn1::log_error("SRB %d does not support default initialization type\n", asn1_type.srb_id); return rlc_config_t(); } } void to_asn1(asn1::rrc::rlc_cfg_c* asn1_type, const srslte::rlc_config_t& cfg) { *asn1_type = asn1::rrc::rlc_cfg_c(); switch (cfg.rlc_mode) { case rlc_mode_t::um: asn1_type->set_um_bi_dir(); asn1::number_to_enum(asn1_type->um_bi_dir().dl_um_rlc.t_reordering, cfg.um.t_reordering); asn1_type->um_bi_dir().dl_um_rlc.sn_field_len.value = (asn1::rrc::sn_field_len_opts::options)cfg.um.rx_sn_field_length; asn1_type->um_bi_dir().ul_um_rlc.sn_field_len.value = (asn1::rrc::sn_field_len_opts::options)cfg.um.tx_sn_field_length; break; case rlc_mode_t::am: asn1_type->set_am(); asn1::number_to_enum(asn1_type->am().ul_am_rlc.t_poll_retx, cfg.am.t_poll_retx); asn1::number_to_enum(asn1_type->am().ul_am_rlc.poll_pdu, cfg.am.poll_pdu); asn1::number_to_enum(asn1_type->am().ul_am_rlc.poll_byte, cfg.am.poll_byte / 1000); asn1::number_to_enum(asn1_type->am().ul_am_rlc.max_retx_thres, cfg.am.max_retx_thresh); asn1::number_to_enum(asn1_type->am().dl_am_rlc.t_reordering, cfg.am.t_reordering); asn1::number_to_enum(asn1_type->am().dl_am_rlc.t_status_prohibit, cfg.am.t_status_prohibit); break; default: // stays TM break; } } /** * PDCP Config */ srslte::pdcp_config_t make_srb_pdcp_config_t(const uint8_t bearer_id, bool is_ue) { pdcp_config_t cfg(bearer_id, PDCP_RB_IS_SRB, is_ue ? SECURITY_DIRECTION_UPLINK : SECURITY_DIRECTION_DOWNLINK, is_ue ? SECURITY_DIRECTION_DOWNLINK : SECURITY_DIRECTION_UPLINK, PDCP_SN_LEN_5, pdcp_t_reordering_t::ms500, pdcp_discard_timer_t::infinity); return cfg; } srslte::pdcp_config_t make_drb_pdcp_config_t(const uint8_t bearer_id, bool is_ue) { pdcp_config_t cfg(bearer_id, PDCP_RB_IS_DRB, is_ue ? SECURITY_DIRECTION_UPLINK : SECURITY_DIRECTION_DOWNLINK, is_ue ? SECURITY_DIRECTION_DOWNLINK : SECURITY_DIRECTION_UPLINK, PDCP_SN_LEN_12, pdcp_t_reordering_t::ms500, pdcp_discard_timer_t::infinity); return cfg; } srslte::pdcp_config_t make_drb_pdcp_config_t(const uint8_t bearer_id, bool is_ue, const asn1::rrc::pdcp_cfg_s& pdcp_cfg) { // TODO: complete config processing pdcp_discard_timer_t discard_timer = pdcp_discard_timer_t::infinity; if (pdcp_cfg.discard_timer_present) { switch (pdcp_cfg.discard_timer.to_number()) { case 10: discard_timer = pdcp_discard_timer_t::ms10; break; default: discard_timer = pdcp_discard_timer_t::infinity; break; } } pdcp_t_reordering_t t_reordering = pdcp_t_reordering_t::ms500; if (pdcp_cfg.t_reordering_r12_present) { switch (pdcp_cfg.t_reordering_r12.to_number()) { case 0: t_reordering = pdcp_t_reordering_t::ms0; break; default: t_reordering = pdcp_t_reordering_t::ms500; } } uint8_t sn_len = srslte::PDCP_SN_LEN_12; if (pdcp_cfg.rlc_um_present) { if (pdcp_cfg.rlc_um.pdcp_sn_size.value == pdcp_cfg_s::rlc_um_s_::pdcp_sn_size_e_::len7bits) { sn_len = srslte::PDCP_SN_LEN_7; } } if (pdcp_cfg.rlc_am_present) { // TODO: handle RLC AM config for PDCP } pdcp_config_t cfg(bearer_id, PDCP_RB_IS_DRB, is_ue ? SECURITY_DIRECTION_UPLINK : SECURITY_DIRECTION_DOWNLINK, is_ue ? SECURITY_DIRECTION_DOWNLINK : SECURITY_DIRECTION_UPLINK, sn_len, t_reordering, discard_timer); return cfg; } /*************************** * MAC Config **************************/ void set_mac_cfg_t_sched_request_cfg(mac_cfg_t* cfg, const asn1::rrc::sched_request_cfg_c& asn1_type) { cfg->sr_cfg.enabled = asn1_type.type() == asn1::rrc::setup_e::setup; if (cfg->sr_cfg.enabled) { cfg->sr_cfg.dsr_transmax = asn1_type.setup().dsr_trans_max.to_number(); } } // MAC-MainConfig section is always present void set_mac_cfg_t_main_cfg(mac_cfg_t* cfg, const asn1::rrc::mac_main_cfg_s& asn1_type) { // Update values only if each section is present if (asn1_type.phr_cfg_present) { cfg->phr_cfg.enabled = asn1_type.phr_cfg.type() == asn1::rrc::setup_e::setup; if (cfg->phr_cfg.enabled) { cfg->phr_cfg.prohibit_timer = asn1_type.phr_cfg.setup().prohibit_phr_timer.to_number(); cfg->phr_cfg.periodic_timer = asn1_type.phr_cfg.setup().periodic_phr_timer.to_number(); cfg->phr_cfg.db_pathloss_change = asn1_type.phr_cfg.setup().dl_pathloss_change.to_number(); } } if (asn1_type.mac_main_cfg_v1020.is_present()) { cfg->phr_cfg.extended = asn1_type.mac_main_cfg_v1020.get()->extended_phr_r10_present; } if (asn1_type.ul_sch_cfg_present) { cfg->bsr_cfg.periodic_timer = asn1_type.ul_sch_cfg.periodic_bsr_timer.to_number(); cfg->bsr_cfg.retx_timer = asn1_type.ul_sch_cfg.retx_bsr_timer.to_number(); if (asn1_type.ul_sch_cfg.max_harq_tx_present) { cfg->harq_cfg.max_harq_tx = asn1_type.ul_sch_cfg.max_harq_tx.to_number(); } } // TimeAlignmentDedicated overwrites Common?? cfg->time_alignment_timer = asn1_type.time_align_timer_ded.to_number(); } // RACH-Common section is always present void set_mac_cfg_t_rach_cfg_common(mac_cfg_t* cfg, const asn1::rrc::rach_cfg_common_s& asn1_type) { // Preamble info cfg->rach_cfg.nof_preambles = asn1_type.preamb_info.nof_ra_preambs.to_number(); if (asn1_type.preamb_info.preambs_group_a_cfg_present) { cfg->rach_cfg.nof_groupA_preambles = asn1_type.preamb_info.preambs_group_a_cfg.size_of_ra_preambs_group_a.to_number(); cfg->rach_cfg.messageSizeGroupA = asn1_type.preamb_info.preambs_group_a_cfg.msg_size_group_a.to_number(); cfg->rach_cfg.messagePowerOffsetGroupB = asn1_type.preamb_info.preambs_group_a_cfg.msg_pwr_offset_group_b.to_number(); } else { cfg->rach_cfg.nof_groupA_preambles = 0; } // Power ramping cfg->rach_cfg.powerRampingStep = asn1_type.pwr_ramp_params.pwr_ramp_step.to_number(); cfg->rach_cfg.iniReceivedTargetPower = asn1_type.pwr_ramp_params.preamb_init_rx_target_pwr.to_number(); // Supervision info cfg->rach_cfg.preambleTransMax = asn1_type.ra_supervision_info.preamb_trans_max.to_number(); cfg->rach_cfg.responseWindowSize = asn1_type.ra_supervision_info.ra_resp_win_size.to_number(); cfg->rach_cfg.contentionResolutionTimer = asn1_type.ra_supervision_info.mac_contention_resolution_timer.to_number(); // HARQ Msg3 cfg->harq_cfg.max_harq_msg3_tx = asn1_type.max_harq_msg3_tx; } void set_mac_cfg_t_time_alignment(mac_cfg_t* cfg, const asn1::rrc::time_align_timer_opts asn1_type) { cfg->time_alignment_timer = asn1_type.to_number(); } srsenb::sched_interface::ant_info_ded_t make_ant_info_ded(const asn1::rrc::ant_info_ded_s& asn1_type) { srsenb::sched_interface::ant_info_ded_t ant_ded = {}; ant_ded.tx_mode = static_cast(asn1_type.tx_mode.value); ant_ded.cookbook_subset_type = srsenb::sched_interface::ant_info_ded_t::codebook_t::none; if (asn1_type.codebook_subset_restrict_present) { auto& asn1code = asn1_type.codebook_subset_restrict; ant_ded.cookbook_subset_type = static_cast(asn1code.type().value); switch (asn1code.type().value) { case ant_info_ded_s::codebook_subset_restrict_c_::types_opts::n2_tx_ant_tm3: ant_ded.codebook_subset_restrict = asn1code.n2_tx_ant_tm3().to_number(); break; case ant_info_ded_s::codebook_subset_restrict_c_::types_opts::n4_tx_ant_tm3: ant_ded.codebook_subset_restrict = asn1code.n4_tx_ant_tm3().to_number(); break; case ant_info_ded_s::codebook_subset_restrict_c_::types_opts::n2_tx_ant_tm4: ant_ded.codebook_subset_restrict = asn1code.n2_tx_ant_tm4().to_number(); break; case ant_info_ded_s::codebook_subset_restrict_c_::types_opts::n4_tx_ant_tm4: ant_ded.codebook_subset_restrict = asn1code.n4_tx_ant_tm4().to_number(); break; case ant_info_ded_s::codebook_subset_restrict_c_::types_opts::n2_tx_ant_tm5: ant_ded.codebook_subset_restrict = asn1code.n2_tx_ant_tm5().to_number(); break; case ant_info_ded_s::codebook_subset_restrict_c_::types_opts::n4_tx_ant_tm5: ant_ded.codebook_subset_restrict = asn1code.n4_tx_ant_tm5().to_number(); break; case ant_info_ded_s::codebook_subset_restrict_c_::types_opts::n2_tx_ant_tm6: ant_ded.codebook_subset_restrict = asn1code.n2_tx_ant_tm6().to_number(); break; case ant_info_ded_s::codebook_subset_restrict_c_::types_opts::n4_tx_ant_tm6: ant_ded.codebook_subset_restrict = asn1code.n4_tx_ant_tm6().to_number(); break; default: asn1::log_error("Failed to convert antenna codebook type to number\n"); } } ant_ded.ue_tx_ant_sel = srsenb::sched_interface::ant_info_ded_t::ue_tx_ant_sel_t::release; if (asn1_type.ue_tx_ant_sel.type().value == setup_opts::setup) { ant_ded.ue_tx_ant_sel = (asn1_type.ue_tx_ant_sel.setup().value == ant_info_ded_s::ue_tx_ant_sel_c_::setup_opts::closed_loop) ? srsenb::sched_interface::ant_info_ded_t::ue_tx_ant_sel_t::closed_loop : srsenb::sched_interface::ant_info_ded_t::ue_tx_ant_sel_t::open_loop; } return ant_ded; } void set_phy_cfg_t_dedicated_cfg(phy_cfg_t* cfg, const asn1::rrc::phys_cfg_ded_s& asn1_type) { if (asn1_type.pucch_cfg_ded_present) { if (asn1_type.pucch_cfg_ded.tdd_ack_nack_feedback_mode_present) { cfg->ul_cfg.pucch.tdd_ack_multiplex = asn1_type.pucch_cfg_ded.tdd_ack_nack_feedback_mode == asn1::rrc::pucch_cfg_ded_s::tdd_ack_nack_feedback_mode_e_::mux; } else { cfg->ul_cfg.pucch.tdd_ack_multiplex = false; } } if (asn1_type.pucch_cfg_ded_v1020.is_present()) { auto* pucch_cfg_ded = asn1_type.pucch_cfg_ded_v1020.get(); if (pucch_cfg_ded->pucch_format_r10_present) { typedef asn1::rrc::pucch_cfg_ded_v1020_s::pucch_format_r10_c_ pucch_format_r10_t; auto* pucch_format_r10 = &pucch_cfg_ded->pucch_format_r10; if (pucch_format_r10->type() == pucch_format_r10_t::types::format3_r10) { // Select feedback mode cfg->ul_cfg.pucch.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3; auto* format3_r13 = &pucch_format_r10->format3_r10(); for (uint32_t n = 0; n < SRSLTE_MIN(format3_r13->n3_pucch_an_list_r13.size(), SRSLTE_PUCCH_SIZE_AN_CS); n++) { cfg->ul_cfg.pucch.n3_pucch_an_list[n] = format3_r13->n3_pucch_an_list_r13[n]; } if (format3_r13->two_ant_port_activ_pucch_format3_r13_present) { if (format3_r13->two_ant_port_activ_pucch_format3_r13.type() == asn1::rrc::setup_e::setup) { // TODO: UL MIMO Configure PUCCH two antenna port } else { // TODO: UL MIMO Disable two antenna port } } } else if (pucch_format_r10->type() == asn1::rrc::pucch_cfg_ded_v1020_s::pucch_format_r10_c_::types::ch_sel_r10) { typedef pucch_format_r10_t::ch_sel_r10_s_ ch_sel_r10_t; auto* ch_sel_r10 = &pucch_format_r10->ch_sel_r10(); if (ch_sel_r10->n1_pucch_an_cs_r10_present) { typedef ch_sel_r10_t::n1_pucch_an_cs_r10_c_ n1_pucch_an_cs_r10_t; auto* n1_pucch_an_cs_r10 = &ch_sel_r10->n1_pucch_an_cs_r10; if (n1_pucch_an_cs_r10->type() == asn1::rrc::setup_e::setup) { // Select feedback mode cfg->ul_cfg.pucch.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS; typedef n1_pucch_an_cs_r10_t::setup_s_::n1_pucch_an_cs_list_r10_l_ n1_pucch_an_cs_list_r10_t; n1_pucch_an_cs_list_r10_t n1_pucch_an_cs_list = ch_sel_r10->n1_pucch_an_cs_r10.setup().n1_pucch_an_cs_list_r10; for (uint32_t i = 0; i < SRSLTE_MIN(n1_pucch_an_cs_list.size(), SRSLTE_PUCCH_NOF_AN_CS); i++) { asn1::rrc::n1_pucch_an_cs_r10_l n1_pucch_an_cs = n1_pucch_an_cs_list[i]; for (uint32_t j = 0; j < SRSLTE_PUCCH_SIZE_AN_CS; j++) { cfg->ul_cfg.pucch.n1_pucch_an_cs[j][i] = n1_pucch_an_cs[j]; } } } else { cfg->ul_cfg.pucch.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_NORMAL; } } } else { // Do nothing } } } if (asn1_type.pusch_cfg_ded_present) { cfg->ul_cfg.pusch.uci_offset.I_offset_ack = asn1_type.pusch_cfg_ded.beta_offset_ack_idx; cfg->ul_cfg.pusch.uci_offset.I_offset_cqi = asn1_type.pusch_cfg_ded.beta_offset_cqi_idx; cfg->ul_cfg.pusch.uci_offset.I_offset_ri = asn1_type.pusch_cfg_ded.beta_offset_ri_idx; } if (asn1_type.ul_pwr_ctrl_ded_present) { cfg->ul_cfg.power_ctrl.p0_ue_pusch = asn1_type.ul_pwr_ctrl_ded.p0_ue_pusch; cfg->ul_cfg.power_ctrl.delta_mcs_based = asn1_type.ul_pwr_ctrl_ded.delta_mcs_enabled == asn1::rrc::ul_pwr_ctrl_ded_s::delta_mcs_enabled_e_::en0; cfg->ul_cfg.power_ctrl.acc_enabled = asn1_type.ul_pwr_ctrl_ded.accumulation_enabled; cfg->ul_cfg.power_ctrl.p0_ue_pucch = asn1_type.ul_pwr_ctrl_ded.p0_ue_pucch; cfg->ul_cfg.power_ctrl.p_srs_offset = asn1_type.ul_pwr_ctrl_ded.psrs_offset; } if (asn1_type.ul_pwr_ctrl_ded.filt_coef_present) { // TODO } if (asn1_type.tpc_pdcch_cfg_pucch_present) { // TODO } if (asn1_type.tpc_pdcch_cfg_pusch_present) { // TODO } if (asn1_type.cqi_report_cfg_present) { if (asn1_type.cqi_report_cfg.cqi_report_periodic_present) { cfg->dl_cfg.cqi_report.periodic_configured = asn1_type.cqi_report_cfg.cqi_report_periodic.type() == asn1::rrc::setup_e::setup; if (cfg->dl_cfg.cqi_report.periodic_configured) { cfg->ul_cfg.pucch.n_pucch_2 = asn1_type.cqi_report_cfg.cqi_report_periodic.setup().cqi_pucch_res_idx; cfg->ul_cfg.pucch.simul_cqi_ack = asn1_type.cqi_report_cfg.cqi_report_periodic.setup().simul_ack_nack_and_cqi; cfg->dl_cfg.cqi_report.pmi_idx = asn1_type.cqi_report_cfg.cqi_report_periodic.setup().cqi_pmi_cfg_idx; cfg->dl_cfg.cqi_report.format_is_subband = asn1_type.cqi_report_cfg.cqi_report_periodic.setup().cqi_format_ind_periodic.type().value == asn1::rrc::cqi_report_periodic_c::setup_s_::cqi_format_ind_periodic_c_::types::subband_cqi; if (cfg->dl_cfg.cqi_report.format_is_subband) { cfg->dl_cfg.cqi_report.subband_size = asn1_type.cqi_report_cfg.cqi_report_periodic.setup().cqi_format_ind_periodic.subband_cqi().k; } if (asn1_type.cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx_present) { cfg->dl_cfg.cqi_report.ri_idx = asn1_type.cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx; cfg->dl_cfg.cqi_report.ri_idx_present = true; } else { cfg->dl_cfg.cqi_report.ri_idx_present = false; } } else { cfg->ul_cfg.pucch.n_pucch_2 = 0; cfg->ul_cfg.pucch.simul_cqi_ack = false; } } if (asn1_type.cqi_report_cfg.cqi_report_mode_aperiodic_present) { cfg->dl_cfg.cqi_report.aperiodic_configured = true; cfg->dl_cfg.cqi_report.aperiodic_mode = make_aperiodic_mode(asn1_type.cqi_report_cfg.cqi_report_mode_aperiodic); } } if (asn1_type.cqi_report_cfg_pcell_v1250.is_present()) { auto cqi_report_cfg_pcell_v1250 = asn1_type.cqi_report_cfg_pcell_v1250.get(); if (cqi_report_cfg_pcell_v1250->alt_cqi_table_r12_present) { cfg->dl_cfg.pdsch.use_tbs_index_alt = true; } } else { cfg->dl_cfg.pdsch.use_tbs_index_alt = false; } if (asn1_type.srs_ul_cfg_ded_present) { cfg->ul_cfg.srs.dedicated_enabled = asn1_type.srs_ul_cfg_ded.type() == asn1::rrc::setup_e::setup; if (cfg->ul_cfg.srs.dedicated_enabled) { cfg->ul_cfg.srs.configured = cfg->ul_cfg.srs.dedicated_enabled and cfg->ul_cfg.srs.common_enabled; cfg->ul_cfg.srs.I_srs = asn1_type.srs_ul_cfg_ded.setup().srs_cfg_idx; cfg->ul_cfg.srs.B = asn1_type.srs_ul_cfg_ded.setup().srs_bw; cfg->ul_cfg.srs.b_hop = asn1_type.srs_ul_cfg_ded.setup().srs_hop_bw; cfg->ul_cfg.srs.n_rrc = asn1_type.srs_ul_cfg_ded.setup().freq_domain_position; cfg->ul_cfg.srs.k_tc = asn1_type.srs_ul_cfg_ded.setup().tx_comb; cfg->ul_cfg.srs.n_srs = asn1_type.srs_ul_cfg_ded.setup().cyclic_shift; } } if (asn1_type.ant_info_r10.is_present() && asn1_type.ant_info_r10->type() == asn1::rrc::phys_cfg_ded_s::ant_info_r10_c_::types::explicit_value_r10) { // Parse Release 10 asn1::rrc::ant_info_ded_r10_s::tx_mode_r10_e_::options tx_mode = asn1_type.ant_info_r10->explicit_value_r10().tx_mode_r10.value; if ((srslte_tm_t)tx_mode < SRSLTE_TMINV) { cfg->dl_cfg.tm = (srslte_tm_t)tx_mode; } else { fprintf(stderr, "Transmission mode (R10) %s is not supported\n", asn1_type.ant_info_r10->explicit_value_r10().tx_mode_r10.to_string().c_str()); } } else if (asn1_type.ant_info_present && asn1_type.ant_info.type() == asn1::rrc::phys_cfg_ded_s::ant_info_c_::types::explicit_value) { // Parse Release 8 asn1::rrc::ant_info_ded_s::tx_mode_e_::options tx_mode = asn1_type.ant_info.explicit_value().tx_mode.value; if ((srslte_tm_t)tx_mode < SRSLTE_TMINV) { cfg->dl_cfg.tm = (srslte_tm_t)tx_mode; } else { fprintf(stderr, "Transmission mode (R8) %s is not supported\n", asn1_type.ant_info.explicit_value().tx_mode.to_string().c_str()); } } if (asn1_type.sched_request_cfg_present) { if (asn1_type.sched_request_cfg_present and asn1_type.sched_request_cfg.type() == asn1::rrc::setup_e::setup) { cfg->ul_cfg.pucch.I_sr = asn1_type.sched_request_cfg.setup().sr_cfg_idx; cfg->ul_cfg.pucch.n_pucch_sr = asn1_type.sched_request_cfg.setup().sr_pucch_res_idx; cfg->ul_cfg.pucch.sr_configured = true; } else { cfg->ul_cfg.pucch.I_sr = 0; cfg->ul_cfg.pucch.n_pucch_sr = 0; cfg->ul_cfg.pucch.sr_configured = false; } } if (asn1_type.pdsch_cfg_ded_present) { // Configure PDSCH if (asn1_type.pdsch_cfg_ded_present && cfg->dl_cfg.pdsch.p_b < 4) { cfg->dl_cfg.pdsch.p_a = asn1_type.pdsch_cfg_ded.p_a.to_number(); cfg->dl_cfg.pdsch.power_scale = true; } else { cfg->dl_cfg.pdsch.power_scale = false; } } } void set_phy_cfg_t_common_prach(phy_cfg_t* cfg, const asn1::rrc::prach_cfg_info_s* asn1_type, uint32_t root_seq_idx) { if (asn1_type) { cfg->prach_cfg.config_idx = asn1_type->prach_cfg_idx; cfg->prach_cfg.zero_corr_zone = asn1_type->zero_correlation_zone_cfg; cfg->prach_cfg.freq_offset = asn1_type->prach_freq_offset; cfg->prach_cfg.hs_flag = asn1_type->high_speed_flag; } cfg->prach_cfg.root_seq_idx = root_seq_idx; cfg->prach_cfg_present = true; } void set_phy_cfg_t_common_pdsch(phy_cfg_t* cfg, const asn1::rrc::pdsch_cfg_common_s& asn1_type) { cfg->dl_cfg.pdsch.rs_power = (float)asn1_type.ref_sig_pwr; cfg->dl_cfg.pdsch.p_b = asn1_type.p_b; } void set_phy_cfg_t_enable_64qam(phy_cfg_t* cfg, const bool enabled) { cfg->ul_cfg.pusch.enable_64qam = enabled; } void set_phy_cfg_t_common_pusch(phy_cfg_t* cfg, const asn1::rrc::pusch_cfg_common_s& asn1_type) { /* PUSCH DMRS signal configuration */ bzero(&cfg->ul_cfg.dmrs, sizeof(srslte_refsignal_dmrs_pusch_cfg_t)); cfg->ul_cfg.dmrs.group_hopping_en = asn1_type.ul_ref_sigs_pusch.group_hop_enabled; cfg->ul_cfg.dmrs.sequence_hopping_en = asn1_type.ul_ref_sigs_pusch.seq_hop_enabled; cfg->ul_cfg.dmrs.cyclic_shift = asn1_type.ul_ref_sigs_pusch.cyclic_shift; cfg->ul_cfg.dmrs.delta_ss = asn1_type.ul_ref_sigs_pusch.group_assign_pusch; /* PUSCH Hopping configuration */ bzero(&cfg->ul_cfg.hopping, sizeof(srslte_pusch_hopping_cfg_t)); cfg->ul_cfg.hopping.n_sb = asn1_type.pusch_cfg_basic.n_sb; cfg->ul_cfg.hopping.hopping_offset = asn1_type.pusch_cfg_basic.pusch_hop_offset; cfg->ul_cfg.hopping.hop_mode = asn1_type.pusch_cfg_basic.hop_mode.value == asn1::rrc::pusch_cfg_common_s::pusch_cfg_basic_s_::hop_mode_e_::intra_and_inter_sub_frame ? cfg->ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF : cfg->ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF; } void set_phy_cfg_t_common_pucch(phy_cfg_t* cfg, const asn1::rrc::pucch_cfg_common_s& asn1_type) { /* PUCCH configuration */ cfg->ul_cfg.pucch.delta_pucch_shift = asn1_type.delta_pucch_shift.to_number(); cfg->ul_cfg.pucch.N_cs = asn1_type.ncs_an; cfg->ul_cfg.pucch.n_rb_2 = asn1_type.nrb_cqi; cfg->ul_cfg.pucch.N_pucch_1 = asn1_type.n1_pucch_an; } void set_phy_cfg_t_common_srs(phy_cfg_t* cfg, const asn1::rrc::srs_ul_cfg_common_c& asn1_type) { cfg->ul_cfg.srs.common_enabled = asn1_type.type() == asn1::rrc::setup_e::setup; if (cfg->ul_cfg.srs.common_enabled) { cfg->ul_cfg.srs.simul_ack = asn1_type.setup().ack_nack_srs_simul_tx; cfg->ul_cfg.srs.bw_cfg = asn1_type.setup().srs_bw_cfg.to_number(); cfg->ul_cfg.srs.subframe_config = asn1_type.setup().srs_sf_cfg.to_number(); } } void set_phy_cfg_t_common_pwr_ctrl(phy_cfg_t* cfg, const asn1::rrc::ul_pwr_ctrl_common_s& asn1_type) { cfg->ul_cfg.power_ctrl.p0_nominal_pusch = asn1_type.p0_nominal_pusch; cfg->ul_cfg.power_ctrl.alpha = asn1_type.alpha.to_number(); cfg->ul_cfg.power_ctrl.p0_nominal_pucch = asn1_type.p0_nominal_pucch; cfg->ul_cfg.power_ctrl.delta_f_pucch[0] = asn1_type.delta_flist_pucch.delta_f_pucch_format1.to_number(); cfg->ul_cfg.power_ctrl.delta_f_pucch[1] = asn1_type.delta_flist_pucch.delta_f_pucch_format1b.to_number(); cfg->ul_cfg.power_ctrl.delta_f_pucch[2] = asn1_type.delta_flist_pucch.delta_f_pucch_format2.to_number(); cfg->ul_cfg.power_ctrl.delta_f_pucch[3] = asn1_type.delta_flist_pucch.delta_f_pucch_format2a.to_number(); cfg->ul_cfg.power_ctrl.delta_f_pucch[4] = asn1_type.delta_flist_pucch.delta_f_pucch_format2b.to_number(); cfg->ul_cfg.power_ctrl.delta_preamble_msg3 = asn1_type.delta_preamb_msg3; } void set_phy_cfg_t_scell_config(phy_cfg_t* cfg, const asn1::rrc::scell_to_add_mod_r10_s& asn1_type) { if (asn1_type.rr_cfg_common_scell_r10_present) { // Enable always CSI request extra bit cfg->dl_cfg.dci.multiple_csi_request_enabled = true; auto* rr_cfg_common_scell_r10 = &asn1_type.rr_cfg_common_scell_r10; if (rr_cfg_common_scell_r10->ul_cfg_r10_present) { auto* ul_cfg_r10 = &rr_cfg_common_scell_r10->ul_cfg_r10; // Parse Power control auto* ul_pwr_ctrl_common_scell_r10 = &ul_cfg_r10->ul_pwr_ctrl_common_scell_r10; bzero(&cfg->ul_cfg.power_ctrl, sizeof(srslte_ue_ul_powerctrl_t)); cfg->ul_cfg.power_ctrl.p0_nominal_pusch = ul_pwr_ctrl_common_scell_r10->p0_nominal_pusch_r10; cfg->ul_cfg.power_ctrl.alpha = ul_pwr_ctrl_common_scell_r10->alpha_r10.to_number(); // Parse SRS cfg->ul_cfg.srs.common_enabled = ul_cfg_r10->srs_ul_cfg_common_r10.type() == asn1::rrc::setup_e::setup; if (cfg->ul_cfg.srs.common_enabled) { auto* srs_ul_cfg_common = &ul_cfg_r10->srs_ul_cfg_common_r10.setup(); cfg->ul_cfg.srs.simul_ack = srs_ul_cfg_common->ack_nack_srs_simul_tx; cfg->ul_cfg.srs.bw_cfg = srs_ul_cfg_common->srs_bw_cfg.to_number(); cfg->ul_cfg.srs.subframe_config = srs_ul_cfg_common->srs_sf_cfg.to_number(); } // Parse PUSCH auto* pusch_cfg_common = &ul_cfg_r10->pusch_cfg_common_r10; bzero(&cfg->ul_cfg.hopping, sizeof(srslte_pusch_hopping_cfg_t)); cfg->ul_cfg.hopping.n_sb = pusch_cfg_common->pusch_cfg_basic.n_sb; cfg->ul_cfg.hopping.hop_mode = pusch_cfg_common->pusch_cfg_basic.hop_mode.value == asn1::rrc::pusch_cfg_common_s::pusch_cfg_basic_s_::hop_mode_e_::intra_and_inter_sub_frame ? cfg->ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF : cfg->ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF; cfg->ul_cfg.hopping.hopping_offset = pusch_cfg_common->pusch_cfg_basic.pusch_hop_offset; cfg->ul_cfg.pusch.enable_64qam = pusch_cfg_common->pusch_cfg_basic.enable64_qam; } } if (asn1_type.rr_cfg_ded_scell_r10_present) { auto* rr_cfg_ded_scell_r10 = &asn1_type.rr_cfg_ded_scell_r10; if (rr_cfg_ded_scell_r10->phys_cfg_ded_scell_r10_present) { auto* phys_cfg_ded_scell_r10 = &rr_cfg_ded_scell_r10->phys_cfg_ded_scell_r10; // Parse nonUL Configuration if (phys_cfg_ded_scell_r10->non_ul_cfg_r10_present) { auto* non_ul_cfg = &phys_cfg_ded_scell_r10->non_ul_cfg_r10; // Parse Transmission mode if (non_ul_cfg->ant_info_r10_present) { if (non_ul_cfg->ant_info_r10.tx_mode_r10.to_number() < (uint8_t)SRSLTE_TMINV) { cfg->dl_cfg.tm = (srslte_tm_t)non_ul_cfg->ant_info_r10.tx_mode_r10.to_number(); } else { fprintf(stderr, "Transmission mode (R10) %s is not supported\n", non_ul_cfg->ant_info_r10.tx_mode_r10.to_string().c_str()); } } // Parse Cross carrier scheduling if (non_ul_cfg->cross_carrier_sched_cfg_r10_present) { typedef asn1::rrc::cross_carrier_sched_cfg_r10_s::sched_cell_info_r10_c_ sched_info_t; typedef sched_info_t::types cross_carrier_type_e; auto* sched_info = &non_ul_cfg->cross_carrier_sched_cfg_r10.sched_cell_info_r10; cross_carrier_type_e cross_carrier_type = sched_info->type(); if (cross_carrier_type == cross_carrier_type_e::own_r10) { cfg->dl_cfg.dci.cif_present = sched_info->own_r10().cif_presence_r10; } else { cfg->dl_cfg.dci.cif_present = false; // This CC does not have Carrier Indicator Field // ue_cfg->dl_cfg.blablabla = sched_info->other_r10().pdsch_start_r10; // ue_cfg->dl_cfg.blablabla = sched_info->other_r10().sched_cell_id_r10; } } // Parse pdsch config dedicated if (non_ul_cfg->pdsch_cfg_ded_r10_present) { cfg->dl_cfg.pdsch.p_b = asn1_type.rr_cfg_common_scell_r10.non_ul_cfg_r10.pdsch_cfg_common_r10.p_b; cfg->dl_cfg.pdsch.p_a = non_ul_cfg->pdsch_cfg_ded_r10.p_a.to_number(); cfg->dl_cfg.pdsch.power_scale = true; } } // Parse UL Configuration if (phys_cfg_ded_scell_r10->ul_cfg_r10_present) { auto* ul_cfg_r10 = &phys_cfg_ded_scell_r10->ul_cfg_r10; // Parse CQI param if (ul_cfg_r10->cqi_report_cfg_scell_r10_present) { auto* cqi_report_cfg = &ul_cfg_r10->cqi_report_cfg_scell_r10; // Aperiodic report if (cqi_report_cfg->cqi_report_mode_aperiodic_r10_present) { cfg->dl_cfg.cqi_report.aperiodic_configured = true; cfg->dl_cfg.cqi_report.aperiodic_mode = make_aperiodic_mode(cqi_report_cfg->cqi_report_mode_aperiodic_r10); } // Periodic report if (cqi_report_cfg->cqi_report_periodic_scell_r10_present) { if (cqi_report_cfg->cqi_report_periodic_scell_r10.type() == asn1::rrc::setup_e::setup) { typedef asn1::rrc::cqi_report_periodic_r10_c::setup_s_ cqi_cfg_t; cqi_cfg_t cqi_cfg = cqi_report_cfg->cqi_report_periodic_scell_r10.setup(); cfg->dl_cfg.cqi_report.periodic_configured = true; cfg->dl_cfg.cqi_report.pmi_idx = cqi_cfg.cqi_pmi_cfg_idx; cfg->dl_cfg.cqi_report.format_is_subband = cqi_cfg.cqi_format_ind_periodic_r10.type().value == cqi_cfg_t::cqi_format_ind_periodic_r10_c_::types::subband_cqi_r10; if (cfg->dl_cfg.cqi_report.format_is_subband) { cfg->dl_cfg.cqi_report.subband_size = cqi_cfg.cqi_format_ind_periodic_r10.subband_cqi_r10().k; } if (cqi_cfg.ri_cfg_idx_present) { cfg->dl_cfg.cqi_report.ri_idx = cqi_cfg.ri_cfg_idx; cfg->dl_cfg.cqi_report.ri_idx_present = true; } else { cfg->dl_cfg.cqi_report.ri_idx_present = false; } } else { // Release, disable periodic reporting cfg->dl_cfg.cqi_report.periodic_configured = false; } } } // Sounding reference signals Dedicated if (ul_cfg_r10->srs_ul_cfg_ded_r10_present) { cfg->ul_cfg.srs.dedicated_enabled = ul_cfg_r10->srs_ul_cfg_ded_r10.type() == asn1::rrc::setup_e::setup; if (cfg->ul_cfg.srs.dedicated_enabled) { auto* srs_ul_cfg_ded_r10 = &ul_cfg_r10->srs_ul_cfg_ded_r10.setup(); cfg->ul_cfg.srs.configured = cfg->ul_cfg.srs.dedicated_enabled and cfg->ul_cfg.srs.common_enabled; cfg->ul_cfg.srs.I_srs = srs_ul_cfg_ded_r10->srs_cfg_idx; cfg->ul_cfg.srs.B = srs_ul_cfg_ded_r10->srs_bw; cfg->ul_cfg.srs.b_hop = srs_ul_cfg_ded_r10->srs_hop_bw; cfg->ul_cfg.srs.n_rrc = srs_ul_cfg_ded_r10->freq_domain_position; cfg->ul_cfg.srs.k_tc = srs_ul_cfg_ded_r10->tx_comb; cfg->ul_cfg.srs.n_srs = srs_ul_cfg_ded_r10->cyclic_shift; } } } if (phys_cfg_ded_scell_r10->cqi_report_cfg_scell_v1250.is_present()) { // Enable/disable PDSCH 256QAM auto cqi_report_cfg_scell = phys_cfg_ded_scell_r10->cqi_report_cfg_scell_v1250.get(); cfg->dl_cfg.pdsch.use_tbs_index_alt = cqi_report_cfg_scell->alt_cqi_table_r12_present; } else { // Assume there is no PDSCH 256QAM cfg->dl_cfg.pdsch.use_tbs_index_alt = false; } } } } /* * UE Capabilities parser */ template static void set_rrc_ue_eutra_cap_t_gen(rrc_ue_capabilities_t& ue_cap, const T& ue_eutra_cap) { if (ue_eutra_cap.non_crit_ext_present) { set_rrc_ue_eutra_cap_t_gen(ue_cap, ue_eutra_cap.non_crit_ext); } } static void set_rrc_ue_eutra_cap_t_gen(rrc_ue_capabilities_t& ue_cap, const asn1::rrc::ue_eutra_cap_s& ue_eutra_cap) { ue_cap.release = ue_eutra_cap.access_stratum_release.to_number(); ue_cap.category = ue_eutra_cap.ue_category; if (ue_eutra_cap.non_crit_ext_present) { set_rrc_ue_eutra_cap_t_gen(ue_cap, ue_eutra_cap.non_crit_ext); } } static void set_rrc_ue_eutra_cap_t_gen(rrc_ue_capabilities_t& ue_cap, const asn1::rrc::ue_eutra_cap_v1020_ies_s& ue_eutra_cap) { if (ue_eutra_cap.ue_category_v1020_present) { ue_cap.category = ue_eutra_cap.ue_category_v1020; } if (ue_eutra_cap.non_crit_ext_present) { set_rrc_ue_eutra_cap_t_gen(ue_cap, ue_eutra_cap.non_crit_ext); } } static void set_rrc_ue_eutra_cap_t_gen(rrc_ue_capabilities_t& ue_cap, const asn1::rrc::ue_eutra_cap_v1250_ies_s& ue_eutra_cap) { if (ue_eutra_cap.ue_category_dl_r12_present) { ue_cap.category_dl = ue_eutra_cap.ue_category_dl_r12; } if (ue_eutra_cap.ue_category_ul_r12_present) { ue_cap.category_ul = ue_eutra_cap.ue_category_ul_r12; } if (ue_eutra_cap.rf_params_v1250_present) { const asn1::rrc::rf_params_v1250_s& rf_params = ue_eutra_cap.rf_params_v1250; if (rf_params.supported_band_list_eutra_v1250_present) { ue_cap.support_dl_256qam = true; for (const asn1::rrc::supported_band_eutra_v1250_s& supported_band : rf_params.supported_band_list_eutra_v1250) { ue_cap.support_dl_256qam &= supported_band.dl_minus256_qam_r12_present; ue_cap.support_ul_64qam &= supported_band.ul_minus64_qam_r12_present; } } } if (ue_eutra_cap.non_crit_ext_present) { set_rrc_ue_eutra_cap_t_gen(ue_cap, ue_eutra_cap.non_crit_ext); } } static void set_rrc_ue_eutra_cap_t_gen(rrc_ue_capabilities_t& ue_cap, const asn1::rrc::ue_eutra_cap_v1530_ies_s& ue_eutra_cap) { ; // Do nothing } rrc_ue_capabilities_t make_rrc_ue_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_cap_s) { rrc_ue_capabilities_t ue_cap; set_rrc_ue_eutra_cap_t_gen(ue_cap, eutra_cap_s); return ue_cap; } // MBMS mbms_notif_cfg_t make_mbms_notif_cfg(const asn1::rrc::mbms_notif_cfg_r9_s& asn1_type) { mbms_notif_cfg_t ret{}; ret.notif_repeat_coeff = (mbms_notif_cfg_t::coeff_t)asn1_type.notif_repeat_coeff_r9.value; ret.notif_offset = asn1_type.notif_offset_r9; ret.notif_sf_idx = asn1_type.notif_sf_idx_r9; return ret; } mbsfn_area_info_t make_mbsfn_area_info(const asn1::rrc::mbsfn_area_info_r9_s& asn1_type) { mbsfn_area_info_t ret{}; ret.mbsfn_area_id = asn1_type.mbsfn_area_id_r9; ret.non_mbsfn_region_len = (mbsfn_area_info_t::region_len_t)asn1_type.non_mbsfn_region_len.value; ret.notif_ind = asn1_type.notif_ind_r9; ret.mcch_cfg.mcch_repeat_period = (mbsfn_area_info_t::mcch_cfg_t::repeat_period_t)asn1_type.mcch_cfg_r9.mcch_repeat_period_r9.value; ret.mcch_cfg.mcch_offset = asn1_type.mcch_cfg_r9.mcch_offset_r9; ret.mcch_cfg.mcch_mod_period = (mbsfn_area_info_t::mcch_cfg_t::mod_period_t)asn1_type.mcch_cfg_r9.mcch_mod_period_r9.value; ret.mcch_cfg.sf_alloc_info = asn1_type.mcch_cfg_r9.sf_alloc_info_r9.to_number(); ret.mcch_cfg.sig_mcs = (mbsfn_area_info_t::mcch_cfg_t::sig_mcs_t)asn1_type.mcch_cfg_r9.sig_mcs_r9.value; return ret; } mbsfn_sf_cfg_t make_mbsfn_sf_cfg(const asn1::rrc::mbsfn_sf_cfg_s& sf_cfg) { mbsfn_sf_cfg_t cfg{}; cfg.radioframe_alloc_period = (mbsfn_sf_cfg_t::alloc_period_t)sf_cfg.radioframe_alloc_period.value; cfg.radioframe_alloc_offset = sf_cfg.radioframe_alloc_offset; cfg.nof_alloc_subfrs = (mbsfn_sf_cfg_t::sf_alloc_type_t)sf_cfg.sf_alloc.type().value; if (sf_cfg.sf_alloc.type().value == asn1::rrc::mbsfn_sf_cfg_s::sf_alloc_c_::types_opts::one_frame) { cfg.sf_alloc = sf_cfg.sf_alloc.one_frame().to_number(); } else { cfg.sf_alloc = sf_cfg.sf_alloc.four_frames().to_number(); } return cfg; } pmch_info_t make_pmch_info(const asn1::rrc::pmch_info_r9_s& asn1_type) { pmch_info_t ret{}; ret.sf_alloc_end = asn1_type.pmch_cfg_r9.sf_alloc_end_r9; ret.data_mcs = asn1_type.pmch_cfg_r9.data_mcs_r9; ret.mch_sched_period = (pmch_info_t::mch_sched_period_t)asn1_type.pmch_cfg_r9.mch_sched_period_r9.value; ret.nof_mbms_session_info = asn1_type.mbms_session_info_list_r9.size(); for (uint32_t i = 0; i < ret.nof_mbms_session_info; ++i) { auto& asn1item = asn1_type.mbms_session_info_list_r9[i]; auto& item = ret.mbms_session_info_list[i]; item.session_id_present = asn1item.session_id_r9_present; item.lc_ch_id = asn1item.lc_ch_id_r9; item.session_id = asn1item.session_id_r9[0]; item.tmgi.plmn_id_type = (tmgi_t::plmn_id_type_t)asn1item.tmgi_r9.plmn_id_r9.type().value; if (item.tmgi.plmn_id_type == tmgi_t::plmn_id_type_t::plmn_idx) { item.tmgi.plmn_id.plmn_idx = asn1item.tmgi_r9.plmn_id_r9.plmn_idx_r9(); } else { item.tmgi.plmn_id.explicit_value = make_plmn_id_t(asn1item.tmgi_r9.plmn_id_r9.explicit_value_r9()); } memcpy(item.tmgi.serviced_id, &asn1item.tmgi_r9.service_id_r9[0], 3); } return ret; } mcch_msg_t make_mcch_msg(const asn1::rrc::mcch_msg_s& asn1_type) { mcch_msg_t msg{}; auto& r9 = asn1_type.msg.c1().mbsfn_area_cfg_r9(); msg.nof_common_sf_alloc = r9.common_sf_alloc_r9.size(); for (uint32_t i = 0; i < msg.nof_common_sf_alloc; ++i) { msg.common_sf_alloc[i] = make_mbsfn_sf_cfg(r9.common_sf_alloc_r9[i]); } msg.common_sf_alloc_period = (mcch_msg_t::common_sf_alloc_period_t)r9.common_sf_alloc_period_r9.value; msg.nof_pmch_info = r9.pmch_info_list_r9.size(); for (uint32_t i = 0; i < msg.nof_pmch_info; ++i) { msg.pmch_info_list[i] = make_pmch_info(r9.pmch_info_list_r9[i]); } return msg; } static_assert(ASN1_RRC_MAX_SESSION_PER_PMCH == pmch_info_t::max_session_per_pmch, "ASN1 to srsLTE interface mismatch"); sib13_t make_sib13(const asn1::rrc::sib_type13_r9_s& asn1_type) { sib13_t sib13{}; sib13.nof_mbsfn_area_info = asn1_type.mbsfn_area_info_list_r9.size(); for (uint32_t i = 0; i < asn1_type.mbsfn_area_info_list_r9.size(); ++i) { sib13.mbsfn_area_info_list[i] = make_mbsfn_area_info(asn1_type.mbsfn_area_info_list_r9[i]); } sib13.notif_cfg = make_mbms_notif_cfg(asn1_type.notif_cfg_r9); return sib13; } } // namespace srslte namespace asn1 { namespace rrc { /*************************** * MeasConfig **************************/ bool operator==(const cells_to_add_mod_s& lhs, const cells_to_add_mod_s& rhs) { return lhs.cell_idx == rhs.cell_idx and lhs.pci == rhs.pci and lhs.cell_individual_offset == rhs.cell_individual_offset; } bool operator==(const meas_obj_to_add_mod_s& lhs, const meas_obj_to_add_mod_s& rhs) { if (lhs.meas_obj_id != rhs.meas_obj_id or lhs.meas_obj.type() != lhs.meas_obj.type()) { return false; } auto &lhs_eutra = lhs.meas_obj.meas_obj_eutra(), &rhs_eutra = rhs.meas_obj.meas_obj_eutra(); if (lhs_eutra.ext or rhs_eutra.ext) { printf("[%d] extension of measObjToAddMod not supported\n", __LINE__); return false; } if (lhs_eutra.offset_freq_present != rhs_eutra.offset_freq_present or (lhs_eutra.offset_freq_present and lhs_eutra.offset_freq != rhs_eutra.offset_freq)) { return false; } if (lhs_eutra.carrier_freq != rhs_eutra.carrier_freq or not(lhs_eutra.neigh_cell_cfg == rhs_eutra.neigh_cell_cfg) or lhs_eutra.presence_ant_port1 != rhs_eutra.presence_ant_port1 or lhs_eutra.allowed_meas_bw != rhs_eutra.allowed_meas_bw) { return false; } if (lhs_eutra.cells_to_add_mod_list.size() != rhs_eutra.cells_to_add_mod_list.size()) { return false; } auto cells_are_equal = [](const cells_to_add_mod_s& lhs, const cells_to_add_mod_s& rhs) { return lhs == rhs; }; return std::equal(lhs_eutra.cells_to_add_mod_list.begin(), lhs_eutra.cells_to_add_mod_list.end(), rhs_eutra.cells_to_add_mod_list.begin(), cells_are_equal); } bool operator==(const report_cfg_eutra_s& lhs, const report_cfg_eutra_s& rhs) { if (lhs.ext or rhs.ext) { printf("[%d] extension of reportCfgToAddMod not supported\n", __LINE__); return false; } if (lhs.trigger_type.type() != rhs.trigger_type.type()) { return false; } if (lhs.trigger_type.type().value == report_cfg_eutra_s::trigger_type_c_::types_opts::event) { auto &lhs_ev = lhs.trigger_type.event(), &rhs_ev = rhs.trigger_type.event(); if (lhs_ev.hysteresis != rhs_ev.hysteresis or lhs_ev.time_to_trigger != rhs_ev.time_to_trigger or lhs_ev.event_id.type() != rhs_ev.event_id.type()) { return false; } if (lhs_ev.event_id.type().value != eutra_event_s::event_id_c_::types_opts::event_a3) { printf("[%d] event type != A3 of reportCfgToAddMod not supported\n", __LINE__); return false; } if (lhs_ev.event_id.event_a3().report_on_leave != rhs_ev.event_id.event_a3().report_on_leave or lhs_ev.event_id.event_a3().a3_offset != rhs_ev.event_id.event_a3().a3_offset) { return false; } } else { if (lhs.trigger_type.periodical().purpose != rhs.trigger_type.periodical().purpose) { return false; } } return lhs.trigger_quant == rhs.trigger_quant and lhs.report_quant == rhs.report_quant and lhs.max_report_cells == rhs.max_report_cells and lhs.report_interv == rhs.report_interv and lhs.report_amount == rhs.report_amount; } bool operator==(const report_cfg_to_add_mod_s& lhs, const report_cfg_to_add_mod_s& rhs) { if (lhs.report_cfg_id != rhs.report_cfg_id or lhs.report_cfg.type() != rhs.report_cfg.type()) { return false; } return lhs.report_cfg.report_cfg_eutra() == rhs.report_cfg.report_cfg_eutra(); } bool operator==(const meas_id_to_add_mod_s& lhs, const meas_id_to_add_mod_s& rhs) { return lhs.meas_id == rhs.meas_id and lhs.meas_obj_id == rhs.meas_obj_id and lhs.report_cfg_id == rhs.report_cfg_id; } bool operator==(const asn1::rrc::quant_cfg_s& lhs, const asn1::rrc::quant_cfg_s& rhs) { if (lhs.ext or lhs.quant_cfg_geran_present or lhs.quant_cfg_utra_present or lhs.quant_cfg_cdma2000_present or rhs.ext or rhs.quant_cfg_geran_present or rhs.quant_cfg_utra_present or rhs.quant_cfg_cdma2000_present) { printf("[%d] quantCfg properties not supported\n", __LINE__); return false; } return lhs.quant_cfg_eutra_present == rhs.quant_cfg_eutra_present and lhs.quant_cfg_eutra.filt_coef_rsrp_present == rhs.quant_cfg_eutra.filt_coef_rsrp_present and lhs.quant_cfg_eutra.filt_coef_rsrp == rhs.quant_cfg_eutra.filt_coef_rsrp and lhs.quant_cfg_eutra.filt_coef_rsrq_present == rhs.quant_cfg_eutra.filt_coef_rsrq_present and lhs.quant_cfg_eutra.filt_coef_rsrq == rhs.quant_cfg_eutra.filt_coef_rsrq; } /*************************** * SRBs/DRBs **************************/ bool operator==(const lc_ch_cfg_s& lhs, const lc_ch_cfg_s& rhs) { if (not(lhs.ul_specific_params_present == rhs.ul_specific_params_present and lhs.ext == rhs.ext)) { return false; } if (lhs.ul_specific_params_present and not(lhs.ul_specific_params.bucket_size_dur == rhs.ul_specific_params.bucket_size_dur and lhs.ul_specific_params.prio == rhs.ul_specific_params.prio and lhs.ul_specific_params.prioritised_bit_rate == rhs.ul_specific_params.prioritised_bit_rate and lhs.ul_specific_params.lc_ch_group_present == rhs.ul_specific_params.lc_ch_group_present and (not lhs.ul_specific_params.lc_ch_group_present or lhs.ul_specific_params.lc_ch_group == rhs.ul_specific_params.lc_ch_group))) { return false; } // TODO: do remaining comparisons return true; } bool operator==(const pdcp_cfg_s& lhs, const pdcp_cfg_s& rhs) { if (lhs.discard_timer_present == rhs.discard_timer_present and lhs.discard_timer == rhs.discard_timer and lhs.ext == rhs.ext) { return false; } // TODO: do remaining comparisons return true; } bool operator==(const rlc_cfg_c& lhs, const rlc_cfg_c& rhs) { // TODO: do remaining comparisons return !(lhs.type().value != rhs.type().value); } bool operator==(const drb_to_add_mod_s& lhs, const drb_to_add_mod_s& rhs) { if (lhs.drb_id != rhs.drb_id or lhs.ext != rhs.ext) { return false; } if (lhs.eps_bearer_id_present != rhs.eps_bearer_id_present or (lhs.eps_bearer_id != rhs.eps_bearer_id)) { return false; } if (not(lhs.pdcp_cfg_present == rhs.pdcp_cfg_present and (not lhs.pdcp_cfg_present or lhs.pdcp_cfg == rhs.pdcp_cfg))) { return false; } if (not(lhs.rlc_cfg_present == rhs.rlc_cfg_present and (not lhs.rlc_cfg_present or lhs.rlc_cfg == rhs.rlc_cfg))) { return false; } if (lhs.lc_ch_id_present != rhs.lc_ch_id_present or (lhs.lc_ch_id_present and lhs.lc_ch_id != rhs.lc_ch_id)) { return false; } if (not(lhs.lc_ch_cfg_present == rhs.lc_ch_cfg_present and (not lhs.lc_ch_cfg_present or lhs.lc_ch_cfg == rhs.lc_ch_cfg))) { return false; } // TODO: compare remaining fields return true; } /*************************** * SCells **************************/ bool operator==(const scell_to_add_mod_r10_s& lhs, const scell_to_add_mod_r10_s& rhs) { return lhs.scell_idx_r10 == rhs.scell_idx_r10 and lhs.ext == rhs.ext and lhs.dl_carrier_freq_v1090_present == rhs.dl_carrier_freq_v1090_present and (not lhs.dl_carrier_freq_v1090_present or lhs.dl_carrier_freq_v1090 == rhs.dl_carrier_freq_v1090) and lhs.rr_cfg_ded_scell_r10_present == rhs.rr_cfg_ded_scell_r10_present and lhs.cell_identif_r10_present == rhs.cell_identif_r10_present and (not lhs.cell_identif_r10_present or (lhs.cell_identif_r10.dl_carrier_freq_r10 == rhs.cell_identif_r10.dl_carrier_freq_r10 and lhs.cell_identif_r10.pci_r10 == rhs.cell_identif_r10.pci_r10)); // TODO: compare remaining fields } /************************** * RRC Obj Id *************************/ uint8_t get_rrc_obj_id(const srb_to_add_mod_s& srb) { return srb.srb_id; } uint8_t get_rrc_obj_id(const drb_to_add_mod_s& drb) { return drb.drb_id; } uint8_t get_rrc_obj_id(const cells_to_add_mod_s& obj) { return obj.cell_idx; } uint8_t get_rrc_obj_id(const meas_obj_to_add_mod_s& obj) { return obj.meas_obj_id; } uint8_t get_rrc_obj_id(const report_cfg_to_add_mod_s& obj) { return obj.report_cfg_id; } uint8_t get_rrc_obj_id(const meas_id_to_add_mod_s& obj) { return obj.meas_id; } void set_rrc_obj_id(srb_to_add_mod_s& srb, uint8_t id) { srb.srb_id = id; } void set_rrc_obj_id(drb_to_add_mod_s& drb, uint8_t id) { drb.drb_id = id; } void set_rrc_obj_id(cells_to_add_mod_s& obj, uint8_t id) { obj.cell_idx = id; } void set_rrc_obj_id(meas_obj_to_add_mod_s& obj, uint8_t id) { obj.meas_obj_id = id; } void set_rrc_obj_id(report_cfg_to_add_mod_s& obj, uint8_t id) { obj.report_cfg_id = id; } void set_rrc_obj_id(meas_id_to_add_mod_s& obj, uint8_t id) { obj.meas_id = id; } } // namespace rrc } // namespace asn1