laforge has submitted this change. (
https://gerrit.osmocom.org/c/libosmocore/+/32931 )
Change subject: ASCI: Add IE transcoding according to 3GPP TS 48.008
......................................................................
ASCI: Add IE transcoding according to 3GPP TS 48.008
Change-Id: Ic1fc714bb04228a7f32e9925811e21c8efc610bd
---
M include/osmocom/gsm/gsm0808_utils.h
M src/gsm/gsm0808_utils.c
M src/gsm/libosmogsm.map
3 files changed, 568 insertions(+), 0 deletions(-)
Approvals:
laforge: Looks good to me, but someone else must approve
pespin: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h
index 85244a5..dbe2abf 100644
--- a/include/osmocom/gsm/gsm0808_utils.h
+++ b/include/osmocom/gsm/gsm0808_utils.h
@@ -31,6 +31,8 @@
#include <osmocom/gsm/gsm23003.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/gsm48.h>
+#include <osmocom/core/endian.h>
/*! (225-1)/2 is the maximum number of elements in a cell identifier list. */
#define GSM0808_CELL_ID_LIST2_MAXLEN 127
@@ -62,6 +64,164 @@
unsigned int id_list_len;
};
+/*! Packed representation of a Priority IE (GGPP TS 48.008 3.2.2.18) */
+struct gsm0808_priority {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t pvi:1, /* Preemption Vulnerability indicator */
+ qa:1, /* Queuing allowed indicator */
+ priority_level:4, /* Priority level: 1 == hightest, 14 == lowest */
+ pci:1, /* Preemption Capability indicator */
+ spare:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above
(libosmocore/contrib/struct_endianness.py) */
+ uint8_t spare:1, pci:1, priority_level:4, qa:1, pvi:1;
+#endif
+} __attribute__ ((packed));
+
+/*! Packed representation of a VGCS Feature Flags IE (3GPP TS 48.008 3.2.2.88) */
+struct gsm0808_vgcs_feature_flags {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t tp_ind:1, /* Talker priority supported */
+ as_ind_circuit:1, /* A-interface circuit sharing supported */
+ as_ind_link:1, /* A-interface link sharing supported */
+ bss_res:1, /* BSS supports re-establishment */
+ tcp:1, /* Talker channel parameter supported */
+ spare:3;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above
(libosmocore/contrib/struct_endianness.py) */
+ uint8_t spare:3, tcp:1, bss_res:1, as_ind_link:1, as_ind_circuit:1, tp_ind:1;
+#endif
+} __attribute__ ((packed));
+
+/* TS 48.008 3.2.2.52 */
+enum gsm0808_assignment_requirement {
+ GSM0808_ASRQ_DELAY_ALLOWED = 0x00,
+ GSM0808_ASRQ_IMMEDIATE = 0x01,
+ GSM0808_ASRQ_IMMEDIATE_ON_DEMAND = 0x02,
+};
+
+/* TS 48.008 Table 10.5.8 */
+enum gsm0808_service_flag {
+ GSM0808_SF_VBS = 0,
+ GSM0808_SF_VGCS = 1,
+};
+
+enum gsm0808_call_priority {
+ GSM0808_CALL_PRIORITY_NONE = 0x00,
+ GSM0808_CALL_PRIORITY_LEVEL_4 = 0x01,
+ GSM0808_CALL_PRIORITY_LEVEL_3 = 0x02,
+ GSM0808_CALL_PRIORITY_LEVEL_2 = 0x03,
+ GSM0808_CALL_PRIORITY_LEVEL_1 = 0x04,
+ GSM0808_CALL_PRIORITY_LEVEL_0 = 0x05,
+ GSM0808_CALL_PRIORITY_LEVEL_B = 0x06,
+ GSM0808_CALL_PRIORITY_LEVEL_A = 0x07,
+};
+
+/*! Packed representation of a Group Call Reference IE (3GPP TS 48.008 3.2.2.55) */
+struct gsm0808_group_callref {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t call_ref_hi[3];
+ uint8_t call_priority:3,
+ af:1, /* Acknowledgement flag */
+ sf:1, /* Service flag */
+ call_ref_lo:3;
+ uint8_t spare:4,
+ ciphering_info:4;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above
(libosmocore/contrib/struct_endianness.py) */
+ uint8_t call_ref_hi[3];
+ uint8_t call_ref_lo:3, sf:1, af:1, call_priority:3;
+ uint8_t ciphering_info:4, spare:4;
+#endif
+} __attribute__ ((packed));
+
+/* TS 48.008 3.2.2.26 */
+enum gsm0808_downlink_dtx_flag {
+ GSM0808_DTX_FLAG_ALLOW = 0,
+ GSM0808_DTX_FLAG_FORBID = 1,
+};
+
+/*! Parsed representation of a Cell Identifier List Segment IE (3GPP TS 48.008 3.2.2.27a)
*/
+struct gsm0808_cell_id_list_segment {
+ uint8_t seq_last;
+ uint8_t seq_number;
+ struct gsm0808_cell_id_list2 cil;
+};
+
+/*! Parsed representation of a Circuit Pool List IE (3GPP TS 48.008 3.2.2.26) */
+#define CIRCUIT_POOL_LIST_MAXLEN 252
+struct gsm0808_circuit_pool_list {
+ uint8_t pool[CIRCUIT_POOL_LIST_MAXLEN];
+ unsigned int list_len;
+};
+
+/* 3GPP TS 48.008 Table 3.2.2.90.1 Talker Priority */
+enum gsm0808_talker_priority {
+ GSM0808_TALKER_PRIORITY_NORMAL = 0x00,
+ GSM0808_TALKER_PRIORITY_PRIVILEGED = 0x01,
+ GSM0808_TALKER_PRIORITY_EMERGENCY = 0x02,
+};
+
+/*! Parsed representation of a Layer 3 Information IE (3GPP TS 48.008 3.2.2.24) */
+#define LAYER_3_INFORMATION_MAXLEN 252
+struct gsm0808_layer_3_information {
+ uint8_t l3[LAYER_3_INFORMATION_MAXLEN];
+ unsigned int l3_len;
+};
+
+/*! Parsed representation of a Talker Identity IE (3GPP TS 48.008 3.2.2.91) */
+#define TALKER_IDENTITY_MAXLEN 17
+struct gsm0808_talker_identity {
+ uint8_t talker_id[TALKER_IDENTITY_MAXLEN];
+ unsigned int id_bits;
+};
+
+/* 3GPP TS 48.008 3.2.2.94 VGCS/VBS Cell Status */
+enum gsm0808_vgcs_vbs_cell_status {
+ GSM0808_CSTAT_ESTABLISHED = 0x00,
+ GSM0808_CSTAT_NOT_ESTABLISHED1 = 0x01,
+ GSM0808_CSTAT_RELEASED_NO_USER = 0x02,
+ GSM0808_CSTAT_NOT_ESTABLISHED2 = 0x03,
+};
+
+/*! Parsed representation of a SMS to VGCS IE (3GPP TS 48.008 3.2.2.92) */
+#define SMS_TO_VGCS_MAXLEN 252
+struct gsm0808_sms_to_vgcs {
+ uint8_t sms[SMS_TO_VGCS_MAXLEN];
+ unsigned int sms_len;
+};
+
+/*! Parsed representation of a Application Data IE (3GPP TS 48.008 3.2.2.98) */
+#define APP_DATA_MAXLEN 9
+struct gsm0808_application_data {
+ uint8_t data[APP_DATA_MAXLEN];
+ unsigned int data_len;
+};
+
+/*! Packed representation of a Data Identity IE (GGPP TS 48.008 3.2.2.99) */
+enum gsm0808_application_idndicator {
+ GSM0808_AI_APP_DATA = 0x00,
+ GSM0808_AI_CONFIRM_APP_DATA = 0x01,
+};
+
+#define GSM0808_DP_MASK_TALKERS_LISTENERS 0x04
+#define GSM0808_DP_MASK_DISPATCHERS 0x02
+#define GSM0808_DP_MASK_NETWORK_APP 0x01
+
+struct gsm0808_data_identity {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t ai:1, /* Application Indicator */
+ di:4, /* Data identifier */
+ dp:3; /* Distribution parameter (bit mask) */
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above
(libosmocore/contrib/struct_endianness.py) */
+ uint8_t dp:3, di:4, ai:1;
+#endif
+} __attribute__ ((packed));
+
+/*! Parsed representation of a MSISDN IE (3GPP TS 48.008 3.2.2.101) */
+#define MSISDN_MAXLEN 20
+
/*! LCLS-related parameters from 3GPP TS 48.008 */
struct osmo_lcls {
enum gsm0808_lcls_config config; /**< §3.2.2.116 Configuration */
@@ -303,4 +463,23 @@
char *gsm0808_channel_type_name_buf(char *buf, size_t buf_len, const struct
gsm0808_channel_type *ct);
char *gsm0808_channel_type_name_c(const void *ctx, const struct gsm0808_channel_type
*ct);
+uint8_t gsm0808_enc_group_callref(struct msgb *msg, const struct gsm0808_group_callref
*gc);
+int gsm0808_dec_group_callref(struct gsm0808_group_callref *gc, const uint8_t *elem,
uint8_t len);
+uint8_t gsm0808_enc_priority(struct msgb *msg, const struct gsm0808_priority *pri);
+int gsm0808_dec_priority(struct gsm0808_priority *pri, const uint8_t *elem, uint8_t
len);
+uint8_t gsm0808_enc_vgcs_feature_flags(struct msgb *msg, const struct
gsm0808_vgcs_feature_flags *ff);
+int gsm0808_dec_vgcs_feature_flags(struct gsm0808_vgcs_feature_flags *ff, const uint8_t
*elem, uint8_t len);
+uint8_t gsm0808_enc_talker_identity(struct msgb *msg, const struct
gsm0808_talker_identity *ti);
+int gsm0808_dec_talker_identity(struct gsm0808_talker_identity *ti, const uint8_t *elem,
uint8_t len);
+uint8_t gsm0808_enc_data_identity(struct msgb *msg, const struct gsm0808_data_identity
*ai);
+int gsm0808_dec_data_identity(struct gsm0808_data_identity *ai, const uint8_t *elem,
uint8_t len);
+uint8_t gsm0808_enc_msisdn(struct msgb *msg, const char *msisdn);
+int gsm0808_dec_msisdn(char *msisdn, const char *elem, uint8_t len);
+uint8_t gsm0808_enc_assign_req(struct msgb *msg, const enum
gsm0808_assignment_requirement ar);
+int gsm0808_dec_assign_req(enum gsm0808_assignment_requirement *ar, const uint8_t *elem,
uint8_t len);
+uint8_t gsm0808_enc_cell_id_list_segment(struct msgb *msg, uint8_t ie_type,
+ const struct gsm0808_cell_id_list_segment *ci);
+int gsm0808_dec_cell_id_list_segment(struct gsm0808_cell_id_list_segment *ci, const
uint8_t *elem, uint8_t len);
+int gsm0808_dec_call_id(uint32_t *ci, const uint8_t *elem, uint8_t len);
+
/*! @} */
diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c
index efa9305..b8e1ff0 100644
--- a/src/gsm/gsm0808_utils.c
+++ b/src/gsm/gsm0808_utils.c
@@ -2210,4 +2210,367 @@
return gsm0808_channel_type_name_buf(buf, 128, ct);
}
+/*! Encode Group Call Reference IE (3GPP TS 48.008 3.2.2.55).
+ * \param[out] msg Message Buffer to which IE is to be appended
+ * \param[in] gc Group Call Reference to be encoded
+ * \returns number of bytes appended to \a msg */
+uint8_t gsm0808_enc_group_callref(struct msgb *msg, const struct gsm0808_group_callref
*gc)
+{
+ uint8_t *old_tail;
+ uint8_t *tlv_len;
+
+ OSMO_ASSERT(msg);
+ OSMO_ASSERT(gc);
+
+ msgb_put_u8(msg, GSM0808_IE_GROUP_CALL_REFERENCE);
+ tlv_len = msgb_put(msg, 1);
+ old_tail = msg->tail;
+
+ memcpy(msgb_put(msg, sizeof(*gc)), gc, sizeof(*gc));
+
+ *tlv_len = (uint8_t) (msg->tail - old_tail);
+ return *tlv_len + 2;
+}
+
+/*! Decode Group Call Reference IE (3GPP TS 48.008 3.2.2.55).
+ * \param[out] gc Group Call Reference structure to store data
+ * \param[in] elem IE value to be decoded.
+ * \param[in] len Length of \a elem in bytes.
+ * \returns number of bytes parsed; negative on error */
+int gsm0808_dec_group_callref(struct gsm0808_group_callref *gc, const uint8_t *elem,
uint8_t len)
+{
+ OSMO_ASSERT(gc);
+ OSMO_ASSERT(elem);
+
+ if (len != sizeof(*gc))
+ return -EINVAL;
+
+ memcpy(gc, elem, sizeof(*gc));
+
+ return len;
+}
+
+/*! Encode Priority IE (3GPP TS 48.008 3.2.2.18).
+ * \param[out] msg Message Buffer to which IE is to be appended
+ * \param[in] pri Priority to be encoded
+ * \returns number of bytes appended to \a msg */
+uint8_t gsm0808_enc_priority(struct msgb *msg, const struct gsm0808_priority *pri)
+{
+ uint8_t *old_tail;
+ uint8_t *tlv_len;
+
+ OSMO_ASSERT(msg);
+ OSMO_ASSERT(pri);
+
+ msgb_put_u8(msg, GSM0808_IE_PRIORITY);
+ tlv_len = msgb_put(msg, 1);
+ old_tail = msg->tail;
+
+ memcpy(msgb_put(msg, sizeof(*pri)), pri, sizeof(*pri));
+
+ *tlv_len = (uint8_t) (msg->tail - old_tail);
+ return *tlv_len + 2;
+}
+
+/*! Decode Priority IE (3GPP TS 48.008 3.2.2.18).
+ * \param[out] pri Priority structure to store data
+ * \param[in] elem IE value to be decoded.
+ * \param[in] len Length of \a elem in bytes.
+ * \returns number of bytes parsed; negative on error */
+int gsm0808_dec_priority(struct gsm0808_priority *pri, const uint8_t *elem, uint8_t len)
+{
+ OSMO_ASSERT(pri);
+ OSMO_ASSERT(elem);
+
+ if (len != sizeof(*pri))
+ return -EINVAL;
+
+ memcpy(pri, elem, sizeof(*pri));
+
+ return len;
+}
+
+/*! Encode VGCS Feature Flags IE (3GPP TS 48.008 3.2.2.88).
+ * \param[out] msg Message Buffer to which IE is to be appended
+ * \param[in] ff VGCS Feature Flags to be encoded
+ * \returns number of bytes appended to \a msg */
+uint8_t gsm0808_enc_vgcs_feature_flags(struct msgb *msg, const struct
gsm0808_vgcs_feature_flags *ff)
+{
+ uint8_t *old_tail;
+ uint8_t *tlv_len;
+
+ OSMO_ASSERT(msg);
+ OSMO_ASSERT(ff);
+
+ msgb_put_u8(msg, GSM0808_IE_VGCS_FEATURE_FLAGS);
+ tlv_len = msgb_put(msg, 1);
+ old_tail = msg->tail;
+
+ memcpy(msgb_put(msg, sizeof(*ff)), ff, sizeof(*ff));
+
+ *tlv_len = (uint8_t) (msg->tail - old_tail);
+ return *tlv_len + 2;
+}
+
+/*! Decode VGCS Feature Flags IE (3GPP TS 48.008 3.2.2.88).
+ * \param[out] ff VGCS Feature Flags structure to store data
+ * \param[in] elem IE value to be decoded.
+ * \param[in] len Length of \a elem in bytes.
+ * \returns number of bytes parsed; negative on error */
+int gsm0808_dec_vgcs_feature_flags(struct gsm0808_vgcs_feature_flags *ff, const uint8_t
*elem, uint8_t len)
+{
+ OSMO_ASSERT(ff);
+ OSMO_ASSERT(elem);
+
+ if (len != sizeof(*ff))
+ return -EINVAL;
+
+ memcpy(ff, elem, sizeof(*ff));
+
+ return len;
+}
+
+/*! Encode Data Identity IE (3GPP TS 48.008 3.2.2.99).
+ * \param[out] msg Message Buffer to which IE is to be appended
+ * \param[in] di Data Identity to be encoded
+ * \returns number of bytes appended to \a msg */
+uint8_t gsm0808_enc_data_identity(struct msgb *msg, const struct gsm0808_data_identity
*ti)
+{
+ uint8_t *old_tail;
+ uint8_t *tlv_len;
+
+ OSMO_ASSERT(msg);
+ OSMO_ASSERT(ti);
+
+ msgb_put_u8(msg, GSM0808_IE_DATA_IDENTITY);
+ tlv_len = msgb_put(msg, 1);
+ old_tail = msg->tail;
+
+ memcpy(msgb_put(msg, sizeof(*ti)), ti, sizeof(*ti));
+
+ *tlv_len = (uint8_t) (msg->tail - old_tail);
+ return *tlv_len + 2;
+}
+
+/*! Decode Data Identity IE (3GPP TS 48.008 3.2.2.99).
+ * \param[out] di Data Identity structure to store data
+ * \param[in] elem IE value to be decoded.
+ * \param[in] len Length of \a elem in bytes.
+ * \returns number of bytes parsed; negative on error */
+int gsm0808_dec_data_identity(struct gsm0808_data_identity *ti, const uint8_t *elem,
uint8_t len)
+{
+ OSMO_ASSERT(ti);
+ OSMO_ASSERT(elem);
+
+ if (len < sizeof(*ti))
+ return -EINVAL;
+
+ memcpy(ti, elem, sizeof(*ti));
+
+ return len;
+}
+
+/*! Encode MSISDN IE (3GPP TS 48.008 3.2.2.101).
+ * \param[out] msg Message Buffer to which IE is to be appended
+ * \param[in] msisdn MSISDN to be encoded
+ * \returns number of bytes appended to \a msg */
+uint8_t gsm0808_enc_msisdn(struct msgb *msg, const char *msisdn)
+{
+ uint8_t *tlv_len;
+ uint8_t bcd_lv[11];
+ int rc;
+
+ OSMO_ASSERT(msg);
+ OSMO_ASSERT(msisdn);
+
+ rc = gsm48_encode_bcd_number(bcd_lv, sizeof(bcd_lv), 0, msisdn);
+ if (rc < 1)
+ return 0;
+
+ msgb_put_u8(msg, GSM0808_IE_MSISDN);
+ tlv_len = msgb_put(msg, rc);
+
+ memcpy(tlv_len, bcd_lv, rc);
+
+ *tlv_len = rc - 1;
+ return *tlv_len + 2;
+}
+
+/*! Decode MSISDN IE (3GPP TS 48.008 3.2.2.101).
+ * \param[out] msisdn MSISDN structure to store data
+ * \param[in] elem IE value to be decoded.
+ * \param[in] len Length of \a elem in bytes.
+ * \returns number of bytes parsed; negative on error */
+int gsm0808_dec_msisdn(char *msisdn, const char *elem, uint8_t len)
+{
+ OSMO_ASSERT(msisdn);
+ OSMO_ASSERT(elem);
+
+ if (len < 1)
+ return -EINVAL;
+
+ gsm48_decode_bcd_number(msisdn, MSISDN_MAXLEN + 1, (uint8_t *)(elem - 1), 0);
+
+ return len;
+}
+
+/*! Encode Talker Identity IE (3GPP TS 48.008 3.2.2.91).
+ * \param[out] msg Message Buffer to which IE is to be appended
+ * \param[in] ti Talker Identity to be encoded
+ * \returns number of bytes appended to \a msg */
+uint8_t gsm0808_enc_talker_identity(struct msgb *msg, const struct
gsm0808_talker_identity *ti)
+{
+ uint8_t *old_tail;
+ uint8_t *tlv_len;
+ uint8_t *ptr;
+ unsigned int bytes;
+
+ OSMO_ASSERT(msg);
+ OSMO_ASSERT(ti);
+
+ msgb_put_u8(msg, GSM0808_IE_TALKER_IDENTITY);
+ tlv_len = msgb_put(msg, 1);
+ old_tail = msg->tail;
+
+ bytes = (ti->id_bits + 7) >> 3;
+ ptr = msgb_put(msg, 1 + bytes);
+ ptr[0] = -ti->id_bits & 0x7;
+ memcpy(ptr + 1, ti->talker_id, bytes);
+
+ *tlv_len = (uint8_t) (msg->tail - old_tail);
+ return *tlv_len + 2;
+}
+
+/*! Decode Talker Identity IE (3GPP TS 48.008 3.2.2.91).
+ * \param[out] ti Talker Identity structure to store data
+ * \param[in] elem IE value to be decoded.
+ * \param[in] len Length of \a elem in bytes.
+ * \returns number of bytes parsed; negative on error */
+int gsm0808_dec_talker_identity(struct gsm0808_talker_identity *ti, const uint8_t *elem,
uint8_t len)
+{
+ OSMO_ASSERT(ti);
+ OSMO_ASSERT(elem);
+
+ if (len < 2)
+ return -EINVAL;
+ unsigned int bytes;
+
+ bytes = len - 1;
+ if (bytes > TALKER_IDENTITY_MAXLEN)
+ return -EINVAL;
+ ti->id_bits = (bytes << 3) - (elem[0] & 0x7);
+ memcpy(ti->talker_id, elem + 1, bytes);
+
+ return len;
+}
+
+/*! Encode Assignment Requirements IE (3GPP TS 48.008 3.2.2.52).
+ * \param[out] msg Message Buffer to which IE is to be appended
+ * \param[in] ar Assignment Requirement to be encoded
+ * \returns number of bytes appended to \a msg */
+uint8_t gsm0808_enc_assign_req(struct msgb *msg, const enum
gsm0808_assignment_requirement ar)
+{
+ uint8_t *ptr;
+
+ OSMO_ASSERT(msg);
+
+ msgb_put_u8(msg, GSM0808_IE_ASSIGNMENT_REQUIREMENT);
+
+ ptr = msgb_put(msg, 1);
+ ptr[0] = ar;
+
+ return 2;
+}
+
+/*! Decode Assignment Requirements IE (3GPP TS 48.008 3.2.2.52).
+ * \param[out] ar Assignment Requirements enum to store data
+ * \param[in] elem IE value to be decoded.
+ * \param[in] len Length of \a elem in bytes.
+ * \returns number of bytes parsed; negative on error */
+int gsm0808_dec_assign_req(enum gsm0808_assignment_requirement *ar, const uint8_t *elem,
uint8_t len)
+{
+ OSMO_ASSERT(ar);
+ OSMO_ASSERT(elem);
+
+ if (len != 1)
+ return -EINVAL;
+
+ *ar = elem[0];
+
+ return 1;
+}
+
+/*! Encode Cell Identifier List Segment IE (3GPP TS 48.008 3.2.2.27a).
+ * \param[out] msg Message Buffer to which IE is to be appended
+ * \param[in] ie_type Type of IE to use (5 different lists are specified.)
+ * \param[in] ci Cell Identifier List Segment to be encoded
+ * \returns number of bytes appended to \a msg */
+uint8_t gsm0808_enc_cell_id_list_segment(struct msgb *msg, uint8_t ie_type,
+ const struct gsm0808_cell_id_list_segment *ci)
+{
+ uint8_t *old_tail;
+ uint8_t *tlv_len;
+ int rc;
+
+ OSMO_ASSERT(msg);
+ OSMO_ASSERT(ci);
+
+ msgb_put_u8(msg, ie_type);
+ tlv_len = msgb_put(msg, 1);
+ old_tail = msg->tail;
+
+ msgb_put_u8(msg, (ci->seq_last << 4) | ci->seq_number);
+
+ rc = gsm0808_enc_cell_id_list2(msg, &ci->cil);
+ if (rc <= 0)
+ return rc;
+
+ *tlv_len = (uint8_t) (msg->tail - old_tail);
+ return *tlv_len + 2;
+}
+
+/*! Decode Cell Identifier List Segment IE (3GPP TS 48.008 3.2.2.27a).
+ * \param[out] ci Cell Identifier List Segment structure to store data
+ * \param[in] elem IE value to be decoded.
+ * \param[in] len Length of \a elem in bytes.
+ * \returns number of bytes parsed; negative on error */
+int gsm0808_dec_cell_id_list_segment(struct gsm0808_cell_id_list_segment *ci, const
uint8_t *elem, uint8_t len)
+{
+ int rc;
+
+ OSMO_ASSERT(ci);
+ OSMO_ASSERT(elem);
+
+ if (len < 1)
+ return -EINVAL;
+
+ ci->seq_last = elem[0] >> 4;
+ ci->seq_number = elem[0] & 0x0f;
+
+ rc = gsm0808_dec_cell_id_list2(&ci->cil, elem + 1, len - 1);
+ if (rc < 0)
+ return rc;
+
+ return len;
+}
+
+/*! Decode Call Identifier IE (3GPP TS 48.008 3.2.2.105).
+ * \param[out] ci Call Identifier structure to store data
+ * \param[in] elem IE value to be decoded.
+ * \param[in] len Length of \a elem in bytes.
+ * \returns number of bytes parsed; negative on error */
+int gsm0808_dec_call_id(uint32_t *ci, const uint8_t *elem, uint8_t len)
+{
+ OSMO_ASSERT(ci);
+ OSMO_ASSERT(elem);
+
+ if (len != 4)
+ return -EINVAL;
+
+ /* The Call Identifier is stored as little endian. */
+ *ci = osmo_load32le(elem);
+
+ return 4;
+}
+
/*! @} */
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 8bc1272..40f3e80 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -231,6 +231,23 @@
gsm0808_enc_cell_id_list2;
gsm0808_dec_cell_id_list;
gsm0808_dec_cell_id_list2;
+gsm0808_enc_group_callref;
+gsm0808_dec_group_callref;
+gsm0808_enc_priority;
+gsm0808_dec_priority;
+gsm0808_enc_vgcs_feature_flags;
+gsm0808_dec_vgcs_feature_flags;
+gsm0808_enc_data_identity;
+gsm0808_dec_data_identity;
+gsm0808_enc_msisdn;
+gsm0808_dec_msisdn;
+gsm0808_enc_talker_identity;
+gsm0808_dec_talker_identity;
+gsm0808_enc_assign_req;
+gsm0808_dec_assign_req;
+gsm0808_enc_cell_id_list_segment;
+gsm0808_dec_cell_id_list_segment;
+gsm0808_dec_call_id;
gsm0808_cell_id_list_add;
gsm0808_cell_id_to_list;
gsm0808_cell_id_to_cgi;
--
To view, visit
https://gerrit.osmocom.org/c/libosmocore/+/32931
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: Ic1fc714bb04228a7f32e9925811e21c8efc610bd
Gerrit-Change-Number: 32931
Gerrit-PatchSet: 5
Gerrit-Owner: jolly <andreas(a)eversberg.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-CC: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-MessageType: merged