Reference: 3GPP 38.473 v16.21.0 Mandatory fields: Transaction ID (supported) LMF Measurement ID (supported) RAN Measurement ID (supported) Optional fields: SRS Configuration (supported)
6421 lines
322 KiB
C
6421 lines
322 KiB
C
/*
|
|
* 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);
|
|
}
|
|
}
|