aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom/gsm
diff options
context:
space:
mode:
Diffstat (limited to 'include/osmocom/gsm')
-rw-r--r--include/osmocom/gsm/Makefile.am69
-rw-r--r--include/osmocom/gsm/a5.h4
-rw-r--r--include/osmocom/gsm/bsslap.h53
-rw-r--r--include/osmocom/gsm/bssmap_le.h77
-rw-r--r--include/osmocom/gsm/bts_features.h23
-rw-r--r--include/osmocom/gsm/cbsp.h33
-rw-r--r--include/osmocom/gsm/gad.h190
-rw-r--r--include/osmocom/gsm/gsm0502.h66
-rw-r--r--include/osmocom/gsm/gsm0808.h290
-rw-r--r--include/osmocom/gsm/gsm0808_lcs.h48
-rw-r--r--include/osmocom/gsm/gsm0808_utils.h279
-rw-r--r--include/osmocom/gsm/gsm23003.h22
-rw-r--r--include/osmocom/gsm/gsm29118.h4
-rw-r--r--include/osmocom/gsm/gsm29205.h8
-rw-r--r--include/osmocom/gsm/gsm44021.h8
-rw-r--r--include/osmocom/gsm/gsm48.h16
-rw-r--r--include/osmocom/gsm/gsm48_ie.h9
-rw-r--r--include/osmocom/gsm/gsm48_rest_octets.h11
-rw-r--r--include/osmocom/gsm/gsm_utils.h31
-rw-r--r--include/osmocom/gsm/gsup.h41
-rw-r--r--include/osmocom/gsm/i460_mux.h121
-rw-r--r--include/osmocom/gsm/ipa.h2
-rw-r--r--include/osmocom/gsm/iuup.h129
-rw-r--r--include/osmocom/gsm/l1sap.h8
-rw-r--r--include/osmocom/gsm/lapd_core.h177
-rw-r--r--include/osmocom/gsm/lapdm.h14
-rw-r--r--include/osmocom/gsm/meas_rep.h4
-rw-r--r--include/osmocom/gsm/prim.h5
-rw-r--r--include/osmocom/gsm/protocol/Makefile.am30
-rw-r--r--include/osmocom/gsm/protocol/gsm_03_41.h8
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_08.h408
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_08_gprs.h66
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_11.h10
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_12.h4
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_14.h8
-rw-r--r--include/osmocom/gsm/protocol/gsm_08_08.h172
-rw-r--r--include/osmocom/gsm/protocol/gsm_08_58.h313
-rw-r--r--include/osmocom/gsm/protocol/gsm_09_02.h5
-rw-r--r--include/osmocom/gsm/protocol/gsm_12_21.h172
-rw-r--r--include/osmocom/gsm/protocol/gsm_23_032.h252
-rw-r--r--include/osmocom/gsm/protocol/gsm_23_041.h12
-rw-r--r--include/osmocom/gsm/protocol/gsm_25_415.h222
-rw-r--r--include/osmocom/gsm/protocol/gsm_44_004.h19
-rw-r--r--include/osmocom/gsm/protocol/gsm_44_060.h252
-rw-r--r--include/osmocom/gsm/protocol/gsm_44_068.h136
-rw-r--r--include/osmocom/gsm/protocol/gsm_44_318.h4
-rw-r--r--include/osmocom/gsm/protocol/gsm_48_071.h118
-rw-r--r--include/osmocom/gsm/protocol/gsm_49_031.h234
-rw-r--r--include/osmocom/gsm/protocol/ipaccess.h1
-rw-r--r--include/osmocom/gsm/rlp.h81
-rw-r--r--include/osmocom/gsm/tlv.h107
51 files changed, 3844 insertions, 532 deletions
diff --git a/include/osmocom/gsm/Makefile.am b/include/osmocom/gsm/Makefile.am
new file mode 100644
index 00000000..5678a51e
--- /dev/null
+++ b/include/osmocom/gsm/Makefile.am
@@ -0,0 +1,69 @@
+SUBDIRS = protocol
+
+BUILT_SOURCES = gsm0503.h
+
+osmogsm_HEADERS = \
+ a5.h \
+ abis_nm.h \
+ apn.h \
+ bts_features.h \
+ cbsp.h \
+ comp128.h \
+ comp128v23.h \
+ bitvec_gsm.h \
+ gan.h \
+ gsm0341.h \
+ gsm0411_smc.h \
+ gsm0411_smr.h \
+ gsm0411_utils.h \
+ gsm0480.h \
+ gsm0502.h \
+ gsm0503.h \
+ bsslap.h \
+ bssmap_le.h \
+ gad.h \
+ gsm0808.h \
+ gsm0808_lcs.h \
+ gsm29205.h \
+ gsm0808_utils.h \
+ gsm23003.h \
+ gsm23236.h \
+ gsm29118.h \
+ gsm44021.h \
+ gsm48.h \
+ gsm48_arfcn_range_encode.h \
+ gsm48_ie.h \
+ gsm48_rest_octets.h \
+ gsm_utils.h \
+ gsup.h \
+ gsup_sms.h \
+ i460_mux.h \
+ ipa.h \
+ iuup.h \
+ lapd_core.h \
+ lapdm.h \
+ meas_rep.h \
+ mncc.h \
+ prim.h \
+ l1sap.h \
+ oap.h \
+ oap_client.h \
+ rlp.h \
+ rsl.h \
+ rxlev_stat.h \
+ sysinfo.h \
+ tlv.h \
+ $(NULL)
+
+osmogsmdir = $(includedir)/osmocom/gsm
+
+noinst_HEADERS = \
+ kasumi.h \
+ gea.h \
+ $(NULL)
+
+gsm0503.h: $(top_srcdir)/utils/conv_gen.py $(top_srcdir)/utils/conv_codes_gsm.py
+ $(AM_V_GEN)python3 $(top_srcdir)/utils/conv_gen.py gen_header gsm \
+ --target-path $(builddir)/
+
+CLEANFILES = gsm0503.h
diff --git a/include/osmocom/gsm/a5.h b/include/osmocom/gsm/a5.h
index fa63246d..1b26842f 100644
--- a/include/osmocom/gsm/a5.h
+++ b/include/osmocom/gsm/a5.h
@@ -12,10 +12,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
diff --git a/include/osmocom/gsm/bsslap.h b/include/osmocom/gsm/bsslap.h
new file mode 100644
index 00000000..56f2e6c8
--- /dev/null
+++ b/include/osmocom/gsm/bsslap.h
@@ -0,0 +1,53 @@
+/*! \addtogroup bsslap
+ * @{
+ * \file bsslap.h
+ * Message encoding and decoding for 3GPP TS 48.071 BSS LCS Assistance Protocol (BSSLAP).
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+#pragma once
+
+#include <osmocom/gsm/protocol/gsm_48_071.h>
+#include <osmocom/gsm/protocol/gsm_49_031.h>
+
+struct msgb;
+
+struct osmo_bsslap_err {
+ int rc;
+ enum bsslap_msgt msg_type;
+ enum bsslap_iei iei;
+ enum lcs_cause cause;
+ char *logmsg;
+};
+
+extern const struct value_string osmo_bsslap_msgt_names[];
+static inline const char *osmo_bsslap_msgt_name(enum bsslap_msgt val)
+{ return get_value_string(osmo_bsslap_msgt_names, val); }
+
+extern const struct value_string osmo_bsslap_iei_names[];
+static inline const char *osmo_bsslap_iei_name(enum bsslap_iei val)
+{ return get_value_string(osmo_bsslap_iei_names, val); }
+
+int osmo_bsslap_enc(struct msgb *msg, const struct bsslap_pdu *pdu);
+int osmo_bsslap_dec(struct bsslap_pdu *pdu,
+ struct osmo_bsslap_err **err, void *err_ctx,
+ const uint8_t *data, size_t len);
+
+/*! @} */
diff --git a/include/osmocom/gsm/bssmap_le.h b/include/osmocom/gsm/bssmap_le.h
new file mode 100644
index 00000000..113d4bd1
--- /dev/null
+++ b/include/osmocom/gsm/bssmap_le.h
@@ -0,0 +1,77 @@
+/*! \addtogroup bssmap_le
+ * @{
+ * \file bssmap_le.h
+ * Message encoding and decoding for 3GPP TS 49.031 BSSMAP-LE.
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+#pragma once
+
+#include <osmocom/gsm/protocol/gsm_49_031.h>
+
+struct osmo_bsslap_err;
+struct osmo_gad_err;
+
+struct osmo_bssmap_le_err {
+ int rc;
+ enum bssmap_le_msgt msg_type;
+ enum bssmap_le_iei iei;
+ enum lcs_cause cause;
+ struct osmo_bsslap_err *bsslap_err;
+ struct osmo_gad_err *gad_err;
+ char *logmsg;
+};
+
+struct osmo_bssap_le_err {
+ int rc;
+ struct osmo_bssmap_le_err *bssmap_le_err;
+ void *dtap_err;
+ char *logmsg;
+};
+
+enum bssmap_le_msgt osmo_bssmap_le_msgt(const uint8_t *data, uint8_t len);
+
+extern const struct value_string osmo_bssmap_le_msgt_names[];
+static inline const char *osmo_bssmap_le_msgt_name(enum bssmap_le_msgt val)
+{ return get_value_string(osmo_bssmap_le_msgt_names, val); }
+
+extern const struct value_string osmo_bssmap_le_iei_names[];
+static inline const char *osmo_bssmap_le_iei_name(enum bssmap_le_iei val)
+{ return get_value_string(osmo_bssmap_le_iei_names, val); }
+
+int osmo_lcs_cause_enc(struct msgb *msg, const struct lcs_cause_ie *lcs_cause);
+int osmo_lcs_cause_dec(struct lcs_cause_ie *lcs_cause,
+ enum bssmap_le_msgt msgt, enum bssmap_le_iei iei,
+ struct osmo_bssmap_le_err **err, void *err_ctx,
+ const uint8_t *data, uint8_t len);
+
+int osmo_bssap_le_pdu_to_str_buf(char *buf, size_t buflen, const struct bssap_le_pdu *bssap_le);
+char *osmo_bssap_le_pdu_to_str_c(void *ctx, const struct bssap_le_pdu *bssap_le);
+
+struct msgb *osmo_bssap_le_enc(const struct bssap_le_pdu *pdu);
+int osmo_bssap_le_dec(struct bssap_le_pdu *pdu, struct osmo_bssap_le_err **err, void *err_ctx, struct msgb *msg);
+
+uint8_t osmo_bssmap_le_ie_enc_location_type(struct msgb *msg, const struct bssmap_le_location_type *location_type);
+int osmo_bssmap_le_ie_dec_location_type(struct bssmap_le_location_type *lt,
+ enum bssmap_le_msgt msgt, enum bssmap_le_iei iei,
+ struct osmo_bssmap_le_err **err, void *err_ctx,
+ const uint8_t *elem, uint8_t len);
+
+/*! @} */
diff --git a/include/osmocom/gsm/bts_features.h b/include/osmocom/gsm/bts_features.h
index 341ba405..cf1db4ac 100644
--- a/include/osmocom/gsm/bts_features.h
+++ b/include/osmocom/gsm/bts_features.h
@@ -7,7 +7,7 @@
/* N. B: always add new features to the end of the list (right before _NUM_BTS_FEAT) to avoid breaking compatibility
with BTS compiled against earlier version of this header. Also make sure that the description strings
- gsm_bts_features_descs[] in gsm_data.c are also updated accordingly! */
+ osmo_bts_features_{descs,names}[] in bts_features.c are also updated accordingly! */
enum osmo_bts_features {
BTS_FEAT_HSCSD,
BTS_FEAT_GPRS,
@@ -26,12 +26,31 @@ enum osmo_bts_features {
BTS_FEAT_ETWS_PN,
BTS_FEAT_PAGING_COORDINATION, /* BTS hands CS paging to PCU/PACCH */
BTS_FEAT_IPV6_NSVC,
+ BTS_FEAT_ACCH_REP,
+ BTS_FEAT_CCN, /* Is CCN supported by the cell? TS 44.060 sec 8.8.2 */
+ BTS_FEAT_VAMOS, /* Is the BTS VAMOS capable? */
+ BTS_FEAT_ABIS_OSMO_PCU, /* BTS supports forwarding data to PCUIF over IPA OML multiplex */
+ BTS_FEAT_BCCH_POWER_RED,
+ BTS_FEAT_DYN_TS_SDCCH8, /* Osmo Dynamic TS supports configured as SDCCH8 */
+ BTS_FEAT_ACCH_TEMP_OVP, /* FACCH/SACCH Temporary overpower */
+ BTS_FEAT_OSMUX, /* Osmux (Osmocom RTP muxing) support */
+ BTS_FEAT_VBS, /* Voice Broadcast Service support, 3GPP TS 43.069 */
+ BTS_FEAT_VGCS, /* Voice Group Call Service support, 3GPP TS 44.068 */
_NUM_BTS_FEAT
};
extern const struct value_string osmo_bts_features_descs[];
-const char *osmo_bts_feature_name(enum osmo_bts_features feature);
+static inline const char *osmo_bts_features_desc(enum osmo_bts_features val)
+{ return get_value_string(osmo_bts_features_descs, val); }
+
+const char *osmo_bts_feature_name(enum osmo_bts_features feature)
+ OSMO_DEPRECATED("Use osmo_bts_features_desc() instead");
+
+extern const struct value_string osmo_bts_features_names[];
+
+static inline const char *osmo_bts_features_name(enum osmo_bts_features val)
+{ return get_value_string(osmo_bts_features_names, val); }
static inline int osmo_bts_set_feature(struct bitvec *features, enum osmo_bts_features feature)
{
diff --git a/include/osmocom/gsm/cbsp.h b/include/osmocom/gsm/cbsp.h
index d456ce2f..efa4ce6f 100644
--- a/include/osmocom/gsm/cbsp.h
+++ b/include/osmocom/gsm/cbsp.h
@@ -24,10 +24,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* Decoded 8.2.3 Message Content */
@@ -75,7 +71,7 @@ struct osmo_cbsp_fail_ent {
struct llist_head list; /* entry in a fail_list below */
enum CELL_IDENT id_discr;
union gsm0808_cell_id_u cell_id;
- uint8_t cause;
+ uint8_t cause; /* enum osmo_cbsp_cause */
};
@@ -245,6 +241,30 @@ struct osmo_cbsp_error_ind {
enum cbsp_channel_ind *channel_ind;
};
+/* 8.2.13 Cause */
+enum osmo_cbsp_cause {
+ OSMO_CBSP_CAUSE_PARAM_NOT_RECOGNISED = 0,
+ OSMO_CBSP_CAUSE_PARAM_VALUE_INVALID,
+ OSMO_CBSP_CAUSE_MSG_REF_NOT_IDENTIFIED,
+ OSMO_CBSP_CAUSE_CELL_ID_NOT_VALID,
+ OSMO_CBSP_CAUSE_UNRECOGNISED_MESSAGE,
+ OSMO_CBSP_CAUSE_MISSING_MANDATORY_ELEMENT,
+ OSMO_CBSP_CAUSE_BSC_CAPACITY_EXCEEDED,
+ OSMO_CBSP_CAUSE_CELL_MEMORY_EXCEEDED,
+ OSMO_CBSP_CAUSE_BSC_MEMORY_EXCEEDED,
+ OSMO_CBSP_CAUSE_CELL_BROADCAST_NOT_SUPPORTED,
+ OSMO_CBSP_CAUSE_CELL_BROADCAST_NOT_OPERATIONAL,
+ OSMO_CBSP_CAUSE_INCOMPATIBLE_DRX_PARAM,
+ OSMO_CBSP_CAUSE_EXT_CHAN_NOT_SUPPORTED,
+ OSMO_CBSP_CAUSE_MSG_REF_ALREADY_USED,
+ OSMO_CBSP_CAUSE_UNSPECIFIED_ERROR,
+ OSMO_CBSP_CAUSE_LAI_OR_LAC_NOT_VALID,
+};
+extern const struct value_string osmo_cbsp_cause_names[];
+static inline const char *osmo_cbsp_cause_name(enum osmo_cbsp_cause cause)
+{
+ return get_value_string(osmo_cbsp_cause_names, cause);
+}
/* decoded CBSP message */
struct osmo_cbsp_decoded {
@@ -283,7 +303,7 @@ struct osmo_cbsp_decoded {
} u;
};
-extern const __thread char *osmo_cbsp_errstr;
+extern __thread const char *osmo_cbsp_errstr;
struct msgb *osmo_cbsp_msgb_alloc(void *ctx, const char *name);
struct msgb *osmo_cbsp_encode(void *ctx, const struct osmo_cbsp_decoded *in);
@@ -292,3 +312,4 @@ void osmo_cbsp_init_struct(struct osmo_cbsp_decoded *cbsp, enum cbsp_msg_type ms
struct osmo_cbsp_decoded *osmo_cbsp_decoded_alloc(void *ctx, enum cbsp_msg_type msg_type);
int osmo_cbsp_recv_buffered(void *ctx, int fd, struct msgb **rmsg, struct msgb **tmp_msg);
+int osmo_cbsp_segmentation_cb(struct msgb *msg);
diff --git a/include/osmocom/gsm/gad.h b/include/osmocom/gsm/gad.h
new file mode 100644
index 00000000..57d0e37a
--- /dev/null
+++ b/include/osmocom/gsm/gad.h
@@ -0,0 +1,190 @@
+/*! \addtogroup gad
+ * @{
+ * \file gad.h
+ * Message encoding and decoding for 3GPP TS 23.032 GAD: Universal Geographical Area Description.
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * This program 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.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <osmocom/gsm/protocol/gsm_23_032.h>
+#include <osmocom/core/utils.h>
+
+struct msgb;
+
+struct osmo_gad_ell_point {
+ /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+};
+
+struct osmo_gad_ell_point_unc_circle {
+ /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Uncertainty circle radius in millimeters (m * 1e3), 0 .. 18'000'000. */
+ uint32_t unc;
+};
+
+struct osmo_gad_ell_point_unc_ellipse {
+ /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_major;
+ /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_minor;
+ /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */
+ uint8_t major_ori;
+ /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t confidence;
+};
+
+struct osmo_gad_polygon {
+ uint8_t num_points;
+ struct osmo_gad_ell_point point[15];
+};
+
+struct osmo_gad_ell_point_alt {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Altitude in meters, -32767 (depth) .. 32767 (height) */
+ int16_t alt;
+};
+
+struct osmo_gad_ell_point_alt_unc_ell {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Altitude in meters, -32767 (depth) .. 32767 (height) */
+ int16_t alt;
+ /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_major;
+ /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_minor;
+ /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */
+ uint8_t major_ori;
+ /*! Uncertainty altitude in millimeters, 0 .. 990'000.
+ * Coding of uncertainty altitude is non-linear, and distinct from the non-altitude uncertainty coding. Use
+ * osmo_gad_dec_unc_alt(osmo_gad_enc_unc_alt(val)) to clamp. */
+ int32_t unc_alt;
+ /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t confidence;
+};
+
+struct osmo_gad_ell_arc {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! inner circle radius in mm (m * 1e3) */
+ uint32_t inner_r;
+ /*! Uncertainty circle radius in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_r;
+ /*! Offset angle of first arc edge in degrees from North clockwise (eastwards), 0..359.
+ * Angle is coded in increments of 2 degrees. */
+ uint16_t ofs_angle;
+ /*! Included angle defining the angular width of the arc, in degrees clockwise, 1..360.
+ * Angle is coded in increments of 2 degrees. */
+ uint16_t incl_angle;
+ /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t confidence;
+};
+
+struct osmo_gad_ha_ell_point_alt_unc_ell {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Altitude in millimeters, -500'000 (depth) .. 10'000'000 (height) */
+ int32_t alt;
+ /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 46'491.
+ * Coding of high-accuracy uncertainty is non-linear, use osmo_gad_dec_ha_unc(osmo_gad_enc_ha_unc(val)) to
+ * clamp. */
+ uint32_t unc_semi_major;
+ /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 46'491.
+ * Coding of high-accuracy uncertainty is non-linear, use osmo_gad_dec_ha_unc(osmo_gad_enc_ha_unc(val)) to
+ * clamp. */
+ uint32_t unc_semi_minor;
+ /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */
+ uint8_t major_ori;
+ /*! Horizontal confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t h_confidence;
+ /*! High-Accuracy uncertainty altitude */
+ int32_t unc_alt;
+ /*! Vertical confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t v_confidence;
+};
+
+struct osmo_gad {
+ enum gad_type type;
+ union {
+ struct osmo_gad_ell_point ell_point;
+ struct osmo_gad_ell_point_unc_circle ell_point_unc_circle;
+ struct osmo_gad_ell_point_unc_ellipse ell_point_unc_ellipse;
+ struct osmo_gad_polygon polygon;
+ struct osmo_gad_ell_point_alt ell_point_alt;
+ struct osmo_gad_ell_point_alt_unc_ell ell_point_alt_unc_ell;
+ struct osmo_gad_ell_arc ell_arc;
+ struct osmo_gad_ell_point_unc_ellipse ha_ell_point_unc_ellipse;
+ struct osmo_gad_ha_ell_point_alt_unc_ell ha_ell_point_alt_unc_ell;
+ };
+};
+
+struct osmo_gad_err {
+ int rc;
+ enum gad_type type;
+ char *logmsg;
+};
+
+extern const struct value_string osmo_gad_type_names[];
+static inline const char *osmo_gad_type_name(enum gad_type val)
+{ return get_value_string(osmo_gad_type_names, val); }
+
+int osmo_gad_raw_write(struct msgb *msg, const union gad_raw *gad_raw);
+int osmo_gad_raw_read(union gad_raw *gad_raw, struct osmo_gad_err **err, void *err_ctx, const uint8_t *data, uint8_t len);
+
+int osmo_gad_enc(union gad_raw *gad_raw, const struct osmo_gad *gad);
+int osmo_gad_dec(struct osmo_gad *gad, struct osmo_gad_err **err, void *err_ctx, const union gad_raw *gad_raw);
+
+int osmo_gad_to_str_buf(char *buf, size_t buflen, const struct osmo_gad *gad);
+char *osmo_gad_to_str_c(void *ctx, const struct osmo_gad *gad);
+
+uint32_t osmo_gad_enc_lat(int32_t deg_1e6);
+int32_t osmo_gad_dec_lat(uint32_t lat);
+uint32_t osmo_gad_enc_lon(int32_t deg_1e6);
+int32_t osmo_gad_dec_lon(uint32_t lon);
+uint8_t osmo_gad_enc_unc(uint32_t mm);
+uint32_t osmo_gad_dec_unc(uint8_t unc);
+/*! @} */
diff --git a/include/osmocom/gsm/gsm0502.h b/include/osmocom/gsm/gsm0502.h
index 1be2cc39..0ac13873 100644
--- a/include/osmocom/gsm/gsm0502.h
+++ b/include/osmocom/gsm/gsm0502.h
@@ -1,4 +1,7 @@
-/*! \file gsm0502.h */
+/*! \defgroup gsm0502 GSM 05.02 / 3GPP TS 45.002
+ * @{
+ * \file gsm0502.h
+ */
#pragma once
@@ -16,10 +19,10 @@
/*! Return the sum of two specified TDMA frame numbers (summation) */
#define GSM_TDMA_FN_SUM(a, b) \
- ((a + b) % GSM_TDMA_HYPERFRAME)
+ (((a) + (b)) % GSM_TDMA_HYPERFRAME)
/*! Return the difference of two specified TDMA frame numbers (subtraction) */
#define GSM_TDMA_FN_SUB(a, b) \
- ((a + GSM_TDMA_HYPERFRAME - b) % GSM_TDMA_HYPERFRAME)
+ (((a) + GSM_TDMA_HYPERFRAME - (b)) % GSM_TDMA_HYPERFRAME)
/*! Return the *minimum* difference of two specified TDMA frame numbers (distance) */
#define GSM_TDMA_FN_DIFF(a, b) \
OSMO_MIN(GSM_TDMA_FN_SUB(a, b), GSM_TDMA_FN_SUB(b, a))
@@ -31,9 +34,58 @@
#define GSM_TDMA_FN_DEC(fn) \
((fn) = GSM_TDMA_FN_SUB((fn), 1))
+/* 5.2.3.1 Normal burst for GMSK (1 bit per symbol) */
+#define GSM_NBITS_NB_GMSK_TAIL 3
+#define GSM_NBITS_NB_GMSK_PAYLOAD (2 * 58)
+#define GSM_NBITS_NB_GMSK_TRAIN_SEQ 26
+#define GSM_NBITS_NB_GMSK_BURST 148 /* without guard period */
+
+/* 5.2.3.3 Normal burst for 8-PSK (3 bits per symbol) */
+#define GSM_NBITS_NB_8PSK_TAIL (GSM_NBITS_NB_GMSK_TAIL * 3)
+#define GSM_NBITS_NB_8PSK_PAYLOAD (GSM_NBITS_NB_GMSK_PAYLOAD * 3)
+#define GSM_NBITS_NB_8PSK_TRAIN_SEQ (GSM_NBITS_NB_GMSK_TRAIN_SEQ * 3)
+#define GSM_NBITS_NB_8PSK_BURST (GSM_NBITS_NB_GMSK_BURST * 3)
+
+/* 5.2.5 Synchronization burst (also GMSK) */
+#define GSM_NBITS_SB_GMSK_TAIL GSM_NBITS_NB_GMSK_TAIL
+#define GSM_NBITS_SB_GMSK_PAYLOAD (2 * 39)
+#define GSM_NBITS_SB_GMSK_ETRAIN_SEQ 64
+#define GSM_NBITS_SB_GMSK_BURST GSM_NBITS_NB_GMSK_BURST
+
+/* 5.2.6 Dummy burst (also GMSK) */
+#define GSM_NBITS_DB_GMSK_TAIL GSM_NBITS_NB_GMSK_TAIL
+#define GSM_NBITS_DB_GMSK_MIXED 142
+#define GSM_NBITS_DB_GMSK_BURST GSM_NBITS_NB_GMSK_BURST
+
+/* 5.2.7 Access burst (also GMSK) */
+#define GSM_NBITS_AB_GMSK_ETAIL 8
+#define GSM_NBITS_AB_GMSK_SYNCH_SEQ 41
+#define GSM_NBITS_AB_GMSK_PAYLOAD 36
+#define GSM_NBITS_AB_GMSK_TAIL GSM_NBITS_NB_GMSK_TAIL
+#define GSM_NBITS_AB_GMSK_BURST GSM_NBITS_NB_GMSK_BURST
+
+/*! Compare the given TDMA FNs, taking the wrapping into account.
+ * \param[in] fn1 First TDMA Fn value to compare.
+ * \param[in] fn2 Second TDMA Fn value to compare.
+ * \returns similarly to memcmp(), -1 if fn1 goes before fn2;
+ * 0 if fn1 equals fn2;
+ * 1 if fn1 goes after fn2. */
+static inline int gsm0502_fncmp(uint32_t fn1, uint32_t fn2)
+{
+ const uint32_t thresh = GSM_TDMA_HYPERFRAME / 2;
+
+ if (fn1 == fn2)
+ return 0;
+ if ((fn1 < fn2 && (fn2 - fn1) < thresh) ||
+ (fn1 > fn2 && (fn1 - fn2) > thresh))
+ return -1;
+
+ return 1;
+}
+
/* Table 5 Clause 7 TS 05.02 */
static inline unsigned int
-gsm0502_get_n_pag_blocks(struct gsm48_control_channel_descr *chan_desc)
+gsm0502_get_n_pag_blocks(const struct gsm48_control_channel_descr *chan_desc)
{
if (chan_desc->ccch_conf == RSL_BCCH_CCCH_CONF_1_C)
return 3 - chan_desc->bs_ag_blks_res;
@@ -58,7 +110,7 @@ gsm0502_get_paging_group(uint64_t imsi, unsigned int bs_cc_chans,
}
unsigned int
-gsm0502_calc_paging_group(struct gsm48_control_channel_descr *chan_desc, uint64_t imsi);
+gsm0502_calc_paging_group(const struct gsm48_control_channel_descr *chan_desc, uint64_t imsi);
enum gsm0502_fn_remap_channel {
FN_REMAP_TCH_F,
@@ -75,3 +127,7 @@ uint32_t gsm0502_fn_remap(uint32_t fn, enum gsm0502_fn_remap_channel channel);
uint16_t gsm0502_hop_seq_gen(const struct gsm_time *t,
uint8_t hsn, uint8_t maio,
size_t n, const uint16_t *ma);
+
+int gsm0502_fn2ccch_block(uint32_t fn);
+
+/*! @} */
diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h
index 20137daf..80ef6836 100644
--- a/include/osmocom/gsm/gsm0808.h
+++ b/include/osmocom/gsm/gsm0808.h
@@ -16,10 +16,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#pragma once
@@ -30,11 +26,11 @@
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/socket_compat.h>
+
#define BSSMAP_MSG_SIZE 1024
#define BSSMAP_MSG_HEADROOM 512
-struct sockaddr_storage;
-
struct msgb;
struct gsm0808_cell_id_list2;
@@ -54,10 +50,30 @@ struct msgb *gsm0808_create_clear_command2(uint8_t cause, bool csfb_ind);
struct msgb *gsm0808_create_clear_complete(void);
struct msgb *gsm0808_create_cipher(const struct gsm0808_encrypt_info *ei,
const uint8_t *cipher_response_mode);
+
+struct gsm0808_cipher_mode_command {
+ struct gsm0808_encrypt_info ei;
+
+ /*! 3GPP TS 48.008 3.2.2.34 Cipher Response Mode, optional IE */
+ bool cipher_response_mode_present;
+ /*! 3GPP TS 48.008 3.2.2.34 Cipher Response Mode:
+ * 0 - IMEISV must not be included by the Mobile Station;
+ * 1 - IMEISV must be included by the Mobile Station.
+ */
+ uint8_t cipher_response_mode;
+
+ bool kc128_present;
+ uint8_t kc128[16];
+
+ /* more items are defined in the spec and may be added later */
+ bool more_items; /*< always set this to false */
+};
+struct msgb *gsm0808_create_cipher2(const struct gsm0808_cipher_mode_command *cmc);
+
struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id);
struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause);
struct msgb *gsm0808_create_cipher_reject_ext(enum gsm0808_cause_class class, uint8_t ext);
-struct msgb *gsm0808_create_classmark_request();
+struct msgb *gsm0808_create_classmark_request(void);
struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len,
const uint8_t *cm3, uint8_t cm3_len);
struct msgb *gsm0808_create_sapi_reject_cause(uint8_t link_id, uint16_t cause);
@@ -126,6 +142,9 @@ struct gsm0808_old_bss_to_new_bss_info {
uint8_t field;
} current_channel_type_2;
+ bool last_eutran_plmn_id_present;
+ struct osmo_plmn_id last_eutran_plmn_id;
+
/* more items are defined in the spec and may be added later */
bool more_items; /*< always set this to false */
};
@@ -195,7 +214,12 @@ struct gsm0808_handover_request {
uint8_t global_call_reference_len;
/* more items are defined in the spec and may be added later */
- bool more_items; /*!< always set this to false */
+ bool more_items; /*!< set this to true iff any fields below are used */
+
+ bool kc128_present;
+ uint8_t kc128[16];
+
+ bool more_items2; /*!< always set this to false */
};
struct msgb *gsm0808_create_handover_request(const struct gsm0808_handover_request *params);
@@ -222,8 +246,12 @@ struct gsm0808_handover_request_ack {
const struct sockaddr_storage *aoip_transport_layer;
+ bool more_items; /*!< set this to true iff any fields below are used */
+
+ struct gsm0808_speech_codec_list codec_list_bss_supported; /*< omit when .len == 0 */
+
/* more items are defined in the spec and may be added later */
- bool more_items; /*!< always set this to false */
+ bool more_items2; /*!< always set this to false */
};
struct msgb *gsm0808_create_handover_request_ack2(const struct gsm0808_handover_request_ack *params);
@@ -241,8 +269,8 @@ struct gsm0808_handover_command {
};
struct msgb *gsm0808_create_handover_command(const struct gsm0808_handover_command *params);
-struct msgb *gsm0808_create_handover_detect();
-struct msgb *gsm0808_create_handover_succeeded();
+struct msgb *gsm0808_create_handover_detect(void);
+struct msgb *gsm0808_create_handover_succeeded(void);
struct gsm0808_handover_complete {
bool rr_cause_present;
@@ -255,7 +283,7 @@ struct gsm0808_handover_complete {
bool chosen_encr_alg_present;
uint8_t chosen_encr_alg;
-
+
bool chosen_channel_present;
uint8_t chosen_channel;
@@ -304,10 +332,248 @@ struct gsm0808_handover_performed {
};
struct msgb *gsm0808_create_handover_performed(const struct gsm0808_handover_performed *params);
+/*! 3GPP TS 48.008 §3.2.1.50 VGCS/VBS SETUP */
+struct gsm0808_vgcs_vbs_setup {
+ struct gsm0808_group_callref callref;
+
+ bool priority_present;
+ struct gsm0808_priority priority;
+
+ bool vgcs_feature_flags_present;
+ struct gsm0808_vgcs_feature_flags flags;
+};
+struct msgb *gsm0808_create_vgcs_vbs_setup(const struct gsm0808_vgcs_vbs_setup *params);
+
+/*! 3GPP TS 48.008 §3.2.1.51 VGCS/VBS SETUP ACK */
+struct gsm0808_vgcs_vbs_setup_ack {
+ bool vgcs_feature_flags_present;
+ struct gsm0808_vgcs_feature_flags flags;
+};
+struct msgb *gsm0808_create_vgcs_vbs_setup_ack(const struct gsm0808_vgcs_vbs_setup_ack *params);
+
+/*! 3GPP TS 48.008 §3.2.1.52 VGCS/VBS SETUP REFUSE */
+struct msgb *gsm0808_create_vgcs_vbs_setup_refuse(enum gsm0808_cause cause);
+
+/*! 3GPP TS 48.008 §3.2.1.53 VGCS/VBS ASSIGNMENT REQUEST */
+struct gsm0808_vgcs_vbs_assign_req {
+ struct gsm0808_channel_type channel_type;
+ enum gsm0808_assignment_requirement ass_req;
+ struct gsm0808_cell_id cell_identifier;
+ struct gsm0808_group_callref callref;
+
+ bool priority_present;
+ struct gsm0808_priority priority;
+
+ bool cic_present;
+ uint16_t cic;
+
+ bool downlink_dtx_flag_present;
+ enum gsm0808_downlink_dtx_flag downlink_dtx_flag;
+
+ bool encryption_information_present;
+ struct gsm0808_encrypt_info encryption_information;
+
+ bool vstk_rand_present;
+ uint8_t vstk_rand[5];
+
+ bool vstk_present;
+ uint8_t vstk[16];
+
+ bool cils_present;
+ struct gsm0808_cell_id_list_segment cils;
+
+ bool aoip_transport_layer_present;
+ struct sockaddr_storage aoip_transport_layer;
+
+ bool call_id_present;
+ uint32_t call_id;
+
+ bool codec_list_present;
+ struct gsm0808_speech_codec_list codec_list_msc_preferred;
+};
+struct msgb *gsm0808_create_vgcs_vbs_assign_req(const struct gsm0808_vgcs_vbs_assign_req *params);
+
+/*! 3GPP TS 48.008 §3.2.1.54 VGCS/VBS ASSIGNMENT RESULT */
+struct gsm0808_vgcs_vbs_assign_res {
+ struct gsm0808_channel_type channel_type;
+ struct gsm0808_cell_id cell_identifier;
+
+ bool chosen_channel_present;
+ uint8_t chosen_channel;
+
+ bool cic_present;
+ uint16_t cic;
+
+ bool circuit_pool_present;
+ uint8_t circuit_pool;
+
+ bool aoip_transport_layer_present;
+ struct sockaddr_storage aoip_transport_layer;
+
+ bool codec_present;
+ struct gsm0808_speech_codec codec_msc_chosen;
+
+ bool call_id_present;
+ uint32_t call_id;
+};
+struct msgb *gsm0808_create_vgcs_vbs_assign_res(const struct gsm0808_vgcs_vbs_assign_res *params);
+
+/*! 3GPP TS 48.008 §3.2.1.55 VGCS/VBS ASSIGNMENT FAILURE */
+struct gsm0808_vgcs_vbs_assign_fail {
+ enum gsm0808_cause cause;
+
+ bool circuit_pool_present;
+ uint8_t circuit_pool;
+
+ bool cpl_present;
+ struct gsm0808_circuit_pool_list cpl;
+
+ bool codec_list_present;
+ struct gsm0808_speech_codec_list codec_list_bss_supported;
+};
+struct msgb *gsm0808_create_vgcs_vbs_assign_fail(const struct gsm0808_vgcs_vbs_assign_fail *params);
+
+/*! 3GPP TS 48.008 §3.2.1.57 (VGCS) UPLINK REQUEST */
+struct gsm0808_uplink_request {
+ bool talker_priority_present;
+ enum gsm0808_talker_priority talker_priority;
+
+ bool cell_identifier_present;
+ struct gsm0808_cell_id cell_identifier;
+
+ bool l3_present;
+ struct gsm0808_layer_3_information l3;
+
+ bool mi_present;
+ struct osmo_mobile_identity mi;
+};
+struct msgb *gsm0808_create_uplink_request(const struct gsm0808_uplink_request *params);
+
+/*! 3GPP TS 48.008 §3.2.1.58 (VGCS) UPLINK REQUEST ACKNOWLEDGE */
+struct gsm0808_uplink_request_ack {
+ bool talker_priority_present;
+ enum gsm0808_talker_priority talker_priority;
+
+ bool emerg_set_ind_present;
+
+ bool talker_identity_present;
+ struct gsm0808_talker_identity talker_identity;
+};
+struct msgb *gsm0808_create_uplink_request_ack(const struct gsm0808_uplink_request_ack *params);
+
+/*! 3GPP TS 48.008 §3.2.1.59 (VGCS) UPLINK REQUEST CONFIRM */
+struct gsm0808_uplink_request_cnf {
+ struct gsm0808_cell_id cell_identifier;
+
+ bool talker_identity_present;
+ struct gsm0808_talker_identity talker_identity;
+
+ /* mandatory! */
+ struct gsm0808_layer_3_information l3;
+};
+struct msgb *gsm0808_create_uplink_request_cnf(const struct gsm0808_uplink_request_cnf *params);
+
+/*! 3GPP TS 48.008 §3.2.1.59a (VGCS) UPLINK APPLICATION DATA */
+struct gsm0808_uplink_app_data {
+ struct gsm0808_cell_id cell_identifier;
+ struct gsm0808_layer_3_information l3;
+ bool bt_ind;
+};
+struct msgb *gsm0808_create_uplink_app_data(const struct gsm0808_uplink_app_data *params);
+
+/*! 3GPP TS 48.008 §3.2.1.60 (VGCS) UPLINK RELEASE INDICATION */
+struct gsm0808_uplink_release_ind {
+ enum gsm0808_cause cause;
+
+ bool talker_priority_present;
+ enum gsm0808_talker_priority talker_priority;
+};
+struct msgb *gsm0808_create_uplink_release_ind(const struct gsm0808_uplink_release_ind *params);
+
+/*! 3GPP TS 48.008 §3.2.1.61 (VGCS) UPLINK REJECT COMMAND */
+struct gsm0808_uplink_reject_cmd {
+ enum gsm0808_cause cause;
+
+ bool current_talker_priority_present;
+ enum gsm0808_talker_priority current_talker_priority;
+ bool rejected_talker_priority_present;
+ enum gsm0808_talker_priority rejected_talker_priority;
+
+ bool talker_identity_present;
+ struct gsm0808_talker_identity talker_identity;
+};
+struct msgb *gsm0808_create_uplink_reject_cmd(const struct gsm0808_uplink_reject_cmd *params);
+
+/*! 3GPP TS 48.008 §3.2.1.62 (VGCS) UPLINK RELEASE COMMAND */
+struct msgb *gsm0808_create_uplink_release_cmd(const enum gsm0808_cause cause);
+
+/*! 3GPP TS 48.008 §3.2.1.63 (VGCS) UPLINK SEIZED COMMAND */
+struct gsm0808_uplink_seized_cmd {
+ enum gsm0808_cause cause;
+
+ bool talker_priority_present;
+ enum gsm0808_talker_priority talker_priority;
+
+ bool emerg_set_ind_present;
+
+ bool talker_identity_present;
+ struct gsm0808_talker_identity talker_identity;
+};
+struct msgb *gsm0808_create_uplink_seized_cmd(const struct gsm0808_uplink_seized_cmd *params);
+
+/*! 3GPP TS 48.008 §3.2.1.78 VGCS ADDITIONAL INFORMATION */
+struct msgb *gsm0808_create_vgcs_additional_info(const struct gsm0808_talker_identity *ti);
+
+/*! 3GPP TS 48.008 §3.2.1.79 VGCS/VBS AREA CELL INFO */
+struct gsm0808_vgcs_vbs_area_cell_info {
+ struct gsm0808_cell_id_list_segment cils;
+
+ bool ass_req_present;
+ enum gsm0808_assignment_requirement ass_req;
+};
+struct msgb *gsm0808_create_vgcs_vbs_area_cell_info(const struct gsm0808_vgcs_vbs_area_cell_info *params);
+
+/*! 3GPP TS 48.008 §3.2.1.80 VGCS/VBS ASSIGNMENT STATUS */
+struct gsm0808_vgcs_vbs_assign_stat {
+ /* established cells */
+ bool cils_est_present;
+ struct gsm0808_cell_id_list_segment cils_est;
+
+ /* cells to be established */
+ bool cils_tbe_present;
+ struct gsm0808_cell_id_list_segment cils_tbe;
+
+ /* released cells - no user present */
+ bool cils_rel_present;
+ struct gsm0808_cell_id_list_segment cils_rel;
+
+ /* not established cells - no establishment possible */
+ bool cils_ne_present;
+ struct gsm0808_cell_id_list_segment cils_ne;
+
+ bool cell_status_present;
+ enum gsm0808_vgcs_vbs_cell_status cell_status;
+};
+struct msgb *gsm0808_create_vgcs_vbs_assign_stat(const struct gsm0808_vgcs_vbs_assign_stat *params);
+
+/*! 3GPP TS 48.008 §3.2.1.81 VGCS SMS */
+struct msgb *gsm0808_create_vgcs_sms(const struct gsm0808_sms_to_vgcs *sms);
+
+/*! 3GPP TS 48.008 §3.2.1.82 (VGCS/VBS) NOTIFICATION DATA */
+struct gsm0808_notification_data {
+ struct gsm0808_application_data app_data;
+ struct gsm0808_data_identity data_ident;
+
+ bool msisdn_present;
+ char msisdn[MSISDN_MAXLEN + 1];
+};
+struct msgb *gsm0808_create_notification_data(const struct gsm0808_notification_data *parms);
+
struct msgb *gsm0808_create_dtap(struct msgb *msg, uint8_t link_id);
void gsm0808_prepend_dtap_header(struct msgb *msg, uint8_t link_id);
const struct tlv_definition *gsm0808_att_tlvdef(void);
+extern const struct tlv_definition gsm0808_old_bss_to_new_bss_info_att_tlvdef;
/*! Parse BSSAP TLV structure using \ref tlv_parse */
#define osmo_bssap_tlv_parse(dec, buf, len) tlv_parse(dec, gsm0808_att_tlvdef(), buf, len, 0, 0)
diff --git a/include/osmocom/gsm/gsm0808_lcs.h b/include/osmocom/gsm/gsm0808_lcs.h
new file mode 100644
index 00000000..71665013
--- /dev/null
+++ b/include/osmocom/gsm/gsm0808_lcs.h
@@ -0,0 +1,48 @@
+/*! \addtogroup gsm0808
+ * @{
+ * \file gsm0808_lcs.h
+ *
+ * Declarations that depend on both gsm0808.h and bssmap_le.h: LCS related message coding.
+ * (This file prevents circular dependency between struct definitions for BSSMAP messages, since BSSMAP references
+ * struct lcs_cause and struct bssmap_le_location_type, and BSSMAP-LE references gsm0808_cause.
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+#pragma once
+
+#include <osmocom/gsm/gsm0808.h>
+#include <osmocom/gsm/bssmap_le.h>
+
+struct gsm0808_perform_location_request {
+ struct bssmap_le_location_type location_type;
+ struct osmo_mobile_identity imsi;
+
+ bool more_items; /*!< always set this to false */
+};
+struct msgb *gsm0808_create_perform_location_request(const struct gsm0808_perform_location_request *params);
+
+struct gsm0808_perform_location_response {
+ bool location_estimate_present;
+ union gad_raw location_estimate;
+
+ struct lcs_cause_ie lcs_cause;
+};
+struct msgb *gsm0808_create_perform_location_response(const struct gsm0808_perform_location_response *params);
+
+int gsm0808_enc_lcs_cause(struct msgb *msg, const struct lcs_cause_ie *lcs_cause);
+struct msgb *gsm0808_create_perform_location_abort(const struct lcs_cause_ie *lcs_cause);
+
+/*! @} */
diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h
index 59db6edc..dbe2abf9 100644
--- a/include/osmocom/gsm/gsm0808_utils.h
+++ b/include/osmocom/gsm/gsm0808_utils.h
@@ -31,6 +31,8 @@ struct sockaddr_storage;
#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
@@ -44,6 +46,9 @@ union gsm0808_cell_id_u {
uint16_t ci;
struct osmo_location_area_id lai_and_lac;
uint16_t lac;
+ struct osmo_service_area_id sai;
+ /* osmocom specific: */
+ struct osmo_cell_global_id_ps global_ps;
};
/*! Parsed representation of Cell Identifier IE (3GPP TS 48.008 3.2.2.17) */
@@ -59,6 +64,164 @@ struct gsm0808_cell_id_list2 {
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 */
@@ -108,12 +271,17 @@ uint8_t gsm0808_enc_lcls(struct msgb *msg, const struct osmo_lcls *lcls);
int gsm0808_dec_lcls(struct osmo_lcls *lcls, const struct tlv_parsed *tp);
uint8_t gsm0808_enc_speech_codec(struct msgb *msg,
- const struct gsm0808_speech_codec *sc);
+ const struct gsm0808_speech_codec *sc)
+ OSMO_DEPRECATED("use gsm0808_enc_speech_codec2() instead");
+int gsm0808_enc_speech_codec2(struct msgb *msg,
+ const struct gsm0808_speech_codec *sc);
int gsm0808_dec_speech_codec(struct gsm0808_speech_codec *sc,
const uint8_t *elem, uint8_t len);
uint8_t gsm0808_enc_speech_codec_list(struct msgb *msg,
- const struct gsm0808_speech_codec_list
- *scl);
+ const struct gsm0808_speech_codec_list *scl)
+ OSMO_DEPRECATED("use gsm0808_enc_speech_codec_list2() instead");
+int gsm0808_enc_speech_codec_list2(struct msgb *msg,
+ const struct gsm0808_speech_codec_list *scl);
int gsm0808_dec_speech_codec_list(struct gsm0808_speech_codec_list *scl,
const uint8_t *elem, uint8_t len);
uint8_t gsm0808_enc_channel_type(struct msgb *msg,
@@ -124,6 +292,8 @@ uint8_t gsm0808_enc_encrypt_info(struct msgb *msg,
const struct gsm0808_encrypt_info *ei);
int gsm0808_dec_encrypt_info(struct gsm0808_encrypt_info *ei,
const uint8_t *elem, uint8_t len);
+int gsm0808_enc_kc128(struct msgb *msg, const uint8_t *kc128);
+int gsm0808_dec_kc128(uint8_t *kc128, const uint8_t *elem, uint8_t len);
uint8_t gsm0808_enc_cell_id_list2(struct msgb *msg, const struct gsm0808_cell_id_list2 *cil);
uint8_t gsm0808_enc_cell_id_list(struct msgb *msg,
const struct gsm0808_cell_id_list *cil)
@@ -178,37 +348,34 @@ static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type)
static inline enum gsm0808_permitted_speech gsm0808_permitted_speech(enum gsm_chan_t type,
enum gsm48_chan_mode mode)
{
- switch (mode) {
- case GSM48_CMODE_SPEECH_V1:
- switch (type) {
- case GSM_LCHAN_TCH_F:
- return GSM0808_PERM_FR1;
- case GSM_LCHAN_TCH_H:
- return GSM0808_PERM_HR1;
- default:
- return 0;
- }
- case GSM48_CMODE_SPEECH_EFR:
- switch (type) {
- case GSM_LCHAN_TCH_F:
- return GSM0808_PERM_FR2;
- case GSM_LCHAN_TCH_H:
- return GSM0808_PERM_HR2;
- default:
- return 0;
- }
- case GSM48_CMODE_SPEECH_AMR:
- switch (type) {
- case GSM_LCHAN_TCH_F:
- return GSM0808_PERM_FR3;
- case GSM_LCHAN_TCH_H:
- return GSM0808_PERM_HR3;
- default:
- return 0;
- }
+#define MODE_TYPE(mode, type) ((mode << 16) | type)
+
+ switch (MODE_TYPE(mode, type)) {
+ case MODE_TYPE(GSM48_CMODE_SPEECH_V1, GSM_LCHAN_TCH_F):
+ return GSM0808_PERM_FR1;
+ case MODE_TYPE(GSM48_CMODE_SPEECH_V1, GSM_LCHAN_TCH_H):
+ return GSM0808_PERM_HR1;
+ case MODE_TYPE(GSM48_CMODE_SPEECH_EFR, GSM_LCHAN_TCH_F):
+ return GSM0808_PERM_FR2;
+ case MODE_TYPE(GSM48_CMODE_SPEECH_EFR, GSM_LCHAN_TCH_H):
+ return GSM0808_PERM_HR2; /* (deprecated) */
+ case MODE_TYPE(GSM48_CMODE_SPEECH_AMR, GSM_LCHAN_TCH_F):
+ return GSM0808_PERM_FR3;
+ case MODE_TYPE(GSM48_CMODE_SPEECH_AMR, GSM_LCHAN_TCH_H):
+ return GSM0808_PERM_HR3;
+ case MODE_TYPE(GSM48_CMODE_SPEECH_V4, GSM_LCHAN_TCH_F):
+ return GSM0808_PERM_FR4;
+ case MODE_TYPE(GSM48_CMODE_SPEECH_V4, GSM_LCHAN_TCH_H):
+ return GSM0808_PERM_HR4;
+ case MODE_TYPE(GSM48_CMODE_SPEECH_V5, GSM_LCHAN_TCH_F):
+ return GSM0808_PERM_FR5; /* FR only */
+ case MODE_TYPE(GSM48_CMODE_SPEECH_V6, GSM_LCHAN_TCH_H):
+ return GSM0808_PERM_HR6; /* HR only */
default:
return 0;
}
+
+#undef MODE_TYPE
}
/*! Return 3GPP TS 48.008 3.2.2.33 Chosen Channel. */
@@ -220,6 +387,9 @@ static inline uint8_t gsm0808_chosen_channel(enum gsm_chan_t type, enum gsm48_ch
case GSM48_CMODE_SPEECH_V1:
case GSM48_CMODE_SPEECH_EFR:
case GSM48_CMODE_SPEECH_AMR:
+ case GSM48_CMODE_SPEECH_V4:
+ case GSM48_CMODE_SPEECH_V5:
+ case GSM48_CMODE_SPEECH_V6:
channel_mode = 0x9;
break;
case GSM48_CMODE_SIGN:
@@ -237,6 +407,33 @@ static inline uint8_t gsm0808_chosen_channel(enum gsm_chan_t type, enum gsm48_ch
case GSM48_CMODE_DATA_3k6:
channel_mode = 0xd;
break;
+ case GSM48_CMODE_DATA_29k0:
+ channel_mode = 0x1;
+ break;
+ case GSM48_CMODE_DATA_32k0:
+ channel_mode = 0x2;
+ break;
+ case GSM48_CMODE_DATA_43k5:
+ channel_mode = 0x3;
+ break;
+ case GSM48_CMODE_DATA_43k5_14k5:
+ channel_mode = 0x4;
+ break;
+ case GSM48_CMODE_DATA_29k0_14k5:
+ channel_mode = 0x5;
+ break;
+ case GSM48_CMODE_DATA_43k5_29k0:
+ channel_mode = 0x6;
+ break;
+ case GSM48_CMODE_DATA_14k5_43k5:
+ channel_mode = 0x7;
+ break;
+ case GSM48_CMODE_DATA_14k5_29k0:
+ channel_mode = 0xa;
+ break;
+ case GSM48_CMODE_DATA_29k0_43k5:
+ channel_mode = 0xf;
+ break;
default:
return 0;
}
@@ -254,6 +451,7 @@ static inline uint8_t gsm0808_chosen_channel(enum gsm_chan_t type, enum gsm48_ch
case GSM_LCHAN_TCH_H:
channel = 0x9;
break;
+ /* TODO: more than 1 TCHs? */
default:
return 0;
}
@@ -265,4 +463,23 @@ const char *gsm0808_channel_type_name(const struct gsm0808_channel_type *ct);
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/include/osmocom/gsm/gsm23003.h b/include/osmocom/gsm/gsm23003.h
index 69f00f68..4070581f 100644
--- a/include/osmocom/gsm/gsm23003.h
+++ b/include/osmocom/gsm/gsm23003.h
@@ -30,6 +30,14 @@ struct osmo_cell_global_id {
uint16_t cell_identity;
};
+/* 3GPP TS 48.018:
+ * 8c.1.4.1.1 GERAN BSS identification (RIM)
+ * sec 11.3.9 Cell Identifier */
+struct osmo_cell_global_id_ps {
+ struct osmo_routing_area_id rai;
+ uint16_t cell_identity;
+};
+
/*! Bitmask of items contained in a struct osmo_cell_global_id.
* See also gsm0808_cell_id_to_cgi().
*/
@@ -37,6 +45,7 @@ enum osmo_cgi_part {
OSMO_CGI_PART_PLMN = 1,
OSMO_CGI_PART_LAC = 2,
OSMO_CGI_PART_CI = 4,
+ OSMO_CGI_PART_RAC = 8,
};
/* Actually defined in 3GPP TS 48.008 3.2.2.27 Cell Identifier List,
@@ -117,10 +126,21 @@ char *osmo_plmn_name_c(const void *ctx, const struct osmo_plmn_id *plmn);
const char *osmo_lai_name(const struct osmo_location_area_id *lai);
char *osmo_lai_name_buf(char *buf, size_t buf_len, const struct osmo_location_area_id *lai);
char *osmo_lai_name_c(const void *ctx, const struct osmo_location_area_id *lai);
+const char *osmo_rai_name2(const struct osmo_routing_area_id *rai);
+char *osmo_rai_name2_buf(char *buf, size_t buf_len, const struct osmo_routing_area_id *rai);
+char *osmo_rai_name2_c(const void *ctx, const struct osmo_routing_area_id *rai);
const char *osmo_cgi_name(const struct osmo_cell_global_id *cgi);
const char *osmo_cgi_name2(const struct osmo_cell_global_id *cgi);
char *osmo_cgi_name_buf(char *buf, size_t buf_len, const struct osmo_cell_global_id *cgi);
char *osmo_cgi_name_c(const void *ctx, const struct osmo_cell_global_id *cgi);
+const char *osmo_cgi_ps_name(const struct osmo_cell_global_id_ps *cgi_ps);
+const char *osmo_cgi_ps_name2(const struct osmo_cell_global_id_ps *cgi_ps);
+char *osmo_cgi_ps_name_buf(char *buf, size_t buf_len, const struct osmo_cell_global_id_ps *cgi_ps);
+char *osmo_cgi_ps_name_c(const void *ctx, const struct osmo_cell_global_id_ps *cgi_ps);
+const char *osmo_sai_name(const struct osmo_service_area_id *sai);
+const char *osmo_sai_name2(const struct osmo_service_area_id *sai);
+char *osmo_sai_name_buf(char *buf, size_t buf_len, const struct osmo_service_area_id *sai);
+char *osmo_sai_name_c(const void *ctx, const struct osmo_service_area_id *sai);
const char *osmo_gummei_name(const struct osmo_gummei *gummei);
char *osmo_gummei_name_buf(char *buf, size_t buf_len, const struct osmo_gummei *gummei);
char *osmo_gummei_name_c(const void *ctx, const struct osmo_gummei *gummei);
@@ -144,7 +164,9 @@ static inline int osmo_mcc_from_str(const char *mcc_str, uint16_t *mcc)
int osmo_mnc_cmp(uint16_t a_mnc, bool a_mnc_3_digits, uint16_t b_mnc, bool b_mnc_3_digits);
int osmo_plmn_cmp(const struct osmo_plmn_id *a, const struct osmo_plmn_id *b);
int osmo_lai_cmp(const struct osmo_location_area_id *a, const struct osmo_location_area_id *b);
+int osmo_rai_cmp(const struct osmo_routing_area_id *a, const struct osmo_routing_area_id *b);
int osmo_cgi_cmp(const struct osmo_cell_global_id *a, const struct osmo_cell_global_id *b);
+int osmo_cgi_ps_cmp(const struct osmo_cell_global_id_ps *a, const struct osmo_cell_global_id_ps *b);
int osmo_gen_home_network_domain(char *out, const struct osmo_plmn_id *plmn);
int osmo_parse_home_network_domain(struct osmo_plmn_id *out, const char *in);
diff --git a/include/osmocom/gsm/gsm29118.h b/include/osmocom/gsm/gsm29118.h
index e81cce4c..33c40d36 100644
--- a/include/osmocom/gsm/gsm29118.h
+++ b/include/osmocom/gsm/gsm29118.h
@@ -17,10 +17,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#pragma once
diff --git a/include/osmocom/gsm/gsm29205.h b/include/osmocom/gsm/gsm29205.h
index 95754567..6c845fb9 100644
--- a/include/osmocom/gsm/gsm29205.h
+++ b/include/osmocom/gsm/gsm29205.h
@@ -15,10 +15,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#pragma once
@@ -37,6 +33,6 @@ struct osmo_gcr_parsed {
uint8_t cr[5]; /** Call Reference ID */
};
-uint8_t osmo_enc_gcr(struct msgb *msg, const struct osmo_gcr_parsed *g) OSMO_DEPRECATED_OUTSIDE_LIBOSMOCORE;
-int osmo_dec_gcr(struct osmo_gcr_parsed *gcr, const uint8_t *elem, uint8_t len) OSMO_DEPRECATED_OUTSIDE_LIBOSMOCORE;
+uint8_t osmo_enc_gcr(struct msgb *msg, const struct osmo_gcr_parsed *g);
+int osmo_dec_gcr(struct osmo_gcr_parsed *gcr, const uint8_t *elem, uint8_t len);
bool osmo_gcr_eq(const struct osmo_gcr_parsed *gcr1, const struct osmo_gcr_parsed *gcr2);
diff --git a/include/osmocom/gsm/gsm44021.h b/include/osmocom/gsm/gsm44021.h
new file mode 100644
index 00000000..8f89c56b
--- /dev/null
+++ b/include/osmocom/gsm/gsm44021.h
@@ -0,0 +1,8 @@
+#pragma once
+#include <osmocom/isdn/v110.h>
+
+int osmo_csd_12k_6k_decode_frame(struct osmo_v110_decoded_frame *fr, const ubit_t *ra_bits, size_t n_bits);
+int osmo_csd_12k_6k_encode_frame(ubit_t *ra_bits, size_t ra_bits_size, const struct osmo_v110_decoded_frame *fr);
+int osmo_csd_3k6_decode_frame(struct osmo_v110_decoded_frame *fr, const ubit_t *ra_bits, size_t n_bits);
+int osmo_csd_3k6_encode_frame(ubit_t *ra_bits, size_t ra_bits_size, const struct osmo_v110_decoded_frame *fr);
+void osmo_csd_ubit_dump(FILE *outf, const ubit_t *fr, size_t in_len);
diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h
index f772f4a1..00fb6f40 100644
--- a/include/osmocom/gsm/gsm48.h
+++ b/include/osmocom/gsm/gsm48.h
@@ -20,7 +20,9 @@
* To mark an invalid / unset MNC, this value shall be used. */
#define GSM_MCC_MNC_INVALID 0xFFFF
-/* A parsed GPRS routing area */
+/* A parsed GPRS routing area.
+ * Preferably use struct osmo_routing_area_id, it is better integrated with API like osmo_plmn_cmp().
+ */
struct gprs_ra_id {
uint16_t mcc;
uint16_t mnc;
@@ -35,6 +37,7 @@ extern const struct tlv_definition gsm48_mm_att_tlvdef;
const char *gsm48_cc_state_name(uint8_t state);
const char *gsm48_cc_msg_name(uint8_t msgtype);
const char *gsm48_rr_msg_name(uint8_t msgtype);
+const char *gsm48_rr_short_pd_msg_name(uint8_t msgtype);
const char *rr_cause_name(uint8_t cause);
const char *osmo_rai_name(const struct gprs_ra_id *rai);
char *osmo_rai_name_buf(char *buf, size_t buf_len, const struct gprs_ra_id *rai);
@@ -95,17 +98,23 @@ char *osmo_mobile_identity_to_str_c(void *ctx, const struct osmo_mobile_identity
int osmo_mobile_identity_cmp(const struct osmo_mobile_identity *a, const struct osmo_mobile_identity *b);
int osmo_mobile_identity_decode(struct osmo_mobile_identity *mi, const uint8_t *mi_data, uint8_t mi_len,
bool allow_hex);
+int osmo_mobile_identity_decode_from_l3_buf(struct osmo_mobile_identity *mi, const uint8_t *l3_data, size_t l3_len,
+ bool allow_hex);
int osmo_mobile_identity_decode_from_l3(struct osmo_mobile_identity *mi, struct msgb *msg, bool allow_hex);
int osmo_mobile_identity_encoded_len(const struct osmo_mobile_identity *mi, int *mi_digits);
int osmo_mobile_identity_encode_buf(uint8_t *buf, size_t buflen, const struct osmo_mobile_identity *mi, bool allow_hex);
int osmo_mobile_identity_encode_msgb(struct msgb *msg, const struct osmo_mobile_identity *mi, bool allow_hex);
/* Parse Routeing Area Identifier */
+int osmo_routing_area_id_decode(struct osmo_routing_area_id *dst, const uint8_t *ra_data, size_t ra_data_len);
+int osmo_routing_area_id_encode_buf(uint8_t *buf, size_t buflen, const struct osmo_routing_area_id *src);
+int osmo_routing_area_id_encode_msgb(struct msgb *msg, const struct osmo_routing_area_id *src);
void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf);
void gsm48_encode_ra(struct gsm48_ra_id *out, const struct gprs_ra_id *raid);
int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid) OSMO_DEPRECATED("Use gsm48_encode_ra() instead");
+bool gsm48_ra_equal(const struct gprs_ra_id *raid1, const struct gprs_ra_id *raid2);
-int gsm48_number_of_paging_subchannels(struct gsm48_control_channel_descr *chan_desc);
+int gsm48_number_of_paging_subchannels(const struct gsm48_control_channel_descr *chan_desc);
void gsm48_mcc_mnc_to_bcd(uint8_t *bcd_dst, uint16_t mcc, uint16_t mnc)
OSMO_DEPRECATED("Use osmo_plmn_to_bcd() instead, to not lose leading zeros in the MNC");
@@ -117,3 +126,6 @@ struct gsm48_hdr *gsm48_push_l3hdr(struct msgb *msg,
#define gsm48_push_l3hdr_tid(msg, pdisc, tid, msg_type) \
gsm48_push_l3hdr(msg, (pdisc & 0x0f) | (tid << 4), msg_type)
+
+enum gsm48_chan_mode gsm48_chan_mode_to_vamos(enum gsm48_chan_mode mode);
+enum gsm48_chan_mode gsm48_chan_mode_to_non_vamos(enum gsm48_chan_mode mode);
diff --git a/include/osmocom/gsm/gsm48_ie.h b/include/osmocom/gsm/gsm48_ie.h
index 339aa136..4768283f 100644
--- a/include/osmocom/gsm/gsm48_ie.h
+++ b/include/osmocom/gsm/gsm48_ie.h
@@ -117,5 +117,10 @@ struct gsm_sysinfo_freq {
};
/* decode "Cell Channel Description" (10.5.2.1b) and other frequency lists */
-int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd,
- uint8_t len, uint8_t mask, uint8_t frqt);
+int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f,
+ const uint8_t *cd, uint8_t len,
+ uint8_t mask, uint8_t frqt);
+
+/* decode "CSN.1 encoded Classmark 3" (10.5.1.7) */
+int gsm48_decode_classmark3(struct gsm48_classmark3 *classmark3_out,
+ const uint8_t *classmark3, size_t classmark3_len);
diff --git a/include/osmocom/gsm/gsm48_rest_octets.h b/include/osmocom/gsm/gsm48_rest_octets.h
index d3bb878e..cdb2e807 100644
--- a/include/osmocom/gsm/gsm48_rest_octets.h
+++ b/include/osmocom/gsm/gsm48_rest_octets.h
@@ -2,7 +2,7 @@
#include <stdbool.h>
#include <osmocom/gsm/sysinfo.h>
-#include <osmocom/gprs/protocol/gsm_04_60.h>
+#include <osmocom/gsm/protocol/gsm_44_060.h>
/* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018 Table 10.5.2.33b.1:
4-bit index is used (2#1111 = 10#15) */
@@ -13,6 +13,9 @@
/* generate SI1 rest octets */
int osmo_gsm48_rest_octets_si1_encode(uint8_t *data, uint8_t *nch_pos, int is1800_net);
+int osmo_gsm48_si1ro_nch_pos_decode(uint8_t value, uint8_t *num_blocks, uint8_t *first_block);
+int osmo_gsm48_si1ro_nch_pos_encode(uint8_t num_blocks, uint8_t first_block);
+
int osmo_gsm48_rest_octets_si2quater_encode(uint8_t *data, uint8_t si2q_index, uint8_t si2q_count,
const uint16_t *uarfcn_list, size_t *u_offset,
size_t uarfcn_length, uint16_t *scramble_list,
@@ -120,8 +123,12 @@ struct osmo_gsm48_si13_info {
uint8_t prio_acc_thr;
};
-/* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */
+/* Parse/Generate SI13 Rest Octests (Chapter 10.5.2.37b) */
+int osmo_gsm48_rest_octets_si13_decode(struct osmo_gsm48_si13_info *si13, const uint8_t *data);
int osmo_gsm48_rest_octets_si13_encode(uint8_t *data, const struct osmo_gsm48_si13_info *si13);
/* Parse SI3 Rest Octets */
void osmo_gsm48_rest_octets_si3_decode(struct osmo_gsm48_si_ro_info *si3, const uint8_t *data);
+
+/* Parse SI4 Rest Octets */
+void osmo_gsm48_rest_octets_si4_decode(struct osmo_gsm48_si_ro_info *si4, const uint8_t *data, int len);
diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h
index de634348..b250c594 100644
--- a/include/osmocom/gsm/gsm_utils.h
+++ b/include/osmocom/gsm/gsm_utils.h
@@ -17,10 +17,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#pragma once
@@ -37,6 +33,7 @@
} while (0)
#define GSM_MAX_FN (26*51*2048)
+#define GSM_FN_UNSET 0xFFFFFFFF
/* Max length of random identifier which can be requested via osmo_get_rand_id() */
#define OSMO_MAX_RAND_ID_LEN 16
@@ -110,7 +107,10 @@ int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets_w
int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets_written);
/* the four functions below are helper functions and here for the unit test */
-int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding);
+int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
+ OSMO_DEPRECATED("This function is unable to handle more than 255 septets, "
+ "use gsm_septet_pack() instead.");
+int gsm_septet_pack(uint8_t *result, const uint8_t *rdata, size_t septet_len, uint8_t padding);
int gsm_septet_encode(uint8_t *result, const char *data);
uint8_t gsm_get_octet_len(const uint8_t sept_len);
int gsm_7bit_decode_n_hdr(char *decoded, size_t n, const uint8_t *user_data, uint8_t length, uint8_t ud_hdr_ind);
@@ -153,6 +153,13 @@ static inline int rach_max_trans_raw2val(int raw) {
const int tbl[4] = { 1, 2, 4, 7 };
return tbl[raw & 3];
}
+static inline uint8_t rach_tx_integer_raw2val(uint8_t raw) {
+ const int tbl[6] = { 14, 16, 20, 25, 32, 50 };
+ raw &= 0x0f;
+ if (raw <= 9)
+ return raw + 3;
+ return tbl[raw - 10];
+}
#define ARFCN_PCS 0x8000
#define ARFCN_UPLINK 0x4000
@@ -174,13 +181,21 @@ void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn);
char *gsm_fn_as_gsmtime_str(uint32_t fn);
/* Convert from GSM time to frame number */
-uint32_t gsm_gsmtime2fn(struct gsm_time *time);
+uint32_t gsm_gsmtime2fn(const struct gsm_time *time);
/* Returns static buffer with string representation of a GSM Time */
char *osmo_dump_gsmtime(const struct gsm_time *tm);
char *osmo_dump_gsmtime_buf(char *buf, size_t buf_len, const struct gsm_time *tm);
char *osmo_dump_gsmtime_c(const void *ctx, const struct gsm_time *tm);
+/* Reduced Frame Number (3GPP TS 44.018 §10.5.2.38) */
+#define GSM_RFN_MODULUS 42432
+uint32_t gsm_rfn2fn(uint16_t rfn, uint32_t curr_fn);
+static inline uint16_t gsm_fn2rfn(uint32_t fn)
+{
+ return fn % GSM_RFN_MODULUS;
+}
+
/* GSM TS 03.03 Chapter 2.6 */
enum gprs_tlli_type {
TLLI_LOCAL,
@@ -210,9 +225,11 @@ enum gsm_phys_chan_config {
GSM_PCHAN_UNKNOWN,
GSM_PCHAN_CCCH_SDCCH4_CBCH,
GSM_PCHAN_SDCCH8_SACCH8C_CBCH,
- GSM_PCHAN_TCH_F_TCH_H_PDCH,
+ GSM_PCHAN_OSMO_DYN,
_GSM_PCHAN_MAX
};
+/* Backward compatibility with older naming: */
+#define GSM_PCHAN_TCH_F_TCH_H_PDCH GSM_PCHAN_OSMO_DYN
/* Osmocom internal, not part of any gsm spec */
enum gsm_chan_t {
diff --git a/include/osmocom/gsm/gsup.h b/include/osmocom/gsm/gsup.h
index 56d7a309..6ad72d28 100644
--- a/include/osmocom/gsm/gsup.h
+++ b/include/osmocom/gsm/gsup.h
@@ -37,9 +37,13 @@
*
*/
#pragma once
+#if (!EMBEDDED)
#include <stdint.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/core/defs.h>
+#include <osmocom/core/endian.h>
+#include <osmocom/core/socket.h>
#include <osmocom/gsm/gsup_sms.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/gsm/protocol/gsm_03_40.h>
@@ -57,8 +61,7 @@
/*! Maximum number of octets encoding MSISDN in BCD format */
#define OSMO_GSUP_MAX_MSISDN_LEN 9
#define OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN 43 /* TS 24.008 10.5.4.7 */
-
-#define OSMO_GSUP_PDP_TYPE_SIZE 2
+#define OSMO_GSUP_MAX_PCO_LEN 251
/*! Information Element Identifiers for GSUP IEs */
enum osmo_gsup_iei {
@@ -71,12 +74,14 @@ enum osmo_gsup_iei {
OSMO_GSUP_FREEZE_PTMSI_IE = 0x07,
OSMO_GSUP_MSISDN_IE = 0x08,
OSMO_GSUP_HLR_NUMBER_IE = 0x09,
- OSMO_GSUP_MESSAGE_CLASS_IE = 0x0a,
+ OSMO_GSUP_MESSAGE_CLASS_IE = 0x0a,
OSMO_GSUP_PDP_CONTEXT_ID_IE = 0x10,
- OSMO_GSUP_PDP_TYPE_IE = 0x11,
+ OSMO_GSUP_PDP_ADDRESS_IE = 0x11,
+#define OSMO_GSUP_PDP_TYPE_IE OSMO_GSUP_PDP_ADDRESS_IE /* Backward compat */
OSMO_GSUP_ACCESS_POINT_NAME_IE = 0x12,
OSMO_GSUP_PDP_QOS_IE = 0x13,
OSMO_GSUP_CHARG_CHAR_IE = 0x14,
+ OSMO_GSUP_PCO_IE = 0x15,
OSMO_GSUP_RAND_IE = 0x20,
OSMO_GSUP_SRES_IE = 0x21,
OSMO_GSUP_KC_IE = 0x22,
@@ -198,6 +203,10 @@ enum osmo_gsup_message_type {
OSMO_GSUP_MSGT_E_ABORT = 0b01001011,
OSMO_GSUP_MSGT_ROUTING_ERROR = 0b01001110,
+
+ OSMO_GSUP_MSGT_EPDG_TUNNEL_REQUEST = 0b01010000,
+ OSMO_GSUP_MSGT_EPDG_TUNNEL_ERROR = 0b01010001,
+ OSMO_GSUP_MSGT_EPDG_TUNNEL_RESULT = 0b01010010,
};
#define OSMO_GSUP_MSGT_E_ROUTING_ERROR OSMO_GSUP_MSGT_ROUTING_ERROR
@@ -256,8 +265,20 @@ osmo_gsup_session_state_name(enum osmo_gsup_session_state val)
struct osmo_gsup_pdp_info {
unsigned int context_id;
int have_info;
- /*! Type of PDP context */
- uint16_t pdp_type;
+ /*! Type of PDP context, 3GPP TS 29.060, 7.7.27 */
+ union {
+ uint16_t pdp_type OSMO_DEPRECATED("use pdp_type_org and pdp_type_nr instead");
+ struct {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t pdp_type_nr; /* enum gsm48_pdp_type_nr */
+ uint8_t pdp_type_org; /* enum gsm48_pdp_type_org */
+#elif OSMO_IS_BIG_ENDIAN
+ uint8_t pdp_type_org; /* enum gsm48_pdp_type_org */
+ uint8_t pdp_type_nr; /* enum gsm48_pdp_type_nr */
+#endif
+ };
+ };
+ struct osmo_sockaddr pdp_address[2];
/*! APN information, still in encoded form. Can be NULL if no
* APN information included */
const uint8_t *apn_enc;
@@ -281,6 +302,7 @@ enum osmo_gsup_message_class {
OSMO_GSUP_MESSAGE_CLASS_SMS = 2,
OSMO_GSUP_MESSAGE_CLASS_USSD = 3,
OSMO_GSUP_MESSAGE_CLASS_INTER_MSC = 4,
+ OSMO_GSUP_MESSAGE_CLASS_IPSEC_EPDG = 5,
/* Keep this as last entry with a value of max(enum osmo_gsup_message_class) + 1.
* This value shall serve as the size for an array to aid de-muxing all known GSUP classes. */
OSMO_GSUP_MESSAGE_CLASS_ARRAYSIZE
@@ -386,6 +408,12 @@ struct osmo_gsup_message {
enum osmo_rat_type current_rat_type;
enum osmo_rat_type supported_rat_types[8]; /*!< arbitrary choice */
size_t supported_rat_types_len;
+
+ /*! PCO protocol option 3GPP TS 24.008 10.5.6.3 / Table 10.5.136. PCO contains Octet 3-ZA */
+ const uint8_t *pco;
+ /*! Number of bytes of the PCO. */
+ size_t pco_len;
+
};
int osmo_gsup_decode(const uint8_t *data, size_t data_len,
@@ -394,4 +422,5 @@ int osmo_gsup_encode(struct msgb *msg, const struct osmo_gsup_message *gsup_msg)
int osmo_gsup_get_err_msg_type(enum osmo_gsup_message_type type_in)
OSMO_DEPRECATED("Use OSMO_GSUP_TO_MSGT_ERROR() instead");
+#endif /* (!EMBEDDED) */
/*! @} */
diff --git a/include/osmocom/gsm/i460_mux.h b/include/osmocom/gsm/i460_mux.h
index 8e392434..7c2f4af3 100644
--- a/include/osmocom/gsm/i460_mux.h
+++ b/include/osmocom/gsm/i460_mux.h
@@ -1,121 +1,2 @@
-/*! \file i460_mux.h
- * ITU-T I.460 sub-channel multiplexer + demultiplexer */
-/*
- * (C) 2020 by Harald Welte <laforge@gnumonks.org>
- *
- * SPDX-License-Identifier: GPL-2.0+
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
#pragma once
-#include <stdint.h>
-#include <osmocom/core/bits.h>
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/msgb.h>
-
-/* I.460 sub-slot rate */
-enum osmo_i460_rate {
- OSMO_I460_RATE_NONE, /* disabled */
- OSMO_I460_RATE_64k,
- OSMO_I460_RATE_32k,
- OSMO_I460_RATE_16k,
- OSMO_I460_RATE_8k,
-};
-
-struct osmo_i460_subchan;
-
-typedef void (*out_cb_bits_t)(struct osmo_i460_subchan *schan, void *user_data,
- const ubit_t *bits, unsigned int num_bits);
-typedef void (*out_cb_bytes_t)(struct osmo_i460_subchan *schan, void *user_data,
- const uint8_t *bytes, unsigned int num_bytes);
-
-struct osmo_i460_subchan_demux {
- /*! bit-buffer for output bits */
- uint8_t *out_bitbuf;
- /*! size of out_bitbuf in bytes */
- unsigned int out_bitbuf_size;
- /*! offset of next bit to be written in out_bitbuf */
- unsigned int out_idx;
- /*! callback to be called once we have received out_bitbuf_size bits */
- out_cb_bits_t out_cb_bits;
- out_cb_bytes_t out_cb_bytes;
- void *user_data;
-};
-
-typedef void (*in_cb_queue_empty_t)(struct osmo_i460_subchan *schan, void *user_data);
-
-struct osmo_i460_subchan_mux {
- /*! list of to-be-transmitted message buffers */
- struct llist_head tx_queue;
- in_cb_queue_empty_t in_cb_queue_empty;
- void *user_data;
-};
-
-struct osmo_i460_subchan {
- struct osmo_i460_timeslot *ts; /* back-pointer */
- enum osmo_i460_rate rate; /* 8/16/32/64k */
- uint8_t bit_offset; /* bit offset inside each byte of the B-channel */
- struct osmo_i460_subchan_demux demux;
- struct osmo_i460_subchan_mux mux;
-};
-
-struct osmo_i460_timeslot {
- struct osmo_i460_subchan schan[8];
-};
-
-/*! description of a sub-channel; passed by caller */
-struct osmo_i460_schan_desc {
- enum osmo_i460_rate rate;
- uint8_t bit_offset;
- struct {
- /* size (in bits) of the internal buffer; determines granularity */
- size_t num_bits;
- /*! call-back function called whenever we received num_bits */
- out_cb_bits_t out_cb_bits;
- /*! out_cb_bytes call-back function called whenever we received num_bits.
- * The user is usually expected to provide either out_cb_bits or out_cb_bytes. If only
- * out_cb_bits is provided, output data will always be provided as unpacked bits; if only
- * out_cb_bytes is provided, output data will always be provided as packet bits (bytes). If
- * both are provided, it is up to the I.460 multiplex to decide if it calls either of the two,
- * depending on what can be provided without extra conversion. */
- out_cb_bytes_t out_cb_bytes;
- /* opaque user data pointer to pass to out_cb */
- void *user_data;
- } demux;
-
- struct {
- /* call-back function whenever the muxer requires more input data from the sub-channels,
- * but has nothing enqueued yet. A typical function would then call osmo_i460_mux_enqueue() */
- in_cb_queue_empty_t in_cb_queue_empty;
- /* opaque user data pointer to pass to in_cb */
- void *user_data;
- } mux;
-};
-
-void osmo_i460_demux_in(struct osmo_i460_timeslot *ts, const uint8_t *data, size_t data_len);
-
-void osmo_i460_mux_enqueue(struct osmo_i460_subchan *schan, struct msgb *msg);
-int osmo_i460_mux_out(struct osmo_i460_timeslot *ts, uint8_t *out, size_t out_len);
-
-void osmo_i460_ts_init(struct osmo_i460_timeslot *ts);
-
-struct osmo_i460_subchan *
-osmo_i460_subchan_add(void *ctx, struct osmo_i460_timeslot *ts, const struct osmo_i460_schan_desc *chd);
-
-void osmo_i460_subchan_del(struct osmo_i460_subchan *schan);
-
-/*! @} */
+#include <osmocom/isdn/i460_mux.h>
diff --git a/include/osmocom/gsm/ipa.h b/include/osmocom/gsm/ipa.h
index 93cb1bf1..851b58e0 100644
--- a/include/osmocom/gsm/ipa.h
+++ b/include/osmocom/gsm/ipa.h
@@ -29,7 +29,7 @@ const char *ipa_ccm_idtag_name(uint8_t tag);
int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len)
OSMO_DEPRECATED("Use ipa_ccm_id_{get,resp}_parse instead");
int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, const int len_offset)
- OSMO_DEPRECATED("Use ipa_ccm_id_{get,resp}_parse instead");
+ OSMO_DEPRECATED_OUTSIDE("Use ipa_ccm_id_{get,resp}_parse instead");
/* parse payload of IPA CCM ID GET into a osmocom TLV style representation */
int ipa_ccm_id_get_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned int len);
diff --git a/include/osmocom/gsm/iuup.h b/include/osmocom/gsm/iuup.h
new file mode 100644
index 00000000..ab6b8acf
--- /dev/null
+++ b/include/osmocom/gsm/iuup.h
@@ -0,0 +1,129 @@
+#pragma once
+
+#include <stdint.h>
+
+#include <osmocom/core/prim.h>
+#include <osmocom/gsm/protocol/gsm_25_415.h>
+
+/***********************************************************************
+ * Primitives towards the lower layers (typically RTP transport)
+ ***********************************************************************/
+enum osmo_iuup_tnl_prim_type {
+ OSMO_IUUP_TNL_UNITDATA,
+};
+
+struct osmo_iuup_tnl_prim {
+ struct osmo_prim_hdr oph;
+};
+
+/***********************************************************************
+ * Primitives towards the upper layers at the RNL SAP
+ ***********************************************************************/
+
+/* 3GPP TS 25.415 Section 7.2.1 */
+enum osmo_iuup_rnl_prim_type {
+ OSMO_IUUP_RNL_CONFIG,
+ OSMO_IUUP_RNL_DATA,
+ OSMO_IUUP_RNL_STATUS,
+ OSMO_IUUP_RNL_UNIT_DATA,
+};
+
+/* TS 25.413 9.2.1.3*/
+#define IUUP_MAX_SUBFLOWS 7
+#define IUUP_MAX_RFCIS 64
+
+#define IUUP_TIMER_INIT_T_DEFAULT 1000
+#define IUUP_TIMER_TA_T_DEFAULT 500
+#define IUUP_TIMER_RC_T_DEFAULT 500
+#define IUUP_TIMER_INIT_N_DEFAULT 3
+#define IUUP_TIMER_TA_N_DEFAULT 1
+#define IUUP_TIMER_RC_N_DEFAULT 1
+struct osmo_iuup_rnl_config_timer {
+ uint32_t t_ms; /* time in ms */
+ uint32_t n_max; /* max number of repetitions */
+};
+struct osmo_iuup_rfci {
+ uint8_t used:1,
+ spare1:1,
+ id:6;
+ uint8_t spare2:4,
+ IPTI:4; /* values range 0-15, 4 bits */;
+ uint16_t subflow_sizes[IUUP_MAX_SUBFLOWS];
+};
+struct osmo_iuup_rnl_config {
+ /* transparent (true) or SMpSDU (false): */
+ bool transparent;
+
+ /* should we actively transmit INIT in SmpSDU mode? */
+ bool active;
+
+ /* Currently Version 0 or 1: */
+ uint8_t data_pdu_type;
+
+ /* Supported mode versions */
+ uint16_t supported_versions_mask;
+ uint8_t num_rfci;
+ uint8_t num_subflows;
+ bool IPTIs_present;
+ struct osmo_iuup_rfci rfci[IUUP_MAX_RFCIS];
+
+ /* TODO: Indication of delivery of erroneous SDUs*/
+ struct osmo_iuup_rnl_config_timer t_init;
+ struct osmo_iuup_rnl_config_timer t_ta;
+ struct osmo_iuup_rnl_config_timer t_rc;
+};
+
+struct osmo_iuup_rnl_data {
+ uint8_t rfci;
+ uint8_t frame_nr;
+ uint8_t fqc;
+};
+
+struct osmo_iuup_rnl_status {
+ enum iuup_procedure procedure;
+ union {
+ struct {
+ enum iuup_error_cause cause;
+ enum iuup_error_distance distance;
+ } error_event;
+ struct {
+ uint16_t mode_version;
+ uint8_t data_pdu_type;
+ uint8_t num_rfci;
+ uint8_t num_subflows;
+ bool IPTIs_present;
+ struct osmo_iuup_rfci rfci[IUUP_MAX_RFCIS];
+ } initialization;
+ struct {
+ } rate_control;
+ struct {
+ } time_alignment;
+ } u;
+};
+
+/* SAP on the upper side of IuUP, towards the user */
+struct osmo_iuup_rnl_prim {
+ struct osmo_prim_hdr oph;
+ union {
+ struct osmo_iuup_rnl_config config;
+ struct osmo_iuup_rnl_data data;
+ struct osmo_iuup_rnl_status status;
+ //struct osmo_iuup_rnl_unitdata unitdata;
+ } u;
+};
+
+struct osmo_iuup_instance;
+struct osmo_iuup_instance *osmo_iuup_instance_alloc(void *ctx, const char *id);
+void osmo_iuup_instance_free(struct osmo_iuup_instance *iui);
+
+void osmo_iuup_instance_set_user_prim_cb(struct osmo_iuup_instance *iui, osmo_prim_cb func, void *priv);
+void osmo_iuup_instance_set_transport_prim_cb(struct osmo_iuup_instance *iui, osmo_prim_cb func, void *priv);
+int osmo_iuup_tnl_prim_up(struct osmo_iuup_instance *iui, struct osmo_iuup_tnl_prim *itp);
+int osmo_iuup_rnl_prim_down(struct osmo_iuup_instance *inst, struct osmo_iuup_rnl_prim *irp);
+
+
+int osmo_iuup_compute_header_crc(const uint8_t *iuup_pdu, unsigned int pdu_len);
+int osmo_iuup_compute_payload_crc(const uint8_t *iuup_pdu, unsigned int pdu_len);
+
+struct osmo_iuup_rnl_prim *osmo_iuup_rnl_prim_alloc(void *ctx, unsigned int primitive, unsigned int operation, unsigned int size);
+struct osmo_iuup_tnl_prim *osmo_iuup_tnl_prim_alloc(void *ctx, unsigned int primitive, unsigned int operation, unsigned int size);
diff --git a/include/osmocom/gsm/l1sap.h b/include/osmocom/gsm/l1sap.h
index d1396908..0faab7e0 100644
--- a/include/osmocom/gsm/l1sap.h
+++ b/include/osmocom/gsm/l1sap.h
@@ -27,6 +27,8 @@ enum osmo_mph_info_type {
PRIM_INFO_MODIFY, /*!< Mode Modify of channel */
PRIM_INFO_ACT_CIPH, /*!< Activation of ciphering */
PRIM_INFO_DEACT_CIPH, /*!< Deactivation of ciphering */
+ PRIM_INFO_ACT_UL_ACC, /*!< Activation of uplink access detection */
+ PRIM_INFO_DEACT_UL_ACC, /*!< Deactivation of uplink access detection */
};
/*! PH-DATA presence information */
@@ -142,6 +144,11 @@ struct info_ciph_req_param {
uint8_t uplink; /*!< Apply to uplink */
};
+/*! for {ACT_UL_ACC,DEACT_UL_ACC} MPH-INFO.req */
+struct info_ulacc_req_param {
+ uint8_t chan_nr; /*!< Channel Number (Like RSL) */
+};
+
/*! for MPH-INFO.ind */
struct mph_info_param {
enum osmo_mph_info_type type; /*!< Info message type */
@@ -151,6 +158,7 @@ struct mph_info_param {
struct info_act_req_param act_req;
struct info_act_cnf_param act_cnf;
struct info_ciph_req_param ciph_req;
+ struct info_ulacc_req_param ulacc_req;
} u;
};
diff --git a/include/osmocom/gsm/lapd_core.h b/include/osmocom/gsm/lapd_core.h
index 69e10875..a4dc2505 100644
--- a/include/osmocom/gsm/lapd_core.h
+++ b/include/osmocom/gsm/lapd_core.h
@@ -1,177 +1,2 @@
-/*! \file lapd_core.h
- * primitive related stuff
- */
#pragma once
-
-#include <stdint.h>
-
-#include <osmocom/core/timer.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/prim.h>
-
-/*! \defgroup lapd LAPD implementation common part
- * @{
- * \file lapd_core.h
- */
-
-#define LOGDL(dl, level, fmt, args...) \
- LOGP(DLLAPD, level, "(%s) " fmt, (dl)->name, ## args)
-
-/*! LAPD related primitives (L2<->L3 SAP)*/
-enum osmo_dl_prim {
- PRIM_DL_UNIT_DATA, /*!< DL-UNIT-DATA */
- PRIM_DL_DATA, /*!< DL-DATA */
- PRIM_DL_EST, /*!< DL-ESTABLISH */
- PRIM_DL_REL, /*!< DL-RLEEASE */
- PRIM_DL_SUSP, /*!< DL-SUSPEND */
- PRIM_DL_RES, /*!< DL-RESUME */
- PRIM_DL_RECON, /*!< DL-RECONNECT */
- PRIM_MDL_ERROR, /*!< MDL-ERROR */
-};
-
-/* Uses the same values as RLL, so no conversion for GSM is required. */
-#define MDL_CAUSE_T200_EXPIRED 0x01
-#define MDL_CAUSE_REEST_REQ 0x02
-#define MDL_CAUSE_UNSOL_UA_RESP 0x03
-#define MDL_CAUSE_UNSOL_DM_RESP 0x04
-#define MDL_CAUSE_UNSOL_DM_RESP_MF 0x05
-#define MDL_CAUSE_UNSOL_SPRV_RESP 0x06
-#define MDL_CAUSE_SEQ_ERR 0x07
-#define MDL_CAUSE_UFRM_INC_PARAM 0x08
-#define MDL_CAUSE_SFRM_INC_PARAM 0x09
-#define MDL_CAUSE_IFRM_INC_MBITS 0x0a
-#define MDL_CAUSE_IFRM_INC_LEN 0x0b
-#define MDL_CAUSE_FRM_UNIMPL 0x0c
-#define MDL_CAUSE_SABM_MF 0x0d
-#define MDL_CAUSE_SABM_INFO_NOTALL 0x0e
-#define MDL_CAUSE_FRMR 0x0f
-
-/*! for MDL-ERROR.ind */
-struct mdl_error_ind_param {
- uint8_t cause; /*!< generic cause value */
-};
-
-/*! for DL-REL.req */
-struct dl_rel_req_param {
- uint8_t mode; /*!< release mode */
-};
-
-/*! primitive header for LAPD DL-SAP primitives */
-struct osmo_dlsap_prim {
- struct osmo_prim_hdr oph; /*!< generic primitive header */
- union {
- struct mdl_error_ind_param error_ind;
- struct dl_rel_req_param rel_req;
- } u; /*!< request-specific data */
-};
-
-/*! LAPD mode/role */
-enum lapd_mode {
- LAPD_MODE_USER, /*!< behave like user */
- LAPD_MODE_NETWORK, /*!< behave like network */
-};
-
-/*! LAPD state (Figure B.2/Q.921)*/
-enum lapd_state {
- LAPD_STATE_NULL = 0,
- LAPD_STATE_TEI_UNASS,
- LAPD_STATE_ASS_TEI_WAIT,
- LAPD_STATE_EST_TEI_WAIT,
- LAPD_STATE_IDLE,
- LAPD_STATE_SABM_SENT,
- LAPD_STATE_DISC_SENT,
- LAPD_STATE_MF_EST,
- LAPD_STATE_TIMER_RECOV,
-};
-
-/*! LAPD message format (I / S / U) */
-enum lapd_format {
- LAPD_FORM_UKN = 0,
- LAPD_FORM_I,
- LAPD_FORM_S,
- LAPD_FORM_U,
-};
-
-/*! LAPD message context */
-struct lapd_msg_ctx {
- struct lapd_datalink *dl;
- int n201;
- /* address */
- uint8_t cr;
- uint8_t sapi;
- uint8_t tei;
- uint8_t lpd;
- /* control */
- uint8_t format;
- uint8_t p_f; /* poll / final bit */
- uint8_t n_send;
- uint8_t n_recv;
- uint8_t s_u; /* S or repectivly U function bits */
- /* length */
- int length;
- uint8_t more;
-};
-
-struct lapd_cr_ent {
- uint8_t cmd;
- uint8_t resp;
-};
-
-struct lapd_history {
- struct msgb *msg; /* message to be sent / NULL, if histoy is empty */
- int more; /* if message is fragmented */
-};
-
-/*! LAPD datalink */
-struct lapd_datalink {
- int (*send_dlsap)(struct osmo_dlsap_prim *dp,
- struct lapd_msg_ctx *lctx);
- int (*send_ph_data_req)(struct lapd_msg_ctx *lctx, struct msgb *msg);
- int (*update_pending_frames)(struct lapd_msg_ctx *lctx);
- struct {
- /*! filled-in once we set the lapd_mode above */
- struct lapd_cr_ent loc2rem;
- struct lapd_cr_ent rem2loc;
- } cr;
- enum lapd_mode mode; /*!< current mode of link */
- int use_sabme; /*!< use SABME instead of SABM */
- int reestablish; /*!< enable reestablish support */
- int n200, n200_est_rel; /*!< number of retranmissions */
- struct lapd_msg_ctx lctx; /*!< LAPD context */
- int maxf; /*!< maximum frame size (after defragmentation) */
- uint8_t k; /*!< maximum number of unacknowledged frames */
- uint8_t v_range; /*!< range of sequence numbers */
- uint8_t v_send; /*!< seq nr of next I frame to be transmitted */
- uint8_t v_ack; /*!< last frame ACKed by peer */
- uint8_t v_recv; /*!< seq nr of next I frame expected to be received */
- uint32_t state; /*!< LAPD state (\ref lapd_state) */
- int seq_err_cond; /*!< condition of sequence error */
- uint8_t own_busy; /*!< receiver busy on our side */
- uint8_t peer_busy; /*!< receiver busy on remote side */
- int t200_sec, t200_usec; /*!< retry timer (default 1 sec) */
- int t203_sec, t203_usec; /*!< retry timer (default 10 secs) */
- struct osmo_timer_list t200; /*!< T200 timer */
- struct osmo_timer_list t203; /*!< T203 timer */
- uint8_t retrans_ctr; /*!< re-transmission counter */
- struct llist_head tx_queue; /*!< frames to L1 */
- struct llist_head send_queue; /*!< frames from L3 */
- struct msgb *send_buffer; /*!< current frame transmitting */
- int send_out; /*!< how much was sent from send_buffer */
- struct lapd_history *tx_hist; /*!< tx history structure array */
- uint8_t range_hist; /*!< range of history buffer 2..2^n */
- struct msgb *rcv_buffer; /*!< buffer to assemble the received message */
- struct msgb *cont_res; /*!< buffer to store content resolution data on network side, to detect multiple phones on same channel */
- char *name; /*!< user-provided name */
-};
-
-void lapd_dl_init(struct lapd_datalink *dl, uint8_t k, uint8_t v_range, int maxf)
- OSMO_DEPRECATED("Use lapd_dl_init2() instead");
-void lapd_dl_init2(struct lapd_datalink *dl, uint8_t k, uint8_t v_range, int maxf, const char *name);
-void lapd_dl_set_name(struct lapd_datalink *dl, const char *name);
-void lapd_dl_exit(struct lapd_datalink *dl);
-void lapd_dl_reset(struct lapd_datalink *dl);
-int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode);
-int lapd_ph_data_ind(struct msgb *msg, struct lapd_msg_ctx *lctx);
-int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx);
-
-/*! @} */
+#include <osmocom/isdn/lapd_core.h>
diff --git a/include/osmocom/gsm/lapdm.h b/include/osmocom/gsm/lapdm.h
index 633df1ad..6812102e 100644
--- a/include/osmocom/gsm/lapdm.h
+++ b/include/osmocom/gsm/lapdm.h
@@ -24,6 +24,7 @@ struct lapdm_msg_ctx {
uint8_t link_id;
uint8_t ta_ind; /* TA indicated by network */
uint8_t tx_power_ind; /* MS power indicated by network */
+ uint32_t fn;
};
/*! LAPDm datalink like TS 04.06 / Section 3.5.2 */
@@ -32,6 +33,10 @@ struct lapdm_datalink {
struct lapdm_msg_ctx mctx; /*!< context of established connection */
struct lapdm_entity *entity; /*!< LAPDm entity we are part of */
+
+ struct llist_head tx_ui_queue; /*!< UI frames to L1 */
+ uint32_t t200_fn; /*!< T200 timer in frames */
+ uint32_t t200_timeout; /*!< T200 timeout frame number */
};
/*! LAPDm datalink SAPIs */
@@ -45,6 +50,8 @@ typedef int (*lapdm_cb_t)(struct msgb *msg, struct lapdm_entity *le, void *ctx);
#define LAPDM_ENT_F_EMPTY_FRAME 0x0001
#define LAPDM_ENT_F_POLLING_ONLY 0x0002
+#define LAPDM_ENT_F_DROP_2ND_REJ 0x0004
+#define LAPDM_ENT_F_RTS 0x0008
/*! a LAPDm Entity */
struct lapdm_entity {
@@ -90,7 +97,7 @@ void lapdm_entity_init2(struct lapdm_entity *le, enum lapdm_mode mode,
void lapdm_entity_init3(struct lapdm_entity *le, enum lapdm_mode mode,
const int *t200_ms, int n200, const char *name_pfx);
void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode)
- OSMO_DEPRECATED("Use lapdm_channel_init3() instead");
+ OSMO_DEPRECATED_OUTSIDE("Use lapdm_channel_init3() instead");
int lapdm_channel_init2(struct lapdm_channel *lc, enum lapdm_mode mode,
const int *t200_ms_dcch, const int *t200_ms_acch, enum gsm_chan_t chan_t);
int lapdm_channel_init3(struct lapdm_channel *lc, enum lapdm_mode mode,
@@ -118,6 +125,11 @@ void lapdm_channel_reset(struct lapdm_channel *lc);
void lapdm_entity_set_flags(struct lapdm_entity *le, unsigned int flags);
void lapdm_channel_set_flags(struct lapdm_channel *lc, unsigned int flags);
+void lapdm_entity_set_t200_fn(struct lapdm_entity *le, const uint32_t *t200_fn);
+void lapdm_channel_set_t200_fn(struct lapdm_channel *lc, const uint32_t *t200_fn_dcch, const uint32_t *t200_fn_acch);
+
int lapdm_phsap_dequeue_prim(struct lapdm_entity *le, struct osmo_phsap_prim *pp);
+int lapdm_phsap_dequeue_prim_fn(struct lapdm_entity *le, struct osmo_phsap_prim *pp, uint32_t fn);
+void lapdm_t200_fn(struct lapdm_entity *le, uint32_t fn);
/*! @} */
diff --git a/include/osmocom/gsm/meas_rep.h b/include/osmocom/gsm/meas_rep.h
index 79f9f06b..5628d8ec 100644
--- a/include/osmocom/gsm/meas_rep.h
+++ b/include/osmocom/gsm/meas_rep.h
@@ -11,7 +11,7 @@ struct gsm_rx_lev_qual {
uint8_t rx_qual;
};
-/* unidirectional measumrement report */
+/* unidirectional measurement report */
struct gsm_meas_rep_unidir {
struct gsm_rx_lev_qual full;
struct gsm_rx_lev_qual sub;
@@ -28,5 +28,5 @@ enum meas_rep_field {
MEAS_REP_UL_RXQUAL_SUB,
};
-size_t gsm0858_rsl_ul_meas_enc(struct gsm_meas_rep_unidir *mru, bool dtxd_used,
+size_t gsm0858_rsl_ul_meas_enc(const struct gsm_meas_rep_unidir *mru, bool dtxd_used,
uint8_t *buf);
diff --git a/include/osmocom/gsm/prim.h b/include/osmocom/gsm/prim.h
index e7a60e30..73cd7f71 100644
--- a/include/osmocom/gsm/prim.h
+++ b/include/osmocom/gsm/prim.h
@@ -16,4 +16,9 @@ enum osmo_gsm_sap {
SAP_BSSGP_PFM,
SAP_NS,
+
+ SAP_BSSGP_RIM,
+
+ SAP_IUUP_TNL,
+ SAP_IUUP_RNL,
};
diff --git a/include/osmocom/gsm/protocol/Makefile.am b/include/osmocom/gsm/protocol/Makefile.am
new file mode 100644
index 00000000..23429dcd
--- /dev/null
+++ b/include/osmocom/gsm/protocol/Makefile.am
@@ -0,0 +1,30 @@
+osmogsmproto_HEADERS = \
+ gsm_23_032.h \
+ gsm_03_40.h \
+ gsm_03_41.h \
+ gsm_04_08.h \
+ gsm_04_08_gprs.h \
+ gsm_04_11.h \
+ gsm_04_12.h \
+ gsm_04_14.h \
+ gsm_04_80.h \
+ gsm_08_08.h \
+ gsm_08_58.h \
+ gsm_09_02.h \
+ gsm_12_21.h \
+ gsm_23_003.h \
+ gsm_23_041.h \
+ gsm_25_415.h \
+ gsm_29_118.h \
+ gsm_44_004.h \
+ gsm_44_060.h \
+ gsm_44_068.h \
+ gsm_44_318.h \
+ gsm_48_049.h \
+ gsm_48_071.h \
+ gsm_49_031.h \
+ ipaccess.h \
+ smpp34_osmocom.h \
+ $(NULL)
+
+osmogsmprotodir = $(includedir)/osmocom/gsm/protocol
diff --git a/include/osmocom/gsm/protocol/gsm_03_41.h b/include/osmocom/gsm/protocol/gsm_03_41.h
index 1b399aee..f6c36cad 100644
--- a/include/osmocom/gsm/protocol/gsm_03_41.h
+++ b/include/osmocom/gsm/protocol/gsm_03_41.h
@@ -25,7 +25,7 @@ struct gsm341_ms_message {
uint8_t update:4;
uint8_t code_lo:4;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t gs:2, code_hi:6;
uint8_t code_lo:4, update:4;
#endif
@@ -36,7 +36,7 @@ struct gsm341_ms_message {
uint8_t language:4;
uint8_t group:4;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t group:4, language:4;
#endif
} dcs;
@@ -45,7 +45,7 @@ struct gsm341_ms_message {
uint8_t total:4;
uint8_t current:4;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t current:4, total:4;
#endif
} page;
@@ -63,7 +63,7 @@ struct gsm341_etws_message {
uint8_t update:4;
uint8_t code_lo:4;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t gs:2, alert:1, popup:1, code_hi:4;
uint8_t code_lo:4, update:4;
#endif
diff --git a/include/osmocom/gsm/protocol/gsm_04_08.h b/include/osmocom/gsm/protocol/gsm_04_08.h
index f8f2eabd..075b6ca6 100644
--- a/include/osmocom/gsm/protocol/gsm_04_08.h
+++ b/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -22,7 +22,7 @@ struct gsm48_classmark1 {
rev_lev:2,
spare:1;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t spare:1, rev_lev:2, es_ind:1, a5_1:1, pwr_lev:3;
#endif
} __attribute__ ((packed));
@@ -51,13 +51,182 @@ struct gsm48_classmark2 {
spare4:1,
cm3:1;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t spare:1, rev_lev:2, es_ind:1, a5_1:1, pwr_lev:3;
uint8_t spare2:1, ps_cap:1, ss_scr:2, sm_cap:1, vbs:1, vgcs:1, fc:1;
uint8_t cm3:1, spare4:1, lcsva_cap:1, spare3:1, solsa:1, cmsp:1, a5_3:1, a5_2:1;
#endif
} __attribute__ ((packed));
+/* Chapter 10.5.1.7 */
+struct gsm48_classmark3 {
+ uint8_t a5_bits;
+ uint8_t mult_band_supp;
+ uint8_t assoc_radio_cap_1;
+ uint8_t assoc_radio_cap_2;
+
+ struct {
+ bool present;
+ uint8_t r_gsm_assoc_radio_cap;
+ } r_support;
+
+ struct {
+ bool present;
+ uint8_t mslot_class;
+ } hscsd_mult_slot_cap;
+
+ bool ucs2_treatment;
+ bool extended_meas_cap;
+
+ struct {
+ bool present;
+ uint8_t sms_value;
+ uint8_t sm_value;
+ } ms_meas_cap;
+
+ struct {
+ bool present;
+ uint8_t method;
+ } ms_pos_method_cap;
+
+ struct {
+ bool present;
+ uint8_t mslot_class;
+ } ecsd_multislot_cap;
+
+ struct {
+ bool present;
+ bool mod_cap;
+
+ struct {
+ bool present;
+ uint8_t value;
+ } rf_pwr_cap_1;
+
+ struct {
+ bool present;
+ uint8_t value;
+ } rf_pwr_cap_2;
+
+ } psk8_struct;
+
+ struct {
+ bool present;
+ uint8_t value;
+ uint8_t assoc_radio_cap;
+ } gsm_400_bands_supp;
+
+ struct {
+ bool present;
+ uint8_t value;
+ } gsm_850_assoc_radio_cap;
+
+ struct {
+ bool present;
+ uint8_t value;
+ } gsm_1900_assoc_radio_cap;
+
+ bool umts_fdd_rat_cap;
+ bool umts_tdd_rat_cap;
+ bool cdma200_rat_cap;
+
+ struct {
+ bool present;
+ uint8_t mslot_class;
+ bool single_slot_dtm;
+ struct {
+ bool present;
+ uint8_t mslot_class;
+ } dtm_egprs_multislot_cap;
+ } dtm_gprs_multislot_cap;
+
+ struct {
+ bool present;
+ uint8_t value;
+ } single_band_supp;
+
+ struct {
+ bool present;
+ uint8_t value;
+ } gsm_750_assoc_radio_cap;
+
+ bool umts_1_28_mcps_tdd_rat_cap;
+ bool geran_feature_package;
+
+ struct {
+ bool present;
+ uint8_t mslot_class;
+ struct {
+ bool present;
+ uint8_t mslot_class;
+ } extended_dtm_egprs_multislot_cap;
+ } extended_dtm_gprs_multislot_cap;
+
+ struct {
+ bool present;
+ uint8_t value;
+ } high_multislot_cap;
+
+ bool geran_feature_package_2;
+ uint8_t gmsk_multislot_power_prof;
+ uint8_t psk8_multislot_power_prof;
+
+ struct {
+ bool present;
+ uint8_t value;
+ uint8_t assoc_radio_cap;
+ } t_gsm_400_bands_supp;
+
+ uint8_t dl_advanced_rx_perf;
+ bool dtm_enhancements_cap;
+
+ struct {
+ bool present;
+ uint8_t mslot_class;
+ bool offset_required;
+ struct {
+ bool present;
+ uint8_t mslot_class;
+ } dtm_egprs_high_multislot_cap;
+ } dtm_gprs_high_multislot_cap;
+
+ bool repeated_acch_capability;
+
+ struct {
+ bool present;
+ uint8_t value;
+ } gsm_710_assoc_radio_cap;
+
+ struct {
+ bool present;
+ uint8_t value;
+ } t_gsm_810_assoc_radio_cap;
+
+ bool ciphering_mode_setting_cap;
+ bool add_pos_cap;
+ bool e_utra_fdd_supp;
+ bool e_utra_tdd_supp;
+ bool e_utra_meas_rep_supp;
+ bool prio_resel_supp;
+ bool utra_csg_cells_rep;
+
+ uint8_t vamos_level;
+ uint8_t tighter_capability;
+
+ bool sel_ciph_dl_sacch;
+
+ uint8_t cs_ps_srvcc_geran_utra;
+ uint8_t cs_ps_srvcc_geran_eutra;
+
+ bool geran_net_sharing;
+ bool e_utra_wb_rsrq_meas_supp;
+ bool er_band_support;
+ bool utra_mult_band_ind_supp;
+ bool e_utra_mult_band_ind_supp;
+ bool extended_tsc_set_cap_supp;
+ bool extended_earfcn_val_range;
+};
+
struct osmo_gsm48_classmark {
bool classmark1_set;
struct gsm48_classmark1 classmark1;
@@ -111,7 +280,7 @@ struct gsm48_range_1024 {
uint8_t w16:6,
w15_lo:2;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t form_id:5, f0:1, w1_hi:2;
uint8_t w1_lo;
uint8_t w2_hi;
@@ -166,7 +335,7 @@ struct gsm48_range_512 {
uint8_t w17:5,
w16_lo:3;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t form_id:7, orig_arfcn_hi:1;
uint8_t orig_arfcn_mid;
uint8_t orig_arfcn_lo:1, w1_hi:7;
@@ -227,7 +396,7 @@ struct gsm48_range_256 {
w21:4,
w20_lo:3;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t form_id:7, orig_arfcn_hi:1;
uint8_t orig_arfcn_mid;
uint8_t orig_arfcn_lo:1, w1_hi:7;
@@ -290,7 +459,7 @@ struct gsm48_range_128 {
w27:3,
w26_lo:1;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t form_id:7, orig_arfcn_hi:1;
uint8_t orig_arfcn_mid;
uint8_t orig_arfcn_lo:1, w1:7;
@@ -320,7 +489,7 @@ struct gsm48_var_bit {
orig_arfcn_lo:1;
uint8_t rrfcn8_111[13];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t form_id:7, orig_arfcn_hi:1;
uint8_t orig_arfcn_mid;
uint8_t orig_arfcn_lo:1, rrfcn1_7:7;
@@ -340,7 +509,7 @@ struct gsm48_chan_desc {
uint8_t hsn:6,
maio_low:2;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t tsc:3, h:1, maio_high:4;
uint8_t maio_low:2, hsn:6;
#endif
@@ -353,7 +522,7 @@ struct gsm48_chan_desc {
tsc:3;
uint8_t arfcn_low;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t tsc:3, h:1, spare:2, arfcn_high:2;
uint8_t arfcn_low;
#endif
@@ -404,7 +573,7 @@ struct gsm48_meas_res {
uint8_t bsic_nc6:6,
bcch_f_nc6_lo:2;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t ba_used:1, dtx_used:1, rxlev_full:6;
uint8_t spare:1, meas_valid:1, rxlev_sub:6;
uint8_t spare2:1, rxqual_full:3, rxqual_sub:3, no_nc_n_hi:1;
@@ -424,6 +593,12 @@ struct gsm48_meas_res {
#endif
} __attribute__ ((packed));
+/*! Check if the given mr contains valid measurement results */
+static inline bool gsm48_meas_res_is_valid(const struct gsm48_meas_res *mr)
+{
+ return (mr->meas_valid == 0); /* 0 means valid */
+}
+
/* Chapter 10.5.2.21aa */
struct gsm48_multi_rate_conf {
#if OSMO_IS_LITTLE_ENDIAN
@@ -441,7 +616,7 @@ struct gsm48_multi_rate_conf {
m10_2 : 1,
m12_2 : 1;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t ver:3, nscb:1, icmi:1, spare:1, smod:2;
uint8_t m12_2:1, m10_2:1, m7_95:1, m7_40:1, m6_70:1, m5_90:1, m5_15:1, m4_75:1;
#endif
@@ -454,7 +629,7 @@ struct gsm48_power_cmd {
spare:2,
atc:1;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t atc:1, spare:2, power_level:5;
#endif
} __attribute__((packed));
@@ -469,7 +644,7 @@ struct gsm48_rach_control {
uint8_t t2; /* ACC 8-15 barred flags */
uint8_t t3; /* ACC 0-7 barred flags */
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t max_trans:2, tx_integer:4, cell_bar:1, re:1;
uint8_t t2;
uint8_t t3;
@@ -527,7 +702,7 @@ struct gsm48_req_ref {
uint8_t t2:5,
t3_low:3;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t ra;
uint8_t t1:5, t3_high:3;
uint8_t t3_low:3, t2:5;
@@ -542,7 +717,7 @@ struct gsm48_start_time {
uint8_t t2:5,
t3_low:3;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t t1:5, t3_high:3;
uint8_t t3_low:3, t2:5;
#endif
@@ -556,7 +731,7 @@ struct gsm48_sync_ind {
nci:1,
sync_ie:4;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t sync_ie:4, nci:1, rot:1, si:2;
#endif
} __attribute__((packed));
@@ -571,15 +746,59 @@ struct gsm48_chan_mode_modify {
uint8_t mode;
} __attribute__ ((packed));
+/*! 10.5.2.6 Channel Mode value */
enum gsm48_chan_mode {
+ /*! Signalling only (TCH/F or TCH/H) */
GSM48_CMODE_SIGN = 0x00,
+ /*! Speech: FR (TCH/FS) or HR (TCH/HS) */
GSM48_CMODE_SPEECH_V1 = 0x01,
- GSM48_CMODE_SPEECH_EFR = 0x21,
- GSM48_CMODE_SPEECH_AMR = 0x41,
+ /*! Speech: EFR (TCH/EFS) */
+ GSM48_CMODE_SPEECH_EFR = 0x21, /*!< a.k.a. V2 */
+ /*! Speech: AMR (TCH/AFS or TCH/AHS) */
+ GSM48_CMODE_SPEECH_AMR = 0x41, /*!< a.k.a. V3 */
+ /*! Speech: OFR AMR-WB (O-TCH/WFS) or OHR AMR-WB (O-TCH/WHS) */
+ GSM48_CMODE_SPEECH_V4 = 0x81,
+ /*! Speech: FR AMR-WB (TCH/WFS) */
+ GSM48_CMODE_SPEECH_V5 = 0x82,
+ /*! Speech: OHR AMR (O-TCH/AHS) */
+ GSM48_CMODE_SPEECH_V6 = 0x83,
+
+ /* ECSD: 43.5 kbit/s (DL) + 14.5 kbit/s (UL) */
+ GSM48_CMODE_DATA_43k5_14k5 = 0x61,
+ /* ECSD: 29.0 kbit/s (DL) + 14.5 kbit/s (UL) */
+ GSM48_CMODE_DATA_29k0_14k5 = 0x62,
+ /* ECSD: 43.5 kbit/s (DL) + 29.0 kbit/s (UL) */
+ GSM48_CMODE_DATA_43k5_29k0 = 0x64,
+ /* ECSD: 14.5 kbit/s (DL) + 43.5 kbit/s (UL) */
+ GSM48_CMODE_DATA_14k5_43k5 = 0x67,
+ /* ECSD: 14.5 kbit/s (DL) + 29.0 kbit/s (UL) */
+ GSM48_CMODE_DATA_14k5_29k0 = 0x65,
+ /* ECSD: 29.0 kbit/s (DL) + 43.5 kbit/s (UL) */
+ GSM48_CMODE_DATA_29k0_43k5 = 0x66,
+
+ /*! ECSD: 43.5 kbit/s radio interface rate, 43.2 kbit/s services (E-TCH/F43.2) */
+ GSM48_CMODE_DATA_43k5 = 0x27,
+ /*! ECSD: 32.0 kbit/s radio interface rate, 32.0 kbit/s services (E-TCH/F32.0) */
+ GSM48_CMODE_DATA_32k0 = 0x63,
+ /*! ECSD: 29.0 kbit/s radio interface rate, 28.8 kbit/s services (E-TCH/F28.8) */
+ GSM48_CMODE_DATA_29k0 = 0x43,
+ /*! CSD: 14.5 kbit/s radio interface rate, 14.4 kbit/s services (TCH/F14.4) */
GSM48_CMODE_DATA_14k5 = 0x0f,
+ /*! CSD: 12.0 kbit/s radio interface rate, 9.6 kbit/s services (TCH/F9.6) */
GSM48_CMODE_DATA_12k0 = 0x03,
+ /*! CSD: 6.0 kbit/s radio interface rate, 4.8 kbit/s services (TCH/{F,H}4.8) */
GSM48_CMODE_DATA_6k0 = 0x0b,
+ /*! CSD: 3.6 kbit/s radio interface rate, 2.4 kbit/s and less services (TCH/{F,H}2.4) */
GSM48_CMODE_DATA_3k6 = 0x13,
+
+ /*! Same as GSM48_CMODE_SPEECH_V1, in VAMOS mode */
+ GSM48_CMODE_SPEECH_V1_VAMOS = 0xc1,
+ /*! Same as GSM48_CMODE_SPEECH_EFR, in VAMOS mode */
+ GSM48_CMODE_SPEECH_V2_VAMOS = 0xc2,
+ /*! Same as GSM48_CMODE_SPEECH_AMR, in VAMOS mode */
+ GSM48_CMODE_SPEECH_V3_VAMOS = 0xc3,
+ /*! Speech: GSM48_CMODE_SPEECH_V5, in VAMOS mode */
+ GSM48_CMODE_SPEECH_V5_VAMOS = 0xc5,
};
extern const struct value_string gsm48_chan_mode_names[];
@@ -618,7 +837,7 @@ struct gsm48_cell_desc {
arfcn_hi:2;
uint8_t arfcn_lo;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t arfcn_hi:2, ncc:3, bcc:3;
uint8_t arfcn_lo;
#endif
@@ -661,7 +880,7 @@ struct gsm48_pag_resp {
uint8_t mi_len;
uint8_t mi[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t key_seq:4, spare:4;
union {
uint32_t classmark2;
@@ -688,7 +907,7 @@ struct gsm48_auth_req {
spare:4;
uint8_t rand[16];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t spare:4, key_seq:4;
uint8_t rand[16];
#endif
@@ -709,7 +928,7 @@ struct gsm48_loc_upd_req {
uint8_t mi_len;
uint8_t mi[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t key_seq:4, type:4;
struct gsm48_loc_area_id lai;
struct gsm48_classmark1 classmark1;
@@ -725,6 +944,20 @@ struct gsm48_hdr {
uint8_t data[0];
} __attribute__ ((packed));
+/* Short header */
+struct gsm48_hdr_sh {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t l2_header:2, /* < short layer 2 header : bit(2) > See 3GPP TS 44.006 §6.4a */
+ msg_type:5, /* < message type : bit(5) > See 3GPP TS 44.018 Table 10.4.2 */
+ rr_short_pd:1; /* < RR short PD : bit > See 3GPP TS 24.007 §11.3.2 */
+ uint8_t data[0];
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t rr_short_pd:1, msg_type:5, l2_header:2;
+ uint8_t data[0];
+#endif
+} __attribute__ ((packed));
+
/* Section 9.1.3x System information Type header */
struct gsm48_system_information_type_header {
#if OSMO_IS_LITTLE_ENDIAN
@@ -733,7 +966,7 @@ struct gsm48_system_information_type_header {
skip_indicator:4;
uint8_t system_information;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t l2_plen;
uint8_t skip_indicator:4, rr_protocol_discriminator:4;
uint8_t system_information;
@@ -749,7 +982,7 @@ struct gsm48_cell_sel_par {
neci:1,
acs:1;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t cell_resel_hyst:3, ms_txpwr_max_ccch:5;
uint8_t acs:1, neci:1, rxlev_acc_min:6;
#endif
@@ -768,7 +1001,7 @@ struct gsm48_control_channel_descr {
spare_2 :1;
uint8_t t3212;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t mscr:1, att:1, bs_ag_blks_res:3, ccch_conf:3;
uint8_t spare_2:1, cbq3:2, spare_1:2, bs_pa_mfrms:3;
uint8_t t3212;
@@ -791,7 +1024,7 @@ struct gsm48_cell_options {
/* either DN-IND or top bit of DTX IND */
d:1;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t d:1, pwrc:1, dtx:2, radio_link_timeout:4;
#endif
} __attribute__ ((packed));
@@ -812,7 +1045,7 @@ struct gsm48_service_request {
uint8_t mi[0];
/* optional priority level */
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t cipher_key_seq:4, cm_service_type:4;
union {
uint32_t classmark;
@@ -895,7 +1128,7 @@ struct gsm48_system_information_type_5 {
uint8_t system_information;
uint8_t bcch_frequency_list[16];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t skip_indicator:4, rr_protocol_discriminator:4;
uint8_t system_information;
uint8_t bcch_frequency_list[16];
@@ -910,7 +1143,7 @@ struct gsm48_system_information_type_5bis {
uint8_t system_information;
uint8_t bcch_frequency_list[16];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t skip_indicator:4, rr_protocol_discriminator:4;
uint8_t system_information;
uint8_t bcch_frequency_list[16];
@@ -925,7 +1158,7 @@ struct gsm48_system_information_type_5ter {
uint8_t system_information;
uint8_t bcch_frequency_list[16];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t skip_indicator:4, rr_protocol_discriminator:4;
uint8_t system_information;
uint8_t bcch_frequency_list[16];
@@ -944,7 +1177,7 @@ struct gsm48_system_information_type_6 {
uint8_t ncc_permitted;
uint8_t rest_octets[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t skip_indicator:4, rr_protocol_discriminator:4;
uint8_t system_information;
uint16_t cell_identity;
@@ -955,6 +1188,27 @@ struct gsm48_system_information_type_6 {
#endif
} __attribute__ ((packed));
+/* Section 9.1.50 System Information type 10 (ASCI) */
+struct gsm48_system_information_type_10 {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t l2_header:2, /* < short layer 2 header : bit(2) > See 3GPP TS 44.006 §6.4a */
+ msg_type:5, /* < message type : bit(5) > See 3GPP TS 44.018 Table 10.4.2 */
+ rr_short_pd:1; /* < RR short PD : bit > See 3GPP TS 24.007 §11.3.2 */
+ uint8_t rest_octets[0]; /* < SI10 Rest Octets : bit(160) > See 3GPP TS 44.018 §10.5.2.44 */
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t rr_short_pd:1, msg_type:5, l2_header:2;
+ uint8_t rest_octets[0];
+#endif
+} __attribute__ ((packed));
+
+/* TS 44.018 Section 9.1.49 */
+struct gsm0408_vgcs_ul_grant {
+ struct gsm48_hdr hdr;
+ struct gsm48_req_ref req_ref;
+ uint8_t ta;
+} __attribute__ ((packed));
+
/* Section 9.1.43a System Information type 13 */
struct gsm48_system_information_type_13 {
struct gsm48_system_information_type_header header;
@@ -1010,7 +1264,7 @@ struct gsm48_cip_mode_cmd {
cr:1,
spare:3;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t spare:3, cr:1, alg_id:3, sc:1;
#endif
} __attribute__((packed));
@@ -1055,6 +1309,14 @@ struct gsm48_imm_ass_rej {
uint8_t rest[0];
} __attribute__ ((packed));
+/* Section 9.1.21b */
+struct gsm48_notification_nch {
+ uint8_t l2_plen;
+ uint8_t proto_discr;
+ uint8_t msg_type;
+ uint8_t data[0];
+} __attribute__((packed));
+
/* Section 9.1.22 */
struct gsm48_paging1 {
#if OSMO_IS_LITTLE_ENDIAN
@@ -1067,7 +1329,7 @@ struct gsm48_paging1 {
cneed2:2;
uint8_t data[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t l2_plen;
uint8_t proto_discr;
uint8_t msg_type;
@@ -1090,7 +1352,7 @@ struct gsm48_paging2 {
uint32_t tmsi2;
uint8_t data[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t l2_plen;
uint8_t proto_discr;
uint8_t msg_type;
@@ -1120,7 +1382,7 @@ struct gsm48_paging3 {
spare2:4;
uint8_t rest[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t l2_plen;
uint8_t proto_discr;
uint8_t msg_type;
@@ -1143,7 +1405,7 @@ struct gsm48_pag_rsp {
struct gsm48_classmark2 cm2;
uint8_t data[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t spare:5, key_seq:3;
uint8_t cm2_len;
struct gsm48_classmark2 cm2;
@@ -1156,6 +1418,18 @@ struct gsm48_rr_status {
uint8_t rr_cause;
} __attribute__((packed));
+/* Section 9.1.44 */
+struct gsm48_talker_indication {
+ uint8_t cm2_len;
+ struct gsm48_classmark2 cm2;
+ uint8_t data[0];
+} __attribute__((packed));
+
+/* Section 9.1.48 */
+struct gsm48_uplink_release {
+ uint8_t rr_cause;
+} __attribute__((packed));
+
/* Section 10.2 + GSM 04.07 12.2.3.1.1 + 3GPP TS 24.007 11.2.3.1.1 */
#define GSM48_PDISC_GROUP_CC 0x00
#define GSM48_PDISC_BCAST_CC 0x01
@@ -1174,6 +1448,9 @@ struct gsm48_rr_status {
#define GSM48_PDISC_TEST 0x0f /* as per 11.10, 04.14 */
#define GSM48_PDISC_MASK 0x0f
+/* Section 11.3.2.1 3GPP TS 24.007: Short PDISC */
+#define GSM48_PDISC_SH_RR 0
+
extern const struct value_string gsm48_pdisc_names[];
static inline const char *gsm48_pdisc_name(uint8_t val)
{ return get_value_string(gsm48_pdisc_names, val); }
@@ -1361,6 +1638,21 @@ void gsm48_set_dtx(struct gsm48_cell_options *op, enum gsm48_dtx_mode full,
#define GSM48_MT_RR_APP_INFO 0x38
+/* 3GPP TS 44.018 Table 10.4.2 */
+#define GSM48_MT_RR_SH_SI10 0x0
+#define GSM48_MT_RR_SH_FACCH 0x1
+#define GSM48_MT_RR_SH_UL_FREE 0x2
+#define GSM48_MT_RR_SH_MEAS_REP 0x4
+#define GSM48_MT_RR_SH_MEAS_INFO 0x5
+#define GSM48_MT_RR_SH_VGCS_RECON 0x6
+#define GSM48_MT_RR_SH_VGCS_RECON2 0x7
+#define GSM48_MT_RR_SH_VGCS_INFO 0x8
+#define GSM48_MT_RR_SH_VGCS_SMS 0x9
+#define GSM48_MT_RR_SH_SI10bis 0xA
+#define GSM48_MT_RR_SH_SI10ter 0xB
+#define GSM48_MT_RR_SH_VGCS_NEIGH 0xC
+#define GSM48_MT_RR_SH_APP_DATA 0xD
+
/* Table 10.2/3GPP TS 04.08 */
#define GSM48_MT_MM_IMSI_DETACH_IND 0x01
#define GSM48_MT_MM_LOC_UPD_ACCEPT 0x02
@@ -1526,6 +1818,10 @@ static inline const char *osmo_lu_type_name(uint8_t lu_type)
#define GSM48_IE_FRQSHORT_AFTER 0x02
#define GSM48_IE_MUL_RATE_CFG 0x03 /* 10.5.2.21aa */
#define GSM48_IE_FREQ_L_AFTER 0x05
+#define GSM48_IE_GROUP_CIP_SEQ_HO 0x08 /* HO = Half Octet Tag */
+#define GSM48_IE_CIP_MODE_SET_HO 0x09 /* HO = Half Octet Tag */
+#define GSM48_IE_GPRS_RESUMPT_HO 0xc0 /* HO = Half Octet Tag */
+#define GSM48_IE_SYNC_IND_HO 0x0d /* HO = Half Octet Tag */
#define GSM48_IE_MSLOT_DESC 0x10
#define GSM48_IE_CHANMODE_2 0x11
#define GSM48_IE_FRQSHORT_BEFORE 0x12
@@ -1556,6 +1852,7 @@ static inline const char *osmo_lu_type_name(uint8_t lu_type)
#define GSM48_IE_CHDES_2_AFTER 0x64
#define GSM48_IE_MODE_SEC_CH 0x66
#define GSM48_IE_F_CH_SEQ_AFTER 0x69
+#define GSM48_IE_EXTENDED_TSC_SET 0x6d
#define GSM48_IE_MA_AFTER 0x72
#define GSM48_IE_BA_RANGE 0x73
#define GSM48_IE_GROUP_CHDES 0x74
@@ -1566,20 +1863,21 @@ static inline const char *osmo_lu_type_name(uint8_t lu_type)
#define GSM48_IE_START_TIME 0x7c
#define GSM48_IE_INDIVIDUAL_PRIORITIES 0x7c /* 44.018 Section 9.1.7 */
#define GSM48_IE_TIMING_ADVANCE 0x7d
-#define GSM48_IE_GROUP_CIP_SEQ 0x80
-#define GSM48_IE_CIP_MODE_SET 0x90
-#define GSM48_IE_GPRS_RESUMPT 0xc0
-#define GSM48_IE_SYNC_IND 0xd0
+#define GSM48_IE_GROUP_CIP_SEQ 0x80 /* DEPRECATED, use GSM48_IE_GROUP_CIP_SEQ_HO instead */
+#define GSM48_IE_CIP_MODE_SET 0x90 /* DEPRECATED, use GSM48_IE_CIP_MODE_SET_HO instead */
+#define GSM48_IE_GPRS_RESUMPT 0xc0 /* DEPRECATED, use GSM48_IE_GPRS_RESUMPT_HO instead */
+#define GSM48_IE_SYNC_IND 0xd0 /* DEPRECATED, use GSM48_IE_SYNC_IND_HO instead */
/* System Information 4 (types are equal IEs above) */
#define GSM48_IE_CBCH_CHAN_DESC 0x64
#define GSM48_IE_CBCH_MOB_AL 0x72
/* Additional MM elements */
+#define GSM48_IE_PRIORITY_LEV_HO 0x08 /* HO = Half Octet Tag */
#define GSM48_IE_LOCATION_AREA 0x13
#define GSM48_IE_AUTN 0x20
#define GSM48_IE_AUTH_RES_EXT 0x21
#define GSM48_IE_AUTS 0x22
-#define GSM48_IE_PRIORITY_LEV 0x80
+#define GSM48_IE_PRIORITY_LEV 0x80 /* DEPRECATED, use GSM48_IE_PRIORITY_LEV_HO instead */
#define GSM48_IE_FOLLOW_ON_PROC 0xa1
#define GSM48_IE_CTS_PERMISSION 0xa2
@@ -1638,9 +1936,12 @@ enum gsm48_rr_cause {
GSM48_RR_CAUSE_ABNORMAL_TIMER = 0x03,
GSM48_RR_CAUSE_ABNORMAL_NOACT = 0x04,
GSM48_RR_CAUSE_PREMPTIVE_REL = 0x05,
+ GSM48_RR_CAUSE_UTRAN_CFG_UNK = 0x06,
GSM48_RR_CAUSE_HNDOVER_IMP = 0x08,
GSM48_RR_CAUSE_CHAN_MODE_UNACCT = 0x09,
GSM48_RR_CAUSE_FREQ_NOT_IMPL = 0x0a,
+ GSM48_RR_CAUSE_LEAVE_GROUP_CA = 0x0b,
+ GSM48_RR_CAUSE_LOW_LEVEL_FAIL = 0x0c,
GSM48_RR_CAUSE_CALL_CLEARED = 0x41,
GSM48_RR_CAUSE_SEMANT_INCORR = 0x5f,
GSM48_RR_CAUSE_INVALID_MAND_INF = 0x60,
@@ -1909,8 +2210,31 @@ enum gsm48_bcap_modem_type {
GSM48_BCAP_MT_AUTO_1 = 8,
};
+/*! Table 10.5.112/3GPP TS 24.008: Other modem type (octet 6d) */
+enum gsm48_bcap_other_modem_type {
+ GSM48_BCAP_OTHER_MT_NONE = 0, /*!< No other modem type specified */
+ GSM48_BCAP_OTHER_MT_V34 = 2, /*!< According to ITU-T Rec. V.34 */
+};
+
+/*! Table 10.5.112/3GPP TS 24.008: Fixed network user rate (octet 6d) */
+enum gsm48_bcap_fixed_net_user_rate {
+ GSM48_BCAP_FNUR_NONE = 0, /*!< FNUR not applicable / No meaning associated */
+ GSM48_BCAP_FNUR_X1_V110_9600 = 1, /*!< 9.6 kbit/s (according to ITU-T Rec. X.1 and V.110) */
+ GSM48_BCAP_FNUR_X1_V110_14400 = 2, /*!< 14.4 kbit/s (according to ITU-T Rec. X.1 and V.110) */
+ GSM48_BCAP_FNUR_X1_V110_19200 = 3, /*!< 19.2 kbit/s (according to ITU-T Rec. X.1 and V.110) */
+ GSM48_BCAP_FNUR_X1_V110_28800 = 4, /*!< 28.8 kbit/s (according to ITU-T Rec. X.1 and V.110) */
+ GSM48_BCAP_FNUR_X1_V110_38400 = 5, /*!< 38.4 kbit/s (according to ITU-T Rec. X.1 and V.110) */
+ GSM48_BCAP_FNUR_X1_V110_48000 = 6, /*!< 48.0 kbit/s (according to ITU-T Rec. X.1 and V.110) */
+ GSM48_BCAP_FNUR_X1_V110_56000 = 7, /*!< 56.0 kbit/s (according to ITU-T Rec. X.1 and V.110) */
+ GSM48_BCAP_FNUR_BT_64000 = 8, /*!< 64.0 kbit/s bit transparent */
+ GSM48_BCAP_FNUR_BT_33600 = 9, /*!< 33.6 kbit/s bit transparent */
+ GSM48_BCAP_FNUR_I460_32000 = 10, /*!< 32.0 kbit/s (according to ITU-T Rec. I.460) */
+ GSM48_BCAP_FNUR_V34_31200 = 11, /*!< 31.2 kbit/s (according to ITU-T Rec. V.34) */
+};
+
/*! GSM 04.08 Bearer Capability: Speech Version Indication
- * (See also 3GPP TS 24.008, Table 10.5.103) */
+ * (See also 3GPP TS 24.008, Table 10.5.103
+ * and 3GPP TS 26.103, Table 4.1 "Support of Codec Types in Radio Access Technologies") */
enum gsm48_bcap_speech_ver {
GSM48_BCAP_SV_FR = 0, /*!< GSM FR V1 (GSM FR) */
GSM48_BCAP_SV_HR = 1, /*!< GSM HR V1 (GSM HR) */
diff --git a/include/osmocom/gsm/protocol/gsm_04_08_gprs.h b/include/osmocom/gsm/protocol/gsm_04_08_gprs.h
index 86c5b016..2671aafb 100644
--- a/include/osmocom/gsm/protocol/gsm_04_08_gprs.h
+++ b/include/osmocom/gsm/protocol/gsm_04_08_gprs.h
@@ -1,7 +1,6 @@
/*! \file gsm_04_08_gprs.h */
-#ifndef _GSM48_GPRS_H
-#define _GSM48_GPRS_H
+#pragma once
#include <stdint.h>
#include <stdbool.h>
@@ -83,6 +82,8 @@ extern const struct value_string *gprs_upd_t_strs;
enum gsm48_gprs_ie_mm {
GSM48_IE_GMM_CIPH_CKSN = 0x08, /* 10.5.1.2 */
+ GSM48_IE_GMM_PTMSI_TYPE = 0x0e, /* 10.5.5.29 */
+ GSM48_IE_GMM_TMSI_BASED_NRI_C = 0x10, /* 10.5.5.31 */
GSM48_IE_GMM_TIMER_READY = 0x17, /* 10.5.7.3 */
GSM48_IE_GMM_ALLOC_PTMSI = 0x18, /* 10.5.1.4 */
GSM48_IE_GMM_PTMSI_SIG = 0x19, /* 10.5.5.8 */
@@ -90,26 +91,39 @@ enum gsm48_gprs_ie_mm {
GSM48_IE_GMM_AUTH_SRES = 0x22, /* 10.5.3.2 */
GSM48_IE_GMM_IMEISV = 0x23, /* 10.5.1.4 */
GSM48_IE_GMM_CAUSE = 0x25, /* 10.5.5.14 */
+ GSM48_IE_GMM_RX_NPDU_NUM_LIST = 0x26, /* 10.5.5.11 */
GSM48_IE_GMM_DRX_PARAM = 0x27, /* 10.5.5.6 */
GSM48_IE_GMM_AUTN = 0x28, /* 10.5.3.1.1 */
GSM48_IE_GMM_AUTH_RES_EXT = 0x29, /* 10.5.3.2.1 */
+ GSM48_IE_GMM_TIMER_T3302 = 0x2A, /* 10.5.7.4 */
GSM48_IE_GMM_AUTH_FAIL_PAR = 0x30, /* 10.5.3.2.2 */
GSM48_IE_GMM_MS_NET_CAPA = 0x31, /* 10.5.5.12 */
GSM48_IE_GMM_PDP_CTX_STATUS = 0x32, /* 10.5.7.1 */
GSM48_IE_GMM_PS_LCS_CAPA = 0x33, /* 10.5.5.22 */
GSM48_IE_GMM_GMM_MBMS_CTX_ST = 0x35, /* 10.5.7.6 */
+ GSM48_IE_GMM_TIMER_T3346 = 0x3A, /* 10.5.7.4 */
+ GSM48_IE_GMM_NET_FEAT_SUPPORT = 0xB0, /* 10.5.5.23 */
};
enum gsm48_gprs_ie_sm {
+ GSM48_IE_GSM_RADIO_PRIO = 0x08, /* 10.5.7.2 */
+ GSM48_IE_GSM_DEV_PROP = 0x0C, /* 10.5.7.8 */
GSM48_IE_GSM_APN = 0x28, /* 10.5.6.1 */
GSM48_IE_GSM_PROTO_CONF_OPT = 0x27, /* 10.5.6.3 */
GSM48_IE_GSM_PDP_ADDR = 0x2b, /* 10.5.6.4 */
GSM48_IE_GSM_AA_TMR = 0x29, /* 10.5.7.3 */
+ GSM48_IE_GSM_QOS = 0x30, /* 10.5.6.5 */
+ GSM48_IE_GSM_TFT = 0x31, /* 10.5.6.12 */
+ GSM48_IE_GSM_LLC_SAPI = 0x32, /* 10.5.6.9 */
+ GSM48_IE_GSM_MBIFOM_CONT = 0x33, /* 10.5.6.21 */
+ GSM48_IE_GSM_PFI = 0x34, /* 10.5.6.11 */
GSM48_IE_GSM_NAME_FULL = 0x43, /* 10.5.3.5a */
GSM48_IE_GSM_NAME_SHORT = 0x45, /* 10.5.3.5a */
GSM48_IE_GSM_TIMEZONE = 0x46, /* 10.5.3.8 */
GSM48_IE_GSM_UTC_AND_TZ = 0x47, /* 10.5.3.9 */
GSM48_IE_GSM_LSA_ID = 0x48, /* 10.5.3.11 */
+ GSM48_IE_GSM_EXT_QOS = 0x5C, /* 10.5.6.5B */
+ GSM48_IE_GSM_EXT_PROTO_CONF_OPT = 0x7B, /* 10.5.6.3a */
/* Fake IEs that are not present on the Layer3 air interface,
* but which we use to simplify internal APIs */
@@ -128,7 +142,7 @@ struct gsm48_ra_upd_ack {
struct gsm48_ra_id ra_id; /* 10.5.5.15 */
uint8_t data[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t upd_result:4, force_stby:4;
uint8_t ra_upd_timer;
struct gsm48_ra_id ra_id;
@@ -157,7 +171,7 @@ struct gsm48_attach_ack {
struct gsm48_ra_id ra_id; /* 10.5.5.15 */
uint8_t data[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t force_stby:4, att_result:4;
uint8_t ra_upd_timer;
uint8_t radio_prio;
@@ -175,7 +189,7 @@ struct gsm48_auth_ciph_req {
ac_ref_nr:4; /* 10.5.5.19 */
uint8_t data[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t imeisv_req:4, ciph_alg:4;
uint8_t ac_ref_nr:4, force_stby:4;
uint8_t data[0];
@@ -189,7 +203,7 @@ struct gsm48_auth_ciph_resp {
spare:4;
uint8_t data[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t spare:4, ac_ref_nr:4;
uint8_t data[0];
#endif
@@ -280,17 +294,52 @@ enum gsm48_pdp_state {
PDP_S_MODIFY_PENDING,
};
-/* Table 10.5.155/3GPP TS 24.008 */
+/* TS 24.008 Table 10.5.155/3GPP */
enum gsm48_pdp_type_org {
PDP_TYPE_ORG_ETSI = 0x00,
PDP_TYPE_ORG_IETF = 0x01,
+ PDP_TYPE_ORG_EMPTY = 0x0f,
};
enum gsm48_pdp_type_nr {
PDP_TYPE_N_ETSI_RESERVED = 0x00,
PDP_TYPE_N_ETSI_PPP = 0x01,
PDP_TYPE_N_IETF_IPv4 = 0x21,
PDP_TYPE_N_IETF_IPv6 = 0x57,
+ PDP_TYPE_N_IETF_IPv4v6 = 0x8D,
};
+/* TS 24.008 10.5.6.4 "Packet data protocol address" value
+ * Note: This can be reused for 3GPP TS 29.060 7.7.27 "End User Address"
+ * with minor changes in the values, like spare being 1111 instead.
+*/
+struct gsm48_pdp_address {
+#if OSMO_IS_LITTLE_ENDIAN
+uint8_t organization:4, /* enum gsm48_pdp_type_org */
+ spare:4; /* 0000 */
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+uint8_t spare:4, organization:4;
+#endif
+uint8_t type; /* enum gsm48_pdp_type_nr */
+ union {
+ /* PDP_TYPE_ORG_ETSI */
+ union {
+ } etsi;
+ /* PDP_TYPE_ORG_IETF */
+ union {
+ /* PDP_TYPE_N_IETF_IPv4 */
+ uint32_t v4;
+
+ /* PDP_TYPE_N_IETF_IPv6 */
+ uint8_t v6[16];
+
+ /* PDP_TYPE_N_IETF_IPv4v6 */
+ struct {
+ uint32_t v4;
+ uint8_t v6[16];
+ } __attribute__ ((packed)) v4v6;
+ } ietf;
+ };
+} __attribute__ ((packed));
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_reliab_class {
@@ -463,6 +512,3 @@ struct gsm48_qos {
/* octet 16 */
uint8_t guar_bitrate_down_ext;
};
-
-
-#endif /* _GSM48_GPRS_H */
diff --git a/include/osmocom/gsm/protocol/gsm_04_11.h b/include/osmocom/gsm/protocol/gsm_04_11.h
index 31f25acb..90543020 100644
--- a/include/osmocom/gsm/protocol/gsm_04_11.h
+++ b/include/osmocom/gsm/protocol/gsm_04_11.h
@@ -62,6 +62,16 @@ enum gsm411_rp_ie {
GSM411_IE_RP_CAUSE = 0x42, /* 8.2.5.4 */
};
+/* Sections 8.2.5.1 and 8.2.5.2 set limits on the length of an SMSC-address.
+ * The spec states these limits in terms of min and max values of the length
+ * octet in type 4 IEs SM-RP-OA and SM-RP-DA; these IE length limits translate
+ * into a minimum of 1 digit and a maximum of 20 digits.
+ */
+#define GSM411_SMSC_ADDR_MIN_OCTETS 2
+#define GSM411_SMSC_ADDR_MAX_OCTETS 11
+#define GSM411_SMSC_ADDR_MIN_DIGITS 1
+#define GSM411_SMSC_ADDR_MAX_DIGITS 20
+
/* Chapter 8.2.5.4 Table 8.4 */
enum gsm411_rp_cause {
/* valid only for MO */
diff --git a/include/osmocom/gsm/protocol/gsm_04_12.h b/include/osmocom/gsm/protocol/gsm_04_12.h
index 3f34ee7f..17ac6454 100644
--- a/include/osmocom/gsm/protocol/gsm_04_12.h
+++ b/include/osmocom/gsm/protocol/gsm_04_12.h
@@ -23,7 +23,7 @@ struct gsm412_block_type {
lpd : 2,
spare : 1;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t spare:1, lpd:2, lb:1, seq_nr:4;
#endif
} __attribute__((packed));
@@ -37,7 +37,7 @@ struct gsm412_sched_msg {
uint8_t cbsms_msg_map[6];
uint8_t data[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t type:2, beg_slot_nr:6;
uint8_t spare2:1, spare1:1, end_slot_nr:6;
uint8_t cbsms_msg_map[6];
diff --git a/include/osmocom/gsm/protocol/gsm_04_14.h b/include/osmocom/gsm/protocol/gsm_04_14.h
index deb474ec..dddec519 100644
--- a/include/osmocom/gsm/protocol/gsm_04_14.h
+++ b/include/osmocom/gsm/protocol/gsm_04_14.h
@@ -30,7 +30,7 @@ struct gsm414_close_mslot_loop_cmd {
loop_mech:3,
tn:3;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t tn:3, loop_mech:3, chc:2;
#endif
} __attribute__((packed));
@@ -43,7 +43,7 @@ struct gsm414_close_mslot_loop_ack {
chc:2,
spare:2;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t spare:2, chc:2, loop_mech:3, err_ind:1;
#endif
} __attribute__((packed));
@@ -70,7 +70,7 @@ struct gsm414_gprs_test_mode_cmd {
dl_tx_offset:3,
_spare:4;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint16_t d:12,
spare:3,
l:1;
@@ -86,7 +86,7 @@ struct gsm414_egprs_st_sb_loop_cmd {
dl_tx_offset:3,
m:1;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t m:1, dl_tx_offset:3, _spare:4;
#endif
} __attribute__((packed));
diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h
index 1390f0e8..1e211dc9 100644
--- a/include/osmocom/gsm/protocol/gsm_08_08.h
+++ b/include/osmocom/gsm/protocol/gsm_08_08.h
@@ -25,6 +25,10 @@ enum CELL_IDENT {
CELL_IDENT_UTRAN_PLMN_LAC_RNC = 8,
CELL_IDENT_UTRAN_RNC = 9,
CELL_IDENT_UTRAN_LAC_RNC = 10,
+ CELL_IDENT_SAI = 11,
+
+ /* Not in 03.03 nor 08.08. Place them > 0x0f (discr_id is 4 bits) */
+ CELL_IDENT_WHOLE_GLOBAL_PS = 128, /* CGI + RAC, TS 48.018 8c.1.4.1.1 */
};
/* Keep this misnamed CELL_IDENT for API backwards compatibility (see OS#3124). */
#define CELL_IDENT_LAI_AND_LAC CELL_IDENT_LAI
@@ -46,12 +50,12 @@ struct dtap_header {
uint8_t link_id; /* Backward compatibility */
struct {
#if OSMO_IS_LITTLE_ENDIAN
- uint8_t dlci_cc:2,
+ uint8_t dlci_sapi:3, /* enum gsm0406_dlci_sapi */
dlci_spare:3,
- dlci_sapi:3; /* enum gsm0406_dlc_sapi */
+ dlci_cc:2;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t dlci_sapi:3, dlci_spare:3, dlci_cc:2;
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t dlci_cc:2, dlci_spare:3, dlci_sapi:3;
#endif
};
};
@@ -164,12 +168,15 @@ enum BSS_MAP_MSG_TYPE {
BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION = 30,
BSS_MAP_MSG_UPLINK_RQST = 31,
BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE = 39,
+ BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_STATUS = 59,
+ BSS_MAP_MSG_VGCS_VBS_AREA_CELL_INFO = 60,
BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION = 73,
BSS_MAP_MSG_UPLINK_RELEASE_INDICATION = 74,
BSS_MAP_MSG_UPLINK_REJECT_CMD = 75,
BSS_MAP_MSG_UPLINK_RELEASE_CMD = 76,
BSS_MAP_MSG_UPLINK_SEIZED_CMD = 77,
BSS_MAP_MSG_VGCS_ADDL_INFO = 0x60,
+ BSS_MAP_MSG_VGCS_SMS = 0x61,
BSS_MAP_MSG_NOTIFICATION_DATA = 0x62,
BSS_MAP_MSG_UPLINK_APP_DATA = 0x63,
@@ -262,7 +269,7 @@ enum GSM0808_IE_CODING {
GSM0808_IE_SEGMENTATION = 79,
GSM0808_IE_SERVICE_HANDOVER = 80,
GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_UMTS = 81,
- GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000= 82,
+ GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000 = 82,
GSM0808_IE_RESERVED_5 = 65,
GSM0808_IE_RESERVED_6 = 66,
GSM0808_IE_GERAN_CLASSMARK = 0x53,
@@ -330,7 +337,8 @@ enum GSM0808_IE_CODING {
GSM0808_IE_OSMO_OSMUX_CID = 0xf1,
};
-/* 3GPP TS 48.008 3.2.3 Signalling Field Element Coding */
+/* 3GPP TS 48.008 3.2.3 Signalling Field Element Coding.
+ See also extra fields in 3.2.2.58 and 3.2.2.80 */
enum GSM0808_SIGNALLING_FIELD_ELEMENT_CODING {
GSM0808_FE_IE_EXTRA_INFORMATION = 0x01, /*< 3.2.3.1 */
GSM0808_FE_IE_CURRENT_CHANNEL_TYPE_2 = 0x02, /*< 3.2.3.2 */
@@ -350,6 +358,8 @@ enum GSM0808_SIGNALLING_FIELD_ELEMENT_CODING {
GSM0808_FE_IE_IRAT_MEASUREMENT_CONFIGURATION = 0x0f, /*< 3.2.3.16 */
GSM0808_FE_IE_SOURCE_CELL_ID = 0x10, /*< 3.2.3.17 */
GSM0808_FE_IE_IRAT_MEASUREMENT_CONFIGURATION_EXTENDED_E_ARFCNS = 0x11, /*< 3.2.3.18 */
+ GSM0808_FE_IE_VGCS_TALKER_MODE = 0x6f, /*< 3.2.2.93 */
+ GSM0808_FE_IE_LAST_USED_EUTRAN_PLMN_ID = 0x95, /*< 3.2.2.127 */
};
/* 3GPP TS 48.008 3.2.2.5 Cause */
@@ -436,13 +446,15 @@ enum gsm0808_chan_indicator {
GSM0808_CHAN_SPEECH = 1,
GSM0808_CHAN_DATA = 2,
GSM0808_CHAN_SIGN = 3,
+ GSM0808_CHAN_SPEECH_CTM_TEXT_TELEPHONY = 4,
};
/* GSM 08.08 3.2.2.11 Channel Type */
+#define GSM0808_DATA_FULL_RPREF GSM0808_DATA_FULL_PREF
enum gsm0808_chan_rate_type_data {
GSM0808_DATA_FULL_BM = 0x8,
GSM0808_DATA_HALF_LM = 0x9,
- GSM0808_DATA_FULL_RPREF = 0xa,
+ GSM0808_DATA_FULL_PREF = 0xa,
GSM0808_DATA_HALF_PREF = 0xb,
GSM0808_DATA_FULL_PREF_NO_CHANGE = 0x1a,
GSM0808_DATA_HALF_PREF_NO_CHANGE = 0x1b,
@@ -491,6 +503,42 @@ enum gsm0808_permitted_speech {
GSM0808_PERM_HR6 = 0x45, /*!< OHR AMR */
};
+/* 3GPP TS 48.008 3.2.2.11 Channel Type
+ * Transparent: Data Rate */
+enum gsm0808_data_rate_transp {
+ GSM0808_DATA_RATE_TRANSP_32k0 = 0x3a,
+ GSM0808_DATA_RATE_TRANSP_28k8 = 0x39,
+ GSM0808_DATA_RATE_TRANSP_14k4 = 0x18,
+ GSM0808_DATA_RATE_TRANSP_9k6 = 0x10,
+ GSM0808_DATA_RATE_TRANSP_4k8 = 0x11,
+ GSM0808_DATA_RATE_TRANSP_2k4 = 0x12,
+ GSM0808_DATA_RATE_TRANSP_1k2 = 0x13,
+ GSM0808_DATA_RATE_TRANSP_600 = 0x14,
+ GSM0808_DATA_RATE_TRANSP_1200_75 = 0x15,
+};
+
+/* 3GPP TS 48.008 3.2.2.11 Channel Type
+ * Non-Transparent: Radio Interface Data Rate (preferred) */
+enum gsm0808_data_rate_non_transp {
+ GSM0808_DATA_RATE_NON_TRANSP_12000_6000 = 0x00,
+ GSM0808_DATA_RATE_NON_TRANSP_43k5 = 0x34,
+ GSM0808_DATA_RATE_NON_TRANSP_29k0 = 0x31,
+ GSM0808_DATA_RATE_NON_TRANSP_14k5 = 0x14,
+ GSM0808_DATA_RATE_NON_TRANSP_12k0 = 0x10,
+ GSM0808_DATA_RATE_NON_TRANSP_6k0 = 0x11,
+};
+
+/* 3GPP TS 48.008 3.2.2.11 Channel Type
+ * Non-Transparent: Allowed Radio Interface Data Rate (all possible allowed) */
+enum gsm0808_data_rate_allowed_r_if {
+ GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_43k5 = 0x40,
+ GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_32k0 = 0x20,
+ GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_29k0 = 0x10,
+ GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_14k5 = 0x08,
+ GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_12k0 = 0x02,
+ GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_6k0 = 0x01,
+};
+
extern const struct value_string gsm0808_permitted_speech_names[];
static inline const char *gsm0808_permitted_speech_name(enum gsm0808_permitted_speech val)
{ return get_value_string(gsm0808_permitted_speech_names, val); }
@@ -509,6 +557,12 @@ enum gsm0808_speech_codec_type {
GSM0808_SCT_CSD = 0xfd, /*!< CSData (see also TS 26.103) */
};
+/* Codec Extension (the real Codec Type follows in the next octet).
+ * This value is intentionally not included in gsm0808_speech_codec_type,
+ * because {enc,dec}_speech_codec() functions take care of the extended
+ * encoding internally. It shall not be used in struct gsm0808_speech_codec. */
+#define GSM0808_SCT_EXT 0x0f
+
extern const struct value_string gsm0808_speech_codec_type_names[];
static inline const char *gsm0808_speech_codec_type_name(enum gsm0808_speech_codec_type val)
{ return get_value_string(gsm0808_speech_codec_type_names, val); }
@@ -533,11 +587,16 @@ enum gsm0808_paging_info {
GSM0808_PAGINF_FOR_USSD = 0x02,
};
-/*! 3GPP TS 48.008 3.2.2.104 Speech Codec */
+/*! 3GPP TS 48.008 3.2.2.104 Speech Codec.
+ * Valid if (fi || pi || pt) == true, otherwise ignore. */
struct gsm0808_speech_codec {
+ /*! Full IP: AoIP with compressed speech via RTP/UDP/IP. */
bool fi;
+ /*! PCMoIP: PCM over A-Interface via RTP/UPD/IP. */
bool pi;
+ /*! PCMoTDM: PCM over A-Interface with TDM as transport. */
bool pt;
+ /*! TFO (Inband Tandem Free Operation). Only valid if (pi || pt) == true. */
bool tf;
/*! See enum gsm0808_speech_codec_type. */
uint8_t type;
@@ -556,7 +615,44 @@ struct gsm0808_speech_codec {
*
* Default values for FR_AMR_WB, OFR_AMR_WB and OHR_AMR_WB:
* See also: 3GPP TS 26.103, Table 5.7-1: Allowed Configurations
- * for the Adaptive Multi-Rate - Wideband Codec Types */
+ * for the Adaptive Multi-Rate - Wideband Codec Types
+ *
+ * This is a copy of 3GPP TS 28.062, Table 7.11.3.1.3-2:
+ *
+ * S0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ * 12,20 (x) x x x
+ * 10,20 x x x
+ * 7,95 x x x
+ * 7,40 x x x x
+ * 6,70 x x x x x x
+ * 5,90 x x x x x x x x x x
+ * 5,15
+ * 4,75 x x x x x x x x x x
+ *
+ * OM F F F F F F F F F F F A F A F A
+ *
+ * HR Y Y Y Y Y Y Y Y Y
+ * FR Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
+ *
+ * Each bit allows one Codec Configuration.
+ * E.g. when bit S3 is set, look at column labeled "3", and see that only 6,7k is active in this configuration; it is
+ * "F" forbidden to change in Optimisation Mode, "Y" HR AMR supports this mode, and "Y" FR AMR can also do it.
+ *
+ * This means that whichever configuration is chosen from S0 thru S15, there are never more than four rates active.
+ *
+ * The spec praises S1 as the most desired configuration: "because it leads in all call cases to TFO/TrFO compatible
+ * connections with optimal voice quality." (Since HR AMR supports up to 7.95k, it seems that S14 would be more optimal
+ * voice quality, but it is not marked as supported by HR AMR.)
+ *
+ * For FR_AMR below, the default of 0x57ff means:
+ * 0x57ff = 0101 0111 1111 1111
+ * ^14 ^10 ^0
+ * allow config 0 thru 10, and configs 12 and 14.
+ *
+ * For HR_AMR, drop all those where there is no "Y" in the HR row:
+ * 0x073f = 0000 0111 0011 1111
+ * ^15 ^11 ^6 ^0
+ */
enum gsm0808_speech_codec_defaults {
GSM0808_SC_CFG_DEFAULT_FR_AMR = 0x57ff,
GSM0808_SC_CFG_DEFAULT_HR_AMR = 0x073f,
@@ -566,9 +662,12 @@ enum gsm0808_speech_codec_defaults {
GSM0808_SC_CFG_DEFAULT_OHR_AMR_WB = 0x01,
};
-/*! Default speech codec configurations broken down by reate.
+/*! Default speech codec configurations broken down by rate.
* See also: 3GPP TS 28.062, Table 7.11.3.1.3-2: Preferred Configurations for
- * the Adaptive Multi-Rate Codec Types. */
+ * the Adaptive Multi-Rate Codec Types.
+ *
+ * Set all Sn bits that have this rate listed as active.
+ */
enum gsm0808_speech_codec_rate_defaults {
GSM0808_SC_CFG_DEFAULT_AMR_4_75 = 0xff03,
GSM0808_SC_CFG_DEFAULT_AMR_5_15 = 0x0000,
@@ -580,9 +679,12 @@ enum gsm0808_speech_codec_rate_defaults {
GSM0808_SC_CFG_DEFAULT_AMR_12_2 = 0xc082
};
-/*! Single speech codec configurations broken down by reate.
+/*! Single speech codec configurations broken down by rate.
* See also: 3GPP TS 28.062, Table 7.11.3.1.3-2: Preferred Configurations for
- * the Adaptive Multi-Rate Codec Types. */
+ * the Adaptive Multi-Rate Codec Types.
+ *
+ * Set bit Sn (S0 = 0x01), where Sn is identified by a descriptive name.
+ */
enum gsm0808_speech_codec_rate {
GSM0808_SC_CFG_AMR_4_75 = 0x0001,
GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20 = 0x0002,
@@ -594,6 +696,29 @@ enum gsm0808_speech_codec_rate {
GSM0808_SC_CFG_AMR_12_2 = 0x0080,
};
+/* Bit index of a mode as returned by gsm0808_amr_modes_from_cfg[].
+ * Example:
+ * if (gsm0808_amr_modes_from_cfg[full_rate ? 1 : 0][9] & GSM0808_AMR_MODE_4_75)
+ * printf("S9 supports 4k75");
+ */
+enum gsm0808_amr_mode {
+ GSM0808_AMR_MODE_4_75 = 0,
+ GSM0808_AMR_MODE_5_15,
+ GSM0808_AMR_MODE_5_90,
+ GSM0808_AMR_MODE_6_70,
+ GSM0808_AMR_MODE_7_40,
+ GSM0808_AMR_MODE_7_95,
+ GSM0808_AMR_MODE_10_2,
+ GSM0808_AMR_MODE_12_2,
+};
+extern const struct value_string gsm0808_amr_mode_names[];
+static inline const char *gsm0808_amr_mode_name(enum gsm0808_amr_mode val)
+{
+ return get_value_string(gsm0808_amr_mode_names, val);
+}
+
+extern const uint8_t gsm0808_amr_modes_from_cfg[2][16];
+
/* 3GPP TS 48.008 3.2.2.103 Speech Codec List */
#define SPEECH_CODEC_MAXLEN 255
struct gsm0808_speech_codec_list {
@@ -601,13 +726,32 @@ struct gsm0808_speech_codec_list {
uint8_t len;
};
+/* 3GPP TS 48.008 3.2.2.11 Channel Type
+ * Asymmetry Preference (used for data, non-transparent service) */
+enum gsm0808_channel_type_asym_pref {
+ GSM0808_CT_ASYM_PREF_NOT_APPLICABLE = 0,
+ GSM0808_CT_ASYM_PREF_UL = 1,
+ GSM0808_CT_ASYM_PREF_DL = 2,
+ GSM0808_CT_ASYM_PREF_SPARE = 3,
+};
+
/* 3GPP TS 48.008 3.2.2.11 Channel Type */
#define CH_TYPE_PERM_SPCH_MAXLEN 9
struct gsm0808_channel_type {
uint8_t ch_indctr;
uint8_t ch_rate_type;
+
+ /* Speech only */
uint8_t perm_spch[CH_TYPE_PERM_SPCH_MAXLEN];
unsigned int perm_spch_len;
+
+ /* Data only */
+ bool data_transparent;
+ uint8_t data_rate;
+ bool data_rate_allowed_is_set;
+ uint8_t data_rate_allowed;
+ bool data_asym_pref_is_set;
+ enum gsm0808_channel_type_asym_pref data_asym_pref;
};
/* 3GPP TS 48.008 3.2.2.10 Encryption Information */
@@ -671,7 +815,7 @@ struct gsm0808_diagnostics {
uint8_t error_pointer_bit_spare:4,
error_pointer_bit:4;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t error_pointer_bit:4, error_pointer_bit_spare:4;
#endif
uint8_t msg[0]; /*! received message which provoked the error */
diff --git a/include/osmocom/gsm/protocol/gsm_08_58.h b/include/osmocom/gsm/protocol/gsm_08_58.h
index cd13a7dc..e8758df0 100644
--- a/include/osmocom/gsm/protocol/gsm_08_58.h
+++ b/include/osmocom/gsm/protocol/gsm_08_58.h
@@ -15,10 +15,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#pragma once
@@ -33,6 +29,7 @@
/* Channel Number 9.3.1 */
union abis_rsl_chan_nr {
+ struct {
#if OSMO_IS_BIG_ENDIAN
uint8_t cbits:5,
tn:3;
@@ -40,7 +37,8 @@ union abis_rsl_chan_nr {
uint8_t tn:3,
cbits:5;
#endif
- uint8_t chan_nr;
+ } __attribute__ ((packed));
+ uint8_t chan_nr;
} __attribute__ ((packed));
#define ABIS_RSL_CHAN_NR_CBITS_Bm_ACCHs 0x01
#define ABIS_RSL_CHAN_NR_CBITS_Lm_ACCHs(ss) (0x02 + (ss))
@@ -53,8 +51,13 @@ union abis_rsl_chan_nr {
#define ABIS_RSL_CHAN_NR_CBITS_OSMO_CBCH4 0x19 /*< non-standard, for CBCH/SDCCH4 */
#define ABIS_RSL_CHAN_NR_CBITS_OSMO_CBCH8 0x1a /*< non-standard, for CBCH/SDCCH8 */
+/* non-standard, Osmocom specific Bm/Lm equivalents for VAMOS */
+#define ABIS_RSL_CHAN_NR_CBITS_OSMO_VAMOS_Bm_ACCHs 0x1d /*< VAMOS TCH/F */
+#define ABIS_RSL_CHAN_NR_CBITS_OSMO_VAMOS_Lm_ACCHs(ss) (0x1e + (ss)) /*< VAMOS TCH/H */
+
/* Link Identifier 9.3.2 */
union abis_rsl_link_id {
+ struct {
#if OSMO_IS_BIG_ENDIAN
uint8_t cbits:2,
na:1,
@@ -66,7 +69,8 @@ union abis_rsl_link_id {
na:1,
cbits:2;
#endif
- uint8_t link_id;
+ } __attribute__ ((packed));
+ uint8_t link_id;
} __attribute__ ((packed));
#define ABIS_RSL_LINK_ID_CBITS_FACCH_SDCCH 0x00
#define ABIS_RSL_LINK_ID_CBITS_SACCH 0x01
@@ -116,6 +120,33 @@ struct abis_rsl_cchan_hdr {
uint8_t data[0]; /*!< message payload data */
} __attribute__ ((packed));
+/* Osmocom specific IE to negotiate repeated ACCH capabilities */
+struct abis_rsl_osmo_rep_acch_cap {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t dl_facch_cmd:1,
+ dl_facch_all:1,
+ dl_sacch:1,
+ ul_sacch:1,
+ rxqual:3,
+ reserved:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t reserved:1, rxqual:3, ul_sacch:1, dl_sacch:1, dl_facch_all:1, dl_facch_cmd:1;
+#endif
+} __attribute__ ((packed));
+
+/* Osmocom specific IE to negotiate temporary overpower of ACCH channels */
+struct abis_rsl_osmo_temp_ovp_acch_cap {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t overpower_db:3,
+ rxqual:3,
+ facch_enable:1,
+ sacch_enable:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t sacch_enable:1, facch_enable:1, rxqual:3, overpower_db:3;
+#endif
+} __attribute__ ((packed));
/* Chapter 9.1 */
/* RSL Message Discriminator: RLL */
@@ -337,6 +368,12 @@ enum abis_rsl_ie {
RSL_IE_SIEMENS_HIGHEST_RATE = 0x4e,
RSL_IE_SIEMENS_SUGGESTED_RATE = 0x4f,
+ /* Osmocom specific */
+ RSL_IE_OSMO_REP_ACCH_CAP = 0x60,
+ RSL_IE_OSMO_TRAINING_SEQUENCE = 0x61,
+ RSL_IE_OSMO_TEMP_OVP_ACCH_CAP = 0x62,
+ RSL_IE_OSMO_OSMUX_CID = 0x63,
+
/* ip.access */
RSL_IE_IPAC_SRTP_CONFIG = 0xe0,
RSL_IE_IPAC_PROXY_UDP = 0xe1,
@@ -353,9 +390,9 @@ enum abis_rsl_ie {
RSL_IE_IPAC_RTP_CSD_FMT = 0xf9,
RSL_IE_IPAC_RTP_JIT_BUF = 0xfa,
RSL_IE_IPAC_RTP_COMPR = 0xfb,
- RSL_IE_IPAC_RTP_PAYLOAD2= 0xfc,
+ RSL_IE_IPAC_RTP_PAYLOAD2 = 0xfc,
RSL_IE_IPAC_RTP_MPLEX = 0xfd,
- RSL_IE_IPAC_RTP_MPLEX_ID= 0xfe,
+ RSL_IE_IPAC_RTP_MPLEX_ID = 0xfe,
};
/* Ericsson specific IEs, clash with above partially, so they're not
@@ -385,10 +422,12 @@ enum abis_rsl_ie {
enum {
IPAC_UNWEIGHTED_AVE = 0,
IPAC_WEIGHTED_AVE,
- IPAC_MEDIAN_AVE
+ IPAC_MEDIAN_AVE,
+ /* EWMA is an Osmocom specific extension */
+ IPAC_OSMO_EWMA_AVE,
};
-/* IPAC MEAS_PREPROC AVERAGING PARAMID */
+/* IPAC MEAS_PREPROC AVERAGING PARAM ID */
enum {
IPAC_RXLEV_AVE = 0,
IPAC_RXQUAL_AVE,
@@ -431,6 +470,11 @@ enum {
#define RSL_CHAN_OSMO_CBCH4 0xc8 /*< non-standard, for CBCH/SDCCH4 */
#define RSL_CHAN_OSMO_CBCH8 0xd0 /*< non-standard, for CBCH/SDCCH8 */
+/* non-standard, Osmocom specific Bm/Lm equivalents for VAMOS */
+#define RSL_CHAN_OSMO_VAMOS_Bm_ACCHs 0xe8 /* VAMOS TCH/F */
+#define RSL_CHAN_OSMO_VAMOS_Lm_ACCHs 0xf0 /* VAMOS TCH/H */
+#define RSL_CHAN_OSMO_VAMOS_MASK 0xe0 /* VAMOS TCH/{F,H} */
+
/* Chapter 9.3.3 */
#define RSL_ACT_TYPE_INITIAL 0x00
#define RSL_ACT_TYPE_REACT 0x80
@@ -456,34 +500,66 @@ enum rsl_cmod_spd {
RSL_CMOD_SPD_DATA = 0x02,
RSL_CMOD_SPD_SIGN = 0x03,
};
-#define RSL_CMOD_CRT_SDCCH 0x01
-#define RSL_CMOD_CRT_TCH_Bm 0x08 /* full-rate */
-#define RSL_CMOD_CRT_TCH_Lm 0x09 /* half-rate */
-/* FIXME: More CRT types */
-/* Speech */
-#define RSL_CMOD_SP_GSM1 0x01
-#define RSL_CMOD_SP_GSM2 0x11
-#define RSL_CMOD_SP_GSM3 0x21
-/* non-transparent data */
-#define RSL_CMOD_CSD_NT_43k5 0x74
-#define RSL_CMOD_CSD_NT_28k8 0x71
-#define RSL_CMOD_CSD_NT_14k5 0x58
-#define RSL_CMOD_CSD_NT_12k0 0x50
-#define RSL_CMOD_CSD_NT_6k0 0x51
+/*! Channel rate and type */
+enum rsl_cmod_crt {
+ RSL_CMOD_CRT_SDCCH = 0x01,
+ RSL_CMOD_CRT_TCH_Bm = 0x08, /* full-rate */
+ RSL_CMOD_CRT_TCH_Lm = 0x09, /* half-rate */
+ RSL_CMOD_CRT_TCH_BI_Bm = 0x0a, /* full-rate: bi-directional (multislot) */
+ RSL_CMOD_CRT_TCH_UNI_Bm = 0x1a, /* full-rate: uni-directional (multislot) */
+ RSL_CMOD_CRT_TCH_GROUP_Bm = 0x18, /* full-rate: group call channel */
+ RSL_CMOD_CRT_TCH_GROUP_Lm = 0x19, /* half-rate: group call channel */
+ RSL_CMOD_CRT_TCH_BCAST_Bm = 0x28, /* full-rate: broadcast call channel */
+ RSL_CMOD_CRT_TCH_BCAST_Lm = 0x29, /* half-rate: broadcast call channel */
+ RSL_CMOD_CRT_OSMO_TCH_VAMOS_Bm = 0x88, /* full-rate in VAMOS mode */
+ RSL_CMOD_CRT_OSMO_TCH_VAMOS_Lm = 0x89, /* half-rate in VAMOS mode */
+};
+/*! Speech */
+enum rsl_cmod_sp {
+ RSL_CMOD_SP_GSM1 = 0x01,
+ RSL_CMOD_SP_GSM2 = 0x11,
+ RSL_CMOD_SP_GSM3 = 0x21,
+ RSL_CMOD_SP_GSM4 = 0x31,
+ RSL_CMOD_SP_GSM5 = 0x09,
+ RSL_CMOD_SP_GSM6 = 0x0d,
+};
+/*! Non-transparent data */
+enum rsl_cmod_csd_nt {
+ RSL_CMOD_CSD_NTA_43k5_14k5 = 0x61, /* asymmetric 43.5 kbit/s (DL) + 14.5 kbit/s (UL) */
+ RSL_CMOD_CSD_NTA_29k0_14k5 = 0x62, /* asymmetric 29.0 kbit/s (DL) + 14.5 kbit/s (UL) */
+ RSL_CMOD_CSD_NTA_43k5_29k0 = 0x63, /* asymmetric 43.5 kbit/s (DL) + 29.0 kbit/s (UL) */
+ RSL_CMOD_CSD_NTA_14k5_43k5 = 0x69, /* asymmetric 14.5 kbit/s (DL) + 43.5 kbit/s (UL) */
+ RSL_CMOD_CSD_NTA_14k5_29k0 = 0x6a, /* asymmetric 14.5 kbit/s (DL) + 29.0 kbit/s (UL) */
+ RSL_CMOD_CSD_NTA_29k0_43k5 = 0x6b, /* asymmetric 29.0 kbit/s (DL) + 43.5 kbit/s (UL) */
+ RSL_CMOD_CSD_NT_43k5 = 0x74,
+ RSL_CMOD_CSD_NT_28k8 = 0x71,
+ RSL_CMOD_CSD_NT_14k5 = 0x58,
+ RSL_CMOD_CSD_NT_12k0 = 0x50,
+ RSL_CMOD_CSD_NT_6k0 = 0x51,
+};
/* legacy #defines with wrong name */
#define RSL_CMOD_SP_NT_14k5 RSL_CMOD_CSD_NT_14k5
#define RSL_CMOD_SP_NT_12k0 RSL_CMOD_CSD_NT_12k0
#define RSL_CMOD_SP_NT_6k0 RSL_CMOD_CSD_NT_6k0
-/* transparent data */
-#define RSL_CMOD_CSD_T_32000 0x38
-#define RSL_CMOD_CSD_T_29000 0x39
-#define RSL_CMOD_CSD_T_14400 0x18
-#define RSL_CMOD_CSD_T_9600 0x10
-#define RSL_CMOD_CSD_T_4800 0x11
-#define RSL_CMOD_CSD_T_2400 0x12
-#define RSL_CMOD_CSD_T_1200 0x13
-#define RSL_CMOD_CSD_T_600 0x14
-#define RSL_CMOD_CSD_T_1200_75 0x15
+#define RSL_CMOD_CSD_T_32000 RSL_CMOD_CSD_T_32k0
+#define RSL_CMOD_CSD_T_29000 RSL_CMOD_CSD_T_29k0
+#define RSL_CMOD_CSD_T_14400 RSL_CMOD_CSD_T_14k4
+#define RSL_CMOD_CSD_T_9600 RSL_CMOD_CSD_T_9k6
+#define RSL_CMOD_CSD_T_4800 RSL_CMOD_CSD_T_4k8
+#define RSL_CMOD_CSD_T_2400 RSL_CMOD_CSD_T_2k4
+#define RSL_CMOD_CSD_T_1200 RSL_CMOD_CSD_T_1k2
+/*! Transparent data */
+enum rsl_cmod_csd_t {
+ RSL_CMOD_CSD_T_32k0 = 0x38,
+ RSL_CMOD_CSD_T_29k0 = 0x39,
+ RSL_CMOD_CSD_T_14k4 = 0x18,
+ RSL_CMOD_CSD_T_9k6 = 0x10,
+ RSL_CMOD_CSD_T_4k8 = 0x11,
+ RSL_CMOD_CSD_T_2k4 = 0x12,
+ RSL_CMOD_CSD_T_1k2 = 0x13,
+ RSL_CMOD_CSD_T_600 = 0x14,
+ RSL_CMOD_CSD_T_1200_75 = 0x15,
+};
/*! RSL Channel Identification IE (Chapter 9.3.5) */
struct rsl_ie_chan_ident {
@@ -601,7 +677,7 @@ struct rsl_ie_chan_ident {
#define RSL_CHANNEED_TCH_F 0x02
#define RSL_CHANNEED_TCH_ForH 0x03
-/*! RSL Cell Broadcast Command (Chapter 9.3.45) */
+/*! RSL Cell Broadcast Command (Chapter 9.3.41) */
struct rsl_ie_cb_cmd_type {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t last_block:2;
@@ -609,7 +685,7 @@ struct rsl_ie_cb_cmd_type {
uint8_t def_bcast:1;
uint8_t command:4;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t command:4, def_bcast:1, spare:1, last_block:2;
#endif
} __attribute__ ((packed));
@@ -627,6 +703,23 @@ struct rsl_ie_cb_cmd_type {
#define RSL_CB_CMD_LASTBLOCK_2 2
#define RSL_CB_CMD_LASTBLOCK_3 3
+/*! NCH DRX Information (Chapter 9.3.47) */
+struct rsl_ie_nch_drx_info {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t nln:2;
+ uint8_t emlpp_priority:3;
+ uint8_t nln_status:1;
+ uint8_t spare:2;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t spare:2, nln_status:1, emlpp_priority:3, nln:2;
+#endif
+} __attribute__ ((packed));
+
+/*! Command Indicator (Chapter 9.3.48) */
+#define RSL_CMD_INDICATOR_START 0x00
+#define RSL_CMD_INDICATOR_STOP 0x01
+
/* Chapter 3.3.2.3 Brocast control channel */
/* CCCH-CONF, NC is not combined */
#define RSL_BCCH_CCCH_CONF_1_NC 0x00
@@ -672,10 +765,10 @@ enum rsl_ipac_speech_mode_m {
/* RSL_IE_IPAC_RTP_CSD_FMT, lower four bits */
enum rsl_ipac_rtp_csd_format_d {
- RSL_IPAC_RTP_CSD_EXT_TRAU = 0,
- RSL_IPAC_RTP_CSD_NON_TRAU = 1,
- RSL_IPAC_RTP_CSD_TRAU_BTS = 2,
- RSL_IPAC_RTP_CSD_IWF_FREE = 3,
+ RSL_IPAC_RTP_CSD_EXT_TRAU = 0, /*!< TRAU-like RTP format, without leading zero-bits */
+ RSL_IPAC_RTP_CSD_NON_TRAU = 1, /*!< packed 16k (252/288 bit) / 8k (126 bit) in RTP */
+ RSL_IPAC_RTP_CSD_TRAU_BTS = 2, /*!< TRAU in BTS; V.110 in RTP/CLEARMODE */
+ RSL_IPAC_RTP_CSD_IWF_FREE = 3, /*!< unknown proprietary IWF-free BTS-BTS data */
};
/* RSL_IE_IPAC_RTP_CSD_FMT, upper four bits */
enum rsl_ipac_rtp_csd_format_ir {
@@ -743,8 +836,14 @@ enum rsl_ipac_embedded_ie {
RSL_IPAC_EIE_SDCCH_CTL_PARAM = 0x1a,
RSL_IPAC_EIE_AMR_CONV_THRESH = 0x1b,
+ /* Osmocom specific extensions: */
+ RSL_IPAC_EIE_OSMO_MEAS_AVG_CFG = 0xf0,
+ RSL_IPAC_EIE_OSMO_MS_PWR_CTL = 0xf1,
+ RSL_IPAC_EIE_OSMO_PC_THRESH_COMP = 0xf2,
+
};
+/* Value of TLV IE RSL_IPAC_EIE_MEAS_AVG_CFG */
struct ipac_preproc_ave_cfg {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t h_reqave:5,
@@ -752,13 +851,67 @@ struct ipac_preproc_ave_cfg {
reserved:1;
uint8_t h_reqt:5,
ave_method:3;
+ uint8_t params[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t reserved:1, param_id:2, h_reqave:5;
uint8_t ave_method:3, h_reqt:5;
+ uint8_t params[0];
#endif
}__attribute__ ((packed));
+
+struct osmo_preproc_ave_cfg_field {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t h_reqave:5,
+ ave_enabled:1,
+ reserved:2;
+ uint8_t h_reqt:5,
+ ave_method:3;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t reserved:2, ave_enabled:1, h_reqave:5;
+ uint8_t ave_method:3, h_reqt:5;
+#endif
+}__attribute__ ((packed));
+/* Value of TLV IE RSL_IPAC_EIE_OSMO_MEAS_AVG_CFG: */
+struct osmo_preproc_ave_cfg {
+ struct osmo_preproc_ave_cfg_field ci_fr;
+ struct osmo_preproc_ave_cfg_field ci_hr;
+ struct osmo_preproc_ave_cfg_field ci_amr_fr;
+ struct osmo_preproc_ave_cfg_field ci_amr_hr;
+ struct osmo_preproc_ave_cfg_field ci_sdcch;
+ struct osmo_preproc_ave_cfg_field ci_gprs;
+ uint8_t params[0]; /* Contains params for each above, appended one after the other */
+}__attribute__ ((packed));
+
+/*! MS/BS Power Control Thresholds (RSL_IPAC_EIE_MS_PWR_CTL) */
+struct ipac_preproc_pc_thresh {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t l_rxlev:6, reserved_l_rxlev:2;
+ uint8_t u_rxlev:6, reserved_u_rxlev:2;
+ uint8_t u_rxqual:3, reserved_u_rxqual:1,
+ l_rxqual:3, reserved_l_rxqual:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t reserved_l_rxlev:2, l_rxlev:6;
+ uint8_t reserved_u_rxlev:2, u_rxlev:6;
+ uint8_t reserved_l_rxqual:1, l_rxqual:3, reserved_u_rxqual:1, u_rxqual:3;
+#endif
+}__attribute__ ((packed));
+
+/*! Osmocom extension for: MS/BS Power Control Thresholds (RSL_IPAC_EIE_OSMO_MS_PWR_CTL) */
+struct osmo_preproc_pc_thresh {
+ /* Carrier-to-Interference (C/I), in dB: */
+ int8_t l_ci_fr; int8_t u_ci_fr; /* FR/EFR */
+ int8_t l_ci_hr; int8_t u_ci_hr; /* HR */
+ int8_t l_ci_amr_fr; int8_t u_ci_amr_fr; /* AMR FR */
+ int8_t l_ci_amr_hr; int8_t u_ci_amr_hr; /* AMR HR */
+ int8_t l_ci_sdcch; int8_t u_ci_sdcch; /* SDCCH */
+ int8_t l_ci_gprs; int8_t u_ci_gprs; /* GPRS */
+}__attribute__ ((packed));
+
+/*! Handover Thresholds */
struct ipac_preproc_ho_thresh {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t l_rxlev_ul_h:6,
@@ -776,7 +929,7 @@ struct ipac_preproc_ho_thresh {
uint8_t ms_range_max:6,
reserved_ms_range:2;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t reserved_l_rxlev_ul:2, l_rxlev_ul_h:6;
uint8_t reserved_l_rxlev_dl:2, l_rxlev_dl_h:6;
uint8_t reserved_rxlev_ul:2, rxlev_ul_ih:6;
@@ -786,6 +939,60 @@ struct ipac_preproc_ho_thresh {
#endif
}__attribute__ ((packed));
+/*! PC Threshold Comparators (RSL_IPAC_EIE_PC_THRESH_COMP) */
+struct ipac_preproc_pc_comp {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t p1:5, reserved_p1:3;
+ uint8_t n1:5, reserved_n1:3;
+ uint8_t p2:5, reserved_p2:3;
+ uint8_t n2:5, reserved_n2:3;
+ uint8_t p3:5, reserved_p3:3;
+ uint8_t n3:5, reserved_n3:3;
+ uint8_t p4:5, reserved_p4:3;
+ uint8_t n4:5, reserved_n4:3;
+ uint8_t pc_interval:5, reserved_pc:3;
+ uint8_t red_step_size:4, inc_step_size:4;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t reserved_p1:3, p1:5;
+ uint8_t reserved_n1:3, n1:5;
+ uint8_t reserved_p2:3, p2:5;
+ uint8_t reserved_n2:3, n2:5;
+ uint8_t reserved_p3:3, p3:5;
+ uint8_t reserved_n3:3, n3:5;
+ uint8_t reserved_p4:3, p4:5;
+ uint8_t reserved_n4:3, n4:5;
+ uint8_t reserved_pc:3, pc_interval:5;
+ uint8_t inc_step_size:4, red_step_size:4;
+#endif
+}__attribute__ ((packed));
+
+/*! Osmocom extension for: PC Threshold Comparators (RSL_IPAC_EIE_OSMO_PC_THRESH_COMP) */
+struct ipac_preproc_pc_comp_field {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t lower_p:5, reserved_lower_p:3;
+ uint8_t lower_n:5, reserved_lower_n:3;
+ uint8_t upper_p:5, reserved_upper_p:3;
+ uint8_t upper_n:5, reserved_upper_n:3;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t reserved_lower_p:3, lower_p:5;
+ uint8_t reserved_lower_n:3, lower_n:5;
+ uint8_t reserved_upper_p:3, upper_p:5;
+ uint8_t reserved_upper_n:3, upper_n:5;
+#endif
+}__attribute__ ((packed));
+struct osmo_preproc_pc_comp {
+ /* Used for Carrier-to-Interference (C/I), in dB: */
+ struct ipac_preproc_pc_comp_field ci_fr;
+ struct ipac_preproc_pc_comp_field ci_hr;
+ struct ipac_preproc_pc_comp_field ci_amr_fr;
+ struct ipac_preproc_pc_comp_field ci_amr_hr;
+ struct ipac_preproc_pc_comp_field ci_sdcch;
+ struct ipac_preproc_pc_comp_field ci_gprs;
+}__attribute__ ((packed));
+
+/*! HO Threshold Comparators */
struct ipac_preproc_ho_comp {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t p5:5,
@@ -809,7 +1016,7 @@ struct ipac_preproc_ho_comp {
uint8_t reserved;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t reserved_p5:3, p5:5;
uint8_t reserved_n5:3, n5:5;
uint8_t reserved_p6:3, p6:5;
@@ -832,7 +1039,7 @@ struct ipac_preproc_ho_candidates {
s:1,
reserved1:1;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t reserved0:2, bsic:6;
uint8_t reserved1:1, s:1, ba_used:1, bcch_freq:5;
#endif
@@ -847,7 +1054,7 @@ struct ipac_preproc_ncell_dflts {
uint8_t ms_txpwr_max_def:5,
reserved_ms_txpwr_max_def:3;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t reserved_rxlev_min_def:2, rxlev_min_def:6;
uint8_t reserved_ho_margin_def:3, ho_margin_def:5;
uint8_t reserved_ms_txpwr_max_def:3, ms_txpwr_max_def:5;
@@ -860,7 +1067,7 @@ struct ipac_preproc_ho_ctl_param {
sdcch_ho_umts:1,
reserved:6;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t reserved:6, sdcch_ho_umts:1, sdcch_ho_gsm:1;
#endif
}__attribute__ ((packed));
@@ -876,4 +1083,18 @@ struct ipac_preproc_cfg {
struct ipac_preproc_ho_ctl_param ho_ctl_param;
};
+struct rsl_l1_info {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t reserved:1,
+ srr_sro:1,
+ fpc_epc:1,
+ ms_pwr:5;
+ uint8_t ta;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t ms_pwr:5, fpc_epc:1, srr_sro:1, reserved:1;
+ uint8_t ta;
+#endif
+} __attribute__ ((packed));
+
/*! @} */
diff --git a/include/osmocom/gsm/protocol/gsm_09_02.h b/include/osmocom/gsm/protocol/gsm_09_02.h
index 0b54fb74..4d5ff13c 100644
--- a/include/osmocom/gsm/protocol/gsm_09_02.h
+++ b/include/osmocom/gsm/protocol/gsm_09_02.h
@@ -1,8 +1,7 @@
/*! \file gsm_09_02.h
* GSM TS 09.02 definitions (MAP). */
-#ifndef PROTO_GSM_09_02_H
-#define PROTO_GSM_09_02_H
+#pragma once
/* Section 17.7.4 */
/* SS-Status */
@@ -134,5 +133,3 @@
#define GSM0902_TS_CODE_PLMN_SPECIFIC_TS_C 0xDC
#define GSM0902_TS_CODE_PLMN_SPECIFIC_TS_D 0xDD
#define GSM0902_TS_CODE_PLMN_SPECIFIC_TS_E 0xDE
-
-#endif /* PROTO_GSM_09_02_H */
diff --git a/include/osmocom/gsm/protocol/gsm_12_21.h b/include/osmocom/gsm/protocol/gsm_12_21.h
index 06755c93..39b1d45c 100644
--- a/include/osmocom/gsm/protocol/gsm_12_21.h
+++ b/include/osmocom/gsm/protocol/gsm_12_21.h
@@ -1,3 +1,4 @@
+/* 3GPP TS 12.21, nowadays 3GPP TS 52.021 */
/*
* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
* All Rights Reserved
@@ -12,10 +13,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#pragma once
@@ -445,7 +442,7 @@ enum abis_nm_attr {
NM_ATT_IPACC_NS_CFG = 0xa0,
NM_ATT_IPACC_BSSGP_CFG = 0xa1,
NM_ATT_IPACC_NS_LINK_CFG = 0xa2,
- NM_ATT_IPACC_RLC_CFG = 0xa3,
+ NM_ATT_IPACC_RLC_CFG = 0xa3,
NM_ATT_IPACC_ALM_THRESH_LIST = 0xa4,
NM_ATT_IPACC_MONIT_VAL_LIST = 0xa5,
NM_ATT_IPACC_TIB_CONTROL = 0xa6,
@@ -462,7 +459,7 @@ enum abis_nm_attr {
NM_ATT_BS11_RF_RES_IND_PER = 0x8f,
-
+
NM_ATT_BS11_RX_LEV_MIN_CELL = 0x90,
NM_ATT_BS11_ABIS_EXT_TIME = 0x91,
NM_ATT_BS11_TIMER_HO_REQUEST = 0x92,
@@ -526,9 +523,11 @@ enum abis_nm_adm_state {
/*! OML Availability State (Section 9.4.7) */
enum abis_nm_avail_state {
- NM_AVSTATE_IN_TEST = 1,
+ NM_AVSTATE_IN_TEST = 0,
+ NM_AVSTATE_FAILED = 1,
NM_AVSTATE_POWER_OFF = 2,
NM_AVSTATE_OFF_LINE = 3,
+ /* <not used> = 4, */
NM_AVSTATE_DEPENDENCY = 5,
NM_AVSTATE_DEGRADED = 6,
NM_AVSTATE_NOT_INSTALLED= 7,
@@ -564,8 +563,10 @@ enum abis_nm_chan_comb {
NM_CHANC_IPAC_TCHFull_PDCH = 0x80,
NM_CHANC_IPAC_TCHFull_TCHHalf = 0x81,
/* osmocom */
- NM_CHANC_OSMO_TCHFull_TCHHalf_PDCH = 0x90,
+ NM_CHANC_OSMO_DYN = 0x90,
};
+/* Backward compatibility with older naming: */
+#define NM_CHANC_OSMO_TCHFull_TCHHalf_PDCH NM_CHANC_OSMO_DYN
/*! Event Type (Section 9.4.16) */
enum abis_nm_event_type {
@@ -774,6 +775,98 @@ enum ipac_eie {
NM_IPAC_EIE_BTS_ID = 0x25,
};
+/*! ip.access support flags for NM_IPAC_EIE_FREQ_BANDS */
+#define NM_IPAC_F_FREQ_BAND_PGSM (1 << 0)
+#define NM_IPAC_F_FREQ_BAND_EGSM (1 << 1)
+#define NM_IPAC_F_FREQ_BAND_RGSM (1 << 2)
+#define NM_IPAC_F_FREQ_BAND_DCS (1 << 3)
+#define NM_IPAC_F_FREQ_BAND_PCS (1 << 4)
+#define NM_IPAC_F_FREQ_BAND_850 (1 << 5)
+#define NM_IPAC_F_FREQ_BAND_480 (1 << 6)
+#define NM_IPAC_F_FREQ_BAND_450 (1 << 7)
+
+/*! ip.access support flags for NM_IPAC_EIE_CIPH_ALGOS */
+#define NM_IPAC_F_CIPH_ALGO_A51 (1 << 0)
+#define NM_IPAC_F_CIPH_ALGO_A52 (1 << 1)
+#define NM_IPAC_F_CIPH_ALGO_A53 (1 << 2)
+#define NM_IPAC_F_CIPH_ALGO_A54 (1 << 3)
+#define NM_IPAC_F_CIPH_ALGO_A55 (1 << 4)
+#define NM_IPAC_F_CIPH_ALGO_A56 (1 << 5)
+#define NM_IPAC_F_CIPH_ALGO_A57 (1 << 6)
+#define NM_IPAC_F_CIPH_ALGO_A58 (1 << 7)
+
+/*! ip.access support flags for NM_IPAC_EIE_CHAN_TYPES (1st octet) */
+#define NM_IPAC_F_CHANT_TCHF (1 << 0)
+#define NM_IPAC_F_CHANT_TCHH (1 << 1)
+#define NM_IPAC_F_CHANT_SDCCH8 (1 << 2)
+#define NM_IPAC_F_CHANT_BCCH (1 << 3)
+#define NM_IPAC_F_CHANT_BCCH_SDCCH4 (1 << 4)
+#define NM_IPAC_F_CHANT_BCH (1 << 5)
+#define NM_IPAC_F_CHANT_BCCH_SDCCH4_CBCH (1 << 6)
+#define NM_IPAC_F_CHANT_SDCCH8_CBCH (1 << 7)
+/*! ip.access support flags for NM_IPAC_EIE_CHAN_TYPES (2nd octet) */
+#define NM_IPAC_F_CHANT_PDCHF (1 << 8)
+#define NM_IPAC_F_CHANT_TCHF_PDCHF (1 << 9)
+#define NM_IPAC_F_CHANT_TCHH_PDCHH (1 << 10)
+#define NM_IPAC_F_CHANT_TCHF_TCHH (1 << 11)
+
+/*! ip.access support flags for NM_IPAC_EIE_CHAN_MODES (speech codecs) */
+#define NM_IPAC_F_CHANM_SPEECH_FS (1 << 0)
+#define NM_IPAC_F_CHANM_SPEECH_EFS (1 << 1)
+#define NM_IPAC_F_CHANM_SPEECH_AFS (1 << 2)
+#define NM_IPAC_F_CHANM_SPEECH_HS (1 << 3)
+#define NM_IPAC_F_CHANM_SPEECH_AHS (1 << 4)
+/*! ip.access support flags for NM_IPAC_EIE_CHAN_MODES (CSD non-transparent) */
+#define NM_IPAC_F_CHANM_CSD_NT_4k8 (1 << 8)
+#define NM_IPAC_F_CHANM_CSD_NT_9k6 (1 << 9)
+#define NM_IPAC_F_CHANM_CSD_NT_14k4 (1 << 10)
+/*! ip.access support flags for NM_IPAC_EIE_CHAN_MODES (CSD transparent) */
+#define NM_IPAC_F_CHANM_CSD_T_1200_75 (1 << 16)
+#define NM_IPAC_F_CHANM_CSD_T_600 (1 << 17)
+#define NM_IPAC_F_CHANM_CSD_T_1k2 (1 << 18)
+#define NM_IPAC_F_CHANM_CSD_T_2k4 (1 << 19)
+#define NM_IPAC_F_CHANM_CSD_T_4k8 (1 << 20)
+#define NM_IPAC_F_CHANM_CSD_T_9k6 (1 << 21)
+#define NM_IPAC_F_CHANM_CSD_T_14k4 (1 << 22)
+
+/*! ip.access support flags for NM_IPAC_EIE_GPRS_CODING (GPRS) */
+#define NM_IPAC_F_GPRS_CODING_CS1 (1 << 0)
+#define NM_IPAC_F_GPRS_CODING_CS2 (1 << 1)
+#define NM_IPAC_F_GPRS_CODING_CS3 (1 << 2)
+#define NM_IPAC_F_GPRS_CODING_CS4 (1 << 3)
+/*! ip.access support flags for NM_IPAC_EIE_GPRS_CODING (EGPRS) */
+#define NM_IPAC_F_GPRS_CODING_MCS1 (1 << 7)
+#define NM_IPAC_F_GPRS_CODING_MCS2 (1 << 8)
+#define NM_IPAC_F_GPRS_CODING_MCS3 (1 << 9)
+#define NM_IPAC_F_GPRS_CODING_MCS4 (1 << 10)
+#define NM_IPAC_F_GPRS_CODING_MCS5 (1 << 11)
+#define NM_IPAC_F_GPRS_CODING_MCS6 (1 << 12)
+#define NM_IPAC_F_GPRS_CODING_MCS7 (1 << 13)
+#define NM_IPAC_F_GPRS_CODING_MCS8 (1 << 14)
+#define NM_IPAC_F_GPRS_CODING_MCS9 (1 << 15)
+
+/*! ip.access support flags for NM_IPAC_EIE_RTP_FEATURES */
+#define NM_IPAC_F_RTP_FEAT_COMPR_CONTROL (1 << 0) /* RTP Compression Control */
+#define NM_IPAC_F_RTP_FEAT_IR_8k (1 << 1) /* IR 8 kbit/s */
+#define NM_IPAC_F_RTP_FEAT_IR_16k (1 << 2) /* IR 16 kbit/s */
+#define NM_IPAC_F_RTP_FEAT_IR_32k (1 << 3) /* IR 32 kbit/s */
+#define NM_IPAC_F_RTP_FEAT_IR_64k (1 << 4) /* IR 64 kbit/s */
+#define NM_IPAC_F_RTP_FEAT_MULTIPLEX_RTP (1 << 6) /* RTP Multiplexing */
+#define NM_IPAC_F_RTP_FEAT_MULTIPLEX_SRTP (1 << 7) /* SRTP Multiplexing */
+
+/*! ip.access support flags for NM_IPAC_EIE_RSL_FEATURES */
+#define NM_IPAC_F_RSL_FEAT_PHYSICAL_CONTEXT (1 << 0)
+#define NM_IPAC_F_RSL_FEAT_DYN_PDCH_ACT (1 << 1)
+#define NM_IPAC_F_RSL_FEAT_RTP_PT2 (1 << 2)
+
+extern const struct value_string abis_nm_ipacc_freq_band_desc[];
+extern const struct value_string abis_nm_ipacc_ciph_algo_desc[];
+extern const struct value_string abis_nm_ipacc_chant_desc[];
+extern const struct value_string abis_nm_ipacc_chanm_desc[];
+extern const struct value_string abis_nm_ipacc_gprs_coding_desc[];
+extern const struct value_string abis_nm_ipacc_rtp_feat_desc[];
+extern const struct value_string abis_nm_ipacc_rsl_feat_desc[];
+
/*! ip.access NWL BCCH information type */
enum ipac_bcch_info_type {
IPAC_BINF_RXLEV = (1 << 8),
@@ -789,6 +882,69 @@ enum ipac_bcch_info_type {
IPAC_BINF_CELL_ALLOC = (1 << 2),
};
+/*! ip.access NM_ATT_IPACC_NS_CFG value */
+struct abis_nm_ipacc_att_ns_cfg {
+ uint8_t un_blocking_timer; /* (un)blocking Timer (Tns-block) timeout */
+ uint8_t un_blocking_retries; /* (un)blocking Timer (Tns-block) number of retries */
+ uint8_t reset_timer; /* Reset Timer (Tns-reset) timeout */
+ uint8_t reset_retries; /* Reset Timer (Tns-reset) number of retries */
+ uint8_t test_timer; /* Test Timer (Tns-test) timeout */
+ uint8_t alive_timer; /* Alive Timer (Tns-alive) timeout */
+ uint8_t alive_retries; /* Alive Timer (Tns-alive) number of retries */
+} __attribute__((packed));
+
+/*! ip.access NM_ATT_IPACC_BSSGP_CFG value */
+struct abis_nm_ipacc_att_bssgp_cfg {
+ uint8_t t1_s; /* blocking timer (T1) */
+ uint8_t t1_blocking_retries; /* blocking retries */
+ uint8_t t1_unblocking_retries; /* unblocking retries */
+ uint8_t t2_s; /* reset timer (T2) */
+ uint8_t t2_retries; /* reset retries */
+ uint8_t t3_100ms; /* suspend timer (T3) in 100ms */
+ uint8_t t3_retries; /* suspend retries */
+ uint8_t t4_100ms; /* resume timer (T4) in 100ms */
+ uint8_t t4_retries; /* resume retries */
+ uint8_t t5_s; /* capability update timer (T5) */
+ uint8_t t5_retries; /* capability update retries */
+} __attribute__((packed));
+
+/*! ip.access NM_ATT_IPACC_RLC_CFG value */
+struct abis_nm_ipacc_att_rlc_cfg {
+ uint8_t t3142;
+ uint8_t t3169;
+ uint8_t t3191;
+ uint8_t t3193_10ms;
+ uint8_t t3195;
+ uint8_t n3101;
+ uint8_t n3103;
+ uint8_t n3105;
+ uint8_t rlc_cv_countdown;
+} __attribute__((packed));
+
+/*! ip.access NM_ATT_IPACC_RLC_CFG_2 value */
+struct abis_nm_ipacc_att_rlc_cfg_2 {
+ /* T downlink TBF extension (0..500, network order) */
+ uint16_t t_dl_tbf_ext_10ms;
+ /* T uplink TBF extension (0..500, network order) */
+ uint16_t t_ul_tbf_ext_10ms;
+ /* Initial CS to use: CS1 -> 1, CS2 -> 2, CS3 -> 3, CS4 -> 4 */
+ uint8_t initial_cs;
+} __attribute__((packed));
+
+/*! ip.access NM_ATT_IPACC_RLC_CFG_3 value */
+struct abis_nm_ipacc_att_rlc_cfg_3 {
+ /* Initial MCS to use when EGPRS is used:
+ * MCS1 -> 1, MCS2 -> 2, ..., MCS9 -> 9 */
+ uint8_t initial_mcs;
+} __attribute__((packed));
+
+/*! Osmocom NSVC address type for NM_ATT_OSMO_NS_LINK_CFG */
+enum osmo_oml_nsvc_address_type {
+ OSMO_NSVC_ADDR_UNSPEC = 0x00,
+ OSMO_NSVC_ADDR_IPV4 = 0x04,
+ OSMO_NSVC_ADDR_IPV6 = 0x29,
+};
+
/*! 3GPP TS 52.021 §9.4.62 SW Description */
struct abis_nm_sw_desc {
uint8_t file_id[UINT8_MAX];
diff --git a/include/osmocom/gsm/protocol/gsm_23_032.h b/include/osmocom/gsm/protocol/gsm_23_032.h
new file mode 100644
index 00000000..6eb65ca2
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_23_032.h
@@ -0,0 +1,252 @@
+/*! \defgroup gad 3GPP TS 23.032 GAD: Universal Geographical Area Description.
+ * @{
+ * \file gsm_23_032.h
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * This program 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.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/endian.h>
+
+enum gad_type {
+ /*! Ellipsoid point */
+ GAD_TYPE_ELL_POINT = 0,
+ /*! Ellipsoid point with uncertainty circle. */
+ GAD_TYPE_ELL_POINT_UNC_CIRCLE = 1,
+ /*! Ellipsoid point with uncertainty ellipse. */
+ GAD_TYPE_ELL_POINT_UNC_ELLIPSE = 3,
+ GAD_TYPE_POLYGON = 5,
+ /*! Ellipsoid point with altitude. */
+ GAD_TYPE_ELL_POINT_ALT = 8,
+ /*! Ellipsoid point with altitude and uncertainty ellipsoid. */
+ GAD_TYPE_ELL_POINT_ALT_UNC_ELL = 9,
+ /*! Ellipsoid arc */
+ GAD_TYPE_ELL_ARC = 10,
+ /*! High accuracy ellipsoid point with uncertainty ellipse. */
+ GAD_TYPE_HA_ELL_POINT_UNC_ELLIPSE = 11,
+ /*! High accuracy ellipsoid point with altitude and uncertainty ellipsoid. */
+ GAD_TYPE_HA_ELL_POINT_ALT_UNC_ELL = 12,
+};
+
+struct gad_raw_head {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t spare:4,
+ type:4;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t type:4, spare:4;
+#endif
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT */
+ uint8_t lat[3];
+ uint8_t lon[3];
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_unc_circle {
+#if OSMO_IS_LITTLE_ENDIAN
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_UNC_CIRCLE */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t unc:7,
+ spare2:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ struct gad_raw_head h;
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t spare2:1, unc:7;
+#endif
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_unc_ellipse {
+#if OSMO_IS_LITTLE_ENDIAN
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_UNC_ELLIPSE */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t unc_semi_major:7,
+ spare1:1;
+ uint8_t unc_semi_minor:7,
+ spare2:1;
+ uint8_t major_ori;
+ uint8_t confidence:7,
+ spare3:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ struct gad_raw_head h;
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t spare1:1, unc_semi_major:7;
+ uint8_t spare2:1, unc_semi_minor:7;
+ uint8_t major_ori;
+ uint8_t spare3:1, confidence:7;
+#endif
+} __attribute__ ((packed));
+
+struct gad_raw_polygon {
+ struct {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t num_points:4;
+ uint8_t type:4; /*!< type = GAD_TYPE_POLYGON */
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t type:4, num_points:4;
+#endif
+ } h;
+ struct {
+ uint8_t lat[3];
+ uint8_t lon[3];
+ } point[15];
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_alt {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_ALT */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t alt[2];
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_alt_unc_ell {
+#if OSMO_IS_LITTLE_ENDIAN
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_ALT_UNC_ELL */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t alt[2];
+ uint8_t unc_semi_major:7,
+ spare1:1;
+ uint8_t unc_semi_minor:7,
+ spare2:1;
+ uint8_t major_ori;
+ uint8_t unc_alt:7,
+ spare3:1;
+ uint8_t confidence:7,
+ spare4:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ struct gad_raw_head h;
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t alt[2];
+ uint8_t spare1:1, unc_semi_major:7;
+ uint8_t spare2:1, unc_semi_minor:7;
+ uint8_t major_ori;
+ uint8_t spare3:1, unc_alt:7;
+ uint8_t spare4:1, confidence:7;
+#endif
+} __attribute__ ((packed));
+
+struct gad_raw_ell_arc {
+#if OSMO_IS_LITTLE_ENDIAN
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_ARC */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t inner_r[2];
+ uint8_t unc_r:7,
+ spare1:1;
+ uint8_t ofs_angle;
+ uint8_t incl_angle;
+ uint8_t confidence:7,
+ spare2:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ struct gad_raw_head h;
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t inner_r[2];
+ uint8_t spare1:1, unc_r:7;
+ uint8_t ofs_angle;
+ uint8_t incl_angle;
+ uint8_t spare2:1, confidence:7;
+#endif
+} __attribute__ ((packed));
+
+struct gad_raw_ha_ell_point_unc_ell {
+#if OSMO_IS_LITTLE_ENDIAN
+ struct gad_raw_head h; /*!< type = GAD_TYPE_HA_ELL_POINT_UNC_ELLIPSE */
+ uint8_t lat[4];
+ uint8_t lon[4];
+ uint8_t alt[3];
+ uint8_t unc_semi_major;
+ uint8_t unc_semi_minor;
+ uint8_t major_ori;
+ uint8_t confidence:7,
+ spare1:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ struct gad_raw_head h;
+ uint8_t lat[4];
+ uint8_t lon[4];
+ uint8_t alt[3];
+ uint8_t unc_semi_major;
+ uint8_t unc_semi_minor;
+ uint8_t major_ori;
+ uint8_t spare1:1, confidence:7;
+#endif
+} __attribute__ ((packed));
+
+struct gad_raw_ha_ell_point_alt_unc_ell {
+#if OSMO_IS_LITTLE_ENDIAN
+ struct gad_raw_head h; /*!< type = GAD_TYPE_HA_ELL_POINT_ALT_UNC_ELL */
+ uint8_t lat[4];
+ uint8_t lon[4];
+ uint8_t alt[3];
+ uint8_t unc_semi_major;
+ uint8_t unc_semi_minor;
+ uint8_t major_ori;
+ uint8_t h_confidence:7,
+ spare1:1;
+ uint8_t unc_alt;
+ uint8_t v_confidence:7,
+ spare2:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ struct gad_raw_head h;
+ uint8_t lat[4];
+ uint8_t lon[4];
+ uint8_t alt[3];
+ uint8_t unc_semi_major;
+ uint8_t unc_semi_minor;
+ uint8_t major_ori;
+ uint8_t spare1:1, h_confidence:7;
+ uint8_t unc_alt;
+ uint8_t spare2:1, v_confidence:7;
+#endif
+} __attribute__ ((packed));
+
+/*! GAD PDU in network-byte-order according to 3GPP TS 23.032 GAD: Universal Geographical Area Description. */
+union gad_raw {
+ struct gad_raw_head h;
+ struct gad_raw_ell_point ell_point;
+ struct gad_raw_ell_point_unc_circle ell_point_unc_circle;
+ struct gad_raw_ell_point_unc_ellipse ell_point_unc_ellipse;
+ struct gad_raw_polygon polygon;
+ struct gad_raw_ell_point_alt ell_point_alt;
+ struct gad_raw_ell_point_alt_unc_ell ell_point_alt_unc_ell;
+ struct gad_raw_ell_arc ell_arc;
+ struct gad_raw_ha_ell_point_unc_ell ha_ell_point_unc_ell;
+ struct gad_raw_ha_ell_point_alt_unc_ell ha_ell_point_alt_unc_ell;
+} __attribute__ ((packed));
+
+/*! @} */
diff --git a/include/osmocom/gsm/protocol/gsm_23_041.h b/include/osmocom/gsm/protocol/gsm_23_041.h
index e726cff2..2a2b006f 100644
--- a/include/osmocom/gsm/protocol/gsm_23_041.h
+++ b/include/osmocom/gsm/protocol/gsm_23_041.h
@@ -2,6 +2,16 @@
#include <osmocom/core/endian.h>
+/* Section 9.3.24: Warning-Type */
+enum gsm23041_warning_type_value {
+ CBS_ETWS_WARN_TYPE_EARTHQUAKE = 0,
+ CBS_ETWS_WARN_TYPE_TSUNAMI = 1,
+ CBS_ETWS_WARN_TYPE_EARTHQUAKE_AND_TSUNAMI = 2,
+ CBS_ETWS_WARN_TYPE_TEST = 3,
+ CBS_ETWS_WARN_TYPE_OTHER = 4,
+ /* 0000101-1111111 Reserved for future use */
+};
+
/* Section 9.4.1.2: GSM Message Format */
struct gsm23041_msg_param_gsm {
uint16_t serial_nr;
@@ -12,7 +22,7 @@ struct gsm23041_msg_param_gsm {
uint8_t num_pages:4,
page_nr:4;
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t page_nr:4, num_pages:4;
#endif
} page_param;
diff --git a/include/osmocom/gsm/protocol/gsm_25_415.h b/include/osmocom/gsm/protocol/gsm_25_415.h
new file mode 100644
index 00000000..5c4dd2bb
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_25_415.h
@@ -0,0 +1,222 @@
+#pragma once
+/* Iu User Plane (IuUP) Definitions as per 3GPP TS 25.415 */
+/* (C) 2017 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <stdint.h>
+#include <osmocom/core/endian.h>
+
+/* 3GPP TS 25.415 Section 6.6.2.1 */
+struct iuup_pdutype0_hdr {
+#if OSMO_IS_LITTLE_ENDIAN
+ /* control part */
+ uint8_t frame_nr:4,
+ pdu_type:4;
+ uint8_t rfci:6,
+ fqc:2;
+ /* checksum part */
+ uint8_t payload_crc_hi:2, header_crc:6;
+ uint8_t payload_crc_lo;
+
+ /* payload part */
+ uint8_t payload[0];
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t pdu_type:4, frame_nr:4;
+ uint8_t fqc:2, rfci:6;
+ uint8_t header_crc:6, payload_crc_hi:2;
+ uint8_t payload_crc_lo;
+ uint8_t payload[0];
+#endif
+} __attribute__((packed));
+
+/* 3GPP TS 25.415 Section 6.6.2.2 */
+struct iuup_pdutype1_hdr {
+#if OSMO_IS_LITTLE_ENDIAN
+ /* control part */
+ uint8_t frame_nr:4,
+ pdu_type:4;
+ uint8_t rfci:6,
+ fqc:2;
+ /* checksum part */
+ uint8_t spare:2,
+ header_crc:6;
+ /* payload part */
+ uint8_t payload[0];
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t pdu_type:4, frame_nr:4;
+ uint8_t fqc:2, rfci:6;
+ uint8_t header_crc:6, spare:2;
+ uint8_t payload[0];
+#endif
+} __attribute__((packed));
+
+/* 3GPP TS 25.415 Section 6.6.2.3 */
+struct iuup_pdutype14_hdr {
+#if OSMO_IS_LITTLE_ENDIAN
+ /* control part */
+ uint8_t frame_nr:2,
+ ack_nack:2,
+ pdu_type:4;
+ uint8_t proc_ind:4,
+ mode_version:4;
+ /* checksum part */
+ uint8_t payload_crc_hi:2, header_crc:6;
+ uint8_t payload_crc_lo;
+ /* payload part */
+ uint8_t payload[0];
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t pdu_type:4, ack_nack:2, frame_nr:2;
+ uint8_t mode_version:4, proc_ind:4;
+ uint8_t header_crc:6, payload_crc_hi:2;
+ uint8_t payload_crc_lo;
+ uint8_t payload[0];
+#endif
+} __attribute__((packed));
+
+/* 3GPP TS 25.415 Section 6.6.2.3.4.1 */
+struct iuup_ctrl_init_rfci_hdr {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t rfci:6,
+ li:1,
+ lri:1;
+ uint8_t subflow_length[0]; /* 1 or 2 bytes depending on li */
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t lri:1, li:1, rfci:6;
+ uint8_t subflow_length[0];
+#endif
+} __attribute__((packed));
+struct iuup_ctrl_init_hdr {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t chain_ind:1,
+ num_subflows_per_rfci:3,
+ ti:1,
+ spare:3;
+ uint8_t rfci_data[0]; /* struct iuup_ctrl_init_rfci_hdr* */
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t spare:3, ti:1, num_subflows_per_rfci:3, chain_ind:1;
+ uint8_t rfci_data[0]; /* struct iuup_ctrl_init_rfci_hdr* */
+;
+#endif
+} __attribute__((packed));
+struct iuup_ctrl_init_tail {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint16_t versions_supported;
+ uint8_t spare:4,
+ data_pdu_type:4;
+ uint8_t spare_extension[0];
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint16_t versions_supported;
+ uint8_t data_pdu_type:4, spare:4;
+ uint8_t spare_extension[0];
+#endif
+} __attribute__((packed));
+
+/* 3GPP TS 25.415 Section 6.6.2.3.4.4 */
+struct iuup_ctrl_error_event {
+#if OSMO_IS_LITTLE_ENDIAN
+ struct iuup_pdutype14_hdr hdr;
+ uint8_t error_cause:6,
+ error_distance:2;
+ uint8_t spare_extension[0];
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ struct iuup_pdutype14_hdr hdr;
+ uint8_t error_distance:2, error_cause:6;
+ uint8_t spare_extension[0];
+#endif
+} __attribute__((packed));
+
+/* 3GPP TS 25.415 Section 6.6.2.3.2 */
+struct iuup_ctrl_ack {
+ struct iuup_pdutype14_hdr hdr;
+ uint8_t spare_extension[0];
+} __attribute__((packed));
+
+/* 3GPP TS 25.415 Section 6.6.2.3.3 */
+struct iuup_ctrl_nack {
+#if OSMO_IS_LITTLE_ENDIAN
+ struct iuup_pdutype14_hdr hdr;
+ uint8_t spare:2,
+ error_cause:6;
+ uint8_t spare_extension[0];
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ struct iuup_pdutype14_hdr hdr;
+ uint8_t error_cause:6, spare:2;
+ uint8_t spare_extension[0];
+#endif
+} __attribute__((packed));
+
+/* 3GPP TS 25.415 Section 6.6.2 + 6.6.3.1 */
+enum iuup_pdu_type {
+ IUUP_PDU_T_DATA_CRC = 0,
+ IUUP_PDU_T_DATA_NOCRC = 1,
+ IUUP_PDU_T_CONTROL = 14,
+};
+
+/* 3GPP TS 25.415 Section 6.6.3.2 */
+enum iuup_ack_nack {
+ IUUP_AN_PROCEDURE = 0,
+ IUUP_AN_ACK = 1,
+ IUUP_AN_NACK = 2,
+};
+
+/* 3GPP TS 25.415 Section 6.6.3.5 */
+enum iuup_fqc {
+ IUUP_FQC_FRAME_GOOD = 0,
+ IUUP_FQC_FRAME_BAD = 1,
+ IUUP_FQC_FRAME_BAD_RADIO = 2,
+};
+
+/* 3GPP TS 25.415 Section 6.6.3.7 */
+enum iuup_procedure {
+ IUUP_PROC_INIT = 0,
+ IUUP_PROC_RATE_CTRL = 1,
+ IUUP_PROC_TIME_ALIGN = 2,
+ IUUP_PROC_ERR_EVENT = 3,
+};
+
+
+/* 3GPP TS 25.415 Section 6.6.3.15 */
+enum iuup_error_distance {
+ IUUP_ERR_DIST_LOCAL = 0,
+ IUUP_ERR_DIST_FIRST_FWD = 1,
+ IUUP_ERR_DIST_SECOND_FWD = 2,
+ IUUP_ERR_DIST_RESERVED = 3,
+};
+
+
+/* 3GPP TS 25.415 Section 6.6.3.16 */
+enum iuup_error_cause {
+ IUUP_ERR_CAUSE_CRC_ERR_HDR = 0,
+ IUUP_ERR_CAUSE_CRC_ERR_DATA = 1,
+ IUUP_ERR_CAUSE_UNEXPECTED_FN = 2,
+ IUUP_ERR_CAUSE_FRAME_LOSS = 3,
+ IUUP_ERR_CAUSE_UNKNOWN_PDUTYPE = 4,
+ IUUP_ERR_CAUSE_UNKNOWN_PROC = 5,
+ IUUP_ERR_CAUSE_UNKNNOWN_RES_VAL = 6,
+ IUUP_ERR_CAUSE_UNKNNOWN_FIELD = 7,
+ IUUP_ERR_CAUSE_FRAME_TOO_SHORT = 8,
+ IUUP_ERR_CAUSE_MISSING_FIELDS = 9,
+ IUUP_ERR_CAUSE_UNEXPECTED_PDU_T = 16,
+ IUUP_ERR_CAUSE_UNEXPECTED_PROC = 18,
+ IUUP_ERR_CAUSE_UNEXPECTED_RFCI = 19,
+ IUUP_ERR_CAUSE_UNEXPECTED_VALUE = 20,
+ IUUP_ERR_CAUSE_INIT_FAILURE = 42,
+ IUUP_ERR_CAUSE_INIT_FAILURE_NET_TMR = 43,
+ IUUP_ERR_CAUSE_INIT_FAILURE_REP_NACK = 44,
+ IUUP_ERR_CAUSE_RATE_CTRL_FAILURE = 45,
+ IUUP_ERR_CAUSE_ERR_EVENT_FAIL = 46,
+ IUUP_ERR_CAUSE_TIME_ALIGN_NOTSUPP = 47,
+ IUUP_ERR_CAUSE_REQ_TIME_ALIGN_NOTPOSS = 48,
+ IUUP_ERR_CAUSE_MODE_VERSION_NOT_SUPPORTED = 49,
+};
diff --git a/include/osmocom/gsm/protocol/gsm_44_004.h b/include/osmocom/gsm/protocol/gsm_44_004.h
new file mode 100644
index 00000000..c30ba0c9
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_44_004.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <osmocom/core/endian.h>
+
+/* TS 44.004 Section 7.1 */
+
+struct gsm_sacch_l1_hdr {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t ms_pwr:5,
+ fpc_epc:1,
+ srr_sro:1,
+ reserved:1;
+ uint8_t ta;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t reserved:1, srr_sro:1, fpc_epc:1, ms_pwr:5;
+ uint8_t ta;
+#endif
+} __attribute__ ((packed));
diff --git a/include/osmocom/gsm/protocol/gsm_44_060.h b/include/osmocom/gsm/protocol/gsm_44_060.h
new file mode 100644
index 00000000..1df2f800
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_44_060.h
@@ -0,0 +1,252 @@
+/*! \file gsm_44_060.h
+ * General Packet Radio Service (GPRS).
+ * Radio Link Control / Medium Access Control (RLC/MAC) protocol
+ * 3GPP TS 44.060
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/endian.h>
+
+/* TS 44.060 10.3a.4.1.1 */
+struct gprs_rlc_ul_header_egprs_1 {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t r:1,
+ si:1,
+ cv:4,
+ tfi_hi:2;
+ uint8_t tfi_lo:3,
+ bsn1_hi:5;
+ uint8_t bsn1_lo:6,
+ bsn2_hi:2;
+ uint8_t bsn2_lo:8;
+ uint8_t cps:5,
+ rsb:1,
+ pi:1,
+ spare_hi:1;
+ uint8_t spare_lo:6,
+ dummy:2;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t tfi_hi:2, cv:4, si:1, r:1;
+ uint8_t bsn1_hi:5, tfi_lo:3;
+ uint8_t bsn2_hi:2, bsn1_lo:6;
+ uint8_t bsn2_lo:8;
+ uint8_t spare_hi:1, pi:1, rsb:1, cps:5;
+ uint8_t dummy:2, spare_lo:6;
+#endif
+} __attribute__ ((packed));
+
+/* TS 44.060 10.3a.4.2.1 */
+struct gprs_rlc_ul_header_egprs_2 {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t r:1,
+ si:1,
+ cv:4,
+ tfi_hi:2;
+ uint8_t tfi_lo:3,
+ bsn1_hi:5;
+ uint8_t bsn1_lo:6,
+ cps_hi:2;
+ uint8_t cps_lo:1,
+ rsb:1,
+ pi:1,
+ spare_hi:5;
+ uint8_t spare_lo:5,
+ dummy:3;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t tfi_hi:2, cv:4, si:1, r:1;
+ uint8_t bsn1_hi:5, tfi_lo:3;
+ uint8_t cps_hi:2, bsn1_lo:6;
+ uint8_t spare_hi:5, pi:1, rsb:1, cps_lo:1;
+ uint8_t dummy:3, spare_lo:5;
+#endif
+} __attribute__ ((packed));
+
+/* TS 44.060 10.3a.4.3.1 */
+struct gprs_rlc_ul_header_egprs_3 {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t r:1,
+ si:1,
+ cv:4,
+ tfi_hi:2;
+ uint8_t tfi_lo:3,
+ bsn1_hi:5;
+ uint8_t bsn1_lo:6,
+ cps_hi:2;
+ uint8_t cps_lo:2,
+ spb:2,
+ rsb:1,
+ pi:1,
+ spare:1,
+ dummy:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t tfi_hi:2, cv:4, si:1, r:1;
+ uint8_t bsn1_hi:5, tfi_lo:3;
+ uint8_t cps_hi:2, bsn1_lo:6;
+ uint8_t dummy:1, spare:1, pi:1, rsb:1, spb:2, cps_lo:2;
+#endif
+} __attribute__ ((packed));
+
+struct gprs_rlc_dl_header_egprs_1 {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t usf:3,
+ es_p:2,
+ rrbp:2,
+ tfi_hi:1;
+ uint8_t tfi_lo:4,
+ pr:2,
+ bsn1_hi:2;
+ uint8_t bsn1_mid:8;
+ uint8_t bsn1_lo:1,
+ bsn2_hi:7;
+ uint8_t bsn2_lo:3,
+ cps:5;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t tfi_hi:1, rrbp:2, es_p:2, usf:3;
+ uint8_t bsn1_hi:2, pr:2, tfi_lo:4;
+ uint8_t bsn1_mid:8;
+ uint8_t bsn2_hi:7, bsn1_lo:1;
+ uint8_t cps:5, bsn2_lo:3;
+#endif
+} __attribute__ ((packed));
+
+struct gprs_rlc_dl_header_egprs_2 {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t usf:3,
+ es_p:2,
+ rrbp:2,
+ tfi_hi:1;
+ uint8_t tfi_lo:4,
+ pr:2,
+ bsn1_hi:2;
+ uint8_t bsn1_mid:8;
+ uint8_t bsn1_lo:1,
+ cps:3,
+ dummy:4;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t tfi_hi:1, rrbp:2, es_p:2, usf:3;
+ uint8_t bsn1_hi:2, pr:2, tfi_lo:4;
+ uint8_t bsn1_mid:8;
+ uint8_t dummy:4, cps:3, bsn1_lo:1;
+#endif
+} __attribute__ ((packed));
+
+struct gprs_rlc_dl_header_egprs_3 {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t usf:3,
+ es_p:2,
+ rrbp:2,
+ tfi_hi:1;
+ uint8_t tfi_lo:4,
+ pr:2,
+ bsn1_hi:2;
+ uint8_t bsn1_mid:8;
+ uint8_t bsn1_lo:1,
+ cps:4,
+ spb:2,
+ dummy:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t tfi_hi:1, rrbp:2, es_p:2, usf:3;
+ uint8_t bsn1_hi:2, pr:2, tfi_lo:4;
+ uint8_t bsn1_mid:8;
+ uint8_t dummy:1, spb:2, cps:4, bsn1_lo:1;
+#endif
+} __attribute__ ((packed));
+
+/* TS 44.060 Table 12.24.2
+* Meaning of values documented in TS 23.060 Chapter 6.3.3.1: Network Mode of Operation */
+enum osmo_gprs_nmo {
+ GPRS_NMO_I = 0, /* CS pagin on GPRS paging or traffic channel */
+ GPRS_NMO_II = 1, /* all paging on CCCH */
+ GPRS_NMO_III = 2, /* no paging coordination */
+};
+
+/* TS 44.060 12.24 */
+struct osmo_gprs_cell_options {
+ enum osmo_gprs_nmo nmo;
+ /* T3168: wait for packet uplink assignment message */
+ uint32_t t3168; /* in milliseconds */
+ /* T3192: wait for release of the TBF after reception of the final block */
+ uint32_t t3192; /* in milliseconds */
+ uint32_t drx_timer_max;/* in seconds */
+ uint32_t bs_cv_max;
+ uint8_t supports_egprs_11bit_rach;
+ bool ctrl_ack_type_use_block; /* use PACKET CONTROL ACKNOWLEDGMENT */
+
+ uint8_t ext_info_present;
+ struct {
+ uint8_t egprs_supported;
+ uint8_t use_egprs_p_ch_req;
+ uint8_t bep_period;
+ uint8_t pfc_supported;
+ uint8_t dtm_supported;
+ uint8_t bss_paging_coordination;
+ bool ccn_active;
+ } ext_info;
+};
+
+/* TS 44.060 Table 12.9.2 */
+struct osmo_gprs_power_ctrl_pars {
+ uint8_t alpha;
+ uint8_t t_avg_w;
+ uint8_t t_avg_t;
+ uint8_t pc_meas_chan;
+ uint8_t n_avg_i;
+};
+
+
+/*! Structure for CPS coding and puncturing scheme (TS 44.060 10.4.8a) */
+struct egprs_cps {
+ uint8_t bits;
+ uint8_t mcs;
+ uint8_t p[2];
+};
+
+/*! CPS puncturing table selection (TS 44.060 10.4.8a) */
+enum egprs_cps_punc {
+ EGPRS_CPS_P1,
+ EGPRS_CPS_P2,
+ EGPRS_CPS_P3,
+ EGPRS_CPS_NONE = -1,
+};
+
+/*! EGPRS header types (TS 44.060 10.0a.2) */
+enum egprs_hdr_type {
+ EGPRS_HDR_TYPE1,
+ EGPRS_HDR_TYPE2,
+ EGPRS_HDR_TYPE3,
+};
+
+enum osmo_gprs_cs {
+ OSMO_GPRS_CS_NONE,
+ OSMO_GPRS_CS1,
+ OSMO_GPRS_CS2,
+ OSMO_GPRS_CS3,
+ OSMO_GPRS_CS4,
+ OSMO_GPRS_MCS1,
+ OSMO_GPRS_MCS2,
+ OSMO_GPRS_MCS3,
+ OSMO_GPRS_MCS4,
+ OSMO_GPRS_MCS5,
+ OSMO_GPRS_MCS6,
+ OSMO_GPRS_MCS7,
+ OSMO_GPRS_MCS8,
+ OSMO_GPRS_MCS9,
+ _NUM_OSMO_GPRS_CS
+};
+
+int egprs_get_cps(struct egprs_cps *cps, uint8_t type, uint8_t bits);
+
+int osmo_gprs_ul_block_size_bits(enum osmo_gprs_cs cs);
+int osmo_gprs_dl_block_size_bits(enum osmo_gprs_cs cs);
+int osmo_gprs_ul_block_size_bytes(enum osmo_gprs_cs cs);
+int osmo_gprs_dl_block_size_bytes(enum osmo_gprs_cs cs);
+enum osmo_gprs_cs osmo_gprs_ul_cs_by_block_bytes(uint8_t block_size);
+enum osmo_gprs_cs osmo_gprs_dl_cs_by_block_bytes(uint8_t block_size);
diff --git a/include/osmocom/gsm/protocol/gsm_44_068.h b/include/osmocom/gsm/protocol/gsm_44_068.h
new file mode 100644
index 00000000..3a33c163
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_44_068.h
@@ -0,0 +1,136 @@
+#pragma once
+#include <stdint.h>
+#include <osmocom/core/utils.h>
+
+/* Group Call Control (GCC) is an ETSI/3GPP standard protocol used between
+ * MS (Mobile Station) and MSC (Mobile Switchting Center) in 2G/GSM-R network.
+ * It is specified in 3GPP TS 44.068.
+ *
+ * (C) 2023 by Sysmocom s.f.m.c. GmbH
+ * All Rights Reserved
+ *
+ * Author: Andreas Eversberg
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/* 9 Information Element Identifiers */
+enum osmo_gsm44068_iei {
+ OSMO_GSM44068_IEI_MOBILE_IDENTITY = 0x17,
+ OSMO_GSM44068_IEI_USER_USER = 0x7E,
+ OSMO_GSM44068_IEI_CALL_STATE = 0xA0,
+ OSMO_GSM44068_IEI_STATE_ATTRIBUTES = 0xB0,
+ OSMO_GSM44068_IEI_TALKER_PRIORITY = 0xC0,
+ OSMO_GSM44068_IEI_SMS_INDICATIONS = 0xD0,
+};
+
+/* 9.3 Message Type */
+enum osmo_gsm44068_msg_type {
+ OSMO_GSM44068_MSGT_IMMEDIATE_SETUP = 0x31,
+ OSMO_GSM44068_MSGT_SETUP = 0x32,
+ OSMO_GSM44068_MSGT_CONNECT = 0x33,
+ OSMO_GSM44068_MSGT_TERMINATION = 0x34,
+ OSMO_GSM44068_MSGT_TERMINATION_REQUEST = 0x35,
+ OSMO_GSM44068_MSGT_TERMINATION_REJECT = 0x36,
+ OSMO_GSM44068_MSGT_STATUS = 0x38,
+ OSMO_GSM44068_MSGT_GET_STATUS = 0x39,
+ OSMO_GSM44068_MSGT_SET_PARAMETER = 0x3a,
+ OSMO_GSM44068_MSGT_IMMEDIATE_SETUP_2 = 0x3b,
+};
+
+/* Table 9.2 priority */
+enum osmo_gsm44068_priority_level {
+ OSMO_GSM44068_PRIO_LEVEL_4 = 0x1,
+ OSMO_GSM44068_PRIO_LEVEL_3 = 0x2,
+ OSMO_GSM44068_PRIO_LEVEL_2 = 0x3,
+ OSMO_GSM44068_PRIO_LEVEL_1 = 0x4,
+ OSMO_GSM44068_PRIO_LEVEL_0 = 0x5,
+ OSMO_GSM44068_PRIO_LEVEL_B = 0x6,
+ OSMO_GSM44068_PRIO_LEVEL_A = 0x7,
+};
+
+/* 9.4.2 Call State */
+enum osmo_gsm44068_call_state {
+ OSMO_GSM44068_CSTATE_U0 = 0x0,
+ OSMO_GSM44068_CSTATE_U1 = 0x1,
+ OSMO_GSM44068_CSTATE_U2sl_U2 = 0x2,
+ OSMO_GSM44068_CSTATE_U3 = 0x3,
+ OSMO_GSM44068_CSTATE_U4 = 0x4,
+ OSMO_GSM44068_CSTATE_U5 = 0x5,
+ OSMO_GSM44068_CSTATE_U0p = 0x6,
+ OSMO_GSM44068_CSTATE_U2wr_U6 = 0x7,
+ OSMO_GSM44068_CSTATE_U2r = 0x8,
+ OSMO_GSM44068_CSTATE_U2ws = 0x9,
+ OSMO_GSM44068_CSTATE_U2sr = 0xa,
+ OSMO_GSM44068_CSTATE_U2nc = 0xb,
+};
+
+/* 9.4.3 Cause */
+enum osmo_gsm44068_cause {
+ OSMO_GSM44068_CAUSE_ILLEGAL_MS = 0x03,
+ OSMO_GSM44068_CAUSE_IMEI_NOT_ACCEPTED = 0x05,
+ OSMO_GSM44068_CAUSE_ILLEGAL_ME = 0x06,
+ OSMO_GSM44068_CAUSE_SERVICE_NOT_AUTHORIZED = 0x08,
+ OSMO_GSM44068_CAUSE_APP_NOT_SUPPORTED_ON_PROTO = 0x09,
+ OSMO_GSM44068_CAUSE_RR_CONNECTION_ABORTED = 0x0a,
+ OSMO_GSM44068_CAUSE_NORMAL_CALL_CLEARING = 0x10,
+ OSMO_GSM44068_CAUSE_NETWORK_FAILURE = 0x11,
+ OSMO_GSM44068_CAUSE_BUSY = 0x14,
+ OSMO_GSM44068_CAUSE_CONGESTION = 0x16,
+ OSMO_GSM44068_CAUSE_USER_NOT_ORIGINATOR = 0x17,
+ OSMO_GSM44068_CAUSE_NET_WANTS_TO_MAINTAIN_CALL = 0x18,
+ OSMO_GSM44068_CAUSE_RESPONSE_TO_GET_STATUS = 0x1e,
+ OSMO_GSM44068_CAUSE_SERVICE_OPTION_NOT_SUBSCR = 0x20,
+ OSMO_GSM44068_CAUSE_REQUESTED_SERVICE_NOT_SUB = 0x21,
+ OSMO_GSM44068_CAUSE_SERVICE_OPTION_OOO = 0x22,
+ OSMO_GSM44068_CAUSE_CALL_CANNOT_BE_IDENTIFIED = 0x26,
+ OSMO_GSM44068_CAUSE_RETRY_UPON_ENTRY_NEW_CALL = 0x30, /* up to 0x3f */
+ OSMO_GSM44068_CAUSE_INVALID_TRANSACTION_ID = 0x51,
+ OSMO_GSM44068_CAUSE_SEMANTICALLY_INCORRECT_MSG = 0x5f,
+ OSMO_GSM44068_CAUSE_INVALID_MANDATORY_INFO = 0x60,
+ OSMO_GSM44068_CAUSE_MESSAGE_TYPE_NON_EXISTENT = 0x61,
+ OSMO_GSM44068_CAUSE_MESSAGE_TYPE_NOT_COMPAT = 0x62,
+ OSMO_GSM44068_CAUSE_IE_NON_EXISTENT = 0x63,
+ OSMO_GSM44068_CAUSE_IE_NOT_COMPAT = 0x64,
+ OSMO_GSM44068_CAUSE_PROTOCOL_ERROR = 0x70,
+};
+
+/* 9.4.4 Originator Indication */
+#define OSMO_GSM44068_OI_MS_IS_ORIGINATOR 0x01
+
+/* 9.4.7 State Attributes */
+#define OSMO_GSM44068_DA_DOWNLINK_ATTACHED 0x08
+#define OSMO_GSM44068_UA_UPLINK_ATTACHED 0x04
+#define OSMO_GSM44068_COMM_T 0x02
+
+/* 9.4.9 Talker Priority */
+enum osmo_gsm44068_talker_priority {
+ OSMO_GSM44068_PRIO_NORMAL = 0x0,
+ OSMO_GSM44068_PRIO_PRIVILEGED = 0x1,
+ OSMO_GSM44068_PRIO_EMERGENCY = 0x2,
+};
+
+/* 9.4.10 SMS Indications */
+#define OSMO_GSM44068_DC_DATA_CONFIDENTALLY_RQD 0x02
+#define OSMO_GSM44068_GP_GUARANTEED_PRIVACY_RQD 0x01
+
+extern const struct value_string osmo_gsm44068_msg_type_names[];
+extern const struct value_string osmo_gsm44068_priority_level_names[];
+extern const struct value_string osmo_gsm44068_cause_names[];
+extern const struct value_string osmo_gsm44068_call_state_names[];
+extern const struct value_string osmo_gsm44068_talker_priority_names[];
+
+extern const struct tlv_definition osmo_gsm44068_att_tlvdef;
diff --git a/include/osmocom/gsm/protocol/gsm_44_318.h b/include/osmocom/gsm/protocol/gsm_44_318.h
index b3942be2..f31a80ae 100644
--- a/include/osmocom/gsm/protocol/gsm_44_318.h
+++ b/include/osmocom/gsm/protocol/gsm_44_318.h
@@ -162,7 +162,7 @@ struct gan_rc_csr_hdr {
uint8_t msg_type;
uint8_t data[0];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint16_t len;
uint8_t skip_ind:4, pdisc:4;
uint8_t msg_type;
@@ -190,7 +190,7 @@ struct gan_cch_desc_ie {
spare2:2;
uint8_t access_class[2];
#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t mscr:1, att:1, dtm:1, gprs:1, nmo:2, ecmc:1, spare:1;
uint8_t t3212;
uint8_t rac;
diff --git a/include/osmocom/gsm/protocol/gsm_48_071.h b/include/osmocom/gsm/protocol/gsm_48_071.h
new file mode 100644
index 00000000..961211b3
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_48_071.h
@@ -0,0 +1,118 @@
+/*! \defgroup bsslap 3GPP TS 48.071 BSS LCS Assistance Protocol (BSSLAP).
+ * @{
+ * \file gsm_48_071.h
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+#pragma once
+
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+enum bsslap_msgt {
+ BSSLAP_MSGT_TA_REQUEST = 0x1,
+ BSSLAP_MSGT_TA_RESPONSE = 0x2,
+ BSSLAP_MSGT_REJECT = 0xa,
+ BSSLAP_MSGT_RESET = 0xb,
+ BSSLAP_MSGT_ABORT = 0xc,
+ BSSLAP_MSGT_TA_LAYER3 = 0xd,
+ BSSLAP_MSGT_MS_POS_CMD = 0xf,
+ BSSLAP_MSGT_MS_POS_RESP = 0x10,
+ BSSLAP_MSGT_UTDOA_REQ = 0x11,
+ BSSLAP_MSGT_UTDOA_RESP = 0x12,
+};
+
+enum bsslap_cause {
+ BSSLAP_CAUSE_CONGESTION = 0x0,
+ BSSLAP_CAUSE_CHAN_MODE_NOT_SUPP = 0x1,
+ BSSLAP_CAUSE_POS_PROC_NOT_SUPP = 0x2,
+ BSSLAP_CAUSE_OTHER_RADIO_EVT_FAIL = 0x3,
+ BSSLAP_CAUSE_INTRA_BSS_HO = 0x4,
+ BSSLAP_CAUSE_SUPERV_TIMER_EXPIRED = 0x5,
+ BSSLAP_CAUSE_INTER_BSS_HO = 0x6,
+ BSSLAP_CAUSE_LOSS_SIG_CONN_MS = 0x7,
+ BSSLAP_CAUSE_INCORR_SERV_CELL_ID = 0x8,
+ BSSLAP_CAUSE_BSSAP_LE_SEGMENT_ERR = 0x9,
+ BSSLAP_CAUSE_CONCUR_POS_PROC_NOT_EN = 0xa,
+};
+
+enum bsslap_iei {
+ BSSLAP_IEI_TA = 0x1,
+ BSSLAP_IEI_CELL_ID = 0x9,
+ BSSLAP_IEI_CHAN_DESC = 0x10,
+ BSSLAP_IEI_MEAS_REP = 0x14,
+ BSSLAP_IEI_CAUSE = 0x18,
+ BSSLAP_IEI_RRLP_FLAG = 0x19,
+ BSSLAP_IEI_RRLP = 0x1b,
+ BSSLAP_IEI_CELL_ID_LIST = 0x1c,
+ BSSLAP_IEI_ENH_MEAS_REP = 0x1d,
+ BSSLAP_IEI_LAC = 0x1e,
+ BSSLAP_IEI_FREQ_LIST = 0x21,
+ BSSLAP_IEI_MS_POWER = 0x22,
+ BSSLAP_IEI_DELTA_TIMER = 0x23,
+ BSSLAP_IEI_SERVING_CELL_ID = 0x24,
+ BSSLAP_IEI_ENCR_KEY = 0x25,
+ BSSLAP_IEI_CIPH_MODE_SET = 0x26,
+ BSSLAP_IEI_CHAN_MODE = 0x27,
+ BSSLAP_IEI_MR_CONFIG = 0x28,
+ BSSLAP_IEI_POLLING_REPETITION = 0x29,
+ BSSLAP_IEI_PACKET_CHAN_DESC = 0x2a,
+ BSSLAP_IEI_TLLI = 0x2b,
+ BSSLAP_IEI_TFI = 0x2c,
+ BSSLAP_IEI_TBF_START_TIME = 0x2d,
+ BSSLAP_IEI_PWRUP_START_TIME = 0x2e,
+ BSSLAP_IEI_LONG_ENCR_KEY = 0x2f,
+ BSSLAP_IEI_CONCUR_POS_PROC_F = 0x30,
+};
+
+struct bsslap_ta_response {
+ uint16_t cell_id;
+ uint8_t ta;
+
+ bool more_items; /*!< always set this to false */
+};
+
+struct bsslap_ta_layer3 {
+ uint8_t ta;
+
+ bool more_items; /*!< always set this to false */
+};
+
+struct bsslap_reset {
+ uint16_t cell_id;
+ uint8_t ta;
+ struct gsm48_chan_desc chan_desc;
+ enum bsslap_cause cause;
+
+ bool more_items; /*!< always set this to false */
+};
+
+struct bsslap_pdu {
+ enum bsslap_msgt msg_type;
+ union {
+ /* ta_request: a TA Request message consists only of the message type. */
+ struct bsslap_ta_response ta_response;
+ enum bsslap_cause reject;
+ struct bsslap_reset reset;
+ enum bsslap_cause abort;
+ struct bsslap_ta_layer3 ta_layer3;
+ };
+};
+
+/*! @} */
diff --git a/include/osmocom/gsm/protocol/gsm_49_031.h b/include/osmocom/gsm/protocol/gsm_49_031.h
new file mode 100644
index 00000000..463fabf5
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_49_031.h
@@ -0,0 +1,234 @@
+/*! \defgroup bssmap_le 3GPP TS 49.031 BSSMAP-LE.
+ * @{
+ * \file gsm_49_031.h
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <osmocom/core/endian.h>
+#include <osmocom/gsm/protocol/gsm_48_071.h>
+#include <osmocom/gsm/protocol/gsm_23_032.h>
+#include <osmocom/gsm/gsm0808_utils.h>
+#include <osmocom/gsm/gsm48.h>
+
+/*! 3GPP TS 49.031 10.13 LCS Cause, also in 3GPP TS 48.008 3.2.2.66, which simply refers to the former. */
+enum lcs_cause {
+ LCS_CAUSE_UNSPECIFIED = 0,
+ LCS_CAUSE_SYSTEM_FAILURE = 1,
+ LCS_CAUSE_PROTOCOL_ERROR = 2,
+ LCS_CAUSE_DATA_MISSING_IN_REQ = 3,
+ LCS_CAUSE_UNEXP_DATA_IN_REQ = 4,
+ LCS_CAUSE_POS_METH_FAILURE = 5,
+ LCS_CAUSE_TGT_MS_UNREACHABLE = 6,
+ LCS_CAUSE_REQUEST_ABORTED = 7,
+ LCS_CAUSE_FACILITY_NOTSUPP = 8,
+ LCS_CAUSE_INTER_BSC_HO = 9,
+ LCS_CAUSE_INTRA_BSC_HO = 10,
+ LCS_CAUSE_CONGESTION = 11,
+ LCS_CAUSE_INTER_NSE_CHG = 12,
+ LCS_CAUSE_RA_UPDAT = 13,
+ LCS_CAUSE_PTMSI_REALLOC = 14,
+ LCS_CAUSE_GPRS_SUSPENSION = 15,
+};
+
+/*! 3GPP TS 49.031 10.13 LCS Cause, also in 3GPP TS 48.008 3.2.2.66, which simply refers to the former. */
+struct lcs_cause_ie {
+ bool present;
+ enum lcs_cause cause_val;
+ bool diag_val_present;
+ uint8_t diag_val;
+};
+
+/* 3GPP TS 49.031 10.16 LCS QoS IE */
+struct osmo_bssmap_le_lcs_qos {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t vert:1, vel:1, spare1:6;
+ uint8_t ha_val:7, ha_ind:1;
+ uint8_t va_val:7, va_ind:1;
+ uint8_t spare3:6, rt:2;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t spare1:6, vel:1, vert:1;
+ uint8_t ha_ind:1, ha_val:7;
+ uint8_t va_ind:1, va_val:7;
+ uint8_t rt:2, spare3:6;
+#endif
+} __attribute__ ((packed));
+
+enum bssap_le_msg_discr {
+ BSSAP_LE_MSG_DISCR_BSSMAP_LE = 0,
+};
+
+enum bssmap_le_msgt {
+ BSSMAP_LE_MSGT_PERFORM_LOC_REQ = 0x2b,
+ BSSMAP_LE_MSGT_PERFORM_LOC_RESP = 0x2d,
+ BSSMAP_LE_MSGT_PERFORM_LOC_ABORT = 0x2e,
+ BSSMAP_LE_MSGT_PERFORM_LOC_INFO = 0x2f,
+ BSSMAP_LE_MSGT_ASSIST_INFO_REQ = 0x20,
+ BSSMAP_LE_MSGT_ASSIST_INFO_RESP = 0x21,
+ BSSMAP_LE_MSGT_CONN_ORIENTED_INFO = 0x2a,
+ BSSMAP_LE_MSGT_CONN_LESS_INFO = 0x3a,
+ BSSMAP_LE_MSGT_RESET = 0x30,
+ BSSMAP_LE_MSGT_RESET_ACK = 0x31,
+};
+
+enum bssmap_le_iei {
+ BSSMAP_LE_IEI_LCS_QoS = 0x3e,
+ BSSMAP_LE_IEI_LCS_PRIORITY = 0x43,
+ BSSMAP_LE_IEI_LOCATION_TYPE = 0x44,
+ BSSMAP_LE_IEI_GANSS_LOCATION_TYPE = 0x82,
+ BSSMAP_LE_IEI_GEO_LOCATION = 0x45,
+ BSSMAP_LE_IEI_POSITIONING_DATA = 0x46,
+ BSSMAP_LE_IEI_GANSS_POS_DATA = 0x83,
+ BSSMAP_LE_IEI_VELOCITY_DATA = 0x55,
+ BSSMAP_LE_IEI_LCS_CAUSE = 0x47,
+ BSSMAP_LE_IEI_LCS_CLIENT_TYPE = 0x48,
+ BSSMAP_LE_IEI_APDU = 0x49,
+ BSSMAP_LE_IEI_NET_ELEM_ID = 0x4a,
+ BSSMAP_LE_IEI_REQ_GPS_ASS_D = 0x4b,
+ BSSMAP_LE_IEI_REQ_GANSS_ASS_D = 0x41,
+ BSSMAP_LE_IEI_DECIPH_KEYS = 0x4c,
+ BSSMAP_LE_IEI_RET_ERR_REQ = 0x4d,
+ BSSMAP_LE_IEI_RET_ERR_CAUSE = 0x4e,
+ BSSMAP_LE_IEI_SEGMENTATION = 0x4f,
+ BSSMAP_LE_IEI_CLASSMARK3_INFO = 0x13,
+ BSSMAP_LE_IEI_CAUSE = 0x4,
+ BSSMAP_LE_IEI_CELL_ID = 0x5,
+ BSSMAP_LE_IEI_CHOSEN_CHAN = 0x21,
+ BSSMAP_LE_IEI_IMSI = 0x0,
+ BSSMAP_LE_IEI_LCS_CAPABILITY = 0x50,
+ BSSMAP_LE_IEI_PKT_MEAS_REP = 0x51,
+ BSSMAP_LE_IEI_CELL_ID_LIST = 0x52,
+ BSSMAP_LE_IEI_IMEI = 0x80,
+ BSSMAP_LE_IEI_BSS_MLAT_CAP = 0x84,
+ BSSMAP_LE_IEI_CELL_INFO_LIST = 0x85,
+ BSSMAP_LE_IEI_BTS_RX_ACC_LVL = 0x86,
+ BSSMAP_LE_IEI_MLAT_METHOD = 0x87,
+ BSSMAP_LE_IEI_MLAT_TA = 0x88,
+ BSSMAP_LE_IEI_MS_SYNC_ACC = 0x89,
+ BSSMAP_LE_IEI_SHORT_ID_SET = 0x8a,
+ BSSMAP_LE_IEI_RANDOM_ID_SET = 0x8b,
+ BSSMAP_LE_IEI_SHORT_BSS_ID = 0x8c,
+ BSSMAP_LE_IEI_RANDOM_ID = 0x8d,
+ BSSMAP_LE_IEI_SHORT_ID = 0x8e,
+ BSSMAP_LE_IEI_COVERAGE_CLASS = 0x8f,
+ BSSMAP_LE_IEI_MTA_ACC_SEC_RQD = 0x90,
+};
+
+enum bssmap_le_apdu_proto {
+ BSSMAP_LE_APDU_PROT_RESERVED = 0,
+ BSSMAP_LE_APDU_PROT_BSSLAP = 1,
+ BSSMAP_LE_APDU_PROT_LLP = 2,
+ BSSMAP_LE_APDU_PROT_SMLCPP = 3,
+};
+
+enum bssmap_le_location_information {
+ BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC = 0x0,
+ BSSMAP_LE_LOC_INFO_ASSIST_TARGET_MS = 0x1,
+ BSSMAP_LE_LOC_INFO_BC_DECIPHER_KEYS = 0x2,
+};
+
+enum bssmap_le_positioning_method {
+ BSSMAP_LE_POS_METHOD_OMITTED = 0x0,
+ BSSMAP_LE_POS_METHOD_MOBILE_ASSISTED_E_OTD = 0x1,
+ BSSMAP_LE_POS_METHOD_MOBILE_BASED_E_OTD = 0x2,
+ BSSMAP_LE_POS_METHOD_ASSISTED_GPS = 0x3,
+};
+
+struct bssmap_le_location_type {
+ enum bssmap_le_location_information location_information;
+ enum bssmap_le_positioning_method positioning_method;
+};
+
+enum bssmap_le_lcs_client_type {
+ BSSMAP_LE_LCS_CTYPE_VALUE_ADDED_UNSPECIFIED = 0x0,
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_UNSPECIFIED = 0x20,
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_BCAST_SERVICE = 0x21,
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_OAM = 0x22,
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_ANON_STATS = 0x23,
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_TGT_MS_SVC = 0x24,
+ BSSMAP_LE_LCS_CTYPE_EMERG_SVC_UNSPECIFIED = 0x30,
+ BSSMAP_LE_LCS_CTYPE_LI_UNSPECIFIED = 0x40,
+};
+
+struct bssmap_le_perform_loc_req {
+ struct bssmap_le_location_type location_type;
+ struct gsm0808_cell_id cell_id;
+
+ bool lcs_client_type_present;
+ enum bssmap_le_lcs_client_type lcs_client_type;
+
+ struct osmo_mobile_identity imsi;
+ struct osmo_mobile_identity imei;
+
+ bool apdu_present;
+ struct bsslap_pdu apdu;
+
+ bool more_items; /*!< set this to true iff any fields below are used */
+
+ bool lcs_priority_present;
+ uint8_t lcs_priority; /*!< see in 3GPP TS 29.002 */
+
+ bool lcs_qos_present;
+ struct osmo_bssmap_le_lcs_qos lcs_qos;
+
+ bool more_items2; /*!< always set this to false */
+};
+
+struct bssmap_le_perform_loc_resp {
+ bool location_estimate_present;
+ union gad_raw location_estimate;
+
+ struct lcs_cause_ie lcs_cause;
+
+ bool more_items; /*!< always set this to false */
+};
+
+struct bssmap_le_conn_oriented_info {
+ struct bsslap_pdu apdu;
+
+ bool more_items; /*!< always set this to false */
+};
+
+struct bssmap_le_pdu {
+ enum bssmap_le_msgt msg_type;
+ union {
+ enum gsm0808_cause reset;
+ /* reset_ack consists only of the message type */
+ struct bssmap_le_perform_loc_req perform_loc_req;
+ struct bssmap_le_perform_loc_resp perform_loc_resp;
+ struct lcs_cause_ie perform_loc_abort;
+ struct bssmap_le_conn_oriented_info conn_oriented_info;
+ };
+};
+
+struct bssap_le_pdu {
+ enum bssap_le_msg_discr discr;
+ union {
+ struct bssmap_le_pdu bssmap_le;
+ /* future: add DTAP PDU, currently not implemented */
+ };
+};
+
+/*! @} */
diff --git a/include/osmocom/gsm/protocol/ipaccess.h b/include/osmocom/gsm/protocol/ipaccess.h
index 4f1d0b16..51827607 100644
--- a/include/osmocom/gsm/protocol/ipaccess.h
+++ b/include/osmocom/gsm/protocol/ipaccess.h
@@ -39,6 +39,7 @@ enum ipaccess_proto_ext {
IPAC_PROTO_EXT_GSUP = 0x05, /* GSUP GPRS extension */
IPAC_PROTO_EXT_OAP = 0x06, /* Osmocom Authn Protocol */
IPAC_PROTO_EXT_RSPRO = 0x07, /* Remote SIM protocol */
+ IPAC_PROTO_EXT_PCU = 0x08, /* BSC<->BTS<->PCU communication */
};
enum ipaccess_msgtype {
diff --git a/include/osmocom/gsm/rlp.h b/include/osmocom/gsm/rlp.h
new file mode 100644
index 00000000..47b0a6c2
--- /dev/null
+++ b/include/osmocom/gsm/rlp.h
@@ -0,0 +1,81 @@
+/*
+ * GSM RLP (Radio Link Protocol) as used in CSD (3GPP TS 44.022)
+ *
+ * Copyright (C) 2022-2023 Harald Welte <laforge@osmocom.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ */
+
+
+
+#pragma once
+#include <stdint.h>
+#include <stdbool.h>
+#include <osmocom/core/utils.h>
+
+/*! \defgroup rlp GSM RLP (Radio Link Protocol) as used in CSD (3GPP TS 24.022)
+ * @{
+ * \file rlp.h */
+
+/*! RLP frame type as per 3GPP TS 24.022 Section 5.2.1 */
+enum osmo_rlp_ftype {
+ OSMO_RLP_FT_U,
+ OSMO_RLP_FT_S,
+ OSMO_RLP_FT_IS,
+};
+extern const struct value_string osmo_rlp_ftype_vals[];
+
+/*! RLP U-Frame Type as per 3GPP TS 24.022 Section 5.2.1 */
+enum osmo_rlp_u_ftype {
+ OSMO_RLP_U_FT_SABM = 0x07,
+ OSMO_RLP_U_FT_UA = 0x0c,
+ OSMO_RLP_U_FT_DISC = 0x08,
+ OSMO_RLP_U_FT_DM = 0x03,
+ OSMO_RLP_U_FT_NULL = 0x0f,
+ OSMO_RLP_U_FT_UI = 0x00,
+ OSMO_RLP_U_FT_XID = 0x17,
+ OSMO_RLP_U_FT_TEST = 0x1c,
+ OSMO_RLP_U_FT_REMAP = 0x11,
+};
+extern const struct value_string osmo_rlp_ftype_u_vals[];
+
+/*! RLP S-Frame type as per 3GPP TS 24.022 Section 5.2.1 */
+enum osmo_rlp_s_ftype {
+ OSMO_RLP_S_FT_RR = 0,
+ OSMO_RLP_S_FT_REJ = 2,
+ OSMO_RLP_S_FT_RNR = 1,
+ OSMO_RLP_S_FT_SREJ = 3,
+};
+extern const struct value_string osmo_rlp_ftype_s_vals[];
+
+/*! Data structure representing one decoded RLP frame */
+struct osmo_rlp_frame_decoded {
+ uint8_t version;
+ enum osmo_rlp_ftype ftype;
+ enum osmo_rlp_u_ftype u_ftype;
+ enum osmo_rlp_s_ftype s_ftype;
+ bool c_r;
+ bool p_f;
+ uint8_t s_bits;
+ uint16_t n_s;
+ uint16_t n_r;
+ uint32_t fcs;
+ uint8_t info[536/8];
+ uint16_t info_len;
+};
+
+int osmo_rlp_decode(struct osmo_rlp_frame_decoded *out, uint8_t version, const uint8_t *data, size_t data_len);
+int osmo_rlp_encode(uint8_t *out, size_t out_size, const struct osmo_rlp_frame_decoded *in);
+uint32_t osmo_rlp_fcs_compute(const uint8_t *in, size_t in_len);
+
+/*! @} */
diff --git a/include/osmocom/gsm/tlv.h b/include/osmocom/gsm/tlv.h
index 254c21bc..28e897d7 100644
--- a/include/osmocom/gsm/tlv.h
+++ b/include/osmocom/gsm/tlv.h
@@ -4,6 +4,7 @@
#include <string.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/core/byteswap.h>
#include <osmocom/core/bit16gen.h>
#include <osmocom/core/bit32gen.h>
@@ -40,6 +41,16 @@
/*! maximum length of TLV of one byte length */
#define TVLV_MAX_ONEBYTE 0x7f
+/*! error return codes of various TLV parser functions */
+enum osmo_tlv_parser_error {
+ OSMO_TLVP_ERR_OFS_BEYOND_BUFFER = -1,
+ OSMO_TLVP_ERR_OFS_LEN_BEYOND_BUFFER = -2,
+ OSMO_TLVP_ERR_UNKNOWN_TLV_TYPE = -3,
+
+ OSMO_TLVP_ERR_MAND_IE_MISSING = -50,
+ OSMO_TLVP_ERR_IE_TOO_SHORT = -51,
+};
+
/*! gross length of a TVLV type field */
static inline uint16_t TVLV_GROSS_LEN(uint16_t len)
{
@@ -137,7 +148,7 @@ static inline uint8_t *tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len,
*buf++ = len >> 8;
*buf++ = len & 0xff;
memcpy(buf, val, len);
- return buf + len*2;
+ return buf + len;
}
/*! put (append) a TL16 field. */
@@ -157,7 +168,7 @@ static inline uint8_t *t16lv_put(uint8_t *buf, uint16_t tag, uint8_t len,
*buf++ = tag & 0xff;
*buf++ = len;
memcpy(buf, val, len);
- return buf + len + 2;
+ return buf + len;
}
/*! put (append) a TvLV field */
@@ -268,6 +279,20 @@ static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len
return tvlv_put(buf, tag, len, val);
}
+/*! put (append) a TvLV field containing a big-endian 16bit value to msgb. */
+static inline uint8_t *msgb_tvlv_put_16be(struct msgb *msg, uint8_t tag, uint16_t val)
+{
+ uint16_t val_be = osmo_htons(val);
+ return msgb_tvlv_put(msg, tag, 2, (const uint8_t *)&val_be);
+}
+
+/*! put (append) a TvLV field containing a big-endian 16bit value to msgb. */
+static inline uint8_t *msgb_tvlv_put_32be(struct msgb *msg, uint8_t tag, uint32_t val)
+{
+ uint32_t val_be = osmo_htonl(val);
+ return msgb_tvlv_put(msg, tag, 4, (const uint8_t *)&val_be);
+}
+
/*! put (append) a vTvLV field to \ref msgb */
static inline uint8_t *msgb_vtvlv_gan_put(struct msgb *msg, uint16_t tag,
uint16_t len, const uint8_t *val)
@@ -297,7 +322,7 @@ static inline uint8_t *v_put(uint8_t *buf, uint8_t val)
}
/*! put (append) a TV field */
-static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag,
+static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag,
uint8_t val)
{
*buf++ = tag;
@@ -319,7 +344,7 @@ static inline uint8_t *tv_fixed_put(uint8_t *buf, uint8_t tag,
* \param[in] tag Tag value
* \param[in] val Value (in host byte order!)
*/
-static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag,
+static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag,
uint16_t val)
{
*buf++ = tag;
@@ -381,7 +406,7 @@ static inline uint8_t *msgb_tl_put(struct msgb *msg, uint8_t tag)
return len;
}
-/*! put (append) a TV16 field to a \ref msgb
+/*! put (append) a TV16 field (network order) to the given msgb
* \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val)
{
@@ -389,6 +414,16 @@ static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val
return tv16_put(buf, tag, val);
}
+/*! put (append) a TV32 field (network order) to the given msgb
+ * \returns pointer to first byte after newly-put information */
+static inline uint8_t *msgb_tv32_put(struct msgb *msg, uint8_t tag, uint32_t val)
+{
+ uint8_t *buf = msgb_put(msg, 1 + 4);
+ *buf++ = tag;
+ osmo_store32be(val, buf);
+ return msg->tail;
+}
+
/*! push (prepend) a TLV field to a \ref msgb
* \returns pointer to first byte of newly-pushed information */
static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
@@ -422,6 +457,16 @@ static inline uint8_t *msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t va
return buf;
}
+/*! push (prepend) a TV32 field to a \ref msgb
+ * \returns pointer to first byte of newly-pushed information */
+static inline uint8_t *msgb_tv32_push(struct msgb *msg, uint8_t tag, uint32_t val)
+{
+ uint8_t *buf = msgb_push(msg, 5);
+ *buf++ = tag;
+ osmo_store32be(val, buf);
+ return buf;
+}
+
/*! push (prepend) a TvLV field to a \ref msgb
* \returns pointer to first byte of newly-pushed information */
static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t len,
@@ -508,7 +553,7 @@ int tlv_encode(struct msgb *msg, const struct tlv_definition *def, const struct
int tlv_encode_ordered(struct msgb *msg, const struct tlv_definition *def, const struct tlv_parsed *tp,
const uint8_t *tag_order, unsigned int tag_order_len);
-#define TLVP_PRESENT(x, y) ((x)->lv[y].val)
+#define TLVP_PRESENT(x, y) (!!((x)->lv[y].val))
#define TLVP_LEN(x, y) (x)->lv[y].len
#define TLVP_VAL(x, y) (x)->lv[y].val
@@ -620,4 +665,54 @@ int osmo_match_shift_tlv(uint8_t **data, size_t *data_len,
int osmo_shift_lv(uint8_t **data, size_t *data_len,
uint8_t **value, size_t *value_len);
+#define MSG_DEF(name, mand_ies, flags) { name, mand_ies, ARRAY_SIZE(mand_ies), flags }
+
+struct osmo_tlv_prot_msg_def {
+ /*! human-readable name of message type (optional) */
+ const char *name;
+ /*! array of mandatory IEs */
+ const uint8_t *mand_ies;
+ /*! number of entries in 'mand_ies' above */
+ uint8_t mand_count;
+ /*! user-defined flags (like uplink/downlink/...) */
+ uint32_t flags;
+};
+struct osmo_tlv_prot_ie_def {
+ /*! minimum length of IE value part, in octets */
+ uint16_t min_len;
+ /*! huamn-readable name (optional) */
+ const char *name;
+};
+
+/*! Osmocom TLV protocol definition */
+struct osmo_tlv_prot_def {
+ /*! human-readable name of protocol */
+ const char *name;
+ /*! TLV parser definition (optional) */
+ const struct tlv_definition *tlv_def;
+ /*! definition of each message (8-bit message type) */
+ struct osmo_tlv_prot_msg_def msg_def[256];
+ /*! definition of IE for each 8-bit tag */
+ struct osmo_tlv_prot_ie_def ie_def[256];
+ /*! value_string array of message type names (legacy, if not populated in msg_def) */
+ const struct value_string *msgt_names;
+};
+
+const char *osmo_tlv_prot_msg_name(const struct osmo_tlv_prot_def *pdef, uint8_t msg_type);
+const char *osmo_tlv_prot_ie_name(const struct osmo_tlv_prot_def *pdef, uint8_t iei);
+
+int osmo_tlv_prot_validate_tp(const struct osmo_tlv_prot_def *pdef, uint8_t msg_type,
+ const struct tlv_parsed *tp, int log_subsys, const char *log_pfx);
+
+int osmo_tlv_prot_parse(const struct osmo_tlv_prot_def *pdef,
+ struct tlv_parsed *dec, unsigned int dec_multiples, uint8_t msg_type,
+ const uint8_t *buf, unsigned int buf_len, uint8_t lv_tag, uint8_t lv_tag2,
+ int log_subsys, const char *log_pfx);
+
+static inline uint32_t osmo_tlv_prot_msgt_flags(const struct osmo_tlv_prot_def *pdef, uint8_t msg_type)
+{
+ return pdef->msg_def[msg_type].flags;
+}
+
+
/*! @} */