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.h4
-rw-r--r--include/osmocom/gsm/bssmap_le.h4
-rw-r--r--include/osmocom/gsm/bts_features.h8
-rw-r--r--include/osmocom/gsm/cbsp.h33
-rw-r--r--include/osmocom/gsm/gsm0502.h66
-rw-r--r--include/osmocom/gsm/gsm0808.h284
-rw-r--r--include/osmocom/gsm/gsm0808_lcs.h4
-rw-r--r--include/osmocom/gsm/gsm0808_utils.h278
-rw-r--r--include/osmocom/gsm/gsm23003.h7
-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.h12
-rw-r--r--include/osmocom/gsm/gsm48_ie.h5
-rw-r--r--include/osmocom/gsm/gsm48_rest_octets.h5
-rw-r--r--include/osmocom/gsm/gsm_utils.h26
-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.h3
-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.h231
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_08_gprs.h65
-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.h162
-rw-r--r--include/osmocom/gsm/protocol/gsm_08_58.h285
-rw-r--r--include/osmocom/gsm/protocol/gsm_09_02.h5
-rw-r--r--include/osmocom/gsm/protocol/gsm_12_21.h165
-rw-r--r--include/osmocom/gsm/protocol/gsm_23_032.h16
-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.h14
-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.h4
-rw-r--r--include/osmocom/gsm/protocol/gsm_49_031.h32
-rw-r--r--include/osmocom/gsm/rlp.h81
-rw-r--r--include/osmocom/gsm/tlv.h16
49 files changed, 2489 insertions, 601 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
index b2174b3a..56f2e6c8 100644
--- a/include/osmocom/gsm/bsslap.h
+++ b/include/osmocom/gsm/bsslap.h
@@ -21,10 +21,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/bssmap_le.h b/include/osmocom/gsm/bssmap_le.h
index 1c750c8a..113d4bd1 100644
--- a/include/osmocom/gsm/bssmap_le.h
+++ b/include/osmocom/gsm/bssmap_le.h
@@ -21,10 +21,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/bts_features.h b/include/osmocom/gsm/bts_features.h
index 8bd5ef57..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
- osmo_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,
@@ -30,6 +30,12 @@ enum osmo_bts_features {
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
};
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/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 dc3610fd..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);
@@ -198,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);
@@ -225,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);
@@ -244,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;
@@ -307,6 +332,243 @@ 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);
diff --git a/include/osmocom/gsm/gsm0808_lcs.h b/include/osmocom/gsm/gsm0808_lcs.h
index 8fcbe380..71665013 100644
--- a/include/osmocom/gsm/gsm0808_lcs.h
+++ b/include/osmocom/gsm/gsm0808_lcs.h
@@ -20,10 +20,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/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h
index 76e90645..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,8 @@ 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;
};
@@ -60,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 */
@@ -109,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,
@@ -125,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)
@@ -179,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. */
@@ -221,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:
@@ -238,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;
}
@@ -255,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;
}
@@ -266,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 487379a4..4070581f 100644
--- a/include/osmocom/gsm/gsm23003.h
+++ b/include/osmocom/gsm/gsm23003.h
@@ -30,6 +30,9 @@ 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;
@@ -134,6 +137,10 @@ 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);
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 c1ca6308..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,18 +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");
diff --git a/include/osmocom/gsm/gsm48_ie.h b/include/osmocom/gsm/gsm48_ie.h
index b79cbfcb..4768283f 100644
--- a/include/osmocom/gsm/gsm48_ie.h
+++ b/include/osmocom/gsm/gsm48_ie.h
@@ -117,8 +117,9 @@ 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,
diff --git a/include/osmocom/gsm/gsm48_rest_octets.h b/include/osmocom/gsm/gsm48_rest_octets.h
index f2958249..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,
diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h
index 0909006e..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
@@ -156,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
@@ -177,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,
@@ -213,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 045e353b..73cd7f71 100644
--- a/include/osmocom/gsm/prim.h
+++ b/include/osmocom/gsm/prim.h
@@ -18,4 +18,7 @@ enum osmo_gsm_sap {
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 3fa94191..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,7 +51,7 @@ 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;
@@ -280,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;
@@ -335,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;
@@ -396,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;
@@ -459,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;
@@ -489,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;
@@ -509,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
@@ -522,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
@@ -573,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;
@@ -593,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
@@ -610,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
@@ -623,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));
@@ -638,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;
@@ -696,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;
@@ -711,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
@@ -725,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));
@@ -740,18 +746,58 @@ 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,
};
@@ -791,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
@@ -834,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;
@@ -861,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
@@ -882,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;
@@ -898,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
@@ -906,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;
@@ -922,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
@@ -941,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;
@@ -964,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));
@@ -985,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;
@@ -1068,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];
@@ -1083,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];
@@ -1098,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];
@@ -1117,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;
@@ -1128,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;
@@ -1183,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));
@@ -1228,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
@@ -1240,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;
@@ -1263,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;
@@ -1293,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;
@@ -1316,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;
@@ -1329,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
@@ -1347,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); }
@@ -1534,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
@@ -1699,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
@@ -1740,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
@@ -2086,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 dbac2597..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,27 +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 */
@@ -129,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;
@@ -158,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;
@@ -176,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];
@@ -190,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
@@ -281,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 {
@@ -464,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 983783ee..1e211dc9 100644
--- a/include/osmocom/gsm/protocol/gsm_08_08.h
+++ b/include/osmocom/gsm/protocol/gsm_08_08.h
@@ -25,9 +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 */
- CELL_IDENT_WHOLE_GLOBAL_PS = 11, /* CGI with + RAC */
+ /* 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
@@ -53,7 +54,7 @@ struct dtap_header {
dlci_spare:3,
dlci_cc: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 dlci_cc:2, dlci_spare:3, dlci_sapi:3;
#endif
};
@@ -167,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,
@@ -265,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,
@@ -442,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,
@@ -497,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); }
@@ -515,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); }
@@ -539,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;
@@ -562,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,
@@ -572,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,
@@ -586,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,
@@ -600,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 {
@@ -607,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 */
@@ -677,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 a03b199c..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))
@@ -59,6 +57,7 @@ union abis_rsl_chan_nr {
/* Link Identifier 9.3.2 */
union abis_rsl_link_id {
+ struct {
#if OSMO_IS_BIG_ENDIAN
uint8_t cbits:2,
na:1,
@@ -70,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
@@ -122,20 +122,29 @@ struct abis_rsl_cchan_hdr {
/* Osmocom specific IE to negotiate repeated ACCH capabilities */
struct abis_rsl_osmo_rep_acch_cap {
-#if OSMO_IS_BIG_ENDIAN
- uint8_t reserved:1,
- rxqual:3,
- ul_sacch:1,
- dl_sacch:1,
- dl_facch_all:1,
- dl_facch_cmd:1;
-#elif OSMO_IS_LITTLE_ENDIAN
- uint8_t dl_facch_cmd:1,
- dl_facch_all:1,
- dl_sacch:1,
- ul_sacch:1,
- rxqual:3,
- reserved:1;
+#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));
@@ -360,8 +369,10 @@ enum abis_rsl_ie {
RSL_IE_SIEMENS_SUGGESTED_RATE = 0x4f,
/* Osmocom specific */
- RSL_IE_OSMO_REP_ACCH_CAP= 0x60,
+ 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,
@@ -379,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
@@ -416,7 +427,7 @@ enum {
IPAC_OSMO_EWMA_AVE,
};
-/* IPAC MEAS_PREPROC AVERAGING PARAMID */
+/* IPAC MEAS_PREPROC AVERAGING PARAM ID */
enum {
IPAC_RXLEV_AVE = 0,
IPAC_RXQUAL_AVE,
@@ -489,51 +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 */
-#define RSL_CMOD_CRT_TCH_BI_Bm 0x0a /* full-rate: bi-directional (multislot) */
-#define RSL_CMOD_CRT_TCH_UNI_Bm 0x1a /* full-rate: uni-directional (multislot) */
-#define RSL_CMOD_CRT_TCH_GROUP_Bm 0x18 /* full-rate: group call channel */
-#define RSL_CMOD_CRT_TCH_GROUP_Lm 0x19 /* half-rate: group call channel */
-#define RSL_CMOD_CRT_TCH_BCAST_Bm 0x28 /* full-rate: broadcast call channel */
-#define RSL_CMOD_CRT_TCH_BCAST_Lm 0x29 /* half-rate: broadcast call channel */
-#define RSL_CMOD_CRT_OSMO_TCH_VAMOS_Bm 0x88 /* full-rate in VAMOS mode */
-#define RSL_CMOD_CRT_OSMO_TCH_VAMOS_Lm 0x89 /* half-rate in VAMOS mode */
-/* Speech */
-#define RSL_CMOD_SP_GSM1 0x01
-#define RSL_CMOD_SP_GSM2 0x11
-#define RSL_CMOD_SP_GSM3 0x21
-#define RSL_CMOD_SP_GSM4 0x31
-#define RSL_CMOD_SP_GSM5 0x09
-#define RSL_CMOD_SP_GSM6 0x0d
-/* non-transparent data (asymmetric) */
-#define RSL_CMOD_CSD_NTA_43k5_14k5 0x61 /* asymmetric 43.5 kbit/s (DL) + 14.5 kbit/s (UL) */
-#define RSL_CMOD_CSD_NTA_29k0_14k5 0x62 /* asymmetric 29.0 kbit/s (DL) + 14.5 kbit/s (UL) */
-#define RSL_CMOD_CSD_NTA_43k5_29k0 0x63 /* asymmetric 43.5 kbit/s (DL) + 29.0 kbit/s (UL) */
-#define RSL_CMOD_CSD_NTA_14k5_43k5 0x69 /* asymmetric 14.5 kbit/s (DL) + 43.5 kbit/s (UL) */
-#define RSL_CMOD_CSD_NTA_14k5_29k0 0x6a /* asymmetric 14.5 kbit/s (DL) + 29.0 kbit/s (UL) */
-#define RSL_CMOD_CSD_NTA_29k0_43k5 0x6b /* asymmetric 29.0 kbit/s (DL) + 43.5 kbit/s (UL) */
-/* 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 {
@@ -651,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;
@@ -659,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));
@@ -677,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
@@ -722,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 {
@@ -793,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,
@@ -804,14 +853,39 @@ struct ipac_preproc_ave_cfg {
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));
-/*! MS/BS Power Control Thresholds */
+
+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;
@@ -819,13 +893,24 @@ struct ipac_preproc_pc_thresh {
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;
+ 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
@@ -844,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;
@@ -854,7 +939,7 @@ struct ipac_preproc_ho_thresh {
#endif
}__attribute__ ((packed));
-/*! PC Threshold Comparators */
+/*! 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;
@@ -868,6 +953,7 @@ struct ipac_preproc_pc_comp {
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;
@@ -881,6 +967,31 @@ struct ipac_preproc_pc_comp {
#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
@@ -905,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;
@@ -928,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
@@ -943,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;
@@ -956,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));
@@ -973,18 +1084,16 @@ struct ipac_preproc_cfg {
};
struct rsl_l1_info {
-#if OSMO_IS_BIG_ENDIAN
- uint8_t ms_pwr:5,
- fpc_epc:1,
- srr_sro:1,
- reserved:1;
- uint8_t ta;
-#elif OSMO_IS_LITTLE_ENDIAN
+#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 34622b33..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,62 @@ 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,
diff --git a/include/osmocom/gsm/protocol/gsm_23_032.h b/include/osmocom/gsm/protocol/gsm_23_032.h
index a4c05061..6eb65ca2 100644
--- a/include/osmocom/gsm/protocol/gsm_23_032.h
+++ b/include/osmocom/gsm/protocol/gsm_23_032.h
@@ -54,7 +54,7 @@ struct gad_raw_head {
uint8_t spare:4,
type: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 type:4, spare:4;
#endif
} __attribute__ ((packed));
@@ -73,7 +73,7 @@ struct gad_raw_ell_point_unc_circle {
uint8_t unc:7,
spare2: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) */
struct gad_raw_head h;
uint8_t lat[3];
uint8_t lon[3];
@@ -94,7 +94,7 @@ struct gad_raw_ell_point_unc_ellipse {
uint8_t confidence:7,
spare3: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) */
struct gad_raw_head h;
uint8_t lat[3];
uint8_t lon[3];
@@ -111,7 +111,7 @@ struct gad_raw_polygon {
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_endianess.py) */
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t type:4, num_points:4;
#endif
} h;
@@ -144,7 +144,7 @@ struct gad_raw_ell_point_alt_unc_ell {
uint8_t confidence:7,
spare4: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) */
struct gad_raw_head h;
uint8_t lat[3];
uint8_t lon[3];
@@ -170,7 +170,7 @@ struct gad_raw_ell_arc {
uint8_t confidence:7,
spare2: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) */
struct gad_raw_head h;
uint8_t lat[3];
uint8_t lon[3];
@@ -194,7 +194,7 @@ struct gad_raw_ha_ell_point_unc_ell {
uint8_t confidence:7,
spare1: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) */
struct gad_raw_head h;
uint8_t lat[4];
uint8_t lon[4];
@@ -221,7 +221,7 @@ struct gad_raw_ha_ell_point_alt_unc_ell {
uint8_t v_confidence:7,
spare2: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) */
struct gad_raw_head h;
uint8_t lat[4];
uint8_t lon[4];
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
index 83be9bfd..c30ba0c9 100644
--- a/include/osmocom/gsm/protocol/gsm_44_004.h
+++ b/include/osmocom/gsm/protocol/gsm_44_004.h
@@ -1,19 +1,19 @@
#pragma once
+#include <osmocom/core/endian.h>
+
/* TS 44.004 Section 7.1 */
struct gsm_sacch_l1_hdr {
-#if OSMO_IS_BIG_ENDIAN
- uint8_t reserved:1,
- srr_sro:1,
- fpc_epc:1,
- ms_pwr:5;
- uint8_t ta;
-#elif OSMO_IS_LITTLE_ENDIAN
+#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
index fb9653ab..961211b3 100644
--- a/include/osmocom/gsm/protocol/gsm_48_071.h
+++ b/include/osmocom/gsm/protocol/gsm_48_071.h
@@ -20,10 +20,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/protocol/gsm_49_031.h b/include/osmocom/gsm/protocol/gsm_49_031.h
index c6152e17..463fabf5 100644
--- a/include/osmocom/gsm/protocol/gsm_49_031.h
+++ b/include/osmocom/gsm/protocol/gsm_49_031.h
@@ -20,15 +20,13 @@
* 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 <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>
@@ -62,6 +60,22 @@ struct lcs_cause_ie {
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,
};
@@ -171,7 +185,15 @@ struct bssmap_le_perform_loc_req {
bool apdu_present;
struct bsslap_pdu apdu;
- bool more_items; /*!< always set this to false */
+ 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 {
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 7e6dfb5f..28e897d7 100644
--- a/include/osmocom/gsm/tlv.h
+++ b/include/osmocom/gsm/tlv.h
@@ -322,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;
@@ -344,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;
@@ -457,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,
@@ -543,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