/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ #include "f1ap_positioning.h" #include "f1ap_lib_common.h" #include "f1ap_lib_includes.h" #include "f1ap_messages_types.h" #include "common/utils/assertions.h" #include "openair3/UTILS/conversions.h" #include "common/utils/oai_asn1.h" #include "common/utils/utils.h" #include "common/utils/ds/byte_array.h" static F1AP_SRSConfig_t encode_srs_config(const f1ap_srs_config_t *in_config) { F1AP_SRSConfig_t out_config = {0}; // optional: srs_resource_list if (in_config->srs_resource_list) { f1ap_srs_resource_list_t *srs_resource_list = in_config->srs_resource_list; uint32_t srs_resource_list_length = srs_resource_list->srs_resource_list_length; asn1cCalloc(out_config.sRSResource_List, f1_sRSResource_List); for (int i = 0; i < srs_resource_list_length; i++) { asn1cSequenceAdd(f1_sRSResource_List->list, F1AP_SRSResource_t, f1_srs_resource); f1ap_srs_resource_t *srs_resource = &srs_resource_list->srs_resource[i]; f1_srs_resource->sRSResourceID = srs_resource->srs_resource_id; switch (srs_resource->nr_of_srs_ports) { case F1AP_SRS_NUMBER_OF_PORTS_N1: f1_srs_resource->nrofSRS_Ports = F1AP_SRSResource__nrofSRS_Ports_port1; break; case F1AP_SRS_NUMBER_OF_PORTS_N2: f1_srs_resource->nrofSRS_Ports = F1AP_SRSResource__nrofSRS_Ports_ports2; break; case F1AP_SRS_NUMBER_OF_PORTS_N4: f1_srs_resource->nrofSRS_Ports = F1AP_SRSResource__nrofSRS_Ports_ports4; break; default: AssertFatal(false, "illegal number of srs ports %d\n", srs_resource->nr_of_srs_ports); break; } f1ap_transmission_comb_t *srs_res_tx_comb = &srs_resource->transmission_comb; switch (srs_res_tx_comb->present) { case F1AP_TRANSMISSION_COMB_PR_NOTHING: f1_srs_resource->transmissionComb.present = F1AP_TransmissionComb_PR_NOTHING; break; case F1AP_TRANSMISSION_COMB_PR_N2: f1_srs_resource->transmissionComb.present = F1AP_TransmissionComb_PR_n2; asn1cCalloc(f1_srs_resource->transmissionComb.choice.n2, f1_n2); f1_n2->combOffset_n2 = srs_res_tx_comb->choice.n2.comb_offset_n2; f1_n2->cyclicShift_n2 = srs_res_tx_comb->choice.n2.cyclic_shift_n2; break; case F1AP_TRANSMISSION_COMB_PR_N4: f1_srs_resource->transmissionComb.present = F1AP_TransmissionComb_PR_n4; asn1cCalloc(f1_srs_resource->transmissionComb.choice.n4, f1_n4); f1_n4->combOffset_n4 = srs_res_tx_comb->choice.n4.comb_offset_n4; f1_n4->cyclicShift_n4 = srs_res_tx_comb->choice.n4.cyclic_shift_n4; break; default: AssertFatal(false, "illegal transmissionComb %d\n", srs_res_tx_comb->present); break; } f1_srs_resource->startPosition = srs_resource->start_position; switch (srs_resource->nr_of_symbols) { case F1AP_SRS_NUMBER_OF_SYMBOLS_N1: f1_srs_resource->nrofSymbols = F1AP_SRSResource__nrofSymbols_n1; break; case F1AP_SRS_NUMBER_OF_SYMBOLS_N2: f1_srs_resource->nrofSymbols = F1AP_SRSResource__nrofSymbols_n2; break; case F1AP_SRS_NUMBER_OF_SYMBOLS_N4: f1_srs_resource->nrofSymbols = F1AP_SRSResource__nrofSymbols_n4; break; default: AssertFatal(false, "illegal number of symbols %d\n", srs_resource->nr_of_symbols); break; } switch (srs_resource->repetition_factor) { case F1AP_SRS_REPETITION_FACTOR_RF1: f1_srs_resource->repetitionFactor = F1AP_SRSResource__repetitionFactor_n1; break; case F1AP_SRS_REPETITION_FACTOR_RF2: f1_srs_resource->repetitionFactor = F1AP_SRSResource__repetitionFactor_n2; break; case F1AP_SRS_REPETITION_FACTOR_RF4: f1_srs_resource->repetitionFactor = F1AP_SRSResource__repetitionFactor_n4; break; default: AssertFatal(false, "illegal repetition factor %d\n", srs_resource->repetition_factor); break; } f1_srs_resource->freqDomainPosition = srs_resource->freq_domain_position; f1_srs_resource->freqDomainShift = srs_resource->freq_domain_shift; f1_srs_resource->c_SRS = srs_resource->c_srs; f1_srs_resource->b_SRS = srs_resource->b_srs; f1_srs_resource->b_hop = srs_resource->b_hop; switch (srs_resource->group_or_sequence_hopping) { case F1AP_GROUPORSEQUENCEHOPPING_NOTHING: f1_srs_resource->groupOrSequenceHopping = F1AP_SRSResource__groupOrSequenceHopping_neither; break; case F1AP_GROUPORSEQUENCEHOPPING_GROUPHOPPING: f1_srs_resource->groupOrSequenceHopping = F1AP_SRSResource__groupOrSequenceHopping_groupHopping; break; case F1AP_GROUPORSEQUENCEHOPPING_SEQUENCEHOPPING: f1_srs_resource->groupOrSequenceHopping = F1AP_SRSResource__groupOrSequenceHopping_sequenceHopping; break; default: AssertFatal(false, "illegal groupOrSequenceHopping %d\n", srs_resource->group_or_sequence_hopping); break; } F1AP_ResourceType_t *f1_resourceType = &f1_srs_resource->resourceType; f1ap_resource_type_t *resource_type = &srs_resource->resource_type; if (resource_type->present == F1AP_RESOURCE_TYPE_PR_NOTHING) { f1_resourceType->present = F1AP_ResourceType_PR_NOTHING; } else if (resource_type->present == F1AP_RESOURCE_TYPE_PR_PERIODIC) { f1_resourceType->present = F1AP_ResourceType_PR_periodic; asn1cCalloc(f1_resourceType->choice.periodic, f1_periodic); switch (resource_type->choice.periodic.periodicity) { case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot1; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot2; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT4: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot4; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT5: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot5; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT8: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot8; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT10: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot10; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT16: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot16; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT20: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot20; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT32: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot32; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT40: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot40; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT64: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot64; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT80: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot80; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT160: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot160; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT320: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot320; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT640: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot640; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1280: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot1280; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2560: f1_periodic->periodicity = F1AP_ResourceTypePeriodic__periodicity_slot2560; break; default: AssertFatal(false, "illegal periodicity %d\n", resource_type->choice.periodic.periodicity); break; } f1_periodic->offset = resource_type->choice.periodic.offset; } else if (resource_type->present == F1AP_RESOURCE_TYPE_PR_SEMI_PERSISTENT) { f1_resourceType->present = F1AP_ResourceType_PR_semi_persistent; asn1cCalloc(f1_resourceType->choice.semi_persistent, f1_semi_persistent); switch (resource_type->choice.semi_persistent.periodicity) { case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot1; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot2; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT4: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot4; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT5: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot5; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT8: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot8; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT10: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot10; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT16: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot16; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT20: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot20; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT32: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot32; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT40: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot40; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT64: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot64; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT80: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot80; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT160: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot160; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT320: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot320; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT640: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot640; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1280: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot1280; break; case F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2560: f1_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistent__periodicity_slot2560; break; default: AssertFatal(false, "illegal periodicity %d\n", resource_type->choice.semi_persistent.periodicity); break; } f1_semi_persistent->offset = resource_type->choice.semi_persistent.offset; } else if (resource_type->present == F1AP_RESOURCE_TYPE_PR_APERIODIC) { f1_resourceType->present = F1AP_ResourceType_PR_aperiodic; asn1cCalloc(f1_resourceType->choice.aperiodic, f1_aperiodic); f1_aperiodic->aperiodicResourceType = resource_type->choice.aperiodic; } else { AssertFatal(false, "illegal resourceType %d\n", resource_type->present); } f1_srs_resource->sequenceId = srs_resource->sequence_id; } } // optional: pos_srs_resource_list if (in_config->pos_srs_resource_list) { f1ap_pos_srs_resource_list_t *pos_srs_resource_list = in_config->pos_srs_resource_list; uint32_t pos_srs_resource_list_length = pos_srs_resource_list->pos_srs_resource_list_length; asn1cCalloc(out_config.posSRSResource_List, f1_posSRSResource_List); for (int i = 0; i < pos_srs_resource_list_length; i++) { asn1cSequenceAdd(f1_posSRSResource_List->list, F1AP_PosSRSResource_Item_t, f1_pos_srs_resource); f1ap_pos_srs_resource_item_t *pos_srs_resource = &pos_srs_resource_list->pos_srs_resource_item[i]; f1_pos_srs_resource->srs_PosResourceId = pos_srs_resource->srs_pos_resource_id; f1ap_transmission_comb_pos_t *pos_srs_res_tx_comb = &pos_srs_resource->transmission_comb_pos; switch (pos_srs_res_tx_comb->present) { case F1AP_TRANSMISSION_COMB_POS_PR_NOTHING: f1_pos_srs_resource->transmissionCombPos.present = F1AP_TransmissionCombPos_PR_NOTHING; break; case F1AP_TRANSMISSION_COMB_POS_PR_N2: f1_pos_srs_resource->transmissionCombPos.present = F1AP_TransmissionCombPos_PR_n2; asn1cCalloc(f1_pos_srs_resource->transmissionCombPos.choice.n2, f1_pos_srs_resource_n2); f1ap_transmission_comb_pos_n2_t *pos_srs_resource_n2 = &pos_srs_res_tx_comb->choice.n2; f1_pos_srs_resource_n2->combOffset_n2 = pos_srs_resource_n2->comb_offset_n2; f1_pos_srs_resource_n2->cyclicShift_n2 = pos_srs_resource_n2->cyclic_shift_n2; break; case F1AP_TRANSMISSION_COMB_POS_PR_N4: f1_pos_srs_resource->transmissionCombPos.present = F1AP_TransmissionCombPos_PR_n4; asn1cCalloc(f1_pos_srs_resource->transmissionCombPos.choice.n4, f1_pos_srs_resource_n4); f1ap_transmission_comb_pos_n4_t *pos_srs_resource_n4 = &pos_srs_res_tx_comb->choice.n4; f1_pos_srs_resource_n4->combOffset_n4 = pos_srs_resource_n4->comb_offset_n4; f1_pos_srs_resource_n4->cyclicShift_n4 = pos_srs_resource_n4->cyclic_shift_n4; break; case F1AP_TRANSMISSION_COMB_POS_PR_N8: f1_pos_srs_resource->transmissionCombPos.present = F1AP_TransmissionCombPos_PR_n8; asn1cCalloc(f1_pos_srs_resource->transmissionCombPos.choice.n8, f1_pos_srs_resource_n8); f1ap_transmission_comb_pos_n8_t *pos_srs_resource_n8 = &pos_srs_res_tx_comb->choice.n8; f1_pos_srs_resource_n8->combOffset_n8 = pos_srs_resource_n8->comb_offset_n8; f1_pos_srs_resource_n8->cyclicShift_n8 = pos_srs_resource_n8->cyclic_shift_n8; break; default: AssertFatal(false, "illegal transmissionComb %d\n", pos_srs_res_tx_comb->present); break; } f1_pos_srs_resource->startPosition = pos_srs_resource->start_position; switch (pos_srs_resource->nr_of_symbols) { case F1AP_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N1: f1_pos_srs_resource->nrofSymbols = F1AP_PosSRSResource_Item__nrofSymbols_n1; break; case F1AP_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N2: f1_pos_srs_resource->nrofSymbols = F1AP_PosSRSResource_Item__nrofSymbols_n2; break; case F1AP_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N4: f1_pos_srs_resource->nrofSymbols = F1AP_PosSRSResource_Item__nrofSymbols_n4; break; case F1AP_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N8: f1_pos_srs_resource->nrofSymbols = F1AP_PosSRSResource_Item__nrofSymbols_n8; break; case F1AP_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N12: f1_pos_srs_resource->nrofSymbols = F1AP_PosSRSResource_Item__nrofSymbols_n12; break; default: AssertFatal(false, "illegal number of symbols %d\n", pos_srs_resource->nr_of_symbols); break; } f1_pos_srs_resource->freqDomainShift = pos_srs_resource->freq_domain_shift; f1_pos_srs_resource->c_SRS = pos_srs_resource->c_srs; switch (pos_srs_resource->group_or_sequence_hopping) { case F1AP_GROUPORSEQUENCEHOPPING_NOTHING: f1_pos_srs_resource->groupOrSequenceHopping = F1AP_PosSRSResource_Item__groupOrSequenceHopping_neither; break; case F1AP_GROUPORSEQUENCEHOPPING_GROUPHOPPING: f1_pos_srs_resource->groupOrSequenceHopping = F1AP_PosSRSResource_Item__groupOrSequenceHopping_groupHopping; break; case F1AP_GROUPORSEQUENCEHOPPING_SEQUENCEHOPPING: f1_pos_srs_resource->groupOrSequenceHopping = F1AP_PosSRSResource_Item__groupOrSequenceHopping_sequenceHopping; break; default: AssertFatal(false, "illegal groupOrSequenceHopping %d\n", pos_srs_resource->group_or_sequence_hopping); break; } f1ap_resource_type_pos_t *resource_type_pos = &pos_srs_resource->resource_type_pos; F1AP_ResourceTypePos_t *f1_resourceTypePos = &f1_pos_srs_resource->resourceTypePos; if (resource_type_pos->present == F1AP_RESOURCE_TYPE_POS_PR_NOTHING) { f1_resourceTypePos->present = F1AP_ResourceTypePos_PR_NOTHING; } else if (resource_type_pos->present == F1AP_RESOURCE_TYPE_POS_PR_PERIODIC) { f1_resourceTypePos->present = F1AP_ResourceTypePos_PR_periodic; asn1cCalloc(f1_resourceTypePos->choice.periodic, f1_pos_periodic); switch (resource_type_pos->choice.periodic.periodicity) { case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot1; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot2; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT4: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot4; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot5; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT8: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot8; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot10; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT16: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot16; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot20; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT32: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot32; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot40; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT64: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot64; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT80: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot80; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT160: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot160; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT320: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot320; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT640: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot640; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1280: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot1280; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2560: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot2560; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5120: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot5120; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10240: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot10240; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20480: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot20480; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40960: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot40960; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT81920: f1_pos_periodic->periodicity = F1AP_ResourceTypePeriodicPos__periodicity_slot81920; break; default: AssertFatal(false, "illegal periodicity %d\n", resource_type_pos->choice.periodic.periodicity); break; } f1_pos_periodic->offset = resource_type_pos->choice.periodic.offset; } else if (resource_type_pos->present == F1AP_RESOURCE_TYPE_POS_PR_SEMI_PERSISTENT) { f1_resourceTypePos->present = F1AP_ResourceTypePos_PR_semi_persistent; asn1cCalloc(f1_resourceTypePos->choice.semi_persistent, f1_pos_semi_persistent); switch (resource_type_pos->choice.semi_persistent.periodicity) { case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot1; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot2; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT4: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot4; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot5; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT8: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot8; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot10; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT16: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot16; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot20; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT32: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot32; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot40; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT64: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot64; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT80: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot80; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT160: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot160; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT320: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot320; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT640: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot640; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1280: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot1280; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2560: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot2560; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5120: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot5120; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10240: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot10240; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20480: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot20480; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40960: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot40960; break; case F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT81920: f1_pos_semi_persistent->periodicity = F1AP_ResourceTypeSemi_persistentPos__periodicity_slot81920; break; default: AssertFatal(false, "illegal periodicity %d\n", resource_type_pos->choice.semi_persistent.periodicity); break; } f1_pos_semi_persistent->offset = resource_type_pos->choice.semi_persistent.offset; } else if (resource_type_pos->present == F1AP_RESOURCE_TYPE_POS_PR_APERIODIC) { f1_resourceTypePos->present = F1AP_ResourceTypePos_PR_aperiodic; asn1cCalloc(f1_resourceTypePos->choice.aperiodic, f1_pos_aperiodic); f1_pos_aperiodic->slotOffset = resource_type_pos->choice.aperiodic.slot_offset; } else { AssertFatal(false, "illegal resourceType %d\n", resource_type_pos->present); } f1_pos_srs_resource->sequenceId = pos_srs_resource->sequence_id; } } // optional: srs_resource_set_list if (in_config->srs_resource_set_list) { f1ap_srs_resource_set_list_t *srs_resource_set_list = in_config->srs_resource_set_list; uint32_t srs_resource_set_list_length = srs_resource_set_list->srs_resource_set_list_length; asn1cCalloc(out_config.sRSResourceSet_List, f1_sRSResourceSet_List); for (int i = 0; i < srs_resource_set_list_length; i++) { asn1cSequenceAdd(f1_sRSResourceSet_List->list, F1AP_SRSResourceSet_t, f1_srs_resource_set); f1ap_srs_resource_set_t *srs_resource_set = &srs_resource_set_list->srs_resource_set[i]; f1_srs_resource_set->sRSResourceSetID = srs_resource_set->srs_resource_set_id; uint8_t srs_resource_id_list_length = srs_resource_set->srs_resource_id_list.srs_resource_id_list_length; for (int j = 0; j < srs_resource_id_list_length; j++) { asn1cSequenceAdd(f1_srs_resource_set->sRSResourceID_List.list, F1AP_SRSResourceID_t, f1_srs_resource_id); *f1_srs_resource_id = srs_resource_set->srs_resource_id_list.srs_resource_id[j]; } F1AP_ResourceSetType_t *f1_resourceSetType = &f1_srs_resource_set->resourceSetType; f1ap_resource_set_type_t *resource_set_type = &srs_resource_set->resource_set_type; switch (resource_set_type->present) { case F1AP_RESOURCE_SET_TYPE_PR_NOTHING: f1_resourceSetType->present = F1AP_ResourceSetType_PR_NOTHING; break; case F1AP_RESOURCE_SET_TYPE_PR_PERIODIC: f1_resourceSetType->present = F1AP_ResourceSetType_PR_periodic; asn1cCalloc(f1_resourceSetType->choice.periodic, f1_periodic_set_type); f1_periodic_set_type->periodicSet = resource_set_type->choice.periodic; break; case F1AP_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT: f1_resourceSetType->present = F1AP_ResourceSetType_PR_semi_persistent; asn1cCalloc(f1_resourceSetType->choice.semi_persistent, f1_semi_persistent_set_type); f1_semi_persistent_set_type->semi_persistentSet = resource_set_type->choice.semi_persistent; break; case F1AP_RESOURCE_SET_TYPE_PR_APERIODIC: f1_resourceSetType->present = F1AP_ResourceSetType_PR_aperiodic; asn1cCalloc(f1_resourceSetType->choice.aperiodic, f1_aperiodic_set_type); f1_aperiodic_set_type->sRSResourceTrigger_List = resource_set_type->choice.aperiodic.srs_resource_trigger; f1_aperiodic_set_type->slotoffset = resource_set_type->choice.aperiodic.slot_offset; break; default: AssertFatal(false, "illegal resource set type %d\n", resource_set_type->present); break; } } } // optional: pos_srs_resource_set_list if (in_config->pos_srs_resource_set_list) { f1ap_pos_srs_resource_set_list_t *pos_srs_resource_set_list = in_config->pos_srs_resource_set_list; uint32_t pos_srs_resource_set_list_length = pos_srs_resource_set_list->pos_srs_resource_set_list_length; asn1cCalloc(out_config.posSRSResourceSet_List, f1_posSRSResourceSet_List); for (int i = 0; i < pos_srs_resource_set_list_length; i++) { asn1cSequenceAdd(f1_posSRSResourceSet_List->list, F1AP_PosSRSResourceSet_Item_t, f1_pos_srs_resource_set); f1ap_pos_srs_resource_set_item_t *pos_srs_resource_set = &pos_srs_resource_set_list->pos_srs_resource_set_item[i]; f1_pos_srs_resource_set->possrsResourceSetID = pos_srs_resource_set->pos_srs_resource_set_id; uint8_t pos_srs_resource_id_list_length = pos_srs_resource_set->pos_srs_resource_id_list.pos_srs_resource_id_list_length; for (int j = 0; j < pos_srs_resource_id_list_length; j++) { asn1cSequenceAdd(f1_pos_srs_resource_set->possRSResourceID_List.list, F1AP_SRSPosResourceID_t, f1_pos_srs_resource_id); *f1_pos_srs_resource_id = pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id[j]; } F1AP_PosResourceSetType_t *f1_posresourceSetType = &f1_pos_srs_resource_set->posresourceSetType; f1ap_pos_resource_set_type_t *pos_resource_set_type = &pos_srs_resource_set->pos_resource_set_type; switch (pos_resource_set_type->present) { case F1AP_POS_RESOURCE_SET_TYPE_PR_NOTHING: f1_posresourceSetType->present = F1AP_PosResourceSetType_PR_NOTHING; break; case F1AP_POS_RESOURCE_SET_TYPE_PR_PERIODIC: f1_posresourceSetType->present = F1AP_PosResourceSetType_PR_periodic; asn1cCalloc(f1_posresourceSetType->choice.periodic, f1_pos_periodic_set_type); f1_pos_periodic_set_type->posperiodicSet = pos_resource_set_type->choice.periodic; break; case F1AP_POS_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT: f1_posresourceSetType->present = F1AP_PosResourceSetType_PR_semi_persistent; asn1cCalloc(f1_posresourceSetType->choice.semi_persistent, f1_pos_semi_persistent_set_type); f1_pos_semi_persistent_set_type->possemi_persistentSet = pos_resource_set_type->choice.semi_persistent; break; case F1AP_POS_RESOURCE_SET_TYPE_PR_APERIODIC: f1_posresourceSetType->present = F1AP_PosResourceSetType_PR_aperiodic; asn1cCalloc(f1_posresourceSetType->choice.aperiodic, f1_pos_aperiodic_set_type); f1_pos_aperiodic_set_type->sRSResourceTrigger_List = pos_resource_set_type->choice.srs_resource; break; default: AssertFatal(false, "illegal resource set type pos %d\n", pos_resource_set_type->present); break; } } } return out_config; } static F1AP_SRSCarrier_List_Item_t encode_srs_carrier_list_item(const f1ap_srs_carrier_list_item_t *in_item) { F1AP_SRSCarrier_List_Item_t out_item = {0}; // pointA out_item.pointA = in_item->pointA; // Uplink Channel BW-PerSCS-List const f1ap_uplink_channel_bw_per_scs_list_t *uplink_channel_bw_per_scs_list = &in_item->uplink_channel_bw_per_scs_list; F1AP_UplinkChannelBW_PerSCS_List_t *f1_uplink_channel_bw_per_scs_list = &out_item.uplinkChannelBW_PerSCS_List; uint32_t scs_specific_carrier_list_length = uplink_channel_bw_per_scs_list->scs_specific_carrier_list_length; for (int i = 0; i < scs_specific_carrier_list_length; i++) { asn1cSequenceAdd(f1_uplink_channel_bw_per_scs_list->list, F1AP_SCS_SpecificCarrier_t, f1_scs_specific_carrier); f1ap_scs_specific_carrier_t *scs_specific_carrier = &uplink_channel_bw_per_scs_list->scs_specific_carrier[i]; // offset to carrier f1_scs_specific_carrier->offsetToCarrier = scs_specific_carrier->offset_to_carrier; // subcarrier spacing switch (scs_specific_carrier->subcarrier_spacing) { case F1AP_SUBCARRIER_SPACING_15KHZ: f1_scs_specific_carrier->subcarrierSpacing = F1AP_SCS_SpecificCarrier__subcarrierSpacing_kHz15; break; case F1AP_SUBCARRIER_SPACING_30KHZ: f1_scs_specific_carrier->subcarrierSpacing = F1AP_SCS_SpecificCarrier__subcarrierSpacing_kHz30; break; case F1AP_SUBCARRIER_SPACING_60KHZ: f1_scs_specific_carrier->subcarrierSpacing = F1AP_SCS_SpecificCarrier__subcarrierSpacing_kHz60; break; case F1AP_SUBCARRIER_SPACING_120KHZ: f1_scs_specific_carrier->subcarrierSpacing = F1AP_SCS_SpecificCarrier__subcarrierSpacing_kHz120; break; default: AssertFatal(false, "illegal subcarrier spacing %d\n", scs_specific_carrier->subcarrier_spacing); break; } // carrier bandwidth f1_scs_specific_carrier->carrierBandwidth = scs_specific_carrier->carrier_bandwidth; } // Active UL BWP F1AP_ActiveULBWP_t *f1_active_ul_bwp = &out_item.activeULBWP; const f1ap_active_ul_bwp_t *active_ul_bwp = &in_item->active_ul_bwp; // location and bandwidth f1_active_ul_bwp->locationAndBandwidth = active_ul_bwp->location_and_bandwidth; // subcarrier spacing switch (active_ul_bwp->subcarrier_spacing) { case F1AP_SUBCARRIER_SPACING_15KHZ: f1_active_ul_bwp->subcarrierSpacing = F1AP_ActiveULBWP__subcarrierSpacing_kHz15; break; case F1AP_SUBCARRIER_SPACING_30KHZ: f1_active_ul_bwp->subcarrierSpacing = F1AP_ActiveULBWP__subcarrierSpacing_kHz30; break; case F1AP_SUBCARRIER_SPACING_60KHZ: f1_active_ul_bwp->subcarrierSpacing = F1AP_ActiveULBWP__subcarrierSpacing_kHz60; break; case F1AP_SUBCARRIER_SPACING_120KHZ: f1_active_ul_bwp->subcarrierSpacing = F1AP_ActiveULBWP__subcarrierSpacing_kHz120; break; default: AssertFatal(false, "illegal subcarrier spacing %d\n", active_ul_bwp->subcarrier_spacing); break; } // cyclic prefix if (active_ul_bwp->cyclic_prefix == F1AP_CP_TYPE_NORMAL) f1_active_ul_bwp->cyclicPrefix = F1AP_ActiveULBWP__cyclicPrefix_normal; else f1_active_ul_bwp->cyclicPrefix = F1AP_ActiveULBWP__cyclicPrefix_extended; // Tx Direct Current Location f1_active_ul_bwp->txDirectCurrentLocation = active_ul_bwp->tx_direct_current_location; // SRS Config const f1ap_srs_config_t *sRSConfig = &active_ul_bwp->srs_config; f1_active_ul_bwp->sRSConfig = encode_srs_config(sRSConfig); return out_item; } static F1AP_SRSCarrier_List_t encode_srs_carrier_list(const f1ap_srs_carrier_list_t *in_list) { F1AP_SRSCarrier_List_t out_list = {0}; uint32_t list_len = in_list->srs_carrier_list_length; for (int i = 0; i < list_len; i++) { asn1cSequenceAdd(out_list.list, F1AP_SRSCarrier_List_Item_t, out_item); f1ap_srs_carrier_list_item_t *in_item = &in_list->srs_carrier_list_item[i]; *out_item = encode_srs_carrier_list_item(in_item); } return out_list; } static void decode_srs_config(const F1AP_SRSConfig_t *in_config, f1ap_srs_config_t *out_config) { // optional: sRSResource_List if (in_config->sRSResource_List) { out_config->srs_resource_list = calloc_or_fail(1, sizeof(*out_config->srs_resource_list)); f1ap_srs_resource_list_t *srs_resource_list = out_config->srs_resource_list; uint32_t srs_resource_list_length = in_config->sRSResource_List->list.count; srs_resource_list->srs_resource_list_length = srs_resource_list_length; srs_resource_list->srs_resource = calloc_or_fail(srs_resource_list_length, sizeof(*srs_resource_list->srs_resource)); for (int i = 0; i < srs_resource_list_length; i++) { f1ap_srs_resource_t *srs_resource = &srs_resource_list->srs_resource[i]; F1AP_SRSResource_t *f1_srs_resource = in_config->sRSResource_List->list.array[i]; srs_resource->srs_resource_id = f1_srs_resource->sRSResourceID; switch (f1_srs_resource->nrofSRS_Ports) { case F1AP_SRSResource__nrofSRS_Ports_port1: srs_resource->nr_of_srs_ports = F1AP_SRS_NUMBER_OF_PORTS_N1; break; case F1AP_SRSResource__nrofSRS_Ports_ports2: srs_resource->nr_of_srs_ports = F1AP_SRS_NUMBER_OF_PORTS_N2; break; case F1AP_SRSResource__nrofSRS_Ports_ports4: srs_resource->nr_of_srs_ports = F1AP_SRS_NUMBER_OF_PORTS_N4; break; default: AssertFatal(false, "illegal number of srs ports %ld\n", f1_srs_resource->nrofSRS_Ports); break; } f1ap_transmission_comb_t *srs_tx_comb = &srs_resource->transmission_comb; F1AP_TransmissionComb_t *f1_srs_tx_comb = &f1_srs_resource->transmissionComb; switch (f1_srs_tx_comb->present) { case F1AP_TransmissionComb_PR_NOTHING: srs_tx_comb->present = F1AP_TRANSMISSION_COMB_PR_NOTHING; break; case F1AP_TransmissionComb_PR_n2: srs_tx_comb->present = F1AP_TRANSMISSION_COMB_PR_N2; srs_tx_comb->choice.n2.comb_offset_n2 = f1_srs_tx_comb->choice.n2->combOffset_n2; srs_tx_comb->choice.n2.cyclic_shift_n2 = f1_srs_tx_comb->choice.n2->cyclicShift_n2; break; case F1AP_TransmissionComb_PR_n4: srs_tx_comb->present = F1AP_TRANSMISSION_COMB_PR_N4; srs_tx_comb->choice.n4.comb_offset_n4 = f1_srs_tx_comb->choice.n4->combOffset_n4; srs_tx_comb->choice.n4.cyclic_shift_n4 = f1_srs_tx_comb->choice.n4->cyclicShift_n4; break; default: AssertFatal(false, "illegal transmissionComb %d\n", f1_srs_tx_comb->present); break; } srs_resource->start_position = f1_srs_resource->startPosition; switch (f1_srs_resource->nrofSymbols) { case F1AP_SRSResource__nrofSymbols_n1: srs_resource->nr_of_symbols = F1AP_SRS_NUMBER_OF_SYMBOLS_N1; break; case F1AP_SRSResource__nrofSymbols_n2: srs_resource->nr_of_symbols = F1AP_SRS_NUMBER_OF_SYMBOLS_N2; break; case F1AP_SRSResource__nrofSymbols_n4: srs_resource->nr_of_symbols = F1AP_SRS_NUMBER_OF_SYMBOLS_N4; break; default: AssertFatal(false, "illegal number of symbols %ld\n", f1_srs_resource->nrofSymbols); break; } switch (f1_srs_resource->repetitionFactor) { case F1AP_SRSResource__repetitionFactor_n1: srs_resource->repetition_factor = F1AP_SRS_REPETITION_FACTOR_RF1; break; case F1AP_SRSResource__repetitionFactor_n2: srs_resource->repetition_factor = F1AP_SRS_REPETITION_FACTOR_RF2; break; case F1AP_SRSResource__repetitionFactor_n4: srs_resource->repetition_factor = F1AP_SRS_REPETITION_FACTOR_RF4; break; default: AssertFatal(false, "illegal repetition factor %ld\n", f1_srs_resource->repetitionFactor); break; } srs_resource->freq_domain_position = f1_srs_resource->freqDomainPosition; srs_resource->freq_domain_shift = f1_srs_resource->freqDomainShift; srs_resource->c_srs = f1_srs_resource->c_SRS; srs_resource->b_srs = f1_srs_resource->b_SRS; srs_resource->b_hop = f1_srs_resource->b_hop; switch (f1_srs_resource->groupOrSequenceHopping) { case F1AP_SRSResource__groupOrSequenceHopping_neither: srs_resource->group_or_sequence_hopping = F1AP_GROUPORSEQUENCEHOPPING_NOTHING; break; case F1AP_SRSResource__groupOrSequenceHopping_groupHopping: srs_resource->group_or_sequence_hopping = F1AP_GROUPORSEQUENCEHOPPING_GROUPHOPPING; break; case F1AP_SRSResource__groupOrSequenceHopping_sequenceHopping: srs_resource->group_or_sequence_hopping = F1AP_GROUPORSEQUENCEHOPPING_SEQUENCEHOPPING; break; default: AssertFatal(false, "illegal groupOrSequenceHopping %ld\n", f1_srs_resource->groupOrSequenceHopping); break; } F1AP_ResourceType_t *f1_resourceType = &f1_srs_resource->resourceType; f1ap_resource_type_t *resource_type = &srs_resource->resource_type; if (f1_resourceType->present == F1AP_ResourceType_PR_NOTHING) { resource_type->present = F1AP_RESOURCE_TYPE_PR_NOTHING; } else if (f1_resourceType->present == F1AP_ResourceType_PR_periodic) { resource_type->present = F1AP_RESOURCE_TYPE_PR_PERIODIC; f1ap_resource_type_periodic_t *periodic = &resource_type->choice.periodic; switch (f1_resourceType->choice.periodic->periodicity) { case F1AP_ResourceTypePeriodic__periodicity_slot1: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1; break; case F1AP_ResourceTypePeriodic__periodicity_slot2: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2; break; case F1AP_ResourceTypePeriodic__periodicity_slot4: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT4; break; case F1AP_ResourceTypePeriodic__periodicity_slot5: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT5; break; case F1AP_ResourceTypePeriodic__periodicity_slot8: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT8; break; case F1AP_ResourceTypePeriodic__periodicity_slot10: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT10; break; case F1AP_ResourceTypePeriodic__periodicity_slot16: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT16; break; case F1AP_ResourceTypePeriodic__periodicity_slot20: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT20; break; case F1AP_ResourceTypePeriodic__periodicity_slot32: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT32; break; case F1AP_ResourceTypePeriodic__periodicity_slot40: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT40; break; case F1AP_ResourceTypePeriodic__periodicity_slot64: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT64; break; case F1AP_ResourceTypePeriodic__periodicity_slot80: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT80; break; case F1AP_ResourceTypePeriodic__periodicity_slot160: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT160; break; case F1AP_ResourceTypePeriodic__periodicity_slot320: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT320; break; case F1AP_ResourceTypePeriodic__periodicity_slot640: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT640; break; case F1AP_ResourceTypePeriodic__periodicity_slot1280: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1280; break; case F1AP_ResourceTypePeriodic__periodicity_slot2560: periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2560; break; default: AssertFatal(false, "illegal periodicity %ld\n", f1_resourceType->choice.periodic->periodicity); break; } periodic->offset = f1_resourceType->choice.periodic->offset; } else if (f1_resourceType->present == F1AP_ResourceType_PR_semi_persistent) { resource_type->present = F1AP_RESOURCE_TYPE_PR_SEMI_PERSISTENT; f1ap_resource_type_semi_persistent_t *semi_persistent = &resource_type->choice.semi_persistent; switch (f1_resourceType->choice.semi_persistent->periodicity) { case F1AP_ResourceTypeSemi_persistent__periodicity_slot1: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot2: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot4: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT4; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot5: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT5; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot8: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT8; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot10: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT10; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot16: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT16; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot20: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT20; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot32: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT32; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot40: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT40; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot64: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT64; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot80: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT80; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot160: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT160; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot320: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT320; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot640: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT640; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot1280: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1280; break; case F1AP_ResourceTypeSemi_persistent__periodicity_slot2560: semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2560; break; default: AssertFatal(false, "illegal periodicity %ld\n", f1_resourceType->choice.semi_persistent->periodicity); break; } semi_persistent->offset = f1_resourceType->choice.semi_persistent->offset; } else if (f1_resourceType->present == F1AP_ResourceType_PR_aperiodic) { resource_type->present = F1AP_RESOURCE_TYPE_PR_APERIODIC; resource_type->choice.aperiodic = f1_resourceType->choice.aperiodic->aperiodicResourceType; } else { AssertFatal(false, "illegal resourceType %d\n", f1_resourceType->present); } srs_resource->sequence_id = f1_srs_resource->sequenceId; } } // optional: posSRSResource_List if (in_config->posSRSResource_List) { out_config->pos_srs_resource_list = calloc_or_fail(1, sizeof(*out_config->pos_srs_resource_list)); f1ap_pos_srs_resource_list_t *pos_srs_resource_list = out_config->pos_srs_resource_list; uint32_t pos_srs_resource_list_length = in_config->posSRSResource_List->list.count; pos_srs_resource_list->pos_srs_resource_list_length = pos_srs_resource_list_length; pos_srs_resource_list->pos_srs_resource_item = calloc_or_fail(pos_srs_resource_list_length, sizeof(*pos_srs_resource_list->pos_srs_resource_item)); for (int i = 0; i < pos_srs_resource_list_length; i++) { F1AP_PosSRSResource_Item_t *f1_pos_srs_resource = in_config->posSRSResource_List->list.array[i]; f1ap_pos_srs_resource_item_t *pos_srs_resource = &pos_srs_resource_list->pos_srs_resource_item[i]; pos_srs_resource->srs_pos_resource_id = f1_pos_srs_resource->srs_PosResourceId; F1AP_TransmissionCombPos_t *f1_tx_comb_pos = &f1_pos_srs_resource->transmissionCombPos; f1ap_transmission_comb_pos_t *tx_comb_pos = &pos_srs_resource->transmission_comb_pos; switch (f1_tx_comb_pos->present) { case F1AP_TransmissionCombPos_PR_NOTHING: tx_comb_pos->present = F1AP_TRANSMISSION_COMB_POS_PR_NOTHING; break; case F1AP_TransmissionCombPos_PR_n2: tx_comb_pos->present = F1AP_TRANSMISSION_COMB_POS_PR_N2; tx_comb_pos->choice.n2.comb_offset_n2 = f1_tx_comb_pos->choice.n2->combOffset_n2; tx_comb_pos->choice.n2.cyclic_shift_n2 = f1_tx_comb_pos->choice.n2->cyclicShift_n2; break; case F1AP_TransmissionCombPos_PR_n4: tx_comb_pos->present = F1AP_TRANSMISSION_COMB_POS_PR_N4; tx_comb_pos->choice.n4.comb_offset_n4 = f1_tx_comb_pos->choice.n4->combOffset_n4; tx_comb_pos->choice.n4.cyclic_shift_n4 = f1_tx_comb_pos->choice.n4->cyclicShift_n4; break; case F1AP_TransmissionCombPos_PR_n8: tx_comb_pos->present = F1AP_TRANSMISSION_COMB_POS_PR_N8; tx_comb_pos->choice.n8.comb_offset_n8 = f1_tx_comb_pos->choice.n8->combOffset_n8; tx_comb_pos->choice.n8.cyclic_shift_n8 = f1_tx_comb_pos->choice.n8->cyclicShift_n8; break; default: AssertFatal(false, "illegal transmissionComb %d\n", f1_tx_comb_pos->present); break; } pos_srs_resource->start_position = f1_pos_srs_resource->startPosition; switch (f1_pos_srs_resource->nrofSymbols) { case F1AP_PosSRSResource_Item__nrofSymbols_n1: pos_srs_resource->nr_of_symbols = F1AP_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N1; break; case F1AP_PosSRSResource_Item__nrofSymbols_n2: pos_srs_resource->nr_of_symbols = F1AP_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N2; break; case F1AP_PosSRSResource_Item__nrofSymbols_n4: pos_srs_resource->nr_of_symbols = F1AP_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N4; break; case F1AP_PosSRSResource_Item__nrofSymbols_n8: pos_srs_resource->nr_of_symbols = F1AP_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N8; break; case F1AP_PosSRSResource_Item__nrofSymbols_n12: pos_srs_resource->nr_of_symbols = F1AP_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N12; break; default: AssertFatal(false, "illegal number of symbols %ld\n", f1_pos_srs_resource->nrofSymbols); break; } pos_srs_resource->freq_domain_shift = f1_pos_srs_resource->freqDomainShift; pos_srs_resource->c_srs = f1_pos_srs_resource->c_SRS; switch (f1_pos_srs_resource->groupOrSequenceHopping) { case F1AP_PosSRSResource_Item__groupOrSequenceHopping_neither: pos_srs_resource->group_or_sequence_hopping = F1AP_GROUPORSEQUENCEHOPPING_NOTHING; break; case F1AP_PosSRSResource_Item__groupOrSequenceHopping_groupHopping: pos_srs_resource->group_or_sequence_hopping = F1AP_GROUPORSEQUENCEHOPPING_GROUPHOPPING; break; case F1AP_PosSRSResource_Item__groupOrSequenceHopping_sequenceHopping: pos_srs_resource->group_or_sequence_hopping = F1AP_GROUPORSEQUENCEHOPPING_SEQUENCEHOPPING; break; default: AssertFatal(false, "illegal groupOrSequenceHopping %ld\n", f1_pos_srs_resource->groupOrSequenceHopping); break; } F1AP_ResourceTypePos_t *f1_res_type_pos = &f1_pos_srs_resource->resourceTypePos; f1ap_resource_type_pos_t *res_type_pos = &pos_srs_resource->resource_type_pos; if (f1_res_type_pos->present == F1AP_ResourceTypePos_PR_NOTHING) { res_type_pos->present = F1AP_RESOURCE_TYPE_POS_PR_NOTHING; } else if (f1_res_type_pos->present == F1AP_ResourceTypePos_PR_periodic) { res_type_pos->present = F1AP_RESOURCE_TYPE_POS_PR_PERIODIC; f1ap_resource_type_periodic_pos_t *pos_periodic = &res_type_pos->choice.periodic; switch (f1_res_type_pos->choice.periodic->periodicity) { case F1AP_ResourceTypePeriodicPos__periodicity_slot1: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot2: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot4: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT4; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot5: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot8: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT8; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot10: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot16: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT16; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot20: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot32: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT32; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot40: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot64: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT64; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot80: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT80; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot160: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT160; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot320: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT320; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot640: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT640; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot1280: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1280; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot2560: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2560; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot5120: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5120; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot10240: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10240; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot20480: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20480; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot40960: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40960; break; case F1AP_ResourceTypePeriodicPos__periodicity_slot81920: pos_periodic->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT81920; break; default: AssertFatal(false, "illegal periodicity %ld\n", f1_res_type_pos->choice.periodic->periodicity); break; } pos_periodic->offset = f1_res_type_pos->choice.periodic->offset; } else if (f1_res_type_pos->present == F1AP_ResourceTypePos_PR_semi_persistent) { res_type_pos->present = F1AP_RESOURCE_TYPE_POS_PR_SEMI_PERSISTENT; f1ap_resource_type_semi_persistent_pos_t *pos_semi_persistent = &res_type_pos->choice.semi_persistent; switch (f1_res_type_pos->choice.semi_persistent->periodicity) { case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot1: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot2: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot4: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT4; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot5: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot8: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT8; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot10: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot16: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT16; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot20: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot32: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT32; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot40: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot64: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT64; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot80: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT80; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot160: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT160; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot320: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT320; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot640: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT640; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot1280: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1280; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot2560: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2560; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot5120: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5120; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot10240: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10240; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot20480: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20480; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot40960: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40960; break; case F1AP_ResourceTypeSemi_persistentPos__periodicity_slot81920: pos_semi_persistent->periodicity = F1AP_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT81920; break; default: AssertFatal(false, "illegal periodicity %ld\n", f1_res_type_pos->choice.semi_persistent->periodicity); break; } pos_semi_persistent->offset = f1_res_type_pos->choice.semi_persistent->offset; } else if (f1_res_type_pos->present == F1AP_ResourceTypePos_PR_aperiodic) { res_type_pos->present = F1AP_RESOURCE_TYPE_POS_PR_APERIODIC; res_type_pos->choice.aperiodic.slot_offset = f1_res_type_pos->choice.aperiodic->slotOffset; } else { AssertFatal(false, "illegal resourceType %d\n", f1_res_type_pos->present); } pos_srs_resource->sequence_id = f1_pos_srs_resource->sequenceId; } } // optional: sRSResourceSet_List if (in_config->sRSResourceSet_List) { out_config->srs_resource_set_list = calloc_or_fail(1, sizeof(*out_config->srs_resource_set_list)); f1ap_srs_resource_set_list_t *srs_resource_set_list = out_config->srs_resource_set_list; uint32_t srs_resource_set_list_length = in_config->sRSResourceSet_List->list.count; srs_resource_set_list->srs_resource_set_list_length = srs_resource_set_list_length; srs_resource_set_list->srs_resource_set = calloc_or_fail(srs_resource_set_list_length, sizeof(*srs_resource_set_list->srs_resource_set)); for (int i = 0; i < srs_resource_set_list_length; i++) { F1AP_SRSResourceSet_t *f1_srs_resource_set = in_config->sRSResourceSet_List->list.array[i]; f1ap_srs_resource_set_t *srs_resource_set = &srs_resource_set_list->srs_resource_set[i]; srs_resource_set->srs_resource_set_id = f1_srs_resource_set->sRSResourceSetID; uint8_t srs_resource_id_list_length = f1_srs_resource_set->sRSResourceID_List.list.count; srs_resource_set->srs_resource_id_list.srs_resource_id_list_length = srs_resource_id_list_length; srs_resource_set->srs_resource_id_list.srs_resource_id = calloc_or_fail(srs_resource_id_list_length, sizeof(*srs_resource_set->srs_resource_id_list.srs_resource_id)); for (int j = 0; j < srs_resource_id_list_length; j++) { F1AP_SRSResourceID_t *f1_srs_resource_id = f1_srs_resource_set->sRSResourceID_List.list.array[j]; srs_resource_set->srs_resource_id_list.srs_resource_id[j] = *f1_srs_resource_id; } F1AP_ResourceSetType_t *f1_res_set_type = &f1_srs_resource_set->resourceSetType; f1ap_resource_set_type_t *res_set_type = &srs_resource_set->resource_set_type; switch (f1_res_set_type->present) { case F1AP_ResourceSetType_PR_NOTHING: res_set_type->present = F1AP_RESOURCE_SET_TYPE_PR_NOTHING; break; case F1AP_ResourceSetType_PR_periodic: res_set_type->present = F1AP_RESOURCE_SET_TYPE_PR_PERIODIC; res_set_type->choice.periodic = f1_res_set_type->choice.periodic->periodicSet; break; case F1AP_ResourceSetType_PR_semi_persistent: res_set_type->present = F1AP_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT; res_set_type->choice.semi_persistent = f1_res_set_type->choice.semi_persistent->semi_persistentSet; break; case F1AP_ResourceSetType_PR_aperiodic: res_set_type->present = F1AP_RESOURCE_SET_TYPE_PR_APERIODIC; res_set_type->choice.aperiodic.srs_resource_trigger = f1_res_set_type->choice.aperiodic->sRSResourceTrigger_List; res_set_type->choice.aperiodic.slot_offset = f1_res_set_type->choice.aperiodic->slotoffset; break; default: AssertFatal(false, "illegal resource set type %d\n", f1_res_set_type->present); break; } } } // optional: posSRSResourceSet_List if (in_config->posSRSResourceSet_List) { out_config->pos_srs_resource_set_list = calloc_or_fail(1, sizeof(*out_config->pos_srs_resource_set_list)); f1ap_pos_srs_resource_set_list_t *pos_srs_resource_set_list = out_config->pos_srs_resource_set_list; uint32_t pos_srs_resource_set_list_length = in_config->posSRSResourceSet_List->list.count; pos_srs_resource_set_list->pos_srs_resource_set_list_length = pos_srs_resource_set_list_length; pos_srs_resource_set_list->pos_srs_resource_set_item = calloc_or_fail(pos_srs_resource_set_list_length, sizeof(*pos_srs_resource_set_list->pos_srs_resource_set_item)); for (int i = 0; i < pos_srs_resource_set_list_length; i++) { F1AP_PosSRSResourceSet_Item_t *f1_pos_srs_resource_set = in_config->posSRSResourceSet_List->list.array[i]; f1ap_pos_srs_resource_set_item_t *pos_srs_resource_set = &pos_srs_resource_set_list->pos_srs_resource_set_item[i]; pos_srs_resource_set->pos_srs_resource_set_id = f1_pos_srs_resource_set->possrsResourceSetID; uint8_t pos_srs_resource_id_list_length = f1_pos_srs_resource_set->possRSResourceID_List.list.count; pos_srs_resource_set->pos_srs_resource_id_list.pos_srs_resource_id_list_length = pos_srs_resource_id_list_length; pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id = calloc_or_fail(pos_srs_resource_id_list_length, sizeof(*pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id)); for (int j = 0; j < pos_srs_resource_id_list_length; j++) { F1AP_SRSPosResourceID_t *f1_pos_srs_resource_id = f1_pos_srs_resource_set->possRSResourceID_List.list.array[j]; pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id[j] = *f1_pos_srs_resource_id; } F1AP_PosResourceSetType_t *f1_pos_res_set_type = &f1_pos_srs_resource_set->posresourceSetType; f1ap_pos_resource_set_type_t *pos_res_set_type = &pos_srs_resource_set->pos_resource_set_type; switch (f1_pos_res_set_type->present) { case F1AP_PosResourceSetType_PR_NOTHING: pos_res_set_type->present = F1AP_POS_RESOURCE_SET_TYPE_PR_NOTHING; break; case F1AP_PosResourceSetType_PR_periodic: pos_res_set_type->present = F1AP_POS_RESOURCE_SET_TYPE_PR_PERIODIC; pos_res_set_type->choice.periodic = f1_pos_res_set_type->choice.periodic->posperiodicSet; break; case F1AP_PosResourceSetType_PR_semi_persistent: pos_res_set_type->present = F1AP_POS_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT; pos_res_set_type->choice.semi_persistent = f1_pos_res_set_type->choice.semi_persistent->possemi_persistentSet; break; case F1AP_PosResourceSetType_PR_aperiodic: pos_res_set_type->present = F1AP_POS_RESOURCE_SET_TYPE_PR_APERIODIC; pos_res_set_type->choice.srs_resource = f1_pos_res_set_type->choice.aperiodic->sRSResourceTrigger_List; break; default: AssertFatal(false, "illegal resource set type pos %d\n", f1_pos_res_set_type->present); break; } } } } static void decode_srs_carrier_list_item(const F1AP_SRSCarrier_List_Item_t *in_item, f1ap_srs_carrier_list_item_t *out_item) { // pointA out_item->pointA = in_item->pointA; // Uplink Channel BW-PerSCS-List f1ap_uplink_channel_bw_per_scs_list_t *uplink_channel_bw_per_scs_list = &out_item->uplink_channel_bw_per_scs_list; const F1AP_UplinkChannelBW_PerSCS_List_t *f1_uplink_channel_bw_per_scs_list = &in_item->uplinkChannelBW_PerSCS_List; uint32_t scs_specific_carrier_list_length = f1_uplink_channel_bw_per_scs_list->list.count; AssertFatal(scs_specific_carrier_list_length > 0, "Atleast 1 uplink channel bw per scs list should be present\n"); uplink_channel_bw_per_scs_list->scs_specific_carrier_list_length = scs_specific_carrier_list_length; uplink_channel_bw_per_scs_list->scs_specific_carrier = calloc_or_fail(scs_specific_carrier_list_length, sizeof(*uplink_channel_bw_per_scs_list->scs_specific_carrier)); for (int i = 0; i < scs_specific_carrier_list_length; i++) { F1AP_SCS_SpecificCarrier_t *f1_scs_specific_carrier = f1_uplink_channel_bw_per_scs_list->list.array[i]; f1ap_scs_specific_carrier_t *scs_specific_carrier = &uplink_channel_bw_per_scs_list->scs_specific_carrier[i]; // offset to carrier scs_specific_carrier->offset_to_carrier = f1_scs_specific_carrier->offsetToCarrier; // subcarrier spacing switch (f1_scs_specific_carrier->subcarrierSpacing) { case F1AP_SCS_SpecificCarrier__subcarrierSpacing_kHz15: scs_specific_carrier->subcarrier_spacing = F1AP_SUBCARRIER_SPACING_15KHZ; break; case F1AP_SCS_SpecificCarrier__subcarrierSpacing_kHz30: scs_specific_carrier->subcarrier_spacing = F1AP_SUBCARRIER_SPACING_30KHZ; break; case F1AP_SCS_SpecificCarrier__subcarrierSpacing_kHz60: scs_specific_carrier->subcarrier_spacing = F1AP_SUBCARRIER_SPACING_60KHZ; break; case F1AP_SCS_SpecificCarrier__subcarrierSpacing_kHz120: scs_specific_carrier->subcarrier_spacing = F1AP_SUBCARRIER_SPACING_120KHZ; break; default: AssertFatal(false, "illegal subcarrier spacing %ld\n", f1_scs_specific_carrier->subcarrierSpacing); break; } // carrier bandwidth scs_specific_carrier->carrier_bandwidth = f1_scs_specific_carrier->carrierBandwidth; } // Active UL BWP const F1AP_ActiveULBWP_t *f1_active_ul_bwp = &in_item->activeULBWP; f1ap_active_ul_bwp_t *active_ul_bwp = &out_item->active_ul_bwp; // location and bandwidth active_ul_bwp->location_and_bandwidth = f1_active_ul_bwp->locationAndBandwidth; // subcarrier spacing switch (f1_active_ul_bwp->subcarrierSpacing) { case F1AP_ActiveULBWP__subcarrierSpacing_kHz15: active_ul_bwp->subcarrier_spacing = F1AP_SUBCARRIER_SPACING_15KHZ; break; case F1AP_ActiveULBWP__subcarrierSpacing_kHz30: active_ul_bwp->subcarrier_spacing = F1AP_SUBCARRIER_SPACING_30KHZ; break; case F1AP_ActiveULBWP__subcarrierSpacing_kHz60: active_ul_bwp->subcarrier_spacing = F1AP_SUBCARRIER_SPACING_60KHZ; break; case F1AP_ActiveULBWP__subcarrierSpacing_kHz120: active_ul_bwp->subcarrier_spacing = F1AP_SUBCARRIER_SPACING_120KHZ; break; default: AssertFatal(false, "illegal subcarrier spacing %ld\n", f1_active_ul_bwp->subcarrierSpacing); break; } // cyclic prefix if (f1_active_ul_bwp->cyclicPrefix == F1AP_ActiveULBWP__cyclicPrefix_normal) active_ul_bwp->cyclic_prefix = F1AP_CP_TYPE_NORMAL; else active_ul_bwp->cyclic_prefix = F1AP_CP_TYPE_EXTENDED; // Tx Direct Current Location active_ul_bwp->tx_direct_current_location = f1_active_ul_bwp->txDirectCurrentLocation; // SRS Config const F1AP_SRSConfig_t *f1_sRSConfig = &f1_active_ul_bwp->sRSConfig; f1ap_srs_config_t *sRSConfig = &active_ul_bwp->srs_config; decode_srs_config(f1_sRSConfig, sRSConfig); } static void decode_srs_carrier_list(f1ap_srs_carrier_list_t *out_list, const F1AP_SRSCarrier_List_t *in_list) { uint32_t list_len = in_list->list.count; AssertFatal(list_len > 0, "atleast 1 SRS carrier list must be present"); out_list->srs_carrier_list_length = list_len; out_list->srs_carrier_list_item = calloc_or_fail(list_len, sizeof(*out_list->srs_carrier_list_item)); for (int i = 0; i < list_len; i++) { F1AP_SRSCarrier_List_Item_t *in_item = in_list->list.array[i]; f1ap_srs_carrier_list_item_t *out_item = &out_list->srs_carrier_list_item[i]; decode_srs_carrier_list_item(in_item, out_item); } } static f1ap_srs_config_t cp_srs_config(const f1ap_srs_config_t *in_config) { f1ap_srs_config_t out_config = {0}; // optional: srs_resource_list if (in_config->srs_resource_list) { f1ap_srs_resource_list_t *srs_resource_list = in_config->srs_resource_list; out_config.srs_resource_list = calloc_or_fail(1, sizeof(*out_config.srs_resource_list)); f1ap_srs_resource_list_t *f1_srs_resource_list = out_config.srs_resource_list; uint32_t srs_resource_list_length = srs_resource_list->srs_resource_list_length; f1_srs_resource_list->srs_resource_list_length = srs_resource_list_length; f1_srs_resource_list->srs_resource = calloc_or_fail(srs_resource_list_length, sizeof(*f1_srs_resource_list->srs_resource)); for (int i = 0; i < srs_resource_list_length; i++) { f1ap_srs_resource_t *srs_resource = &srs_resource_list->srs_resource[i]; f1ap_srs_resource_t *f1_srs_resource = &f1_srs_resource_list->srs_resource[i]; f1_srs_resource->srs_resource_id = srs_resource->srs_resource_id; f1_srs_resource->nr_of_srs_ports = srs_resource->nr_of_srs_ports; f1ap_transmission_comb_t *f1_srs_tx_comb = &f1_srs_resource->transmission_comb; f1ap_transmission_comb_t *srs_tx_comb = &srs_resource->transmission_comb; f1_srs_tx_comb->present = srs_tx_comb->present; switch (srs_tx_comb->present) { case F1AP_TRANSMISSION_COMB_PR_NOTHING: // nothing to copy break; case F1AP_TRANSMISSION_COMB_PR_N2: f1_srs_tx_comb->choice.n2.comb_offset_n2 = srs_tx_comb->choice.n2.comb_offset_n2; f1_srs_tx_comb->choice.n2.cyclic_shift_n2 = srs_tx_comb->choice.n2.cyclic_shift_n2; break; case F1AP_TRANSMISSION_COMB_PR_N4: f1_srs_tx_comb->choice.n4.comb_offset_n4 = srs_tx_comb->choice.n4.comb_offset_n4; f1_srs_tx_comb->choice.n4.cyclic_shift_n4 = srs_tx_comb->choice.n4.cyclic_shift_n4; break; default: AssertFatal(false, "illegal transmissionComb %d\n", srs_tx_comb->present); break; } f1_srs_resource->start_position = srs_resource->start_position; f1_srs_resource->nr_of_symbols = srs_resource->nr_of_symbols; f1_srs_resource->repetition_factor = srs_resource->repetition_factor; f1_srs_resource->freq_domain_position = srs_resource->freq_domain_position; f1_srs_resource->freq_domain_shift = srs_resource->freq_domain_shift; f1_srs_resource->c_srs = srs_resource->c_srs; f1_srs_resource->b_srs = srs_resource->b_srs; f1_srs_resource->b_hop = srs_resource->b_hop; f1_srs_resource->group_or_sequence_hopping = srs_resource->group_or_sequence_hopping; f1_srs_resource->resource_type.present = srs_resource->resource_type.present; f1ap_resource_type_t *f1_res_type = &f1_srs_resource->resource_type; f1ap_resource_type_t *res_type = &srs_resource->resource_type; if (res_type->present == F1AP_RESOURCE_TYPE_PR_NOTHING) { // nothing to copy } else if (res_type->present == F1AP_RESOURCE_TYPE_PR_PERIODIC) { f1_res_type->choice.periodic.periodicity = res_type->choice.periodic.periodicity; f1_res_type->choice.periodic.offset = res_type->choice.periodic.offset; } else if (res_type->present == F1AP_RESOURCE_TYPE_PR_SEMI_PERSISTENT) { f1_res_type->choice.semi_persistent.periodicity = res_type->choice.semi_persistent.periodicity; f1_res_type->choice.semi_persistent.offset = res_type->choice.semi_persistent.offset; } else if (res_type->present == F1AP_RESOURCE_TYPE_PR_APERIODIC) { f1_res_type->choice.aperiodic = res_type->choice.aperiodic; } else { AssertFatal(false, "illegal resourceType %d\n", res_type->present); } f1_srs_resource->sequence_id = srs_resource->sequence_id; } } // optional: pos_srs_resource_list if (in_config->pos_srs_resource_list) { f1ap_pos_srs_resource_list_t *pos_srs_resource_list = in_config->pos_srs_resource_list; out_config.pos_srs_resource_list = calloc_or_fail(1, sizeof(*out_config.pos_srs_resource_list)); f1ap_pos_srs_resource_list_t *f1_pos_srs_resource_list = out_config.pos_srs_resource_list; uint32_t pos_srs_resource_list_length = pos_srs_resource_list->pos_srs_resource_list_length; f1_pos_srs_resource_list->pos_srs_resource_list_length = pos_srs_resource_list_length; f1_pos_srs_resource_list->pos_srs_resource_item = calloc_or_fail(pos_srs_resource_list_length, sizeof(*f1_pos_srs_resource_list->pos_srs_resource_item)); for (int i = 0; i < pos_srs_resource_list_length; i++) { f1ap_pos_srs_resource_item_t *pos_srs_resource = &pos_srs_resource_list->pos_srs_resource_item[i]; f1ap_pos_srs_resource_item_t *f1_pos_srs_resource = &f1_pos_srs_resource_list->pos_srs_resource_item[i]; f1_pos_srs_resource->srs_pos_resource_id = pos_srs_resource->srs_pos_resource_id; f1_pos_srs_resource->transmission_comb_pos.present = pos_srs_resource->transmission_comb_pos.present; f1ap_transmission_comb_pos_t *f1_tx_comb_pos = &f1_pos_srs_resource->transmission_comb_pos; f1ap_transmission_comb_pos_t *tx_comb_pos = &pos_srs_resource->transmission_comb_pos; switch (tx_comb_pos->present) { case F1AP_TRANSMISSION_COMB_POS_PR_NOTHING: // nothing to copy break; case F1AP_TRANSMISSION_COMB_POS_PR_N2: f1_tx_comb_pos->choice.n2.comb_offset_n2 = tx_comb_pos->choice.n2.comb_offset_n2; f1_tx_comb_pos->choice.n2.cyclic_shift_n2 = tx_comb_pos->choice.n2.cyclic_shift_n2; break; case F1AP_TRANSMISSION_COMB_POS_PR_N4: f1_tx_comb_pos->choice.n4.comb_offset_n4 = tx_comb_pos->choice.n4.comb_offset_n4; f1_tx_comb_pos->choice.n4.cyclic_shift_n4 = tx_comb_pos->choice.n4.cyclic_shift_n4; break; case F1AP_TRANSMISSION_COMB_POS_PR_N8: f1_tx_comb_pos->choice.n8.comb_offset_n8 = tx_comb_pos->choice.n8.comb_offset_n8; f1_tx_comb_pos->choice.n8.cyclic_shift_n8 = tx_comb_pos->choice.n8.cyclic_shift_n8; break; default: AssertFatal(false, "illegal transmissionComb %d\n", tx_comb_pos->present); break; } f1_pos_srs_resource->start_position = pos_srs_resource->start_position; f1_pos_srs_resource->nr_of_symbols = pos_srs_resource->nr_of_symbols; f1_pos_srs_resource->freq_domain_shift = pos_srs_resource->freq_domain_shift; f1_pos_srs_resource->c_srs = pos_srs_resource->c_srs; f1_pos_srs_resource->group_or_sequence_hopping = pos_srs_resource->group_or_sequence_hopping; f1ap_resource_type_pos_t *f1_res_type_pos = &f1_pos_srs_resource->resource_type_pos; f1ap_resource_type_pos_t *res_type_pos = &pos_srs_resource->resource_type_pos; f1_res_type_pos->present = res_type_pos->present; if (res_type_pos->present == F1AP_RESOURCE_TYPE_POS_PR_NOTHING) { // nothing to copy } else if (res_type_pos->present == F1AP_RESOURCE_TYPE_POS_PR_PERIODIC) { f1_res_type_pos->choice.periodic.periodicity = res_type_pos->choice.periodic.periodicity; f1_res_type_pos->choice.periodic.offset = res_type_pos->choice.periodic.offset; } else if (pos_srs_resource->resource_type_pos.present == F1AP_RESOURCE_TYPE_POS_PR_SEMI_PERSISTENT) { f1_res_type_pos->choice.semi_persistent.periodicity = res_type_pos->choice.semi_persistent.periodicity; f1_res_type_pos->choice.semi_persistent.offset = res_type_pos->choice.semi_persistent.offset; } else if (res_type_pos->present == F1AP_RESOURCE_TYPE_POS_PR_APERIODIC) { f1_res_type_pos->choice.aperiodic.slot_offset = res_type_pos->choice.aperiodic.slot_offset; } else { AssertFatal(false, "illegal resourceType %d\n", res_type_pos->present); } f1_pos_srs_resource->sequence_id = pos_srs_resource->sequence_id; } } // optional: srs_resource_set_list if (in_config->srs_resource_set_list) { f1ap_srs_resource_set_list_t *srs_resource_set_list = in_config->srs_resource_set_list; out_config.srs_resource_set_list = calloc_or_fail(1, sizeof(*out_config.srs_resource_set_list)); f1ap_srs_resource_set_list_t *f1_srs_resource_set_list = out_config.srs_resource_set_list; uint32_t srs_resource_set_list_length = srs_resource_set_list->srs_resource_set_list_length; f1_srs_resource_set_list->srs_resource_set_list_length = srs_resource_set_list_length; f1_srs_resource_set_list->srs_resource_set = calloc_or_fail(srs_resource_set_list_length, sizeof(*f1_srs_resource_set_list->srs_resource_set)); for (int i = 0; i < srs_resource_set_list_length; i++) { f1ap_srs_resource_set_t *srs_resource_set = &srs_resource_set_list->srs_resource_set[i]; f1ap_srs_resource_set_t *f1_srs_resource_set = &f1_srs_resource_set_list->srs_resource_set[i]; f1_srs_resource_set->srs_resource_set_id = srs_resource_set->srs_resource_set_id; uint8_t srs_resource_id_list_length = srs_resource_set->srs_resource_id_list.srs_resource_id_list_length; f1_srs_resource_set->srs_resource_id_list.srs_resource_id_list_length = srs_resource_id_list_length; f1_srs_resource_set->srs_resource_id_list.srs_resource_id = calloc_or_fail(srs_resource_id_list_length, sizeof(*f1_srs_resource_set->srs_resource_id_list.srs_resource_id)); for (int j = 0; j < srs_resource_id_list_length; j++) { f1_srs_resource_set->srs_resource_id_list.srs_resource_id[j] = srs_resource_set->srs_resource_id_list.srs_resource_id[j]; } f1ap_resource_set_type_t *f1_res_set_type = &f1_srs_resource_set->resource_set_type; f1ap_resource_set_type_t *res_set_type = &srs_resource_set->resource_set_type; f1_res_set_type->present = res_set_type->present; switch (res_set_type->present) { case F1AP_RESOURCE_SET_TYPE_PR_NOTHING: // nothing to copy break; case F1AP_RESOURCE_SET_TYPE_PR_PERIODIC: f1_res_set_type->choice.periodic = res_set_type->choice.periodic; break; case F1AP_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT: f1_res_set_type->choice.semi_persistent = res_set_type->choice.semi_persistent; break; case F1AP_RESOURCE_SET_TYPE_PR_APERIODIC: f1_res_set_type->choice.aperiodic.srs_resource_trigger = res_set_type->choice.aperiodic.srs_resource_trigger; f1_res_set_type->choice.aperiodic.slot_offset = res_set_type->choice.aperiodic.slot_offset; break; default: AssertFatal(false, "illegal resource set type %d\n", res_set_type->present); break; } } } // optional: pos_srs_resource_set_list if (in_config->pos_srs_resource_set_list) { f1ap_pos_srs_resource_set_list_t *pos_srs_resource_set_list = in_config->pos_srs_resource_set_list; out_config.pos_srs_resource_set_list = calloc_or_fail(1, sizeof(*out_config.pos_srs_resource_set_list)); f1ap_pos_srs_resource_set_list_t *f1_pos_srs_resource_set_list = out_config.pos_srs_resource_set_list; uint32_t pos_srs_resource_set_list_length = pos_srs_resource_set_list->pos_srs_resource_set_list_length; f1_pos_srs_resource_set_list->pos_srs_resource_set_list_length = pos_srs_resource_set_list_length; f1_pos_srs_resource_set_list->pos_srs_resource_set_item = calloc_or_fail(pos_srs_resource_set_list_length, sizeof(*f1_pos_srs_resource_set_list->pos_srs_resource_set_item)); for (int i = 0; i < pos_srs_resource_set_list_length; i++) { f1ap_pos_srs_resource_set_item_t *pos_srs_resource_set = &pos_srs_resource_set_list->pos_srs_resource_set_item[i]; f1ap_pos_srs_resource_set_item_t *f1_pos_srs_resource_set = &f1_pos_srs_resource_set_list->pos_srs_resource_set_item[i]; f1_pos_srs_resource_set->pos_srs_resource_set_id = pos_srs_resource_set->pos_srs_resource_set_id; uint8_t pos_srs_resource_id_list_length = pos_srs_resource_set->pos_srs_resource_id_list.pos_srs_resource_id_list_length; f1_pos_srs_resource_set->pos_srs_resource_id_list.pos_srs_resource_id_list_length = pos_srs_resource_id_list_length; f1_pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id = calloc_or_fail(pos_srs_resource_id_list_length, sizeof(*f1_pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id)); for (int j = 0; j < pos_srs_resource_id_list_length; j++) { f1_pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id[j] = pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id[j]; } f1ap_pos_resource_set_type_t *f1_pos_res_set_type = &f1_pos_srs_resource_set->pos_resource_set_type; f1ap_pos_resource_set_type_t *pos_res_set_type = &pos_srs_resource_set->pos_resource_set_type; f1_pos_res_set_type->present = pos_res_set_type->present; switch (pos_res_set_type->present) { case F1AP_POS_RESOURCE_SET_TYPE_PR_NOTHING: // nothing to copy break; case F1AP_POS_RESOURCE_SET_TYPE_PR_PERIODIC: f1_pos_res_set_type->choice.periodic = pos_res_set_type->choice.periodic; break; case F1AP_POS_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT: f1_pos_res_set_type->choice.semi_persistent = pos_res_set_type->choice.semi_persistent; break; case F1AP_POS_RESOURCE_SET_TYPE_PR_APERIODIC: f1_pos_res_set_type->choice.srs_resource = pos_res_set_type->choice.srs_resource; break; default: AssertFatal(false, "illegal resource set type pos %d\n", pos_res_set_type->present); break; } } } return out_config; } static f1ap_srs_carrier_list_item_t cp_srs_carrier_list_item(const f1ap_srs_carrier_list_item_t *in_item) { f1ap_srs_carrier_list_item_t out_item = {0}; // pointA out_item.pointA = in_item->pointA; // Uplink Channel BW-PerSCS-List const f1ap_uplink_channel_bw_per_scs_list_t *uplink_channel_bw_per_scs_list = &in_item->uplink_channel_bw_per_scs_list; f1ap_uplink_channel_bw_per_scs_list_t *f1_uplink_channel_bw_per_scs_list = &out_item.uplink_channel_bw_per_scs_list; uint32_t scs_specific_carrier_list_length = uplink_channel_bw_per_scs_list->scs_specific_carrier_list_length; f1_uplink_channel_bw_per_scs_list->scs_specific_carrier_list_length = scs_specific_carrier_list_length; f1_uplink_channel_bw_per_scs_list->scs_specific_carrier = calloc_or_fail(scs_specific_carrier_list_length, sizeof(*f1_uplink_channel_bw_per_scs_list->scs_specific_carrier)); for (int i = 0; i < scs_specific_carrier_list_length; i++) { f1ap_scs_specific_carrier_t *scs_specific_carrier = &uplink_channel_bw_per_scs_list->scs_specific_carrier[i]; f1ap_scs_specific_carrier_t *f1_scs_specific_carrier = &f1_uplink_channel_bw_per_scs_list->scs_specific_carrier[i]; // offset to carrier f1_scs_specific_carrier->offset_to_carrier = scs_specific_carrier->offset_to_carrier; // subcarrier spacing f1_scs_specific_carrier->subcarrier_spacing = scs_specific_carrier->subcarrier_spacing; // carrier bandwidth f1_scs_specific_carrier->carrier_bandwidth = scs_specific_carrier->carrier_bandwidth; } // Active UL BWP f1ap_active_ul_bwp_t *f1_active_ul_bwp = &out_item.active_ul_bwp; const f1ap_active_ul_bwp_t *active_ul_bwp = &in_item->active_ul_bwp; // location and bandwidth f1_active_ul_bwp->location_and_bandwidth = active_ul_bwp->location_and_bandwidth; // subcarrier spacing f1_active_ul_bwp->subcarrier_spacing = active_ul_bwp->subcarrier_spacing; // cyclic prefix f1_active_ul_bwp->cyclic_prefix = active_ul_bwp->cyclic_prefix; // Tx Direct Current Location f1_active_ul_bwp->tx_direct_current_location = active_ul_bwp->tx_direct_current_location; // SRS Config f1ap_srs_config_t *f1_sRSConfig = &f1_active_ul_bwp->srs_config; const f1ap_srs_config_t *sRSConfig = &active_ul_bwp->srs_config; *f1_sRSConfig = cp_srs_config(sRSConfig); return out_item; } static f1ap_srs_carrier_list_t cp_srs_carrier_list(const f1ap_srs_carrier_list_t *in_list) { f1ap_srs_carrier_list_t out_list = {0}; uint32_t list_len = in_list->srs_carrier_list_length; out_list.srs_carrier_list_length = list_len; out_list.srs_carrier_list_item = calloc_or_fail(list_len, sizeof(*out_list.srs_carrier_list_item)); for (int i = 0; i < list_len; i++) { f1ap_srs_carrier_list_item_t *in_item = &in_list->srs_carrier_list_item[i]; f1ap_srs_carrier_list_item_t *out_item = &out_list.srs_carrier_list_item[i]; *out_item = cp_srs_carrier_list_item(in_item); } return out_list; } static bool eq_srs_config(const f1ap_srs_config_t *f1_sRSConfig, const f1ap_srs_config_t *sRSConfig) { // optional: srs_resource_list if ((f1_sRSConfig->srs_resource_list == NULL) != (sRSConfig->srs_resource_list == NULL)) { return false; } if (sRSConfig->srs_resource_list) { f1ap_srs_resource_list_t *srs_resource_list = sRSConfig->srs_resource_list; f1ap_srs_resource_list_t *f1_srs_resource_list = f1_sRSConfig->srs_resource_list; uint32_t srs_resource_list_length = srs_resource_list->srs_resource_list_length; _F1_EQ_CHECK_INT(f1_srs_resource_list->srs_resource_list_length, srs_resource_list_length); for (int i = 0; i < srs_resource_list_length; i++) { f1ap_srs_resource_t *srs_resource = &srs_resource_list->srs_resource[i]; f1ap_srs_resource_t *f1_srs_resource = &f1_srs_resource_list->srs_resource[i]; _F1_EQ_CHECK_INT(f1_srs_resource->srs_resource_id, srs_resource->srs_resource_id); _F1_EQ_CHECK_INT(f1_srs_resource->nr_of_srs_ports, srs_resource->nr_of_srs_ports); f1ap_transmission_comb_t *f1_srs_tx_comb = &f1_srs_resource->transmission_comb; f1ap_transmission_comb_t *srs_tx_comb = &srs_resource->transmission_comb; _F1_EQ_CHECK_INT(f1_srs_tx_comb->present, srs_tx_comb->present); switch (srs_tx_comb->present) { case F1AP_TRANSMISSION_COMB_PR_NOTHING: // nothing to check break; case F1AP_TRANSMISSION_COMB_PR_N2: _F1_EQ_CHECK_INT(f1_srs_tx_comb->choice.n2.comb_offset_n2, srs_tx_comb->choice.n2.comb_offset_n2); _F1_EQ_CHECK_INT(f1_srs_tx_comb->choice.n2.cyclic_shift_n2, srs_tx_comb->choice.n2.cyclic_shift_n2); break; case F1AP_TRANSMISSION_COMB_PR_N4: _F1_EQ_CHECK_INT(f1_srs_tx_comb->choice.n4.comb_offset_n4, srs_tx_comb->choice.n4.comb_offset_n4); _F1_EQ_CHECK_INT(f1_srs_tx_comb->choice.n4.cyclic_shift_n4, srs_tx_comb->choice.n4.cyclic_shift_n4); break; default: AssertFatal(false, "illegal transmissionComb %d\n", srs_tx_comb->present); break; } _F1_EQ_CHECK_INT(f1_srs_resource->start_position, srs_resource->start_position); _F1_EQ_CHECK_INT(f1_srs_resource->nr_of_symbols, srs_resource->nr_of_symbols); _F1_EQ_CHECK_INT(f1_srs_resource->repetition_factor, srs_resource->repetition_factor); _F1_EQ_CHECK_INT(f1_srs_resource->freq_domain_position, srs_resource->freq_domain_position); _F1_EQ_CHECK_INT(f1_srs_resource->freq_domain_shift, srs_resource->freq_domain_shift); _F1_EQ_CHECK_INT(f1_srs_resource->c_srs, srs_resource->c_srs); _F1_EQ_CHECK_INT(f1_srs_resource->b_srs, srs_resource->b_srs); _F1_EQ_CHECK_INT(f1_srs_resource->b_hop, srs_resource->b_hop); _F1_EQ_CHECK_INT(f1_srs_resource->group_or_sequence_hopping, srs_resource->group_or_sequence_hopping); f1ap_resource_type_t *f1_res_type = &f1_srs_resource->resource_type; f1ap_resource_type_t *res_type = &srs_resource->resource_type; _F1_EQ_CHECK_INT(f1_res_type->present, res_type->present); if (res_type->present == F1AP_RESOURCE_TYPE_PR_NOTHING) { // nothing to check } else if (res_type->present == F1AP_RESOURCE_TYPE_PR_PERIODIC) { _F1_EQ_CHECK_INT(f1_res_type->choice.periodic.periodicity, res_type->choice.periodic.periodicity); _F1_EQ_CHECK_INT(f1_res_type->choice.periodic.offset, res_type->choice.periodic.offset); } else if (res_type->present == F1AP_RESOURCE_TYPE_PR_SEMI_PERSISTENT) { _F1_EQ_CHECK_INT(f1_res_type->choice.semi_persistent.periodicity, res_type->choice.semi_persistent.periodicity); _F1_EQ_CHECK_INT(f1_res_type->choice.semi_persistent.offset, res_type->choice.semi_persistent.offset); } else if (res_type->present == F1AP_RESOURCE_TYPE_PR_APERIODIC) { _F1_EQ_CHECK_INT(f1_res_type->choice.aperiodic, res_type->choice.aperiodic); } else { AssertFatal(false, "illegal resourceType %d\n", res_type->present); } _F1_EQ_CHECK_INT(f1_srs_resource->sequence_id, srs_resource->sequence_id); } } // optional: pos_srs_resource_list if ((f1_sRSConfig->pos_srs_resource_list == NULL) != (sRSConfig->pos_srs_resource_list == NULL)) { return false; } if (sRSConfig->pos_srs_resource_list) { f1ap_pos_srs_resource_list_t *pos_srs_resource_list = sRSConfig->pos_srs_resource_list; f1ap_pos_srs_resource_list_t *f1_pos_srs_resource_list = f1_sRSConfig->pos_srs_resource_list; uint32_t pos_srs_resource_list_length = pos_srs_resource_list->pos_srs_resource_list_length; _F1_EQ_CHECK_INT(f1_pos_srs_resource_list->pos_srs_resource_list_length, pos_srs_resource_list_length); for (int i = 0; i < pos_srs_resource_list_length; i++) { f1ap_pos_srs_resource_item_t *pos_srs_resource = &pos_srs_resource_list->pos_srs_resource_item[i]; f1ap_pos_srs_resource_item_t *f1_pos_srs_resource = &f1_pos_srs_resource_list->pos_srs_resource_item[i]; _F1_EQ_CHECK_INT(f1_pos_srs_resource->srs_pos_resource_id, pos_srs_resource->srs_pos_resource_id); _F1_EQ_CHECK_INT(f1_pos_srs_resource->transmission_comb_pos.present, pos_srs_resource->transmission_comb_pos.present); f1ap_transmission_comb_pos_t *f1_srs_tx_comb_pos = &f1_pos_srs_resource->transmission_comb_pos; f1ap_transmission_comb_pos_t *srs_tx_comb_pos = &pos_srs_resource->transmission_comb_pos; switch (srs_tx_comb_pos->present) { case F1AP_TRANSMISSION_COMB_POS_PR_NOTHING: // nothing to check break; case F1AP_TRANSMISSION_COMB_POS_PR_N2: _F1_EQ_CHECK_INT(f1_srs_tx_comb_pos->choice.n2.comb_offset_n2, srs_tx_comb_pos->choice.n2.comb_offset_n2); _F1_EQ_CHECK_INT(f1_srs_tx_comb_pos->choice.n2.cyclic_shift_n2, srs_tx_comb_pos->choice.n2.cyclic_shift_n2); break; case F1AP_TRANSMISSION_COMB_POS_PR_N4: _F1_EQ_CHECK_INT(f1_srs_tx_comb_pos->choice.n4.comb_offset_n4, srs_tx_comb_pos->choice.n4.comb_offset_n4); _F1_EQ_CHECK_INT(f1_srs_tx_comb_pos->choice.n4.cyclic_shift_n4, srs_tx_comb_pos->choice.n4.cyclic_shift_n4); break; case F1AP_TRANSMISSION_COMB_POS_PR_N8: _F1_EQ_CHECK_INT(f1_srs_tx_comb_pos->choice.n8.comb_offset_n8, srs_tx_comb_pos->choice.n8.comb_offset_n8); _F1_EQ_CHECK_INT(f1_srs_tx_comb_pos->choice.n8.cyclic_shift_n8, srs_tx_comb_pos->choice.n8.cyclic_shift_n8); break; default: AssertFatal(false, "illegal transmissionComb %d\n", srs_tx_comb_pos->present); break; } _F1_EQ_CHECK_INT(f1_pos_srs_resource->start_position, pos_srs_resource->start_position); _F1_EQ_CHECK_INT(f1_pos_srs_resource->nr_of_symbols, pos_srs_resource->nr_of_symbols); _F1_EQ_CHECK_INT(f1_pos_srs_resource->freq_domain_shift, pos_srs_resource->freq_domain_shift); _F1_EQ_CHECK_INT(f1_pos_srs_resource->c_srs, pos_srs_resource->c_srs); _F1_EQ_CHECK_INT(f1_pos_srs_resource->group_or_sequence_hopping, pos_srs_resource->group_or_sequence_hopping); f1ap_resource_type_pos_t *f1_res_type_pos = &f1_pos_srs_resource->resource_type_pos; f1ap_resource_type_pos_t *res_type_pos = &pos_srs_resource->resource_type_pos; _F1_EQ_CHECK_INT(f1_res_type_pos->present, res_type_pos->present); if (res_type_pos->present == F1AP_RESOURCE_TYPE_POS_PR_NOTHING) { // nothing to check } else if (res_type_pos->present == F1AP_RESOURCE_TYPE_POS_PR_PERIODIC) { _F1_EQ_CHECK_INT(f1_res_type_pos->choice.periodic.periodicity, res_type_pos->choice.periodic.periodicity); _F1_EQ_CHECK_INT(f1_res_type_pos->choice.periodic.offset, res_type_pos->choice.periodic.offset); } else if (res_type_pos->present == F1AP_RESOURCE_TYPE_POS_PR_SEMI_PERSISTENT) { _F1_EQ_CHECK_INT(f1_res_type_pos->choice.semi_persistent.periodicity, res_type_pos->choice.semi_persistent.periodicity); _F1_EQ_CHECK_INT(f1_res_type_pos->choice.semi_persistent.offset, res_type_pos->choice.semi_persistent.offset); } else if (res_type_pos->present == F1AP_RESOURCE_TYPE_POS_PR_APERIODIC) { _F1_EQ_CHECK_INT(f1_res_type_pos->choice.aperiodic.slot_offset, res_type_pos->choice.aperiodic.slot_offset); } else { AssertFatal(false, "illegal resourceType %d\n", res_type_pos->present); } _F1_EQ_CHECK_INT(f1_pos_srs_resource->sequence_id, pos_srs_resource->sequence_id); } } // optional: srs_resource_set_list if ((f1_sRSConfig->srs_resource_set_list == NULL) != (sRSConfig->srs_resource_set_list == NULL)) { return false; } if (sRSConfig->srs_resource_set_list) { f1ap_srs_resource_set_list_t *srs_resource_set_list = sRSConfig->srs_resource_set_list; f1ap_srs_resource_set_list_t *f1_srs_resource_set_list = f1_sRSConfig->srs_resource_set_list; uint32_t srs_resource_set_list_length = srs_resource_set_list->srs_resource_set_list_length; _F1_EQ_CHECK_INT(f1_srs_resource_set_list->srs_resource_set_list_length, srs_resource_set_list_length); for (int i = 0; i < srs_resource_set_list_length; i++) { f1ap_srs_resource_set_t *srs_resource_set = &srs_resource_set_list->srs_resource_set[i]; f1ap_srs_resource_set_t *f1_srs_resource_set = &f1_srs_resource_set_list->srs_resource_set[i]; _F1_EQ_CHECK_INT(f1_srs_resource_set->srs_resource_set_id, srs_resource_set->srs_resource_set_id); uint8_t srs_resource_id_list_length = srs_resource_set->srs_resource_id_list.srs_resource_id_list_length; _F1_EQ_CHECK_INT(f1_srs_resource_set->srs_resource_id_list.srs_resource_id_list_length, srs_resource_id_list_length); for (int j = 0; j < srs_resource_id_list_length; j++) { _F1_EQ_CHECK_LONG(f1_srs_resource_set->srs_resource_id_list.srs_resource_id[j], srs_resource_set->srs_resource_id_list.srs_resource_id[j]); } f1ap_resource_set_type_t *f1_res_set_type = &f1_srs_resource_set->resource_set_type; f1ap_resource_set_type_t *res_set_type = &srs_resource_set->resource_set_type; _F1_EQ_CHECK_INT(f1_res_set_type->present, res_set_type->present); switch (res_set_type->present) { case F1AP_RESOURCE_SET_TYPE_PR_NOTHING: // nothing to check break; case F1AP_RESOURCE_SET_TYPE_PR_PERIODIC: _F1_EQ_CHECK_INT(f1_res_set_type->choice.periodic, res_set_type->choice.periodic); break; case F1AP_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT: _F1_EQ_CHECK_INT(f1_res_set_type->choice.semi_persistent, res_set_type->choice.semi_persistent); break; case F1AP_RESOURCE_SET_TYPE_PR_APERIODIC: _F1_EQ_CHECK_INT(f1_res_set_type->choice.aperiodic.srs_resource_trigger, res_set_type->choice.aperiodic.srs_resource_trigger); _F1_EQ_CHECK_LONG(f1_res_set_type->choice.aperiodic.slot_offset, res_set_type->choice.aperiodic.slot_offset); break; default: AssertFatal(false, "illegal resource set type %d\n", res_set_type->present); break; } } } // optional: pos_srs_resource_set_list if ((f1_sRSConfig->pos_srs_resource_set_list == NULL) != (sRSConfig->pos_srs_resource_set_list == NULL)) { return false; } if (sRSConfig->pos_srs_resource_set_list) { f1ap_pos_srs_resource_set_list_t *pos_srs_resource_set_list = sRSConfig->pos_srs_resource_set_list; f1ap_pos_srs_resource_set_list_t *f1_pos_srs_resource_set_list = f1_sRSConfig->pos_srs_resource_set_list; uint32_t pos_srs_resource_set_list_length = pos_srs_resource_set_list->pos_srs_resource_set_list_length; _F1_EQ_CHECK_INT(f1_pos_srs_resource_set_list->pos_srs_resource_set_list_length, pos_srs_resource_set_list_length); for (int i = 0; i < pos_srs_resource_set_list_length; i++) { f1ap_pos_srs_resource_set_item_t *pos_srs_resource_set = &pos_srs_resource_set_list->pos_srs_resource_set_item[i]; f1ap_pos_srs_resource_set_item_t *f1_pos_srs_resource_set = &f1_pos_srs_resource_set_list->pos_srs_resource_set_item[i]; _F1_EQ_CHECK_INT(f1_pos_srs_resource_set->pos_srs_resource_set_id, pos_srs_resource_set->pos_srs_resource_set_id); uint8_t pos_srs_resource_id_list_length = pos_srs_resource_set->pos_srs_resource_id_list.pos_srs_resource_id_list_length; _F1_EQ_CHECK_INT(f1_pos_srs_resource_set->pos_srs_resource_id_list.pos_srs_resource_id_list_length, pos_srs_resource_id_list_length); for (int j = 0; j < pos_srs_resource_id_list_length; j++) { _F1_EQ_CHECK_LONG(f1_pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id[j], pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id[j]); } f1ap_pos_resource_set_type_t *f1_pos_res_set_type = &f1_pos_srs_resource_set->pos_resource_set_type; f1ap_pos_resource_set_type_t *pos_res_set_type = &pos_srs_resource_set->pos_resource_set_type; _F1_EQ_CHECK_INT(f1_pos_res_set_type->present, pos_res_set_type->present); switch (pos_res_set_type->present) { case F1AP_POS_RESOURCE_SET_TYPE_PR_NOTHING: // nothing to check break; case F1AP_POS_RESOURCE_SET_TYPE_PR_PERIODIC: _F1_EQ_CHECK_INT(f1_pos_res_set_type->choice.periodic, pos_res_set_type->choice.periodic); break; case F1AP_POS_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT: _F1_EQ_CHECK_INT(f1_pos_res_set_type->choice.semi_persistent, pos_res_set_type->choice.semi_persistent); break; case F1AP_POS_RESOURCE_SET_TYPE_PR_APERIODIC: _F1_EQ_CHECK_INT(f1_pos_res_set_type->choice.srs_resource, pos_res_set_type->choice.srs_resource); break; default: AssertFatal(false, "illegal resource set type pos %d\n", pos_res_set_type->present); break; } } } return true; } static bool eq_srs_carrier_list_item(const f1ap_srs_carrier_list_item_t *f1_srs_carrier_list_item, const f1ap_srs_carrier_list_item_t *srs_carrier_list_item) { // pointA _F1_EQ_CHECK_INT(f1_srs_carrier_list_item->pointA, srs_carrier_list_item->pointA); // Uplink Channel BW-PerSCS-List const f1ap_uplink_channel_bw_per_scs_list_t *uplink_channel_bw_per_scs_list = &srs_carrier_list_item->uplink_channel_bw_per_scs_list; const f1ap_uplink_channel_bw_per_scs_list_t *f1_uplink_channel_bw_per_scs_list = &f1_srs_carrier_list_item->uplink_channel_bw_per_scs_list; uint32_t scs_specific_carrier_list_length = uplink_channel_bw_per_scs_list->scs_specific_carrier_list_length; _F1_EQ_CHECK_INT(f1_uplink_channel_bw_per_scs_list->scs_specific_carrier_list_length, scs_specific_carrier_list_length); for (int i = 0; i < scs_specific_carrier_list_length; i++) { f1ap_scs_specific_carrier_t *scs_specific_carrier = &uplink_channel_bw_per_scs_list->scs_specific_carrier[i]; f1ap_scs_specific_carrier_t *f1_scs_specific_carrier = &f1_uplink_channel_bw_per_scs_list->scs_specific_carrier[i]; // offset to carrier _F1_EQ_CHECK_INT(f1_scs_specific_carrier->offset_to_carrier, scs_specific_carrier->offset_to_carrier); // subcarrier spacing _F1_EQ_CHECK_INT(f1_scs_specific_carrier->subcarrier_spacing, scs_specific_carrier->subcarrier_spacing); // carrier bandwidth _F1_EQ_CHECK_INT(f1_scs_specific_carrier->carrier_bandwidth, scs_specific_carrier->carrier_bandwidth); } // Active UL BWP const f1ap_active_ul_bwp_t *f1_active_ul_bwp = &f1_srs_carrier_list_item->active_ul_bwp; const f1ap_active_ul_bwp_t *active_ul_bwp = &srs_carrier_list_item->active_ul_bwp; // location and bandwidth _F1_EQ_CHECK_INT(f1_active_ul_bwp->location_and_bandwidth, active_ul_bwp->location_and_bandwidth); // subcarrier spacing _F1_EQ_CHECK_INT(f1_active_ul_bwp->subcarrier_spacing, active_ul_bwp->subcarrier_spacing); // cyclic prefix _F1_EQ_CHECK_INT(f1_active_ul_bwp->cyclic_prefix, active_ul_bwp->cyclic_prefix); // Tx Direct Current Location _F1_EQ_CHECK_INT(f1_active_ul_bwp->tx_direct_current_location, active_ul_bwp->tx_direct_current_location); // SRS Config const f1ap_srs_config_t *f1_sRSConfig = &f1_active_ul_bwp->srs_config; const f1ap_srs_config_t *sRSConfig = &active_ul_bwp->srs_config; _F1_CHECK_EXP(eq_srs_config(f1_sRSConfig, sRSConfig)); return true; } static bool eq_srs_carrier_list(const f1ap_srs_carrier_list_t *srs_carrier_list_a, const f1ap_srs_carrier_list_t *srs_carrier_list_b) { uint32_t srs_carrier_list_len = srs_carrier_list_a->srs_carrier_list_length; _F1_EQ_CHECK_INT(srs_carrier_list_b->srs_carrier_list_length, srs_carrier_list_len); for (int i = 0; i < srs_carrier_list_len; i++) { f1ap_srs_carrier_list_item_t *srs_carrier_list_item_a = &srs_carrier_list_a->srs_carrier_list_item[i]; f1ap_srs_carrier_list_item_t *srs_carrier_list_item_b = &srs_carrier_list_b->srs_carrier_list_item[i]; _F1_CHECK_EXP(eq_srs_carrier_list_item(srs_carrier_list_item_a, srs_carrier_list_item_b)); } return true; } static void free_srs_carrier_list(f1ap_srs_carrier_list_t *srs_carrier_list) { uint32_t srs_carrier_list_len = srs_carrier_list->srs_carrier_list_length; for (int i = 0; i < srs_carrier_list_len; i++) { f1ap_srs_carrier_list_item_t *srs_carrier_list_item = &srs_carrier_list->srs_carrier_list_item[i]; free(srs_carrier_list_item->uplink_channel_bw_per_scs_list.scs_specific_carrier); f1ap_active_ul_bwp_t *active_ul_bwp = &srs_carrier_list_item->active_ul_bwp; f1ap_srs_config_t *sRSConfig = &active_ul_bwp->srs_config; if (sRSConfig->srs_resource_list) { f1ap_srs_resource_list_t *srs_resource_list = sRSConfig->srs_resource_list; free(srs_resource_list->srs_resource); free(sRSConfig->srs_resource_list); } if (sRSConfig->pos_srs_resource_list) { f1ap_pos_srs_resource_list_t *pos_srs_resource_list = sRSConfig->pos_srs_resource_list; free(pos_srs_resource_list->pos_srs_resource_item); free(sRSConfig->pos_srs_resource_list); } if (sRSConfig->srs_resource_set_list) { f1ap_srs_resource_set_list_t *srs_resource_set_list = sRSConfig->srs_resource_set_list; uint32_t srs_resource_set_list_length = srs_resource_set_list->srs_resource_set_list_length; for (int j = 0; j < srs_resource_set_list_length; j++) { f1ap_srs_resource_set_t *srs_resource_set = &srs_resource_set_list->srs_resource_set[j]; free(srs_resource_set->srs_resource_id_list.srs_resource_id); } free(srs_resource_set_list->srs_resource_set); free(sRSConfig->srs_resource_set_list); } if (sRSConfig->pos_srs_resource_set_list) { f1ap_pos_srs_resource_set_list_t *pos_srs_resource_set_list = sRSConfig->pos_srs_resource_set_list; uint32_t pos_srs_resource_set_list_length = pos_srs_resource_set_list->pos_srs_resource_set_list_length; for (int j = 0; j < pos_srs_resource_set_list_length; j++) { f1ap_pos_srs_resource_set_item_t *pos_srs_resource_set = &pos_srs_resource_set_list->pos_srs_resource_set_item[j]; free(pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id); } free(pos_srs_resource_set_list->pos_srs_resource_set_item); free(sRSConfig->pos_srs_resource_set_list); } } free(srs_carrier_list->srs_carrier_list_item); } static F1AP_SRSType_t encode_f1ap_srstype(const f1ap_srs_type_t *srs_type) { F1AP_SRSType_t f1_srstype = {0}; switch (srs_type->present) { case F1AP_SRS_TYPE_PR_NOTHING: f1_srstype.present = F1AP_SRSType_PR_NOTHING; break; case F1AP_SRS_TYPE_PR_SEMIPERSISTENTSRS: f1_srstype.present = F1AP_SRSType_PR_semipersistentSRS; asn1cCalloc(f1_srstype.choice.semipersistentSRS, sp_srs); sp_srs->sRSResourceSetID = *srs_type->choice.srs_resource_set_id; break; case F1AP_SRS_TYPE_PR_APERIODICSRS: f1_srstype.present = F1AP_SRSType_PR_aperiodicSRS; asn1cCalloc(f1_srstype.choice.aperiodicSRS, ap_srs); ap_srs->aperiodic = *srs_type->choice.aperiodic; break; default: AssertFatal(false, "unknown SRS type %d\n", srs_type->present); break; } return f1_srstype; } static bool decode_f1ap_srstype(const F1AP_SRSType_t *srs_type, f1ap_srs_type_t *out) { switch (srs_type->present) { case F1AP_SRSType_PR_NOTHING: out->present = F1AP_SRS_TYPE_PR_NOTHING; break; case F1AP_SRSType_PR_semipersistentSRS: out->present = F1AP_SRS_TYPE_PR_SEMIPERSISTENTSRS; out->choice.srs_resource_set_id = calloc_or_fail(1, sizeof(*out->choice.srs_resource_set_id)); *out->choice.srs_resource_set_id = srs_type->choice.semipersistentSRS->sRSResourceSetID; break; case F1AP_SRSType_PR_aperiodicSRS: out->present = F1AP_SRS_TYPE_PR_APERIODICSRS; out->choice.aperiodic = calloc_or_fail(1, sizeof(*out->choice.aperiodic)); *out->choice.aperiodic = srs_type->choice.aperiodicSRS->aperiodic; break; default: PRINT_ERROR("received illegal SRS type %d\n", srs_type->present); return false; break; } return true; } static F1AP_AbortTransmission_t encode_f1ap_abort_transmission(const f1ap_abort_transmission_t *abort_tx) { F1AP_AbortTransmission_t f1_abort_tx = {0}; switch (abort_tx->present) { case F1AP_ABORT_TRANSMISSION_PR_NOTHING: f1_abort_tx.present = F1AP_AbortTransmission_PR_NOTHING; break; case F1AP_ABORT_TRANSMISSION_PR_SRSRESOURCESETID: f1_abort_tx.present = F1AP_AbortTransmission_PR_sRSResourceSetID; f1_abort_tx.choice.sRSResourceSetID = abort_tx->choice.srs_resource_set_id; break; case F1AP_ABORT_TRANSMISSION_PR_RELEASEALL: f1_abort_tx.present = F1AP_AbortTransmission_PR_releaseALL; break; default: AssertFatal(false, "unknown Abort Transmission %d\n", abort_tx->present); break; } return f1_abort_tx; } static bool decode_f1ap_abort_transmission(const F1AP_AbortTransmission_t *in, f1ap_abort_transmission_t *out) { switch (in->present) { case F1AP_AbortTransmission_PR_NOTHING: out->present = F1AP_ABORT_TRANSMISSION_PR_NOTHING; break; case F1AP_AbortTransmission_PR_sRSResourceSetID: out->present = F1AP_ABORT_TRANSMISSION_PR_SRSRESOURCESETID; out->choice.srs_resource_set_id = in->choice.sRSResourceSetID; break; case F1AP_AbortTransmission_PR_releaseALL: out->present = F1AP_ABORT_TRANSMISSION_PR_RELEASEALL; out->choice.release_all = true; break; default: AssertError(false, return false, "received illegal Abort Transmission %d\n", in->present); break; } return true; } static F1AP_TRPReferencePointType_t encode_reference_point_type(const f1ap_trp_reference_point_type_t *in) { F1AP_TRPReferencePointType_t out = {0}; switch (in->present) { case F1AP_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_GEODETIC: out.present = F1AP_TRPReferencePointType_PR_tRPPositionRelativeGeodetic; asn1cCalloc(out.choice.tRPPositionRelativeGeodetic, f1_tRPPositionRelativeGeodetic); const f1ap_relative_geodetic_location_t *tRPPositionRelativeGeodetic = &in->choice.trp_position_relative_geodetic; f1_tRPPositionRelativeGeodetic->milli_Arc_SecondUnits = tRPPositionRelativeGeodetic->milli_arc_second_units; f1_tRPPositionRelativeGeodetic->heightUnits = tRPPositionRelativeGeodetic->height_units; f1_tRPPositionRelativeGeodetic->deltaLatitude = tRPPositionRelativeGeodetic->delta_latitude; f1_tRPPositionRelativeGeodetic->deltaLongitude = tRPPositionRelativeGeodetic->delta_longitude; f1_tRPPositionRelativeGeodetic->deltaHeight = tRPPositionRelativeGeodetic->delta_height; F1AP_LocationUncertainty_t *f1_locationUncertainty_g = &f1_tRPPositionRelativeGeodetic->locationUncertainty; const f1ap_location_uncertainty_t *locationUncertainty_g = &tRPPositionRelativeGeodetic->location_uncertainty; f1_locationUncertainty_g->horizontalUncertainty = locationUncertainty_g->horizontal_uncertainty; f1_locationUncertainty_g->horizontalConfidence = locationUncertainty_g->horizontal_confidence; f1_locationUncertainty_g->verticalUncertainty = locationUncertainty_g->vertical_uncertainty; f1_locationUncertainty_g->verticalConfidence = locationUncertainty_g->vertical_confidence; break; case F1AP_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_CARTESIAN: out.present = F1AP_TRPReferencePointType_PR_tRPPositionRelativeCartesian; asn1cCalloc(out.choice.tRPPositionRelativeCartesian, f1_tRPPositionRelativeCartesian); const f1ap_relative_cartesian_location_t *tRPPositionRelativeCartesian = &in->choice.trp_position_relative_cartesian; f1_tRPPositionRelativeCartesian->xYZunit = tRPPositionRelativeCartesian->xyz_unit; f1_tRPPositionRelativeCartesian->xvalue = tRPPositionRelativeCartesian->xvalue; f1_tRPPositionRelativeCartesian->yvalue = tRPPositionRelativeCartesian->yvalue; f1_tRPPositionRelativeCartesian->zvalue = tRPPositionRelativeCartesian->zvalue; F1AP_LocationUncertainty_t *f1_locationUncertainty_c = &f1_tRPPositionRelativeCartesian->locationUncertainty; const f1ap_location_uncertainty_t *locationUncertainty_c = &tRPPositionRelativeCartesian->location_uncertainty; f1_locationUncertainty_c->horizontalUncertainty = locationUncertainty_c->horizontal_uncertainty; f1_locationUncertainty_c->horizontalConfidence = locationUncertainty_c->horizontal_confidence; f1_locationUncertainty_c->verticalUncertainty = locationUncertainty_c->vertical_uncertainty; f1_locationUncertainty_c->verticalConfidence = locationUncertainty_c->vertical_confidence; break; default: AssertFatal(false, "illegal trp reference point type entry %d\n", in->present); break; } return out; } static F1AP_NGRANHighAccuracyAccessPointPosition_t encode_trp_ha_pos(const f1ap_ngran_high_accuracy_access_point_position_t *in) { F1AP_NGRANHighAccuracyAccessPointPosition_t out = {0}; out.latitude = in->latitude; out.longitude = in->longitude; out.altitude = in->altitude; out.uncertaintySemi_major = in->uncertainty_semi_major; out.uncertaintySemi_minor = in->uncertainty_semi_minor; out.orientationOfMajorAxis = in->orientation_of_major_axis; out.horizontalConfidence = in->horizontal_confidence; out.uncertaintyAltitude = in->uncertainty_altitude; out.verticalConfidence = in->vertical_confidence; return out; } static F1AP_GeographicalCoordinates_t encode_geographical_coordinates(const f1ap_geographical_coordinates_t *in) { F1AP_GeographicalCoordinates_t out = {0}; F1AP_TRPPositionDefinitionType_t *f1_trp_pos_def_type = &out.tRPPositionDefinitionType; const f1ap_trp_position_definition_type_t *trp_pos_def_type = &in->trp_position_definition_type; switch (trp_pos_def_type->present) { case F1AP_TRP_POSITION_DEFINITION_TYPE_PR_NOTHING: f1_trp_pos_def_type->present = F1AP_TRPPositionDefinitionType_PR_NOTHING; break; case F1AP_TRP_POSITION_DEFINITION_TYPE_PR_DIRECT: f1_trp_pos_def_type->present = F1AP_TRPPositionDefinitionType_PR_direct; asn1cCalloc(f1_trp_pos_def_type->choice.direct, f1_direct); const f1ap_trp_position_direct_t *direct = &trp_pos_def_type->choice.direct; if (direct->accuracy.present == F1AP_TRP_POSITION_DIRECT_ACCURACY_PR_TRPPOSITION) { f1_direct->accuracy.present = F1AP_TRPPositionDirectAccuracy_PR_tRPPosition; const f1ap_access_point_position_t *trp_pos = &direct->accuracy.choice.trp_position; F1AP_AccessPointPosition_t *f1_trp_pos = f1_direct->accuracy.choice.tRPPosition; f1_trp_pos->latitudeSign = trp_pos->latitude_sign; f1_trp_pos->latitude = trp_pos->latitude; f1_trp_pos->longitude = trp_pos->longitude; f1_trp_pos->directionOfAltitude = trp_pos->direction_of_altitude; f1_trp_pos->altitude = trp_pos->altitude; f1_trp_pos->uncertaintySemi_major = trp_pos->uncertainty_semi_major; f1_trp_pos->uncertaintySemi_minor = trp_pos->uncertainty_semi_minor; f1_trp_pos->orientationOfMajorAxis = trp_pos->orientation_of_major_axis; f1_trp_pos->uncertaintyAltitude = trp_pos->uncertainty_altitude; f1_trp_pos->confidence = trp_pos->confidence; } else if (direct->accuracy.present == F1AP_TRP_POSITION_DIRECT_ACCURACY_PR_TRPHAPOSITION) { f1_direct->accuracy.present = F1AP_TRPPositionDirectAccuracy_PR_tRPHAposition; const f1ap_ngran_high_accuracy_access_point_position_t *trp_ha_pos = &direct->accuracy.choice.trp_HAposition; F1AP_NGRANHighAccuracyAccessPointPosition_t *f1_trp_ha_pos = f1_direct->accuracy.choice.tRPHAposition; *f1_trp_ha_pos = encode_trp_ha_pos(trp_ha_pos); } else { AssertFatal(false, "illegal direct accuracy entry %d\n", direct->accuracy.present); } break; case F1AP_TRP_POSITION_DEFINITION_TYPE_PR_REFERENCED: f1_trp_pos_def_type->present = F1AP_TRPPositionDefinitionType_PR_referenced; asn1cCalloc(f1_trp_pos_def_type->choice.referenced, f1_referenced); const f1ap_trp_position_referenced_t *referenced = &trp_pos_def_type->choice.referenced; F1AP_ReferencePoint_t *f1_referencePoint = &f1_referenced->referencePoint; const f1ap_reference_point_t *referencePoint = &referenced->reference_point; if (referencePoint->present == F1AP_REFERENCE_POINT_PR_COORDINATEID) { f1_referencePoint->present = F1AP_ReferencePoint_PR_coordinateID; f1_referencePoint->choice.coordinateID = referencePoint->choice.coordinate_id; } else if (referencePoint->present == F1AP_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATE) { f1_referencePoint->present = F1AP_ReferencePoint_PR_referencePointCoordinate; const f1ap_access_point_position_t *referencePointCoordinate = &referencePoint->choice.reference_point_coordinate; asn1cCalloc(f1_referencePoint->choice.referencePointCoordinate, f1_referencePointCoordinate); f1_referencePointCoordinate->latitudeSign = referencePointCoordinate->latitude_sign; f1_referencePointCoordinate->latitude = referencePointCoordinate->latitude; f1_referencePointCoordinate->longitude = referencePointCoordinate->longitude; f1_referencePointCoordinate->directionOfAltitude = referencePointCoordinate->direction_of_altitude; f1_referencePointCoordinate->altitude = referencePointCoordinate->altitude; f1_referencePointCoordinate->uncertaintySemi_major = referencePointCoordinate->uncertainty_semi_major; f1_referencePointCoordinate->uncertaintySemi_minor = referencePointCoordinate->uncertainty_semi_minor; f1_referencePointCoordinate->orientationOfMajorAxis = referencePointCoordinate->orientation_of_major_axis; f1_referencePointCoordinate->uncertaintyAltitude = referencePointCoordinate->uncertainty_altitude; f1_referencePointCoordinate->confidence = referencePointCoordinate->confidence; } else if (referencePoint->present == F1AP_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATEHA) { f1_referencePoint->present = F1AP_ReferencePoint_PR_referencePointCoordinateHA; const f1ap_ngran_high_accuracy_access_point_position_t *referencePointCoordinateHA = &referencePoint->choice.reference_point_coordinateHA; asn1cCalloc(f1_referencePoint->choice.referencePointCoordinateHA, f1_referencePointCoordinateHA); *f1_referencePointCoordinateHA = encode_trp_ha_pos(referencePointCoordinateHA); } else { AssertFatal(false, "illegal reference point entry %d\n", referencePoint->present); } F1AP_TRPReferencePointType_t *f1_referencePointType = &f1_referenced->referencePointType; const f1ap_trp_reference_point_type_t *referencePointType = &referenced->reference_point_type; *f1_referencePointType = encode_reference_point_type(referencePointType); break; default: AssertFatal(false, "illegal Geographical Coordinates entry\n"); break; } return out; } static void decode_reference_point_type(const F1AP_TRPReferencePointType_t *in, f1ap_trp_reference_point_type_t *out) { switch (in->present) { case F1AP_TRPReferencePointType_PR_tRPPositionRelativeGeodetic: out->present = F1AP_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_GEODETIC; F1AP_RelativeGeodeticLocation_t *f1_tRPPositionRelativeGeodetic = in->choice.tRPPositionRelativeGeodetic; f1ap_relative_geodetic_location_t *tRPPositionRelativeGeodetic = &out->choice.trp_position_relative_geodetic; tRPPositionRelativeGeodetic->milli_arc_second_units = f1_tRPPositionRelativeGeodetic->milli_Arc_SecondUnits; tRPPositionRelativeGeodetic->height_units = f1_tRPPositionRelativeGeodetic->heightUnits; tRPPositionRelativeGeodetic->delta_latitude = f1_tRPPositionRelativeGeodetic->deltaLatitude; tRPPositionRelativeGeodetic->delta_longitude = f1_tRPPositionRelativeGeodetic->deltaLongitude; tRPPositionRelativeGeodetic->delta_height = f1_tRPPositionRelativeGeodetic->deltaHeight; F1AP_LocationUncertainty_t *f1_locationUncertainty_g = &f1_tRPPositionRelativeGeodetic->locationUncertainty; f1ap_location_uncertainty_t *locationUncertainty_g = &tRPPositionRelativeGeodetic->location_uncertainty; locationUncertainty_g->horizontal_uncertainty = f1_locationUncertainty_g->horizontalUncertainty; locationUncertainty_g->horizontal_confidence = f1_locationUncertainty_g->horizontalConfidence; locationUncertainty_g->vertical_uncertainty = f1_locationUncertainty_g->verticalUncertainty; locationUncertainty_g->vertical_confidence = f1_locationUncertainty_g->verticalConfidence; break; case F1AP_TRPReferencePointType_PR_tRPPositionRelativeCartesian: out->present = F1AP_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_CARTESIAN; F1AP_RelativeCartesianLocation_t *f1_tRPPositionRelativeCartesian = in->choice.tRPPositionRelativeCartesian; f1ap_relative_cartesian_location_t *tRPPositionRelativeCartesian = &out->choice.trp_position_relative_cartesian; tRPPositionRelativeCartesian->xyz_unit = f1_tRPPositionRelativeCartesian->xYZunit; tRPPositionRelativeCartesian->xvalue = f1_tRPPositionRelativeCartesian->xvalue; tRPPositionRelativeCartesian->yvalue = f1_tRPPositionRelativeCartesian->yvalue; tRPPositionRelativeCartesian->zvalue = f1_tRPPositionRelativeCartesian->zvalue; F1AP_LocationUncertainty_t *f1_locationUncertainty_c = &f1_tRPPositionRelativeCartesian->locationUncertainty; f1ap_location_uncertainty_t *locationUncertainty_c = &tRPPositionRelativeCartesian->location_uncertainty; locationUncertainty_c->horizontal_uncertainty = f1_locationUncertainty_c->horizontalUncertainty; locationUncertainty_c->horizontal_confidence = f1_locationUncertainty_c->horizontalConfidence; locationUncertainty_c->vertical_uncertainty = f1_locationUncertainty_c->verticalUncertainty; locationUncertainty_c->vertical_confidence = f1_locationUncertainty_c->verticalConfidence; break; default: AssertFatal(false, "illegal trp reference point type entry %d\n", in->present); break; } } static void decode_trp_ha_pos(const F1AP_NGRANHighAccuracyAccessPointPosition_t *in, f1ap_ngran_high_accuracy_access_point_position_t *out) { out->latitude = in->latitude; out->longitude = in->longitude; out->altitude = in->altitude; out->uncertainty_semi_major = in->uncertaintySemi_major; out->uncertainty_semi_minor = in->uncertaintySemi_minor; out->orientation_of_major_axis = in->orientationOfMajorAxis; out->horizontal_confidence = in->horizontalConfidence; out->uncertainty_altitude = in->uncertaintyAltitude; out->vertical_confidence = in->verticalConfidence; } static void decode_geographical_coordinates(const F1AP_GeographicalCoordinates_t *in, f1ap_geographical_coordinates_t *out) { const F1AP_TRPPositionDefinitionType_t *f1_trp_pos_def_type = &in->tRPPositionDefinitionType; f1ap_trp_position_definition_type_t *trp_pos_def_type = &out->trp_position_definition_type; switch (f1_trp_pos_def_type->present) { case F1AP_TRPPositionDefinitionType_PR_NOTHING: trp_pos_def_type->present = F1AP_TRP_POSITION_DEFINITION_TYPE_PR_NOTHING; break; case F1AP_TRPPositionDefinitionType_PR_direct: trp_pos_def_type->present = F1AP_TRP_POSITION_DEFINITION_TYPE_PR_DIRECT; F1AP_TRPPositionDirect_t *f1_direct = f1_trp_pos_def_type->choice.direct; f1ap_trp_position_direct_t *direct = &trp_pos_def_type->choice.direct; if (f1_direct->accuracy.present == F1AP_TRPPositionDirectAccuracy_PR_tRPPosition) { direct->accuracy.present = F1AP_TRP_POSITION_DIRECT_ACCURACY_PR_TRPPOSITION; f1ap_access_point_position_t *trp_pos = &direct->accuracy.choice.trp_position; F1AP_AccessPointPosition_t *f1_trp_pos = f1_direct->accuracy.choice.tRPPosition; trp_pos->latitude_sign = f1_trp_pos->latitudeSign; trp_pos->latitude = f1_trp_pos->latitude; trp_pos->longitude = f1_trp_pos->longitude; trp_pos->direction_of_altitude = f1_trp_pos->directionOfAltitude; trp_pos->altitude = f1_trp_pos->altitude; trp_pos->uncertainty_semi_major = f1_trp_pos->uncertaintySemi_major; trp_pos->uncertainty_semi_minor = f1_trp_pos->uncertaintySemi_minor; trp_pos->orientation_of_major_axis = f1_trp_pos->orientationOfMajorAxis; trp_pos->uncertainty_altitude = f1_trp_pos->uncertaintyAltitude; trp_pos->confidence = f1_trp_pos->confidence; } else if (f1_direct->accuracy.present == F1AP_TRPPositionDirectAccuracy_PR_tRPHAposition) { direct->accuracy.present = F1AP_TRP_POSITION_DIRECT_ACCURACY_PR_TRPHAPOSITION; f1ap_ngran_high_accuracy_access_point_position_t *trp_ha_pos = &direct->accuracy.choice.trp_HAposition; F1AP_NGRANHighAccuracyAccessPointPosition_t *f1_trp_ha_pos = f1_direct->accuracy.choice.tRPHAposition; decode_trp_ha_pos(f1_trp_ha_pos, trp_ha_pos); } else { AssertFatal(false, "illegal direct accuracy entry %d\n", direct->accuracy.present); } break; case F1AP_TRPPositionDefinitionType_PR_referenced: trp_pos_def_type->present = F1AP_TRP_POSITION_DEFINITION_TYPE_PR_REFERENCED; F1AP_TRPPositionReferenced_t *f1_referenced = f1_trp_pos_def_type->choice.referenced; f1ap_trp_position_referenced_t *referenced = &trp_pos_def_type->choice.referenced; F1AP_ReferencePoint_t *f1_referencePoint = &f1_referenced->referencePoint; f1ap_reference_point_t *referencePoint = &referenced->reference_point; if (f1_referencePoint->present == F1AP_ReferencePoint_PR_coordinateID) { referencePoint->present = F1AP_REFERENCE_POINT_PR_COORDINATEID; referencePoint->choice.coordinate_id = f1_referencePoint->choice.coordinateID; } else if (f1_referencePoint->present == F1AP_ReferencePoint_PR_referencePointCoordinate) { referencePoint->present = F1AP_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATE; f1ap_access_point_position_t *referencePointCoordinate = &referencePoint->choice.reference_point_coordinate; F1AP_AccessPointPosition_t *f1_referencePointCoordinate = f1_referencePoint->choice.referencePointCoordinate; referencePointCoordinate->latitude_sign = f1_referencePointCoordinate->latitudeSign; referencePointCoordinate->latitude = f1_referencePointCoordinate->latitude; referencePointCoordinate->longitude = f1_referencePointCoordinate->longitude; referencePointCoordinate->direction_of_altitude = f1_referencePointCoordinate->directionOfAltitude; referencePointCoordinate->altitude = f1_referencePointCoordinate->altitude; referencePointCoordinate->uncertainty_semi_major = f1_referencePointCoordinate->uncertaintySemi_major; referencePointCoordinate->uncertainty_semi_minor = f1_referencePointCoordinate->uncertaintySemi_minor; referencePointCoordinate->orientation_of_major_axis = f1_referencePointCoordinate->orientationOfMajorAxis; referencePointCoordinate->uncertainty_altitude = f1_referencePointCoordinate->uncertaintyAltitude; referencePointCoordinate->confidence = f1_referencePointCoordinate->confidence; } else if (f1_referencePoint->present == F1AP_ReferencePoint_PR_referencePointCoordinateHA) { referencePoint->present = F1AP_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATEHA; f1ap_ngran_high_accuracy_access_point_position_t *referencePointCoordinateHA = &referencePoint->choice.reference_point_coordinateHA; F1AP_NGRANHighAccuracyAccessPointPosition_t *f1_referencePointCoordinateHA = f1_referencePoint->choice.referencePointCoordinateHA; decode_trp_ha_pos(f1_referencePointCoordinateHA, referencePointCoordinateHA); } else { AssertFatal(false, "illegal reference point entry %d\n", referencePoint->present); } F1AP_TRPReferencePointType_t *f1_referencePointType = &f1_referenced->referencePointType; f1ap_trp_reference_point_type_t *referencePointType = &referenced->reference_point_type; decode_reference_point_type(f1_referencePointType, referencePointType); break; default: AssertFatal(false, "illegal Geographical Coordinates entry\n"); break; } } static f1ap_trp_reference_point_type_t cp_encode_reference_point_type(const f1ap_trp_reference_point_type_t *in) { f1ap_trp_reference_point_type_t out = {0}; switch (in->present) { case F1AP_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_GEODETIC: out.present = F1AP_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_GEODETIC; const f1ap_relative_geodetic_location_t *f1_tRPPositionRelativeGeodetic = &in->choice.trp_position_relative_geodetic; f1ap_relative_geodetic_location_t *tRPPositionRelativeGeodetic = &out.choice.trp_position_relative_geodetic; tRPPositionRelativeGeodetic->milli_arc_second_units = f1_tRPPositionRelativeGeodetic->milli_arc_second_units; tRPPositionRelativeGeodetic->height_units = f1_tRPPositionRelativeGeodetic->height_units; tRPPositionRelativeGeodetic->delta_latitude = f1_tRPPositionRelativeGeodetic->delta_latitude; tRPPositionRelativeGeodetic->delta_longitude = f1_tRPPositionRelativeGeodetic->delta_longitude; tRPPositionRelativeGeodetic->delta_height = f1_tRPPositionRelativeGeodetic->delta_height; const f1ap_location_uncertainty_t *f1_locationUncertainty_g = &f1_tRPPositionRelativeGeodetic->location_uncertainty; f1ap_location_uncertainty_t *locationUncertainty_g = &tRPPositionRelativeGeodetic->location_uncertainty; locationUncertainty_g->horizontal_uncertainty = f1_locationUncertainty_g->horizontal_uncertainty; locationUncertainty_g->horizontal_confidence = f1_locationUncertainty_g->horizontal_confidence; locationUncertainty_g->vertical_uncertainty = f1_locationUncertainty_g->vertical_uncertainty; locationUncertainty_g->vertical_confidence = f1_locationUncertainty_g->vertical_confidence; break; case F1AP_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_CARTESIAN: out.present = F1AP_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_CARTESIAN; const f1ap_relative_cartesian_location_t *f1_tRPPositionRelativeCartesian = &in->choice.trp_position_relative_cartesian; f1ap_relative_cartesian_location_t *tRPPositionRelativeCartesian = &out.choice.trp_position_relative_cartesian; tRPPositionRelativeCartesian->xyz_unit = f1_tRPPositionRelativeCartesian->xyz_unit; tRPPositionRelativeCartesian->xvalue = f1_tRPPositionRelativeCartesian->xvalue; tRPPositionRelativeCartesian->yvalue = f1_tRPPositionRelativeCartesian->yvalue; tRPPositionRelativeCartesian->zvalue = f1_tRPPositionRelativeCartesian->zvalue; const f1ap_location_uncertainty_t *f1_locationUncertainty_c = &f1_tRPPositionRelativeCartesian->location_uncertainty; f1ap_location_uncertainty_t *locationUncertainty_c = &tRPPositionRelativeCartesian->location_uncertainty; locationUncertainty_c->horizontal_uncertainty = f1_locationUncertainty_c->horizontal_uncertainty; locationUncertainty_c->horizontal_confidence = f1_locationUncertainty_c->horizontal_confidence; locationUncertainty_c->vertical_uncertainty = f1_locationUncertainty_c->vertical_uncertainty; locationUncertainty_c->vertical_confidence = f1_locationUncertainty_c->vertical_confidence; break; default: AssertFatal(false, "illegal trp reference point type entry %d\n", in->present); break; } return out; } static f1ap_ngran_high_accuracy_access_point_position_t cp_trp_ha_pos(const f1ap_ngran_high_accuracy_access_point_position_t *in) { f1ap_ngran_high_accuracy_access_point_position_t out = {0}; out.latitude = in->latitude; out.longitude = in->longitude; out.altitude = in->altitude; out.uncertainty_semi_major = in->uncertainty_semi_major; out.uncertainty_semi_minor = in->uncertainty_semi_minor; out.orientation_of_major_axis = in->orientation_of_major_axis; out.horizontal_confidence = in->horizontal_confidence; out.uncertainty_altitude = in->uncertainty_altitude; out.vertical_confidence = in->vertical_confidence; return out; } static f1ap_geographical_coordinates_t cp_geographical_coordinates(const f1ap_geographical_coordinates_t *in) { f1ap_geographical_coordinates_t out = {0}; const f1ap_trp_position_definition_type_t *f1_trp_pos_def_type = &in->trp_position_definition_type; f1ap_trp_position_definition_type_t *trp_pos_def_type = &out.trp_position_definition_type; switch (f1_trp_pos_def_type->present) { case F1AP_TRP_POSITION_DEFINITION_TYPE_PR_NOTHING: trp_pos_def_type->present = F1AP_TRP_POSITION_DEFINITION_TYPE_PR_NOTHING; break; case F1AP_TRP_POSITION_DEFINITION_TYPE_PR_DIRECT: trp_pos_def_type->present = F1AP_TRP_POSITION_DEFINITION_TYPE_PR_DIRECT; const f1ap_trp_position_direct_t *f1_direct = &f1_trp_pos_def_type->choice.direct; f1ap_trp_position_direct_t *direct = &trp_pos_def_type->choice.direct; if (f1_direct->accuracy.present == F1AP_TRP_POSITION_DIRECT_ACCURACY_PR_TRPPOSITION) { direct->accuracy.present = F1AP_TRP_POSITION_DIRECT_ACCURACY_PR_TRPPOSITION; f1ap_access_point_position_t *trp_pos = &direct->accuracy.choice.trp_position; const f1ap_access_point_position_t *f1_trp_pos = &f1_direct->accuracy.choice.trp_position; trp_pos->latitude_sign = f1_trp_pos->latitude_sign; trp_pos->latitude = f1_trp_pos->latitude; trp_pos->longitude = f1_trp_pos->longitude; trp_pos->direction_of_altitude = f1_trp_pos->direction_of_altitude; trp_pos->altitude = f1_trp_pos->altitude; trp_pos->uncertainty_semi_major = f1_trp_pos->uncertainty_semi_major; trp_pos->uncertainty_semi_minor = f1_trp_pos->uncertainty_semi_minor; trp_pos->orientation_of_major_axis = f1_trp_pos->orientation_of_major_axis; trp_pos->uncertainty_altitude = f1_trp_pos->uncertainty_altitude; trp_pos->confidence = f1_trp_pos->confidence; } else if (f1_direct->accuracy.present == F1AP_TRP_POSITION_DIRECT_ACCURACY_PR_TRPHAPOSITION) { direct->accuracy.present = F1AP_TRP_POSITION_DIRECT_ACCURACY_PR_TRPHAPOSITION; f1ap_ngran_high_accuracy_access_point_position_t *trp_ha_pos = &direct->accuracy.choice.trp_HAposition; const f1ap_ngran_high_accuracy_access_point_position_t *f1_trp_ha_pos = &f1_direct->accuracy.choice.trp_HAposition; *trp_ha_pos = cp_trp_ha_pos(f1_trp_ha_pos); } else { AssertFatal(false, "illegal direct accuracy entry %d\n", direct->accuracy.present); } break; case F1AP_TRP_POSITION_DEFINITION_TYPE_PR_REFERENCED: trp_pos_def_type->present = F1AP_TRP_POSITION_DEFINITION_TYPE_PR_REFERENCED; const f1ap_trp_position_referenced_t *f1_referenced = &f1_trp_pos_def_type->choice.referenced; f1ap_trp_position_referenced_t *referenced = &trp_pos_def_type->choice.referenced; const f1ap_reference_point_t *f1_referencePoint = &f1_referenced->reference_point; f1ap_reference_point_t *referencePoint = &referenced->reference_point; if (f1_referencePoint->present == F1AP_REFERENCE_POINT_PR_COORDINATEID) { referencePoint->present = F1AP_REFERENCE_POINT_PR_COORDINATEID; referencePoint->choice.coordinate_id = f1_referencePoint->choice.coordinate_id; } else if (f1_referencePoint->present == F1AP_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATE) { referencePoint->present = F1AP_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATE; f1ap_access_point_position_t *referencePointCoordinate = &referencePoint->choice.reference_point_coordinate; const f1ap_access_point_position_t *f1_referencePointCoordinate = &f1_referencePoint->choice.reference_point_coordinate; referencePointCoordinate->latitude_sign = f1_referencePointCoordinate->latitude_sign; referencePointCoordinate->latitude = f1_referencePointCoordinate->latitude; referencePointCoordinate->longitude = f1_referencePointCoordinate->longitude; referencePointCoordinate->direction_of_altitude = f1_referencePointCoordinate->direction_of_altitude; referencePointCoordinate->altitude = f1_referencePointCoordinate->altitude; referencePointCoordinate->uncertainty_semi_major = f1_referencePointCoordinate->uncertainty_semi_major; referencePointCoordinate->uncertainty_semi_minor = f1_referencePointCoordinate->uncertainty_semi_minor; referencePointCoordinate->orientation_of_major_axis = f1_referencePointCoordinate->orientation_of_major_axis; referencePointCoordinate->uncertainty_altitude = f1_referencePointCoordinate->uncertainty_altitude; referencePointCoordinate->confidence = f1_referencePointCoordinate->confidence; } else if (f1_referencePoint->present == F1AP_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATEHA) { referencePoint->present = F1AP_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATEHA; f1ap_ngran_high_accuracy_access_point_position_t *referencePointCoordinateHA = &referencePoint->choice.reference_point_coordinateHA; const f1ap_ngran_high_accuracy_access_point_position_t *f1_referencePointCoordinateHA = &f1_referencePoint->choice.reference_point_coordinateHA; *referencePointCoordinateHA = cp_trp_ha_pos(f1_referencePointCoordinateHA); } else { AssertFatal(false, "illegal reference point entry %d\n", referencePoint->present); } const f1ap_trp_reference_point_type_t *f1_referencePointType = &f1_referenced->reference_point_type; f1ap_trp_reference_point_type_t *referencePointType = &referenced->reference_point_type; *referencePointType = cp_encode_reference_point_type(f1_referencePointType); break; default: AssertFatal(false, "illegal Geographical Coordinates entry\n"); break; } return out; } static bool eq_reference_point_type(const f1ap_trp_reference_point_type_t *f1_referencePointType, const f1ap_trp_reference_point_type_t *referencePointType) { _F1_EQ_CHECK_INT(f1_referencePointType->present, referencePointType->present); switch (f1_referencePointType->present) { case F1AP_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_GEODETIC: { const f1ap_relative_geodetic_location_t *f1_tRPPositionRelativeGeodetic = &f1_referencePointType->choice.trp_position_relative_geodetic; const f1ap_relative_geodetic_location_t *tRPPositionRelativeGeodetic = &referencePointType->choice.trp_position_relative_geodetic; _F1_EQ_CHECK_LONG(tRPPositionRelativeGeodetic->milli_arc_second_units, f1_tRPPositionRelativeGeodetic->milli_arc_second_units); _F1_EQ_CHECK_LONG(tRPPositionRelativeGeodetic->height_units, f1_tRPPositionRelativeGeodetic->height_units); _F1_EQ_CHECK_LONG(tRPPositionRelativeGeodetic->delta_latitude, f1_tRPPositionRelativeGeodetic->delta_latitude); _F1_EQ_CHECK_LONG(tRPPositionRelativeGeodetic->delta_longitude, f1_tRPPositionRelativeGeodetic->delta_longitude); _F1_EQ_CHECK_LONG(tRPPositionRelativeGeodetic->delta_height, f1_tRPPositionRelativeGeodetic->delta_height); const f1ap_location_uncertainty_t *f1_locationUncertainty_g = &f1_tRPPositionRelativeGeodetic->location_uncertainty; const f1ap_location_uncertainty_t *locationUncertainty_g = &tRPPositionRelativeGeodetic->location_uncertainty; _F1_EQ_CHECK_LONG(locationUncertainty_g->horizontal_uncertainty, f1_locationUncertainty_g->horizontal_uncertainty); _F1_EQ_CHECK_LONG(locationUncertainty_g->horizontal_confidence, f1_locationUncertainty_g->horizontal_confidence); _F1_EQ_CHECK_LONG(locationUncertainty_g->vertical_uncertainty, f1_locationUncertainty_g->vertical_uncertainty); _F1_EQ_CHECK_LONG(locationUncertainty_g->vertical_confidence, f1_locationUncertainty_g->vertical_confidence); break; } case F1AP_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_CARTESIAN: { const f1ap_relative_cartesian_location_t *f1_tRPPositionRelativeCartesian = &f1_referencePointType->choice.trp_position_relative_cartesian; const f1ap_relative_cartesian_location_t *tRPPositionRelativeCartesian = &referencePointType->choice.trp_position_relative_cartesian; _F1_EQ_CHECK_LONG(tRPPositionRelativeCartesian->xyz_unit, f1_tRPPositionRelativeCartesian->xyz_unit); _F1_EQ_CHECK_LONG(tRPPositionRelativeCartesian->xvalue, f1_tRPPositionRelativeCartesian->xvalue); _F1_EQ_CHECK_LONG(tRPPositionRelativeCartesian->yvalue, f1_tRPPositionRelativeCartesian->yvalue); _F1_EQ_CHECK_LONG(tRPPositionRelativeCartesian->zvalue, f1_tRPPositionRelativeCartesian->zvalue); const f1ap_location_uncertainty_t *f1_locationUncertainty_c = &f1_tRPPositionRelativeCartesian->location_uncertainty; const f1ap_location_uncertainty_t *locationUncertainty_c = &tRPPositionRelativeCartesian->location_uncertainty; _F1_EQ_CHECK_LONG(locationUncertainty_c->horizontal_uncertainty, f1_locationUncertainty_c->horizontal_uncertainty); _F1_EQ_CHECK_LONG(locationUncertainty_c->horizontal_confidence, f1_locationUncertainty_c->horizontal_confidence); _F1_EQ_CHECK_LONG(locationUncertainty_c->vertical_uncertainty, f1_locationUncertainty_c->vertical_uncertainty); _F1_EQ_CHECK_LONG(locationUncertainty_c->vertical_confidence, f1_locationUncertainty_c->vertical_confidence); break; } default: AssertError(false, return false, "illegal trp reference point type entry %d\n", f1_referencePointType->present); break; } return true; } static bool eq_trp_ha_pos(const f1ap_ngran_high_accuracy_access_point_position_t *trp_ha_pos, const f1ap_ngran_high_accuracy_access_point_position_t *f1_trp_ha_pos) { _F1_EQ_CHECK_LONG(trp_ha_pos->latitude, f1_trp_ha_pos->latitude); _F1_EQ_CHECK_LONG(trp_ha_pos->longitude, f1_trp_ha_pos->longitude); _F1_EQ_CHECK_LONG(trp_ha_pos->altitude, f1_trp_ha_pos->altitude); _F1_EQ_CHECK_LONG(trp_ha_pos->uncertainty_semi_major, f1_trp_ha_pos->uncertainty_semi_major); _F1_EQ_CHECK_LONG(trp_ha_pos->uncertainty_semi_minor, f1_trp_ha_pos->uncertainty_semi_minor); _F1_EQ_CHECK_LONG(trp_ha_pos->orientation_of_major_axis, f1_trp_ha_pos->orientation_of_major_axis); _F1_EQ_CHECK_LONG(trp_ha_pos->horizontal_confidence, f1_trp_ha_pos->horizontal_confidence); _F1_EQ_CHECK_LONG(trp_ha_pos->uncertainty_altitude, f1_trp_ha_pos->uncertainty_altitude); _F1_EQ_CHECK_LONG(trp_ha_pos->vertical_confidence, f1_trp_ha_pos->vertical_confidence); return true; } static bool eq_geographical_coordinates(const f1ap_geographical_coordinates_t *in, const f1ap_geographical_coordinates_t *out) { const f1ap_trp_position_definition_type_t *f1_trp_pos_def_type = &in->trp_position_definition_type; const f1ap_trp_position_definition_type_t *trp_pos_def_type = &out->trp_position_definition_type; _F1_EQ_CHECK_INT(f1_trp_pos_def_type->present, trp_pos_def_type->present); switch (f1_trp_pos_def_type->present) { case F1AP_TRP_POSITION_DEFINITION_TYPE_PR_NOTHING: // nothing to check break; case F1AP_TRP_POSITION_DEFINITION_TYPE_PR_DIRECT: { const f1ap_trp_position_direct_t *f1_direct = &f1_trp_pos_def_type->choice.direct; const f1ap_trp_position_direct_t *direct = &trp_pos_def_type->choice.direct; _F1_EQ_CHECK_INT(f1_direct->accuracy.present, direct->accuracy.present); if (f1_direct->accuracy.present == F1AP_TRP_POSITION_DIRECT_ACCURACY_PR_TRPPOSITION) { const f1ap_access_point_position_t *trp_pos = &direct->accuracy.choice.trp_position; const f1ap_access_point_position_t *f1_trp_pos = &f1_direct->accuracy.choice.trp_position; _F1_EQ_CHECK_LONG(trp_pos->latitude_sign, f1_trp_pos->latitude_sign); _F1_EQ_CHECK_LONG(trp_pos->latitude, f1_trp_pos->latitude); _F1_EQ_CHECK_LONG(trp_pos->longitude, f1_trp_pos->longitude); _F1_EQ_CHECK_LONG(trp_pos->direction_of_altitude, f1_trp_pos->direction_of_altitude); _F1_EQ_CHECK_LONG(trp_pos->altitude, f1_trp_pos->altitude); _F1_EQ_CHECK_LONG(trp_pos->uncertainty_semi_major, f1_trp_pos->uncertainty_semi_major); _F1_EQ_CHECK_LONG(trp_pos->uncertainty_semi_minor, f1_trp_pos->uncertainty_semi_minor); _F1_EQ_CHECK_LONG(trp_pos->orientation_of_major_axis, f1_trp_pos->orientation_of_major_axis); _F1_EQ_CHECK_LONG(trp_pos->uncertainty_altitude, f1_trp_pos->uncertainty_altitude); _F1_EQ_CHECK_LONG(trp_pos->confidence, f1_trp_pos->confidence); } else if (f1_direct->accuracy.present == F1AP_TRP_POSITION_DIRECT_ACCURACY_PR_TRPHAPOSITION) { const f1ap_ngran_high_accuracy_access_point_position_t *trp_ha_pos = &direct->accuracy.choice.trp_HAposition; const f1ap_ngran_high_accuracy_access_point_position_t *f1_trp_ha_pos = &f1_direct->accuracy.choice.trp_HAposition; _F1_CHECK_EXP(eq_trp_ha_pos(trp_ha_pos, f1_trp_ha_pos)); } else { AssertError(false, return false, "illegal direct accuracy entry %d\n", direct->accuracy.present); } break; } case F1AP_TRP_POSITION_DEFINITION_TYPE_PR_REFERENCED: { const f1ap_trp_position_referenced_t *f1_referenced = &f1_trp_pos_def_type->choice.referenced; const f1ap_trp_position_referenced_t *referenced = &trp_pos_def_type->choice.referenced; const f1ap_reference_point_t *f1_referencePoint = &f1_referenced->reference_point; const f1ap_reference_point_t *referencePoint = &referenced->reference_point; _F1_EQ_CHECK_INT(f1_referencePoint->present, referencePoint->present); if (f1_referencePoint->present == F1AP_REFERENCE_POINT_PR_COORDINATEID) { _F1_EQ_CHECK_LONG(referencePoint->choice.coordinate_id, f1_referencePoint->choice.coordinate_id); } else if (f1_referencePoint->present == F1AP_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATE) { const f1ap_access_point_position_t *referencePointCoordinate = &referencePoint->choice.reference_point_coordinate; const f1ap_access_point_position_t *f1_referencePointCoordinate = &f1_referencePoint->choice.reference_point_coordinate; _F1_EQ_CHECK_LONG(referencePointCoordinate->latitude_sign, f1_referencePointCoordinate->latitude_sign); _F1_EQ_CHECK_LONG(referencePointCoordinate->latitude, f1_referencePointCoordinate->latitude); _F1_EQ_CHECK_LONG(referencePointCoordinate->longitude, f1_referencePointCoordinate->longitude); _F1_EQ_CHECK_LONG(referencePointCoordinate->direction_of_altitude, f1_referencePointCoordinate->direction_of_altitude); _F1_EQ_CHECK_LONG(referencePointCoordinate->altitude, f1_referencePointCoordinate->altitude); _F1_EQ_CHECK_LONG(referencePointCoordinate->uncertainty_semi_major, f1_referencePointCoordinate->uncertainty_semi_major); _F1_EQ_CHECK_LONG(referencePointCoordinate->uncertainty_semi_minor, f1_referencePointCoordinate->uncertainty_semi_minor); _F1_EQ_CHECK_LONG(referencePointCoordinate->orientation_of_major_axis, f1_referencePointCoordinate->orientation_of_major_axis); _F1_EQ_CHECK_LONG(referencePointCoordinate->uncertainty_altitude, f1_referencePointCoordinate->uncertainty_altitude); _F1_EQ_CHECK_LONG(referencePointCoordinate->confidence, f1_referencePointCoordinate->confidence); } else if (f1_referencePoint->present == F1AP_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATEHA) { const f1ap_ngran_high_accuracy_access_point_position_t *referencePointCoordinateHA = &referencePoint->choice.reference_point_coordinateHA; const f1ap_ngran_high_accuracy_access_point_position_t *f1_referencePointCoordinateHA = &f1_referencePoint->choice.reference_point_coordinateHA; _F1_CHECK_EXP(eq_trp_ha_pos(referencePointCoordinateHA, f1_referencePointCoordinateHA)); } else { AssertError(false, return false, "illegal reference point entry %d\n", referencePoint->present); } const f1ap_trp_reference_point_type_t *f1_referencePointType = &f1_referenced->reference_point_type; const f1ap_trp_reference_point_type_t *referencePointType = &referenced->reference_point_type; _F1_CHECK_EXP(eq_reference_point_type(f1_referencePointType, referencePointType)); break; } default: AssertError(false, return false, "illegal Geographical Coordinates entry\n"); break; } return true; } static F1AP_TRPInformationTypeResponseItem_t encode_trp_info_type_response_item(const f1ap_trp_information_type_response_item_t *in) { F1AP_TRPInformationTypeResponseItem_t out = {0}; switch (in->present) { case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NOTHING: out.present = F1AP_TRPInformationTypeResponseItem_PR_NOTHING; break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PCI_NR: out.present = F1AP_TRPInformationTypeResponseItem_PR_pCI_NR; out.choice.pCI_NR = in->choice.pci_nr; break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NG_RAN_CGI: out.present = F1AP_TRPInformationTypeResponseItem_PR_nG_RAN_CGI; asn1cCalloc(out.choice.nG_RAN_CGI, nG_RAN_CGI); MCC_MNC_TO_PLMNID(in->choice.ng_ran_cgi.plmn.mcc, in->choice.ng_ran_cgi.plmn.mnc, in->choice.ng_ran_cgi.plmn.mnc_digit_length, &(nG_RAN_CGI->pLMN_Identity)); NR_CELL_ID_TO_BIT_STRING(in->choice.ng_ran_cgi.nr_cellid, &(nG_RAN_CGI->nRCellIdentity)); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NRARFCN: out.present = F1AP_TRPInformationTypeResponseItem_PR_nRARFCN; out.choice.nRARFCN = in->choice.nr_arfcn; break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PRSCONFIGURATION: out.present = F1AP_TRPInformationTypeResponseItem_PR_pRSConfiguration; AssertFatal(false, "TRP information type response item PRS configuration unsupported\n"); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SSBINFORMATION: out.present = F1AP_TRPInformationTypeResponseItem_PR_sSBinformation; AssertFatal(false, "TRP information type response item SSB Information unsupported\n"); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SFNINITIALISATIONTIME: out.present = F1AP_TRPInformationTypeResponseItem_PR_sFNInitialisationTime; AssertFatal(false, "TRP information type response item SFN Initialization Time unsupported\n"); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SPATIALDIRECTIONINFORMATION: out.present = F1AP_TRPInformationTypeResponseItem_PR_spatialDirectionInformation; AssertFatal(false, "TRP information type response item Spatial Direction Information unsupported\n"); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_GEOGRAPHICALCOORDINATES: out.present = F1AP_TRPInformationTypeResponseItem_PR_geographicalCoordinates; asn1cCalloc(out.choice.geographicalCoordinates, f1_geo_coord); f1ap_geographical_coordinates_t geo_coord = in->choice.geographical_coordinates; *f1_geo_coord = encode_geographical_coordinates(&geo_coord); break; default: AssertFatal(false, "received illegal trp information type response item %d\n", in->present); break; } return out; } static void decode_trp_info_type_response_item(const F1AP_TRPInformationTypeResponseItem_t *in, f1ap_trp_information_type_response_item_t *out) { switch (in->present) { case F1AP_TRPInformationTypeResponseItem_PR_NOTHING: out->present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NOTHING; break; case F1AP_TRPInformationTypeResponseItem_PR_pCI_NR: out->present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PCI_NR; out->choice.pci_nr = in->choice.pCI_NR; break; case F1AP_TRPInformationTypeResponseItem_PR_nG_RAN_CGI: out->present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NG_RAN_CGI; // NR CGI (M) PLMNID_TO_MCC_MNC(&(in->choice.nG_RAN_CGI->pLMN_Identity), out->choice.ng_ran_cgi.plmn.mcc, out->choice.ng_ran_cgi.plmn.mnc, out->choice.ng_ran_cgi.plmn.mnc_digit_length); // NR Cell Identity (M) BIT_STRING_TO_NR_CELL_IDENTITY(&in->choice.nG_RAN_CGI->nRCellIdentity, out->choice.ng_ran_cgi.nr_cellid); break; case F1AP_TRPInformationTypeResponseItem_PR_nRARFCN: out->present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NRARFCN; out->choice.nr_arfcn = in->choice.nRARFCN; break; case F1AP_TRPInformationTypeResponseItem_PR_pRSConfiguration: out->present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PRSCONFIGURATION; AssertFatal(false, "TRP information type response item PRS configuration unsupported\n"); break; case F1AP_TRPInformationTypeResponseItem_PR_sSBinformation: out->present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SSBINFORMATION; AssertFatal(false, "TRP information type response item SSB Information unsupported\n"); break; case F1AP_TRPInformationTypeResponseItem_PR_sFNInitialisationTime: out->present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SFNINITIALISATIONTIME; AssertFatal(false, "TRP information type response item SFN Initialization Time unsupported\n"); break; case F1AP_TRPInformationTypeResponseItem_PR_spatialDirectionInformation: out->present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SPATIALDIRECTIONINFORMATION; AssertFatal(false, "TRP information type response item Spatial Direction Information unsupported\n"); break; case F1AP_TRPInformationTypeResponseItem_PR_geographicalCoordinates: out->present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_GEOGRAPHICALCOORDINATES; decode_geographical_coordinates(in->choice.geographicalCoordinates, &out->choice.geographical_coordinates); break; default: AssertFatal(false, "received illegal trp information type response item %d\n", in->present); break; } } static f1ap_trp_information_type_response_item_t cp_trp_info_type_response_item(const f1ap_trp_information_type_response_item_t *in) { f1ap_trp_information_type_response_item_t out = {0}; switch (in->present) { case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NOTHING: out.present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NOTHING; break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PCI_NR: out.present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PCI_NR; out.choice.pci_nr = in->choice.pci_nr; break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NG_RAN_CGI: out.present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NG_RAN_CGI; out.choice.ng_ran_cgi.plmn.mcc = in->choice.ng_ran_cgi.plmn.mcc; out.choice.ng_ran_cgi.plmn.mnc = in->choice.ng_ran_cgi.plmn.mnc; out.choice.ng_ran_cgi.plmn.mnc_digit_length = in->choice.ng_ran_cgi.plmn.mnc_digit_length; out.choice.ng_ran_cgi.nr_cellid = in->choice.ng_ran_cgi.nr_cellid; break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NRARFCN: out.present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NRARFCN; out.choice.nr_arfcn = in->choice.nr_arfcn; break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PRSCONFIGURATION: out.present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PRSCONFIGURATION; AssertFatal(false, "TRP information type response item PRS configuration unsupported\n"); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SSBINFORMATION: out.present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SSBINFORMATION; AssertFatal(false, "TRP information type response item SSB Information unsupported\n"); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SFNINITIALISATIONTIME: out.present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SFNINITIALISATIONTIME; AssertFatal(false, "TRP information type response item SFN Initialization Time unsupported\n"); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SPATIALDIRECTIONINFORMATION: out.present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SPATIALDIRECTIONINFORMATION; AssertFatal(false, "TRP information type response item Spatial Direction Information unsupported\n"); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_GEOGRAPHICALCOORDINATES: out.present = F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_GEOGRAPHICALCOORDINATES; out.choice.geographical_coordinates = cp_geographical_coordinates(&in->choice.geographical_coordinates); break; default: AssertFatal(false, "received illegal trp information type response item %d\n", in->present); break; } return out; } static bool eq_trp_info_type_response_item(const f1ap_trp_information_type_response_item_t *in, const f1ap_trp_information_type_response_item_t *out) { _F1_EQ_CHECK_INT(in->present, out->present); switch (in->present) { case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NOTHING: // nothing to check break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PCI_NR: _F1_EQ_CHECK_INT(in->choice.pci_nr, out->choice.pci_nr); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NG_RAN_CGI: _F1_EQ_CHECK_INT(in->choice.ng_ran_cgi.plmn.mcc, out->choice.ng_ran_cgi.plmn.mcc); _F1_EQ_CHECK_INT(in->choice.ng_ran_cgi.plmn.mnc, out->choice.ng_ran_cgi.plmn.mnc); _F1_EQ_CHECK_INT(in->choice.ng_ran_cgi.plmn.mnc_digit_length, out->choice.ng_ran_cgi.plmn.mnc_digit_length); _F1_EQ_CHECK_LONG(in->choice.ng_ran_cgi.nr_cellid, out->choice.ng_ran_cgi.nr_cellid); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NRARFCN: _F1_EQ_CHECK_INT(in->choice.nr_arfcn, out->choice.nr_arfcn); break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PRSCONFIGURATION: PRINT_ERROR("TRP information type response item PRS configuration unsupported\n"); return false; break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SSBINFORMATION: PRINT_ERROR("TRP information type response item SSB Information unsupported\n"); return false; break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SFNINITIALISATIONTIME: PRINT_ERROR("TRP information type response item SFN Initialization Time unsupported\n"); return false; break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SPATIALDIRECTIONINFORMATION: PRINT_ERROR("TRP information type response item Spatial Direction Information unsupported\n"); return false; break; case F1AP_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_GEOGRAPHICALCOORDINATES: _F1_CHECK_EXP(eq_geographical_coordinates(&in->choice.geographical_coordinates, &out->choice.geographical_coordinates)); break; default: PRINT_ERROR("received illegal trp information type response item %d\n", in->present); return false; break; } return true; } static F1AP_PosMeasurementResult_t encode_positioning_measurement_result(const f1ap_pos_measurement_result_t *posMeasurementResult) { F1AP_PosMeasurementResult_t f1_posMeasurementResult = {0}; for (int i = 0; i < posMeasurementResult->pos_measurement_result_item_length; i++) { asn1cSequenceAdd(f1_posMeasurementResult.list, F1AP_PosMeasurementResultItem_t, f1_pos_measurement_result_item); f1ap_pos_measurement_result_item_t *pos_measurement_result_item = &posMeasurementResult->pos_measurement_result_item[i]; // measuredResultsValue F1AP_MeasuredResultsValue_t *f1_measuredResultsValue = &f1_pos_measurement_result_item->measuredResultsValue; f1ap_measured_results_value_t *measuredResultsValue = &pos_measurement_result_item->measured_results_value; switch (measuredResultsValue->present) { case F1AP_MEASURED_RESULTS_VALUE_PR_NOTHING: f1_measuredResultsValue->present = F1AP_MeasuredResultsValue_PR_NOTHING; break; // Angle of Arrival case F1AP_MEASURED_RESULTS_VALUE_PR_UL_ANGLEOFARRIVAL: f1_measuredResultsValue->present = F1AP_MeasuredResultsValue_PR_uL_AngleOfArrival; asn1cCalloc(f1_measuredResultsValue->choice.uL_AngleOfArrival, f1_uL_AngleOfArrival); f1ap_ul_aoa_t *uL_AngleOfArrival = &measuredResultsValue->choice.ul_angle_of_arrival; f1_uL_AngleOfArrival->azimuthAoA = uL_AngleOfArrival->azimuth_aoa; if (uL_AngleOfArrival->zenith_aoa) { asn1cCalloc(f1_uL_AngleOfArrival->zenithAoA, f1_zenithAoA); *f1_zenithAoA = *uL_AngleOfArrival->zenith_aoa; } if (uL_AngleOfArrival->lcs_to_gcs_translation_aoa) { asn1cCalloc(f1_uL_AngleOfArrival->lCS_to_GCS_TranslationAoA, f1_lCS_to_GCS_TranslationAoA); f1ap_lcs_to_gcs_translationaoa_t *lCS_to_GCS_TranslationAoA = uL_AngleOfArrival->lcs_to_gcs_translation_aoa; f1_lCS_to_GCS_TranslationAoA->alpha = lCS_to_GCS_TranslationAoA->alpha; f1_lCS_to_GCS_TranslationAoA->beta = lCS_to_GCS_TranslationAoA->beta; f1_lCS_to_GCS_TranslationAoA->gamma = lCS_to_GCS_TranslationAoA->gamma; } break; // UL SRS RSRP case F1AP_MEASURED_RESULTS_VALUE_PR_UL_SRS_RSRP: f1_measuredResultsValue->present = F1AP_MeasuredResultsValue_PR_uL_SRS_RSRP; f1_measuredResultsValue->choice.uL_SRS_RSRP = measuredResultsValue->choice.ul_srs_rsrp; break; // UL RTOA case F1AP_MEASURED_RESULTS_VALUE_PR_UL_RTOA: f1_measuredResultsValue->present = F1AP_MeasuredResultsValue_PR_uL_RTOA; asn1cCalloc(f1_measuredResultsValue->choice.uL_RTOA, f1_uL_RTOA); f1ap_ul_rtoa_measurement_t *uL_RTOA = &measuredResultsValue->choice.ul_rtoa; f1ap_ul_rtoa_measurement_item_t *ul_rtoa_meas_item = &uL_RTOA->ul_rtoa_measurement_item; F1AP_UL_RTOA_MeasurementItem_t *f1_ul_rtoa_meas_item = &f1_uL_RTOA->uL_RTOA_MeasurementItem; switch (ul_rtoa_meas_item->present) { case F1AP_ULRTOAMEAS_PR_NOTHING: f1_ul_rtoa_meas_item->present = F1AP_UL_RTOA_MeasurementItem_PR_NOTHING; break; case F1AP_ULRTOAMEAS_PR_K0: f1_ul_rtoa_meas_item->present = F1AP_UL_RTOA_MeasurementItem_PR_k0; f1_ul_rtoa_meas_item->choice.k0 = ul_rtoa_meas_item->choice.k0; break; case F1AP_ULRTOAMEAS_PR_K1: f1_ul_rtoa_meas_item->present = F1AP_UL_RTOA_MeasurementItem_PR_k1; f1_ul_rtoa_meas_item->choice.k1 = ul_rtoa_meas_item->choice.k1; break; case F1AP_ULRTOAMEAS_PR_K2: f1_ul_rtoa_meas_item->present = F1AP_UL_RTOA_MeasurementItem_PR_k2; f1_ul_rtoa_meas_item->choice.k2 = ul_rtoa_meas_item->choice.k2; break; case F1AP_ULRTOAMEAS_PR_K3: f1_ul_rtoa_meas_item->present = F1AP_UL_RTOA_MeasurementItem_PR_k3; f1_ul_rtoa_meas_item->choice.k3 = ul_rtoa_meas_item->choice.k3; break; case F1AP_ULRTOAMEAS_PR_K4: f1_ul_rtoa_meas_item->present = F1AP_UL_RTOA_MeasurementItem_PR_k4; f1_ul_rtoa_meas_item->choice.k4 = ul_rtoa_meas_item->choice.k4; break; case F1AP_ULRTOAMEAS_PR_K5: f1_ul_rtoa_meas_item->present = F1AP_UL_RTOA_MeasurementItem_PR_k5; f1_ul_rtoa_meas_item->choice.k5 = ul_rtoa_meas_item->choice.k5; break; default: AssertFatal(false, "Illegal uL_RTOA_MeasurementItem %d\n", ul_rtoa_meas_item->present); break; } break; // gNB RX-TX Time Diff case F1AP_MEASURED_RESULTS_VALUE_PR_GNB_RXTXTIMEDIFF: f1_measuredResultsValue->present = F1AP_MeasuredResultsValue_PR_gNB_RxTxTimeDiff; asn1cCalloc(f1_measuredResultsValue->choice.gNB_RxTxTimeDiff, f1_gNB_RxTxTimeDiff); f1ap_gnb_rx_tx_time_diff_t *gNB_RxTxTimeDiff = &measuredResultsValue->choice.gnb_rx_tx_time_diff; f1ap_gnb_rx_tx_time_diff_meas_t *rx_tx_time_diff = &gNB_RxTxTimeDiff->rx_tx_time_diff; F1AP_GNBRxTxTimeDiffMeas_t *f1_rxTxTimeDiff = &f1_gNB_RxTxTimeDiff->rxTxTimeDiff; switch (rx_tx_time_diff->present) { case F1AP_GNBRXTXTIMEDIFFMEAS_PR_NOTHING: f1_rxTxTimeDiff->present = F1AP_GNBRxTxTimeDiffMeas_PR_NOTHING; break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K0: f1_rxTxTimeDiff->present = F1AP_GNBRxTxTimeDiffMeas_PR_k0; f1_rxTxTimeDiff->choice.k0 = rx_tx_time_diff->choice.k0; break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K1: f1_rxTxTimeDiff->present = F1AP_GNBRxTxTimeDiffMeas_PR_k1; f1_rxTxTimeDiff->choice.k1 = rx_tx_time_diff->choice.k1; break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K2: f1_rxTxTimeDiff->present = F1AP_GNBRxTxTimeDiffMeas_PR_k2; f1_rxTxTimeDiff->choice.k2 = rx_tx_time_diff->choice.k2; break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K3: f1_rxTxTimeDiff->present = F1AP_GNBRxTxTimeDiffMeas_PR_k3; f1_rxTxTimeDiff->choice.k3 = rx_tx_time_diff->choice.k3; break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K4: f1_rxTxTimeDiff->present = F1AP_GNBRxTxTimeDiffMeas_PR_k4; f1_rxTxTimeDiff->choice.k4 = rx_tx_time_diff->choice.k4; break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K5: f1_rxTxTimeDiff->present = F1AP_GNBRxTxTimeDiffMeas_PR_k5; f1_rxTxTimeDiff->choice.k5 = rx_tx_time_diff->choice.k5; break; default: AssertFatal(false, "Illegal rxTxTimeDiff value %d\n", rx_tx_time_diff->present); break; } break; default: AssertFatal(false, "Illegal measuredResultsValue %d\n", measuredResultsValue->present); break; } // timeStamp F1AP_TimeStamp_t *f1_timeStamp = &f1_pos_measurement_result_item->timeStamp; f1ap_time_stamp_t *timeStamp = &pos_measurement_result_item->time_stamp; f1_timeStamp->systemFrameNumber = timeStamp->system_frame_number; F1AP_TimeStampSlotIndex_t *f1_slotIndex = &f1_timeStamp->slotIndex; f1ap_time_stamp_slot_index_t *slot_index = &timeStamp->slot_index; switch (slot_index->present) { case F1AP_TIME_STAMP_SLOT_INDEX_PR_NOTHING: f1_slotIndex->present = F1AP_TimeStampSlotIndex_PR_NOTHING; break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_15: f1_slotIndex->present = F1AP_TimeStampSlotIndex_PR_sCS_15; f1_slotIndex->choice.sCS_15 = slot_index->choice.scs_15; break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_30: f1_slotIndex->present = F1AP_TimeStampSlotIndex_PR_sCS_30; f1_slotIndex->choice.sCS_30 = slot_index->choice.scs_30; break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_60: f1_slotIndex->present = F1AP_TimeStampSlotIndex_PR_sCS_60; f1_slotIndex->choice.sCS_60 = slot_index->choice.scs_60; break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_120: f1_slotIndex->present = F1AP_TimeStampSlotIndex_PR_sCS_120; f1_slotIndex->choice.sCS_120 = slot_index->choice.scs_120; break; default: AssertFatal(false, "Illegal slotIndex value %d\n", slot_index->present); break; } } return f1_posMeasurementResult; } static bool decode_positioning_measurement_result(F1AP_PosMeasurementResult_t *f1_posMeasurementResult, f1ap_pos_measurement_result_t *posMeasurementResult) { uint32_t pos_meas_result_length = f1_posMeasurementResult->list.count; posMeasurementResult->pos_measurement_result_item_length = pos_meas_result_length; posMeasurementResult->pos_measurement_result_item = calloc_or_fail(pos_meas_result_length, sizeof(*posMeasurementResult->pos_measurement_result_item)); for (int i = 0; i < pos_meas_result_length; i++) { F1AP_PosMeasurementResultItem_t *f1_pos_measurement_result_item = f1_posMeasurementResult->list.array[i]; f1ap_pos_measurement_result_item_t *pos_measurement_result_item = &posMeasurementResult->pos_measurement_result_item[i]; // measuredResultsValue F1AP_MeasuredResultsValue_t *f1_measuredResultsValue = &f1_pos_measurement_result_item->measuredResultsValue; f1ap_measured_results_value_t *measuredResultsValue = &pos_measurement_result_item->measured_results_value; switch (f1_measuredResultsValue->present) { case F1AP_MeasuredResultsValue_PR_NOTHING: measuredResultsValue->present = F1AP_MEASURED_RESULTS_VALUE_PR_NOTHING; break; // Angle of Arrival case F1AP_MeasuredResultsValue_PR_uL_AngleOfArrival: measuredResultsValue->present = F1AP_MEASURED_RESULTS_VALUE_PR_UL_ANGLEOFARRIVAL; F1AP_UL_AoA_t *f1_uL_AngleOfArrival = f1_measuredResultsValue->choice.uL_AngleOfArrival; f1ap_ul_aoa_t *uL_AngleOfArrival = &measuredResultsValue->choice.ul_angle_of_arrival; uL_AngleOfArrival->azimuth_aoa = f1_uL_AngleOfArrival->azimuthAoA; if (f1_uL_AngleOfArrival->zenithAoA) { uL_AngleOfArrival->zenith_aoa = calloc_or_fail(1, sizeof(*uL_AngleOfArrival->zenith_aoa)); *uL_AngleOfArrival->zenith_aoa = *f1_uL_AngleOfArrival->zenithAoA; } if (f1_uL_AngleOfArrival->lCS_to_GCS_TranslationAoA) { uL_AngleOfArrival->lcs_to_gcs_translation_aoa = calloc_or_fail(1, sizeof(*uL_AngleOfArrival->lcs_to_gcs_translation_aoa)); f1ap_lcs_to_gcs_translationaoa_t *lCS_to_GCS_TranslationAoA = uL_AngleOfArrival->lcs_to_gcs_translation_aoa; F1AP_LCS_to_GCS_TranslationAoA_t *f1_lCS_to_GCS_TranslationAoA = f1_uL_AngleOfArrival->lCS_to_GCS_TranslationAoA; lCS_to_GCS_TranslationAoA->alpha = f1_lCS_to_GCS_TranslationAoA->alpha; lCS_to_GCS_TranslationAoA->beta = f1_lCS_to_GCS_TranslationAoA->beta; lCS_to_GCS_TranslationAoA->gamma = f1_lCS_to_GCS_TranslationAoA->gamma; } break; // UL SRS RSRP case F1AP_MeasuredResultsValue_PR_uL_SRS_RSRP: measuredResultsValue->present = F1AP_MEASURED_RESULTS_VALUE_PR_UL_SRS_RSRP; measuredResultsValue->choice.ul_srs_rsrp = f1_measuredResultsValue->choice.uL_SRS_RSRP; break; // UL RTOA case F1AP_MeasuredResultsValue_PR_uL_RTOA: measuredResultsValue->present = F1AP_MEASURED_RESULTS_VALUE_PR_UL_RTOA; F1AP_UL_RTOA_Measurement_t *f1_uL_RTOA = f1_measuredResultsValue->choice.uL_RTOA; f1ap_ul_rtoa_measurement_t *uL_RTOA = &measuredResultsValue->choice.ul_rtoa; F1AP_UL_RTOA_MeasurementItem_t *f1_ul_rtoa_meas_item = &f1_uL_RTOA->uL_RTOA_MeasurementItem; f1ap_ul_rtoa_measurement_item_t *ul_rtoa_meas_item = &uL_RTOA->ul_rtoa_measurement_item; switch (f1_ul_rtoa_meas_item->present) { case F1AP_UL_RTOA_MeasurementItem_PR_NOTHING: ul_rtoa_meas_item->present = F1AP_ULRTOAMEAS_PR_NOTHING; break; case F1AP_UL_RTOA_MeasurementItem_PR_k0: ul_rtoa_meas_item->present = F1AP_ULRTOAMEAS_PR_K0; ul_rtoa_meas_item->choice.k0 = f1_ul_rtoa_meas_item->choice.k0; break; case F1AP_UL_RTOA_MeasurementItem_PR_k1: ul_rtoa_meas_item->present = F1AP_ULRTOAMEAS_PR_K1; ul_rtoa_meas_item->choice.k1 = f1_ul_rtoa_meas_item->choice.k1; break; case F1AP_UL_RTOA_MeasurementItem_PR_k2: ul_rtoa_meas_item->present = F1AP_ULRTOAMEAS_PR_K2; ul_rtoa_meas_item->choice.k2 = f1_ul_rtoa_meas_item->choice.k2; break; case F1AP_UL_RTOA_MeasurementItem_PR_k3: ul_rtoa_meas_item->present = F1AP_ULRTOAMEAS_PR_K3; ul_rtoa_meas_item->choice.k3 = f1_ul_rtoa_meas_item->choice.k3; break; case F1AP_UL_RTOA_MeasurementItem_PR_k4: ul_rtoa_meas_item->present = F1AP_ULRTOAMEAS_PR_K4; ul_rtoa_meas_item->choice.k4 = f1_ul_rtoa_meas_item->choice.k4; break; case F1AP_UL_RTOA_MeasurementItem_PR_k5: ul_rtoa_meas_item->present = F1AP_ULRTOAMEAS_PR_K5; ul_rtoa_meas_item->choice.k5 = f1_ul_rtoa_meas_item->choice.k5; break; default: AssertError(false, return false, "Illegal uL_RTOA_MeasurementItem %d\n", f1_ul_rtoa_meas_item->present); break; } break; // gNB RX-TX Time Diff case F1AP_MeasuredResultsValue_PR_gNB_RxTxTimeDiff: measuredResultsValue->present = F1AP_MEASURED_RESULTS_VALUE_PR_GNB_RXTXTIMEDIFF; F1AP_GNB_RxTxTimeDiff_t *f1_gNB_RxTxTimeDiff = f1_measuredResultsValue->choice.gNB_RxTxTimeDiff; f1ap_gnb_rx_tx_time_diff_t *gNB_RxTxTimeDiff = &measuredResultsValue->choice.gnb_rx_tx_time_diff; F1AP_GNBRxTxTimeDiffMeas_t *f1_rxTxTimeDiff = &f1_gNB_RxTxTimeDiff->rxTxTimeDiff; f1ap_gnb_rx_tx_time_diff_meas_t *rx_tx_time_diff = &gNB_RxTxTimeDiff->rx_tx_time_diff; switch (f1_rxTxTimeDiff->present) { case F1AP_GNBRxTxTimeDiffMeas_PR_NOTHING: rx_tx_time_diff->present = F1AP_GNBRXTXTIMEDIFFMEAS_PR_NOTHING; break; case F1AP_GNBRxTxTimeDiffMeas_PR_k0: rx_tx_time_diff->present = F1AP_GNBRXTXTIMEDIFFMEAS_PR_K0; rx_tx_time_diff->choice.k0 = f1_rxTxTimeDiff->choice.k0; break; case F1AP_GNBRxTxTimeDiffMeas_PR_k1: rx_tx_time_diff->present = F1AP_GNBRXTXTIMEDIFFMEAS_PR_K1; rx_tx_time_diff->choice.k1 = f1_rxTxTimeDiff->choice.k1; break; case F1AP_GNBRxTxTimeDiffMeas_PR_k2: rx_tx_time_diff->present = F1AP_GNBRXTXTIMEDIFFMEAS_PR_K2; rx_tx_time_diff->choice.k2 = f1_rxTxTimeDiff->choice.k2; break; case F1AP_GNBRxTxTimeDiffMeas_PR_k3: rx_tx_time_diff->present = F1AP_GNBRXTXTIMEDIFFMEAS_PR_K3; rx_tx_time_diff->choice.k3 = f1_rxTxTimeDiff->choice.k3; break; case F1AP_GNBRxTxTimeDiffMeas_PR_k4: rx_tx_time_diff->present = F1AP_GNBRXTXTIMEDIFFMEAS_PR_K4; rx_tx_time_diff->choice.k4 = f1_rxTxTimeDiff->choice.k4; break; case F1AP_GNBRxTxTimeDiffMeas_PR_k5: rx_tx_time_diff->present = F1AP_GNBRXTXTIMEDIFFMEAS_PR_K5; rx_tx_time_diff->choice.k5 = f1_rxTxTimeDiff->choice.k5; break; default: AssertError(false, return false, "Illegal rxTxTimeDiff value %d\n", f1_rxTxTimeDiff->present); break; } break; default: AssertError(false, return false, "Illegal measuredResultsValue %d\n", f1_measuredResultsValue->present); break; } // timeStamp F1AP_TimeStamp_t *f1_timeStamp = &f1_pos_measurement_result_item->timeStamp; f1ap_time_stamp_t *timeStamp = &pos_measurement_result_item->time_stamp; timeStamp->system_frame_number = f1_timeStamp->systemFrameNumber; F1AP_TimeStampSlotIndex_t *f1_slotIndex = &f1_timeStamp->slotIndex; f1ap_time_stamp_slot_index_t *slot_index = &timeStamp->slot_index; switch (f1_slotIndex->present) { case F1AP_TimeStampSlotIndex_PR_NOTHING: slot_index->present = F1AP_TIME_STAMP_SLOT_INDEX_PR_NOTHING; break; case F1AP_TimeStampSlotIndex_PR_sCS_15: slot_index->present = F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_15; slot_index->choice.scs_15 = f1_slotIndex->choice.sCS_15; break; case F1AP_TimeStampSlotIndex_PR_sCS_30: slot_index->present = F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_30; slot_index->choice.scs_30 = f1_slotIndex->choice.sCS_30; break; case F1AP_TimeStampSlotIndex_PR_sCS_60: slot_index->present = F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_60; slot_index->choice.scs_60 = f1_slotIndex->choice.sCS_60; break; case F1AP_TimeStampSlotIndex_PR_sCS_120: slot_index->present = F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_120; slot_index->choice.scs_120 = f1_slotIndex->choice.sCS_120; break; default: AssertError(false, return false, "Illegal slotIndex value %d\n", f1_slotIndex->present); break; } } return true; } static f1ap_pos_measurement_result_t cp_positioning_measurement_result(const f1ap_pos_measurement_result_t *in) { f1ap_pos_measurement_result_t out = {0}; uint32_t pos_meas_result_length = in->pos_measurement_result_item_length; out.pos_measurement_result_item_length = pos_meas_result_length; out.pos_measurement_result_item = calloc_or_fail(pos_meas_result_length, sizeof(*out.pos_measurement_result_item)); for (int i = 0; i < pos_meas_result_length; i++) { f1ap_pos_measurement_result_item_t *f1_pos_measurement_result_item = &in->pos_measurement_result_item[i]; f1ap_pos_measurement_result_item_t *pos_measurement_result_item = &out.pos_measurement_result_item[i]; // measuredResultsValue f1ap_measured_results_value_t *f1_measuredResultsValue = &f1_pos_measurement_result_item->measured_results_value; f1ap_measured_results_value_t *measuredResultsValue = &pos_measurement_result_item->measured_results_value; measuredResultsValue->present = f1_measuredResultsValue->present; switch (f1_measuredResultsValue->present) { case F1AP_MEASURED_RESULTS_VALUE_PR_NOTHING: // nothing to copy break; // Angle of Arrival case F1AP_MEASURED_RESULTS_VALUE_PR_UL_ANGLEOFARRIVAL: { f1ap_ul_aoa_t *f1_uL_AngleOfArrival = &f1_measuredResultsValue->choice.ul_angle_of_arrival; f1ap_ul_aoa_t *uL_AngleOfArrival = &measuredResultsValue->choice.ul_angle_of_arrival; uL_AngleOfArrival->azimuth_aoa = f1_uL_AngleOfArrival->azimuth_aoa; if (f1_uL_AngleOfArrival->zenith_aoa) { uL_AngleOfArrival->zenith_aoa = calloc_or_fail(1, sizeof(*uL_AngleOfArrival->zenith_aoa)); *uL_AngleOfArrival->zenith_aoa = *f1_uL_AngleOfArrival->zenith_aoa; } if (f1_uL_AngleOfArrival->lcs_to_gcs_translation_aoa) { uL_AngleOfArrival->lcs_to_gcs_translation_aoa = calloc_or_fail(1, sizeof(*uL_AngleOfArrival->lcs_to_gcs_translation_aoa)); f1ap_lcs_to_gcs_translationaoa_t *lCS_to_GCS_TranslationAoA = uL_AngleOfArrival->lcs_to_gcs_translation_aoa; f1ap_lcs_to_gcs_translationaoa_t *f1_lCS_to_GCS_TranslationAoA = f1_uL_AngleOfArrival->lcs_to_gcs_translation_aoa; lCS_to_GCS_TranslationAoA->alpha = f1_lCS_to_GCS_TranslationAoA->alpha; lCS_to_GCS_TranslationAoA->beta = f1_lCS_to_GCS_TranslationAoA->beta; lCS_to_GCS_TranslationAoA->gamma = f1_lCS_to_GCS_TranslationAoA->gamma; } break; } // UL SRS RSRP case F1AP_MEASURED_RESULTS_VALUE_PR_UL_SRS_RSRP: measuredResultsValue->choice.ul_srs_rsrp = f1_measuredResultsValue->choice.ul_srs_rsrp; break; // UL RTOA case F1AP_MEASURED_RESULTS_VALUE_PR_UL_RTOA: { f1ap_ul_rtoa_measurement_t *f1_uL_RTOA = &f1_measuredResultsValue->choice.ul_rtoa; f1ap_ul_rtoa_measurement_t *uL_RTOA = &measuredResultsValue->choice.ul_rtoa; f1ap_ul_rtoa_measurement_item_t *f1_ul_rtoa_meas_item = &f1_uL_RTOA->ul_rtoa_measurement_item; f1ap_ul_rtoa_measurement_item_t *ul_rtoa_meas_item = &uL_RTOA->ul_rtoa_measurement_item; switch (f1_ul_rtoa_meas_item->present) { case F1AP_ULRTOAMEAS_PR_NOTHING: break; case F1AP_ULRTOAMEAS_PR_K0: ul_rtoa_meas_item->choice.k0 = f1_ul_rtoa_meas_item->choice.k0; break; case F1AP_ULRTOAMEAS_PR_K1: ul_rtoa_meas_item->choice.k1 = f1_ul_rtoa_meas_item->choice.k1; break; case F1AP_ULRTOAMEAS_PR_K2: ul_rtoa_meas_item->choice.k2 = f1_ul_rtoa_meas_item->choice.k2; break; case F1AP_ULRTOAMEAS_PR_K3: ul_rtoa_meas_item->choice.k3 = f1_ul_rtoa_meas_item->choice.k3; break; case F1AP_ULRTOAMEAS_PR_K4: ul_rtoa_meas_item->choice.k4 = f1_ul_rtoa_meas_item->choice.k4; break; case F1AP_ULRTOAMEAS_PR_K5: ul_rtoa_meas_item->choice.k5 = f1_ul_rtoa_meas_item->choice.k5; break; default: AssertFatal(false, "Illegal uL_RTOA_MeasurementItem %d\n", f1_uL_RTOA->ul_rtoa_measurement_item.present); break; } break; } // gNB RX-TX Time Diff case F1AP_MEASURED_RESULTS_VALUE_PR_GNB_RXTXTIMEDIFF: { f1ap_gnb_rx_tx_time_diff_t *f1_gNB_RxTxTimeDiff = &f1_measuredResultsValue->choice.gnb_rx_tx_time_diff; f1ap_gnb_rx_tx_time_diff_t *gNB_RxTxTimeDiff = &measuredResultsValue->choice.gnb_rx_tx_time_diff; f1_gNB_RxTxTimeDiff->rx_tx_time_diff.present = gNB_RxTxTimeDiff->rx_tx_time_diff.present; f1ap_gnb_rx_tx_time_diff_meas_t *f1_rx_tx_time_diff = &f1_gNB_RxTxTimeDiff->rx_tx_time_diff; f1ap_gnb_rx_tx_time_diff_meas_t *rx_tx_time_diff = &gNB_RxTxTimeDiff->rx_tx_time_diff; switch (f1_rx_tx_time_diff->present) { case F1AP_GNBRXTXTIMEDIFFMEAS_PR_NOTHING: break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K0: rx_tx_time_diff->choice.k0 = f1_rx_tx_time_diff->choice.k0; break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K1: rx_tx_time_diff->choice.k1 = f1_rx_tx_time_diff->choice.k1; break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K2: rx_tx_time_diff->choice.k2 = f1_rx_tx_time_diff->choice.k2; break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K3: rx_tx_time_diff->choice.k3 = f1_rx_tx_time_diff->choice.k3; break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K4: rx_tx_time_diff->choice.k4 = f1_rx_tx_time_diff->choice.k4; break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K5: rx_tx_time_diff->choice.k5 = f1_rx_tx_time_diff->choice.k5; break; default: AssertFatal(false, "Illegal rxTxTimeDiff value %d\n", f1_rx_tx_time_diff->present); break; } break; } default: AssertFatal(false, "Illegal measuredResultsValue %d\n", f1_measuredResultsValue->present); break; } // timeStamp f1ap_time_stamp_t *f1_timeStamp = &f1_pos_measurement_result_item->time_stamp; f1ap_time_stamp_t *timeStamp = &pos_measurement_result_item->time_stamp; timeStamp->system_frame_number = f1_timeStamp->system_frame_number; f1ap_time_stamp_slot_index_t *f1_slot_index = &f1_timeStamp->slot_index; f1ap_time_stamp_slot_index_t *slot_index = &timeStamp->slot_index; switch (f1_slot_index->present) { case F1AP_TIME_STAMP_SLOT_INDEX_PR_NOTHING: break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_15: slot_index->choice.scs_15 = f1_slot_index->choice.scs_15; break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_30: slot_index->choice.scs_30 = f1_slot_index->choice.scs_30; break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_60: slot_index->choice.scs_60 = f1_slot_index->choice.scs_60; break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_120: slot_index->choice.scs_120 = f1_slot_index->choice.scs_120; break; default: AssertFatal(false, "Illegal slotIndex value %d\n", f1_slot_index->present); break; } } return out; } static bool eq_positioning_measurement_result(const f1ap_pos_measurement_result_t *f1_posMeasurementResult, const f1ap_pos_measurement_result_t *posMeasurementResult) { uint32_t pos_meas_result_length = f1_posMeasurementResult->pos_measurement_result_item_length; _F1_EQ_CHECK_INT(posMeasurementResult->pos_measurement_result_item_length, pos_meas_result_length); for (int i = 0; i < pos_meas_result_length; i++) { f1ap_pos_measurement_result_item_t *f1_pos_measurement_result_item = &f1_posMeasurementResult->pos_measurement_result_item[i]; f1ap_pos_measurement_result_item_t *pos_measurement_result_item = &posMeasurementResult->pos_measurement_result_item[i]; // measuredResultsValue f1ap_measured_results_value_t *f1_measuredResultsValue = &f1_pos_measurement_result_item->measured_results_value; f1ap_measured_results_value_t *measuredResultsValue = &pos_measurement_result_item->measured_results_value; _F1_EQ_CHECK_INT(measuredResultsValue->present, f1_measuredResultsValue->present); switch (measuredResultsValue->present) { case F1AP_MEASURED_RESULTS_VALUE_PR_NOTHING: // nothing to check break; // Angle of Arrival case F1AP_MEASURED_RESULTS_VALUE_PR_UL_ANGLEOFARRIVAL: { f1ap_ul_aoa_t *f1_uL_AngleOfArrival = &f1_measuredResultsValue->choice.ul_angle_of_arrival; f1ap_ul_aoa_t *uL_AngleOfArrival = &measuredResultsValue->choice.ul_angle_of_arrival; _F1_EQ_CHECK_INT(uL_AngleOfArrival->azimuth_aoa, f1_uL_AngleOfArrival->azimuth_aoa); if (f1_uL_AngleOfArrival->zenith_aoa) { _F1_EQ_CHECK_INT(*uL_AngleOfArrival->zenith_aoa, *f1_uL_AngleOfArrival->zenith_aoa); } if (f1_uL_AngleOfArrival->lcs_to_gcs_translation_aoa) { f1ap_lcs_to_gcs_translationaoa_t *lCS_to_GCS_TranslationAoA = uL_AngleOfArrival->lcs_to_gcs_translation_aoa; f1ap_lcs_to_gcs_translationaoa_t *f1_lCS_to_GCS_TranslationAoA = f1_uL_AngleOfArrival->lcs_to_gcs_translation_aoa; _F1_EQ_CHECK_INT(lCS_to_GCS_TranslationAoA->alpha, f1_lCS_to_GCS_TranslationAoA->alpha); _F1_EQ_CHECK_INT(lCS_to_GCS_TranslationAoA->beta, f1_lCS_to_GCS_TranslationAoA->beta); _F1_EQ_CHECK_INT(lCS_to_GCS_TranslationAoA->gamma, f1_lCS_to_GCS_TranslationAoA->gamma); } break; } // UL SRS RSRP case F1AP_MEASURED_RESULTS_VALUE_PR_UL_SRS_RSRP: _F1_EQ_CHECK_INT(measuredResultsValue->choice.ul_srs_rsrp, f1_measuredResultsValue->choice.ul_srs_rsrp); break; // UL RTOA case F1AP_MEASURED_RESULTS_VALUE_PR_UL_RTOA: { f1ap_ul_rtoa_measurement_t *f1_uL_RTOA = &f1_measuredResultsValue->choice.ul_rtoa; f1ap_ul_rtoa_measurement_t *uL_RTOA = &measuredResultsValue->choice.ul_rtoa; f1ap_ul_rtoa_measurement_item_t *f1_ul_rtoa_meas_item = &f1_uL_RTOA->ul_rtoa_measurement_item; f1ap_ul_rtoa_measurement_item_t *ul_rtoa_meas_item = &uL_RTOA->ul_rtoa_measurement_item; switch (f1_ul_rtoa_meas_item->present) { case F1AP_ULRTOAMEAS_PR_NOTHING: break; case F1AP_ULRTOAMEAS_PR_K0: _F1_EQ_CHECK_INT(ul_rtoa_meas_item->choice.k0, f1_ul_rtoa_meas_item->choice.k0); break; case F1AP_ULRTOAMEAS_PR_K1: _F1_EQ_CHECK_INT(ul_rtoa_meas_item->choice.k1, f1_ul_rtoa_meas_item->choice.k1); break; case F1AP_ULRTOAMEAS_PR_K2: _F1_EQ_CHECK_INT(ul_rtoa_meas_item->choice.k2, f1_ul_rtoa_meas_item->choice.k2); break; case F1AP_ULRTOAMEAS_PR_K3: _F1_EQ_CHECK_INT(ul_rtoa_meas_item->choice.k3, f1_ul_rtoa_meas_item->choice.k3); break; case F1AP_ULRTOAMEAS_PR_K4: _F1_EQ_CHECK_INT(ul_rtoa_meas_item->choice.k4, f1_ul_rtoa_meas_item->choice.k4); break; case F1AP_ULRTOAMEAS_PR_K5: _F1_EQ_CHECK_INT(ul_rtoa_meas_item->choice.k5, f1_ul_rtoa_meas_item->choice.k5); break; default: AssertError(false, return false, "Illegal uL_RTOA_MeasurementItem %d\n", f1_ul_rtoa_meas_item->present); break; } break; } // gNB RX-TX Time Diff case F1AP_MEASURED_RESULTS_VALUE_PR_GNB_RXTXTIMEDIFF: { f1ap_gnb_rx_tx_time_diff_t *f1_gNB_RxTxTimeDiff = &f1_measuredResultsValue->choice.gnb_rx_tx_time_diff; f1ap_gnb_rx_tx_time_diff_t *gNB_RxTxTimeDiff = &measuredResultsValue->choice.gnb_rx_tx_time_diff; f1ap_gnb_rx_tx_time_diff_meas_t *f1_rx_tx_time_diff = &f1_gNB_RxTxTimeDiff->rx_tx_time_diff; f1ap_gnb_rx_tx_time_diff_meas_t *rx_tx_time_diff = &gNB_RxTxTimeDiff->rx_tx_time_diff; _F1_EQ_CHECK_INT(f1_rx_tx_time_diff->present, rx_tx_time_diff->present); switch (f1_rx_tx_time_diff->present) { case F1AP_GNBRXTXTIMEDIFFMEAS_PR_NOTHING: break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K0: _F1_EQ_CHECK_INT(rx_tx_time_diff->choice.k0, f1_rx_tx_time_diff->choice.k0); break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K1: _F1_EQ_CHECK_INT(rx_tx_time_diff->choice.k1, f1_rx_tx_time_diff->choice.k1); break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K2: _F1_EQ_CHECK_INT(rx_tx_time_diff->choice.k2, f1_rx_tx_time_diff->choice.k2); break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K3: _F1_EQ_CHECK_INT(rx_tx_time_diff->choice.k3, f1_rx_tx_time_diff->choice.k3); break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K4: _F1_EQ_CHECK_INT(rx_tx_time_diff->choice.k4, f1_rx_tx_time_diff->choice.k4); break; case F1AP_GNBRXTXTIMEDIFFMEAS_PR_K5: _F1_EQ_CHECK_INT(rx_tx_time_diff->choice.k5, f1_rx_tx_time_diff->choice.k5); break; default: AssertError(false, return false, "Illegal rxTxTimeDiff value %d\n", f1_rx_tx_time_diff->present); break; } break; } default: AssertError(false, return false, "Illegal measuredResultsValue %d\n", f1_measuredResultsValue->present); break; } // timeStamp f1ap_time_stamp_t *f1_timeStamp = &f1_pos_measurement_result_item->time_stamp; f1ap_time_stamp_t *timeStamp = &pos_measurement_result_item->time_stamp; _F1_EQ_CHECK_INT(timeStamp->system_frame_number, f1_timeStamp->system_frame_number); f1ap_time_stamp_slot_index_t *f1_slot_index = &f1_timeStamp->slot_index; f1ap_time_stamp_slot_index_t *slot_index = &timeStamp->slot_index; switch (f1_slot_index->present) { case F1AP_TIME_STAMP_SLOT_INDEX_PR_NOTHING: break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_15: _F1_EQ_CHECK_INT(slot_index->choice.scs_15, f1_slot_index->choice.scs_15); break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_30: _F1_EQ_CHECK_INT(slot_index->choice.scs_30, f1_slot_index->choice.scs_30); break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_60: _F1_EQ_CHECK_INT(slot_index->choice.scs_60, f1_slot_index->choice.scs_60); break; case F1AP_TIME_STAMP_SLOT_INDEX_PR_SCS_120: _F1_EQ_CHECK_INT(slot_index->choice.scs_120, f1_slot_index->choice.scs_120); break; default: AssertError(false, return false, "Illegal slotIndex value %d\n", f1_slot_index->present); break; } } return true; } /** * @brief Encode F1 positioning information request to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_information_req(const f1ap_positioning_information_req_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningInformationExchange; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_InitiatingMessage__value_PR_PositioningInformationRequest; F1AP_PositioningInformationRequest_t *out = &tmp->value.choice.PositioningInformationRequest; /* mandatory : GNB_CU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationRequestIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningInformationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; /* mandatory : GNB_DU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationRequestIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningInformationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; return pdu; } /** * @brief Decode F1 positioning information request */ bool decode_positioning_information_req(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_information_req_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningInformationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.PositioningInformationRequest; F1AP_PositioningInformationRequestIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningInformationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningInformationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_RequestedSRSTransmissionCharacteristics: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 positioning information request deep copy */ f1ap_positioning_information_req_t cp_positioning_information_req(const f1ap_positioning_information_req_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_positioning_information_req_t cp = { .gNB_CU_ue_id = orig->gNB_CU_ue_id, .gNB_DU_ue_id = orig->gNB_DU_ue_id, }; return cp; } /** * @brief F1 positioning information request equality check */ bool eq_positioning_information_req(const f1ap_positioning_information_req_t *a, const f1ap_positioning_information_req_t *b) { _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); return true; } /** * @brief Free Allocated F1 positioning information request */ void free_positioning_information_req(f1ap_positioning_information_req_t *msg) { // nothing to free } /** * @brief Encode F1 positioning information response to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_information_resp(const f1ap_positioning_information_resp_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; asn1cCalloc(pdu->choice.successfulOutcome, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningInformationExchange; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_SuccessfulOutcome__value_PR_PositioningInformationResponse; F1AP_PositioningInformationResponse_t *out = &tmp->value.choice.PositioningInformationResponse; /* mandatory : GNB_CU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationResponseIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningInformationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; /* mandatory : GNB_DU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationResponseIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningInformationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; /* optional : SRSConfiguration */ if (msg->srs_configuration) { asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationResponseIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_SRSConfiguration; ie3->criticality = F1AP_Criticality_ignore; ie3->value.present = F1AP_PositioningInformationResponseIEs__value_PR_SRSConfiguration; f1ap_srs_carrier_list_t *srs_carrier_list = &msg->srs_configuration->srs_carrier_list; ie3->value.choice.SRSConfiguration.sRSCarrier_List = encode_srs_carrier_list(srs_carrier_list); } return pdu; } /** * @brief Decode F1 positioning information response */ bool decode_positioning_information_resp(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_information_resp_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningInformationResponse_t *in = &pdu->choice.successfulOutcome->value.choice.PositioningInformationResponse; F1AP_PositioningInformationResponseIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningInformationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningInformationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningInformationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_SRSConfiguration, false); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID); out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID); out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_SRSConfiguration: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationResponseIEs__value_PR_SRSConfiguration); F1AP_SRSCarrier_List_t *f1_sRSCarrier_List = &ie->value.choice.SRSConfiguration.sRSCarrier_List; out->srs_configuration = calloc_or_fail(1, sizeof(*out->srs_configuration)); f1ap_srs_carrier_list_t *srs_carrier_list = &out->srs_configuration->srs_carrier_list; decode_srs_carrier_list(srs_carrier_list, f1_sRSCarrier_List); break; case F1AP_ProtocolIE_ID_id_SFNInitialisationTime: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; case F1AP_ProtocolIE_ID_id_CriticalityDiagnostics: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 positioning information response deep copy */ f1ap_positioning_information_resp_t cp_positioning_information_resp(const f1ap_positioning_information_resp_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_positioning_information_resp_t cp = { .gNB_CU_ue_id = orig->gNB_CU_ue_id, .gNB_DU_ue_id = orig->gNB_DU_ue_id, }; /* optional: SRS Configuration */ if (orig->srs_configuration) { cp.srs_configuration = calloc_or_fail(1, sizeof(*cp.srs_configuration)); f1ap_srs_carrier_list_t *srs_carrier_list_cp = &cp.srs_configuration->srs_carrier_list; f1ap_srs_carrier_list_t *srs_carrier_list = &orig->srs_configuration->srs_carrier_list; *srs_carrier_list_cp = cp_srs_carrier_list(srs_carrier_list); } return cp; } /** * @brief F1 positioning information response equality check */ bool eq_positioning_information_resp(const f1ap_positioning_information_resp_t *a, const f1ap_positioning_information_resp_t *b) { _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); /* optional: SRS Configuration (O) */ if ((a->srs_configuration == NULL) != (b->srs_configuration == NULL)) { return false; } if (a->srs_configuration) { f1ap_srs_carrier_list_t *srs_carrier_list_a = &a->srs_configuration->srs_carrier_list; f1ap_srs_carrier_list_t *srs_carrier_list_b = &b->srs_configuration->srs_carrier_list; _F1_CHECK_EXP(eq_srs_carrier_list(srs_carrier_list_a, srs_carrier_list_b)); } return true; } /** * @brief Free Allocated F1 positioning information response */ void free_positioning_information_resp(f1ap_positioning_information_resp_t *msg) { /* SRS Configuration (O) */ if (msg->srs_configuration) { f1ap_srs_carrier_list_t *srs_carrier_list = &msg->srs_configuration->srs_carrier_list; free_srs_carrier_list(srs_carrier_list); free(msg->srs_configuration); } } /** * @brief Encode F1 positioning information failure to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_information_failure(const f1ap_positioning_information_failure_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_unsuccessfulOutcome; asn1cCalloc(pdu->choice.unsuccessfulOutcome, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningInformationExchange; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_UnsuccessfulOutcome__value_PR_PositioningInformationFailure; F1AP_PositioningInformationFailure_t *out = &tmp->value.choice.PositioningInformationFailure; /* mandatory : GNB_CU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationFailureIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningInformationFailureIEs__value_PR_GNB_CU_UE_F1AP_ID; ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; /* mandatory : GNB_DU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationFailureIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningInformationFailureIEs__value_PR_GNB_DU_UE_F1AP_ID; ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; /* mandatory : Cause */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationFailureIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_Cause; ie3->criticality = F1AP_Criticality_ignore; ie3->value.present = F1AP_PositioningInformationFailureIEs__value_PR_Cause; ie3->value.choice.Cause = encode_f1ap_cause(msg->cause, msg->cause_value); return pdu; } /** * @brief Decode F1 positioning information failure */ bool decode_positioning_information_failure(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_information_failure_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningInformationFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.PositioningInformationFailure; F1AP_PositioningInformationFailureIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningInformationFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningInformationFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningInformationFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationFailureIEs__value_PR_GNB_CU_UE_F1AP_ID); out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationFailureIEs__value_PR_GNB_DU_UE_F1AP_ID); out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_Cause: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationFailureIEs__value_PR_Cause); _F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)); break; case F1AP_ProtocolIE_ID_id_CriticalityDiagnostics: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 positioning information failure deep copy */ f1ap_positioning_information_failure_t cp_positioning_information_failure(const f1ap_positioning_information_failure_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_positioning_information_failure_t cp = { .gNB_CU_ue_id = orig->gNB_CU_ue_id, .gNB_DU_ue_id = orig->gNB_DU_ue_id, .cause = orig->cause, .cause_value = orig->cause_value, }; return cp; } /** * @brief F1 positioning information failure equality check */ bool eq_positioning_information_failure(const f1ap_positioning_information_failure_t *a, const f1ap_positioning_information_failure_t *b) { _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); _F1_EQ_CHECK_INT(a->cause, b->cause); _F1_EQ_CHECK_LONG(a->cause_value, b->cause_value); return true; } /** * @brief Free Allocated F1 positioning information failure */ void free_positioning_information_failure(f1ap_positioning_information_failure_t *msg) { // nothing to free } /** * @brief Encode F1 positioning activation request to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_activation_req(const f1ap_positioning_activation_req_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningActivation; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_InitiatingMessage__value_PR_PositioningActivationRequest; F1AP_PositioningActivationRequest_t *out = &tmp->value.choice.PositioningActivationRequest; /* mandatory : GNB_CU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningActivationRequestIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningActivationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; /* mandatory : GNB_DU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningActivationRequestIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningActivationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; /* mandatory : SRS type */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningActivationRequestIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_SRSType; ie3->criticality = F1AP_Criticality_reject; ie3->value.present = F1AP_PositioningActivationRequestIEs__value_PR_SRSType; ie3->value.choice.SRSType = encode_f1ap_srstype(&msg->srs_type); return pdu; } /** * @brief Decode F1 positioning activation request */ bool decode_positioning_activation_req(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_activation_req_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningActivationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.PositioningActivationRequest; F1AP_PositioningActivationRequestIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningActivationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningActivationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningActivationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_SRSType, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningActivationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningActivationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_SRSType: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningActivationRequestIEs__value_PR_SRSType); _F1_CHECK_EXP(decode_f1ap_srstype(&ie->value.choice.SRSType, &out->srs_type)); break; case F1AP_ProtocolIE_ID_id_ActivationTime: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 positioning activation request deep copy */ f1ap_positioning_activation_req_t cp_positioning_activation_req(const f1ap_positioning_activation_req_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_positioning_activation_req_t cp = { .gNB_CU_ue_id = orig->gNB_CU_ue_id, .gNB_DU_ue_id = orig->gNB_DU_ue_id, .srs_type.present = orig->srs_type.present, }; switch (orig->srs_type.present) { case F1AP_SRS_TYPE_PR_NOTHING: // nothing to copy break; case F1AP_SRS_TYPE_PR_SEMIPERSISTENTSRS: cp.srs_type.choice.srs_resource_set_id = calloc_or_fail(1, sizeof(*cp.srs_type.choice.srs_resource_set_id)); *cp.srs_type.choice.srs_resource_set_id = *orig->srs_type.choice.srs_resource_set_id; break; case F1AP_SRS_TYPE_PR_APERIODICSRS: cp.srs_type.choice.aperiodic = calloc_or_fail(1, sizeof(*cp.srs_type.choice.aperiodic)); *cp.srs_type.choice.aperiodic = *orig->srs_type.choice.aperiodic; break; default: PRINT_ERROR("received illegal SRS type %d\n", orig->srs_type.present); break; } return cp; } /** * @brief F1 positioning activation request equality check */ bool eq_positioning_activation_req(const f1ap_positioning_activation_req_t *a, const f1ap_positioning_activation_req_t *b) { _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); _F1_EQ_CHECK_INT(a->srs_type.present, b->srs_type.present); const f1ap_srs_type_t *srs_type_a = &a->srs_type; const f1ap_srs_type_t *srs_type_b = &b->srs_type; switch (srs_type_a->present) { case F1AP_SRS_TYPE_PR_NOTHING: // nothing to check break; case F1AP_SRS_TYPE_PR_SEMIPERSISTENTSRS: _F1_EQ_CHECK_INT(*srs_type_a->choice.srs_resource_set_id, *srs_type_b->choice.srs_resource_set_id); break; case F1AP_SRS_TYPE_PR_APERIODICSRS: _F1_EQ_CHECK_INT(*srs_type_a->choice.aperiodic, *srs_type_b->choice.aperiodic); break; default: PRINT_ERROR("received illegal SRS type %d\n", srs_type_a->present); break; } return true; } /** * @brief Free Allocated F1 activation request */ void free_positioning_activation_req(f1ap_positioning_activation_req_t *msg) { DevAssert(msg != NULL); switch (msg->srs_type.present) { case F1AP_SRS_TYPE_PR_NOTHING: // nothing to free return; case F1AP_SRS_TYPE_PR_SEMIPERSISTENTSRS: free(msg->srs_type.choice.srs_resource_set_id); break; case F1AP_SRS_TYPE_PR_APERIODICSRS: free(msg->srs_type.choice.aperiodic); break; default: PRINT_ERROR("received illegal SRS type %d\n", msg->srs_type.present); break; } } /** * @brief Encode F1 positioning activation response to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_activation_resp(const f1ap_positioning_activation_resp_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; asn1cCalloc(pdu->choice.successfulOutcome, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningActivation; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_SuccessfulOutcome__value_PR_PositioningActivationResponse; F1AP_PositioningActivationResponse_t *out = &tmp->value.choice.PositioningActivationResponse; /* mandatory : GNB_CU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningActivationResponseIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningActivationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; /* mandatory : GNB_DU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningActivationResponseIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningActivationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; return pdu; } /** * @brief Decode F1 positioning activation response */ bool decode_positioning_activation_resp(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_activation_resp_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningActivationResponse_t *in = &pdu->choice.successfulOutcome->value.choice.PositioningActivationResponse; F1AP_PositioningActivationResponseIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningActivationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningActivationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningActivationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID); out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningActivationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID); out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_SystemFrameNumber: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; case F1AP_ProtocolIE_ID_id_SlotNumber: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; case F1AP_ProtocolIE_ID_id_CriticalityDiagnostics: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 positioning activation response deep copy */ f1ap_positioning_activation_resp_t cp_positioning_activation_resp(const f1ap_positioning_activation_resp_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_positioning_activation_resp_t cp = { .gNB_CU_ue_id = orig->gNB_CU_ue_id, .gNB_DU_ue_id = orig->gNB_DU_ue_id, }; return cp; } /** * @brief F1 positioning activation response equality check */ bool eq_positioning_activation_resp(const f1ap_positioning_activation_resp_t *a, const f1ap_positioning_activation_resp_t *b) { _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); return true; } /** * @brief Free Allocated F1 positioning activation response */ void free_positioning_activation_resp(f1ap_positioning_activation_resp_t *msg) { // nothing to free } /** * @brief Encode F1 positioning activation failure to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_activation_failure(const f1ap_positioning_activation_failure_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_unsuccessfulOutcome; asn1cCalloc(pdu->choice.unsuccessfulOutcome, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningActivation; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_UnsuccessfulOutcome__value_PR_PositioningActivationFailure; F1AP_PositioningActivationFailure_t *out = &tmp->value.choice.PositioningActivationFailure; /* mandatory : GNB_CU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningActivationFailureIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningActivationFailureIEs__value_PR_GNB_CU_UE_F1AP_ID; ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; /* mandatory : GNB_DU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningActivationFailureIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningActivationFailureIEs__value_PR_GNB_DU_UE_F1AP_ID; ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; /* mandatory : Cause */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningActivationFailureIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_Cause; ie3->criticality = F1AP_Criticality_ignore; ie3->value.present = F1AP_PositioningActivationFailureIEs__value_PR_Cause; ie3->value.choice.Cause = encode_f1ap_cause(msg->cause, msg->cause_value); return pdu; } /** * @brief Decode F1 positioning activation failure */ bool decode_positioning_activation_failure(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_activation_failure_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningActivationFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.PositioningActivationFailure; F1AP_PositioningActivationFailureIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningActivationFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningActivationFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningActivationFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningActivationFailureIEs__value_PR_GNB_CU_UE_F1AP_ID); out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningActivationFailureIEs__value_PR_GNB_DU_UE_F1AP_ID); out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_Cause: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningActivationFailureIEs__value_PR_Cause); _F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)); break; case F1AP_ProtocolIE_ID_id_CriticalityDiagnostics: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 positioning activation failure deep copy */ f1ap_positioning_activation_failure_t cp_positioning_activation_failure(const f1ap_positioning_activation_failure_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_positioning_activation_failure_t cp = { .gNB_CU_ue_id = orig->gNB_CU_ue_id, .gNB_DU_ue_id = orig->gNB_DU_ue_id, .cause = orig->cause, .cause_value = orig->cause_value, }; return cp; } /** * @brief F1 positioning activation failure equality check */ bool eq_positioning_activation_failure(const f1ap_positioning_activation_failure_t *a, const f1ap_positioning_activation_failure_t *b) { _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); _F1_EQ_CHECK_INT(a->cause, b->cause); _F1_EQ_CHECK_LONG(a->cause_value, b->cause_value); return true; } /** * @brief Free Allocated F1 positioning activation failure */ void free_positioning_activation_failure(f1ap_positioning_activation_failure_t *msg) { // nothing to free } /** * @brief Encode F1 positioning deactivation to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_deactivation(const f1ap_positioning_deactivation_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningDeactivation; tmp->criticality = F1AP_Criticality_ignore; tmp->value.present = F1AP_InitiatingMessage__value_PR_PositioningDeactivation; F1AP_PositioningDeactivation_t *out = &tmp->value.choice.PositioningDeactivation; /* mandatory : GNB_CU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningDeactivationIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningDeactivationIEs__value_PR_GNB_CU_UE_F1AP_ID; ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; /* mandatory : GNB_DU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningDeactivationIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningDeactivationIEs__value_PR_GNB_DU_UE_F1AP_ID; ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; /* mandatory : CHOICE ABORT TRANSMISSION */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningDeactivationIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_AbortTransmission; ie3->criticality = F1AP_Criticality_ignore; ie3->value.present = F1AP_PositioningDeactivationIEs__value_PR_AbortTransmission; ie3->value.choice.AbortTransmission = encode_f1ap_abort_transmission(&msg->abort_transmission); return pdu; } /** * @brief Decode F1 positioning deactivation */ bool decode_positioning_deactivation(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_deactivation_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningDeactivation_t *in = &pdu->choice.initiatingMessage->value.choice.PositioningDeactivation; F1AP_PositioningDeactivationIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningDeactivationIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningDeactivationIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningDeactivationIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_AbortTransmission, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningDeactivationIEs__value_PR_GNB_CU_UE_F1AP_ID); out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningDeactivationIEs__value_PR_GNB_DU_UE_F1AP_ID); out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_AbortTransmission: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningDeactivationIEs__value_PR_AbortTransmission); _F1_CHECK_EXP(decode_f1ap_abort_transmission(&ie->value.choice.AbortTransmission, &out->abort_transmission)); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 positioning deactivation deep copy */ f1ap_positioning_deactivation_t cp_positioning_deactivation(const f1ap_positioning_deactivation_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_positioning_deactivation_t cp = { .gNB_CU_ue_id = orig->gNB_CU_ue_id, .gNB_DU_ue_id = orig->gNB_DU_ue_id, .abort_transmission.present = orig->abort_transmission.present, }; // do this properly abort mission switch (orig->abort_transmission.present) { case F1AP_ABORT_TRANSMISSION_PR_NOTHING: // nothing to copy break; case F1AP_ABORT_TRANSMISSION_PR_SRSRESOURCESETID: cp.abort_transmission.choice.srs_resource_set_id = orig->abort_transmission.choice.srs_resource_set_id; break; case F1AP_ABORT_TRANSMISSION_PR_RELEASEALL: cp.abort_transmission.choice.release_all = orig->abort_transmission.choice.release_all; break; default: PRINT_ERROR("received illegal Abort Transmission value %d\n", orig->abort_transmission.present); break; } return cp; } /** * @brief F1 positioning deactivation equality check */ bool eq_positioning_deactivation(const f1ap_positioning_deactivation_t *a, const f1ap_positioning_deactivation_t *b) { _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); _F1_EQ_CHECK_INT(a->abort_transmission.present, b->abort_transmission.present); switch (a->abort_transmission.present) { case F1AP_ABORT_TRANSMISSION_PR_NOTHING: // nothing to check break; case F1AP_ABORT_TRANSMISSION_PR_SRSRESOURCESETID: _F1_EQ_CHECK_INT(a->abort_transmission.choice.srs_resource_set_id, b->abort_transmission.choice.srs_resource_set_id); break; case F1AP_ABORT_TRANSMISSION_PR_RELEASEALL: _F1_EQ_CHECK_INT(a->abort_transmission.choice.release_all, b->abort_transmission.choice.release_all); break; default: PRINT_ERROR("received illegal Abort Transmission value %d\n", a->abort_transmission.present); break; } return true; } /** * @brief Free Allocated F1 positioning activation failure */ void free_positioning_deactivation(f1ap_positioning_deactivation_t *msg) { // nothing to free } /** * @brief Encode F1 positioning information update to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_information_update(const f1ap_positioning_information_update_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningInformationUpdate; tmp->criticality = F1AP_Criticality_ignore; tmp->value.present = F1AP_InitiatingMessage__value_PR_PositioningInformationUpdate; F1AP_PositioningInformationUpdate_t *out = &tmp->value.choice.PositioningInformationUpdate; /* mandatory : GNB_CU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationUpdateIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningInformationUpdateIEs__value_PR_GNB_CU_UE_F1AP_ID; ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; /* mandatory : GNB_DU_UE_F1AP_ID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationUpdateIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningInformationUpdateIEs__value_PR_GNB_DU_UE_F1AP_ID; ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; /* optional : SRSConfiguration */ if (msg->srs_configuration) { asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationUpdateIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_SRSConfiguration; ie3->criticality = F1AP_Criticality_ignore; ie3->value.present = F1AP_PositioningInformationUpdateIEs__value_PR_SRSConfiguration; f1ap_srs_carrier_list_t *srs_carrier_list = &msg->srs_configuration->srs_carrier_list; ie3->value.choice.SRSConfiguration.sRSCarrier_List = encode_srs_carrier_list(srs_carrier_list); } return pdu; } /** * @brief Decode F1 positioning information update */ bool decode_positioning_information_update(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_information_update_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningInformationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.PositioningInformationUpdate; F1AP_PositioningInformationUpdateIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningInformationUpdateIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningInformationUpdateIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); F1AP_LIB_FIND_IE(F1AP_PositioningInformationUpdateIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_SRSConfiguration, false); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationUpdateIEs__value_PR_GNB_CU_UE_F1AP_ID); out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationUpdateIEs__value_PR_GNB_DU_UE_F1AP_ID); out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; break; case F1AP_ProtocolIE_ID_id_SRSConfiguration: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationUpdateIEs__value_PR_SRSConfiguration); F1AP_SRSCarrier_List_t *f1_sRSCarrier_List = &ie->value.choice.SRSConfiguration.sRSCarrier_List; out->srs_configuration = calloc_or_fail(1, sizeof(*out->srs_configuration)); f1ap_srs_carrier_list_t *srs_carrier_list = &out->srs_configuration->srs_carrier_list; decode_srs_carrier_list(srs_carrier_list, f1_sRSCarrier_List); break; case F1AP_ProtocolIE_ID_id_SFNInitialisationTime: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 positioning information update deep copy */ f1ap_positioning_information_update_t cp_positioning_information_update(const f1ap_positioning_information_update_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_positioning_information_update_t cp = { .gNB_CU_ue_id = orig->gNB_CU_ue_id, .gNB_DU_ue_id = orig->gNB_DU_ue_id, }; /* optional: SRS Configuration */ if (orig->srs_configuration) { cp.srs_configuration = calloc_or_fail(1, sizeof(*cp.srs_configuration)); f1ap_srs_carrier_list_t *srs_carrier_list_cp = &cp.srs_configuration->srs_carrier_list; f1ap_srs_carrier_list_t *srs_carrier_list = &orig->srs_configuration->srs_carrier_list; *srs_carrier_list_cp = cp_srs_carrier_list(srs_carrier_list); } return cp; } /** * @brief F1 positioning information update equality check */ bool eq_positioning_information_update(const f1ap_positioning_information_update_t *a, const f1ap_positioning_information_update_t *b) { _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); /* optional: SRS Configuration */ if ((a->srs_configuration == NULL) != (b->srs_configuration == NULL)) { return false; } if (a->srs_configuration) { f1ap_srs_carrier_list_t *srs_carrier_list_a = &a->srs_configuration->srs_carrier_list; f1ap_srs_carrier_list_t *srs_carrier_list_b = &b->srs_configuration->srs_carrier_list; _F1_CHECK_EXP(eq_srs_carrier_list(srs_carrier_list_a, srs_carrier_list_b)); } return true; } /** * @brief Free Allocated F1 positioning information update */ void free_positioning_information_update(f1ap_positioning_information_update_t *msg) { /* optional: SRS Configuration */ if (msg->srs_configuration) { f1ap_srs_carrier_list_t *srs_carrier_list = &msg->srs_configuration->srs_carrier_list; free_srs_carrier_list(srs_carrier_list); free(msg->srs_configuration); } } /** * @brief Encode F1 TRP information request to ASN.1 */ F1AP_F1AP_PDU_t *encode_trp_information_req(const f1ap_trp_information_req_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_TRPInformationExchange; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_InitiatingMessage__value_PR_TRPInformationRequest; F1AP_TRPInformationRequest_t *out = &tmp->value.choice.TRPInformationRequest; /* mandatory : TransactionID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_TRPInformationRequestIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_TRPInformationRequestIEs__value_PR_TransactionID; ie1->value.choice.TransactionID = msg->transaction_id; /* TRPList */ if (msg->has_trp_list) { asn1cSequenceAdd(out->protocolIEs.list, F1AP_TRPInformationRequestIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_TRPList; ie2->criticality = F1AP_Criticality_ignore; ie2->value.present = F1AP_TRPInformationRequestIEs__value_PR_TRPList; for (int i = 0; i < msg->trp_list.trp_list_length; i++) { // mandatory : TRP List Item (M) asn1cSequenceAdd(ie2->value.choice.TRPList.list, F1AP_TRPListItem_t, trplistitem); trplistitem->tRPID = msg->trp_list.trp_list_item[i].trp_id; } } /* mandatory : TRPInformationTypeList */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_TRPInformationRequestIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_TRPInformationTypeListTRPReq; ie3->criticality = F1AP_Criticality_reject; ie3->value.present = F1AP_TRPInformationRequestIEs__value_PR_TRPInformationTypeListTRPReq; for (int i = 0; i < msg->trp_information_type_list.trp_information_type_list_length; i++) { // TRPInformationTypeItem (M) asn1cSequenceAdd(ie3->value.choice.TRPInformationTypeListTRPReq.list, F1AP_TRPInformationTypeItemTRPReq_t, trpinfotypeitem); trpinfotypeitem->id = F1AP_ProtocolIE_ID_id_TRPInformationTypeItem; trpinfotypeitem->criticality = F1AP_Criticality_reject; trpinfotypeitem->value.present = F1AP_TRPInformationTypeItemTRPReq__value_PR_TRPInformationTypeItem; trpinfotypeitem->value.choice.TRPInformationTypeItem = msg->trp_information_type_list.trp_information_type_item[i]; } return pdu; } /** * @brief Decode F1 TRP information request */ bool decode_trp_information_req(const F1AP_F1AP_PDU_t *pdu, f1ap_trp_information_req_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_TRPInformationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.TRPInformationRequest; F1AP_TRPInformationRequestIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_TRPInformationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); F1AP_LIB_FIND_IE(F1AP_TRPInformationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TRPList, true); F1AP_LIB_FIND_IE(F1AP_TRPInformationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TRPInformationTypeListTRPReq, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_TransactionID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_TRPInformationRequestIEs__value_PR_TransactionID); out->transaction_id = ie->value.choice.TransactionID; break; case F1AP_ProtocolIE_ID_id_TRPList: _F1_EQ_CHECK_INT(ie->value.present, F1AP_TRPInformationRequestIEs__value_PR_TRPList); out->has_trp_list = true; uint32_t trp_list_length = ie->value.choice.TRPList.list.count; AssertError(trp_list_length > 0, return false, "at least 1 TRP must be present"); out->trp_list.trp_list_length = trp_list_length; out->trp_list.trp_list_item = calloc_or_fail(trp_list_length, sizeof(*out->trp_list.trp_list_item)); F1AP_TRPList_t *TRPList = &ie->value.choice.TRPList; for (int i = 0; i < trp_list_length; i++) { out->trp_list.trp_list_item[i].trp_id = TRPList->list.array[i]->tRPID; } break; case F1AP_ProtocolIE_ID_id_TRPInformationTypeListTRPReq: _F1_EQ_CHECK_INT(ie->value.present, F1AP_TRPInformationRequestIEs__value_PR_TRPInformationTypeListTRPReq); uint8_t trp_info_type_list_length = ie->value.choice.TRPInformationTypeListTRPReq.list.count; AssertError(trp_info_type_list_length > 0, return false, "at least 1 TRP Information Type must be present"); f1ap_trp_information_type_list_t *trp_information_type_list = &out->trp_information_type_list; trp_information_type_list->trp_information_type_list_length = trp_info_type_list_length; trp_information_type_list->trp_information_type_item = calloc_or_fail(trp_info_type_list_length, sizeof(*trp_information_type_list->trp_information_type_item)); for (int i = 0; i < trp_info_type_list_length; i++) { F1AP_TRPInformationTypeItemTRPReq_t *f1_trpinfotypeitem = (F1AP_TRPInformationTypeItemTRPReq_t *)ie->value.choice.TRPInformationTypeListTRPReq.list.array[i]; _F1_EQ_CHECK_LONG(f1_trpinfotypeitem->id, F1AP_ProtocolIE_ID_id_TRPInformationTypeItem); _F1_EQ_CHECK_INT(f1_trpinfotypeitem->value.present, F1AP_TRPInformationTypeItemTRPReq__value_PR_TRPInformationTypeItem); trp_information_type_list->trp_information_type_item[i] = f1_trpinfotypeitem->value.choice.TRPInformationTypeItem; } break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 TRP information request deep copy */ f1ap_trp_information_req_t cp_trp_information_req(const f1ap_trp_information_req_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_trp_information_req_t cp = { .transaction_id = orig->transaction_id, .has_trp_list = orig->has_trp_list, }; if (orig->has_trp_list) { uint32_t trp_list_length = orig->trp_list.trp_list_length; cp.trp_list.trp_list_length = trp_list_length; cp.trp_list.trp_list_item = calloc_or_fail(trp_list_length, sizeof(*cp.trp_list.trp_list_item)); for (int i = 0; i < trp_list_length; i++) { cp.trp_list.trp_list_item[i].trp_id = orig->trp_list.trp_list_item[i].trp_id; } } const f1ap_trp_information_type_list_t *trp_information_type_list = &orig->trp_information_type_list; f1ap_trp_information_type_list_t *trp_information_type_list_cp = &cp.trp_information_type_list; uint8_t trp_info_type_list_length = trp_information_type_list->trp_information_type_list_length; trp_information_type_list_cp->trp_information_type_list_length = trp_info_type_list_length; trp_information_type_list_cp->trp_information_type_item = calloc_or_fail(trp_info_type_list_length, sizeof(*trp_information_type_list_cp->trp_information_type_item)); for (int i = 0; i < trp_info_type_list_length; i++) { trp_information_type_list_cp->trp_information_type_item[i] = trp_information_type_list->trp_information_type_item[i]; } return cp; } /** * @brief F1 TRP information request equality check */ bool eq_trp_information_req(const f1ap_trp_information_req_t *a, const f1ap_trp_information_req_t *b) { _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); _F1_EQ_CHECK_INT(a->has_trp_list, b->has_trp_list); if (a->has_trp_list) { _F1_EQ_CHECK_INT(a->trp_list.trp_list_length, b->trp_list.trp_list_length); for (int i = 0; i < a->trp_list.trp_list_length; i++) { _F1_EQ_CHECK_INT(a->trp_list.trp_list_item[i].trp_id, b->trp_list.trp_list_item[i].trp_id); } } const f1ap_trp_information_type_list_t *trp_information_type_list_a = &a->trp_information_type_list; const f1ap_trp_information_type_list_t *trp_information_type_list_b = &b->trp_information_type_list; _F1_EQ_CHECK_INT(trp_information_type_list_a->trp_information_type_list_length, trp_information_type_list_b->trp_information_type_list_length); for (int i = 0; i < trp_information_type_list_a->trp_information_type_list_length; i++) { _F1_EQ_CHECK_INT(trp_information_type_list_a->trp_information_type_item[i], trp_information_type_list_b->trp_information_type_item[i]); } return true; } /** * @brief Free Allocated F1 TRP information request */ void free_trp_information_req(f1ap_trp_information_req_t *msg) { if (msg->has_trp_list) { free(msg->trp_list.trp_list_item); } free(msg->trp_information_type_list.trp_information_type_item); } /** * @brief Encode F1 TRP information response to ASN.1 */ F1AP_F1AP_PDU_t *encode_trp_information_resp(const f1ap_trp_information_resp_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; asn1cCalloc(pdu->choice.successfulOutcome, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_TRPInformationExchange; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_SuccessfulOutcome__value_PR_TRPInformationResponse; F1AP_TRPInformationResponse_t *out = &tmp->value.choice.TRPInformationResponse; /* mandatory : TransactionID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_TRPInformationResponseIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_TRPInformationResponseIEs__value_PR_TransactionID; ie1->value.choice.TransactionID = msg->transaction_id; /* mandatory : TRPInformationList */ // Supported : NR PCI, NG-RAN CGI, NR ARFCN, Geogarphical Coordinates asn1cSequenceAdd(out->protocolIEs.list, F1AP_TRPInformationResponseIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_TRPInformationListTRPResp; ie3->criticality = F1AP_Criticality_ignore; ie3->value.present = F1AP_TRPInformationResponseIEs__value_PR_TRPInformationListTRPResp; uint32_t trp_info_item_len = msg->trp_information_list.trp_information_item_length; for (int i = 0; i < trp_info_item_len; i++) { // TRPInformationItem (M) asn1cSequenceAdd(ie3->value.choice.TRPInformationListTRPResp.list, F1AP_TRPInformationItemTRPResp_t, trpinfolist); trpinfolist->id = F1AP_ProtocolIE_ID_id_TRPInformationItem; trpinfolist->criticality = F1AP_Criticality_ignore; trpinfolist->value.present = F1AP_TRPInformationItemTRPResp__value_PR_TRPInformationItem; F1AP_TRPInformationItem_t *trp_info_item = &trpinfolist->value.choice.TRPInformationItem; F1AP_TRPInformation_t *trp_info = &trp_info_item->tRPInformation; f1ap_trp_information_t *tRPInformation = &msg->trp_information_list.trp_information_item[i]; trp_info->tRPID = tRPInformation->trp_id; f1ap_trp_information_type_response_list_t *tRPInformationTypeResponseList = &tRPInformation->trp_information_type_response_list; uint8_t trp_item_len = tRPInformationTypeResponseList->trp_information_type_response_item_length; for (int j = 0; j < trp_item_len; j++) { asn1cSequenceAdd(trp_info->tRPInformationTypeResponseList, F1AP_TRPInformationTypeResponseItem_t, trp_resp_item); *trp_resp_item = encode_trp_info_type_response_item(&tRPInformationTypeResponseList->trp_information_type_response_item[j]); } } return pdu; } /** * @brief Decode F1 TRP information response */ bool decode_trp_information_resp(const F1AP_F1AP_PDU_t *pdu, f1ap_trp_information_resp_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_TRPInformationResponse_t *in = &pdu->choice.successfulOutcome->value.choice.TRPInformationResponse; F1AP_TRPInformationResponseIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_TRPInformationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); F1AP_LIB_FIND_IE(F1AP_TRPInformationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TRPInformationListTRPResp, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_TransactionID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_TRPInformationResponseIEs__value_PR_TransactionID); out->transaction_id = ie->value.choice.TransactionID; break; case F1AP_ProtocolIE_ID_id_TRPInformationListTRPResp: _F1_EQ_CHECK_INT(ie->value.present, F1AP_TRPInformationResponseIEs__value_PR_TRPInformationListTRPResp); uint32_t trp_info_item_length = ie->value.choice.TRPInformationListTRPResp.list.count; AssertError(trp_info_item_length > 0, return false, "at least 1 TRP Information Item must be present"); out->trp_information_list.trp_information_item_length = trp_info_item_length; f1ap_trp_information_t *trp_info_item = calloc_or_fail(trp_info_item_length, sizeof(*trp_info_item)); out->trp_information_list.trp_information_item = trp_info_item; for (int i = 0; i < trp_info_item_length; i++) { F1AP_TRPInformationItemTRPResp_t *f1_trpinfolist = (F1AP_TRPInformationItemTRPResp_t *)ie->value.choice.TRPInformationListTRPResp.list.array[i]; _F1_EQ_CHECK_LONG(f1_trpinfolist->id, F1AP_ProtocolIE_ID_id_TRPInformationItem); _F1_EQ_CHECK_INT(f1_trpinfolist->value.present, F1AP_TRPInformationItemTRPResp__value_PR_TRPInformationItem); F1AP_TRPInformationItem_t *f1_trp_info_item = &f1_trpinfolist->value.choice.TRPInformationItem; F1AP_TRPInformation_t *f1_trp_info = &f1_trp_info_item->tRPInformation; trp_info_item[i].trp_id = f1_trp_info->tRPID; F1AP_TRPInformationTypeResponseList_t *f1_trp_info_type_resp_list = (F1AP_TRPInformationTypeResponseList_t *)&f1_trp_info->tRPInformationTypeResponseList; uint8_t trp_info_type_resp_item_len = f1_trp_info_type_resp_list->list.count; AssertError(trp_info_type_resp_item_len > 0, return false, "at least 1 TRP Information type response Item must be present"); f1ap_trp_information_type_response_list_t *trp_info_resp_list = &trp_info_item[i].trp_information_type_response_list; trp_info_resp_list->trp_information_type_response_item_length = trp_info_type_resp_item_len; trp_info_resp_list->trp_information_type_response_item = calloc_or_fail(trp_info_type_resp_item_len, sizeof(*trp_info_resp_list->trp_information_type_response_item)); for (int j = 0; j < trp_info_type_resp_item_len; j++) { f1ap_trp_information_type_response_item_t *trp_info_type_resp_item = &trp_info_resp_list->trp_information_type_response_item[j]; decode_trp_info_type_response_item(f1_trp_info_type_resp_list->list.array[j], trp_info_type_resp_item); } } break; case F1AP_ProtocolIE_ID_id_CriticalityDiagnostics: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 TRP information response deep copy */ f1ap_trp_information_resp_t cp_trp_information_resp(const f1ap_trp_information_resp_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_trp_information_resp_t cp = { .transaction_id = orig->transaction_id, }; uint32_t trp_info_item_length = orig->trp_information_list.trp_information_item_length; AssertFatal(trp_info_item_length > 0, "at least 1 TRP Information Item must be present\n"); cp.trp_information_list.trp_information_item_length = trp_info_item_length; cp.trp_information_list.trp_information_item = calloc_or_fail(trp_info_item_length, sizeof(*cp.trp_information_list.trp_information_item)); f1ap_trp_information_t *trp_information_item_cp = cp.trp_information_list.trp_information_item; f1ap_trp_information_t *trp_information_item_orig = orig->trp_information_list.trp_information_item; for (int i = 0; i < trp_info_item_length; i++) { uint8_t trp_info_type_resp_item_len = trp_information_item_orig[i].trp_information_type_response_list.trp_information_type_response_item_length; AssertFatal(trp_info_type_resp_item_len > 0, "at least 1 TRP Information type response Item must be present\n"); trp_information_item_cp[i].trp_id = trp_information_item_orig[i].trp_id; f1ap_trp_information_type_response_list_t *trp_info_type_resp_list_cp = &trp_information_item_cp[i].trp_information_type_response_list; f1ap_trp_information_type_response_list_t *trp_info_type_resp_list_orig = &trp_information_item_orig[i].trp_information_type_response_list; trp_info_type_resp_list_cp->trp_information_type_response_item_length = trp_info_type_resp_item_len; trp_info_type_resp_list_cp->trp_information_type_response_item = calloc_or_fail(trp_info_type_resp_item_len, sizeof(*trp_info_type_resp_list_cp->trp_information_type_response_item)); for (int j = 0; j < trp_info_type_resp_item_len; j++) { trp_info_type_resp_list_cp->trp_information_type_response_item[j] = cp_trp_info_type_response_item(&trp_info_type_resp_list_orig->trp_information_type_response_item[j]); } } return cp; } /** * @brief F1 TRP information response equality check */ bool eq_trp_information_resp(const f1ap_trp_information_resp_t *a, const f1ap_trp_information_resp_t *b) { _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); _F1_EQ_CHECK_INT(a->trp_information_list.trp_information_item_length, b->trp_information_list.trp_information_item_length); uint32_t trp_info_item_length = a->trp_information_list.trp_information_item_length; AssertError(trp_info_item_length > 0, return false, "at least 1 TRP Information Item must be present\n"); f1ap_trp_information_t *trp_information_item_a = a->trp_information_list.trp_information_item; f1ap_trp_information_t *trp_information_item_b = b->trp_information_list.trp_information_item; for (int i = 0; i < trp_info_item_length; i++) { f1ap_trp_information_type_response_list_t *trp_info_type_resp_list_a = &trp_information_item_a[i].trp_information_type_response_list; f1ap_trp_information_type_response_list_t *trp_info_type_resp_list_b = &trp_information_item_b[i].trp_information_type_response_list; _F1_EQ_CHECK_INT(trp_info_type_resp_list_a->trp_information_type_response_item_length, trp_info_type_resp_list_b->trp_information_type_response_item_length); uint8_t trp_info_type_resp_item_len = trp_info_type_resp_list_a->trp_information_type_response_item_length; AssertError(trp_info_type_resp_item_len > 0, return false, "at least 1 TRP Information type response Item must be present\n"); _F1_EQ_CHECK_INT(trp_information_item_a[i].trp_id, trp_information_item_b[i].trp_id); for (int j = 0; j < trp_info_type_resp_item_len; j++) { _F1_CHECK_EXP(eq_trp_info_type_response_item(&trp_info_type_resp_list_a->trp_information_type_response_item[j], &trp_info_type_resp_list_b->trp_information_type_response_item[j])); } } return true; } /** * @brief Free Allocated F1 TRP information response */ void free_trp_information_resp(f1ap_trp_information_resp_t *msg) { f1ap_trp_information_list_t *trp_information_list = &msg->trp_information_list; uint32_t trp_info_item_length = trp_information_list->trp_information_item_length; for (int i = 0; i < trp_info_item_length; i++) { f1ap_trp_information_t *trp_information_item = &trp_information_list->trp_information_item[i]; f1ap_trp_information_type_response_list_t *trp_info_type_resp_list = &trp_information_item->trp_information_type_response_list; free(trp_info_type_resp_list->trp_information_type_response_item); } free(msg->trp_information_list.trp_information_item); } /** * @brief Encode F1 TRP information failure to ASN.1 */ F1AP_F1AP_PDU_t *encode_trp_information_failure(const f1ap_trp_information_failure_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_unsuccessfulOutcome; asn1cCalloc(pdu->choice.unsuccessfulOutcome, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_TRPInformationExchange; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_UnsuccessfulOutcome__value_PR_TRPInformationFailure; F1AP_TRPInformationFailure_t *out = &tmp->value.choice.TRPInformationFailure; /* mandatory : TransactionID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_TRPInformationFailureIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_TRPInformationFailureIEs__value_PR_TransactionID; ie1->value.choice.TransactionID = msg->transaction_id; /* mandatory : Cause */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_TRPInformationFailureIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_Cause; ie3->criticality = F1AP_Criticality_ignore; ie3->value.present = F1AP_TRPInformationFailureIEs__value_PR_Cause; ie3->value.choice.Cause = encode_f1ap_cause(msg->cause, msg->cause_value); return pdu; } /** * @brief Decode F1 TRP information failure */ bool decode_trp_information_failure(const F1AP_F1AP_PDU_t *pdu, f1ap_trp_information_failure_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_TRPInformationFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.TRPInformationFailure; F1AP_TRPInformationFailureIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_TRPInformationFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); F1AP_LIB_FIND_IE(F1AP_TRPInformationFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_TransactionID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_TRPInformationFailureIEs__value_PR_TransactionID); out->transaction_id = ie->value.choice.TransactionID; break; case F1AP_ProtocolIE_ID_id_Cause: _F1_EQ_CHECK_INT(ie->value.present, F1AP_TRPInformationFailureIEs__value_PR_Cause); _F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)); break; case F1AP_ProtocolIE_ID_id_CriticalityDiagnostics: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 trp information failure deep copy */ f1ap_trp_information_failure_t cp_trp_information_failure(const f1ap_trp_information_failure_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_trp_information_failure_t cp = { .transaction_id = orig->transaction_id, .cause = orig->cause, .cause_value = orig->cause_value, }; return cp; } /** * @brief F1 trp information failure equality check */ bool eq_trp_information_failure(const f1ap_trp_information_failure_t *a, const f1ap_trp_information_failure_t *b) { _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); _F1_EQ_CHECK_INT(a->cause, b->cause); _F1_EQ_CHECK_LONG(a->cause_value, b->cause_value); return true; } /** * @brief Free Allocated F1 trp information failure */ void free_trp_information_failure(f1ap_trp_information_failure_t *msg) { // nothing to free } /** * @brief Encode F1 positioning measurement request to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_measurement_req(const f1ap_positioning_measurement_req_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningMeasurementExchange; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_InitiatingMessage__value_PR_PositioningMeasurementRequest; F1AP_PositioningMeasurementRequest_t *out = &tmp->value.choice.PositioningMeasurementRequest; /* mandatory : TransactionID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementRequestIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningMeasurementRequestIEs__value_PR_TransactionID; ie1->value.choice.TransactionID = msg->transaction_id; /* mandatory : LMF_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementRequestIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_LMF_MeasurementID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningMeasurementRequestIEs__value_PR_LMF_MeasurementID; ie2->value.choice.LMF_MeasurementID = msg->lmf_measurement_id; /* mandatory : RAN_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementRequestIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_RAN_MeasurementID; ie3->criticality = F1AP_Criticality_reject; ie3->value.present = F1AP_PositioningMeasurementRequestIEs__value_PR_RAN_MeasurementID; ie3->value.choice.RAN_MeasurementID = msg->ran_measurement_id; /* TRP Measurement Request List */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementRequestIEs_t, ie4); ie4->id = F1AP_ProtocolIE_ID_id_TRP_MeasurementRequestList; ie4->criticality = F1AP_Criticality_reject; ie4->value.present = F1AP_PositioningMeasurementRequestIEs__value_PR_TRP_MeasurementRequestList; F1AP_TRP_MeasurementRequestList_t *f1_trp_meas_req_list = &ie4->value.choice.TRP_MeasurementRequestList; const f1ap_trp_measurement_request_list_t *trp_meas_req_list = &msg->trp_measurement_request_list; for (int i = 0; i < trp_meas_req_list->trp_measurement_request_list_length; i++) { // mandatory : TRP List Item asn1cSequenceAdd(f1_trp_meas_req_list->list, F1AP_TRP_MeasurementRequestItem_t, trp_meas_req_item); trp_meas_req_item->tRPID = trp_meas_req_list->trp_measurement_request_item[i].tRPID; } /* mandatory : PosReportCharacteristics */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementRequestIEs_t, ie5); ie5->id = F1AP_ProtocolIE_ID_id_PosReportCharacteristics; ie5->criticality = F1AP_Criticality_reject; ie5->value.present = F1AP_PositioningMeasurementRequestIEs__value_PR_PosReportCharacteristics; ie5->value.choice.PosReportCharacteristics = msg->pos_report_characteristics; /* C : if ReportCharacteristicsPeriodic */ if (msg->pos_report_characteristics == F1AP_POSREPORTCHARACTERISTICS_PERIODIC) { asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementRequestIEs_t, ie6); ie6->id = F1AP_ProtocolIE_ID_id_PosMeasurementPeriodicity; ie6->criticality = F1AP_Criticality_reject; ie6->value.present = F1AP_PositioningMeasurementRequestIEs__value_PR_MeasurementPeriodicity; ie6->value.choice.MeasurementPeriodicity = msg->measurement_periodicity; } /* mandatory : Positioning Measurement Periodicity */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementRequestIEs_t, ie7); ie7->id = F1AP_ProtocolIE_ID_id_PosMeasurementQuantities; ie7->criticality = F1AP_Criticality_reject; ie7->value.present = F1AP_PositioningMeasurementRequestIEs__value_PR_PosMeasurementQuantities; F1AP_PosMeasurementQuantities_t *f1_pos_meas_quantities = &ie7->value.choice.PosMeasurementQuantities; const f1ap_pos_measurement_quantities_t *pos_meas_quantities = &msg->pos_measurement_quantities; for (int i = 0; i < pos_meas_quantities->pos_measurement_quantities_length; i++) { // mandatory: PosMeasurementQuantitiesItem asn1cSequenceAdd(f1_pos_meas_quantities->list, F1AP_PosMeasurementQuantities_Item_t, pos_meas_quantity_item); pos_meas_quantity_item->posMeasurementType = pos_meas_quantities->pos_measurement_quantities_item[i].pos_measurement_type; } /* optional: SRS Configuration */ if (msg->srs_configuration) { asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementRequestIEs_t, ie8); ie8->id = F1AP_ProtocolIE_ID_id_SRSConfiguration; ie8->criticality = F1AP_Criticality_ignore; ie8->value.present = F1AP_PositioningMeasurementRequestIEs__value_PR_SRSConfiguration; f1ap_srs_carrier_list_t *srs_carrier_list = &msg->srs_configuration->srs_carrier_list; ie8->value.choice.SRSConfiguration.sRSCarrier_List = encode_srs_carrier_list(srs_carrier_list); } return pdu; } /** * @brief Decode F1 Positioning Measurement request */ bool decode_positioning_measurement_req(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_measurement_req_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningMeasurementRequest_t *in = &pdu->choice.initiatingMessage->value.choice.PositioningMeasurementRequest; F1AP_PositioningMeasurementRequestIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_LMF_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_RAN_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TRP_MeasurementRequestList, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_PosReportCharacteristics, true); F1AP_PosReportCharacteristics_t *report_char = &ie->value.choice.PosReportCharacteristics; if (*report_char == F1AP_PosReportCharacteristics_periodic) { F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_PosMeasurementPeriodicity, true); } F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_PosMeasurementQuantities, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_SRSConfiguration, false); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_TransactionID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementRequestIEs__value_PR_TransactionID); out->transaction_id = ie->value.choice.TransactionID; break; case F1AP_ProtocolIE_ID_id_LMF_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementRequestIEs__value_PR_LMF_MeasurementID); out->lmf_measurement_id = ie->value.choice.LMF_MeasurementID; break; case F1AP_ProtocolIE_ID_id_RAN_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementRequestIEs__value_PR_RAN_MeasurementID); out->ran_measurement_id = ie->value.choice.RAN_MeasurementID; break; case F1AP_ProtocolIE_ID_id_TRP_MeasurementRequestList: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementRequestIEs__value_PR_TRP_MeasurementRequestList); F1AP_TRP_MeasurementRequestList_t *f1_trp_meas_req_list = &ie->value.choice.TRP_MeasurementRequestList; f1ap_trp_measurement_request_list_t *trp_meas_req_list = &out->trp_measurement_request_list; uint32_t trp_meas_req_list_len = f1_trp_meas_req_list->list.count; AssertError(trp_meas_req_list_len > 0, return false, "at least 1 TRP must be present"); trp_meas_req_list->trp_measurement_request_list_length = trp_meas_req_list_len; trp_meas_req_list->trp_measurement_request_item = calloc_or_fail(trp_meas_req_list_len, sizeof(*trp_meas_req_list->trp_measurement_request_item)); for (int i = 0; i < trp_meas_req_list_len; i++) { trp_meas_req_list->trp_measurement_request_item[i].tRPID = f1_trp_meas_req_list->list.array[i]->tRPID; } break; case F1AP_ProtocolIE_ID_id_PosReportCharacteristics: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementRequestIEs__value_PR_PosReportCharacteristics); out->pos_report_characteristics = ie->value.choice.PosReportCharacteristics; break; case F1AP_ProtocolIE_ID_id_PosMeasurementPeriodicity: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementRequestIEs__value_PR_MeasurementPeriodicity); out->measurement_periodicity = ie->value.choice.MeasurementPeriodicity; break; case F1AP_ProtocolIE_ID_id_PosMeasurementQuantities: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementRequestIEs__value_PR_PosMeasurementQuantities); F1AP_PosMeasurementQuantities_t *f1_pos_meas_quantities = &ie->value.choice.PosMeasurementQuantities; f1ap_pos_measurement_quantities_t *pos_meas_quantities = &out->pos_measurement_quantities; uint32_t pos_meas_quantities_len = f1_pos_meas_quantities->list.count; AssertError(pos_meas_quantities_len > 0, return false, "at least 1 position measurement must be present"); pos_meas_quantities->pos_measurement_quantities_length = pos_meas_quantities_len; pos_meas_quantities->pos_measurement_quantities_item = calloc_or_fail(pos_meas_quantities_len, sizeof(*pos_meas_quantities->pos_measurement_quantities_item)); for (int i = 0; i < pos_meas_quantities_len; i++) { f1ap_pos_measurement_quantities_item_t *pos_meas_quantities_item = &pos_meas_quantities->pos_measurement_quantities_item[i]; F1AP_PosMeasurementQuantities_Item_t *f1_PosMeasurementQuantities_Item = f1_pos_meas_quantities->list.array[i]; pos_meas_quantities_item->pos_measurement_type = f1_PosMeasurementQuantities_Item->posMeasurementType; } break; case F1AP_ProtocolIE_ID_id_SFNInitialisationTime: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not supported, skipping\n", ie->id); break; case F1AP_ProtocolIE_ID_id_SRSConfiguration: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementRequestIEs__value_PR_SRSConfiguration); F1AP_SRSCarrier_List_t *f1_sRSCarrier_List = &ie->value.choice.SRSConfiguration.sRSCarrier_List; out->srs_configuration = calloc_or_fail(1, sizeof(*out->srs_configuration)); f1ap_srs_carrier_list_t *srs_carrier_list = &out->srs_configuration->srs_carrier_list; decode_srs_carrier_list(srs_carrier_list, f1_sRSCarrier_List); break; case F1AP_ProtocolIE_ID_id_MeasurementBeamInfoRequest: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not supported, skipping\n", ie->id); break; case F1AP_ProtocolIE_ID_id_SystemFrameNumber: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not supported, skipping\n", ie->id); break; case F1AP_ProtocolIE_ID_id_SlotNumber: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not supported, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 Positioning Measurement request deep copy */ f1ap_positioning_measurement_req_t cp_positioning_measurement_req(const f1ap_positioning_measurement_req_t *orig) { // copy all mandatory fields that are not dynamic memory f1ap_positioning_measurement_req_t cp = { .transaction_id = orig->transaction_id, .lmf_measurement_id = orig->lmf_measurement_id, .ran_measurement_id = orig->ran_measurement_id, }; f1ap_trp_measurement_request_list_t *trp_meas_req_list_cp = &cp.trp_measurement_request_list; const f1ap_trp_measurement_request_list_t *trp_meas_req_list_orig = &orig->trp_measurement_request_list; uint32_t trp_meas_req_list_len = trp_meas_req_list_orig->trp_measurement_request_list_length; AssertFatal(trp_meas_req_list_len > 0, "at least 1 TRP must be present"); trp_meas_req_list_cp->trp_measurement_request_list_length = trp_meas_req_list_len; trp_meas_req_list_cp->trp_measurement_request_item = calloc_or_fail(trp_meas_req_list_len, sizeof(*trp_meas_req_list_cp->trp_measurement_request_item)); for (int i = 0; i < trp_meas_req_list_len; i++) { trp_meas_req_list_cp->trp_measurement_request_item[i].tRPID = trp_meas_req_list_orig->trp_measurement_request_item[i].tRPID; } cp.pos_report_characteristics = orig->pos_report_characteristics; if (orig->pos_report_characteristics == F1AP_POSREPORTCHARACTERISTICS_PERIODIC) { cp.measurement_periodicity = orig->measurement_periodicity; } f1ap_pos_measurement_quantities_t *q_out = &cp.pos_measurement_quantities; const f1ap_pos_measurement_quantities_t *q_in = &orig->pos_measurement_quantities; uint32_t q_len = q_in->pos_measurement_quantities_length; AssertFatal(q_len > 0, "at least 1 position measurement must be present"); q_out->pos_measurement_quantities_length = q_len; q_out->pos_measurement_quantities_item = calloc_or_fail(q_len, sizeof(*q_out->pos_measurement_quantities_item)); for (int i = 0; i < q_len; i++) { f1ap_pos_measurement_quantities_item_t *q_item_in = &q_in->pos_measurement_quantities_item[i]; f1ap_pos_measurement_quantities_item_t *q_item_out = &q_out->pos_measurement_quantities_item[i]; q_item_out->pos_measurement_type = q_item_in->pos_measurement_type; } /* optional: SRS Configuration */ if (orig->srs_configuration) { cp.srs_configuration = calloc_or_fail(1, sizeof(*cp.srs_configuration)); f1ap_srs_carrier_list_t *srs_carrier_list_cp = &cp.srs_configuration->srs_carrier_list; f1ap_srs_carrier_list_t *srs_carrier_list = &orig->srs_configuration->srs_carrier_list; *srs_carrier_list_cp = cp_srs_carrier_list(srs_carrier_list); } return cp; } /** * @brief F1 Positioning Measurement request equality check */ bool eq_positioning_measurement_req(const f1ap_positioning_measurement_req_t *a, const f1ap_positioning_measurement_req_t *b) { _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); _F1_EQ_CHECK_INT(a->lmf_measurement_id, b->lmf_measurement_id); _F1_EQ_CHECK_INT(a->ran_measurement_id, b->ran_measurement_id); const f1ap_trp_measurement_request_list_t *trp_meas_req_list_a = &a->trp_measurement_request_list; const f1ap_trp_measurement_request_list_t *trp_meas_req_list_b = &b->trp_measurement_request_list; uint32_t trp_meas_req_list_len = trp_meas_req_list_a->trp_measurement_request_list_length; AssertFatal(trp_meas_req_list_len > 0, "at least 1 TRP must be present"); _F1_EQ_CHECK_INT(trp_meas_req_list_b->trp_measurement_request_list_length, trp_meas_req_list_len); for (int i = 0; i < trp_meas_req_list_len; i++) { _F1_EQ_CHECK_INT(trp_meas_req_list_a->trp_measurement_request_item[i].tRPID, trp_meas_req_list_b->trp_measurement_request_item[i].tRPID); } _F1_EQ_CHECK_INT(a->pos_report_characteristics, b->pos_report_characteristics); if (a->pos_report_characteristics == F1AP_POSREPORTCHARACTERISTICS_PERIODIC) { _F1_EQ_CHECK_INT(a->measurement_periodicity, b->measurement_periodicity); } const f1ap_pos_measurement_quantities_t *pos_meas_quantities_a = &a->pos_measurement_quantities; const f1ap_pos_measurement_quantities_t *pos_meas_quantities_b = &b->pos_measurement_quantities; uint32_t pos_meas_quantities_len = pos_meas_quantities_a->pos_measurement_quantities_length; AssertFatal(pos_meas_quantities_len > 0, "at least 1 position measurement must be present"); _F1_EQ_CHECK_INT(pos_meas_quantities_b->pos_measurement_quantities_length, pos_meas_quantities_len); for (int i = 0; i < pos_meas_quantities_len; i++) { f1ap_pos_measurement_quantities_item_t *a_pos_meas_quantities_item = &pos_meas_quantities_a->pos_measurement_quantities_item[i]; f1ap_pos_measurement_quantities_item_t *b_pos_meas_quantities_item = &pos_meas_quantities_b->pos_measurement_quantities_item[i]; _F1_EQ_CHECK_INT(a_pos_meas_quantities_item->pos_measurement_type, b_pos_meas_quantities_item->pos_measurement_type); } /* optional: SRS Configuration */ if ((a->srs_configuration == NULL) != (b->srs_configuration == NULL)) { return false; } if (a->srs_configuration) { f1ap_srs_carrier_list_t *srs_carrier_list_a = &a->srs_configuration->srs_carrier_list; f1ap_srs_carrier_list_t *srs_carrier_list_b = &b->srs_configuration->srs_carrier_list; _F1_CHECK_EXP(eq_srs_carrier_list(srs_carrier_list_a, srs_carrier_list_b)); } return true; } /** * @brief Free Allocated F1 Positioning Measurement request */ void free_positioning_measurement_req(f1ap_positioning_measurement_req_t *msg) { free(msg->trp_measurement_request_list.trp_measurement_request_item); free(msg->pos_measurement_quantities.pos_measurement_quantities_item); /* optional: SRS Configuration */ if (msg->srs_configuration) { f1ap_srs_carrier_list_t *srs_carrier_list = &msg->srs_configuration->srs_carrier_list; free_srs_carrier_list(srs_carrier_list); free(msg->srs_configuration); } } /** * @brief Encode F1 positioning measurement response to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_measurement_resp(const f1ap_positioning_measurement_resp_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; asn1cCalloc(pdu->choice.successfulOutcome, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningMeasurementExchange; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_SuccessfulOutcome__value_PR_PositioningMeasurementResponse; F1AP_PositioningMeasurementResponse_t *out = &tmp->value.choice.PositioningMeasurementResponse; /* mandatory : TransactionID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementResponseIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningMeasurementResponseIEs__value_PR_TransactionID; ie1->value.choice.TransactionID = msg->transaction_id; /* mandatory : LMF_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementResponseIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_LMF_MeasurementID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningMeasurementResponseIEs__value_PR_LMF_MeasurementID; ie2->value.choice.LMF_MeasurementID = msg->lmf_measurement_id; /* mandatory : RAN_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementResponseIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_RAN_MeasurementID; ie3->criticality = F1AP_Criticality_reject; ie3->value.present = F1AP_PositioningMeasurementResponseIEs__value_PR_RAN_MeasurementID; ie3->value.choice.RAN_MeasurementID = msg->ran_measurement_id; /* Positioning Measurement Result List */ if (msg->pos_measurement_result_list) { asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementResponseIEs_t, ie4); ie4->id = F1AP_ProtocolIE_ID_id_PosMeasurementResultList; ie4->criticality = F1AP_Criticality_reject; ie4->value.present = F1AP_PositioningMeasurementResponseIEs__value_PR_PosMeasurementResultList; const f1ap_pos_measurement_result_list_t *in_list = msg->pos_measurement_result_list; for (int i = 0; i < in_list->pos_measurement_result_list_length; i++) { // mandatory : Positioning Measurement Result List Item asn1cSequenceAdd(ie4->value.choice.PosMeasurementResultList.list, F1AP_PosMeasurementResultList_Item_t, out_item); f1ap_pos_measurement_result_list_item_t *in_item = &in_list->pos_measurement_result_list_item[i]; F1AP_PosMeasurementResult_t *out_result = &out_item->posMeasurementResult; f1ap_pos_measurement_result_t *in_result = &in_item->pos_measurement_result; *out_result = encode_positioning_measurement_result(in_result); out_item->tRPID = in_item->trp_id; } } return pdu; } /** * @brief Decode F1 Positioning Measurement response */ bool decode_positioning_measurement_resp(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_measurement_resp_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningMeasurementResponse_t *in = &pdu->choice.successfulOutcome->value.choice.PositioningMeasurementResponse; F1AP_PositioningMeasurementResponseIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_LMF_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_RAN_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_PosMeasurementResultList, false); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_TransactionID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementResponseIEs__value_PR_TransactionID); out->transaction_id = ie->value.choice.TransactionID; break; case F1AP_ProtocolIE_ID_id_LMF_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementResponseIEs__value_PR_LMF_MeasurementID); out->lmf_measurement_id = ie->value.choice.LMF_MeasurementID; break; case F1AP_ProtocolIE_ID_id_RAN_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementResponseIEs__value_PR_RAN_MeasurementID); out->ran_measurement_id = ie->value.choice.RAN_MeasurementID; break; case F1AP_ProtocolIE_ID_id_PosMeasurementResultList: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementResponseIEs__value_PR_PosMeasurementResultList); F1AP_PosMeasurementResultList_t *in_list = &ie->value.choice.PosMeasurementResultList; uint32_t pos_meas_result_list_len = in_list->list.count; out->pos_measurement_result_list = calloc_or_fail(1, sizeof(*out->pos_measurement_result_list)); f1ap_pos_measurement_result_list_t *out_list = out->pos_measurement_result_list; out_list->pos_measurement_result_list_length = pos_meas_result_list_len; out_list->pos_measurement_result_list_item = calloc_or_fail(pos_meas_result_list_len, sizeof(*out_list->pos_measurement_result_list_item)); for (int i = 0; i < pos_meas_result_list_len; i++) { F1AP_PosMeasurementResultList_Item_t *in_item = in_list->list.array[i]; f1ap_pos_measurement_result_list_item_t *out_item = &out_list->pos_measurement_result_list_item[i]; _F1_CHECK_EXP(decode_positioning_measurement_result(&in_item->posMeasurementResult, &out_item->pos_measurement_result)); out_item->trp_id = in_item->tRPID; } break; case F1AP_ProtocolIE_ID_id_CriticalityDiagnostics: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 Positioning Measurement response deep copy */ f1ap_positioning_measurement_resp_t cp_positioning_measurement_resp(const f1ap_positioning_measurement_resp_t *orig) { // copy all mandatory fields that are not dynamic memory f1ap_positioning_measurement_resp_t cp = { .transaction_id = orig->transaction_id, .lmf_measurement_id = orig->lmf_measurement_id, .ran_measurement_id = orig->ran_measurement_id, }; if (orig->pos_measurement_result_list) { cp.pos_measurement_result_list = calloc_or_fail(1, sizeof(*cp.pos_measurement_result_list)); f1ap_pos_measurement_result_list_t *list_orig = orig->pos_measurement_result_list; f1ap_pos_measurement_result_list_t *list_cp = cp.pos_measurement_result_list; uint32_t pos_meas_result_list_len = list_orig->pos_measurement_result_list_length; list_cp->pos_measurement_result_list_length = pos_meas_result_list_len; list_cp->pos_measurement_result_list_item = calloc_or_fail(pos_meas_result_list_len, sizeof(*list_cp->pos_measurement_result_list_item)); for (int i = 0; i < pos_meas_result_list_len; i++) { f1ap_pos_measurement_result_list_item_t *item_cp = &list_cp->pos_measurement_result_list_item[i]; f1ap_pos_measurement_result_list_item_t *item_orig = &list_orig->pos_measurement_result_list_item[i]; item_cp->pos_measurement_result = cp_positioning_measurement_result(&item_orig->pos_measurement_result); item_cp->trp_id = item_orig->trp_id; } } return cp; } /** * @brief F1 Positioning Measurement response equality check */ bool eq_positioning_measurement_resp(const f1ap_positioning_measurement_resp_t *a, const f1ap_positioning_measurement_resp_t *b) { _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); _F1_EQ_CHECK_INT(a->lmf_measurement_id, b->lmf_measurement_id); _F1_EQ_CHECK_INT(a->ran_measurement_id, b->ran_measurement_id); if ((a->pos_measurement_result_list == NULL) != (b->pos_measurement_result_list == NULL)) { return false; } if (a->pos_measurement_result_list) { f1ap_pos_measurement_result_list_t *list_a = a->pos_measurement_result_list; f1ap_pos_measurement_result_list_t *list_b = b->pos_measurement_result_list; uint32_t pos_meas_result_list_len = list_a->pos_measurement_result_list_length; _F1_EQ_CHECK_INT(list_b->pos_measurement_result_list_length, pos_meas_result_list_len); for (int i = 0; i < pos_meas_result_list_len; i++) { f1ap_pos_measurement_result_list_item_t *item_a = &list_a->pos_measurement_result_list_item[i]; f1ap_pos_measurement_result_list_item_t *item_b = &list_b->pos_measurement_result_list_item[i]; _F1_CHECK_EXP(eq_positioning_measurement_result(&item_a->pos_measurement_result, &item_b->pos_measurement_result)); _F1_EQ_CHECK_INT(item_a->trp_id, item_b->trp_id); } } return true; } /** * @brief Free Allocated F1 Positioning Measurement response */ void free_positioning_measurement_resp(f1ap_positioning_measurement_resp_t *msg) { if (msg->pos_measurement_result_list) { f1ap_pos_measurement_result_list_t *list = msg->pos_measurement_result_list; uint32_t pos_meas_result_list_len = list->pos_measurement_result_list_length; for (int i = 0; i < pos_meas_result_list_len; i++) { f1ap_pos_measurement_result_t *posMeasurementResult = &list->pos_measurement_result_list_item[i].pos_measurement_result; uint32_t pos_meas_result_length = posMeasurementResult->pos_measurement_result_item_length; for (int j = 0; j < pos_meas_result_length; j++) { f1ap_pos_measurement_result_item_t *item = &posMeasurementResult->pos_measurement_result_item[j]; f1ap_measured_results_value_t *measuredResultsValue = &item->measured_results_value; if (measuredResultsValue->present == F1AP_MEASURED_RESULTS_VALUE_PR_UL_ANGLEOFARRIVAL) { if (measuredResultsValue->choice.ul_angle_of_arrival.zenith_aoa) { free(measuredResultsValue->choice.ul_angle_of_arrival.zenith_aoa); } if (measuredResultsValue->choice.ul_angle_of_arrival.lcs_to_gcs_translation_aoa) { free(measuredResultsValue->choice.ul_angle_of_arrival.lcs_to_gcs_translation_aoa); } } } free(posMeasurementResult->pos_measurement_result_item); } free(msg->pos_measurement_result_list->pos_measurement_result_list_item); free(msg->pos_measurement_result_list); } } /** * @brief Encode F1 positioning measurement failure to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_measurement_failure(const f1ap_positioning_measurement_failure_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_unsuccessfulOutcome; asn1cCalloc(pdu->choice.unsuccessfulOutcome, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningMeasurementExchange; tmp->criticality = F1AP_Criticality_reject; tmp->value.present = F1AP_UnsuccessfulOutcome__value_PR_PositioningMeasurementFailure; F1AP_PositioningMeasurementFailure_t *out = &tmp->value.choice.PositioningMeasurementFailure; /* mandatory : TransactionID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementFailureIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningMeasurementFailureIEs__value_PR_TransactionID; ie1->value.choice.TransactionID = msg->transaction_id; /* mandatory : LMF_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementFailureIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_LMF_MeasurementID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningMeasurementFailureIEs__value_PR_LMF_MeasurementID; ie2->value.choice.LMF_MeasurementID = msg->lmf_measurement_id; /* mandatory : RAN_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementFailureIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_RAN_MeasurementID; ie3->criticality = F1AP_Criticality_reject; ie3->value.present = F1AP_PositioningMeasurementFailureIEs__value_PR_RAN_MeasurementID; ie3->value.choice.RAN_MeasurementID = msg->ran_measurement_id; /* mandatory : Cause */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementFailureIEs_t, ie4); ie4->id = F1AP_ProtocolIE_ID_id_Cause; ie4->criticality = F1AP_Criticality_ignore; ie4->value.present = F1AP_PositioningMeasurementFailureIEs__value_PR_Cause; ie4->value.choice.Cause = encode_f1ap_cause(msg->cause, msg->cause_value); return pdu; } /** * @brief Decode F1 positioning measurement failure */ bool decode_positioning_measurement_failure(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_measurement_failure_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningMeasurementFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.PositioningMeasurementFailure; F1AP_PositioningMeasurementFailureIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_LMF_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_RAN_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_TransactionID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementFailureIEs__value_PR_TransactionID); out->transaction_id = ie->value.choice.TransactionID; break; case F1AP_ProtocolIE_ID_id_LMF_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementFailureIEs__value_PR_LMF_MeasurementID); out->lmf_measurement_id = ie->value.choice.LMF_MeasurementID; break; case F1AP_ProtocolIE_ID_id_RAN_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementFailureIEs__value_PR_RAN_MeasurementID); out->ran_measurement_id = ie->value.choice.RAN_MeasurementID; break; case F1AP_ProtocolIE_ID_id_Cause: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementFailureIEs__value_PR_Cause); _F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)); break; case F1AP_ProtocolIE_ID_id_CriticalityDiagnostics: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 positioning measurement failure deep copy */ f1ap_positioning_measurement_failure_t cp_positioning_measurement_failure(const f1ap_positioning_measurement_failure_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_positioning_measurement_failure_t cp = { .transaction_id = orig->transaction_id, .lmf_measurement_id = orig->lmf_measurement_id, .ran_measurement_id = orig->ran_measurement_id, .cause = orig->cause, .cause_value = orig->cause_value, }; return cp; } /** * @brief F1 positioning measurement failure equality check */ bool eq_positioning_measurement_failure(const f1ap_positioning_measurement_failure_t *a, const f1ap_positioning_measurement_failure_t *b) { _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); _F1_EQ_CHECK_INT(a->lmf_measurement_id, b->lmf_measurement_id); _F1_EQ_CHECK_INT(a->ran_measurement_id, b->ran_measurement_id); _F1_EQ_CHECK_INT(a->cause, b->cause); _F1_EQ_CHECK_LONG(a->cause_value, b->cause_value); return true; } /** * @brief Free Allocated F1 positioning measurement failure */ void free_positioning_measurement_failure(f1ap_positioning_measurement_failure_t *msg) { // nothing to free } /** * @brief Encode F1 positioning measurement report to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_measurement_report(const f1ap_positioning_measurement_report_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningMeasurementReport; tmp->criticality = F1AP_Criticality_ignore; tmp->value.present = F1AP_InitiatingMessage__value_PR_PositioningMeasurementReport; F1AP_PositioningMeasurementReport_t *out = &tmp->value.choice.PositioningMeasurementReport; /* mandatory : TransactionID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementReportIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningMeasurementReportIEs__value_PR_TransactionID; ie1->value.choice.TransactionID = msg->transaction_id; /* mandatory : LMF_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementReportIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_LMF_MeasurementID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningMeasurementReportIEs__value_PR_LMF_MeasurementID; ie2->value.choice.LMF_MeasurementID = msg->lmf_measurement_id; /* mandatory : RAN_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementReportIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_RAN_MeasurementID; ie3->criticality = F1AP_Criticality_reject; ie3->value.present = F1AP_PositioningMeasurementReportIEs__value_PR_RAN_MeasurementID; ie3->value.choice.RAN_MeasurementID = msg->ran_measurement_id; /* Positioning Measurement Result List */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementReportIEs_t, ie4); ie4->id = F1AP_ProtocolIE_ID_id_PosMeasurementResultList; ie4->criticality = F1AP_Criticality_reject; ie4->value.present = F1AP_PositioningMeasurementReportIEs__value_PR_PosMeasurementResultList; const f1ap_pos_measurement_result_list_t *pos_meas_res_list = msg->pos_measurement_result_list; for (int i = 0; i < pos_meas_res_list->pos_measurement_result_list_length; i++) { // mandatory : Positioning Measurement Result List Item asn1cSequenceAdd(ie4->value.choice.PosMeasurementResultList.list, F1AP_PosMeasurementResultList_Item_t, f1_pos_meas_result_list_item); f1ap_pos_measurement_result_list_item_t *pos_meas_res_list_item = &pos_meas_res_list->pos_measurement_result_list_item[i]; F1AP_PosMeasurementResult_t *f1_posMeasurementResult = &f1_pos_meas_result_list_item->posMeasurementResult; f1ap_pos_measurement_result_t *pos_measurement_result = &pos_meas_res_list_item->pos_measurement_result; *f1_posMeasurementResult = encode_positioning_measurement_result(pos_measurement_result); f1_pos_meas_result_list_item->tRPID = pos_meas_res_list_item->trp_id; } return pdu; } /** * @brief Decode F1 Positioning Measurement report */ bool decode_positioning_measurement_report(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_measurement_report_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningMeasurementReport_t *in = &pdu->choice.initiatingMessage->value.choice.PositioningMeasurementReport; F1AP_PositioningMeasurementReportIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementReportIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementReportIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_LMF_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementReportIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_RAN_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementReportIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_PosMeasurementResultList, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_TransactionID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementReportIEs__value_PR_TransactionID); out->transaction_id = ie->value.choice.TransactionID; break; case F1AP_ProtocolIE_ID_id_LMF_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementReportIEs__value_PR_LMF_MeasurementID); out->lmf_measurement_id = ie->value.choice.LMF_MeasurementID; break; case F1AP_ProtocolIE_ID_id_RAN_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementReportIEs__value_PR_RAN_MeasurementID); out->ran_measurement_id = ie->value.choice.RAN_MeasurementID; break; case F1AP_ProtocolIE_ID_id_PosMeasurementResultList: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementReportIEs__value_PR_PosMeasurementResultList); F1AP_PosMeasurementResultList_t *f1_PosMeasurementResultList = &ie->value.choice.PosMeasurementResultList; uint32_t pos_meas_result_list_len = f1_PosMeasurementResultList->list.count; out->pos_measurement_result_list = calloc_or_fail(1, sizeof(*out->pos_measurement_result_list)); f1ap_pos_measurement_result_list_t *pos_meas_res_list = out->pos_measurement_result_list; pos_meas_res_list->pos_measurement_result_list_length = pos_meas_result_list_len; pos_meas_res_list->pos_measurement_result_list_item = calloc_or_fail(pos_meas_result_list_len, sizeof(*pos_meas_res_list->pos_measurement_result_list_item)); for (int i = 0; i < pos_meas_result_list_len; i++) { F1AP_PosMeasurementResultList_Item_t *f1_pos_meas_result_list_item = f1_PosMeasurementResultList->list.array[i]; f1ap_pos_measurement_result_list_item_t *pos_meas_result_list_item = &pos_meas_res_list->pos_measurement_result_list_item[i]; _F1_CHECK_EXP(decode_positioning_measurement_result(&f1_pos_meas_result_list_item->posMeasurementResult, &pos_meas_result_list_item->pos_measurement_result)); pos_meas_result_list_item->trp_id = f1_pos_meas_result_list_item->tRPID; } break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 Positioning Measurement report deep copy */ f1ap_positioning_measurement_report_t cp_positioning_measurement_report(const f1ap_positioning_measurement_report_t *orig) { // copy all mandatory fields that are not dynamic memory f1ap_positioning_measurement_report_t cp = { .transaction_id = orig->transaction_id, .lmf_measurement_id = orig->lmf_measurement_id, .ran_measurement_id = orig->ran_measurement_id, }; cp.pos_measurement_result_list = calloc_or_fail(1, sizeof(*cp.pos_measurement_result_list)); f1ap_pos_measurement_result_list_t *list_orig = orig->pos_measurement_result_list; f1ap_pos_measurement_result_list_t *list_cp = cp.pos_measurement_result_list; uint32_t pos_meas_result_list_len = list_orig->pos_measurement_result_list_length; list_cp->pos_measurement_result_list_length = pos_meas_result_list_len; list_cp->pos_measurement_result_list_item = calloc_or_fail(pos_meas_result_list_len, sizeof(*list_cp->pos_measurement_result_list_item)); for (int i = 0; i < pos_meas_result_list_len; i++) { f1ap_pos_measurement_result_list_item_t *item_cp = &list_cp->pos_measurement_result_list_item[i]; f1ap_pos_measurement_result_list_item_t *item_orig = &list_orig->pos_measurement_result_list_item[i]; item_cp->pos_measurement_result = cp_positioning_measurement_result(&item_orig->pos_measurement_result); item_cp->trp_id = item_orig->trp_id; } return cp; } /** * @brief F1 Positioning Measurement report equality check */ bool eq_positioning_measurement_report(const f1ap_positioning_measurement_report_t *a, const f1ap_positioning_measurement_report_t *b) { _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); _F1_EQ_CHECK_INT(a->lmf_measurement_id, b->lmf_measurement_id); _F1_EQ_CHECK_INT(a->ran_measurement_id, b->ran_measurement_id); f1ap_pos_measurement_result_list_t *list_a = a->pos_measurement_result_list; f1ap_pos_measurement_result_list_t *list_b = b->pos_measurement_result_list; uint32_t pos_meas_result_list_len = list_a->pos_measurement_result_list_length; _F1_EQ_CHECK_INT(list_b->pos_measurement_result_list_length, pos_meas_result_list_len); for (int i = 0; i < pos_meas_result_list_len; i++) { f1ap_pos_measurement_result_list_item_t *item_a = &list_a->pos_measurement_result_list_item[i]; f1ap_pos_measurement_result_list_item_t *item_b = &list_b->pos_measurement_result_list_item[i]; _F1_CHECK_EXP(eq_positioning_measurement_result(&item_a->pos_measurement_result, &item_b->pos_measurement_result)); _F1_EQ_CHECK_INT(item_a->trp_id, item_b->trp_id); } return true; } /** * @brief Free Allocated F1 Positioning Measurement report */ void free_positioning_measurement_report(f1ap_positioning_measurement_report_t *msg) { f1ap_pos_measurement_result_list_t *list = msg->pos_measurement_result_list; uint32_t pos_meas_result_list_len = list->pos_measurement_result_list_length; for (int i = 0; i < pos_meas_result_list_len; i++) { f1ap_pos_measurement_result_t *posMeasurementResult = &list->pos_measurement_result_list_item[i].pos_measurement_result; uint32_t pos_meas_result_length = posMeasurementResult->pos_measurement_result_item_length; for (int j = 0; j < pos_meas_result_length; j++) { f1ap_pos_measurement_result_item_t *item = &posMeasurementResult->pos_measurement_result_item[j]; f1ap_measured_results_value_t *measuredResultsValue = &item->measured_results_value; if (measuredResultsValue->present == F1AP_MEASURED_RESULTS_VALUE_PR_UL_ANGLEOFARRIVAL) { if (measuredResultsValue->choice.ul_angle_of_arrival.zenith_aoa) { free(measuredResultsValue->choice.ul_angle_of_arrival.zenith_aoa); } if (measuredResultsValue->choice.ul_angle_of_arrival.lcs_to_gcs_translation_aoa) { free(measuredResultsValue->choice.ul_angle_of_arrival.lcs_to_gcs_translation_aoa); } } } free(posMeasurementResult->pos_measurement_result_item); } free(msg->pos_measurement_result_list->pos_measurement_result_list_item); free(msg->pos_measurement_result_list); } /** * @brief Encode F1 positioning measurement abort to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_measurement_abort(const f1ap_positioning_measurement_abort_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningMeasurementAbort; tmp->criticality = F1AP_Criticality_ignore; tmp->value.present = F1AP_InitiatingMessage__value_PR_PositioningMeasurementAbort; F1AP_PositioningMeasurementAbort_t *out = &tmp->value.choice.PositioningMeasurementAbort; /* mandatory : TransactionID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementAbortIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningMeasurementAbortIEs__value_PR_TransactionID; ie1->value.choice.TransactionID = msg->transaction_id; /* mandatory : LMF_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementAbortIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_LMF_MeasurementID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningMeasurementAbortIEs__value_PR_LMF_MeasurementID; ie2->value.choice.LMF_MeasurementID = msg->lmf_measurement_id; /* mandatory : RAN_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementAbortIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_RAN_MeasurementID; ie3->criticality = F1AP_Criticality_reject; ie3->value.present = F1AP_PositioningMeasurementAbortIEs__value_PR_RAN_MeasurementID; ie3->value.choice.RAN_MeasurementID = msg->ran_measurement_id; return pdu; } /** * @brief Decode F1 positioning measurement abort */ bool decode_positioning_measurement_abort(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_measurement_abort_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningMeasurementAbort_t *in = &pdu->choice.initiatingMessage->value.choice.PositioningMeasurementAbort; F1AP_PositioningMeasurementAbortIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementAbortIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementAbortIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_LMF_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementAbortIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_RAN_MeasurementID, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_TransactionID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementAbortIEs__value_PR_TransactionID); out->transaction_id = ie->value.choice.TransactionID; break; case F1AP_ProtocolIE_ID_id_LMF_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementAbortIEs__value_PR_LMF_MeasurementID); out->lmf_measurement_id = ie->value.choice.LMF_MeasurementID; break; case F1AP_ProtocolIE_ID_id_RAN_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementAbortIEs__value_PR_RAN_MeasurementID); out->ran_measurement_id = ie->value.choice.RAN_MeasurementID; break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 positioning measurement abort deep copy */ f1ap_positioning_measurement_abort_t cp_positioning_measurement_abort(const f1ap_positioning_measurement_abort_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_positioning_measurement_abort_t cp = { .transaction_id = orig->transaction_id, .lmf_measurement_id = orig->lmf_measurement_id, .ran_measurement_id = orig->ran_measurement_id, }; return cp; } /** * @brief F1 positioning measurement abort equality check */ bool eq_positioning_measurement_abort(const f1ap_positioning_measurement_abort_t *a, const f1ap_positioning_measurement_abort_t *b) { _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); _F1_EQ_CHECK_INT(a->lmf_measurement_id, b->lmf_measurement_id); _F1_EQ_CHECK_INT(a->ran_measurement_id, b->ran_measurement_id); return true; } /** * @brief Free Allocated F1 positioning measurement abort */ void free_positioning_measurement_abort(f1ap_positioning_measurement_abort_t *msg) { // nothing to free } /** * @brief Encode F1 positioning measurement failure indication to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_measurement_failure_indication(const f1ap_positioning_measurement_failure_indication_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningMeasurementFailureIndication; tmp->criticality = F1AP_Criticality_ignore; tmp->value.present = F1AP_InitiatingMessage__value_PR_PositioningMeasurementFailureIndication; F1AP_PositioningMeasurementFailureIndication_t *out = &tmp->value.choice.PositioningMeasurementFailureIndication; /* mandatory : TransactionID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementFailureIndicationIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningMeasurementFailureIndicationIEs__value_PR_TransactionID; ie1->value.choice.TransactionID = msg->transaction_id; /* mandatory : LMF_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementFailureIndicationIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_LMF_MeasurementID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningMeasurementFailureIndicationIEs__value_PR_LMF_MeasurementID; ie2->value.choice.LMF_MeasurementID = msg->lmf_measurement_id; /* mandatory : RAN_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementFailureIndicationIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_RAN_MeasurementID; ie3->criticality = F1AP_Criticality_reject; ie3->value.present = F1AP_PositioningMeasurementFailureIndicationIEs__value_PR_RAN_MeasurementID; ie3->value.choice.RAN_MeasurementID = msg->ran_measurement_id; /* mandatory : Cause */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementFailureIndicationIEs_t, ie4); ie4->id = F1AP_ProtocolIE_ID_id_Cause; ie4->criticality = F1AP_Criticality_ignore; ie4->value.present = F1AP_PositioningMeasurementFailureIndicationIEs__value_PR_Cause; ie4->value.choice.Cause = encode_f1ap_cause(msg->cause, msg->cause_value); return pdu; } /** * @brief Decode F1 positioning measurement failure indication */ bool decode_positioning_measurement_failure_indication(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_measurement_failure_indication_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningMeasurementFailureIndication_t *in = &pdu->choice.initiatingMessage->value.choice.PositioningMeasurementFailureIndication; F1AP_PositioningMeasurementFailureIndicationIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementFailureIndicationIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementFailureIndicationIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_LMF_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementFailureIndicationIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_RAN_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementFailureIndicationIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_TransactionID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementFailureIndicationIEs__value_PR_TransactionID); out->transaction_id = ie->value.choice.TransactionID; break; case F1AP_ProtocolIE_ID_id_LMF_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementFailureIndicationIEs__value_PR_LMF_MeasurementID); out->lmf_measurement_id = ie->value.choice.LMF_MeasurementID; break; case F1AP_ProtocolIE_ID_id_RAN_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementFailureIndicationIEs__value_PR_RAN_MeasurementID); out->ran_measurement_id = ie->value.choice.RAN_MeasurementID; break; case F1AP_ProtocolIE_ID_id_Cause: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementFailureIndicationIEs__value_PR_Cause); _F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 positioning measurement failure indication deep copy */ f1ap_positioning_measurement_failure_indication_t cp_positioning_measurement_failure_indication( const f1ap_positioning_measurement_failure_indication_t *orig) { /* copy all mandatory fields that are not dynamic memory */ f1ap_positioning_measurement_failure_indication_t cp = { .transaction_id = orig->transaction_id, .lmf_measurement_id = orig->lmf_measurement_id, .ran_measurement_id = orig->ran_measurement_id, .cause = orig->cause, .cause_value = orig->cause_value, }; return cp; } /** * @brief F1 positioning measurement failure indication equality check */ bool eq_positioning_measurement_failure_indication(const f1ap_positioning_measurement_failure_indication_t *a, const f1ap_positioning_measurement_failure_indication_t *b) { _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); _F1_EQ_CHECK_INT(a->lmf_measurement_id, b->lmf_measurement_id); _F1_EQ_CHECK_INT(a->ran_measurement_id, b->ran_measurement_id); _F1_EQ_CHECK_INT(a->cause, b->cause); _F1_EQ_CHECK_LONG(a->cause_value, b->cause_value); return true; } /** * @brief Free Allocated F1 positioning measurement failure indication */ void free_positioning_measurement_failure_indication(f1ap_positioning_measurement_failure_indication_t *msg) { // nothing to free } /** * @brief Encode F1 positioning measurement update to ASN.1 */ F1AP_F1AP_PDU_t *encode_positioning_measurement_update(const f1ap_positioning_measurement_update_t *msg) { F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Message Type */ pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, tmp); tmp->procedureCode = F1AP_ProcedureCode_id_PositioningMeasurementUpdate; tmp->criticality = F1AP_Criticality_ignore; tmp->value.present = F1AP_InitiatingMessage__value_PR_PositioningMeasurementUpdate; F1AP_PositioningMeasurementUpdate_t *out = &tmp->value.choice.PositioningMeasurementUpdate; /* mandatory : TransactionID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementUpdateIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_PositioningMeasurementUpdateIEs__value_PR_TransactionID; ie1->value.choice.TransactionID = msg->transaction_id; /* mandatory : LMF_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementUpdateIEs_t, ie2); ie2->id = F1AP_ProtocolIE_ID_id_LMF_MeasurementID; ie2->criticality = F1AP_Criticality_reject; ie2->value.present = F1AP_PositioningMeasurementUpdateIEs__value_PR_LMF_MeasurementID; ie2->value.choice.LMF_MeasurementID = msg->lmf_measurement_id; /* mandatory : RAN_MeasurementID */ asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementUpdateIEs_t, ie3); ie3->id = F1AP_ProtocolIE_ID_id_RAN_MeasurementID; ie3->criticality = F1AP_Criticality_reject; ie3->value.present = F1AP_PositioningMeasurementUpdateIEs__value_PR_RAN_MeasurementID; ie3->value.choice.RAN_MeasurementID = msg->ran_measurement_id; /* optional: SRS Configuration */ if (msg->srs_configuration) { asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningMeasurementUpdateIEs_t, ie4); ie4->id = F1AP_ProtocolIE_ID_id_SRSConfiguration; ie4->criticality = F1AP_Criticality_ignore; ie4->value.present = F1AP_PositioningMeasurementUpdateIEs__value_PR_SRSConfiguration; f1ap_srs_carrier_list_t *srs_carrier_list = &msg->srs_configuration->srs_carrier_list; ie4->value.choice.SRSConfiguration.sRSCarrier_List = encode_srs_carrier_list(srs_carrier_list); } return pdu; } /** * @brief Decode F1 Positioning Measurement Update */ bool decode_positioning_measurement_update(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_measurement_update_t *out) { DevAssert(out != NULL); memset(out, 0, sizeof(*out)); F1AP_PositioningMeasurementUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.PositioningMeasurementUpdate; F1AP_PositioningMeasurementUpdateIEs_t *ie; F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementUpdateIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementUpdateIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_LMF_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementUpdateIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_RAN_MeasurementID, true); F1AP_LIB_FIND_IE(F1AP_PositioningMeasurementUpdateIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_SRSConfiguration, false); for (int i = 0; i < in->protocolIEs.list.count; ++i) { ie = in->protocolIEs.list.array[i]; AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); switch (ie->id) { case F1AP_ProtocolIE_ID_id_TransactionID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementUpdateIEs__value_PR_TransactionID); out->transaction_id = ie->value.choice.TransactionID; break; case F1AP_ProtocolIE_ID_id_LMF_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementUpdateIEs__value_PR_LMF_MeasurementID); out->lmf_measurement_id = ie->value.choice.LMF_MeasurementID; break; case F1AP_ProtocolIE_ID_id_RAN_MeasurementID: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementUpdateIEs__value_PR_RAN_MeasurementID); out->ran_measurement_id = ie->value.choice.RAN_MeasurementID; break; case F1AP_ProtocolIE_ID_id_SRSConfiguration: _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningMeasurementUpdateIEs__value_PR_SRSConfiguration); F1AP_SRSCarrier_List_t *f1_sRSCarrier_List = &ie->value.choice.SRSConfiguration.sRSCarrier_List; out->srs_configuration = calloc_or_fail(1, sizeof(*out->srs_configuration)); f1ap_srs_carrier_list_t *srs_carrier_list = &out->srs_configuration->srs_carrier_list; decode_srs_carrier_list(srs_carrier_list, f1_sRSCarrier_List); break; default: PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); break; } } return true; } /** * @brief F1 Positioning Measurement Update deep copy */ f1ap_positioning_measurement_update_t cp_positioning_measurement_update(const f1ap_positioning_measurement_update_t *orig) { // copy all mandatory fields that are not dynamic memory f1ap_positioning_measurement_update_t cp = { .transaction_id = orig->transaction_id, .lmf_measurement_id = orig->lmf_measurement_id, .ran_measurement_id = orig->ran_measurement_id, }; /* optional: SRS Configuration */ if (orig->srs_configuration) { cp.srs_configuration = calloc_or_fail(1, sizeof(*cp.srs_configuration)); f1ap_srs_carrier_list_t *srs_carrier_list_cp = &cp.srs_configuration->srs_carrier_list; f1ap_srs_carrier_list_t *srs_carrier_list = &orig->srs_configuration->srs_carrier_list; *srs_carrier_list_cp = cp_srs_carrier_list(srs_carrier_list); } return cp; } /** * @brief F1 Positioning Measurement Update equality check */ bool eq_positioning_measurement_update(const f1ap_positioning_measurement_update_t *a, const f1ap_positioning_measurement_update_t *b) { _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); _F1_EQ_CHECK_INT(a->lmf_measurement_id, b->lmf_measurement_id); _F1_EQ_CHECK_INT(a->ran_measurement_id, b->ran_measurement_id); /* optional: SRS Configuration */ if ((a->srs_configuration == NULL) != (b->srs_configuration == NULL)) { return false; } if (a->srs_configuration) { f1ap_srs_carrier_list_t *srs_carrier_list_a = &a->srs_configuration->srs_carrier_list; f1ap_srs_carrier_list_t *srs_carrier_list_b = &b->srs_configuration->srs_carrier_list; _F1_CHECK_EXP(eq_srs_carrier_list(srs_carrier_list_a, srs_carrier_list_b)); } return true; } /** * @brief Free Allocated F1 Positioning Measurement Update */ void free_positioning_measurement_update(f1ap_positioning_measurement_update_t *msg) { /* SRS Configuration */ if (msg->srs_configuration) { f1ap_srs_carrier_list_t *srs_carrier_list = &msg->srs_configuration->srs_carrier_list; free_srs_carrier_list(srs_carrier_list); free(msg->srs_configuration); } }