diff --git a/lib/include/srslte/asn1/liblte_m2ap.h b/lib/include/srslte/asn1/liblte_m2ap.h new file mode 100644 index 000000000..942fbe51b --- /dev/null +++ b/lib/include/srslte/asn1/liblte_m2ap.h @@ -0,0 +1,1740 @@ +/******************************************************************************* + * + * Copyright 2018 Software Radio Systems Limited + * + *******************************************************************************/ +#ifndef SRSLTE_LIBLTE_M2AP_H +#define SRSLTE_LIBLTE_M2AP_H + +/******************************************************************************* + * Warnings/Todos + *******************************************************************************/ +// Extensions are not yet handled correctly + +/******************************************************************************* + * INCLUDES + *******************************************************************************/ +#include + +/******************************************************************************* + LOGGING +*******************************************************************************/ +typedef void (*log_handler_t)(void *ctx, char *str); +void liblte_log_register_handler(void *ctx, log_handler_t handler); + +/******************************************************************************* + * MAX defines + *******************************************************************************/ +#define LIBLTE_M2AP_MAXPRIVATEIES 256 +#define LIBLTE_M2AP_MAXNOOFMBSFNAREAS 8 +#define LIBLTE_M2AP_MAXNOOFMBSFN_ALLOCATIONS 15 +#define LIBLTE_M2AP_MAXNOOFPMCHSPERMBSFNAREA 256 +#define LIBLTE_M2AP_MAXNOOFCELLS 256 +#define LIBLTE_M2AP_MAXNOOFMBMSSERVICEAREASPERCELL 256 +#define LIBLTE_M2AP_MAXNOOFSESSIONSPERPMCH 29 +#define LIBLTE_M2AP_MAXNOOFERRORS 256 +#define LIBLTE_M2AP_MAXNROFINDIVIDUALM2CONNECTIONSTORESET 256 +#define LIBLTE_M2AP_MAXNOOFCOUNTINGSERVICE 16 + +/******************************************************************************* + * Elementary Procedures + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_PROC_ID_SESSIONSTART = 0, + LIBLTE_M2AP_PROC_ID_SESSIONSTOP = 1, + LIBLTE_M2AP_PROC_ID_MBMSSCHEDULINGINFORMATION = 2, + LIBLTE_M2AP_PROC_ID_ERRORINDICATION = 3, + LIBLTE_M2AP_PROC_ID_RESET = 4, + LIBLTE_M2AP_PROC_ID_M2SETUP = 5, + LIBLTE_M2AP_PROC_ID_ENBCONFIGURATIONUPDATE = 6, + LIBLTE_M2AP_PROC_ID_MCECONFIGURATIONUPDATE = 7, + LIBLTE_M2AP_PROC_ID_PRIVATEMESSAGE = 8, + LIBLTE_M2AP_PROC_ID_SESSIONUPDATE = 9, + LIBLTE_M2AP_PROC_ID_MBMSSERVICECOUNTING = 10, + LIBLTE_M2AP_PROC_ID_MBMSSERVICECOUNTINGRESULTSREPORT = 11, + LIBLTE_M2AP_PROC_N_ITEMS, +}LIBLTE_M2AP_PROC_ENUM; +static const char liblte_m2ap_proc_text[LIBLTE_M2AP_PROC_N_ITEMS][64] = { + "id-sessionStart", + "id-sessionStop", + "id-mbmsSchedulingInformation", + "id-errorIndication", + "id-reset", + "id-m2Setup", + "id-eNBConfigurationUpdate", + "id-mCEConfigurationUpdate", + "id-privateMessage", + "id-sessionUpdate", + "id-mbmsServiceCounting", + "id-mbmsServiceCountingResultsReport" +}; + +/******************************************************************************* + * ProtocolIE Ids + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_IE_ID_MCE_MBMS_M2AP_ID = 0, + LIBLTE_M2AP_IE_ID_ENB_MBMS_M2AP_ID = 1, + LIBLTE_M2AP_IE_ID_TMGI = 2, + LIBLTE_M2AP_IE_ID_MBMS_SESSION_ID = 3, + LIBLTE_M2AP_IE_ID_MBMS_SERVICE_AREA = 6, + LIBLTE_M2AP_IE_ID_TNL_INFORMATION = 7, + LIBLTE_M2AP_IE_ID_CRITICALITYDIAGNOSTICS = 8, + LIBLTE_M2AP_IE_ID_CAUSE = 9, + LIBLTE_M2AP_IE_ID_MBSFN_AREA_CONFIGURATION_LIST = 10, + LIBLTE_M2AP_IE_ID_PMCH_CONFIGURATION_LIST = 11, + LIBLTE_M2AP_IE_ID_PMCH_CONFIGURATION_ITEM = 12, + LIBLTE_M2AP_IE_ID_GLOBALENB_ID = 13, + LIBLTE_M2AP_IE_ID_ENBNAME = 14, + LIBLTE_M2AP_IE_ID_ENB_MBMS_CONFIGURATION_DATA_LIST = 15, + LIBLTE_M2AP_IE_ID_ENB_MBMS_CONFIGURATION_DATA_ITEM = 16, + LIBLTE_M2AP_IE_ID_GLOBALMCE_ID = 17, + LIBLTE_M2AP_IE_ID_MCENAME = 18, + LIBLTE_M2AP_IE_ID_MCCHRELATEDBCCH_CONFIGPERMBSFNAREA = 19, + LIBLTE_M2AP_IE_ID_MCCHRELATEDBCCH_CONFIGPERMBSFNAREA_ITEM = 20, + LIBLTE_M2AP_IE_ID_TIMETOWAIT = 21, + LIBLTE_M2AP_IE_ID_MBSFN_SUBFRAME_CONFIGURATION_LIST = 22, + LIBLTE_M2AP_IE_ID_MBSFN_SUBFRAME_CONFIGURATION_ITEM = 23, + LIBLTE_M2AP_IE_ID_COMMON_SUBFRAME_ALLOCATION_PERIOD = 24, + LIBLTE_M2AP_IE_ID_MCCH_UPDATE_TIME = 25, + LIBLTE_M2AP_IE_ID_ENB_MBMS_CONFIGURATION_DATA_LIST_CONFIGUPDATE = 26, + LIBLTE_M2AP_IE_ID_ENB_MBMS_CONFIGURATION_DATA_CONFIGUPDATE_ITEM = 27, + LIBLTE_M2AP_IE_ID_MBMS_SERVICE_ASSOCIATEDLOGICALM2_CONNECTIONITEM = 28, + LIBLTE_M2AP_IE_ID_MBSFN_AREA_ID = 29, + LIBLTE_M2AP_IE_ID_RESETTYPE = 30, + LIBLTE_M2AP_IE_ID_MBMS_SERVICE_ASSOCIATEDLOGICALM2_CONNECTIONLISTRESACK = 31, + LIBLTE_M2AP_IE_ID_MBMS_COUNTING_REQUEST_SESSION = 32, + LIBLTE_M2AP_IE_ID_MBMS_COUNTING_REQUEST_SESSION_ITEM = 33, + LIBLTE_M2AP_IE_ID_MBMS_COUNTING_RESULT_LIST = 34, + LIBLTE_M2AP_IE_ID_MBMS_COUNTING_RESULT_ITEM = 35, + LIBLTE_M2AP_IE_N_ITEMS +}LIBLTE_M2AP_IE_ENUM; +static const char liblte_m2ap_ie_text[LIBLTE_M2AP_IE_N_ITEMS][64] = { + "id-MCE-MBMS-M2AP-ID", + "id-ENB-MBMS-M2AP-ID", + "id-TMGI", + "id-MBMS-Session-ID", + "id-MBMS-Service-Area", + "id-TNL-Information", + "id-CriticalityDiagnostics", + "id-Cause", + "id-MBSFN-Area-Configuration-List", + "id-PMCH-Configuration-List", + "id-PMCH-Configuration-Item", + "id-GlobalENB-ID", + "id-ENBname", + "id-ENB-MBMS-Configuration-data-List", + "id-ENB-MBMS-Configuration-data-Item", + "id-GlobalMCE-ID", + "id-MCEname", + "id-MCCHrelatedBCCH-ConfigPerMBSFNArea", + "id-MCCHrelatedBCCH-ConfigPerMBSFNArea-Item", + "id-TimeToWait", + "id-MBSFN-Subframe-Configuration-List", + "id-MBSFN-Subframe-Configuration-Item", + "id-Common-Subframe-Allocation-Period", + "id-MCCH-Update-Time", + "id-ENB-MBMS-Configuration-data-List-ConfigUpdate", + "id-ENB-MBMS-Configuration-data-ConfigUpdate-Item", + "id-MBMS-Service-associatedLogicalM2-ConnectionItem", + "id-MBSFN-Area-ID", + "id-ResetType", + "id-MBMS-Service-associatedLogicalM2-ConnectionListResAck", + "id-MBMS-Counting-Request-Session", + "id-MBMS-Counting-Request-Session-Item", + "id-MBMS-Counting-Result-List", + "id-MBMS-Counting-Result-Item" +}; + +/******************************************************************************* + * ProtocolIE AllocatedSubFramesEnd INTEGER + *******************************************************************************/ +//lb:0;ub:1535 +typedef struct{ + uint16_t allocated_subframes_end; +}LIBLTE_M2AP_ALLOCATED_SUBFRAMES_END_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_allocatedsubframesend( + LIBLTE_M2AP_ALLOCATED_SUBFRAMES_END_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_allocatedsubframesend( + uint8_t **ptr, + LIBLTE_M2AP_ALLOCATED_SUBFRAMES_END_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE CauseMisc CHOICE + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_CAUSE_MISC_CONTROL_PROCESSING_OVERLOAD, + LIBLTE_M2AP_CAUSE_MISC_HARDWARE_FAILURE, + LIBLTE_M2AP_CAUSE_MISC_OM_INTERVENTION, + LIBLTE_M2AP_CAUSE_MISC_UNSPECIFIED, + LIBLTE_M2AP_CAUSE_MISC_N_ITEMS +}LIBLTE_M2AP_CAUSE_CHOICE_MISC_ENUM; +static const char liblte_s1ap_cause_misc_text[LIBLTE_M2AP_CAUSE_MISC_N_ITEMS][80] = { + "control-processing-overload", + "hardware-failure", + "om-intervention", + "unspecified", +}; + +typedef struct{ + bool ext; + LIBLTE_M2AP_CAUSE_CHOICE_MISC_ENUM cause; +}LIBLTE_M2AP_CAUSE_MISC_STRUCT; + +/******************************************************************************* + * ProtocolIE CauseNas CHOICE + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_CAUSE_NAS_UNSPECIFIED, + LIBLTE_M2AP_CAUSE_NAS_N_ITEMS +}LIBLTE_M2AP_CAUSE_CHOICE_NAS_ENUM; +static const char liblte_s1ap_cause_nas_text[LIBLTE_M2AP_CAUSE_NAS_N_ITEMS][80] = { + "unspecified", +}; + +typedef struct{ + bool ext; + LIBLTE_M2AP_CAUSE_CHOICE_NAS_ENUM cause; +}LIBLTE_M2AP_CAUSE_NAS_STRUCT; + +/******************************************************************************* + * ProtocolIE CauseProtocol CHOICE + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_CAUSE_PROTOCOL_TRANSFER_SYNTAX_ERROR, + LIBLTE_M2AP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_REJECT, + LIBLTE_M2AP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_IGNORE_AND_NOTIFY, + LIBLTE_M2AP_CAUSE_PROTOCOL_MESSAGE_NOT_COMPATIBLE_WITH_RECEIVER_STATE, + LIBLTE_M2AP_CAUSE_PROTOCOL_SEMANTIC_ERROR, + LIBLTE_M2AP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_FALSELY_CONSTRUCTED_MESSAGE, + LIBLTE_M2AP_CAUSE_PROTOCOL_UNSPECIFIED, + LIBLTE_M2AP_CAUSE_PROTOCOL_N_ITEMS +}LIBLTE_M2AP_CAUSE_CHOICE_PROTOCOL_ENUM; +static const char liblte_m2ap_cause_protocol_text[LIBLTE_M2AP_CAUSE_PROTOCOL_N_ITEMS][80] = { + "transfer-syntax-error", + "abstract-syntax-error-reject", + "abstract-syntax-error-ignore-and-notify", + "message-not-compatible-with-receiver-state", + "semantic-error", + "abstract-syntax-error-falsely-constructed-message", + "unspecified", +}; + +typedef struct{ + bool ext; + LIBLTE_M2AP_CAUSE_CHOICE_PROTOCOL_ENUM cause; +}LIBLTE_M2AP_CAUSE_PROTOCOL_STRUCT; + +/******************************************************************************* + * ProtocolIE CauseRadioNetwork CHOICE + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_CAUSE_RADIONETWORK_UNKNOWN_OR_ALREADY_ALLOCATED_MCE_MBMS_M2AP_ID, + LIBLTE_M2AP_CAUSE_RADIONETWORK_UNKNOWN_OR_ALREADY_ALLOCATED_ENB_MBMS_M2AP_ID, + LIBLTE_M2AP_CAUSE_RADIONETWORK_UNKNOWN_OR_INCONSISTENT_PAIR_OF_MBMS_M2AP_IDS, + LIBLTE_M2AP_CAUSE_RADIONETWORK_RADIO_RESOURCES_NOT_AVAILABLE, + LIBLTE_M2AP_CAUSE_RADIONETWORK_INTERACTION_WITH_OTHER_PROCEDURE, + LIBLTE_M2AP_CAUSE_RADIONETWORK_UNSPECIFIED, + LIBLTE_M2AP_CAUSE_RADIONETWORK_N_ITEMS +}LIBLTE_M2AP_CAUSE_CHOICE_RADIONETWORK_ENUM; +static const char liblte_m2ap_cause_radionetwork_text[LIBLTE_M2AP_CAUSE_RADIONETWORK_N_ITEMS][80] = { + "unknown-or-already-allocated-MCE-MBMS-M2AP-ID", + "unknown-or-already-allocated-eNB-MBMS-M2AP-ID", + "unknown-or-inconsistent-pair-of-MBMS-M2AP-IDs", + "radio-resources-not-available", + "interaction-with-other-procedure", + "unspecified", +}; + +typedef struct{ + bool ext; + LIBLTE_M2AP_CAUSE_CHOICE_RADIONETWORK_ENUM cause; +}LIBLTE_M2AP_CAUSE_RADIONETWORK_STRUCT; + +/******************************************************************************* + * ProtocolIE CauseTransport CHOICE + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_CAUSE_TRANSPORT_TRANSPORT_RESOURCE_UNAVAILABLE, + LIBLTE_M2AP_CAUSE_TRANSPORT_UNSPECIFIED, + LIBLTE_M2AP_CAUSE_TRANSPORT_N_ITEMS +}LIBLTE_M2AP_CAUSE_CHOICE_TRANSPORT_ENUM; +static const char liblte_m2ap_cause_transport_text[LIBLTE_M2AP_CAUSE_TRANSPORT_N_ITEMS][80] = { + "transport-resource-unavailable", + "unspecified", +}; + +typedef struct{ + bool ext; + LIBLTE_M2AP_CAUSE_CHOICE_TRANSPORT_ENUM cause; +}LIBLTE_M2AP_CAUSE_TRANSPORT_STRUCT; + +/******************************************************************************* + * ProtocolIE Cause CHOICE + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_CAUSE_CHOICE_RADIONETWORK, + LIBLTE_M2AP_CAUSE_CHOICE_TRANSPORT, + LIBLTE_M2AP_CAUSE_CHOICE_NAS, + LIBLTE_M2AP_CAUSE_CHOICE_PROTOCOL, + LIBLTE_M2AP_CAUSE_CHOICE_MISC, + LIBLTE_M2AP_CAUSE_CHOICE_N_ITEMS, +}LIBLTE_M2AP_CAUSE_CHOICE_ENUM; +static const char liblte_m2ap_cause_choice_text[LIBLTE_M2AP_CAUSE_CHOICE_N_ITEMS][50] = { + "radioNetwork", + "transport", + "nas", + "protocol", + "misc", +}; + +typedef union{ + LIBLTE_M2AP_CAUSE_RADIONETWORK_STRUCT radioNetwork; + LIBLTE_M2AP_CAUSE_TRANSPORT_STRUCT transport; + LIBLTE_M2AP_CAUSE_NAS_STRUCT nas; + LIBLTE_M2AP_CAUSE_PROTOCOL_STRUCT protocol; + LIBLTE_M2AP_CAUSE_MISC_STRUCT misc; +}LIBLTE_M2AP_CAUSE_CHOICE_UNION; + +typedef struct{ + bool ext; + LIBLTE_M2AP_CAUSE_CHOICE_UNION choice; + LIBLTE_M2AP_CAUSE_CHOICE_ENUM choice_type; +}LIBLTE_M2AP_CAUSE_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_cause( + LIBLTE_M2AP_CAUSE_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_cause( + uint8_t **ptr, + LIBLTE_M2AP_CAUSE_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE Criticality ENUMERATED + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_CRITICALITY_REJECT, + LIBLTE_M2AP_CRITICALITY_IGNORE, + LIBLTE_M2AP_CRITICALITY_NOTIFY, + LIBLTE_M2AP_CRITICALITY_N_ITEMS, +}LIBLTE_M2AP_CRITICALITY_ENUM; +static const char liblte_m2ap_criticality_text[LIBLTE_M2AP_CRITICALITY_N_ITEMS][80] = { + "reject", + "ignore", + "notify", +}; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_criticality( + LIBLTE_M2AP_CRITICALITY_ENUM *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_criticality( + uint8_t **ptr, + LIBLTE_M2AP_CRITICALITY_ENUM *ie); + +/******************************************************************************* + * ProtocolIE ProtocolIE_ID INTEGER + *******************************************************************************/ +typedef struct{ + uint16_t ProtocolIE_ID; +}LIBLTE_M2AP_PROTOCOLIE_ID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_protocolie_id( + LIBLTE_M2AP_PROTOCOLIE_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_protocolie_id( + uint8_t **ptr, + LIBLTE_M2AP_PROTOCOLIE_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE ProtocolExtensionID INTEGER + *******************************************************************************/ +typedef struct{ + uint16_t ProtocolExtensionID; +}LIBLTE_M2AP_PROTOCOLEXTENSIONID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolextensionid( + LIBLTE_M2AP_PROTOCOLEXTENSIONID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolextensionid( + uint8_t **ptr, + LIBLTE_M2AP_PROTOCOLEXTENSIONID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE ProtocolExtensionField SEQUENCE + ********************************************************************************/ +typedef struct{ + LIBLTE_M2AP_PROTOCOLEXTENSIONID_STRUCT id; + LIBLTE_M2AP_CRITICALITY_ENUM criticality; + LIBLTE_ASN1_OPEN_TYPE_STRUCT extensionValue; +}LIBLTE_M2AP_PROTOCOLEXTENSIONFIELD_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_protocolextensionfield( + LIBLTE_M2AP_PROTOCOLEXTENSIONFIELD_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_protocolextensionfield( + uint8_t **ptr, + LIBLTE_M2AP_PROTOCOLEXTENSIONFIELD_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE ProtocolIE_SingleContainer SEQUENCE + *******************************************************************************/ +typedef struct{ + LIBLTE_M2AP_PROTOCOLIE_ID_STRUCT id; + LIBLTE_M2AP_CRITICALITY_ENUM criticality; + LIBLTE_ASN1_OPEN_TYPE_STRUCT value; +}LIBLTE_M2AP_PROTOCOLIE_SINGLECONTAINER_STRUCT; + +LIBLTE_ERROR_ENUM liblte_s1ap_pack_protocolie_singlecontainer( + LIBLTE_M2AP_PROTOCOLIE_SINGLECONTAINER_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_s1ap_unpack_protocolie_singlecontainer( + uint8_t **ptr, + LIBLTE_M2AP_PROTOCOLIE_SINGLECONTAINER_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE ProtocolExtensionContainer DYNAMIC SEQUENCE OF + *******************************************************************************/ +// lb:1, ub:65535 +typedef struct{ + uint32_t len; + LIBLTE_M2AP_PROTOCOLEXTENSIONFIELD_STRUCT buffer[32]; //WARNING: Artificial limit to reduce memory footprint +}LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_protocolextensioncontainer( + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_protocolextensioncontainer( + uint8_t **ptr, + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE PLMNidentity STATIC OCTET STRING + *******************************************************************************/ +#define LIBLTE_M2AP_PLMN_IDENTITY_OCTET_STRING_LEN 3 +typedef struct{ + uint8_t buffer[LIBLTE_M2AP_PLMN_IDENTITY_OCTET_STRING_LEN]; +}LIBLTE_M2AP_PLMN_IDENTITY_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_plmnidentity( + LIBLTE_M2AP_PLMN_IDENTITY_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_plmnidentity( + uint8_t **ptr, + LIBLTE_M2AP_PLMN_IDENTITY_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE EUTRANCellIdentifier STATIC BIT STRING + *******************************************************************************/ +#define LIBLTE_M2AP_EUTRAN_CELL_IDENTIFIER_BIT_STRING_LEN 28 +typedef struct{ + uint32_t eUTRANCellIdentifier; +}LIBLTE_M2AP_EUTRAN_CELL_IDENTIFIER_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_eutrancellidentifier( + LIBLTE_M2AP_EUTRAN_CELL_IDENTIFIER_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_eutrancellidentifier( + uint8_t **ptr, + LIBLTE_M2AP_EUTRAN_CELL_IDENTIFIER_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE ECGI SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_PLMN_IDENTITY_STRUCT pLMN_Identity; + LIBLTE_M2AP_EUTRAN_CELL_IDENTIFIER_STRUCT EUTRANCellIdentifier; + bool iE_Extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; +}LIBLTE_M2AP_ECGI_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_ecgi( + LIBLTE_M2AP_ECGI_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_ecgi( + uint8_t **ptr, + LIBLTE_M2AP_ECGI_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE CellReservationInfo ENUMERATED + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_CELL_RESERVATION_INFO_RESERVED_CELL, + LIBLTE_M2AP_CELL_RESERVATION_INFO_NON_RESERVED_CELL, +}LIBLTE_M2AP_CELL_RESERVATION_INFO_ENUM; + +typedef struct{ + bool ext; + LIBLTE_M2AP_CELL_RESERVATION_INFO_ENUM e; +}LIBLTE_M2AP_CELL_RESERVATION_INFO_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_cellreservationinfo( + LIBLTE_M2AP_CELL_RESERVATION_INFO_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_cellreservationinfo( + uint8_t **ptr, + LIBLTE_M2AP_CELL_RESERVATION_INFO_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE CellInformation SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_ECGI_STRUCT eCGI; + LIBLTE_M2AP_CELL_RESERVATION_INFO_STRUCT cellReservationInfo; + bool ie_extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT ie_extensions; +}LIBLTE_M2AP_CELL_INFORMATION_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_cellinformation( + LIBLTE_M2AP_CELL_INFORMATION_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_cellinformation( + uint8_t **ptr, + LIBLTE_M2AP_CELL_INFORMATION_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE CellInformationList SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + uint16_t len; + LIBLTE_M2AP_CELL_INFORMATION_STRUCT buffer[32]; //artificial limit to 32 +}LIBLTE_M2AP_CELL_INFORMATION_LIST_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_cellinformationlist( + LIBLTE_M2AP_CELL_INFORMATION_LIST_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_cellinformationlist( + uint8_t **ptr, + LIBLTE_M2AP_CELL_INFORMATION_LIST_STRUCT *ie); +/******************************************************************************* + * ProtocolIE ProcedureCode INTEGER + *******************************************************************************/ +typedef struct{ + uint8_t ProcedureCode; +}LIBLTE_M2AP_PROCEDURECODE_STRUCT; + +/******************************************************************************* + * ProtocolIE TriggeringMessage ENUMERATED + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_TRIGGERINGMESSAGE_INITIATING_MESSAGE, + LIBLTE_M2AP_TRIGGERINGMESSAGE_SUCCESSFUL_OUTCOME, + LIBLTE_M2AP_TRIGGERINGMESSAGE_UNSUCCESSFULL_OUTCOME, + LIBLTE_M2AP_TRIGGERINGMESSAGE_N_ITEMS, +}LIBLTE_M2AP_TRIGGERINGMESSAGE_ENUM; +static const char liblte_m2ap_triggeringmessage_text[LIBLTE_M2AP_TRIGGERINGMESSAGE_N_ITEMS][80] = { + "initiating-message", + "successful-outcome", + "unsuccessfull-outcome", +}; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_triggeringmessage( + LIBLTE_M2AP_TRIGGERINGMESSAGE_ENUM *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_triggeringmessage( + uint8_t **ptr, + LIBLTE_M2AP_TRIGGERINGMESSAGE_ENUM *ie); + +/******************************************************************************* + * ProtocolIE TypeOfError ENUMERATED + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_TYPEOFERROR_NOT_UNDERSTOOD, + LIBLTE_M2AP_TYPEOFERROR_MISSING, + LIBLTE_M2AP_TYPEOFERROR_N_ITEMS, +}LIBLTE_M2AP_TYPEOFERROR_ENUM; +static const char liblte_M2ap_typeoferror_text[LIBLTE_M2AP_TYPEOFERROR_N_ITEMS][80] = { + "not-understood", + "missing", +}; + +typedef struct{ + bool ext; + LIBLTE_M2AP_TYPEOFERROR_ENUM e; +}LIBLTE_M2AP_TYPEOFERROR_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_typeoferror( + LIBLTE_M2AP_TYPEOFERROR_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_typeoferror( + uint8_t **ptr, + LIBLTE_M2AP_TYPEOFERROR_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE CriticalityDiagnostics_IE_Item SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_CRITICALITY_ENUM iECriticality; + LIBLTE_M2AP_PROTOCOLIE_ID_STRUCT iE_ID; + LIBLTE_M2AP_TYPEOFERROR_STRUCT typeOfError; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; + bool iE_Extensions_present; +}LIBLTE_M2AP_CRITICALITYDIAGNOSTICS_IE_ITEM_STRUCT; + +/******************************************************************************* + * ProtocolIE CriticalityDiagnostics_IE_List DYNAMIC SEQUENCE OF + *******************************************************************************/ +// lb:1, ub:256 +typedef struct{ + uint32_t len; + LIBLTE_M2AP_CRITICALITYDIAGNOSTICS_IE_ITEM_STRUCT buffer[32]; //WARNING: Artificial limit to reduce memory footprint +}LIBLTE_M2AP_CRITICALITYDIAGNOSTICS_IE_LIST_STRUCT; + +/******************************************************************************* + * ProtocolIE CriticalityDiagnostics SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_PROCEDURECODE_STRUCT procedureCode; + bool procedureCode_present; + LIBLTE_M2AP_TRIGGERINGMESSAGE_ENUM triggeringMessage; + bool triggeringMessage_present; + LIBLTE_M2AP_CRITICALITY_ENUM procedureCriticality; + bool procedureCriticality_present; + LIBLTE_M2AP_CRITICALITYDIAGNOSTICS_IE_LIST_STRUCT iEsCriticalityDiagnostics; + bool iEsCriticalityDiagnostics_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; + bool iE_Extensions_present; +}LIBLTE_M2AP_CRITICALITYDIAGNOSTICS_STRUCT; + +/******************************************************************************* + * ProtocolIE ENB-ID STATIC BIT STRING + *******************************************************************************/ +#define LIBLTE_M2AP_ENBID_BIT_STRING_LEN 20 +typedef struct{ + bool ext; + uint8_t buffer[20]; +}LIBLTE_M2AP_ENB_ID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_enbid( + LIBLTE_M2AP_ENB_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_enbid( + uint8_t **ptr, + LIBLTE_M2AP_ENB_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MCE-ID STATIC OCTET STRING + *******************************************************************************/ +#define LIBLTE_M2AP_MCEID_OCTET_STRING_LEN 2 +typedef struct{ + bool ext; + uint8_t buffer[2]; +}LIBLTE_M2AP_MCE_ID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mceid( + LIBLTE_M2AP_MCE_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mceid( + uint8_t **ptr, + LIBLTE_M2AP_MCE_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MCE-Name PRINTABLE STRING + *******************************************************************************/ +typedef struct{ + bool ext; + uint32_t n_octets; + uint8_t buffer[150]; +}LIBLTE_M2AP_MCE_NAME_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mcename( + LIBLTE_M2AP_MCE_NAME_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mceid( + uint8_t **ptr, + LIBLTE_M2AP_MCE_NAME_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MCE-MBMS-M2AP-ID INTEGER + *******************************************************************************/ +//lb:0;ub:16777215 +typedef struct{ + uint32_t mce_mbms_m2ap_id; +}LIBLTE_M2AP_MCE_MBMS_M2AP_ID_STRUCT; + + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mcembmsm2apid( + LIBLTE_M2AP_MCE_MBMS_M2AP_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mcembmsm2apid( + uint8_t **ptr, + LIBLTE_M2AP_MCE_MBMS_M2AP_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBSFN-Synchronization-Area-Id INTEGER + *******************************************************************************/ +typedef struct{ + uint32_t mbsfn_synchronisation_area_id; +}LIBLTE_M2AP_MBSFN_SYNCHRONISATION_AREA_ID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnsynchronisationareaid( + LIBLTE_M2AP_MBSFN_SYNCHRONISATION_AREA_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnsynchronisationareaid( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_SYNCHRONISATION_AREA_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBMS-Service-Area DYNAMIC OCTET STRING + *******************************************************************************/ +// lb:0, ub:512 +typedef struct{ + uint32_t n_octets; + uint8_t buffer[512]; +}LIBLTE_M2AP_MBMS_SERVICE_AREA_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmsservicearea( + LIBLTE_M2AP_MBMS_SERVICE_AREA_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmsservicearea( + uint8_t **ptr, + LIBLTE_M2AP_MBMS_SERVICE_AREA_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBMS-Service-Area-Id-List SEQUENCE + *******************************************************************************/ +typedef struct{ + uint8_t len; + LIBLTE_M2AP_MBMS_SERVICE_AREA_STRUCT buffer[32]; //Waring: Artificial limit to reduce memory footprint +}LIBLTE_M2AP_MBMS_SERVICE_AREA_ID_LIST_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmsserviceareaidlist( + LIBLTE_M2AP_MBMS_SERVICE_AREA_ID_LIST_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmsserviceareaidlist( + uint8_t **ptr, + LIBLTE_M2AP_MBMS_SERVICE_AREA_ID_LIST_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE ENB-MBMS-ConfigurationDataItem SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_ECGI_STRUCT eCGI; + LIBLTE_M2AP_MBSFN_SYNCHRONISATION_AREA_ID_STRUCT mbsfnSynchronisationArea; + LIBLTE_M2AP_MBMS_SERVICE_AREA_ID_LIST_STRUCT mbmsServiceAreaList; + bool iE_Extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; +}LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_ITEM_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_enbmbmsconfigurationdataitem( + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_ITEM_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_enbmbmsconfigurationdataitem( + uint8_t **ptr, + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_ITEM_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE ENB-MBMS-ConfigurationDataConfigUpdateItem SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_ITEM_STRUCT mBMSConfigData; + LIBLTE_M2AP_ECGI_STRUCT eCGI; +}LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_CONFIGUPDATE_ITEM_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_enbmbmsconfigurationdataconfigupdateitem( + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_CONFIGUPDATE_ITEM_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_enbmbmsconfigurationdataconfigupdateitem( + uint8_t **ptr, + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_CONFIGUPDATE_ITEM_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE ENB-MBMS-M2AP-ID INTEGER + *******************************************************************************/ +//lb:0;ub:65535 +typedef struct{ + uint16_t enb_mbms_m2ap_id; +}LIBLTE_M2AP_ENB_MBMS_M2AP_ID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_enbmbmsm2apid( + LIBLTE_M2AP_ENB_MBMS_M2AP_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_enbmbmsm2apid( + uint8_t **ptr, + LIBLTE_M2AP_ENB_MBMS_M2AP_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE ENB-NAME PRINTABLE STRING + *******************************************************************************/ +typedef struct{ + bool ext; + uint32_t n_octets; + uint8_t buffer[150]; +}LIBLTE_M2AP_ENBNAME_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_enbname( + LIBLTE_M2AP_ENBNAME_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_enbname( + uint8_t **ptr, + LIBLTE_M2AP_ENBNAME_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE Global-ENB-Id SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_PLMN_IDENTITY_STRUCT pLMNidentity; + LIBLTE_M2AP_ENB_ID_STRUCT eNB_ID; + bool iE_Extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; +}LIBLTE_M2AP_GLOBAL_ENB_ID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_globalenbid( + LIBLTE_M2AP_GLOBAL_ENB_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_globalenbid( + uint8_t **ptr, + LIBLTE_M2AP_GLOBAL_ENB_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE Global-MCE-Id SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_PLMN_IDENTITY_STRUCT pLMN_Identity; + LIBLTE_M2AP_MCE_ID_STRUCT mCE_ID; + bool iE_Extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_extensions; +}LIBLTE_M2AP_GLOBAL_MCE_ID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_globalmceid( + LIBLTE_M2AP_GLOBAL_MCE_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_globalmceid( + uint8_t **ptr, + LIBLTE_M2AP_GLOBAL_MCE_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE GTP-TEID STATIC OCTET STRING + *******************************************************************************/ +typedef struct{ + uint8_t buffer[4]; +}LIBLTE_M2AP_GTP_TEID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_gtpteid( + LIBLTE_M2AP_GTP_TEID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_gtpteid( + uint8_t **ptr, + LIBLTE_M2AP_GTP_TEID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE IPAddress DYNAMIC OCTET STRING + *******************************************************************************/ +typedef struct{ + uint8_t len; + uint8_t buffer[16]; +}LIBLTE_M2AP_IP_ADDRESS_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_ipaddress( + LIBLTE_M2AP_IP_ADDRESS_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_ipaddress( + uint8_t **ptr, + LIBLTE_M2AP_IP_ADDRESS_STRUCT *ie); + + +/******************************************************************************* + * ProtocolIE LCID INTEGER + *******************************************************************************/ +typedef struct{ + uint8_t lcid; +}LIBLTE_M2AP_LCID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_lcid( + LIBLTE_M2AP_LCID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_lcid( + uint8_t **ptr, + LIBLTE_M2AP_LCID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBMS-Service-associatedLogicalM2-ConnectionItem SEQUENCE + *******************************************************************************/ +typedef struct{ + bool eNB_MBMS_M2AP_ID_present; + LIBLTE_M2AP_ENB_MBMS_M2AP_ID_STRUCT eNB_MBMS_M2AP_ID; + bool mCE_MBMS_M2AP_ID_present; + LIBLTE_M2AP_ENB_MBMS_M2AP_ID_STRUCT mCE_MBMS_M2AP_ID; +}LIBLTE_M2AP_MBMS_SERVICE_ASSOCIATEDLOGICALM2_CONNECTIONITEM_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmsserviceassociatedlogicalm2connectionitem( + LIBLTE_M2AP_MBMS_SERVICE_ASSOCIATEDLOGICALM2_CONNECTIONITEM_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmsserviceassociatedlogicalm2connectionitem( + uint8_t **ptr, + LIBLTE_M2AP_MBMS_SERVICE_ASSOCIATEDLOGICALM2_CONNECTIONITEM_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBMS-Session-Id STATIC OCTET STRING + *******************************************************************************/ +typedef struct{ + uint8_t buffer[1]; +}LIBLTE_M2AP_MBMS_SESSION_ID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmssessionid( + LIBLTE_M2AP_MBMS_SESSION_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmssessionid( + uint8_t **ptr, + LIBLTE_M2AP_MBMS_SESSION_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBSFN-Area-ID INTEGER + *******************************************************************************/ +typedef struct{ + uint8_t mbsfn_area_id; +}LIBLTE_M2AP_MBSFN_AREA_ID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnareaid( + LIBLTE_M2AP_MBSFN_AREA_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnareaid( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_AREA_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBSFN-SynchronizationArea-ID INTEGER + *******************************************************************************/ +typedef struct{ + uint32_t mbsfn_synchronization_area_id; +}LIBLTE_M2AP_MBSFN_SYNCHRONIZATION_AREA_ID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnsynchronizationareaid( + LIBLTE_M2AP_MBSFN_SYNCHRONIZATION_AREA_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnsynchronizationareaid( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_SYNCHRONIZATION_AREA_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE RadioframeAllocationPeriod ENUMERATED + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N1, + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N2, + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N4, + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N8, + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N16, + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N32 +}LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_ENUM; + +typedef struct{ + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_ENUM e; +}LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_radioframeallocationperiod( + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_radioframeallocationperiod( + uint8_t **ptr, + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE RadioframeAllocationOffset INTEGER + *******************************************************************************/ +typedef struct{ + uint8_t radioframeAllocationOffset; +}LIBLTE_M2AP_RADIOFRAME_ALLOCATION_OFFSET_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_radioframeallocationoffset( + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_OFFSET_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_radioframeallocationoffset( + uint8_t **ptr, + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_OFFSET_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE SubframeAllocation CHOICE + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_SUBFRAME_ALLOCATION_ONE_FRAME, + LIBLTE_M2AP_SUBFRAME_ALLOCATION_FOUR_FRAMES +}LIBLTE_M2AP_SUBFRAME_ALLOCATION_ENUM; + +typedef struct{ + LIBLTE_M2AP_SUBFRAME_ALLOCATION_ENUM choice_type; + union { + uint8_t oneFrame[6]; //BIT STRING + uint8_t fourFrames[24]; //BIT STRING + } choice; +}LIBLTE_M2AP_SUBFRAME_ALLOCATION_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_subframeallocation( + LIBLTE_M2AP_SUBFRAME_ALLOCATION_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_subframeallocation( + uint8_t **ptr, + LIBLTE_M2AP_SUBFRAME_ALLOCATION_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBSFN-Subframe-Configuration SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_STRUCT radioFrameAllocationPeriod; + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_OFFSET_STRUCT radioFrameAllocationOffset; + LIBLTE_M2AP_SUBFRAME_ALLOCATION_STRUCT subframeAllocation; + bool iE_Extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; +}LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnsubframeconfiguration( + LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnsubframeconfiguration( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBSFN-Subframe-Configuration-List SEQUENCE + *******************************************************************************/ +typedef struct{ + uint32_t len; + LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_STRUCT buffer[32]; +}LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_LIST_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnsubframeconfigurationlist( + LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_LIST_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnsubframeconfigurationlist( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_LIST_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MCCH-Upadte-Time INTEGER + *******************************************************************************/ +//lb:0;ub:255 +typedef struct{ + uint8_t mcchUpdateTime; +}LIBLTE_M2AP_MCCH_UPDATE_TIME_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mcchupdatetime( + LIBLTE_M2AP_MCCH_UPDATE_TIME_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mcchupdatetime( + uint8_t **ptr, + LIBLTE_M2AP_MCCH_UPDATE_TIME_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE PDCCH-Length ENUM + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_PDCCH_LENGTH_S1, + LIBLTE_M2AP_PDCCH_LENGTH_S2, +}LIBLTE_M2AP_PDCCH_LENGTH_ENUM; + +typedef struct{ + bool ext; + LIBLTE_M2AP_PDCCH_LENGTH_ENUM pdcchLength; +}LIBLTE_M2AP_PDCCH_LENGTH_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_pdcchlength( + LIBLTE_M2AP_PDCCH_LENGTH_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_pdcchlength( + uint8_t **ptr, + LIBLTE_M2AP_PDCCH_LENGTH_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE Repetition Period ENUM + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_REPETITION_PERIOD_RF32, + LIBLTE_M2AP_REPETITION_PERIOD_RF64, + LIBLTE_M2AP_REPETITION_PERIOD_RF128, + LIBLTE_M2AP_REPETITION_PERIOD_RF256, +}LIBLTE_M2AP_REPETITION_PERIOD_ENUM; + +typedef struct{ + LIBLTE_M2AP_REPETITION_PERIOD_ENUM repetitionPeriod; +}LIBLTE_M2AP_REPETITION_PERIOD_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_repetiotionperiod( + LIBLTE_M2AP_REPETITION_PERIOD_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_repetiotionperiod( + uint8_t **ptr, + LIBLTE_M2AP_REPETITION_PERIOD_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE OFFSET INTEGER + *******************************************************************************/ +typedef struct{ + uint8_t offset; +}LIBLTE_M2AP_OFFSET_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_offset( + LIBLTE_M2AP_OFFSET_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_offset( + uint8_t **ptr, + LIBLTE_M2AP_OFFSET_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE Modification Period ENUM + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_MODIFICATION_PERIOD_RF512, + LIBLTE_M2AP_MODIFICATION_PERIOD_RF1024, +}LIBLTE_M2AP_MODIFICATION_PERIOD_ENUM; + +typedef struct{ + LIBLTE_M2AP_MODIFICATION_PERIOD_ENUM modificationPeriod; +}LIBLTE_M2AP_MODIFICATION_PERIOD_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_modificationperiod( + LIBLTE_M2AP_MODIFICATION_PERIOD_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_modificationperiod( + uint8_t **ptr, + LIBLTE_M2AP_MODIFICATION_PERIOD_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE Subframe-Allocation-Info STATIC BIT STRING + *******************************************************************************/ +#define LIBLTE_M2AP_SUBFRAME_ALLOCATION_INFO_BIT_STRING_LEN 6 +typedef struct{ + uint8_t buffer[6]; +}LIBLTE_M2AP_SUBFRAME_ALLOCATION_INFO_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_subframeallocationinfo( + LIBLTE_M2AP_SUBFRAME_ALLOCATION_INFO_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_subframeallocationinfo( + uint8_t **ptr, + LIBLTE_M2AP_SUBFRAME_ALLOCATION_INFO_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE Modulation-and-Coding-Scheme ENUM + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N2, + LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N7, + LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N13, + LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N19 +}LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_ENUM; + +typedef struct{ + LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_ENUM mcs; +}LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_modulationandcodingscheme( + LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_modulationandcodingscheme( + uint8_t **ptr, + LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MCCHrelatedBCCH-ConfigPerMBSFNArea-Item SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_MBSFN_AREA_ID_STRUCT mbsfnArea; + LIBLTE_M2AP_PDCCH_LENGTH_STRUCT pdcchLength; + LIBLTE_M2AP_REPETITION_PERIOD_STRUCT repetitionPeriod; + LIBLTE_M2AP_OFFSET_STRUCT offset; + LIBLTE_M2AP_MODIFICATION_PERIOD_STRUCT modificationPeriod; + LIBLTE_M2AP_SUBFRAME_ALLOCATION_INFO_STRUCT subframeAllocationInfo; + LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_STRUCT modulationAndCodingScheme; + bool cellInformationList_present; + LIBLTE_M2AP_CELL_INFORMATION_LIST_STRUCT cellInformationList; + bool iE_Extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; +}LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_ITEM_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mcchrelatedbcchconfigpermbsfnareaitem( + LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_ITEM_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mcchrelatedbcchconfigpermbsfnareaitem( + uint8_t **ptr, + LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_ITEM_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MCCHrelatedBCCH-ConfigPerMBSFNArea DYNAMIC SEQUENCE + *******************************************************************************/ +typedef struct{ + uint16_t len; + LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_ITEM_STRUCT buffer[8]; +}LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mcchrelatedbcchconfigpermbsfnarea( + LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mcchrelatedbcchconfigpermbsfnarea( + uint8_t **ptr, + LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_STRUCT *ie); +/******************************************************************************* + * ProtocolIE MCH-Scheduling-Period ENUM + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF8, + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF16, + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF32, + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF64, + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF128, + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF256, + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF512, + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF1024 +}LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_ENUM; + +typedef struct{ + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_ENUM e; +}LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mchschedulingperiod( + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mchschedulingperiod( + uint8_t **ptr, + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE OFFSET INTEGER + *******************************************************************************/ +typedef struct{ + uint8_t dataMCS; +}LIBLTE_M2AP_DATA_MCS_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_datamcs( + LIBLTE_M2AP_DATA_MCS_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_datamcs( + uint8_t **ptr, + LIBLTE_M2AP_DATA_MCS_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE Service Id STATIC OCTET STRING + *******************************************************************************/ +#define LIBLTE_M2AP_SERVICE_ID_OCTET_STRING_LEN 3 +typedef struct{ + uint8_t buffer[3]; +}LIBLTE_M2AP_SERVICE_ID_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_serviceid( + LIBLTE_M2AP_SERVICE_ID_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_serviceid( + uint8_t **ptr, + LIBLTE_M2AP_SERVICE_ID_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE TMGI SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_PLMN_IDENTITY_STRUCT pLMN_Identity; + LIBLTE_M2AP_SERVICE_ID_STRUCT serviceID; + bool iE_Extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; +}LIBLTE_M2AP_TMGI_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_tmgi( + LIBLTE_M2AP_TMGI_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_tmgi( + uint8_t **ptr, + LIBLTE_M2AP_TMGI_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBMSSessionListPerPMCH-Item SEQUENCE (SIZE(1..maxnoofSessionsPerPMCH)) OF SEQUENCE + *******************************************************************************/ +typedef struct{ + uint16_t len; + struct { + bool ext; + LIBLTE_M2AP_TMGI_STRUCT Tmgi; + LIBLTE_M2AP_LCID_STRUCT Lcid; + bool iE_Extensions_present; + } buffer[8]; +}LIBLTE_M2AP_MBMS_SESSION_LIST_PER_PMCH_ITEM_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmssessionlistperpmchitem( + LIBLTE_M2AP_MBMS_SESSION_LIST_PER_PMCH_ITEM_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmssessionlistperpmchitem( + uint8_t **ptr, + LIBLTE_M2AP_MBMS_SESSION_LIST_PER_PMCH_ITEM_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE PMCH-Configuration SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_ALLOCATED_SUBFRAMES_END_STRUCT allocatedSubframesEnd; + LIBLTE_M2AP_DATA_MCS_STRUCT dataMCS; + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_STRUCT mchSchedulingPeriod; + bool iE_Extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; +}LIBLTE_M2AP_PMCH_CONFIGURATION_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_pmchconfiguration( + LIBLTE_M2AP_PMCH_CONFIGURATION_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_pmchconfiguration( + uint8_t **ptr, + LIBLTE_M2AP_PMCH_CONFIGURATION_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE PMCH-Configuration-Item SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_PMCH_CONFIGURATION_STRUCT PMCHConfiguration; + LIBLTE_M2AP_MBMS_SESSION_LIST_PER_PMCH_ITEM_STRUCT MBMSSessionListPerPMCHItem; + bool iE_Extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; +}LIBLTE_M2AP_PMCH_CONFIGURATION_ITEM_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_pmchconfigurationitem( + LIBLTE_M2AP_PMCH_CONFIGURATION_ITEM_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_pmchconfigurationitem( + uint8_t **ptr, + LIBLTE_M2AP_PMCH_CONFIGURATION_ITEM_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE PMCH-Configuration-List SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + uint16_t len; + LIBLTE_M2AP_PMCH_CONFIGURATION_ITEM_STRUCT buffer[32]; + bool iE_Extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; +}LIBLTE_M2AP_PMCH_CONFIGURATION_LIST_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_pmchconfigurationlist( + LIBLTE_M2AP_PMCH_CONFIGURATION_LIST_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_pmchconfigurationlist( + uint8_t **ptr, + LIBLTE_M2AP_PMCH_CONFIGURATION_LIST_STRUCT *ie); +/******************************************************************************* + * ProtocolIE Common-Subframe-Scheduling-Period ENUM + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF4, + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF8, + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF16, + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF32, + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF64, + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF128, + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF256, +}LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_ENUM; + +typedef struct{ + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_ENUM e; +}LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_commonsubframeallocationperiod( + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_commonsubframeallocationperiod( + uint8_t **ptr, + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE Time-to-Wait ENUM + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_TIME_TO_WAIT_V1S, + LIBLTE_M2AP_TIME_TO_WAIT_V2S, + LIBLTE_M2AP_TIME_TO_WAIT_V5S, + LIBLTE_M2AP_TIME_TO_WAIT_V10S, + LIBLTE_M2AP_TIME_TO_WAIT_V20S, + LIBLTE_M2AP_TIME_TO_WAIT_V60S, +}LIBLTE_M2AP_TIME_TO_WAIT_ENUM; + +typedef struct{ + LIBLTE_M2AP_TIME_TO_WAIT_ENUM e; +}LIBLTE_M2AP_TIME_TO_WAIT_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_timetowait( + LIBLTE_M2AP_TIME_TO_WAIT_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_timetowait( + uint8_t **ptr, + LIBLTE_M2AP_TIME_TO_WAIT_STRUCT *ie); + + + +/******************************************************************************* + * ProtocolIE TNL-Information SEQUENCE + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_IP_ADDRESS_STRUCT iPMCAddress; + LIBLTE_M2AP_IP_ADDRESS_STRUCT iPSourceAddress; + LIBLTE_M2AP_GTP_TEID_STRUCT gtpTeid; + bool iE_Extensions_present; + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT iE_Extensions; +}LIBLTE_M2AP_TNL_INFORMATION_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_tnlinformation( + LIBLTE_M2AP_TNL_INFORMATION_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_tnlinformation( + uint8_t **ptr, + LIBLTE_M2AP_TNL_INFORMATION_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE ENB-MBMS-Configuration-data-List SEQUENCE OF ProtocolIE-Single-Container + *******************************************************************************/ +//lb:1;ub:maxnofCells (256) +typedef struct{ + uint8_t len; + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_ITEM_STRUCT buffer[32]; //Waring: Artificial limit to reduce memory footprint +} LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_LIST_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_enbmbmsconfigurationdatalist( + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_LIST_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_enbmbmsconfigurationdatalist( + uint8_t **ptr, + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_LIST_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBSFN-AreaConfiguration-Item ProtocolIE-Container + *******************************************************************************/ +typedef struct{ + LIBLTE_M2AP_PMCH_CONFIGURATION_LIST_STRUCT PMCHConfigurationList; + LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_LIST_STRUCT MBSFNSubframeConfigurationList; + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_STRUCT CommonSubframeAllocationPeriod; + LIBLTE_M2AP_MBSFN_AREA_ID_STRUCT MBSFNAreaId; +} LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_ITEM_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnareaconfigurationitem( + LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_ITEM_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnareaconfigurationitem( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_ITEM_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE MBSFN-AreaConfiguration-List SEQUENCE OF ProtocolIE-Single-Container + *******************************************************************************/ +//lb:1;ub:maxnofCells (256) +typedef struct{ + uint8_t len; + LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_ITEM_STRUCT buffer[32]; //Waring: Artificial limit to reduce memory footprint +} LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_LIST_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnareaconfigurationlist( + LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_LIST_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnareaconfigurationlist( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_LIST_STRUCT *ie); + +/******************************************************************************* + * Protocol Message M2SetupRequest STRUCT + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_GLOBAL_ENB_ID_STRUCT Global_ENB_ID; + bool eNBname_present; + LIBLTE_M2AP_ENBNAME_STRUCT eNBname; + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_LIST_STRUCT configurationDataList; +}LIBLTE_M2AP_MESSAGE_M2SETUPREQUEST_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_m2setuprequest( + LIBLTE_M2AP_MESSAGE_M2SETUPREQUEST_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_m2setuprequest( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_M2SETUPREQUEST_STRUCT *ie); + +/******************************************************************************* + * Protocol Message M2SetupResponse STRUCT + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_GLOBAL_MCE_ID_STRUCT Global_MCE_ID; + bool MCEname_present; + LIBLTE_M2AP_MCE_NAME_STRUCT MCEname; + LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_STRUCT MCCHrelatedBCCHConfigPerMBSFNArea; + bool criticalityDiagnosis_present; + LIBLTE_M2AP_CRITICALITYDIAGNOSTICS_STRUCT criticalityDiagnosis; +}LIBLTE_M2AP_MESSAGE_M2SETUPRESPONSE_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_m2setupresponse( + LIBLTE_M2AP_MESSAGE_M2SETUPRESPONSE_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_m2setupresponse( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_M2SETUPRESPONSE_STRUCT *ie); + +/******************************************************************************* + * Protocol Message MBMSSessionStartRequest STRUCT + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_MCE_MBMS_M2AP_ID_STRUCT MceMbmsM2apId; + LIBLTE_M2AP_TMGI_STRUCT Tmgi; + bool MbmsSessionId_present; + LIBLTE_M2AP_MBMS_SESSION_ID_STRUCT MbmsSessionId; + LIBLTE_M2AP_MBMS_SERVICE_AREA_STRUCT MbmsServiceArea; + LIBLTE_M2AP_TNL_INFORMATION_STRUCT TnlInformation; +}LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTREQUEST_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmssessionstartrequest( + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTREQUEST_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmssessionstartrequest( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTREQUEST_STRUCT *ie); + +/******************************************************************************* + * Protocol Message MBMSSessionStartResponse STRUCT + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_MCE_MBMS_M2AP_ID_STRUCT MceMbmsM2apId; + LIBLTE_M2AP_ENB_MBMS_M2AP_ID_STRUCT EnbMbmsM2apId; + bool CriticalityDiagnostics_present; + LIBLTE_M2AP_CRITICALITYDIAGNOSTICS_STRUCT CriticalityDiagnostics; +}LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTRESPONSE_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmssessionstartresponse( + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTRESPONSE_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmssessionstartresponse( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTRESPONSE_STRUCT *ie); + +/******************************************************************************* + * Protocol Message MBMSSchedulingInformation STRUCT + *******************************************************************************/ +typedef struct{ + bool ext; + LIBLTE_M2AP_MCCH_UPDATE_TIME_STRUCT MCCHUpdateTime; + LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_LIST_STRUCT MbsfnAreaConfigurationList; +}LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATION_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmsschedulinginformation( + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATION_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmsschedulinginformation( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATION_STRUCT *ie); + +/******************************************************************************* + * Protocol Message MBMSSchedulingInformationResponse STRUCT + *******************************************************************************/ +typedef struct{ + bool ext; + bool CriticalityDiagnostics_present; + LIBLTE_M2AP_CRITICALITYDIAGNOSTICS_STRUCT CriticalityDiagnostics; +}LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATIONRESPONSE_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmsschedulinginformation( + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATION_STRUCT *ie, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmsschedulinginformation( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATION_STRUCT *ie); + +/******************************************************************************* + * ProtocolIE-Field + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_protocolie_header( + uint32_t len, + uint32_t ie_id, + LIBLTE_M2AP_CRITICALITY_ENUM crit, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_protocolie_header( + uint8_t **ptr, + uint32_t *ie_id, + LIBLTE_M2AP_CRITICALITY_ENUM *crit, + uint32_t *len); + +/******************************************************************************* + * Procedure code criticality lookups + *******************************************************************************/ + LIBLTE_M2AP_CRITICALITY_ENUM liblte_m2ap_procedure_criticality(uint8_t procedureCode); + +/******************************************************************************* + * InitiatingMessage CHOICE + ********************************************************************************/ +typedef enum{ + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MBMSSESSIONSTARTREQUEST, + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MBMSSESSIONSTOPREQUEST, + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MBMSSESSION_UPDATEREQUEST, + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MBMSSCHEDULINGINFORMATION, + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_RESET, + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_M2SETUPREQUEST, + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_ENBCONFIGURATIONUPDATE, + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MCECONFIGURATIONUPDATE, + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MBMSSERVICECOUNTINGREQUEST, + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_N_ITEMS, +}LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_ENUM; +static const char liblte_m2ap_initiatingmessage_choice_text[LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_N_ITEMS][50] = { + "MbmsSessionStartRequest", + "MbmsSessionStopRequest", + "MbmsSessionUpdateRequest", + "MbmsSchedulingInformation", + "Reset", + "M2SetupRequest", + "EnbConfigurationUpdate", + "MceConfigurationUpdate", + "MbmsServiceCountingRequest" +}; + +typedef union{ + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTREQUEST_STRUCT MbmsSessionStartRequest; + //LIBLTE_M2AP_MBMS_SESSION_STOP_REQUEST MbmsSessionStopRequest; + //LIBLTE_M2AP_MBMS_SESSION_UPDATE_REQUEST MbmsSessionUpdateRequest; + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATION_STRUCT MbmsSchedulingInformation; + //LIBLTE_M2AP_RESET Reset; + LIBLTE_M2AP_MESSAGE_M2SETUPREQUEST_STRUCT M2SetupRequest; + //LIBLTE_M2AP_ENB_CONFIGURATION_UPDATE EnbConfigurationUpdate; + //LIBLTE_M2AP_MCE_CONFIGURATION_UPDATE MceConfigurationUpdate; + //LIBLTE_M2AP_MBMS_SERVICE_COUNTING_REQUEST MbmsServiceCountingRequest +}LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_UNION; + +typedef struct{ + uint8_t procedureCode; + LIBLTE_M2AP_CRITICALITY_ENUM criticality; + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_UNION choice; + LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_ENUM choice_type; +}LIBLTE_M2AP_INITIATINGMESSAGE_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_initiatingmessage( + LIBLTE_M2AP_INITIATINGMESSAGE_STRUCT *msg, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_initiatingmessage( + uint8_t **ptr, + LIBLTE_M2AP_INITIATINGMESSAGE_STRUCT *msg); + +/******************************************************************************* + * UnsuccessfulOutcome CHOICE + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_MBMSSESSIONSTARTFAILURE, + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_MBMSSESSIONUPDATEFAILURE, + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_M2SETUPFAILURE, + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_ENBCONFIGURATIONUPDATEFAILURE, + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_MCECONFIGURATIONUPDATEFAILURE, + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_MBMSSERVICECOUNTINGFAILURE, + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_N_ITEMS, +}LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_ENUM; +static const char liblte_m2ap_unsuccessfuloutcome_choice_text[LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_N_ITEMS][50] = { + "MbmsSessionStartFailure", + "Mbmssessionupdatefailure", + "M2SetupFailure", + "EnbConfigurationUpdateFailure", + "MceConfigurationUpdateFailure", +}; + +typedef union{ + //LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT S1SetupFailure; + //LIBLTE_S1AP_MESSAGE_HANDOVERFAILURE_STRUCT HandoverFailure; + //LIBLTE_S1AP_MESSAGE_MMECONFIGURATIONUPDATEFAILURE_STRUCT MMEConfigurationUpdateFailure; +}LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_UNION; + +typedef struct{ + uint8_t procedureCode; + LIBLTE_M2AP_CRITICALITY_ENUM criticality; + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_UNION choice; + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_CHOICE_ENUM choice_type; +}LIBLTE_M2AP_UNSUCCESSFULOUTCOME_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_unsuccessfuloutcome( + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_STRUCT *msg, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_unsuccessfuloutcome( + uint8_t **ptr, + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_STRUCT *msg); + +/******************************************************************************* + * SuccessfulOutcome CHOICE + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MBMSSESSIONSTARTRESPONSE, + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MBMSSESSIONSTOPRESPONSE, + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MBMSSESSIONUPDATERESPONSE, + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MBMSSCHEDULINGINFORMATIONRESPONSE, + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_RESETACKNOWLEDGE, + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_M2SETUPRESPONSE, + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_ENBCONFIGURATIONUPDATEACKNOWLEDGE, + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MCECONFIGURATIONUPDATEACKNOWLEDGE, + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MBMSSERVICECOUNTINGRESPONSE, + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_N_ITEMS, +}LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_ENUM; +static const char liblte_m2ap_successfuloutcome_choice_text[LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_N_ITEMS][50] = { + "MbmsSessionStartResponse", + "MbmsSessionStopResponse", + "MbmsSessionUpdateResponse", + "MbmsSchedulingInformationResponse", + "ResetAcknowledge", + "M2SetupResponse", + "EnbConfigurationUpdateAcknowledge", + "MceConfigurationUpdateAcknowledge", + "MbmsServiceCountingResponse", +}; +typedef union { + LIBLTE_M2AP_MESSAGE_M2SETUPRESPONSE_STRUCT M2SetupResponse; + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTRESPONSE_STRUCT MbmsSessionStartResponse; + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATIONRESPONSE_STRUCT MbmsSchedulingInformationResponse; +} LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_UNION; + +typedef struct{ + uint8_t procedureCode; + LIBLTE_M2AP_CRITICALITY_ENUM criticality; + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_UNION choice; + LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_ENUM choice_type; +}LIBLTE_M2AP_SUCCESSFULOUTCOME_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_successfuloutcome( + LIBLTE_M2AP_SUCCESSFULOUTCOME_STRUCT *msg, + uint8_t **ptr); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_successfuloutcome( + uint8_t **ptr, + LIBLTE_M2AP_SUCCESSFULOUTCOME_STRUCT *msg); + +/******************************************************************************* + * M2AP_PDU CHOICE + *******************************************************************************/ +typedef enum{ + LIBLTE_M2AP_M2AP_PDU_CHOICE_INITIATINGMESSAGE, + LIBLTE_M2AP_M2AP_PDU_CHOICE_SUCCESSFULOUTCOME, + LIBLTE_M2AP_M2AP_PDU_CHOICE_UNSUCCESSFULOUTCOME, + LIBLTE_M2AP_M2AP_PDU_CHOICE_N_ITEMS, +}LIBLTE_M2AP_M2AP_PDU_CHOICE_ENUM; +static const char liblte_m2ap_m2ap_pdu_choice_text[LIBLTE_M2AP_M2AP_PDU_CHOICE_N_ITEMS][50] = { + "initiatingMessage", + "successfulOutcome", + "unsuccessfulOutcome", +}; + +typedef union{ + LIBLTE_M2AP_INITIATINGMESSAGE_STRUCT initiatingMessage; + LIBLTE_M2AP_SUCCESSFULOUTCOME_STRUCT successfulOutcome; + LIBLTE_M2AP_UNSUCCESSFULOUTCOME_STRUCT unsuccessfulOutcome; +}LIBLTE_M2AP_M2AP_PDU_CHOICE_UNION; + +typedef struct{ + bool ext; + LIBLTE_M2AP_M2AP_PDU_CHOICE_UNION choice; + LIBLTE_M2AP_M2AP_PDU_CHOICE_ENUM choice_type; +}LIBLTE_M2AP_M2AP_PDU_STRUCT; + +LIBLTE_ERROR_ENUM liblte_m2ap_pack_m2ap_pdu( + LIBLTE_M2AP_M2AP_PDU_STRUCT *m2ap_pdu, + LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_m2ap_pdu( + LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_M2AP_M2AP_PDU_STRUCT *m2ap_pdu); + +#endif // SRSLTE_LIBLTE_M2AP_H diff --git a/lib/src/asn1/CMakeLists.txt b/lib/src/asn1/CMakeLists.txt index caddb384c..b46739c40 100644 --- a/lib/src/asn1/CMakeLists.txt +++ b/lib/src/asn1/CMakeLists.txt @@ -24,6 +24,7 @@ add_library(srslte_asn1 STATIC liblte_rrc.cc liblte_mme.cc liblte_s1ap.cc + liblte_m2ap.cc gtpc.cc ) install(TARGETS srslte_asn1 DESTINATION ${LIBRARY_DIR}) diff --git a/lib/src/asn1/liblte_m2ap.cc b/lib/src/asn1/liblte_m2ap.cc new file mode 100644 index 000000000..6791e166f --- /dev/null +++ b/lib/src/asn1/liblte_m2ap.cc @@ -0,0 +1,4401 @@ +/******************************************************************************* + * + * Copyright 2018 Software Radio Systems Limited + * + ********************************************************************************/ +#include "srslte/asn1/liblte_m2ap.h" +#include +#include + +/******************************************************************************* + LOGGING +*******************************************************************************/ + +static log_handler_t log_handler; +static void *callback_ctx = NULL; + +void liblte_log_register_handler(void *ctx, log_handler_t handler) { + log_handler = handler; + callback_ctx = ctx; +} + +static void liblte_log_print(const char *format, ...) { + va_list args; + va_start(args, format); + if (log_handler) { + char *args_msg = NULL; + if(vasprintf(&args_msg, format, args) > 0) { + log_handler(callback_ctx, args_msg); + } + if (args_msg) { + free(args_msg); + } + } else { + vprintf(format, args); + } + va_end(args); +} + +/******************************************************************************* + * Procedure code criticality lookups + *******************************************************************************/ +LIBLTE_M2AP_CRITICALITY_ENUM liblte_m2ap_procedure_criticality(uint8_t procedureCode) +{ + switch (procedureCode) { + case LIBLTE_M2AP_PROC_ID_SESSIONSTART: + return LIBLTE_M2AP_CRITICALITY_REJECT; + case LIBLTE_M2AP_PROC_ID_SESSIONSTOP: + return LIBLTE_M2AP_CRITICALITY_REJECT; + case LIBLTE_M2AP_PROC_ID_MBMSSCHEDULINGINFORMATION: + return LIBLTE_M2AP_CRITICALITY_REJECT; + case LIBLTE_M2AP_PROC_ID_ERRORINDICATION: + return LIBLTE_M2AP_CRITICALITY_REJECT; + case LIBLTE_M2AP_PROC_ID_RESET: + return LIBLTE_M2AP_CRITICALITY_REJECT; + case LIBLTE_M2AP_PROC_ID_M2SETUP: + return LIBLTE_M2AP_CRITICALITY_REJECT; + case LIBLTE_M2AP_PROC_ID_ENBCONFIGURATIONUPDATE: + return LIBLTE_M2AP_CRITICALITY_REJECT; + case LIBLTE_M2AP_PROC_ID_MCECONFIGURATIONUPDATE: + return LIBLTE_M2AP_CRITICALITY_REJECT; + case LIBLTE_M2AP_PROC_ID_PRIVATEMESSAGE: + return LIBLTE_M2AP_CRITICALITY_REJECT; + case LIBLTE_M2AP_PROC_ID_SESSIONUPDATE: + return LIBLTE_M2AP_CRITICALITY_REJECT; + case LIBLTE_M2AP_PROC_ID_MBMSSERVICECOUNTING: + return LIBLTE_M2AP_CRITICALITY_REJECT; + case LIBLTE_M2AP_PROC_ID_MBMSSERVICECOUNTINGRESULTSREPORT: + return LIBLTE_M2AP_CRITICALITY_REJECT; + } + return LIBLTE_M2AP_CRITICALITY_REJECT; +} + +/******************************************************************************* + * ProtocolIE-Field + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_protocolie_header( + uint32_t len, + uint32_t ie_id, + LIBLTE_M2AP_CRITICALITY_ENUM crit, + uint8_t **ptr) +{ + liblte_value_2_bits(ie_id, ptr, 16); // ProtocolIE-ID + liblte_value_2_bits(crit, ptr, 2); // Criticality + liblte_align_up_zero(ptr, 8); + if(len < 128) { // Length + liblte_value_2_bits(0, ptr, 1); + liblte_value_2_bits(len, ptr, 7); + } else if(len < 16383) { + liblte_value_2_bits(1, ptr, 1); + liblte_value_2_bits(0, ptr, 1); + liblte_value_2_bits(len, ptr, 14); + } else { + // FIXME: Unlikely to have more than 16K of octets + } + + return LIBLTE_SUCCESS; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_protocolie_header( + uint8_t **ptr, + uint32_t *ie_id, + LIBLTE_M2AP_CRITICALITY_ENUM *crit, + uint32_t *len) +{ + *ie_id = liblte_bits_2_value(ptr, 16); // ProtocolIE-ID + *crit = (LIBLTE_M2AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2); // Criticality + liblte_align_up(ptr, 8); + if(0 == liblte_bits_2_value(ptr, 1)) { // Length + *len = liblte_bits_2_value(ptr, 7); + } else { + if(0 == liblte_bits_2_value(ptr, 1)) { + *len = liblte_bits_2_value(ptr, 14); + } else { + // FIXME: Unlikely to have more than 16K of octets + } + } + return LIBLTE_SUCCESS; +} + +/******************************************************************************* + * ProtocolIE ProtocolIE_ID INTEGER + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_protocolie_id( + LIBLTE_M2AP_PROTOCOLIE_ID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Integer - ie->ProtocolIE_ID + // lb:0, ub:65535 + liblte_align_up_zero(ptr, 8); + liblte_value_2_bits(0, ptr, (2*8)-16); + liblte_value_2_bits(ie->ProtocolIE_ID, ptr, 16); + liblte_align_up_zero(ptr, 8); + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_protocolie_id( + uint8_t **ptr, + LIBLTE_M2AP_PROTOCOLIE_ID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Integer - ie->ProtocolIE_ID + // lb:0, ub:65535 + liblte_align_up(ptr, 8); + ie->ProtocolIE_ID = (uint16_t)liblte_bits_2_value(ptr, 16); + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE ProtocolIE_SingleContainer SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_protocolie_singlecontainer( + LIBLTE_M2AP_PROTOCOLIE_SINGLECONTAINER_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + + liblte_value_2_bits(ie->id.ProtocolIE_ID, ptr, 16); // ProtocolIE-ID + liblte_value_2_bits(ie->criticality, ptr, 2); // Criticality + liblte_align_up_zero(ptr, 8); + //if(liblte_m2ap_pack_protocolie_id(&ie->id, ptr) != LIBLTE_SUCCESS) { + // return LIBLTE_ERROR_ENCODE_FAIL; + //} + + // Enum - ie->criticality + //liblte_value_2_bits(ie->criticality, ptr, 8); + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_protocolie_singlecontainer( + uint8_t **ptr, + LIBLTE_M2AP_PROTOCOLIE_SINGLECONTAINER_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + + if(liblte_m2ap_unpack_protocolie_id(ptr, &ie->id) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + // Enum - ie->criticality + ie->criticality = (LIBLTE_M2AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2); + liblte_align_up(ptr, 16); + + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE ProtocolExtensionID INTEGER + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_protocolextensionid( + LIBLTE_M2AP_PROTOCOLEXTENSIONID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Integer - ie->ProtocolExtensionID + // lb:0, ub:65535 + liblte_align_up_zero(ptr, 8); + liblte_value_2_bits(0, ptr, (2*8)-16); + liblte_value_2_bits(ie->ProtocolExtensionID, ptr, 16); + liblte_align_up_zero(ptr, 8); + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_protocolextensionid( + uint8_t **ptr, + LIBLTE_M2AP_PROTOCOLEXTENSIONID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Integer - ie->ProtocolExtensionID + // lb:0, ub:65535 + liblte_align_up(ptr, 8); + ie->ProtocolExtensionID = (uint16_t)liblte_bits_2_value(ptr, 2.0*8); + liblte_align_up(ptr, 8); + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE ProtocolExtensionField SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_protocolextensionfield( + LIBLTE_M2AP_PROTOCOLEXTENSIONFIELD_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + + if(liblte_m2ap_pack_protocolextensionid(&ie->id, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Enum - ie->criticality + liblte_value_2_bits(ie->criticality, ptr, 2); + + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_protocolextensionfield( + uint8_t **ptr, + LIBLTE_M2AP_PROTOCOLEXTENSIONFIELD_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + + if(liblte_m2ap_unpack_protocolextensionid(ptr, &ie->id) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + // Enum - ie->criticality + ie->criticality = (LIBLTE_M2AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2); + + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE ProtocolExtensionContainer DYNAMIC SEQUENCE OF + *******************************************************************************/ +// lb:1, ub:65535 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_protocolextensioncontainer( + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + if(ie->len > 32) { + liblte_log_print("ProtocolExtensionContainer pack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len); + return LIBLTE_ERROR_ENCODE_FAIL; + } + // Length + liblte_value_2_bits(ie->len-1, ptr, 16); + liblte_align_up_zero(ptr, 8); + uint32_t i; + for(i=0;ilen;i++) { + if(liblte_m2ap_pack_protocolextensionfield(&ie->buffer[i], ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_protocolextensioncontainer( + uint8_t **ptr, + LIBLTE_M2AP_PROTOCOLEXTENSIONCONTAINER_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Length + ie->len = liblte_bits_2_value(ptr, 16) + 1; + liblte_align_up(ptr, 8); + if(ie->len > 32) { + liblte_log_print("ProtocolExtensionContainer unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", ie->len); + return LIBLTE_ERROR_DECODE_FAIL; + } + uint32_t i; + for(i=0;ilen;i++) { + if(liblte_m2ap_unpack_protocolextensionfield(ptr, &ie->buffer[i]) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE Criticality Diagnostics SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_criticalitydiagnostics( + LIBLTE_M2AP_CRITICALITYDIAGNOSTICS_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + liblte_log_print("CriticalityDiagnostics pack error - Criticality Diagnostics not supported yet\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_criticalitydiagnostics( + uint8_t **ptr, + LIBLTE_M2AP_CRITICALITYDIAGNOSTICS_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + liblte_log_print("CriticalityDiagnostics unpack error - criticality diagnostics not supported yet\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + return err; +} +/******************************************************************************* + * ProtocolIE PLMNidentity STATIC OCTET STRING + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_plmnidentity( + LIBLTE_M2AP_PLMN_IDENTITY_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Static octet string + if(LIBLTE_M2AP_PLMN_IDENTITY_OCTET_STRING_LEN > 2) { // X.691 Sec.16 + liblte_align_up_zero(ptr, 8); + } + // Octets + uint32_t i; + for(i=0;ibuffer[i], ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_plmnidentity( + uint8_t **ptr, + LIBLTE_M2AP_PLMN_IDENTITY_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + + // Static octet string + if(LIBLTE_M2AP_PLMN_IDENTITY_OCTET_STRING_LEN > 2) { // X.691 Sec.16 + liblte_align_up(ptr, 8); + } + // Octets + uint32_t i; + for(i=0;ibuffer[i] = liblte_bits_2_value(ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE IP address OCTET STRING + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_ipaddress( + LIBLTE_M2AP_IP_ADDRESS_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->len-4, ptr,4); + liblte_align_up_zero(ptr,8); + // Octets + uint32_t i; + for(i=0;ilen;i++) { + liblte_value_2_bits(ie->buffer[i], ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_ipaddress( + uint8_t **ptr, + LIBLTE_M2AP_IP_ADDRESS_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + + ie->len = liblte_bits_2_value(ptr,4)+4; + liblte_align_up(ptr,8); + if(ie->len > 16) { + return LIBLTE_ERROR_DECODE_FAIL; + } + for(int i=0; ilen; i++) { + ie->buffer[i] = liblte_bits_2_value(ptr,8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE GTP TEID OCTET STRING + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_gtpteid( + LIBLTE_M2AP_GTP_TEID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + + // Octets + uint32_t i; + for(i=0;i<4;i++) { + liblte_value_2_bits(ie->buffer[i], ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_gtpteid( + uint8_t **ptr, + LIBLTE_M2AP_GTP_TEID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + for(int i=0; i<4; i++) { + ie->buffer[i] = liblte_bits_2_value(ptr,8); + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE Service Id STATIC OCTET STRING + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_serviceid( + LIBLTE_M2AP_SERVICE_ID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Static octet string + if(LIBLTE_M2AP_SERVICE_ID_OCTET_STRING_LEN > 2) { // X.691 Sec.16 + liblte_align_up_zero(ptr, 8); + } + // Octets + uint32_t i; + for(i=0;ibuffer[i], ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_serviceid( + uint8_t **ptr, + LIBLTE_M2AP_SERVICE_ID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Static octet string + if(LIBLTE_M2AP_SERVICE_ID_OCTET_STRING_LEN > 2) { // X.691 Sec.16 + liblte_align_up(ptr, 8); + } + // Octets + uint32_t i; + for(i=0;ibuffer[i] = liblte_bits_2_value(ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE ENBname PrintableString + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_enbname( + LIBLTE_M2AP_ENBNAME_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Printable string - ENBname + // Extension + liblte_value_2_bits(ie->ext?1:0, ptr, 1); + if(ie->ext) { + liblte_log_print("ENBname error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Length + liblte_value_2_bits(ie->n_octets-1, ptr, 8); + liblte_align_up_zero(ptr, 8); + + uint32_t i; + for(i=0;in_octets;i++) { + liblte_value_2_bits(ie->buffer[i], ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_enbname( + uint8_t **ptr, + LIBLTE_M2AP_ENBNAME_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Printable string - ENBname + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("ENBname error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + // Length + ie->n_octets = liblte_bits_2_value(ptr, 8) + 1; + liblte_align_up(ptr, 8); + + uint32_t i; + for(i=0;in_octets;i++) { + ie->buffer[i] = liblte_bits_2_value(ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE MCEname PrintableString + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mcename( + LIBLTE_M2AP_MCE_NAME_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Printable string - ENBname + // Extension + liblte_value_2_bits(ie->ext?1:0, ptr, 1); + if(ie->ext) { + liblte_log_print("MCEname error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Length + liblte_value_2_bits(ie->n_octets-1, ptr, 8); + liblte_align_up_zero(ptr, 8); + + uint32_t i; + for(i=0;in_octets;i++) { + liblte_value_2_bits(ie->buffer[i], ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mcename( + uint8_t **ptr, + LIBLTE_M2AP_MCE_NAME_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Printable string - ENBname + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("MCEname error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + // Length + ie->n_octets = liblte_bits_2_value(ptr, 8) + 1; + liblte_align_up(ptr, 8); + + uint32_t i; + for(i=0;in_octets;i++) { + ie->buffer[i] = liblte_bits_2_value(ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE ENB-ID STATIC BIT STRING + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_enbid( + LIBLTE_M2AP_ENB_ID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + liblte_value_2_bits(ie->ext?1:0, ptr, 1); + if(ie->ext) { + liblte_log_print("ENBname error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up(ptr, 8); + + // Static bit string - eNB-Id + uint32_t i; + for(i=0;ibuffer[i], ptr, 1); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_enbid( + uint8_t **ptr, + LIBLTE_M2AP_ENB_ID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("ENBname error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + // Static bit string - eNB-Id + liblte_align_up_zero(ptr, 8); + uint32_t i; + for(i=0;ibuffer[i] = liblte_bits_2_value(ptr, 1); + } + liblte_align_up_zero(ptr, 8); + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE Global_ENB_ID SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_globalenbid( + LIBLTE_M2AP_GLOBAL_ENB_ID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + liblte_value_2_bits(ie->ext?1:0, ptr, 1); + if(ie->ext) { + liblte_log_print("Global_ENB_ID error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1); + liblte_align_up_zero(ptr,8); + + if(liblte_m2ap_pack_plmnidentity(&ie->pLMNidentity, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + if(liblte_m2ap_pack_enbid(&ie->eNB_ID, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_globalenbid( + uint8_t **ptr, + LIBLTE_M2AP_GLOBAL_ENB_ID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("Global_ENB_ID error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1); + + if(liblte_m2ap_unpack_plmnidentity(ptr, &ie->pLMNidentity) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(liblte_m2ap_unpack_enbid(ptr, &ie->eNB_ID) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + + +/******************************************************************************* + * ProtocolIE ECGI SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_ecgi( + LIBLTE_M2AP_ECGI_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + //Extension present + liblte_value_2_bits(ie->ext?1:0, ptr, 1); + if(ie->ext) { + liblte_log_print("eNB-MBMS-Configuration-Data Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + //IE Extension present + liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1); + if(ie->iE_Extensions_present) { + liblte_log_print("eNB-MBMS-Configuration-Data Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + //PLMN Identity + if(liblte_m2ap_pack_plmnidentity(&ie->pLMN_Identity, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + //E-UTRAN Cell Identifier + if(liblte_m2ap_pack_eutrancellidentifier(&ie->EUTRANCellIdentifier,ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_ecgi( + uint8_t **ptr, + LIBLTE_M2AP_ECGI_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("ECGI error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1); + + if(liblte_m2ap_unpack_plmnidentity(ptr, &ie->pLMN_Identity) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(liblte_m2ap_unpack_eutrancellidentifier(ptr, &ie->EUTRANCellIdentifier) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE MCE-ID STATIC OCTET STRING + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mceid( + LIBLTE_M2AP_MCE_ID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Static octet string + if(LIBLTE_M2AP_MCEID_OCTET_STRING_LEN > 2) { // X.691 Sec.16 + liblte_align_up_zero(ptr, 8); + } + // Octets + uint32_t i; + for(i=0;ibuffer[i], ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mceid( + uint8_t **ptr, + LIBLTE_M2AP_MCE_ID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Static octet string + if(LIBLTE_M2AP_MCEID_OCTET_STRING_LEN > 2) { // X.691 Sec.16 + liblte_align_up(ptr, 8); + } + // Octets + uint32_t i; + for(i=0;ibuffer[i] = liblte_bits_2_value(ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE Global_MCE_ID SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_globalmceid( + LIBLTE_M2AP_GLOBAL_MCE_ID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + + // Extension + liblte_value_2_bits(ie->ext?1:0, ptr, 1); + if(ie->ext) { + liblte_log_print("Global_ENB_ID error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(ptr,8); + + if(liblte_m2ap_pack_plmnidentity(&ie->pLMN_Identity, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + if(liblte_m2ap_pack_mceid(&ie->mCE_ID, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_pack_protocolextensioncontainer(&ie->iE_extensions, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_globalmceid( + uint8_t **ptr, + LIBLTE_M2AP_GLOBAL_MCE_ID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("Global_ENB_ID error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1); + + if(liblte_m2ap_unpack_plmnidentity(ptr, &ie->pLMN_Identity) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(liblte_m2ap_unpack_mceid(ptr, &ie->mCE_ID) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_unpack_protocolextensioncontainer(ptr, &ie->iE_extensions) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE EUTRANCellIdentifier STATIC BIT STRING + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_eutrancellidentifier( + LIBLTE_M2AP_EUTRAN_CELL_IDENTIFIER_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Static bit string - E-UTRAN Cell Identifier + liblte_value_2_bits(ie->eUTRANCellIdentifier, ptr, LIBLTE_M2AP_EUTRAN_CELL_IDENTIFIER_BIT_STRING_LEN); + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_eutrancellidentifier( + uint8_t **ptr, + LIBLTE_M2AP_EUTRAN_CELL_IDENTIFIER_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Static bit string - E-UTRAN Cell Identifier + ie->eUTRANCellIdentifier = liblte_bits_2_value(ptr, LIBLTE_M2AP_EUTRAN_CELL_IDENTIFIER_BIT_STRING_LEN); + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE MBSFN-Synchronization-Area-Id INTEGER + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnsynchronisationareaid( + LIBLTE_M2AP_MBSFN_SYNCHRONISATION_AREA_ID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + // Integer - ie->local + // lb:0, ub:65535 + liblte_align_up_zero(ptr,8); + liblte_value_2_bits(ie->mbsfn_synchronisation_area_id, ptr,16); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnsynchronisationareaid( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_SYNCHRONISATION_AREA_ID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + // Integer - ie->local + // lb:0, ub:65535 + liblte_align_up(ptr,8); + ie->mbsfn_synchronisation_area_id = liblte_bits_2_value(ptr,16); + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE MBMS-Service-Area-List DYNAMIC OCTET STRING + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmsserviceareaidlist( + LIBLTE_M2AP_MBMS_SERVICE_AREA_ID_LIST_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + liblte_value_2_bits(ie->len-1, ptr,8); + for (int i = 0; i < ie->len; i++ ){ + liblte_m2ap_pack_mbmsservicearea(&ie->buffer[i], ptr); + } + err = LIBLTE_SUCCESS; + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmsserviceareaidlist( + uint8_t **ptr, + LIBLTE_M2AP_MBMS_SERVICE_AREA_ID_LIST_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + ie->len = liblte_bits_2_value(ptr,8)+1; + for (int i = 0; i < ie->len; i++ ){ + liblte_m2ap_unpack_mbmsservicearea(ptr,&ie->buffer[i]); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE MBMS-Service-Area DYNAMIC OCTET STRING + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmsservicearea( + LIBLTE_M2AP_MBMS_SERVICE_AREA_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + if(ie->n_octets < 127) { // Length + liblte_value_2_bits(0, ptr, 1); + liblte_value_2_bits(ie->n_octets, ptr, 7); + } else { + if(ie->n_octets < 16384 ) { + liblte_value_2_bits( 0, ptr, 1); + liblte_value_2_bits(ie->n_octets, ptr, 14); + } else { + // too large + return LIBLTE_ERROR_ENCODE_FAIL; + } + } + for(int i = 0; i < ie->n_octets; i++){ + liblte_value_2_bits(ie->buffer[i], ptr,8); + } + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmsservicearea( + uint8_t **ptr, + LIBLTE_M2AP_MBMS_SERVICE_AREA_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + if(0 == liblte_bits_2_value(ptr, 1)) { // Length + ie->n_octets = liblte_bits_2_value(ptr, 7); + } else { + if(0 == liblte_bits_2_value(ptr, 1)) { + ie->n_octets = liblte_bits_2_value(ptr, 14); + } else { + // FIXME: Unlikely to have more than 16K of octets + } + } + //ie->n_octets = liblte_bits_2_value(ptr,8); + for(int i = 0; i < ie->n_octets; i++){ + ie->buffer[i] = liblte_bits_2_value(ptr,8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE ENB-MBMS-ConfigurationDataItem SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_enbmbmsconfigurationdataitem( + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_ITEM_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + //Extension present + liblte_value_2_bits(ie->ext?1:0, ptr, 1); + if(ie->ext) { + liblte_log_print("eNB-MBMS-Configuration-Data Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + //IE Extension present + liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1); + if(ie->iE_Extensions_present) { + liblte_log_print("eNB-MBMS-Configuration-Data Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // eCGI + err = liblte_m2ap_pack_ecgi(&ie->eCGI,ptr); + if(err != LIBLTE_SUCCESS) + return err; + + // MBSFN Synchronization Area Id + if(liblte_m2ap_pack_mbsfnsynchronisationareaid(&ie->mbsfnSynchronisationArea, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // MBMS Service area id + if(liblte_m2ap_pack_mbmsserviceareaidlist(&ie->mbmsServiceAreaList, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_enbmbmsconfigurationdataitem( + uint8_t **ptr, + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_ITEM_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("eNB-MBMS-Configuration-Data Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1); + if(liblte_m2ap_unpack_ecgi(ptr, &ie->eCGI) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + if(liblte_m2ap_unpack_mbsfnsynchronisationareaid(ptr, &ie->mbsfnSynchronisationArea) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + if(liblte_m2ap_unpack_mbmsserviceareaidlist(ptr, &ie->mbmsServiceAreaList) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + if(ie->iE_Extensions_present) { + if(liblte_m2ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE MCCH-Update-Time INTEGER (0..255) + *******************************************************************************/ +// lb:0, ub:255 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mcchupdatetime( + LIBLTE_M2AP_MCCH_UPDATE_TIME_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->mcchUpdateTime,ptr,8); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mcchupdatetime( + uint8_t **ptr, + LIBLTE_M2AP_MCCH_UPDATE_TIME_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + ie->mcchUpdateTime = liblte_bits_2_value(ptr, 8); + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE MBSFN-Area-Id INTEGER (0..255) + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnareaid( + LIBLTE_M2AP_MBSFN_AREA_ID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->mbsfn_area_id,ptr,8); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnareaid( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_AREA_ID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + ie->mbsfn_area_id = liblte_bits_2_value(ptr, 8); + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE LCID INTEGER (0..28) + *******************************************************************************/ +// lb:0, ub:28 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_lcid( + LIBLTE_M2AP_LCID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->lcid, ptr,5); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_lcid( + uint8_t **ptr, + LIBLTE_M2AP_LCID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + ie->lcid = liblte_bits_2_value(ptr, 5); + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE Data MCS INTEGER (0..28) + *******************************************************************************/ +// lb:0, ub:28 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_datamcs( + LIBLTE_M2AP_DATA_MCS_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->dataMCS, ptr,5); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_datamcs( + uint8_t **ptr, + LIBLTE_M2AP_DATA_MCS_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + ie->dataMCS = liblte_bits_2_value(ptr, 5); + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE Radio Frame Allocation Offset INTEGER (0..7) + *******************************************************************************/ +// lb:0, ub:7 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_radioframeallocationoffset( + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_OFFSET_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->radioframeAllocationOffset, ptr,3); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_radioframeallocationoffset( + uint8_t **ptr, + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_OFFSET_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + ie->radioframeAllocationOffset = liblte_bits_2_value(ptr, 3); + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE AllocatedSubframesEnd INTEGER (0..1535) + *******************************************************************************/ +// lb:0, ub:1535 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_allocatedsubframesend( + LIBLTE_M2AP_ALLOCATED_SUBFRAMES_END_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->allocated_subframes_end, ptr,16); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_allocatedsubframesend( + uint8_t **ptr, + LIBLTE_M2AP_ALLOCATED_SUBFRAMES_END_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + ie->allocated_subframes_end = liblte_bits_2_value(ptr, 16); + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE MCE-MBMS-M2AP-ID INTEGER (0..16777215) + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mcembmsm2apid( + LIBLTE_M2AP_MCE_MBMS_M2AP_ID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + if(ie->mce_mbms_m2ap_id < 256) { + liblte_value_2_bits(0,ptr,2); + liblte_align_up_zero(ptr, 8); + liblte_value_2_bits(ie->mce_mbms_m2ap_id, ptr, 8); + } else if (ie->mce_mbms_m2ap_id < 65536) { + liblte_value_2_bits(1,ptr,2); + liblte_align_up_zero(ptr, 8); + liblte_value_2_bits(ie->mce_mbms_m2ap_id, ptr, 16); + } else if (ie->mce_mbms_m2ap_id < 16777215) { + liblte_value_2_bits(2,ptr,2); + liblte_align_up_zero(ptr, 8); + liblte_value_2_bits(ie->mce_mbms_m2ap_id, ptr, 24); + } else { + return LIBLTE_ERROR_ENCODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mcembmsm2apid( + uint8_t **ptr, + LIBLTE_M2AP_MCE_MBMS_M2AP_ID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + uint8_t value = liblte_bits_2_value(ptr, 2); + liblte_align_up(ptr, 8); + if(value == 0){ + ie->mce_mbms_m2ap_id = liblte_bits_2_value(ptr, 8); + } else if (value == 1){ + ie->mce_mbms_m2ap_id = liblte_bits_2_value(ptr, 16); + } else if(value == 2){ + ie->mce_mbms_m2ap_id = liblte_bits_2_value(ptr, 24); + } else { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE ENB-MBMS-M2AP-ID INTEGER (0..65535) + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_enbmbmsm2apid( + LIBLTE_M2AP_ENB_MBMS_M2AP_ID_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + if(ie->enb_mbms_m2ap_id < 256) { + liblte_value_2_bits(0,ptr,2); + liblte_align_up_zero(ptr, 8); + liblte_value_2_bits(ie->enb_mbms_m2ap_id, ptr, 8); + } else if (ie->enb_mbms_m2ap_id < 65535) { + liblte_value_2_bits(1,ptr,2); + liblte_align_up_zero(ptr, 8); + liblte_value_2_bits(ie->enb_mbms_m2ap_id, ptr, 16); + } else { + return LIBLTE_ERROR_ENCODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_enbmbmsm2apid( + uint8_t **ptr, + LIBLTE_M2AP_ENB_MBMS_M2AP_ID_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + uint8_t value = liblte_bits_2_value(ptr, 2); + liblte_align_up(ptr, 8); + if(value == 0){ + ie->enb_mbms_m2ap_id = liblte_bits_2_value(ptr, 8); + } else if (value == 1){ + ie->enb_mbms_m2ap_id = liblte_bits_2_value(ptr, 16); + } else { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE PDCCH-Length ENUM + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_pdcchlength( + LIBLTE_M2AP_PDCCH_LENGTH_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->ext, ptr,1); + liblte_value_2_bits(ie->pdcchLength, ptr,1); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_pdcchlength( + uint8_t **ptr, + LIBLTE_M2AP_PDCCH_LENGTH_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("PDCCH-Length error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + uint32_t tmp = liblte_bits_2_value(ptr, 1); + if(tmp == LIBLTE_M2AP_PDCCH_LENGTH_S1){ + ie->pdcchLength = LIBLTE_M2AP_PDCCH_LENGTH_S1; + } else if(tmp == LIBLTE_M2AP_PDCCH_LENGTH_S2) { + ie->pdcchLength = LIBLTE_M2AP_PDCCH_LENGTH_S2; + } else{ + return LIBLTE_ERROR_ENCODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE Repetition-Period ENUM + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_repetitionperiod( + LIBLTE_M2AP_REPETITION_PERIOD_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->repetitionPeriod, ptr,2); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_repetitionperiod( + uint8_t **ptr, + LIBLTE_M2AP_REPETITION_PERIOD_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + uint32_t tmp = liblte_bits_2_value(ptr, 2); + if(tmp == LIBLTE_M2AP_REPETITION_PERIOD_RF32){ + ie->repetitionPeriod = LIBLTE_M2AP_REPETITION_PERIOD_RF32; + } else if(tmp == LIBLTE_M2AP_REPETITION_PERIOD_RF64) { + ie->repetitionPeriod = LIBLTE_M2AP_REPETITION_PERIOD_RF64; + } else if(tmp == LIBLTE_M2AP_REPETITION_PERIOD_RF128) { + ie->repetitionPeriod = LIBLTE_M2AP_REPETITION_PERIOD_RF128; + } else if(tmp == LIBLTE_M2AP_REPETITION_PERIOD_RF256) { + ie->repetitionPeriod = LIBLTE_M2AP_REPETITION_PERIOD_RF256; + } else{ + return LIBLTE_ERROR_ENCODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE Offset ENUM + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_offset( + LIBLTE_M2AP_OFFSET_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->offset, ptr,4); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_offset( + uint8_t **ptr, + LIBLTE_M2AP_OFFSET_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + ie->offset = liblte_bits_2_value(ptr, 4); + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE Modification Period ENUM + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_modificationperiod( + LIBLTE_M2AP_MODIFICATION_PERIOD_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->modificationPeriod, ptr,1); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_modificationperiod( + uint8_t **ptr, + LIBLTE_M2AP_MODIFICATION_PERIOD_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + uint32_t tmp = liblte_bits_2_value(ptr, 1); + if(tmp == LIBLTE_M2AP_MODIFICATION_PERIOD_RF512){ + ie->modificationPeriod = LIBLTE_M2AP_MODIFICATION_PERIOD_RF512; + } else if(tmp == LIBLTE_M2AP_MODIFICATION_PERIOD_RF1024) { + ie->modificationPeriod = LIBLTE_M2AP_MODIFICATION_PERIOD_RF1024; + } else{ + return LIBLTE_ERROR_ENCODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE Subframe Allocation Info STATIC BIT STRING + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_subframeallocationinfo( + LIBLTE_M2AP_SUBFRAME_ALLOCATION_INFO_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + for (int i = 0; i < LIBLTE_M2AP_SUBFRAME_ALLOCATION_INFO_BIT_STRING_LEN;i++){ + liblte_value_2_bits(ie->buffer[i], ptr,1); + } + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_subframeallocationinfo( + uint8_t **ptr, + LIBLTE_M2AP_SUBFRAME_ALLOCATION_INFO_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + for (int i = 0; i < LIBLTE_M2AP_SUBFRAME_ALLOCATION_INFO_BIT_STRING_LEN;i++){ + ie->buffer[i] = liblte_bits_2_value(ptr, 1); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE Subframe Allocation CHOICE + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_subframeallocation( + LIBLTE_M2AP_SUBFRAME_ALLOCATION_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->choice_type , ptr, 1); + if (ie->choice_type == LIBLTE_M2AP_SUBFRAME_ALLOCATION_ONE_FRAME) { + for (int i = 0; i < 6; i++) { + liblte_value_2_bits(ie->choice.oneFrame[i], ptr, 1); + } + } else if (ie->choice_type == LIBLTE_M2AP_SUBFRAME_ALLOCATION_FOUR_FRAMES) { + for (int i = 0; i < 24; i++) { + liblte_value_2_bits(ie->choice.fourFrames[i], ptr,1); + } + } + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_subframeallocation( + uint8_t **ptr, + LIBLTE_M2AP_SUBFRAME_ALLOCATION_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + uint8_t tmp = liblte_bits_2_value(ptr, 1); + if (tmp == LIBLTE_M2AP_SUBFRAME_ALLOCATION_ONE_FRAME){ + ie->choice_type = LIBLTE_M2AP_SUBFRAME_ALLOCATION_ONE_FRAME; + for (int i = 0; i < 6; i++){ + ie->choice.oneFrame[i] = liblte_bits_2_value(ptr, 1); + } + } else{ + ie->choice_type = LIBLTE_M2AP_SUBFRAME_ALLOCATION_FOUR_FRAMES; + for (int i = 0; i < 24; i++){ + ie->choice.fourFrames[i] = liblte_bits_2_value(ptr, 1); + } + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE Modulation and Coding Scheme ENUM + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_modulationandcodingscheme( + LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->mcs, ptr,2); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_modulationandcodingscheme( + uint8_t **ptr, + LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + uint32_t tmp = liblte_bits_2_value(ptr, 2); + if(tmp == LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N2) { + ie->mcs = LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N2; + } else if(tmp == LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N7) { + ie->mcs = LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N7; + } else if(tmp == LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N13) { + ie->mcs = LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N13; + } else if(tmp == LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N19) { + ie->mcs = LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N19; + } else { + return LIBLTE_ERROR_ENCODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE RadioframeAllocationPeriod ENUM + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_radioframeallocationperiod( + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->e, ptr,3); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_radioframeallocationperiod( + uint8_t **ptr, + LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + uint32_t tmp = liblte_bits_2_value(ptr, 3); + if(tmp == LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N1) { + ie->e = LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N1; + } else if(tmp == LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N2) { + ie->e = LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N2; + } else if(tmp == LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N4) { + ie->e = LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N4; + } else if(tmp == LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N8) { + ie->e = LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N8; + } else if(tmp == LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N16) { + ie->e = LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N16; + } else if(tmp == LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N32) { + ie->e = LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N32; + } else { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE Common-Subframe-Scheduling-Period ENUM + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_commonsubframeallocationperiod( + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->e, ptr,3); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_commonsubframeallocationperiod( + uint8_t **ptr, + LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + uint32_t tmp = liblte_bits_2_value(ptr, 3); + if(tmp == LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF8) { + ie->e = LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF8; + } else if(tmp == LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF16) { + ie->e = LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF16; + } else if(tmp == LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF32) { + ie->e = LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF32; + } else if(tmp == LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF64) { + ie->e = LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF64; + } else if(tmp == LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF128) { + ie->e = LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF128; + } else if(tmp == LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF256) { + ie->e = LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF256; + } else { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE MCH Scheduling Period ENUM + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mchschedulingperiod( + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->e, ptr,3); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mchschedulingperiod( + uint8_t **ptr, + LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + uint32_t tmp = liblte_bits_2_value(ptr, 3); + if(tmp == LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF8) { + ie->e = LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF8; + } else if(tmp == LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF16) { + ie->e = LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF16; + } else if(tmp == LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF32) { + ie->e = LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF32; + } else if(tmp == LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF64) { + ie->e = LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF64; + } else if(tmp == LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF128) { + ie->e = LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF128; + } else if(tmp == LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF256) { + ie->e = LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF256; + } else if(tmp == LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF512) { + ie->e = LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF512; + } else if(tmp == LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF1024) { + ie->e = LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF1024; + } else { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE Cell-Reservation-Info ENUM + *******************************************************************************/ +// lb:0, ub:512 +LIBLTE_ERROR_ENUM liblte_m2ap_pack_cellreservationinfo( + LIBLTE_M2AP_CELL_RESERVATION_INFO_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + liblte_value_2_bits(ie->ext, ptr,1); + liblte_value_2_bits(ie->e, ptr,1); + err = LIBLTE_SUCCESS; + } + return err; +} +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_cellreservationinfo( + uint8_t **ptr, + LIBLTE_M2AP_CELL_RESERVATION_INFO_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if (ie != NULL && ptr != NULL) + { + ie->ext = liblte_bits_2_value(ptr, 1); + uint32_t tmp = liblte_bits_2_value(ptr, 1); + if(tmp == LIBLTE_M2AP_CELL_RESERVATION_INFO_RESERVED_CELL) { + ie->e = LIBLTE_M2AP_CELL_RESERVATION_INFO_RESERVED_CELL; + } else if(tmp == LIBLTE_M2AP_CELL_RESERVATION_INFO_NON_RESERVED_CELL) { + ie->e = LIBLTE_M2AP_CELL_RESERVATION_INFO_NON_RESERVED_CELL; + } else { + return LIBLTE_ERROR_ENCODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} +/*************************************************************************************** + * ProtocolIE TMGI SEQUENCE + ***************************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_tmgi( + LIBLTE_M2AP_TMGI_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + // Extension + liblte_value_2_bits(ie->ext, ptr, 1); + if(ie->ext) { + liblte_log_print("Cell-Information Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + //Bools + liblte_value_2_bits(ie->iE_Extensions_present, ptr, 1); + if(liblte_m2ap_pack_plmnidentity(&ie->pLMN_Identity, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + if(liblte_m2ap_pack_serviceid(&ie->serviceID, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_tmgi( + uint8_t **ptr, + LIBLTE_M2AP_TMGI_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("TMGI error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + //Bools + ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1); + liblte_align_up(ptr,8); + + //PLMN Identity + if(liblte_m2ap_unpack_plmnidentity(ptr, &ie->pLMN_Identity) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + if(liblte_m2ap_unpack_serviceid(ptr, &ie->serviceID) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} +/*************************************************************************************** + * ProtocolIE TNL Information SEQUENCE + ***************************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_tnlinformation( + LIBLTE_M2AP_TNL_INFORMATION_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + // Extension + liblte_value_2_bits(ie->ext, ptr, 1); + if(ie->ext) { + liblte_log_print("TNL-Information Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + //Bools + liblte_value_2_bits(ie->iE_Extensions_present, ptr, 1); + + if(liblte_m2ap_pack_ipaddress(&ie->iPMCAddress, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + if(liblte_m2ap_pack_ipaddress(&ie->iPSourceAddress, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + if(liblte_m2ap_pack_gtpteid(&ie->gtpTeid, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_tnlinformation( + uint8_t **ptr, + LIBLTE_M2AP_TNL_INFORMATION_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("Cell-Information Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + //Bools + ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1); + + if(liblte_m2ap_unpack_ipaddress(ptr, &ie->iPMCAddress) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + if(liblte_m2ap_unpack_ipaddress(ptr, &ie->iPSourceAddress) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + if(liblte_m2ap_unpack_gtpteid(ptr, &ie->gtpTeid) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} +/*************************************************************************************** + * ProtocolIE CellInformation SEQUENCE + ***************************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_cellinformation( + LIBLTE_M2AP_CELL_INFORMATION_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + // Extension + liblte_value_2_bits(ie->ext, ptr, 1); + if(ie->ext) { + liblte_log_print("Cell-Information Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + //Bools + liblte_value_2_bits(ie->ie_extensions_present, ptr, 1); + if(liblte_m2ap_pack_ecgi(&ie->eCGI, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + if(liblte_m2ap_pack_cellreservationinfo(&ie->cellReservationInfo, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_cellinformation( + uint8_t **ptr, + LIBLTE_M2AP_CELL_INFORMATION_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("Cell-Information Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + //Bools + ie->ie_extensions_present = liblte_bits_2_value(ptr, 1); + if(liblte_m2ap_unpack_ecgi(ptr, &ie->eCGI) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + if(liblte_m2ap_unpack_cellreservationinfo(ptr, &ie->cellReservationInfo) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/*************************************************************************************** + * ProtocolIE CellInformation-List SEQUENCE + ***************************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_cellinformationlist( + LIBLTE_M2AP_CELL_INFORMATION_LIST_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + if(ie != NULL && + ptr != NULL) + { + // Length + liblte_align_up_zero(ptr,8); + liblte_value_2_bits(ie->len-1, ptr, 8); + if (ie->len > 32) { + liblte_log_print( + "Cell-Information-List pack error - max supported dynamic sequence length = 32, ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + for(uint16_t i =0; i < ie->len; i++){ + err = liblte_m2ap_pack_cellinformation(&ie->buffer[i], ptr); + if(err != LIBLTE_SUCCESS) + return err; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_cellinformationlist( + uint8_t **ptr, + LIBLTE_M2AP_CELL_INFORMATION_LIST_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Length + liblte_align_up(ptr,8); + ie->len = liblte_bits_2_value(ptr, 8) + 1; + if (ie->len > 32) { + liblte_log_print( + "Cell-Information-List unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_DECODE_FAIL; + } + + for(uint16_t i =0; i < ie->len; i++){ + err = liblte_m2ap_unpack_cellinformation(ptr, &ie->buffer[i]); + if(err != LIBLTE_SUCCESS) + return err; + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE MCCHRelatedBCCH-ConfigPerMBSFNArea-Item SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mcchrelatedbcchconfigpermbsfnareaitem( + LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_ITEM_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + //Extension present + liblte_value_2_bits(ie->ext?1:0, ptr, 1); + if(ie->ext) { + liblte_log_print("MCCHRelatedBCCH-ConfigPerMBSFNArea Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + //Bools + liblte_value_2_bits(ie->cellInformationList_present?1:0, ptr, 1); + //IE Extension present + liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1); + if(ie->iE_Extensions_present) { + liblte_log_print("MCCHRelatedBCCH-ConfigPerMBSFNArea Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(ptr,8); + + // MBSFN Area Id + err = liblte_m2ap_pack_mbsfnareaid(&ie->mbsfnArea,ptr); + if(err != LIBLTE_SUCCESS) + return err; + + // PDCCH Length + if(liblte_m2ap_pack_pdcchlength(&ie->pdcchLength, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Repetition Period + if(liblte_m2ap_pack_repetitionperiod(&ie->repetitionPeriod, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Offset + if(liblte_m2ap_pack_offset(&ie->offset, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Modification Period + if(liblte_m2ap_pack_modificationperiod(&ie->modificationPeriod, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Subframe Allocation Info + if(liblte_m2ap_pack_subframeallocationinfo(&ie->subframeAllocationInfo, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Modulation and Conding Scheme + if(liblte_m2ap_pack_modulationandcodingscheme(&ie->modulationAndCodingScheme, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Cell Information List + if(liblte_m2ap_pack_cellinformationlist(&ie->cellInformationList, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mcchrelatedbcchconfigpermbsfnareaitem( + uint8_t **ptr, + LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_ITEM_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("MCCHRelatedBCCH-ConfigPerMBSFNArea Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + //Bools + ie->cellInformationList_present = liblte_bits_2_value(ptr, 1); + ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1); + liblte_align_up_zero(ptr,8); + + //MBSFN Area Id + if(liblte_m2ap_unpack_mbsfnareaid(ptr, &ie->mbsfnArea) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + //PDCCH Length + if(liblte_m2ap_unpack_pdcchlength(ptr, &ie->pdcchLength) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + //Repetition Period + if(liblte_m2ap_unpack_repetitionperiod(ptr, &ie->repetitionPeriod) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + //Offset + if(liblte_m2ap_unpack_offset(ptr, &ie->offset) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + ////Modification Period + if(liblte_m2ap_unpack_modificationperiod(ptr, &ie->modificationPeriod) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + //Subframe Allocation Info + if(liblte_m2ap_unpack_subframeallocationinfo(ptr, &ie->subframeAllocationInfo) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + //Modulation Coding Scheme + if(liblte_m2ap_unpack_modulationandcodingscheme(ptr, &ie->modulationAndCodingScheme) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + //Cell Information List + if(ie->cellInformationList_present) { + if(liblte_m2ap_unpack_cellinformationlist(ptr, &ie->cellInformationList) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + if(ie->iE_Extensions_present) { + if(liblte_m2ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + + +/*************************************************************************************** + * ProtocolIE ENB-MBMS-Configuration-data-List SEQUENCE OF ProtocolIE-Single-Container + ***************************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_enbmbmsconfigurationdatalist( + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_LIST_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_M2AP_PROTOCOLIE_SINGLECONTAINER_STRUCT proto_container; + proto_container.id.ProtocolIE_ID = LIBLTE_M2AP_IE_ID_ENB_MBMS_CONFIGURATION_DATA_ITEM; + proto_container.criticality = LIBLTE_M2AP_CRITICALITY_REJECT; + + if(ie != NULL && + ptr != NULL) + { + if(ie->len > 32) { + liblte_log_print( + "ProtocolIE_ENB-MBMS-Configuration-data-List pack error - max supported dynamic sequence length = 32, " + "ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Length + liblte_value_2_bits(ie->len-1, ptr, 8); + + for(uint16_t i =0; i < ie->len; i++){ + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr; + + // ProtocolIE - ENB-MBMS-Configuration-Data-Item + tmp_ptr = tmp_msg.msg; + err = liblte_m2ap_pack_enbmbmsconfigurationdataitem(&ie->buffer[i],&tmp_ptr); + if(err != LIBLTE_SUCCESS){ + return err; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_ENB_MBMS_CONFIGURATION_DATA_ITEM, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_enbmbmsconfigurationdatalist( + uint8_t **ptr, + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_LIST_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_M2AP_CRITICALITY_ENUM crit; + LIBLTE_M2AP_PROTOCOLIE_SINGLECONTAINER_STRUCT proto_container; + uint32_t ie_id; + uint32_t len; + + if(ie != NULL && + ptr != NULL) + { + // Length FIXME!!! + ie->len = liblte_bits_2_value(ptr, 16) + 1; + liblte_align_up(ptr, 8); + if (ie->len > 32) { + liblte_log_print( + "ENB-MBMS-Configuration-data-List unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_DECODE_FAIL; + } + + for(uint16_t i =0; i < ie->len; i++){ + if(liblte_m2ap_unpack_protocolie_singlecontainer(ptr, &proto_container) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = liblte_m2ap_unpack_enbmbmsconfigurationdataitem(ptr, &ie->buffer[i]); + if(err != LIBLTE_SUCCESS) + return err; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/*************************************************************************************** + * ProtocolIE MCCHrelatedBCCH-ConfigPerMBSFNArea SEQUENCE OF ProtocolIE-Single-Container + ***************************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mcchrelatedbcchconfigpermbsfnarea( + LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + if(ie->len > 32) { + liblte_log_print( + "ProtocolIE_MCCHrelatedBCCH-ConfigPerMBSFNArea pack error - max supported dynamic sequence length = 32, " + "ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Length + liblte_value_2_bits(ie->len-1, ptr, 8); + + for(uint16_t i =0; i < ie->len; i++){ + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr; + + // ProtocolIE - MCCHrelatedBCCH-ConfigPerMBSFNArea + tmp_ptr = tmp_msg.msg; + err = liblte_m2ap_pack_mcchrelatedbcchconfigpermbsfnareaitem(&ie->buffer[i],&tmp_ptr); + if(err != LIBLTE_SUCCESS){ + return err; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_MCCHRELATEDBCCH_CONFIGPERMBSFNAREA_ITEM, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mcchrelatedbcchconfigpermbsfnarea( + uint8_t **ptr, + LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_M2AP_CRITICALITY_ENUM crit; + LIBLTE_M2AP_PROTOCOLIE_SINGLECONTAINER_STRUCT proto_container; + uint32_t ie_id; + uint32_t len; + + if(ie != NULL && + ptr != NULL) + { + // Length FIXME!!! + ie->len = liblte_bits_2_value(ptr, 16) + 1; + liblte_align_up(ptr, 8); + if (ie->len > 32) { + liblte_log_print( + "MCCHrelatedBCCH-ConfigPerMBSFNAreaunpack error - max supported dynamic sequence length=32, ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_DECODE_FAIL; + } + + for(uint16_t i =0; i < ie->len; i++){ + if(liblte_m2ap_unpack_protocolie_singlecontainer(ptr, &proto_container) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = liblte_m2ap_unpack_mcchrelatedbcchconfigpermbsfnareaitem(ptr, &ie->buffer[i]); + if(err != LIBLTE_SUCCESS) + return err; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE MBMSSessionListPerPMCH-Item SEQUENCE (SIZE(1..maxnoofSessionsPerPMCH)) OF SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmssessionlistperpmchitem( + LIBLTE_M2AP_MBMS_SESSION_LIST_PER_PMCH_ITEM_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Length + liblte_value_2_bits(ie->len-1, ptr, 5); + + for (int i =0; ilen; i++) { + liblte_value_2_bits(ie->buffer[i].ext, ptr,1); + liblte_value_2_bits(ie->buffer[i].iE_Extensions_present, ptr,1); + + //TMGI + if(liblte_m2ap_pack_tmgi(&ie->buffer[i].Tmgi, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + // LCID + if(liblte_m2ap_pack_lcid(&ie->buffer[i].Lcid, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmssessionlistperpmchitem( + uint8_t **ptr, + LIBLTE_M2AP_MBMS_SESSION_LIST_PER_PMCH_ITEM_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Length + ie->len = liblte_bits_2_value(ptr, 5)+1; + + for (int i =0; ilen; i++){ + ie->buffer[i].ext = liblte_bits_2_value(ptr,1); + ie->buffer[i].iE_Extensions_present = liblte_bits_2_value(ptr,1); + //TMGI + if(liblte_m2ap_unpack_tmgi(ptr, &ie->buffer[i].Tmgi) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + // LCID + if(liblte_m2ap_unpack_lcid(ptr, &ie->buffer[i].Lcid) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + + + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE MBSFN-Subframe-Configuration SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnsubframeconfiguration( + LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + //Extension present + liblte_value_2_bits(ie->ext?1:0, ptr, 1); + if(ie->ext) { + liblte_log_print("MBSFN-Subframe-Configuration Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + //IE Extension present + liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1); + if(ie->iE_Extensions_present) { + liblte_log_print("MBSFN Subframe Configuration Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Radio Frame Allocation Period + if(liblte_m2ap_pack_radioframeallocationperiod(&ie->radioFrameAllocationPeriod, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Radio Frame Allocation Offset + if(liblte_m2ap_pack_radioframeallocationoffset(&ie->radioFrameAllocationOffset, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Subframe Allocation + if(liblte_m2ap_pack_subframeallocation(&ie->subframeAllocation, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_pack_protocolextensioncontainer(&ie->iE_Extensions, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnsubframeconfiguration( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("PMCH Configuration error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + //Bools + ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1); + + // Radio Frame Allocation Period + if(liblte_m2ap_unpack_radioframeallocationperiod(ptr, &ie->radioFrameAllocationPeriod) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + // Radio Frame Allocation Offset + if(liblte_m2ap_unpack_radioframeallocationoffset(ptr, &ie->radioFrameAllocationOffset) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + // Subframe Allocation + if(liblte_m2ap_unpack_subframeallocation(ptr, &ie->subframeAllocation) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} +/*************************************************************************************** + * ProtocolIE MBSFN-Subframe-Configuration-List SEQUENCE OF ProtocolIE-Single-Container + ***************************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnsubframeconfigurationlist( + LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_LIST_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + if(ie->len > 32) { + liblte_log_print( + "ProtocolIE_PMCH-Configuration-List pack error - max supported dynamic sequence length = 32, " + "ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Length + liblte_value_2_bits(ie->len-1, ptr, 3); + liblte_align_up_zero(ptr, 8); + + for(uint16_t i =0; i < ie->len; i++){ + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr; + + // ProtocolIE - MBSFN-Subframe-Configuration + tmp_ptr = tmp_msg.msg; + err = liblte_m2ap_pack_mbsfnsubframeconfiguration(&ie->buffer[i],&tmp_ptr); + if(err != LIBLTE_SUCCESS){ + return err; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_MBSFN_SUBFRAME_CONFIGURATION_ITEM, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + } + + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnsubframeconfigurationlist( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_LIST_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_M2AP_CRITICALITY_ENUM crit; + LIBLTE_M2AP_PROTOCOLIE_SINGLECONTAINER_STRUCT proto_container; + uint32_t ie_id; + uint32_t len; + + if(ie != NULL && + ptr != NULL) + { + // Length FIXME!!! + ie->len = liblte_bits_2_value(ptr, 3)+1; + liblte_align_up(ptr, 8); + if (ie->len > 32) { + liblte_log_print( + "MBSFN-Area-Configuration-List unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_DECODE_FAIL; + } + + for(uint16_t i =0; i < ie->len; i++){ + if(liblte_m2ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = liblte_m2ap_unpack_mbsfnsubframeconfiguration(ptr, &ie->buffer[i]); + if(err != LIBLTE_SUCCESS) + return err; + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE PMCH-Configiguration SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_pmchconfiguration( + LIBLTE_M2AP_PMCH_CONFIGURATION_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + //Extension present + liblte_value_2_bits(ie->ext?1:0, ptr, 1); + if(ie->ext) { + liblte_log_print("PMCH-Configuration Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + //IE Extension present + liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1); + if(ie->iE_Extensions_present) { + liblte_log_print("PMCH Configuration Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(ptr,8); + + // Allocated Subframes End + if(liblte_m2ap_pack_allocatedsubframesend(&ie->allocatedSubframesEnd, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Data MCS + if(liblte_m2ap_pack_datamcs(&ie->dataMCS, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + // Scheduling Period + if(liblte_m2ap_pack_mchschedulingperiod(&ie->mchSchedulingPeriod, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_pmchconfiguration( + uint8_t **ptr, + LIBLTE_M2AP_PMCH_CONFIGURATION_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("PMCH Configuration error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + //Bools + //ie->cellInformationList_present = liblte_bits_2_value(ptr, 1); + ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1); + liblte_align_up_zero(ptr,8); + + // Allocated Subframes End + if(liblte_m2ap_unpack_allocatedsubframesend(ptr, &ie->allocatedSubframesEnd) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + // Data MCS + if(liblte_m2ap_unpack_datamcs(ptr, &ie->dataMCS) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + // Scheduling Period + if(liblte_m2ap_unpack_mchschedulingperiod(ptr, &ie->mchSchedulingPeriod) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * ProtocolIE PMCH-Configiguration-Item SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_pmchconfigurationitem( + LIBLTE_M2AP_PMCH_CONFIGURATION_ITEM_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + //Extension present + liblte_value_2_bits(ie->ext?1:0, ptr, 1); + if(ie->ext) { + liblte_log_print("PMCH-Configuration Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + //IE Extension present + liblte_value_2_bits(ie->iE_Extensions_present?1:0, ptr, 1); + if(ie->iE_Extensions_present) { + liblte_log_print("PMCH Configuration Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // PMCH-Configuration + err = liblte_m2ap_pack_pmchconfiguration(&ie->PMCHConfiguration, ptr); + if(err != LIBLTE_SUCCESS){ + return err; + } + + // MBMS Session List per PMCH Item + if(liblte_m2ap_pack_mbmssessionlistperpmchitem(&ie->MBMSSessionListPerPMCHItem, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_pmchconfigurationitem( + uint8_t **ptr, + LIBLTE_M2AP_PMCH_CONFIGURATION_ITEM_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + // Extension + ie->ext = liblte_bits_2_value(ptr, 1); + if(ie->ext) { + liblte_log_print("PMCH Configuration Item error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + //Bools + ie->iE_Extensions_present = liblte_bits_2_value(ptr, 1); + + //PMCH Configuration + if(liblte_m2ap_unpack_pmchconfiguration(ptr, &ie->PMCHConfiguration) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + // MBMS Session List per PMCH Item + if(liblte_m2ap_unpack_mbmssessionlistperpmchitem(ptr, &ie->MBMSSessionListPerPMCHItem) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + + if(ie->iE_Extensions_present) { + if(liblte_m2ap_unpack_protocolextensioncontainer(ptr, &ie->iE_Extensions) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + err = LIBLTE_SUCCESS; + } + return err; +} +/*************************************************************************************** + * ProtocolIE PMCH-Configuration-List SEQUENCE OF ProtocolIE-Single-Container + ***************************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_pmchconfigurationlist( + LIBLTE_M2AP_PMCH_CONFIGURATION_LIST_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + if(ie->len > 32) { + liblte_log_print( + "ProtocolIE_PMCH-Configuration-List pack error - max supported dynamic sequence length = 32, " + "ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Length + liblte_value_2_bits(ie->len, ptr, 4); + liblte_align_up_zero(ptr, 8); + + for(uint16_t i =0; i < ie->len; i++){ + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr; + + // ProtocolIE - PMCH-Configuration-Item + tmp_ptr = tmp_msg.msg; + err = liblte_m2ap_pack_pmchconfigurationitem(&ie->buffer[i],&tmp_ptr); + if(err != LIBLTE_SUCCESS){ + return err; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_PMCH_CONFIGURATION_ITEM, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_pmchconfigurationlist( + uint8_t **ptr, + LIBLTE_M2AP_PMCH_CONFIGURATION_LIST_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_M2AP_CRITICALITY_ENUM crit; + LIBLTE_M2AP_PROTOCOLIE_SINGLECONTAINER_STRUCT proto_container; + uint32_t ie_id; + uint32_t len; + + if(ie != NULL && + ptr != NULL) + { + // Length FIXME!!! + ie->len = liblte_bits_2_value(ptr, 4); + liblte_align_up(ptr, 8); + if (ie->len > 32) { + liblte_log_print( + "MBSFN-Area-Configuration-List unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_DECODE_FAIL; + } + + for(uint16_t i =0; i < ie->len; i++){ + if(liblte_m2ap_unpack_protocolie_header(ptr, &ie_id, &crit, &len) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = liblte_m2ap_unpack_pmchconfigurationitem(ptr, &ie->buffer[i]); + if(err != LIBLTE_SUCCESS) + return err; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * ProtocolIE MBSFN-Area-Configuration-Item SEQUENCE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnareaconfigurationitem( + LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_ITEM_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + int n_ies = 4; + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr; + + liblte_value_2_bits(n_ies,ptr,16); + + // PMCH Configuration List + tmp_ptr = tmp_msg.msg; + err = liblte_m2ap_pack_pmchconfigurationlist(&ie->PMCHConfigurationList, &tmp_ptr); + if (err != LIBLTE_SUCCESS) + return err; + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_PMCH_CONFIGURATION_LIST, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + + // MBSFN Subframe Configuration List + tmp_ptr = tmp_msg.msg; + err = liblte_m2ap_pack_mbsfnsubframeconfigurationlist(&ie->MBSFNSubframeConfigurationList, &tmp_ptr); + if (err != LIBLTE_SUCCESS) + return err; + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_MBSFN_SUBFRAME_CONFIGURATION_LIST, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + // Common Subframe Allocation Period + tmp_ptr = tmp_msg.msg; + err = liblte_m2ap_pack_commonsubframeallocationperiod(&ie->CommonSubframeAllocationPeriod, &tmp_ptr); + if (err != LIBLTE_SUCCESS) + return err; + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_COMMON_SUBFRAME_ALLOCATION_PERIOD, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + //MBSFN Area Id + tmp_ptr = tmp_msg.msg; + err = liblte_m2ap_pack_mbsfnareaid(&ie->MBSFNAreaId, &tmp_ptr); + if (err != LIBLTE_SUCCESS) + return err; + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_MBSFN_AREA_ID, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnareaconfigurationitem( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_ITEM_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_M2AP_CRITICALITY_ENUM crit; + uint32_t ie_id; + uint32_t len; + uint32_t n_ie; + uint32_t i; + + if(ie != NULL && + ptr != NULL) + { + // No. of ProtocolIE-Container + n_ie = liblte_bits_2_value(ptr, 16); + + // Unpack ProtocolIE Fields + for(i=0;iPMCHConfigurationList) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } else if(LIBLTE_M2AP_IE_ID_MBSFN_SUBFRAME_CONFIGURATION_LIST == ie_id) { + if(liblte_m2ap_unpack_mbsfnsubframeconfigurationlist(ptr, &ie->MBSFNSubframeConfigurationList) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } else if (LIBLTE_M2AP_IE_ID_COMMON_SUBFRAME_ALLOCATION_PERIOD == ie_id) { + if (liblte_m2ap_unpack_commonsubframeallocationperiod(ptr, &ie->CommonSubframeAllocationPeriod) != + LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } else if (LIBLTE_M2AP_IE_ID_MBSFN_AREA_ID == ie_id) { + if (liblte_m2ap_unpack_mbsfnareaid(ptr, &ie->MBSFNAreaId) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/*************************************************************************************** + * ProtocolIE MBSFN-Area-Configuration-List SEQUENCE OF ProtocolIE-Single-Container + ***************************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbsfnareaconfigurationlist( + LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_LIST_STRUCT *ie, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie != NULL && + ptr != NULL) + { + if(ie->len > 32) { + liblte_log_print( + "ProtocolIE_MBSFN-Area-Configuration-List pack error - max supported dynamic sequence length = 32, " + "ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // Length + liblte_value_2_bits(ie->len-1, ptr, 8); + + for(uint16_t i =0; i < ie->len; i++){ + // ProtocolIE - MBSFN-Area-Configuration-Item + err = liblte_m2ap_pack_mbsfnareaconfigurationitem(&ie->buffer[i],ptr); + if(err != LIBLTE_SUCCESS){ + return err; + } + liblte_align_up_zero(ptr, 8); + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbsfnareaconfigurationlist( + uint8_t **ptr, + LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_LIST_STRUCT *ie) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_M2AP_CRITICALITY_ENUM crit; + LIBLTE_M2AP_PROTOCOLIE_SINGLECONTAINER_STRUCT proto_container; + uint32_t ie_id; + uint32_t len; + + if(ie != NULL && + ptr != NULL) + { + // Length FIXME!!! + ie->len = liblte_bits_2_value(ptr, 8) + 1; + liblte_align_up(ptr, 8); + if (ie->len > 32) { + liblte_log_print( + "MBSFN-Area-Configuration-List unpack error - max supported dynamic sequence length = 32, ie->len = %d\n", + ie->len); + return LIBLTE_ERROR_DECODE_FAIL; + } + + for(uint16_t i =0; i < ie->len; i++){ + err = liblte_m2ap_unpack_mbsfnareaconfigurationitem(ptr, &ie->buffer[i]); + if(err != LIBLTE_SUCCESS) + return err; + } + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * Protocol Message M2SetupRequest STRUCT + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_m2setuprequest( + LIBLTE_M2AP_MESSAGE_M2SETUPREQUEST_STRUCT *msg, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + + // Extension + liblte_value_2_bits(msg->ext?1:0, ptr, 1); + liblte_align_up_zero(ptr, 8); + if(msg->ext) { + liblte_log_print("M2SetupRequestIEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // No. of ProtocolIE + uint32_t n_ie = 3; + if(!msg->eNBname_present) + n_ie--; + liblte_value_2_bits(n_ie, ptr, 16); + + // Temp container for IEs + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr; + + // ProtocolIE - Global_ENB_ID + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_globalenbid(&msg->Global_ENB_ID, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_GLOBALENB_ID, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + // ProtocolIE - eNBname + if(msg->eNBname_present) { + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_enbname(&msg->eNBname, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header(tmp_msg.N_bits / 8, + LIBLTE_M2AP_IE_ID_ENBNAME, + LIBLTE_M2AP_CRITICALITY_IGNORE, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + } + + //Protocol IE - eNB-MBMS-Configuration-Data-List + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_enbmbmsconfigurationdatalist(&msg->configurationDataList, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header(tmp_msg.N_bits / 8, + LIBLTE_M2AP_IE_ID_ENB_MBMS_CONFIGURATION_DATA_LIST, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_m2setuprequest( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_M2SETUPREQUEST_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + LIBLTE_M2AP_CRITICALITY_ENUM crit; + uint32_t ie_id; + uint32_t len; + uint32_t n_ie; + uint32_t i; + + // Set booleans + msg->eNBname_present = false; + + // Extension + msg->ext = liblte_bits_2_value(ptr, 1); + liblte_align_up(ptr, 8); + if(msg->ext) { + liblte_log_print("M2SetupRequestIEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + // No. of ProtocolIE-Container + n_ie = liblte_bits_2_value(ptr, 16); + + // Unpack ProtocolIE Fields + for(i=0;iGlobal_ENB_ID) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } else if(LIBLTE_M2AP_IE_ID_ENBNAME == ie_id) { + if(liblte_m2ap_unpack_enbname(ptr, &msg->eNBname) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + msg->eNBname_present = true; + } else if(LIBLTE_M2AP_IE_ID_ENB_MBMS_CONFIGURATION_DATA_LIST == ie_id){ + if(liblte_m2ap_unpack_enbmbmsconfigurationdatalist(ptr, &msg->configurationDataList) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + } + + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * Protocol Message M2SetupResponse STRUCT + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_m2setupresponse( + LIBLTE_M2AP_MESSAGE_M2SETUPRESPONSE_STRUCT *msg, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + // Extension + liblte_value_2_bits(msg->ext?1:0, ptr, 1); + liblte_align_up_zero(ptr, 8); + if(msg->ext) { + liblte_log_print("M2SetupResponseIEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // No. of ProtocolIE + uint32_t n_ie = 2; + liblte_value_2_bits(n_ie, ptr, 16); + + // Temp container for IEs + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr; + + // ProtocolIE - Global_MCE_ID + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_globalmceid(&msg->Global_MCE_ID, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_GLOBALMCE_ID, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + // ProtocolIE - MCEname FIXME + + // ProtocolIE - MCCHrelatedBCCH-ConfigPerMBSFNArea + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_mcchrelatedbcchconfigpermbsfnarea(&msg->MCCHrelatedBCCHConfigPerMBSFNArea, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_MCCHRELATEDBCCH_CONFIGPERMBSFNAREA, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_m2setupresponse( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_M2SETUPRESPONSE_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + LIBLTE_M2AP_CRITICALITY_ENUM crit; + uint32_t ie_id; + uint32_t len; + uint32_t n_ie; + uint32_t i; + + //Set bools + msg->MCEname_present = false; + + // Extension + msg->ext = liblte_bits_2_value(ptr, 1); + liblte_align_up(ptr, 8); + if(msg->ext) { + liblte_log_print("M2SetupResponseIEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + // No. of ProtocolIE-Container + n_ie = liblte_bits_2_value(ptr, 16); + // Unpack ProtocolIE Fields + for(i=0;iGlobal_MCE_ID) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } else if(LIBLTE_M2AP_IE_ID_MCENAME == ie_id) { + if(liblte_m2ap_unpack_mcename(ptr, &msg->MCEname) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + msg->MCEname_present = true; + } else if(LIBLTE_M2AP_IE_ID_MCCHRELATEDBCCH_CONFIGPERMBSFNAREA == ie_id) { + if(liblte_m2ap_unpack_mcchrelatedbcchconfigpermbsfnarea(ptr, &msg->MCCHrelatedBCCHConfigPerMBSFNArea) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * Protocol Message MBMSSessionStartRequest STRUCT + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmssessionstartrequest( + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTREQUEST_STRUCT *msg, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + // Extension + liblte_value_2_bits(msg->ext?1:0, ptr, 1); + liblte_align_up_zero(ptr, 8); + if(msg->ext) { + liblte_log_print("M2SetupResponseIEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // No. of ProtocolIE + uint32_t n_ie = 4; + liblte_value_2_bits(n_ie, ptr, 16); + + // Temp container for IEs + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr; + + // ProtocolIE - MCE MBMS M2AP Id + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_mcembmsm2apid(&msg->MceMbmsM2apId, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_MCE_MBMS_M2AP_ID, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + // ProtocolIE - TMGI + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_tmgi(&msg->Tmgi, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_TMGI, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + // ProtocolIE - MBMS Session Id + /* + if (ie->MBMSSessionId_present) { + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_mbmssessionid(&msg->MbmsSessionId, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_TMGI, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + */ + + // ProtocolIE - MBMS Service Area + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_mbmsservicearea(&msg->MbmsServiceArea, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_MBMS_SERVICE_AREA, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + // ProtocolIE - TNL Information + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_tnlinformation(&msg->TnlInformation, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_TNL_INFORMATION, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmssessionstartrequest( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTREQUEST_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + LIBLTE_M2AP_CRITICALITY_ENUM crit; + uint32_t ie_id; + uint32_t len; + uint32_t n_ie; + uint32_t i; + + //Set bools + msg->MbmsSessionId_present = false; + + // Extension + msg->ext = liblte_bits_2_value(ptr, 1); + liblte_align_up(ptr, 8); + if(msg->ext) { + liblte_log_print("M2SetupResponseIEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + // No. of ProtocolIE-Container + n_ie = liblte_bits_2_value(ptr, 16); + // Unpack ProtocolIE Fields + for(i=0;iMceMbmsM2apId) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } else if(LIBLTE_M2AP_IE_ID_TMGI == ie_id) { + if(liblte_m2ap_unpack_tmgi(ptr, &msg->Tmgi) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } else if(LIBLTE_M2AP_IE_ID_MBMS_SESSION_ID == ie_id) { + msg->MbmsSessionId_present = true; + //if(liblte_m2ap_unpack_mbmssessionid(ptr, &msg->MbmsSessionId) != LIBLTE_SUCCESS) { + // return LIBLTE_ERROR_DECODE_FAIL; + //} + liblte_align_up(ptr, 8); + } else if(LIBLTE_M2AP_IE_ID_MBMS_SERVICE_AREA == ie_id) { + if(liblte_m2ap_unpack_mbmsservicearea(ptr, &msg->MbmsServiceArea) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } else if(LIBLTE_M2AP_IE_ID_TNL_INFORMATION == ie_id) { + if(liblte_m2ap_unpack_tnlinformation(ptr, &msg->TnlInformation) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * Protocol Message MBMSSessionStartResponse STRUCT + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmssessionstartresponse( + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTRESPONSE_STRUCT *msg, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + // Extension + liblte_value_2_bits(msg->ext?1:0, ptr, 1); + liblte_align_up_zero(ptr, 8); + if(msg->ext) { + liblte_log_print("M2SetupResponseIEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // No. of ProtocolIE + uint32_t n_ie = 2; + liblte_value_2_bits(n_ie, ptr, 16); + + // Temp container for IEs + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr; + + // ProtocolIE - MCE MBMS M2AP Id + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_mcembmsm2apid(&msg->MceMbmsM2apId, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_MCE_MBMS_M2AP_ID, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + // ProtocolIE - ENB MBMS M2AP Id + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_enbmbmsm2apid(&msg->EnbMbmsM2apId, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_ENB_MBMS_M2AP_ID, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + // ProtocolIE - Criticality Diagnostics + /* + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_mbmsservicearea(&msg->MbmsServiceArea, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_MBMS_SERVICE_AREA, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + */ + + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmssessionstartresponse( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTRESPONSE_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + LIBLTE_M2AP_CRITICALITY_ENUM crit; + uint32_t ie_id; + uint32_t len; + uint32_t n_ie; + uint32_t i; + + //Set bools + msg->CriticalityDiagnostics_present = false; + + // Extension + msg->ext = liblte_bits_2_value(ptr, 1); + liblte_align_up(ptr, 8); + if(msg->ext) { + liblte_log_print("M2SetupResponseIEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + // No. of ProtocolIE-Container + n_ie = liblte_bits_2_value(ptr, 16); + // Unpack ProtocolIE Fields + for(i=0;iMceMbmsM2apId) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } else if(LIBLTE_M2AP_IE_ID_ENB_MBMS_M2AP_ID == ie_id) { + if(liblte_m2ap_unpack_enbmbmsm2apid(ptr, &msg->EnbMbmsM2apId) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } else if(LIBLTE_M2AP_IE_ID_CRITICALITYDIAGNOSTICS == ie_id) { + /*msg->CriticalityDiagnostics_present = true; + if(liblte_m2ap_unpack_criticalitydiagnostics(ptr, &msg->CriticalityDiagnostics) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8);*/ + } + + } + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * Protocol Message MBMS Scheduling Information STRUCT + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmsschedulinginformation( + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATION_STRUCT *msg, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + + // Extension + liblte_value_2_bits(msg->ext?1:0, ptr, 1); + liblte_align_up_zero(ptr, 8); + if(msg->ext) { + liblte_log_print("MBMSSchedulingInformation IEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // No. of ProtocolIE + uint32_t n_ie = 2; + liblte_value_2_bits(n_ie, ptr, 16); + + // Temp container for IEs + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr; + + // ProtocolIE - MCCH-Update-Time + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_mcchupdatetime(&msg->MCCHUpdateTime, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_MCCH_UPDATE_TIME, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + // ProtocolIE - MBSFN-Area-Configuration-List + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_mbsfnareaconfigurationlist(&msg->MbsfnAreaConfigurationList, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header(tmp_msg.N_bits / 8, + LIBLTE_M2AP_IE_ID_MBSFN_AREA_CONFIGURATION_LIST, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmsschedulinginformation( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATION_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + LIBLTE_M2AP_CRITICALITY_ENUM crit; + uint32_t ie_id; + uint32_t len; + uint32_t n_ie; + uint32_t i; + + // Extension + msg->ext = liblte_bits_2_value(ptr, 1); + liblte_align_up(ptr, 8); + if(msg->ext) { + liblte_log_print("M2SetupRequestIEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + // No. of ProtocolIE-Container + n_ie = liblte_bits_2_value(ptr, 16); + + // Unpack ProtocolIE Fields + for(i=0;iMCCHUpdateTime) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } else if(LIBLTE_M2AP_IE_ID_MBSFN_AREA_CONFIGURATION_LIST == ie_id) { + if(liblte_m2ap_unpack_mbsfnareaconfigurationlist(ptr, &msg->MbsfnAreaConfigurationList) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } + } + + err = LIBLTE_SUCCESS; + } + return err; +} + +/******************************************************************************* + * Protocol Message MBMS Scheduling Information Response STRUCT + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_mbmsschedulinginformationresponse( + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATIONRESPONSE_STRUCT *msg, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + + // Extension + liblte_value_2_bits(msg->ext?1:0, ptr, 1); + liblte_align_up_zero(ptr, 8); + if(msg->ext) { + liblte_log_print("MBMSSchedulingInformation IEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_ENCODE_FAIL; + } + + // No. of ProtocolIE + uint32_t n_ie = 1; + if(msg->CriticalityDiagnostics_present == false){ + --n_ie; + } + liblte_value_2_bits(n_ie, ptr, 16); + + if(msg->CriticalityDiagnostics_present){ + // Temp container for IEs + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr; + + // ProtocolIE - Criticality Diagnostics + tmp_ptr = tmp_msg.msg; + if(liblte_m2ap_pack_criticalitydiagnostics(&msg->CriticalityDiagnostics, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + liblte_align_up_zero(&tmp_ptr, 8); + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + if(liblte_m2ap_pack_protocolie_header((tmp_msg.N_bits) / 8, + LIBLTE_M2AP_IE_ID_CRITICALITYDIAGNOSTICS, + LIBLTE_M2AP_CRITICALITY_REJECT, + ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + } + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_mbmsschedulinginformationresponse( + uint8_t **ptr, + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATIONRESPONSE_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + LIBLTE_M2AP_CRITICALITY_ENUM crit; + uint32_t ie_id; + uint32_t len; + uint32_t n_ie; + uint32_t i; + + // Extension + msg->ext = liblte_bits_2_value(ptr, 1); + liblte_align_up(ptr, 8); + if(msg->ext) { + liblte_log_print("M2SetupRequestIEs error: M2AP ASN extensions not currently supported\n"); + return LIBLTE_ERROR_DECODE_FAIL; + } + + // No. of ProtocolIE-Container + n_ie = liblte_bits_2_value(ptr, 16); + if (n_ie == 0){ + msg->CriticalityDiagnostics_present = false; + } else { + msg->CriticalityDiagnostics_present = true; + } + // Unpack ProtocolIE Fields + for(i=0;iCriticalityDiagnostics) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + liblte_align_up(ptr, 8); + } else { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + + err = LIBLTE_SUCCESS; + } + return err; +} +/******************************************************************************* + * InitiatingMessage CHOICE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_initiatingmessage( + LIBLTE_M2AP_INITIATINGMESSAGE_STRUCT *msg, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr = tmp_msg.msg; + + // Message + if(msg->choice_type == LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_M2SETUPREQUEST) { + if(liblte_m2ap_pack_m2setuprequest(&msg->choice.M2SetupRequest, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } else if(msg->choice_type == LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MBMSSESSIONSTARTREQUEST) { + if(liblte_m2ap_pack_mbmssessionstartrequest(&msg->choice.MbmsSessionStartRequest, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } else if(msg->choice_type == LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MBMSSCHEDULINGINFORMATION) { + if(liblte_m2ap_pack_mbmsschedulinginformation(&msg->choice.MbmsSchedulingInformation, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + + // Procedure code + liblte_value_2_bits(msg->procedureCode, ptr, 8); + + // Criticality + LIBLTE_M2AP_CRITICALITY_ENUM crit = liblte_m2ap_procedure_criticality(msg->procedureCode); + liblte_value_2_bits(crit, ptr, 2); + liblte_align_up_zero(ptr, 8); + + // Length + uint32_t len = (tmp_msg.N_bits + 7) / 8; + if(len < 128) { + liblte_value_2_bits(0, ptr, 1); + liblte_value_2_bits(len, ptr, 7); + } else if(len < 16383) { + liblte_value_2_bits(1, ptr, 1); + liblte_value_2_bits(0, ptr, 1); + liblte_value_2_bits(len, ptr, 14); + } else { + // FIXME: Unlikely to have more than 16K of octets + } + + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_initiatingmessage( + uint8_t **ptr, + LIBLTE_M2AP_INITIATINGMESSAGE_STRUCT *msg) +{ LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + // Procedure code + msg->procedureCode = liblte_bits_2_value(ptr, 8); + + // Criticality + msg->criticality = (LIBLTE_M2AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2); + liblte_align_up(ptr, 8); + + // Length + uint32_t len = 0; + if(0 == liblte_bits_2_value(ptr, 1)) { + len = liblte_bits_2_value(ptr, 7); + } else { + if(0 == liblte_bits_2_value(ptr, 1)) { + len = liblte_bits_2_value(ptr, 14); + } else { + // FIXME: Unlikely to have more than 16K of octets + } + } + + // Message + if(msg->procedureCode == LIBLTE_M2AP_PROC_ID_M2SETUP) { + msg->choice_type = LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_M2SETUPREQUEST; + err = liblte_m2ap_unpack_m2setuprequest(ptr, &msg->choice.M2SetupRequest); + } else if(msg->procedureCode == LIBLTE_M2AP_PROC_ID_SESSIONSTART) { + msg->choice_type = LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MBMSSESSIONSTARTREQUEST; + err = liblte_m2ap_unpack_mbmssessionstartrequest(ptr, &msg->choice.MbmsSessionStartRequest); + } else if(msg->procedureCode == LIBLTE_M2AP_PROC_ID_MBMSSCHEDULINGINFORMATION) { + msg->choice_type = LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MBMSSCHEDULINGINFORMATION; + err = liblte_m2ap_unpack_mbmsschedulinginformation(ptr, &msg->choice.MbmsSchedulingInformation); + } else { + err = LIBLTE_ERROR_DECODE_FAIL; + } + } + return err; +} + +/******************************************************************************* + * SuccessfulOutcome CHOICE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_successfuloutcome( + LIBLTE_M2AP_SUCCESSFULOUTCOME_STRUCT *msg, + uint8_t **ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + LIBLTE_BIT_MSG_STRUCT tmp_msg; + uint8_t *tmp_ptr = tmp_msg.msg; + + // Message + if (msg->choice_type == LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_M2SETUPRESPONSE) { + if (liblte_m2ap_pack_m2setupresponse(&msg->choice.M2SetupResponse, &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } else if (msg->choice_type == LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MBMSSESSIONSTARTRESPONSE) { + if (liblte_m2ap_pack_mbmssessionstartresponse(&msg->choice.MbmsSessionStartResponse, &tmp_ptr) != + LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } else if (msg->choice_type == LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MBMSSCHEDULINGINFORMATIONRESPONSE) { + if (liblte_m2ap_pack_mbmsschedulinginformationresponse(&msg->choice.MbmsSchedulingInformationResponse, + &tmp_ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } else { + return LIBLTE_ERROR_ENCODE_FAIL; + } + tmp_msg.N_bits = tmp_ptr - tmp_msg.msg; + + // Procedure code + liblte_value_2_bits(msg->procedureCode, ptr, 8); + + // Criticality + LIBLTE_M2AP_CRITICALITY_ENUM crit = liblte_m2ap_procedure_criticality(msg->procedureCode); + liblte_value_2_bits(crit, ptr, 2); + liblte_align_up_zero(ptr, 8); + + // Length + uint32_t len = (tmp_msg.N_bits + 7) / 8; + if(len < 128) { + liblte_value_2_bits(0, ptr, 1); + liblte_value_2_bits(len, ptr, 7); + } else if(len < 16383) { + liblte_value_2_bits(1, ptr, 1); + liblte_value_2_bits(0, ptr, 1); + liblte_value_2_bits(len, ptr, 14); + } else { + // FIXME: Unlikely to have more than 16K of octets + } + + memcpy(*ptr, tmp_msg.msg, tmp_msg.N_bits); + *ptr += tmp_msg.N_bits; + + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_successfuloutcome( + uint8_t **ptr, + LIBLTE_M2AP_SUCCESSFULOUTCOME_STRUCT *msg) +{ LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(msg != NULL && + ptr != NULL) + { + // Procedure code + msg->procedureCode = liblte_bits_2_value(ptr, 8); + + // Criticality + msg->criticality = (LIBLTE_M2AP_CRITICALITY_ENUM)liblte_bits_2_value(ptr, 2); + liblte_align_up(ptr, 8); + + // Length + uint32_t len = 0; + if(0 == liblte_bits_2_value(ptr, 1)) { + len = liblte_bits_2_value(ptr, 7); + } else { + if(0 == liblte_bits_2_value(ptr, 1)) { + len = liblte_bits_2_value(ptr, 14); + } else { + // FIXME: Unlikely to have more than 16K of octets + } + } + + // Message + if(msg->procedureCode == LIBLTE_M2AP_PROC_ID_M2SETUP) { + msg->choice_type = LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_M2SETUPRESPONSE; + if(liblte_m2ap_unpack_m2setupresponse(ptr, &msg->choice.M2SetupResponse) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = LIBLTE_SUCCESS; + } else if (msg->procedureCode == LIBLTE_M2AP_PROC_ID_SESSIONSTART) { + msg->choice_type = LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MBMSSESSIONSTARTRESPONSE; + if(liblte_m2ap_unpack_mbmssessionstartresponse(ptr, &msg->choice.MbmsSessionStartResponse) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = LIBLTE_SUCCESS; + } else if (msg->procedureCode == LIBLTE_M2AP_PROC_ID_MBMSSCHEDULINGINFORMATION) { + msg->choice_type = LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MBMSSCHEDULINGINFORMATIONRESPONSE; + if(liblte_m2ap_unpack_mbmsschedulinginformationresponse(ptr, &msg->choice.MbmsSchedulingInformationResponse) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + err = LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR_DECODE_FAIL; + } + } + return err; +} + +/******************************************************************************* + * M2AP_PDU CHOICE + *******************************************************************************/ +LIBLTE_ERROR_ENUM liblte_m2ap_pack_m2ap_pdu( + LIBLTE_M2AP_M2AP_PDU_STRUCT *m2ap_pdu, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_BIT_MSG_STRUCT bit_msg; + + if(m2ap_pdu != NULL && + msg != NULL) + { + uint8_t *p = bit_msg.msg; + uint8_t **ptr = &p; + + // Extension + liblte_value_2_bits(m2ap_pdu->ext?1:0, ptr, 1); + + // Message choice + liblte_value_2_bits(m2ap_pdu->choice_type, ptr, 2); + liblte_align_up_zero(ptr, 8); + + // Message + if(LIBLTE_M2AP_M2AP_PDU_CHOICE_INITIATINGMESSAGE == m2ap_pdu->choice_type) { + if(liblte_m2ap_pack_initiatingmessage(&m2ap_pdu->choice.initiatingMessage, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } else if(LIBLTE_M2AP_M2AP_PDU_CHOICE_SUCCESSFULOUTCOME == m2ap_pdu->choice_type) { + if(liblte_m2ap_pack_successfuloutcome(&m2ap_pdu->choice.successfulOutcome, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + } /*else if(LIBLTE_M2AP_M2AP_PDU_CHOICE_UNSUCCESSFULOUTCOME == m2ap_pdu->choice_type) { + if(liblte_m2ap_pack_unsuccessfuloutcome(&m2ap_pdu->choice.unsuccessfulOutcome, ptr) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_ENCODE_FAIL; + } + }*/ + + liblte_align_up_zero(ptr, 8); + bit_msg.N_bits = (*ptr - bit_msg.msg); + + liblte_pack(&bit_msg, msg); + err = LIBLTE_SUCCESS; + } + return err; +} + +LIBLTE_ERROR_ENUM liblte_m2ap_unpack_m2ap_pdu( + LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_M2AP_M2AP_PDU_STRUCT *m2ap_pdu) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + LIBLTE_BIT_MSG_STRUCT bit_msg; + + if(m2ap_pdu != NULL && + msg != NULL) + { + liblte_unpack(msg, &bit_msg); + + uint8_t *p = bit_msg.msg; + uint8_t **ptr = &p; + + // Extension + m2ap_pdu->ext = liblte_bits_2_value(ptr, 1); + + // Message choice + m2ap_pdu->choice_type = (LIBLTE_M2AP_M2AP_PDU_CHOICE_ENUM)liblte_bits_2_value(ptr, 2); + liblte_align_up(ptr, 8); + + // Message + if(LIBLTE_M2AP_M2AP_PDU_CHOICE_INITIATINGMESSAGE == m2ap_pdu->choice_type) { + if(liblte_m2ap_unpack_initiatingmessage(ptr, &m2ap_pdu->choice.initiatingMessage) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + }else if(LIBLTE_M2AP_M2AP_PDU_CHOICE_SUCCESSFULOUTCOME == m2ap_pdu->choice_type) { + if(liblte_m2ap_unpack_successfuloutcome(ptr, &m2ap_pdu->choice.successfulOutcome) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + } /*else if(LIBLTE_M2AP_M2AP_PDU_CHOICE_UNSUCCESSFULOUTCOME == m2ap_pdu->choice_type) { + if(liblte_m2ap_unpack_unsuccessfuloutcome(ptr, &m2ap_pdu->choice.unsuccessfulOutcome) != LIBLTE_SUCCESS) { + return LIBLTE_ERROR_DECODE_FAIL; + } + }*/ + err = LIBLTE_SUCCESS; + } + return err; +} diff --git a/lib/test/asn1/CMakeLists.txt b/lib/test/asn1/CMakeLists.txt index 0f59d0417..c573cd291 100644 --- a/lib/test/asn1/CMakeLists.txt +++ b/lib/test/asn1/CMakeLists.txt @@ -25,3 +25,7 @@ add_test(srslte_asn1_rrc_mcch_test srslte_asn1_rrc_mcch_test) add_executable(srslte_asn1_rrc_meas_test srslte_asn1_rrc_meas_test.cc) target_link_libraries(srslte_asn1_rrc_meas_test srslte_common srslte_phy srslte_asn1) add_test(srslte_asn1_rrc_meas_test srslte_asn1_rrc_meas_test) + +add_executable(srslte_asn1_m2ap_test srslte_asn1_m2ap_test.cc) +target_link_libraries(srslte_asn1_m2ap_test srslte_common srslte_phy srslte_asn1) +add_test(srslte_asn1_m2ap_test srslte_asn1_m2ap_test) diff --git a/lib/test/asn1/srslte_asn1_m2ap_test.cc b/lib/test/asn1/srslte_asn1_m2ap_test.cc new file mode 100644 index 000000000..35ceb2ea2 --- /dev/null +++ b/lib/test/asn1/srslte_asn1_m2ap_test.cc @@ -0,0 +1,495 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include +#include +#include +#include "srslte/asn1/liblte_m2ap.h" +#include "srslte/common/log_filter.h" + +void m2_setup_request_test() +{ + srslte::log_filter log1("M2AP"); + log1.set_level(srslte::LOG_LEVEL_DEBUG); + log1.set_hex_limit(128); + + LIBLTE_BYTE_MSG_STRUCT tst_msg; + LIBLTE_BYTE_MSG_STRUCT out_msg; + LIBLTE_M2AP_M2AP_PDU_STRUCT m2ap_pdu; + + uint32_t m2ap_message_len = 59; + uint8_t m2ap_message[] = {0x00, 0x05, 0x00, 0x37, 0x00, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0xf1, 0x10, + 0x00, 0x1a, 0x2d, 0x00, 0x00, 0x0e, 0x40, 0x0a, 0x03, 0x80, 0x65, 0x6e, 0x62, 0x31, 0x61, + 0x32, 0x64, 0x30, 0x00, 0x0f, 0x00, 0x16, 0x00, 0x00, 0x10, 0x00, 0x11, 0x00, 0x00, 0xf1, + 0x10, 0x1a, 0x2d, 0x00, 0x10, 0x27, 0x10, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x02}; + + /*M2AP Setup Request Unpack Test*/ + tst_msg.N_bytes = m2ap_message_len; + memcpy(tst_msg.msg, m2ap_message, m2ap_message_len); + log1.info_hex(tst_msg.msg, tst_msg.N_bytes, "M2 Setup Request original message\n"); + + liblte_m2ap_unpack_m2ap_pdu(&tst_msg, &m2ap_pdu); + assert(m2ap_pdu.choice_type == LIBLTE_M2AP_M2AP_PDU_CHOICE_INITIATINGMESSAGE); + + LIBLTE_M2AP_INITIATINGMESSAGE_STRUCT *in_msg = &m2ap_pdu.choice.initiatingMessage; + assert(in_msg->choice_type == LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_M2SETUPREQUEST); + + LIBLTE_M2AP_MESSAGE_M2SETUPREQUEST_STRUCT *m2_setup = &in_msg->choice.M2SetupRequest; + assert(m2_setup->ext == false); + + /*Global eNB-Id*/ + // PLMN Identity (MCC = 001 , MNC = 01) + uint8_t *plmn_id = m2_setup->Global_ENB_ID.pLMNidentity.buffer; + assert((plmn_id[0] & 0x0F) == 0 && (plmn_id[0] & 0xF0) >> 4 == 0 && (plmn_id[1] & 0x0F) == 1); // MCC + assert((plmn_id[1] & 0xF0) >> 4 == 0xF && (plmn_id[2] & 0x0F) == 0 && (plmn_id[2] & 0xF0) >> 4 == 1); // MNC + + // eNB Identity + uint8_t enb_id_bits[32]; + uint32_t enb_id; + bzero(enb_id_bits, sizeof(enb_id_bits)); + memcpy(&enb_id_bits[32 - LIBLTE_M2AP_ENBID_BIT_STRING_LEN], m2_setup->Global_ENB_ID.eNB_ID.buffer, + LIBLTE_M2AP_ENBID_BIT_STRING_LEN); + liblte_pack(enb_id_bits, 32, (uint8_t *)&enb_id); + enb_id = ntohl(enb_id); + assert(enb_id == 0x1a2d0); + + // eNB Name + assert(m2_setup->eNBname_present == true); + assert(m2_setup->eNBname.n_octets == 8); + assert(strncmp((const char *)m2_setup->eNBname.buffer, "enb1a2d0", m2_setup->eNBname.n_octets) == 0); + + // eNB MBMS Configuration Data List + assert(m2_setup->configurationDataList.len == 1); + + // eNB MBMS Configuration Data Item + LIBLTE_M2AP_ENB_MBMS_CONFIGURATION_DATA_ITEM_STRUCT *conf_item = &m2_setup->configurationDataList.buffer[0]; + + // eCGI + plmn_id = conf_item->eCGI.pLMN_Identity.buffer; + assert((plmn_id[0] & 0x0F) == 0 && (plmn_id[0] & 0xF0) >> 4 == 0 && (plmn_id[1] & 0x0F) == 1); // MCC + assert((plmn_id[1] & 0xF0) >> 4 == 0xF && (plmn_id[2] & 0x0F) == 0 && (plmn_id[2] & 0xF0) >> 4 == 1); // MNC + + // E-UTRAN Cell Identifier + assert(conf_item->eCGI.EUTRANCellIdentifier.eUTRANCellIdentifier == 27447297); + + // MBSFN Synchronization Area + assert(conf_item->mbsfnSynchronisationArea.mbsfn_synchronisation_area_id == 10000); + + // MBMS Service Area + assert(conf_item->mbmsServiceAreaList.len == 2); + assert(conf_item->mbmsServiceAreaList.buffer[0].n_octets == 2); // Service Area 1 + assert((conf_item->mbmsServiceAreaList.buffer[0].buffer[0] == 0) && + (conf_item->mbmsServiceAreaList.buffer[0].buffer[1] == 1)); // Service Area 1 + assert(conf_item->mbmsServiceAreaList.buffer[1].n_octets == 2); // Service Area 2 + assert((conf_item->mbmsServiceAreaList.buffer[1].buffer[0] == 0) && + (conf_item->mbmsServiceAreaList.buffer[1].buffer[1] == 2)); // Service Area 2 + + /*M2AP Setup Request Pack Test*/ + liblte_m2ap_pack_m2ap_pdu(&m2ap_pdu, &out_msg); + log1.info_hex(out_msg.msg, out_msg.N_bytes, "M2 Setup Request Packed message\n"); + + for (uint32_t i = 0; i < m2ap_message_len; i++) { + assert(tst_msg.msg[i] == out_msg.msg[i]); + } + printf("Test M2SetupRequest successfull\n"); +} + +void m2_setup_response_test() +{ + srslte::log_filter log1("M2AP"); + log1.set_level(srslte::LOG_LEVEL_DEBUG); + log1.set_hex_limit(128); + + LIBLTE_BYTE_MSG_STRUCT tst_msg; + LIBLTE_BYTE_MSG_STRUCT out_msg; + LIBLTE_M2AP_M2AP_PDU_STRUCT m2ap_pdu; + + uint32_t m2ap_message_len = 40; + uint8_t m2ap_message[] = {0x20, 0x05, 0x00, 0x24, 0x00, 0x00, 0x02, 0x00, 0x11, 0x00, 0x06, 0x00, 0x00, 0xf1, + 0x10, 0x00, 0x50, 0x00, 0x13, 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x0e, 0x40, 0x01, + 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x10, 0x1a, 0x2d, 0x00, 0x14}; + + /*M2AP Setup Response Unpack Test*/ + tst_msg.N_bytes = m2ap_message_len; + memcpy(tst_msg.msg, m2ap_message, m2ap_message_len); + + LIBLTE_ERROR_ENUM err = liblte_m2ap_unpack_m2ap_pdu(&tst_msg, &m2ap_pdu); + assert(err == LIBLTE_SUCCESS); + assert(m2ap_pdu.choice_type == LIBLTE_M2AP_M2AP_PDU_CHOICE_SUCCESSFULOUTCOME); + + LIBLTE_M2AP_SUCCESSFULOUTCOME_STRUCT *succ_out = &m2ap_pdu.choice.successfulOutcome; + assert(succ_out->choice_type == LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_M2SETUPRESPONSE); + + LIBLTE_M2AP_MESSAGE_M2SETUPRESPONSE_STRUCT *m2_setup = &succ_out->choice.M2SetupResponse; + assert(m2_setup->ext == false); + + /*Global MCE-Id*/ + // PLMN Identity (MCC = 001 , MNC = 01) + uint8_t *plmn_id = m2_setup->Global_MCE_ID.pLMN_Identity.buffer; + assert((plmn_id[0] & 0x0F) == 0 && (plmn_id[0] & 0xF0) >> 4 == 0 && (plmn_id[1] & 0x0F) == 1); // MCC + assert((plmn_id[1] & 0xF0) >> 4 == 0xF && (plmn_id[2] & 0x0F) == 0 && (plmn_id[2] & 0xF0) >> 4 == 1); // MNC + + // MCE Identity + uint16_t mce_id; + memcpy(&mce_id, m2_setup->Global_MCE_ID.mCE_ID.buffer, LIBLTE_M2AP_MCEID_OCTET_STRING_LEN); + mce_id = ntohs(mce_id); + assert(mce_id == 0x0050); + + /*MCE Name*/ + assert(m2_setup->MCEname_present == false); // FIXME Test with MCE name + + /*MCCHrelatedBCCH-ConfigPerMBSFNArea*/ + // Length + assert(m2_setup->MCCHrelatedBCCHConfigPerMBSFNArea.len == 1); + + // MCCH Related BCCH Config Per MBSFN Area Configuration Item + LIBLTE_M2AP_MCCH_RELATED_BCCH_CONFIG_PER_MBSFN_AREA_ITEM_STRUCT *conf_item = + &m2_setup->MCCHrelatedBCCHConfigPerMBSFNArea.buffer[0]; + + // MBSFN Area + assert(conf_item->mbsfnArea.mbsfn_area_id == 1); + + // PDCCH Length + assert(conf_item->pdcchLength.ext == false); + assert(conf_item->pdcchLength.pdcchLength == LIBLTE_M2AP_PDCCH_LENGTH_S2); + + // Repetition Period + assert(conf_item->repetitionPeriod.repetitionPeriod == LIBLTE_M2AP_REPETITION_PERIOD_RF64); + + // Offset + assert(conf_item->offset.offset == 0); + + // Modification Period + assert(conf_item->modificationPeriod.modificationPeriod == LIBLTE_M2AP_MODIFICATION_PERIOD_RF512); + + // Subframe Allocation Info + assert(conf_item->subframeAllocationInfo.buffer[0] == 1); + assert(conf_item->subframeAllocationInfo.buffer[1] == 0); + assert(conf_item->subframeAllocationInfo.buffer[2] == 0); + assert(conf_item->subframeAllocationInfo.buffer[3] == 0); + assert(conf_item->subframeAllocationInfo.buffer[4] == 0); + assert(conf_item->subframeAllocationInfo.buffer[5] == 0); + + // Modulation and Coding Scheme + assert(conf_item->modulationAndCodingScheme.mcs == LIBLTE_M2AP_MODULATION_AND_CODING_SCHEME_N2); + + /*Cell Information List*/ + assert(conf_item->cellInformationList_present); + assert(conf_item->cellInformationList.len == 1); + + /*Cell Information*/ + LIBLTE_M2AP_CELL_INFORMATION_STRUCT *cell_info = &conf_item->cellInformationList.buffer[0]; + + // eCGI + plmn_id = cell_info->eCGI.pLMN_Identity.buffer; + assert((plmn_id[0] & 0x0F) == 0 && (plmn_id[0] & 0xF0) >> 4 == 0 && (plmn_id[1] & 0x0F) == 1); // MCC + assert((plmn_id[1] & 0xF0) >> 4 == 0xF && (plmn_id[2] & 0x0F) == 0 && (plmn_id[2] & 0xF0) >> 4 == 1); // MNC + // E-UTRAN Cell Identifier + assert(cell_info->eCGI.EUTRANCellIdentifier.eUTRANCellIdentifier == 27447297); + // Cell Reservation + assert(cell_info->cellReservationInfo.e == LIBLTE_M2AP_CELL_RESERVATION_INFO_NON_RESERVED_CELL); + + /*M2AP Setup Request Pack Test*/ + err = liblte_m2ap_pack_m2ap_pdu(&m2ap_pdu, &out_msg); + log1.info_hex(tst_msg.msg, tst_msg.N_bytes, "M2 Setup Request original message\n"); + log1.info_hex(out_msg.msg, out_msg.N_bytes, "M2 Setup Request Packed message\n"); + + assert(err == LIBLTE_SUCCESS); + for (uint32_t i = 0; i < m2ap_message_len; i++) { + assert(tst_msg.msg[i] == out_msg.msg[i]); + } + printf("Test M2SetupResponse successfull\n"); +} + +void mbms_session_start_request_test() +{ + srslte::log_filter log1("M2AP"); + log1.set_level(srslte::LOG_LEVEL_DEBUG); + log1.set_hex_limit(128); + + LIBLTE_BYTE_MSG_STRUCT tst_msg; + LIBLTE_BYTE_MSG_STRUCT out_msg; + LIBLTE_M2AP_M2AP_PDU_STRUCT m2ap_pdu; + + uint32_t m2ap_message_len = 49; + uint8_t m2ap_message[] = {0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x02, + 0x01, 0x00, 0x7f, 0x00, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x01}; + + tst_msg.N_bytes = m2ap_message_len; + memcpy(tst_msg.msg, m2ap_message, m2ap_message_len); + + /*M2AP MBMS Session Start Request Unpack Test*/ + LIBLTE_ERROR_ENUM err = liblte_m2ap_unpack_m2ap_pdu(&tst_msg, &m2ap_pdu); + assert(err == LIBLTE_SUCCESS); + assert(m2ap_pdu.choice_type == LIBLTE_M2AP_M2AP_PDU_CHOICE_INITIATINGMESSAGE); + + LIBLTE_M2AP_INITIATINGMESSAGE_STRUCT *in_msg = &m2ap_pdu.choice.initiatingMessage; + assert(in_msg->choice_type == LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MBMSSESSIONSTARTREQUEST); + + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTREQUEST_STRUCT *mbms_sess = &in_msg->choice.MbmsSessionStartRequest; + + /*ProtocolIE MCE-MBMS-M2AP-ID*/ + assert(mbms_sess->MceMbmsM2apId.mce_mbms_m2ap_id == 0); + + /*ProtocolIE TMGI*/ + uint8_t *plmn_id = mbms_sess->Tmgi.pLMN_Identity.buffer; + assert((plmn_id[0] & 0x0F) == 0 && (plmn_id[0] & 0xF0) >> 4 == 0 && (plmn_id[1] & 0x0F) == 1); // MCC + assert((plmn_id[1] & 0xF0) >> 4 == 0xF && (plmn_id[2] & 0x0F) == 0 && (plmn_id[2] & 0xF0) >> 4 == 1); // MNC + assert(mbms_sess->Tmgi.serviceID.buffer[0] == 0); + assert(mbms_sess->Tmgi.serviceID.buffer[1] == 0); + assert(mbms_sess->Tmgi.serviceID.buffer[2] == 1); + + /*Service Area*/ + assert(mbms_sess->MbmsServiceArea.n_octets == 2); + assert(mbms_sess->MbmsServiceArea.buffer[0] == 0); + assert(mbms_sess->MbmsServiceArea.buffer[1] == 1); + + /* TNL Information */ + // IPMC Address + assert(mbms_sess->TnlInformation.iPMCAddress.len == 4); + int32_t addr; + memcpy(&addr, mbms_sess->TnlInformation.iPMCAddress.buffer, 4); + assert(ntohl(addr) == 0x7F000201); + // Source Address + assert(mbms_sess->TnlInformation.iPSourceAddress.len == 4); + memcpy(&addr, mbms_sess->TnlInformation.iPSourceAddress.buffer, 4); + assert(ntohl(addr) == 0x7F0001C8); + + // TEID + int32_t teid; + memcpy(&teid, mbms_sess->TnlInformation.gtpTeid.buffer, 4); + assert(ntohl(teid) == 0x00000001); + + /*M2AP Setup Request Pack Test*/ + err = liblte_m2ap_pack_m2ap_pdu(&m2ap_pdu, &out_msg); + log1.info_hex(tst_msg.msg, tst_msg.N_bytes, "MBMS Session Start Request original message\n"); + log1.info_hex(out_msg.msg, out_msg.N_bytes, "MBMS Session Start Request Packed message\n"); + + assert(err == LIBLTE_SUCCESS); + for (uint32_t i = 0; i < m2ap_message_len; i++) { + assert(tst_msg.msg[i] == out_msg.msg[i]); + } + printf("Test MBMSSessionStartRequest successfull\n"); +} + +void mbms_session_start_response_test() +{ + srslte::log_filter log1("M2AP"); + log1.set_level(srslte::LOG_LEVEL_DEBUG); + log1.set_hex_limit(128); + + LIBLTE_BYTE_MSG_STRUCT tst_msg; + LIBLTE_BYTE_MSG_STRUCT out_msg; + LIBLTE_M2AP_M2AP_PDU_STRUCT m2ap_pdu; + + uint32_t m2ap_message_len = 19; + uint8_t m2ap_message[] = {0x20, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00}; + + tst_msg.N_bytes = m2ap_message_len; + memcpy(tst_msg.msg, m2ap_message, m2ap_message_len); + log1.info_hex(tst_msg.msg, tst_msg.N_bytes, "MBMS Session Start Response original message\n"); + + /*M2AP MBMS Session Start Request Unpack Test*/ + LIBLTE_ERROR_ENUM err = liblte_m2ap_unpack_m2ap_pdu(&tst_msg, &m2ap_pdu); + assert(err == LIBLTE_SUCCESS); + assert(m2ap_pdu.choice_type == LIBLTE_M2AP_M2AP_PDU_CHOICE_SUCCESSFULOUTCOME); + + LIBLTE_M2AP_SUCCESSFULOUTCOME_STRUCT *succ_msg = &m2ap_pdu.choice.successfulOutcome; + assert(succ_msg->choice_type == LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MBMSSESSIONSTARTRESPONSE); + + LIBLTE_M2AP_MESSAGE_MBMSSESSIONSTARTRESPONSE_STRUCT *mbms_sess = &succ_msg->choice.MbmsSessionStartResponse; + + /*ProtocolIE MCE-MBMS-M2AP-ID*/ + assert(mbms_sess->MceMbmsM2apId.mce_mbms_m2ap_id == 0); + + /*ProtocolIE ENB-MBMS-M2AP-ID*/ + assert(mbms_sess->EnbMbmsM2apId.enb_mbms_m2ap_id == 0); + + /*M2AP Setup Request Pack Test*/ + err = liblte_m2ap_pack_m2ap_pdu(&m2ap_pdu, &out_msg); + log1.info_hex(tst_msg.msg, tst_msg.N_bytes, "MBMS Session Start Response original message\n"); + log1.info_hex(out_msg.msg, out_msg.N_bytes, "MBMS Session Start Response Packed message\n"); + + assert(err == LIBLTE_SUCCESS); + for (uint32_t i = 0; i < m2ap_message_len; i++) { + assert(tst_msg.msg[i] == out_msg.msg[i]); + } + printf("Test MBMSSessionStartRequest successfull\n"); +} + +void mbms_scheduling_information_test() +{ + srslte::log_filter log1("M2AP"); + log1.set_level(srslte::LOG_LEVEL_DEBUG); + log1.set_hex_limit(128); + + LIBLTE_BYTE_MSG_STRUCT tst_msg; + LIBLTE_BYTE_MSG_STRUCT out_msg; + LIBLTE_M2AP_M2AP_PDU_STRUCT m2ap_pdu; + + uint32_t m2ap_message_len = 62; + uint8_t m2ap_message[] = {0x00, 0x02, 0x00, 0x3a, 0x00, 0x00, 0x02, 0x00, 0x19, 0x00, 0x01, 0x00, 0x00, + 0x0a, 0x00, 0x2e, 0x00, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x12, 0x10, 0x00, 0x0c, + 0x00, 0x0d, 0x00, 0x00, 0x3f, 0x13, 0x00, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x00, + 0x01, 0x08, 0x00, 0x16, 0x00, 0x07, 0x00, 0x00, 0x17, 0x00, 0x02, 0x00, 0x40, + 0x00, 0x18, 0x00, 0x01, 0x80, 0x00, 0x1d, 0x00, 0x01, 0x01}; + + tst_msg.N_bytes = m2ap_message_len; + memcpy(tst_msg.msg, m2ap_message, m2ap_message_len); + log1.info_hex(tst_msg.msg, tst_msg.N_bytes, "MBMS Scheduling Information message\n"); + + /*M2AP MBMS Scheduling Information Unpack Test*/ + LIBLTE_ERROR_ENUM err = liblte_m2ap_unpack_m2ap_pdu(&tst_msg, &m2ap_pdu); + assert(err == LIBLTE_SUCCESS); + assert(m2ap_pdu.choice_type == LIBLTE_M2AP_M2AP_PDU_CHOICE_INITIATINGMESSAGE); + + LIBLTE_M2AP_INITIATINGMESSAGE_STRUCT *in_msg = &m2ap_pdu.choice.initiatingMessage; + assert(in_msg->choice_type == LIBLTE_M2AP_INITIATINGMESSAGE_CHOICE_MBMSSCHEDULINGINFORMATION); + + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATION_STRUCT *sched_info = &in_msg->choice.MbmsSchedulingInformation; + + /*ProtocolIE MCCH-Update-Time*/ + assert(sched_info->MCCHUpdateTime.mcchUpdateTime == 0); + + /*ProtocolIE MBSFN-Area-Configuration-Item*/ + assert(sched_info->MbsfnAreaConfigurationList.len == 1); + LIBLTE_M2AP_MBSFN_AREA_CONFIGURATION_ITEM_STRUCT *area_conf = &sched_info->MbsfnAreaConfigurationList.buffer[0]; + + //PMCH Configuration List/Item + assert(area_conf->PMCHConfigurationList.len == 1); + LIBLTE_M2AP_PMCH_CONFIGURATION_ITEM_STRUCT *pmch_conf_item = &area_conf->PMCHConfigurationList.buffer[0]; + + //PMCH Configuration + LIBLTE_M2AP_PMCH_CONFIGURATION_STRUCT *pmch_conf = &area_conf->PMCHConfigurationList.buffer[0].PMCHConfiguration; + + //Allocated Subframes End + assert(pmch_conf->allocatedSubframesEnd.allocated_subframes_end == 63); + + //Data MCS + assert(pmch_conf->dataMCS.dataMCS == 2); + + //MCH Scheduling Period + assert(pmch_conf->mchSchedulingPeriod.e == LIBLTE_M2AP_MCH_SCHEDULING_PERIOD_RF64); + + //MBMS Session List Per PMCH Item + assert(pmch_conf_item->MBMSSessionListPerPMCHItem.len == 1); + LIBLTE_M2AP_MBMS_SESSION_LIST_PER_PMCH_ITEM_STRUCT *mbms_sess = &pmch_conf_item->MBMSSessionListPerPMCHItem; + + //TMGI + uint8_t *plmn_id = mbms_sess->buffer[0].Tmgi.pLMN_Identity.buffer; + assert((plmn_id[0] & 0x0F) == 0 && (plmn_id[0] & 0xF0) >> 4 == 0 && (plmn_id[1] & 0x0F) == 1); // MCC + assert((plmn_id[1] & 0xF0) >> 4 == 0xF && (plmn_id[2] & 0x0F) == 0 && (plmn_id[2] & 0xF0) >> 4 == 1); // MNC + assert(mbms_sess->buffer[0].Tmgi.serviceID.buffer[0] == 0); + assert(mbms_sess->buffer[0].Tmgi.serviceID.buffer[1] == 0); + assert(mbms_sess->buffer[0].Tmgi.serviceID.buffer[2] == 1); + + //LCID + assert(mbms_sess->buffer[0].Lcid.lcid == 1); + + /*MBSFN Subframe Configuration List*/ + assert(area_conf->MBSFNSubframeConfigurationList.len == 1); + LIBLTE_M2AP_MBSFN_SUBFRAME_CONFIGURATION_STRUCT *sub_conf = &area_conf->MBSFNSubframeConfigurationList.buffer[0]; + + /*MBSFN Subframe configuration*/ + //Radioframe Allocation period + assert(sub_conf->radioFrameAllocationPeriod.e == LIBLTE_M2AP_RADIOFRAME_ALLOCATION_PERIOD_N1); + //Radioframe Allocation Offset + assert(sub_conf->radioFrameAllocationOffset.radioframeAllocationOffset == 0); + //Subframe Allocation + assert(sub_conf->subframeAllocation.choice_type == LIBLTE_M2AP_SUBFRAME_ALLOCATION_ONE_FRAME); + assert(sub_conf->subframeAllocation.choice.oneFrame[0] == 1); + assert(sub_conf->subframeAllocation.choice.oneFrame[1] == 0); + assert(sub_conf->subframeAllocation.choice.oneFrame[2] == 0); + assert(sub_conf->subframeAllocation.choice.oneFrame[3] == 0); + assert(sub_conf->subframeAllocation.choice.oneFrame[4] == 0); + assert(sub_conf->subframeAllocation.choice.oneFrame[5] == 0); + + /* Common Subframe Allocation Period*/ + assert(area_conf->CommonSubframeAllocationPeriod.e == LIBLTE_M2AP_COMMON_SUBFRAME_ALLOCATION_PERIOD_RF64); + + /*MBSFN Area Id*/ + assert(area_conf->MBSFNAreaId.mbsfn_area_id == 1); + + /*M2AP Setup Request Pack Test*/ + err = liblte_m2ap_pack_m2ap_pdu(&m2ap_pdu, &out_msg); + log1.info_hex(out_msg.msg, out_msg.N_bytes, "MBMS Scheduling Information message\n"); + + assert(err == LIBLTE_SUCCESS); + for (uint32_t i = 0; i < m2ap_message_len; i++) { + assert(tst_msg.msg[i] == out_msg.msg[i]); + } + printf("Test MBMS Scheduling Information successfull\n"); +} + +void mbms_scheduling_information_response_test() +{ + srslte::log_filter log1("M2AP"); + log1.set_level(srslte::LOG_LEVEL_DEBUG); + log1.set_hex_limit(128); + + LIBLTE_BYTE_MSG_STRUCT tst_msg; + LIBLTE_BYTE_MSG_STRUCT out_msg; + LIBLTE_M2AP_M2AP_PDU_STRUCT m2ap_pdu; + + uint32_t m2ap_message_len = 7; + uint8_t m2ap_message[] = {0x20, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00}; + tst_msg.N_bytes = m2ap_message_len; + memcpy(tst_msg.msg, m2ap_message, m2ap_message_len); + log1.info_hex(tst_msg.msg, tst_msg.N_bytes, "MBMS Scheduling Information Response message\n"); + + /*M2AP MBMS Scheduling Information Unpack Test*/ + LIBLTE_ERROR_ENUM err = liblte_m2ap_unpack_m2ap_pdu(&tst_msg, &m2ap_pdu); + assert(err == LIBLTE_SUCCESS); + assert(m2ap_pdu.choice_type == LIBLTE_M2AP_M2AP_PDU_CHOICE_SUCCESSFULOUTCOME); + + LIBLTE_M2AP_SUCCESSFULOUTCOME_STRUCT *succ_out = &m2ap_pdu.choice.successfulOutcome; + assert(succ_out->choice_type == LIBLTE_M2AP_SUCCESSFULOUTCOME_CHOICE_MBMSSCHEDULINGINFORMATIONRESPONSE); + + LIBLTE_M2AP_MESSAGE_MBMSSCHEDULINGINFORMATIONRESPONSE_STRUCT *sched_info = &succ_out->choice.MbmsSchedulingInformationResponse; + + + /*M2AP Setup Request Pack Test*/ + err = liblte_m2ap_pack_m2ap_pdu(&m2ap_pdu, &out_msg); + log1.info_hex(out_msg.msg, out_msg.N_bytes, "MBMS Scheduling Information message\n"); + + assert(err == LIBLTE_SUCCESS); + for (uint32_t i = 0; i < m2ap_message_len; i++) { + assert(tst_msg.msg[i] == out_msg.msg[i]); + } + printf("Test MBMS Scheduling Information successfull\n"); +} +int main(int argc, char **argv) +{ + m2_setup_request_test(); + m2_setup_response_test(); + mbms_session_start_request_test(); + mbms_session_start_response_test(); + mbms_scheduling_information_test(); + mbms_scheduling_information_response_test(); +}