diff options
Diffstat (limited to 'include/osmocom/gsm')
52 files changed, 3911 insertions, 534 deletions
diff --git a/include/osmocom/gsm/Makefile.am b/include/osmocom/gsm/Makefile.am new file mode 100644 index 00000000..e42ffeca --- /dev/null +++ b/include/osmocom/gsm/Makefile.am @@ -0,0 +1,70 @@ +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 \ + rtp_extensions.h \ + rxlev_stat.h \ + sysinfo.h \ + tlv.h \ + $(NULL) + +osmogsmdir = $(includedir)/osmocom/gsm + +noinst_HEADERS = \ + kasumi.h \ + gea.h \ + $(NULL) + +gsm0503.h: $(top_srcdir)/utils/conv_gen.py $(top_srcdir)/utils/conv_codes_gsm.py + $(AM_V_GEN)python3 $(top_srcdir)/utils/conv_gen.py gen_header gsm \ + --target-path $(builddir)/ + +CLEANFILES = gsm0503.h diff --git a/include/osmocom/gsm/a5.h b/include/osmocom/gsm/a5.h index fa63246d..1b26842f 100644 --- a/include/osmocom/gsm/a5.h +++ b/include/osmocom/gsm/a5.h @@ -12,10 +12,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #pragma once diff --git a/include/osmocom/gsm/bsslap.h b/include/osmocom/gsm/bsslap.h new file mode 100644 index 00000000..56f2e6c8 --- /dev/null +++ b/include/osmocom/gsm/bsslap.h @@ -0,0 +1,53 @@ +/*! \addtogroup bsslap + * @{ + * \file bsslap.h + * Message encoding and decoding for 3GPP TS 48.071 BSS LCS Assistance Protocol (BSSLAP). + */ +/* + * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr <neels@hofmeyr.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#pragma once + +#include <osmocom/gsm/protocol/gsm_48_071.h> +#include <osmocom/gsm/protocol/gsm_49_031.h> + +struct msgb; + +struct osmo_bsslap_err { + int rc; + enum bsslap_msgt msg_type; + enum bsslap_iei iei; + enum lcs_cause cause; + char *logmsg; +}; + +extern const struct value_string osmo_bsslap_msgt_names[]; +static inline const char *osmo_bsslap_msgt_name(enum bsslap_msgt val) +{ return get_value_string(osmo_bsslap_msgt_names, val); } + +extern const struct value_string osmo_bsslap_iei_names[]; +static inline const char *osmo_bsslap_iei_name(enum bsslap_iei val) +{ return get_value_string(osmo_bsslap_iei_names, val); } + +int osmo_bsslap_enc(struct msgb *msg, const struct bsslap_pdu *pdu); +int osmo_bsslap_dec(struct bsslap_pdu *pdu, + struct osmo_bsslap_err **err, void *err_ctx, + const uint8_t *data, size_t len); + +/*! @} */ diff --git a/include/osmocom/gsm/bssmap_le.h b/include/osmocom/gsm/bssmap_le.h new file mode 100644 index 00000000..113d4bd1 --- /dev/null +++ b/include/osmocom/gsm/bssmap_le.h @@ -0,0 +1,77 @@ +/*! \addtogroup bssmap_le + * @{ + * \file bssmap_le.h + * Message encoding and decoding for 3GPP TS 49.031 BSSMAP-LE. + */ +/* + * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr <neels@hofmeyr.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#pragma once + +#include <osmocom/gsm/protocol/gsm_49_031.h> + +struct osmo_bsslap_err; +struct osmo_gad_err; + +struct osmo_bssmap_le_err { + int rc; + enum bssmap_le_msgt msg_type; + enum bssmap_le_iei iei; + enum lcs_cause cause; + struct osmo_bsslap_err *bsslap_err; + struct osmo_gad_err *gad_err; + char *logmsg; +}; + +struct osmo_bssap_le_err { + int rc; + struct osmo_bssmap_le_err *bssmap_le_err; + void *dtap_err; + char *logmsg; +}; + +enum bssmap_le_msgt osmo_bssmap_le_msgt(const uint8_t *data, uint8_t len); + +extern const struct value_string osmo_bssmap_le_msgt_names[]; +static inline const char *osmo_bssmap_le_msgt_name(enum bssmap_le_msgt val) +{ return get_value_string(osmo_bssmap_le_msgt_names, val); } + +extern const struct value_string osmo_bssmap_le_iei_names[]; +static inline const char *osmo_bssmap_le_iei_name(enum bssmap_le_iei val) +{ return get_value_string(osmo_bssmap_le_iei_names, val); } + +int osmo_lcs_cause_enc(struct msgb *msg, const struct lcs_cause_ie *lcs_cause); +int osmo_lcs_cause_dec(struct lcs_cause_ie *lcs_cause, + enum bssmap_le_msgt msgt, enum bssmap_le_iei iei, + struct osmo_bssmap_le_err **err, void *err_ctx, + const uint8_t *data, uint8_t len); + +int osmo_bssap_le_pdu_to_str_buf(char *buf, size_t buflen, const struct bssap_le_pdu *bssap_le); +char *osmo_bssap_le_pdu_to_str_c(void *ctx, const struct bssap_le_pdu *bssap_le); + +struct msgb *osmo_bssap_le_enc(const struct bssap_le_pdu *pdu); +int osmo_bssap_le_dec(struct bssap_le_pdu *pdu, struct osmo_bssap_le_err **err, void *err_ctx, struct msgb *msg); + +uint8_t osmo_bssmap_le_ie_enc_location_type(struct msgb *msg, const struct bssmap_le_location_type *location_type); +int osmo_bssmap_le_ie_dec_location_type(struct bssmap_le_location_type *lt, + enum bssmap_le_msgt msgt, enum bssmap_le_iei iei, + struct osmo_bssmap_le_err **err, void *err_ctx, + const uint8_t *elem, uint8_t len); + +/*! @} */ diff --git a/include/osmocom/gsm/bts_features.h b/include/osmocom/gsm/bts_features.h index 22461a6b..8da08d83 100644 --- a/include/osmocom/gsm/bts_features.h +++ b/include/osmocom/gsm/bts_features.h @@ -7,7 +7,7 @@ /* N. B: always add new features to the end of the list (right before _NUM_BTS_FEAT) to avoid breaking compatibility with BTS compiled against earlier version of this header. Also make sure that the description strings - gsm_bts_features_descs[] in gsm_data.c are also updated accordingly! */ + osmo_bts_features_{descs,names}[] in bts_features.c are also updated accordingly! */ enum osmo_bts_features { BTS_FEAT_HSCSD, BTS_FEAT_GPRS, @@ -25,12 +25,34 @@ enum osmo_bts_features { BTS_FEAT_SPEECH_H_AMR, BTS_FEAT_ETWS_PN, BTS_FEAT_PAGING_COORDINATION, /* BTS hands CS paging to PCU/PACCH */ + BTS_FEAT_IPV6_NSVC, + BTS_FEAT_ACCH_REP, + BTS_FEAT_CCN, /* Is CCN supported by the cell? TS 44.060 sec 8.8.2 */ + BTS_FEAT_VAMOS, /* Is the BTS VAMOS capable? */ + BTS_FEAT_ABIS_OSMO_PCU, /* BTS supports forwarding data to PCUIF over IPA OML multiplex */ + BTS_FEAT_BCCH_POWER_RED, + BTS_FEAT_DYN_TS_SDCCH8, /* Osmo Dynamic TS supports configured as SDCCH8 */ + BTS_FEAT_ACCH_TEMP_OVP, /* FACCH/SACCH Temporary overpower */ + BTS_FEAT_OSMUX, /* Osmux (Osmocom RTP muxing) support */ + BTS_FEAT_VBS, /* Voice Broadcast Service support, 3GPP TS 43.069 */ + BTS_FEAT_VGCS, /* Voice Group Call Service support, 3GPP TS 44.068 */ + BTS_FEAT_TWTS001, /* TW-TS-001: enhanced RTP transport for FR & EFR */ + BTS_FEAT_TWTS002, /* TW-TS-002: enhanced RTP transport for HRv1 */ _NUM_BTS_FEAT }; extern const struct value_string osmo_bts_features_descs[]; -const char *osmo_bts_feature_name(enum osmo_bts_features feature); +static inline const char *osmo_bts_features_desc(enum osmo_bts_features val) +{ return get_value_string(osmo_bts_features_descs, val); } + +const char *osmo_bts_feature_name(enum osmo_bts_features feature) + OSMO_DEPRECATED("Use osmo_bts_features_desc() instead"); + +extern const struct value_string osmo_bts_features_names[]; + +static inline const char *osmo_bts_features_name(enum osmo_bts_features val) +{ return get_value_string(osmo_bts_features_names, val); } static inline int osmo_bts_set_feature(struct bitvec *features, enum osmo_bts_features feature) { diff --git a/include/osmocom/gsm/cbsp.h b/include/osmocom/gsm/cbsp.h index 90516cb7..efa4ce6f 100644 --- a/include/osmocom/gsm/cbsp.h +++ b/include/osmocom/gsm/cbsp.h @@ -6,8 +6,8 @@ #include <osmocom/gsm/gsm0808_utils.h> /* Definitions for parsed / abstract representation of messages in the - * CBSP (Cell Broadcast Service Protocol). Data here is *not* formatted - * like the * on-the-wire format. Any similarities are coincidetial ;) */ + * CBSP (Cell Broadcast Service Protocol, 3GPP TS 48.049). Data here is *not* formatted + * like the on-the-wire format. Any similarities are coincidential ;) */ /* Copyright (C) 2019 Harald Welte <laforge@gnumonks.org> * @@ -24,10 +24,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Decoded 8.2.3 Message Content */ @@ -75,7 +71,7 @@ struct osmo_cbsp_fail_ent { struct llist_head list; /* entry in a fail_list below */ enum CELL_IDENT id_discr; union gsm0808_cell_id_u cell_id; - uint8_t cause; + uint8_t cause; /* enum osmo_cbsp_cause */ }; @@ -245,6 +241,30 @@ struct osmo_cbsp_error_ind { enum cbsp_channel_ind *channel_ind; }; +/* 8.2.13 Cause */ +enum osmo_cbsp_cause { + OSMO_CBSP_CAUSE_PARAM_NOT_RECOGNISED = 0, + OSMO_CBSP_CAUSE_PARAM_VALUE_INVALID, + OSMO_CBSP_CAUSE_MSG_REF_NOT_IDENTIFIED, + OSMO_CBSP_CAUSE_CELL_ID_NOT_VALID, + OSMO_CBSP_CAUSE_UNRECOGNISED_MESSAGE, + OSMO_CBSP_CAUSE_MISSING_MANDATORY_ELEMENT, + OSMO_CBSP_CAUSE_BSC_CAPACITY_EXCEEDED, + OSMO_CBSP_CAUSE_CELL_MEMORY_EXCEEDED, + OSMO_CBSP_CAUSE_BSC_MEMORY_EXCEEDED, + OSMO_CBSP_CAUSE_CELL_BROADCAST_NOT_SUPPORTED, + OSMO_CBSP_CAUSE_CELL_BROADCAST_NOT_OPERATIONAL, + OSMO_CBSP_CAUSE_INCOMPATIBLE_DRX_PARAM, + OSMO_CBSP_CAUSE_EXT_CHAN_NOT_SUPPORTED, + OSMO_CBSP_CAUSE_MSG_REF_ALREADY_USED, + OSMO_CBSP_CAUSE_UNSPECIFIED_ERROR, + OSMO_CBSP_CAUSE_LAI_OR_LAC_NOT_VALID, +}; +extern const struct value_string osmo_cbsp_cause_names[]; +static inline const char *osmo_cbsp_cause_name(enum osmo_cbsp_cause cause) +{ + return get_value_string(osmo_cbsp_cause_names, cause); +} /* decoded CBSP message */ struct osmo_cbsp_decoded { @@ -283,7 +303,7 @@ struct osmo_cbsp_decoded { } u; }; -extern const __thread char *osmo_cbsp_errstr; +extern __thread const char *osmo_cbsp_errstr; struct msgb *osmo_cbsp_msgb_alloc(void *ctx, const char *name); struct msgb *osmo_cbsp_encode(void *ctx, const struct osmo_cbsp_decoded *in); @@ -292,3 +312,4 @@ void osmo_cbsp_init_struct(struct osmo_cbsp_decoded *cbsp, enum cbsp_msg_type ms struct osmo_cbsp_decoded *osmo_cbsp_decoded_alloc(void *ctx, enum cbsp_msg_type msg_type); int osmo_cbsp_recv_buffered(void *ctx, int fd, struct msgb **rmsg, struct msgb **tmp_msg); +int osmo_cbsp_segmentation_cb(struct msgb *msg); diff --git a/include/osmocom/gsm/gad.h b/include/osmocom/gsm/gad.h new file mode 100644 index 00000000..57d0e37a --- /dev/null +++ b/include/osmocom/gsm/gad.h @@ -0,0 +1,190 @@ +/*! \addtogroup gad + * @{ + * \file gad.h + * Message encoding and decoding for 3GPP TS 23.032 GAD: Universal Geographical Area Description. + */ +/* + * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * + * All Rights Reserved + * + * Author: Neels Hofmeyr <neels@hofmeyr.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#pragma once + +#include <osmocom/gsm/protocol/gsm_23_032.h> +#include <osmocom/core/utils.h> + +struct msgb; + +struct osmo_gad_ell_point { + /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */ + int32_t lat; + /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */ + int32_t lon; +}; + +struct osmo_gad_ell_point_unc_circle { + /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */ + int32_t lat; + /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */ + int32_t lon; + /*! Uncertainty circle radius in millimeters (m * 1e3), 0 .. 18'000'000. */ + uint32_t unc; +}; + +struct osmo_gad_ell_point_unc_ellipse { + /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */ + int32_t lat; + /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */ + int32_t lon; + /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 18'000'000. + * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */ + uint32_t unc_semi_major; + /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 18'000'000. + * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */ + uint32_t unc_semi_minor; + /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */ + uint8_t major_ori; + /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */ + uint8_t confidence; +}; + +struct osmo_gad_polygon { + uint8_t num_points; + struct osmo_gad_ell_point point[15]; +}; + +struct osmo_gad_ell_point_alt { + /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */ + int32_t lat; + /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */ + int32_t lon; + /*! Altitude in meters, -32767 (depth) .. 32767 (height) */ + int16_t alt; +}; + +struct osmo_gad_ell_point_alt_unc_ell { + /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */ + int32_t lat; + /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */ + int32_t lon; + /*! Altitude in meters, -32767 (depth) .. 32767 (height) */ + int16_t alt; + /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 18'000'000. + * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */ + uint32_t unc_semi_major; + /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 18'000'000. + * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */ + uint32_t unc_semi_minor; + /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */ + uint8_t major_ori; + /*! Uncertainty altitude in millimeters, 0 .. 990'000. + * Coding of uncertainty altitude is non-linear, and distinct from the non-altitude uncertainty coding. Use + * osmo_gad_dec_unc_alt(osmo_gad_enc_unc_alt(val)) to clamp. */ + int32_t unc_alt; + /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */ + uint8_t confidence; +}; + +struct osmo_gad_ell_arc { + /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */ + int32_t lat; + /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */ + int32_t lon; + /*! inner circle radius in mm (m * 1e3) */ + uint32_t inner_r; + /*! Uncertainty circle radius in millimeters, 0 .. 18'000'000. + * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */ + uint32_t unc_r; + /*! Offset angle of first arc edge in degrees from North clockwise (eastwards), 0..359. + * Angle is coded in increments of 2 degrees. */ + uint16_t ofs_angle; + /*! Included angle defining the angular width of the arc, in degrees clockwise, 1..360. + * Angle is coded in increments of 2 degrees. */ + uint16_t incl_angle; + /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */ + uint8_t confidence; +}; + +struct osmo_gad_ha_ell_point_alt_unc_ell { + /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */ + int32_t lat; + /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */ + int32_t lon; + /*! Altitude in millimeters, -500'000 (depth) .. 10'000'000 (height) */ + int32_t alt; + /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 46'491. + * Coding of high-accuracy uncertainty is non-linear, use osmo_gad_dec_ha_unc(osmo_gad_enc_ha_unc(val)) to + * clamp. */ + uint32_t unc_semi_major; + /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 46'491. + * Coding of high-accuracy uncertainty is non-linear, use osmo_gad_dec_ha_unc(osmo_gad_enc_ha_unc(val)) to + * clamp. */ + uint32_t unc_semi_minor; + /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */ + uint8_t major_ori; + /*! Horizontal confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */ + uint8_t h_confidence; + /*! High-Accuracy uncertainty altitude */ + int32_t unc_alt; + /*! Vertical confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */ + uint8_t v_confidence; +}; + +struct osmo_gad { + enum gad_type type; + union { + struct osmo_gad_ell_point ell_point; + struct osmo_gad_ell_point_unc_circle ell_point_unc_circle; + struct osmo_gad_ell_point_unc_ellipse ell_point_unc_ellipse; + struct osmo_gad_polygon polygon; + struct osmo_gad_ell_point_alt ell_point_alt; + struct osmo_gad_ell_point_alt_unc_ell ell_point_alt_unc_ell; + struct osmo_gad_ell_arc ell_arc; + struct osmo_gad_ell_point_unc_ellipse ha_ell_point_unc_ellipse; + struct osmo_gad_ha_ell_point_alt_unc_ell ha_ell_point_alt_unc_ell; + }; +}; + +struct osmo_gad_err { + int rc; + enum gad_type type; + char *logmsg; +}; + +extern const struct value_string osmo_gad_type_names[]; +static inline const char *osmo_gad_type_name(enum gad_type val) +{ return get_value_string(osmo_gad_type_names, val); } + +int osmo_gad_raw_write(struct msgb *msg, const union gad_raw *gad_raw); +int osmo_gad_raw_read(union gad_raw *gad_raw, struct osmo_gad_err **err, void *err_ctx, const uint8_t *data, uint8_t len); + +int osmo_gad_enc(union gad_raw *gad_raw, const struct osmo_gad *gad); +int osmo_gad_dec(struct osmo_gad *gad, struct osmo_gad_err **err, void *err_ctx, const union gad_raw *gad_raw); + +int osmo_gad_to_str_buf(char *buf, size_t buflen, const struct osmo_gad *gad); +char *osmo_gad_to_str_c(void *ctx, const struct osmo_gad *gad); + +uint32_t osmo_gad_enc_lat(int32_t deg_1e6); +int32_t osmo_gad_dec_lat(uint32_t lat); +uint32_t osmo_gad_enc_lon(int32_t deg_1e6); +int32_t osmo_gad_dec_lon(uint32_t lon); +uint8_t osmo_gad_enc_unc(uint32_t mm); +uint32_t osmo_gad_dec_unc(uint8_t unc); +/*! @} */ diff --git a/include/osmocom/gsm/gsm0502.h b/include/osmocom/gsm/gsm0502.h index 1be2cc39..0ac13873 100644 --- a/include/osmocom/gsm/gsm0502.h +++ b/include/osmocom/gsm/gsm0502.h @@ -1,4 +1,7 @@ -/*! \file gsm0502.h */ +/*! \defgroup gsm0502 GSM 05.02 / 3GPP TS 45.002 + * @{ + * \file gsm0502.h + */ #pragma once @@ -16,10 +19,10 @@ /*! Return the sum of two specified TDMA frame numbers (summation) */ #define GSM_TDMA_FN_SUM(a, b) \ - ((a + b) % GSM_TDMA_HYPERFRAME) + (((a) + (b)) % GSM_TDMA_HYPERFRAME) /*! Return the difference of two specified TDMA frame numbers (subtraction) */ #define GSM_TDMA_FN_SUB(a, b) \ - ((a + GSM_TDMA_HYPERFRAME - b) % GSM_TDMA_HYPERFRAME) + (((a) + GSM_TDMA_HYPERFRAME - (b)) % GSM_TDMA_HYPERFRAME) /*! Return the *minimum* difference of two specified TDMA frame numbers (distance) */ #define GSM_TDMA_FN_DIFF(a, b) \ OSMO_MIN(GSM_TDMA_FN_SUB(a, b), GSM_TDMA_FN_SUB(b, a)) @@ -31,9 +34,58 @@ #define GSM_TDMA_FN_DEC(fn) \ ((fn) = GSM_TDMA_FN_SUB((fn), 1)) +/* 5.2.3.1 Normal burst for GMSK (1 bit per symbol) */ +#define GSM_NBITS_NB_GMSK_TAIL 3 +#define GSM_NBITS_NB_GMSK_PAYLOAD (2 * 58) +#define GSM_NBITS_NB_GMSK_TRAIN_SEQ 26 +#define GSM_NBITS_NB_GMSK_BURST 148 /* without guard period */ + +/* 5.2.3.3 Normal burst for 8-PSK (3 bits per symbol) */ +#define GSM_NBITS_NB_8PSK_TAIL (GSM_NBITS_NB_GMSK_TAIL * 3) +#define GSM_NBITS_NB_8PSK_PAYLOAD (GSM_NBITS_NB_GMSK_PAYLOAD * 3) +#define GSM_NBITS_NB_8PSK_TRAIN_SEQ (GSM_NBITS_NB_GMSK_TRAIN_SEQ * 3) +#define GSM_NBITS_NB_8PSK_BURST (GSM_NBITS_NB_GMSK_BURST * 3) + +/* 5.2.5 Synchronization burst (also GMSK) */ +#define GSM_NBITS_SB_GMSK_TAIL GSM_NBITS_NB_GMSK_TAIL +#define GSM_NBITS_SB_GMSK_PAYLOAD (2 * 39) +#define GSM_NBITS_SB_GMSK_ETRAIN_SEQ 64 +#define GSM_NBITS_SB_GMSK_BURST GSM_NBITS_NB_GMSK_BURST + +/* 5.2.6 Dummy burst (also GMSK) */ +#define GSM_NBITS_DB_GMSK_TAIL GSM_NBITS_NB_GMSK_TAIL +#define GSM_NBITS_DB_GMSK_MIXED 142 +#define GSM_NBITS_DB_GMSK_BURST GSM_NBITS_NB_GMSK_BURST + +/* 5.2.7 Access burst (also GMSK) */ +#define GSM_NBITS_AB_GMSK_ETAIL 8 +#define GSM_NBITS_AB_GMSK_SYNCH_SEQ 41 +#define GSM_NBITS_AB_GMSK_PAYLOAD 36 +#define GSM_NBITS_AB_GMSK_TAIL GSM_NBITS_NB_GMSK_TAIL +#define GSM_NBITS_AB_GMSK_BURST GSM_NBITS_NB_GMSK_BURST + +/*! Compare the given TDMA FNs, taking the wrapping into account. + * \param[in] fn1 First TDMA Fn value to compare. + * \param[in] fn2 Second TDMA Fn value to compare. + * \returns similarly to memcmp(), -1 if fn1 goes before fn2; + * 0 if fn1 equals fn2; + * 1 if fn1 goes after fn2. */ +static inline int gsm0502_fncmp(uint32_t fn1, uint32_t fn2) +{ + const uint32_t thresh = GSM_TDMA_HYPERFRAME / 2; + + if (fn1 == fn2) + return 0; + if ((fn1 < fn2 && (fn2 - fn1) < thresh) || + (fn1 > fn2 && (fn1 - fn2) > thresh)) + return -1; + + return 1; +} + /* Table 5 Clause 7 TS 05.02 */ static inline unsigned int -gsm0502_get_n_pag_blocks(struct gsm48_control_channel_descr *chan_desc) +gsm0502_get_n_pag_blocks(const struct gsm48_control_channel_descr *chan_desc) { if (chan_desc->ccch_conf == RSL_BCCH_CCCH_CONF_1_C) return 3 - chan_desc->bs_ag_blks_res; @@ -58,7 +110,7 @@ gsm0502_get_paging_group(uint64_t imsi, unsigned int bs_cc_chans, } unsigned int -gsm0502_calc_paging_group(struct gsm48_control_channel_descr *chan_desc, uint64_t imsi); +gsm0502_calc_paging_group(const struct gsm48_control_channel_descr *chan_desc, uint64_t imsi); enum gsm0502_fn_remap_channel { FN_REMAP_TCH_F, @@ -75,3 +127,7 @@ uint32_t gsm0502_fn_remap(uint32_t fn, enum gsm0502_fn_remap_channel channel); uint16_t gsm0502_hop_seq_gen(const struct gsm_time *t, uint8_t hsn, uint8_t maio, size_t n, const uint16_t *ma); + +int gsm0502_fn2ccch_block(uint32_t fn); + +/*! @} */ diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h index 2a26fb5d..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,13 +50,35 @@ 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(uint8_t link_id); +struct msgb *gsm0808_create_sapi_reject_cause(uint8_t link_id, uint16_t cause); +struct msgb *gsm0808_create_sapi_reject(uint8_t link_id) + OSMO_DEPRECATED("Use gsm0808_create_sapi_reject_cause() instead"); struct msgb *gsm0808_create_ass(const struct gsm0808_channel_type *ct, const uint16_t *cic, const struct sockaddr_storage *ss, @@ -124,6 +142,9 @@ struct gsm0808_old_bss_to_new_bss_info { uint8_t field; } current_channel_type_2; + bool last_eutran_plmn_id_present; + struct osmo_plmn_id last_eutran_plmn_id; + /* more items are defined in the spec and may be added later */ bool more_items; /*< always set this to false */ }; @@ -193,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); @@ -220,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); @@ -239,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; @@ -253,7 +283,7 @@ struct gsm0808_handover_complete { bool chosen_encr_alg_present; uint8_t chosen_encr_alg; - + bool chosen_channel_present; uint8_t chosen_channel; @@ -302,10 +332,248 @@ struct gsm0808_handover_performed { }; struct msgb *gsm0808_create_handover_performed(const struct gsm0808_handover_performed *params); +/*! 3GPP TS 48.008 §3.2.1.50 VGCS/VBS SETUP */ +struct gsm0808_vgcs_vbs_setup { + struct gsm0808_group_callref callref; + + bool priority_present; + struct gsm0808_priority priority; + + bool vgcs_feature_flags_present; + struct gsm0808_vgcs_feature_flags flags; +}; +struct msgb *gsm0808_create_vgcs_vbs_setup(const struct gsm0808_vgcs_vbs_setup *params); + +/*! 3GPP TS 48.008 §3.2.1.51 VGCS/VBS SETUP ACK */ +struct gsm0808_vgcs_vbs_setup_ack { + bool vgcs_feature_flags_present; + struct gsm0808_vgcs_feature_flags flags; +}; +struct msgb *gsm0808_create_vgcs_vbs_setup_ack(const struct gsm0808_vgcs_vbs_setup_ack *params); + +/*! 3GPP TS 48.008 §3.2.1.52 VGCS/VBS SETUP REFUSE */ +struct msgb *gsm0808_create_vgcs_vbs_setup_refuse(enum gsm0808_cause cause); + +/*! 3GPP TS 48.008 §3.2.1.53 VGCS/VBS ASSIGNMENT REQUEST */ +struct gsm0808_vgcs_vbs_assign_req { + struct gsm0808_channel_type channel_type; + enum gsm0808_assignment_requirement ass_req; + struct gsm0808_cell_id cell_identifier; + struct gsm0808_group_callref callref; + + bool priority_present; + struct gsm0808_priority priority; + + bool cic_present; + uint16_t cic; + + bool downlink_dtx_flag_present; + enum gsm0808_downlink_dtx_flag downlink_dtx_flag; + + bool encryption_information_present; + struct gsm0808_encrypt_info encryption_information; + + bool vstk_rand_present; + uint8_t vstk_rand[5]; + + bool vstk_present; + uint8_t vstk[16]; + + bool cils_present; + struct gsm0808_cell_id_list_segment cils; + + bool aoip_transport_layer_present; + struct sockaddr_storage aoip_transport_layer; + + bool call_id_present; + uint32_t call_id; + + bool codec_list_present; + struct gsm0808_speech_codec_list codec_list_msc_preferred; +}; +struct msgb *gsm0808_create_vgcs_vbs_assign_req(const struct gsm0808_vgcs_vbs_assign_req *params); + +/*! 3GPP TS 48.008 §3.2.1.54 VGCS/VBS ASSIGNMENT RESULT */ +struct gsm0808_vgcs_vbs_assign_res { + struct gsm0808_channel_type channel_type; + struct gsm0808_cell_id cell_identifier; + + bool chosen_channel_present; + uint8_t chosen_channel; + + bool cic_present; + uint16_t cic; + + bool circuit_pool_present; + uint8_t circuit_pool; + + bool aoip_transport_layer_present; + struct sockaddr_storage aoip_transport_layer; + + bool codec_present; + struct gsm0808_speech_codec codec_msc_chosen; + + bool call_id_present; + uint32_t call_id; +}; +struct msgb *gsm0808_create_vgcs_vbs_assign_res(const struct gsm0808_vgcs_vbs_assign_res *params); + +/*! 3GPP TS 48.008 §3.2.1.55 VGCS/VBS ASSIGNMENT FAILURE */ +struct gsm0808_vgcs_vbs_assign_fail { + enum gsm0808_cause cause; + + bool circuit_pool_present; + uint8_t circuit_pool; + + bool cpl_present; + struct gsm0808_circuit_pool_list cpl; + + bool codec_list_present; + struct gsm0808_speech_codec_list codec_list_bss_supported; +}; +struct msgb *gsm0808_create_vgcs_vbs_assign_fail(const struct gsm0808_vgcs_vbs_assign_fail *params); + +/*! 3GPP TS 48.008 §3.2.1.57 (VGCS) UPLINK REQUEST */ +struct gsm0808_uplink_request { + bool talker_priority_present; + enum gsm0808_talker_priority talker_priority; + + bool cell_identifier_present; + struct gsm0808_cell_id cell_identifier; + + bool l3_present; + struct gsm0808_layer_3_information l3; + + bool mi_present; + struct osmo_mobile_identity mi; +}; +struct msgb *gsm0808_create_uplink_request(const struct gsm0808_uplink_request *params); + +/*! 3GPP TS 48.008 §3.2.1.58 (VGCS) UPLINK REQUEST ACKNOWLEDGE */ +struct gsm0808_uplink_request_ack { + bool talker_priority_present; + enum gsm0808_talker_priority talker_priority; + + bool emerg_set_ind_present; + + bool talker_identity_present; + struct gsm0808_talker_identity talker_identity; +}; +struct msgb *gsm0808_create_uplink_request_ack(const struct gsm0808_uplink_request_ack *params); + +/*! 3GPP TS 48.008 §3.2.1.59 (VGCS) UPLINK REQUEST CONFIRM */ +struct gsm0808_uplink_request_cnf { + struct gsm0808_cell_id cell_identifier; + + bool talker_identity_present; + struct gsm0808_talker_identity talker_identity; + + /* mandatory! */ + struct gsm0808_layer_3_information l3; +}; +struct msgb *gsm0808_create_uplink_request_cnf(const struct gsm0808_uplink_request_cnf *params); + +/*! 3GPP TS 48.008 §3.2.1.59a (VGCS) UPLINK APPLICATION DATA */ +struct gsm0808_uplink_app_data { + struct gsm0808_cell_id cell_identifier; + struct gsm0808_layer_3_information l3; + bool bt_ind; +}; +struct msgb *gsm0808_create_uplink_app_data(const struct gsm0808_uplink_app_data *params); + +/*! 3GPP TS 48.008 §3.2.1.60 (VGCS) UPLINK RELEASE INDICATION */ +struct gsm0808_uplink_release_ind { + enum gsm0808_cause cause; + + bool talker_priority_present; + enum gsm0808_talker_priority talker_priority; +}; +struct msgb *gsm0808_create_uplink_release_ind(const struct gsm0808_uplink_release_ind *params); + +/*! 3GPP TS 48.008 §3.2.1.61 (VGCS) UPLINK REJECT COMMAND */ +struct gsm0808_uplink_reject_cmd { + enum gsm0808_cause cause; + + bool current_talker_priority_present; + enum gsm0808_talker_priority current_talker_priority; + bool rejected_talker_priority_present; + enum gsm0808_talker_priority rejected_talker_priority; + + bool talker_identity_present; + struct gsm0808_talker_identity talker_identity; +}; +struct msgb *gsm0808_create_uplink_reject_cmd(const struct gsm0808_uplink_reject_cmd *params); + +/*! 3GPP TS 48.008 §3.2.1.62 (VGCS) UPLINK RELEASE COMMAND */ +struct msgb *gsm0808_create_uplink_release_cmd(const enum gsm0808_cause cause); + +/*! 3GPP TS 48.008 §3.2.1.63 (VGCS) UPLINK SEIZED COMMAND */ +struct gsm0808_uplink_seized_cmd { + enum gsm0808_cause cause; + + bool talker_priority_present; + enum gsm0808_talker_priority talker_priority; + + bool emerg_set_ind_present; + + bool talker_identity_present; + struct gsm0808_talker_identity talker_identity; +}; +struct msgb *gsm0808_create_uplink_seized_cmd(const struct gsm0808_uplink_seized_cmd *params); + +/*! 3GPP TS 48.008 §3.2.1.78 VGCS ADDITIONAL INFORMATION */ +struct msgb *gsm0808_create_vgcs_additional_info(const struct gsm0808_talker_identity *ti); + +/*! 3GPP TS 48.008 §3.2.1.79 VGCS/VBS AREA CELL INFO */ +struct gsm0808_vgcs_vbs_area_cell_info { + struct gsm0808_cell_id_list_segment cils; + + bool ass_req_present; + enum gsm0808_assignment_requirement ass_req; +}; +struct msgb *gsm0808_create_vgcs_vbs_area_cell_info(const struct gsm0808_vgcs_vbs_area_cell_info *params); + +/*! 3GPP TS 48.008 §3.2.1.80 VGCS/VBS ASSIGNMENT STATUS */ +struct gsm0808_vgcs_vbs_assign_stat { + /* established cells */ + bool cils_est_present; + struct gsm0808_cell_id_list_segment cils_est; + + /* cells to be established */ + bool cils_tbe_present; + struct gsm0808_cell_id_list_segment cils_tbe; + + /* released cells - no user present */ + bool cils_rel_present; + struct gsm0808_cell_id_list_segment cils_rel; + + /* not established cells - no establishment possible */ + bool cils_ne_present; + struct gsm0808_cell_id_list_segment cils_ne; + + bool cell_status_present; + enum gsm0808_vgcs_vbs_cell_status cell_status; +}; +struct msgb *gsm0808_create_vgcs_vbs_assign_stat(const struct gsm0808_vgcs_vbs_assign_stat *params); + +/*! 3GPP TS 48.008 §3.2.1.81 VGCS SMS */ +struct msgb *gsm0808_create_vgcs_sms(const struct gsm0808_sms_to_vgcs *sms); + +/*! 3GPP TS 48.008 §3.2.1.82 (VGCS/VBS) NOTIFICATION DATA */ +struct gsm0808_notification_data { + struct gsm0808_application_data app_data; + struct gsm0808_data_identity data_ident; + + bool msisdn_present; + char msisdn[MSISDN_MAXLEN + 1]; +}; +struct msgb *gsm0808_create_notification_data(const struct gsm0808_notification_data *parms); + struct msgb *gsm0808_create_dtap(struct msgb *msg, uint8_t link_id); void gsm0808_prepend_dtap_header(struct msgb *msg, uint8_t link_id); const struct tlv_definition *gsm0808_att_tlvdef(void); +extern const struct tlv_definition gsm0808_old_bss_to_new_bss_info_att_tlvdef; /*! Parse BSSAP TLV structure using \ref tlv_parse */ #define osmo_bssap_tlv_parse(dec, buf, len) tlv_parse(dec, gsm0808_att_tlvdef(), buf, len, 0, 0) diff --git a/include/osmocom/gsm/gsm0808_lcs.h b/include/osmocom/gsm/gsm0808_lcs.h new file mode 100644 index 00000000..71665013 --- /dev/null +++ b/include/osmocom/gsm/gsm0808_lcs.h @@ -0,0 +1,48 @@ +/*! \addtogroup gsm0808 + * @{ + * \file gsm0808_lcs.h + * + * Declarations that depend on both gsm0808.h and bssmap_le.h: LCS related message coding. + * (This file prevents circular dependency between struct definitions for BSSMAP messages, since BSSMAP references + * struct lcs_cause and struct bssmap_le_location_type, and BSSMAP-LE references gsm0808_cause. + */ +/* + * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#pragma once + +#include <osmocom/gsm/gsm0808.h> +#include <osmocom/gsm/bssmap_le.h> + +struct gsm0808_perform_location_request { + struct bssmap_le_location_type location_type; + struct osmo_mobile_identity imsi; + + bool more_items; /*!< always set this to false */ +}; +struct msgb *gsm0808_create_perform_location_request(const struct gsm0808_perform_location_request *params); + +struct gsm0808_perform_location_response { + bool location_estimate_present; + union gad_raw location_estimate; + + struct lcs_cause_ie lcs_cause; +}; +struct msgb *gsm0808_create_perform_location_response(const struct gsm0808_perform_location_response *params); + +int gsm0808_enc_lcs_cause(struct msgb *msg, const struct lcs_cause_ie *lcs_cause); +struct msgb *gsm0808_create_perform_location_abort(const struct lcs_cause_ie *lcs_cause); + +/*! @} */ diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index 59db6edc..dbe2abf9 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -31,6 +31,8 @@ struct sockaddr_storage; #include <osmocom/gsm/gsm23003.h> #include <osmocom/gsm/gsm_utils.h> #include <osmocom/gsm/tlv.h> +#include <osmocom/gsm/gsm48.h> +#include <osmocom/core/endian.h> /*! (225-1)/2 is the maximum number of elements in a cell identifier list. */ #define GSM0808_CELL_ID_LIST2_MAXLEN 127 @@ -44,6 +46,9 @@ union gsm0808_cell_id_u { uint16_t ci; struct osmo_location_area_id lai_and_lac; uint16_t lac; + struct osmo_service_area_id sai; + /* osmocom specific: */ + struct osmo_cell_global_id_ps global_ps; }; /*! Parsed representation of Cell Identifier IE (3GPP TS 48.008 3.2.2.17) */ @@ -59,6 +64,164 @@ struct gsm0808_cell_id_list2 { unsigned int id_list_len; }; +/*! Packed representation of a Priority IE (GGPP TS 48.008 3.2.2.18) */ +struct gsm0808_priority { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t pvi:1, /* Preemption Vulnerability indicator */ + qa:1, /* Queuing allowed indicator */ + priority_level:4, /* Priority level: 1 == hightest, 14 == lowest */ + pci:1, /* Preemption Capability indicator */ + spare:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t spare:1, pci:1, priority_level:4, qa:1, pvi:1; +#endif +} __attribute__ ((packed)); + +/*! Packed representation of a VGCS Feature Flags IE (3GPP TS 48.008 3.2.2.88) */ +struct gsm0808_vgcs_feature_flags { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t tp_ind:1, /* Talker priority supported */ + as_ind_circuit:1, /* A-interface circuit sharing supported */ + as_ind_link:1, /* A-interface link sharing supported */ + bss_res:1, /* BSS supports re-establishment */ + tcp:1, /* Talker channel parameter supported */ + spare:3; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t spare:3, tcp:1, bss_res:1, as_ind_link:1, as_ind_circuit:1, tp_ind:1; +#endif +} __attribute__ ((packed)); + +/* TS 48.008 3.2.2.52 */ +enum gsm0808_assignment_requirement { + GSM0808_ASRQ_DELAY_ALLOWED = 0x00, + GSM0808_ASRQ_IMMEDIATE = 0x01, + GSM0808_ASRQ_IMMEDIATE_ON_DEMAND = 0x02, +}; + +/* TS 48.008 Table 10.5.8 */ +enum gsm0808_service_flag { + GSM0808_SF_VBS = 0, + GSM0808_SF_VGCS = 1, +}; + +enum gsm0808_call_priority { + GSM0808_CALL_PRIORITY_NONE = 0x00, + GSM0808_CALL_PRIORITY_LEVEL_4 = 0x01, + GSM0808_CALL_PRIORITY_LEVEL_3 = 0x02, + GSM0808_CALL_PRIORITY_LEVEL_2 = 0x03, + GSM0808_CALL_PRIORITY_LEVEL_1 = 0x04, + GSM0808_CALL_PRIORITY_LEVEL_0 = 0x05, + GSM0808_CALL_PRIORITY_LEVEL_B = 0x06, + GSM0808_CALL_PRIORITY_LEVEL_A = 0x07, +}; + +/*! Packed representation of a Group Call Reference IE (3GPP TS 48.008 3.2.2.55) */ +struct gsm0808_group_callref { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t call_ref_hi[3]; + uint8_t call_priority:3, + af:1, /* Acknowledgement flag */ + sf:1, /* Service flag */ + call_ref_lo:3; + uint8_t spare:4, + ciphering_info:4; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t call_ref_hi[3]; + uint8_t call_ref_lo:3, sf:1, af:1, call_priority:3; + uint8_t ciphering_info:4, spare:4; +#endif +} __attribute__ ((packed)); + +/* TS 48.008 3.2.2.26 */ +enum gsm0808_downlink_dtx_flag { + GSM0808_DTX_FLAG_ALLOW = 0, + GSM0808_DTX_FLAG_FORBID = 1, +}; + +/*! Parsed representation of a Cell Identifier List Segment IE (3GPP TS 48.008 3.2.2.27a) */ +struct gsm0808_cell_id_list_segment { + uint8_t seq_last; + uint8_t seq_number; + struct gsm0808_cell_id_list2 cil; +}; + +/*! Parsed representation of a Circuit Pool List IE (3GPP TS 48.008 3.2.2.26) */ +#define CIRCUIT_POOL_LIST_MAXLEN 252 +struct gsm0808_circuit_pool_list { + uint8_t pool[CIRCUIT_POOL_LIST_MAXLEN]; + unsigned int list_len; +}; + +/* 3GPP TS 48.008 Table 3.2.2.90.1 Talker Priority */ +enum gsm0808_talker_priority { + GSM0808_TALKER_PRIORITY_NORMAL = 0x00, + GSM0808_TALKER_PRIORITY_PRIVILEGED = 0x01, + GSM0808_TALKER_PRIORITY_EMERGENCY = 0x02, +}; + +/*! Parsed representation of a Layer 3 Information IE (3GPP TS 48.008 3.2.2.24) */ +#define LAYER_3_INFORMATION_MAXLEN 252 +struct gsm0808_layer_3_information { + uint8_t l3[LAYER_3_INFORMATION_MAXLEN]; + unsigned int l3_len; +}; + +/*! Parsed representation of a Talker Identity IE (3GPP TS 48.008 3.2.2.91) */ +#define TALKER_IDENTITY_MAXLEN 17 +struct gsm0808_talker_identity { + uint8_t talker_id[TALKER_IDENTITY_MAXLEN]; + unsigned int id_bits; +}; + +/* 3GPP TS 48.008 3.2.2.94 VGCS/VBS Cell Status */ +enum gsm0808_vgcs_vbs_cell_status { + GSM0808_CSTAT_ESTABLISHED = 0x00, + GSM0808_CSTAT_NOT_ESTABLISHED1 = 0x01, + GSM0808_CSTAT_RELEASED_NO_USER = 0x02, + GSM0808_CSTAT_NOT_ESTABLISHED2 = 0x03, +}; + +/*! Parsed representation of a SMS to VGCS IE (3GPP TS 48.008 3.2.2.92) */ +#define SMS_TO_VGCS_MAXLEN 252 +struct gsm0808_sms_to_vgcs { + uint8_t sms[SMS_TO_VGCS_MAXLEN]; + unsigned int sms_len; +}; + +/*! Parsed representation of a Application Data IE (3GPP TS 48.008 3.2.2.98) */ +#define APP_DATA_MAXLEN 9 +struct gsm0808_application_data { + uint8_t data[APP_DATA_MAXLEN]; + unsigned int data_len; +}; + +/*! Packed representation of a Data Identity IE (GGPP TS 48.008 3.2.2.99) */ +enum gsm0808_application_idndicator { + GSM0808_AI_APP_DATA = 0x00, + GSM0808_AI_CONFIRM_APP_DATA = 0x01, +}; + +#define GSM0808_DP_MASK_TALKERS_LISTENERS 0x04 +#define GSM0808_DP_MASK_DISPATCHERS 0x02 +#define GSM0808_DP_MASK_NETWORK_APP 0x01 + +struct gsm0808_data_identity { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t ai:1, /* Application Indicator */ + di:4, /* Data identifier */ + dp:3; /* Distribution parameter (bit mask) */ +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t dp:3, di:4, ai:1; +#endif +} __attribute__ ((packed)); + +/*! Parsed representation of a MSISDN IE (3GPP TS 48.008 3.2.2.101) */ +#define MSISDN_MAXLEN 20 + /*! LCLS-related parameters from 3GPP TS 48.008 */ struct osmo_lcls { enum gsm0808_lcls_config config; /**< §3.2.2.116 Configuration */ @@ -108,12 +271,17 @@ uint8_t gsm0808_enc_lcls(struct msgb *msg, const struct osmo_lcls *lcls); int gsm0808_dec_lcls(struct osmo_lcls *lcls, const struct tlv_parsed *tp); uint8_t gsm0808_enc_speech_codec(struct msgb *msg, - const struct gsm0808_speech_codec *sc); + const struct gsm0808_speech_codec *sc) + OSMO_DEPRECATED("use gsm0808_enc_speech_codec2() instead"); +int gsm0808_enc_speech_codec2(struct msgb *msg, + const struct gsm0808_speech_codec *sc); int gsm0808_dec_speech_codec(struct gsm0808_speech_codec *sc, const uint8_t *elem, uint8_t len); uint8_t gsm0808_enc_speech_codec_list(struct msgb *msg, - const struct gsm0808_speech_codec_list - *scl); + const struct gsm0808_speech_codec_list *scl) + OSMO_DEPRECATED("use gsm0808_enc_speech_codec_list2() instead"); +int gsm0808_enc_speech_codec_list2(struct msgb *msg, + const struct gsm0808_speech_codec_list *scl); int gsm0808_dec_speech_codec_list(struct gsm0808_speech_codec_list *scl, const uint8_t *elem, uint8_t len); uint8_t gsm0808_enc_channel_type(struct msgb *msg, @@ -124,6 +292,8 @@ uint8_t gsm0808_enc_encrypt_info(struct msgb *msg, const struct gsm0808_encrypt_info *ei); int gsm0808_dec_encrypt_info(struct gsm0808_encrypt_info *ei, const uint8_t *elem, uint8_t len); +int gsm0808_enc_kc128(struct msgb *msg, const uint8_t *kc128); +int gsm0808_dec_kc128(uint8_t *kc128, const uint8_t *elem, uint8_t len); uint8_t gsm0808_enc_cell_id_list2(struct msgb *msg, const struct gsm0808_cell_id_list2 *cil); uint8_t gsm0808_enc_cell_id_list(struct msgb *msg, const struct gsm0808_cell_id_list *cil) @@ -178,37 +348,34 @@ static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type) static inline enum gsm0808_permitted_speech gsm0808_permitted_speech(enum gsm_chan_t type, enum gsm48_chan_mode mode) { - switch (mode) { - case GSM48_CMODE_SPEECH_V1: - switch (type) { - case GSM_LCHAN_TCH_F: - return GSM0808_PERM_FR1; - case GSM_LCHAN_TCH_H: - return GSM0808_PERM_HR1; - default: - return 0; - } - case GSM48_CMODE_SPEECH_EFR: - switch (type) { - case GSM_LCHAN_TCH_F: - return GSM0808_PERM_FR2; - case GSM_LCHAN_TCH_H: - return GSM0808_PERM_HR2; - default: - return 0; - } - case GSM48_CMODE_SPEECH_AMR: - switch (type) { - case GSM_LCHAN_TCH_F: - return GSM0808_PERM_FR3; - case GSM_LCHAN_TCH_H: - return GSM0808_PERM_HR3; - default: - return 0; - } +#define MODE_TYPE(mode, type) ((mode << 16) | type) + + switch (MODE_TYPE(mode, type)) { + case MODE_TYPE(GSM48_CMODE_SPEECH_V1, GSM_LCHAN_TCH_F): + return GSM0808_PERM_FR1; + case MODE_TYPE(GSM48_CMODE_SPEECH_V1, GSM_LCHAN_TCH_H): + return GSM0808_PERM_HR1; + case MODE_TYPE(GSM48_CMODE_SPEECH_EFR, GSM_LCHAN_TCH_F): + return GSM0808_PERM_FR2; + case MODE_TYPE(GSM48_CMODE_SPEECH_EFR, GSM_LCHAN_TCH_H): + return GSM0808_PERM_HR2; /* (deprecated) */ + case MODE_TYPE(GSM48_CMODE_SPEECH_AMR, GSM_LCHAN_TCH_F): + return GSM0808_PERM_FR3; + case MODE_TYPE(GSM48_CMODE_SPEECH_AMR, GSM_LCHAN_TCH_H): + return GSM0808_PERM_HR3; + case MODE_TYPE(GSM48_CMODE_SPEECH_V4, GSM_LCHAN_TCH_F): + return GSM0808_PERM_FR4; + case MODE_TYPE(GSM48_CMODE_SPEECH_V4, GSM_LCHAN_TCH_H): + return GSM0808_PERM_HR4; + case MODE_TYPE(GSM48_CMODE_SPEECH_V5, GSM_LCHAN_TCH_F): + return GSM0808_PERM_FR5; /* FR only */ + case MODE_TYPE(GSM48_CMODE_SPEECH_V6, GSM_LCHAN_TCH_H): + return GSM0808_PERM_HR6; /* HR only */ default: return 0; } + +#undef MODE_TYPE } /*! Return 3GPP TS 48.008 3.2.2.33 Chosen Channel. */ @@ -220,6 +387,9 @@ static inline uint8_t gsm0808_chosen_channel(enum gsm_chan_t type, enum gsm48_ch case GSM48_CMODE_SPEECH_V1: case GSM48_CMODE_SPEECH_EFR: case GSM48_CMODE_SPEECH_AMR: + case GSM48_CMODE_SPEECH_V4: + case GSM48_CMODE_SPEECH_V5: + case GSM48_CMODE_SPEECH_V6: channel_mode = 0x9; break; case GSM48_CMODE_SIGN: @@ -237,6 +407,33 @@ static inline uint8_t gsm0808_chosen_channel(enum gsm_chan_t type, enum gsm48_ch case GSM48_CMODE_DATA_3k6: channel_mode = 0xd; break; + case GSM48_CMODE_DATA_29k0: + channel_mode = 0x1; + break; + case GSM48_CMODE_DATA_32k0: + channel_mode = 0x2; + break; + case GSM48_CMODE_DATA_43k5: + channel_mode = 0x3; + break; + case GSM48_CMODE_DATA_43k5_14k5: + channel_mode = 0x4; + break; + case GSM48_CMODE_DATA_29k0_14k5: + channel_mode = 0x5; + break; + case GSM48_CMODE_DATA_43k5_29k0: + channel_mode = 0x6; + break; + case GSM48_CMODE_DATA_14k5_43k5: + channel_mode = 0x7; + break; + case GSM48_CMODE_DATA_14k5_29k0: + channel_mode = 0xa; + break; + case GSM48_CMODE_DATA_29k0_43k5: + channel_mode = 0xf; + break; default: return 0; } @@ -254,6 +451,7 @@ static inline uint8_t gsm0808_chosen_channel(enum gsm_chan_t type, enum gsm48_ch case GSM_LCHAN_TCH_H: channel = 0x9; break; + /* TODO: more than 1 TCHs? */ default: return 0; } @@ -265,4 +463,23 @@ const char *gsm0808_channel_type_name(const struct gsm0808_channel_type *ct); char *gsm0808_channel_type_name_buf(char *buf, size_t buf_len, const struct gsm0808_channel_type *ct); char *gsm0808_channel_type_name_c(const void *ctx, const struct gsm0808_channel_type *ct); +uint8_t gsm0808_enc_group_callref(struct msgb *msg, const struct gsm0808_group_callref *gc); +int gsm0808_dec_group_callref(struct gsm0808_group_callref *gc, const uint8_t *elem, uint8_t len); +uint8_t gsm0808_enc_priority(struct msgb *msg, const struct gsm0808_priority *pri); +int gsm0808_dec_priority(struct gsm0808_priority *pri, const uint8_t *elem, uint8_t len); +uint8_t gsm0808_enc_vgcs_feature_flags(struct msgb *msg, const struct gsm0808_vgcs_feature_flags *ff); +int gsm0808_dec_vgcs_feature_flags(struct gsm0808_vgcs_feature_flags *ff, const uint8_t *elem, uint8_t len); +uint8_t gsm0808_enc_talker_identity(struct msgb *msg, const struct gsm0808_talker_identity *ti); +int gsm0808_dec_talker_identity(struct gsm0808_talker_identity *ti, const uint8_t *elem, uint8_t len); +uint8_t gsm0808_enc_data_identity(struct msgb *msg, const struct gsm0808_data_identity *ai); +int gsm0808_dec_data_identity(struct gsm0808_data_identity *ai, const uint8_t *elem, uint8_t len); +uint8_t gsm0808_enc_msisdn(struct msgb *msg, const char *msisdn); +int gsm0808_dec_msisdn(char *msisdn, const char *elem, uint8_t len); +uint8_t gsm0808_enc_assign_req(struct msgb *msg, const enum gsm0808_assignment_requirement ar); +int gsm0808_dec_assign_req(enum gsm0808_assignment_requirement *ar, const uint8_t *elem, uint8_t len); +uint8_t gsm0808_enc_cell_id_list_segment(struct msgb *msg, uint8_t ie_type, + const struct gsm0808_cell_id_list_segment *ci); +int gsm0808_dec_cell_id_list_segment(struct gsm0808_cell_id_list_segment *ci, const uint8_t *elem, uint8_t len); +int gsm0808_dec_call_id(uint32_t *ci, const uint8_t *elem, uint8_t len); + /*! @} */ diff --git a/include/osmocom/gsm/gsm23003.h b/include/osmocom/gsm/gsm23003.h index 69f00f68..4070581f 100644 --- a/include/osmocom/gsm/gsm23003.h +++ b/include/osmocom/gsm/gsm23003.h @@ -30,6 +30,14 @@ struct osmo_cell_global_id { uint16_t cell_identity; }; +/* 3GPP TS 48.018: + * 8c.1.4.1.1 GERAN BSS identification (RIM) + * sec 11.3.9 Cell Identifier */ +struct osmo_cell_global_id_ps { + struct osmo_routing_area_id rai; + uint16_t cell_identity; +}; + /*! Bitmask of items contained in a struct osmo_cell_global_id. * See also gsm0808_cell_id_to_cgi(). */ @@ -37,6 +45,7 @@ enum osmo_cgi_part { OSMO_CGI_PART_PLMN = 1, OSMO_CGI_PART_LAC = 2, OSMO_CGI_PART_CI = 4, + OSMO_CGI_PART_RAC = 8, }; /* Actually defined in 3GPP TS 48.008 3.2.2.27 Cell Identifier List, @@ -117,10 +126,21 @@ char *osmo_plmn_name_c(const void *ctx, const struct osmo_plmn_id *plmn); const char *osmo_lai_name(const struct osmo_location_area_id *lai); char *osmo_lai_name_buf(char *buf, size_t buf_len, const struct osmo_location_area_id *lai); char *osmo_lai_name_c(const void *ctx, const struct osmo_location_area_id *lai); +const char *osmo_rai_name2(const struct osmo_routing_area_id *rai); +char *osmo_rai_name2_buf(char *buf, size_t buf_len, const struct osmo_routing_area_id *rai); +char *osmo_rai_name2_c(const void *ctx, const struct osmo_routing_area_id *rai); const char *osmo_cgi_name(const struct osmo_cell_global_id *cgi); const char *osmo_cgi_name2(const struct osmo_cell_global_id *cgi); char *osmo_cgi_name_buf(char *buf, size_t buf_len, const struct osmo_cell_global_id *cgi); char *osmo_cgi_name_c(const void *ctx, const struct osmo_cell_global_id *cgi); +const char *osmo_cgi_ps_name(const struct osmo_cell_global_id_ps *cgi_ps); +const char *osmo_cgi_ps_name2(const struct osmo_cell_global_id_ps *cgi_ps); +char *osmo_cgi_ps_name_buf(char *buf, size_t buf_len, const struct osmo_cell_global_id_ps *cgi_ps); +char *osmo_cgi_ps_name_c(const void *ctx, const struct osmo_cell_global_id_ps *cgi_ps); +const char *osmo_sai_name(const struct osmo_service_area_id *sai); +const char *osmo_sai_name2(const struct osmo_service_area_id *sai); +char *osmo_sai_name_buf(char *buf, size_t buf_len, const struct osmo_service_area_id *sai); +char *osmo_sai_name_c(const void *ctx, const struct osmo_service_area_id *sai); const char *osmo_gummei_name(const struct osmo_gummei *gummei); char *osmo_gummei_name_buf(char *buf, size_t buf_len, const struct osmo_gummei *gummei); char *osmo_gummei_name_c(const void *ctx, const struct osmo_gummei *gummei); @@ -144,7 +164,9 @@ static inline int osmo_mcc_from_str(const char *mcc_str, uint16_t *mcc) int osmo_mnc_cmp(uint16_t a_mnc, bool a_mnc_3_digits, uint16_t b_mnc, bool b_mnc_3_digits); int osmo_plmn_cmp(const struct osmo_plmn_id *a, const struct osmo_plmn_id *b); int osmo_lai_cmp(const struct osmo_location_area_id *a, const struct osmo_location_area_id *b); +int osmo_rai_cmp(const struct osmo_routing_area_id *a, const struct osmo_routing_area_id *b); int osmo_cgi_cmp(const struct osmo_cell_global_id *a, const struct osmo_cell_global_id *b); +int osmo_cgi_ps_cmp(const struct osmo_cell_global_id_ps *a, const struct osmo_cell_global_id_ps *b); int osmo_gen_home_network_domain(char *out, const struct osmo_plmn_id *plmn); int osmo_parse_home_network_domain(struct osmo_plmn_id *out, const char *in); diff --git a/include/osmocom/gsm/gsm29118.h b/include/osmocom/gsm/gsm29118.h index e81cce4c..33c40d36 100644 --- a/include/osmocom/gsm/gsm29118.h +++ b/include/osmocom/gsm/gsm29118.h @@ -17,10 +17,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * */ #pragma once diff --git a/include/osmocom/gsm/gsm29205.h b/include/osmocom/gsm/gsm29205.h index 95754567..6c845fb9 100644 --- a/include/osmocom/gsm/gsm29205.h +++ b/include/osmocom/gsm/gsm29205.h @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * */ #pragma once @@ -37,6 +33,6 @@ struct osmo_gcr_parsed { uint8_t cr[5]; /** Call Reference ID */ }; -uint8_t osmo_enc_gcr(struct msgb *msg, const struct osmo_gcr_parsed *g) OSMO_DEPRECATED_OUTSIDE_LIBOSMOCORE; -int osmo_dec_gcr(struct osmo_gcr_parsed *gcr, const uint8_t *elem, uint8_t len) OSMO_DEPRECATED_OUTSIDE_LIBOSMOCORE; +uint8_t osmo_enc_gcr(struct msgb *msg, const struct osmo_gcr_parsed *g); +int osmo_dec_gcr(struct osmo_gcr_parsed *gcr, const uint8_t *elem, uint8_t len); bool osmo_gcr_eq(const struct osmo_gcr_parsed *gcr1, const struct osmo_gcr_parsed *gcr2); diff --git a/include/osmocom/gsm/gsm44021.h b/include/osmocom/gsm/gsm44021.h new file mode 100644 index 00000000..8f89c56b --- /dev/null +++ b/include/osmocom/gsm/gsm44021.h @@ -0,0 +1,8 @@ +#pragma once +#include <osmocom/isdn/v110.h> + +int osmo_csd_12k_6k_decode_frame(struct osmo_v110_decoded_frame *fr, const ubit_t *ra_bits, size_t n_bits); +int osmo_csd_12k_6k_encode_frame(ubit_t *ra_bits, size_t ra_bits_size, const struct osmo_v110_decoded_frame *fr); +int osmo_csd_3k6_decode_frame(struct osmo_v110_decoded_frame *fr, const ubit_t *ra_bits, size_t n_bits); +int osmo_csd_3k6_encode_frame(ubit_t *ra_bits, size_t ra_bits_size, const struct osmo_v110_decoded_frame *fr); +void osmo_csd_ubit_dump(FILE *outf, const ubit_t *fr, size_t in_len); diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h index f772f4a1..d36b85cb 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,10 +37,13 @@ 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); char *osmo_rai_name_c(const void *ctx, const struct gprs_ra_id *rai); +void osmo_rai_to_gprs(struct gprs_ra_id *dest, const struct osmo_routing_area_id *src); +void gprs_rai_to_osmo(struct osmo_routing_area_id *dest, const struct gprs_ra_id *src); int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc, uint16_t *mnc, uint16_t *lac) @@ -95,17 +100,23 @@ char *osmo_mobile_identity_to_str_c(void *ctx, const struct osmo_mobile_identity int osmo_mobile_identity_cmp(const struct osmo_mobile_identity *a, const struct osmo_mobile_identity *b); int osmo_mobile_identity_decode(struct osmo_mobile_identity *mi, const uint8_t *mi_data, uint8_t mi_len, bool allow_hex); +int osmo_mobile_identity_decode_from_l3_buf(struct osmo_mobile_identity *mi, const uint8_t *l3_data, size_t l3_len, + bool allow_hex); int osmo_mobile_identity_decode_from_l3(struct osmo_mobile_identity *mi, struct msgb *msg, bool allow_hex); int osmo_mobile_identity_encoded_len(const struct osmo_mobile_identity *mi, int *mi_digits); int osmo_mobile_identity_encode_buf(uint8_t *buf, size_t buflen, const struct osmo_mobile_identity *mi, bool allow_hex); int osmo_mobile_identity_encode_msgb(struct msgb *msg, const struct osmo_mobile_identity *mi, bool allow_hex); /* Parse Routeing Area Identifier */ +int osmo_routing_area_id_decode(struct osmo_routing_area_id *dst, const uint8_t *ra_data, size_t ra_data_len); +int osmo_routing_area_id_encode_buf(uint8_t *buf, size_t buflen, const struct osmo_routing_area_id *src); +int osmo_routing_area_id_encode_msgb(struct msgb *msg, const struct osmo_routing_area_id *src); void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf); void gsm48_encode_ra(struct gsm48_ra_id *out, const struct gprs_ra_id *raid); int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid) OSMO_DEPRECATED("Use gsm48_encode_ra() instead"); +bool gsm48_ra_equal(const struct gprs_ra_id *raid1, const struct gprs_ra_id *raid2); -int gsm48_number_of_paging_subchannels(struct gsm48_control_channel_descr *chan_desc); +int gsm48_number_of_paging_subchannels(const struct gsm48_control_channel_descr *chan_desc); void gsm48_mcc_mnc_to_bcd(uint8_t *bcd_dst, uint16_t mcc, uint16_t mnc) OSMO_DEPRECATED("Use osmo_plmn_to_bcd() instead, to not lose leading zeros in the MNC"); @@ -117,3 +128,6 @@ struct gsm48_hdr *gsm48_push_l3hdr(struct msgb *msg, #define gsm48_push_l3hdr_tid(msg, pdisc, tid, msg_type) \ gsm48_push_l3hdr(msg, (pdisc & 0x0f) | (tid << 4), msg_type) + +enum gsm48_chan_mode gsm48_chan_mode_to_vamos(enum gsm48_chan_mode mode); +enum gsm48_chan_mode gsm48_chan_mode_to_non_vamos(enum gsm48_chan_mode mode); diff --git a/include/osmocom/gsm/gsm48_ie.h b/include/osmocom/gsm/gsm48_ie.h index 339aa136..4768283f 100644 --- a/include/osmocom/gsm/gsm48_ie.h +++ b/include/osmocom/gsm/gsm48_ie.h @@ -117,5 +117,10 @@ struct gsm_sysinfo_freq { }; /* decode "Cell Channel Description" (10.5.2.1b) and other frequency lists */ -int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd, - uint8_t len, uint8_t mask, uint8_t frqt); +int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, + const uint8_t *cd, uint8_t len, + uint8_t mask, uint8_t frqt); + +/* decode "CSN.1 encoded Classmark 3" (10.5.1.7) */ +int gsm48_decode_classmark3(struct gsm48_classmark3 *classmark3_out, + const uint8_t *classmark3, size_t classmark3_len); diff --git a/include/osmocom/gsm/gsm48_rest_octets.h b/include/osmocom/gsm/gsm48_rest_octets.h index d3bb878e..cdb2e807 100644 --- a/include/osmocom/gsm/gsm48_rest_octets.h +++ b/include/osmocom/gsm/gsm48_rest_octets.h @@ -2,7 +2,7 @@ #include <stdbool.h> #include <osmocom/gsm/sysinfo.h> -#include <osmocom/gprs/protocol/gsm_04_60.h> +#include <osmocom/gsm/protocol/gsm_44_060.h> /* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018 Table 10.5.2.33b.1: 4-bit index is used (2#1111 = 10#15) */ @@ -13,6 +13,9 @@ /* generate SI1 rest octets */ int osmo_gsm48_rest_octets_si1_encode(uint8_t *data, uint8_t *nch_pos, int is1800_net); +int osmo_gsm48_si1ro_nch_pos_decode(uint8_t value, uint8_t *num_blocks, uint8_t *first_block); +int osmo_gsm48_si1ro_nch_pos_encode(uint8_t num_blocks, uint8_t first_block); + int osmo_gsm48_rest_octets_si2quater_encode(uint8_t *data, uint8_t si2q_index, uint8_t si2q_count, const uint16_t *uarfcn_list, size_t *u_offset, size_t uarfcn_length, uint16_t *scramble_list, @@ -120,8 +123,12 @@ struct osmo_gsm48_si13_info { uint8_t prio_acc_thr; }; -/* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */ +/* Parse/Generate SI13 Rest Octests (Chapter 10.5.2.37b) */ +int osmo_gsm48_rest_octets_si13_decode(struct osmo_gsm48_si13_info *si13, const uint8_t *data); int osmo_gsm48_rest_octets_si13_encode(uint8_t *data, const struct osmo_gsm48_si13_info *si13); /* Parse SI3 Rest Octets */ void osmo_gsm48_rest_octets_si3_decode(struct osmo_gsm48_si_ro_info *si3, const uint8_t *data); + +/* Parse SI4 Rest Octets */ +void osmo_gsm48_rest_octets_si4_decode(struct osmo_gsm48_si_ro_info *si4, const uint8_t *data, int len); diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h index de634348..b250c594 100644 --- a/include/osmocom/gsm/gsm_utils.h +++ b/include/osmocom/gsm/gsm_utils.h @@ -17,10 +17,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * */ #pragma once @@ -37,6 +33,7 @@ } while (0) #define GSM_MAX_FN (26*51*2048) +#define GSM_FN_UNSET 0xFFFFFFFF /* Max length of random identifier which can be requested via osmo_get_rand_id() */ #define OSMO_MAX_RAND_ID_LEN 16 @@ -110,7 +107,10 @@ int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets_w int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets_written); /* the four functions below are helper functions and here for the unit test */ -int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding); +int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding) + OSMO_DEPRECATED("This function is unable to handle more than 255 septets, " + "use gsm_septet_pack() instead."); +int gsm_septet_pack(uint8_t *result, const uint8_t *rdata, size_t septet_len, uint8_t padding); int gsm_septet_encode(uint8_t *result, const char *data); uint8_t gsm_get_octet_len(const uint8_t sept_len); int gsm_7bit_decode_n_hdr(char *decoded, size_t n, const uint8_t *user_data, uint8_t length, uint8_t ud_hdr_ind); @@ -153,6 +153,13 @@ static inline int rach_max_trans_raw2val(int raw) { const int tbl[4] = { 1, 2, 4, 7 }; return tbl[raw & 3]; } +static inline uint8_t rach_tx_integer_raw2val(uint8_t raw) { + const int tbl[6] = { 14, 16, 20, 25, 32, 50 }; + raw &= 0x0f; + if (raw <= 9) + return raw + 3; + return tbl[raw - 10]; +} #define ARFCN_PCS 0x8000 #define ARFCN_UPLINK 0x4000 @@ -174,13 +181,21 @@ void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn); char *gsm_fn_as_gsmtime_str(uint32_t fn); /* Convert from GSM time to frame number */ -uint32_t gsm_gsmtime2fn(struct gsm_time *time); +uint32_t gsm_gsmtime2fn(const struct gsm_time *time); /* Returns static buffer with string representation of a GSM Time */ char *osmo_dump_gsmtime(const struct gsm_time *tm); char *osmo_dump_gsmtime_buf(char *buf, size_t buf_len, const struct gsm_time *tm); char *osmo_dump_gsmtime_c(const void *ctx, const struct gsm_time *tm); +/* Reduced Frame Number (3GPP TS 44.018 §10.5.2.38) */ +#define GSM_RFN_MODULUS 42432 +uint32_t gsm_rfn2fn(uint16_t rfn, uint32_t curr_fn); +static inline uint16_t gsm_fn2rfn(uint32_t fn) +{ + return fn % GSM_RFN_MODULUS; +} + /* GSM TS 03.03 Chapter 2.6 */ enum gprs_tlli_type { TLLI_LOCAL, @@ -210,9 +225,11 @@ enum gsm_phys_chan_config { GSM_PCHAN_UNKNOWN, GSM_PCHAN_CCCH_SDCCH4_CBCH, GSM_PCHAN_SDCCH8_SACCH8C_CBCH, - GSM_PCHAN_TCH_F_TCH_H_PDCH, + GSM_PCHAN_OSMO_DYN, _GSM_PCHAN_MAX }; +/* Backward compatibility with older naming: */ +#define GSM_PCHAN_TCH_F_TCH_H_PDCH GSM_PCHAN_OSMO_DYN /* Osmocom internal, not part of any gsm spec */ enum gsm_chan_t { diff --git a/include/osmocom/gsm/gsup.h b/include/osmocom/gsm/gsup.h index 56d7a309..6ad72d28 100644 --- a/include/osmocom/gsm/gsup.h +++ b/include/osmocom/gsm/gsup.h @@ -37,9 +37,13 @@ * */ #pragma once +#if (!EMBEDDED) #include <stdint.h> #include <osmocom/core/msgb.h> +#include <osmocom/core/defs.h> +#include <osmocom/core/endian.h> +#include <osmocom/core/socket.h> #include <osmocom/gsm/gsup_sms.h> #include <osmocom/gsm/protocol/gsm_23_003.h> #include <osmocom/gsm/protocol/gsm_03_40.h> @@ -57,8 +61,7 @@ /*! Maximum number of octets encoding MSISDN in BCD format */ #define OSMO_GSUP_MAX_MSISDN_LEN 9 #define OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN 43 /* TS 24.008 10.5.4.7 */ - -#define OSMO_GSUP_PDP_TYPE_SIZE 2 +#define OSMO_GSUP_MAX_PCO_LEN 251 /*! Information Element Identifiers for GSUP IEs */ enum osmo_gsup_iei { @@ -71,12 +74,14 @@ enum osmo_gsup_iei { OSMO_GSUP_FREEZE_PTMSI_IE = 0x07, OSMO_GSUP_MSISDN_IE = 0x08, OSMO_GSUP_HLR_NUMBER_IE = 0x09, - OSMO_GSUP_MESSAGE_CLASS_IE = 0x0a, + OSMO_GSUP_MESSAGE_CLASS_IE = 0x0a, OSMO_GSUP_PDP_CONTEXT_ID_IE = 0x10, - OSMO_GSUP_PDP_TYPE_IE = 0x11, + OSMO_GSUP_PDP_ADDRESS_IE = 0x11, +#define OSMO_GSUP_PDP_TYPE_IE OSMO_GSUP_PDP_ADDRESS_IE /* Backward compat */ OSMO_GSUP_ACCESS_POINT_NAME_IE = 0x12, OSMO_GSUP_PDP_QOS_IE = 0x13, OSMO_GSUP_CHARG_CHAR_IE = 0x14, + OSMO_GSUP_PCO_IE = 0x15, OSMO_GSUP_RAND_IE = 0x20, OSMO_GSUP_SRES_IE = 0x21, OSMO_GSUP_KC_IE = 0x22, @@ -198,6 +203,10 @@ enum osmo_gsup_message_type { OSMO_GSUP_MSGT_E_ABORT = 0b01001011, OSMO_GSUP_MSGT_ROUTING_ERROR = 0b01001110, + + OSMO_GSUP_MSGT_EPDG_TUNNEL_REQUEST = 0b01010000, + OSMO_GSUP_MSGT_EPDG_TUNNEL_ERROR = 0b01010001, + OSMO_GSUP_MSGT_EPDG_TUNNEL_RESULT = 0b01010010, }; #define OSMO_GSUP_MSGT_E_ROUTING_ERROR OSMO_GSUP_MSGT_ROUTING_ERROR @@ -256,8 +265,20 @@ osmo_gsup_session_state_name(enum osmo_gsup_session_state val) struct osmo_gsup_pdp_info { unsigned int context_id; int have_info; - /*! Type of PDP context */ - uint16_t pdp_type; + /*! Type of PDP context, 3GPP TS 29.060, 7.7.27 */ + union { + uint16_t pdp_type OSMO_DEPRECATED("use pdp_type_org and pdp_type_nr instead"); + struct { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t pdp_type_nr; /* enum gsm48_pdp_type_nr */ + uint8_t pdp_type_org; /* enum gsm48_pdp_type_org */ +#elif OSMO_IS_BIG_ENDIAN + uint8_t pdp_type_org; /* enum gsm48_pdp_type_org */ + uint8_t pdp_type_nr; /* enum gsm48_pdp_type_nr */ +#endif + }; + }; + struct osmo_sockaddr pdp_address[2]; /*! APN information, still in encoded form. Can be NULL if no * APN information included */ const uint8_t *apn_enc; @@ -281,6 +302,7 @@ enum osmo_gsup_message_class { OSMO_GSUP_MESSAGE_CLASS_SMS = 2, OSMO_GSUP_MESSAGE_CLASS_USSD = 3, OSMO_GSUP_MESSAGE_CLASS_INTER_MSC = 4, + OSMO_GSUP_MESSAGE_CLASS_IPSEC_EPDG = 5, /* Keep this as last entry with a value of max(enum osmo_gsup_message_class) + 1. * This value shall serve as the size for an array to aid de-muxing all known GSUP classes. */ OSMO_GSUP_MESSAGE_CLASS_ARRAYSIZE @@ -386,6 +408,12 @@ struct osmo_gsup_message { enum osmo_rat_type current_rat_type; enum osmo_rat_type supported_rat_types[8]; /*!< arbitrary choice */ size_t supported_rat_types_len; + + /*! PCO protocol option 3GPP TS 24.008 10.5.6.3 / Table 10.5.136. PCO contains Octet 3-ZA */ + const uint8_t *pco; + /*! Number of bytes of the PCO. */ + size_t pco_len; + }; int osmo_gsup_decode(const uint8_t *data, size_t data_len, @@ -394,4 +422,5 @@ int osmo_gsup_encode(struct msgb *msg, const struct osmo_gsup_message *gsup_msg) int osmo_gsup_get_err_msg_type(enum osmo_gsup_message_type type_in) OSMO_DEPRECATED("Use OSMO_GSUP_TO_MSGT_ERROR() instead"); +#endif /* (!EMBEDDED) */ /*! @} */ diff --git a/include/osmocom/gsm/i460_mux.h b/include/osmocom/gsm/i460_mux.h index 2e33b37e..7c2f4af3 100644 --- a/include/osmocom/gsm/i460_mux.h +++ b/include/osmocom/gsm/i460_mux.h @@ -1,104 +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, -}; - -typedef void (*out_cb_bits_t)(void *user_data, const ubit_t *bits, unsigned int num_bits); -typedef void (*out_cb_bytes_t)(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; -}; - -struct osmo_i460_subchan_mux { - /*! list of to-be-transmitted message buffers */ - struct llist_head tx_queue; -}; - -struct osmo_i460_subchan { - 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; -}; - -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 11b27730..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 */ @@ -126,7 +128,7 @@ struct info_meas_ind_param { /*! for {ACTIVATE,DEACTIVATE,MODIFY} MPH-INFO.req */ struct info_act_req_param { uint8_t chan_nr; /*!< Channel Number (Like RSL) */ - uint8_t sacch_only; /*!< \breif Only deactivate SACCH */ + uint8_t sacch_only; /*!< \brief Only deactivate SACCH */ }; /*! for {ACTIVATE,DEACTIVATE} MPH-INFO.cnf */ @@ -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 386b7d89..73cd7f71 100644 --- a/include/osmocom/gsm/prim.h +++ b/include/osmocom/gsm/prim.h @@ -14,4 +14,11 @@ enum osmo_gsm_sap { SAP_BSSGP_LL, SAP_BSSGP_NM, SAP_BSSGP_PFM, + + SAP_NS, + + SAP_BSSGP_RIM, + + SAP_IUUP_TNL, + SAP_IUUP_RNL, }; diff --git a/include/osmocom/gsm/protocol/Makefile.am b/include/osmocom/gsm/protocol/Makefile.am new file mode 100644 index 00000000..23429dcd --- /dev/null +++ b/include/osmocom/gsm/protocol/Makefile.am @@ -0,0 +1,30 @@ +osmogsmproto_HEADERS = \ + gsm_23_032.h \ + gsm_03_40.h \ + gsm_03_41.h \ + gsm_04_08.h \ + gsm_04_08_gprs.h \ + gsm_04_11.h \ + gsm_04_12.h \ + gsm_04_14.h \ + gsm_04_80.h \ + gsm_08_08.h \ + gsm_08_58.h \ + gsm_09_02.h \ + gsm_12_21.h \ + gsm_23_003.h \ + gsm_23_041.h \ + gsm_25_415.h \ + gsm_29_118.h \ + gsm_44_004.h \ + gsm_44_060.h \ + gsm_44_068.h \ + gsm_44_318.h \ + gsm_48_049.h \ + gsm_48_071.h \ + gsm_49_031.h \ + ipaccess.h \ + smpp34_osmocom.h \ + $(NULL) + +osmogsmprotodir = $(includedir)/osmocom/gsm/protocol diff --git a/include/osmocom/gsm/protocol/gsm_03_41.h b/include/osmocom/gsm/protocol/gsm_03_41.h index 1b399aee..f6c36cad 100644 --- a/include/osmocom/gsm/protocol/gsm_03_41.h +++ b/include/osmocom/gsm/protocol/gsm_03_41.h @@ -25,7 +25,7 @@ struct gsm341_ms_message { uint8_t update:4; uint8_t code_lo:4; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t gs:2, code_hi:6; uint8_t code_lo:4, update:4; #endif @@ -36,7 +36,7 @@ struct gsm341_ms_message { uint8_t language:4; uint8_t group:4; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t group:4, language:4; #endif } dcs; @@ -45,7 +45,7 @@ struct gsm341_ms_message { uint8_t total:4; uint8_t current:4; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t current:4, total:4; #endif } page; @@ -63,7 +63,7 @@ struct gsm341_etws_message { uint8_t update:4; uint8_t code_lo:4; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t gs:2, alert:1, popup:1, code_hi:4; uint8_t code_lo:4, update:4; #endif diff --git a/include/osmocom/gsm/protocol/gsm_04_08.h b/include/osmocom/gsm/protocol/gsm_04_08.h index f8f2eabd..075b6ca6 100644 --- a/include/osmocom/gsm/protocol/gsm_04_08.h +++ b/include/osmocom/gsm/protocol/gsm_04_08.h @@ -22,7 +22,7 @@ struct gsm48_classmark1 { rev_lev:2, spare:1; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t spare:1, rev_lev:2, es_ind:1, a5_1:1, pwr_lev:3; #endif } __attribute__ ((packed)); @@ -51,13 +51,182 @@ struct gsm48_classmark2 { spare4:1, cm3:1; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t spare:1, rev_lev:2, es_ind:1, a5_1:1, pwr_lev:3; uint8_t spare2:1, ps_cap:1, ss_scr:2, sm_cap:1, vbs:1, vgcs:1, fc:1; uint8_t cm3:1, spare4:1, lcsva_cap:1, spare3:1, solsa:1, cmsp:1, a5_3:1, a5_2:1; #endif } __attribute__ ((packed)); +/* Chapter 10.5.1.7 */ +struct gsm48_classmark3 { + uint8_t a5_bits; + uint8_t mult_band_supp; + uint8_t assoc_radio_cap_1; + uint8_t assoc_radio_cap_2; + + struct { + bool present; + uint8_t r_gsm_assoc_radio_cap; + } r_support; + + struct { + bool present; + uint8_t mslot_class; + } hscsd_mult_slot_cap; + + bool ucs2_treatment; + bool extended_meas_cap; + + struct { + bool present; + uint8_t sms_value; + uint8_t sm_value; + } ms_meas_cap; + + struct { + bool present; + uint8_t method; + } ms_pos_method_cap; + + struct { + bool present; + uint8_t mslot_class; + } ecsd_multislot_cap; + + struct { + bool present; + bool mod_cap; + + struct { + bool present; + uint8_t value; + } rf_pwr_cap_1; + + struct { + bool present; + uint8_t value; + } rf_pwr_cap_2; + + } psk8_struct; + + struct { + bool present; + uint8_t value; + uint8_t assoc_radio_cap; + } gsm_400_bands_supp; + + struct { + bool present; + uint8_t value; + } gsm_850_assoc_radio_cap; + + struct { + bool present; + uint8_t value; + } gsm_1900_assoc_radio_cap; + + bool umts_fdd_rat_cap; + bool umts_tdd_rat_cap; + bool cdma200_rat_cap; + + struct { + bool present; + uint8_t mslot_class; + bool single_slot_dtm; + struct { + bool present; + uint8_t mslot_class; + } dtm_egprs_multislot_cap; + } dtm_gprs_multislot_cap; + + struct { + bool present; + uint8_t value; + } single_band_supp; + + struct { + bool present; + uint8_t value; + } gsm_750_assoc_radio_cap; + + bool umts_1_28_mcps_tdd_rat_cap; + bool geran_feature_package; + + struct { + bool present; + uint8_t mslot_class; + struct { + bool present; + uint8_t mslot_class; + } extended_dtm_egprs_multislot_cap; + } extended_dtm_gprs_multislot_cap; + + struct { + bool present; + uint8_t value; + } high_multislot_cap; + + bool geran_feature_package_2; + uint8_t gmsk_multislot_power_prof; + uint8_t psk8_multislot_power_prof; + + struct { + bool present; + uint8_t value; + uint8_t assoc_radio_cap; + } t_gsm_400_bands_supp; + + uint8_t dl_advanced_rx_perf; + bool dtm_enhancements_cap; + + struct { + bool present; + uint8_t mslot_class; + bool offset_required; + struct { + bool present; + uint8_t mslot_class; + } dtm_egprs_high_multislot_cap; + } dtm_gprs_high_multislot_cap; + + bool repeated_acch_capability; + + struct { + bool present; + uint8_t value; + } gsm_710_assoc_radio_cap; + + struct { + bool present; + uint8_t value; + } t_gsm_810_assoc_radio_cap; + + bool ciphering_mode_setting_cap; + bool add_pos_cap; + bool e_utra_fdd_supp; + bool e_utra_tdd_supp; + bool e_utra_meas_rep_supp; + bool prio_resel_supp; + bool utra_csg_cells_rep; + + uint8_t vamos_level; + uint8_t tighter_capability; + + bool sel_ciph_dl_sacch; + + uint8_t cs_ps_srvcc_geran_utra; + uint8_t cs_ps_srvcc_geran_eutra; + + bool geran_net_sharing; + bool e_utra_wb_rsrq_meas_supp; + bool er_band_support; + bool utra_mult_band_ind_supp; + bool e_utra_mult_band_ind_supp; + bool extended_tsc_set_cap_supp; + bool extended_earfcn_val_range; +}; + struct osmo_gsm48_classmark { bool classmark1_set; struct gsm48_classmark1 classmark1; @@ -111,7 +280,7 @@ struct gsm48_range_1024 { uint8_t w16:6, w15_lo:2; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t form_id:5, f0:1, w1_hi:2; uint8_t w1_lo; uint8_t w2_hi; @@ -166,7 +335,7 @@ struct gsm48_range_512 { uint8_t w17:5, w16_lo:3; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t form_id:7, orig_arfcn_hi:1; uint8_t orig_arfcn_mid; uint8_t orig_arfcn_lo:1, w1_hi:7; @@ -227,7 +396,7 @@ struct gsm48_range_256 { w21:4, w20_lo:3; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t form_id:7, orig_arfcn_hi:1; uint8_t orig_arfcn_mid; uint8_t orig_arfcn_lo:1, w1_hi:7; @@ -290,7 +459,7 @@ struct gsm48_range_128 { w27:3, w26_lo:1; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t form_id:7, orig_arfcn_hi:1; uint8_t orig_arfcn_mid; uint8_t orig_arfcn_lo:1, w1:7; @@ -320,7 +489,7 @@ struct gsm48_var_bit { orig_arfcn_lo:1; uint8_t rrfcn8_111[13]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t form_id:7, orig_arfcn_hi:1; uint8_t orig_arfcn_mid; uint8_t orig_arfcn_lo:1, rrfcn1_7:7; @@ -340,7 +509,7 @@ struct gsm48_chan_desc { uint8_t hsn:6, maio_low:2; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t tsc:3, h:1, maio_high:4; uint8_t maio_low:2, hsn:6; #endif @@ -353,7 +522,7 @@ struct gsm48_chan_desc { tsc:3; uint8_t arfcn_low; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t tsc:3, h:1, spare:2, arfcn_high:2; uint8_t arfcn_low; #endif @@ -404,7 +573,7 @@ struct gsm48_meas_res { uint8_t bsic_nc6:6, bcch_f_nc6_lo:2; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t ba_used:1, dtx_used:1, rxlev_full:6; uint8_t spare:1, meas_valid:1, rxlev_sub:6; uint8_t spare2:1, rxqual_full:3, rxqual_sub:3, no_nc_n_hi:1; @@ -424,6 +593,12 @@ struct gsm48_meas_res { #endif } __attribute__ ((packed)); +/*! Check if the given mr contains valid measurement results */ +static inline bool gsm48_meas_res_is_valid(const struct gsm48_meas_res *mr) +{ + return (mr->meas_valid == 0); /* 0 means valid */ +} + /* Chapter 10.5.2.21aa */ struct gsm48_multi_rate_conf { #if OSMO_IS_LITTLE_ENDIAN @@ -441,7 +616,7 @@ struct gsm48_multi_rate_conf { m10_2 : 1, m12_2 : 1; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t ver:3, nscb:1, icmi:1, spare:1, smod:2; uint8_t m12_2:1, m10_2:1, m7_95:1, m7_40:1, m6_70:1, m5_90:1, m5_15:1, m4_75:1; #endif @@ -454,7 +629,7 @@ struct gsm48_power_cmd { spare:2, atc:1; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t atc:1, spare:2, power_level:5; #endif } __attribute__((packed)); @@ -469,7 +644,7 @@ struct gsm48_rach_control { uint8_t t2; /* ACC 8-15 barred flags */ uint8_t t3; /* ACC 0-7 barred flags */ #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t max_trans:2, tx_integer:4, cell_bar:1, re:1; uint8_t t2; uint8_t t3; @@ -527,7 +702,7 @@ struct gsm48_req_ref { uint8_t t2:5, t3_low:3; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t ra; uint8_t t1:5, t3_high:3; uint8_t t3_low:3, t2:5; @@ -542,7 +717,7 @@ struct gsm48_start_time { uint8_t t2:5, t3_low:3; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t t1:5, t3_high:3; uint8_t t3_low:3, t2:5; #endif @@ -556,7 +731,7 @@ struct gsm48_sync_ind { nci:1, sync_ie:4; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t sync_ie:4, nci:1, rot:1, si:2; #endif } __attribute__((packed)); @@ -571,15 +746,59 @@ struct gsm48_chan_mode_modify { uint8_t mode; } __attribute__ ((packed)); +/*! 10.5.2.6 Channel Mode value */ enum gsm48_chan_mode { + /*! Signalling only (TCH/F or TCH/H) */ GSM48_CMODE_SIGN = 0x00, + /*! Speech: FR (TCH/FS) or HR (TCH/HS) */ GSM48_CMODE_SPEECH_V1 = 0x01, - GSM48_CMODE_SPEECH_EFR = 0x21, - GSM48_CMODE_SPEECH_AMR = 0x41, + /*! Speech: EFR (TCH/EFS) */ + GSM48_CMODE_SPEECH_EFR = 0x21, /*!< a.k.a. V2 */ + /*! Speech: AMR (TCH/AFS or TCH/AHS) */ + GSM48_CMODE_SPEECH_AMR = 0x41, /*!< a.k.a. V3 */ + /*! Speech: OFR AMR-WB (O-TCH/WFS) or OHR AMR-WB (O-TCH/WHS) */ + GSM48_CMODE_SPEECH_V4 = 0x81, + /*! Speech: FR AMR-WB (TCH/WFS) */ + GSM48_CMODE_SPEECH_V5 = 0x82, + /*! Speech: OHR AMR (O-TCH/AHS) */ + GSM48_CMODE_SPEECH_V6 = 0x83, + + /* ECSD: 43.5 kbit/s (DL) + 14.5 kbit/s (UL) */ + GSM48_CMODE_DATA_43k5_14k5 = 0x61, + /* ECSD: 29.0 kbit/s (DL) + 14.5 kbit/s (UL) */ + GSM48_CMODE_DATA_29k0_14k5 = 0x62, + /* ECSD: 43.5 kbit/s (DL) + 29.0 kbit/s (UL) */ + GSM48_CMODE_DATA_43k5_29k0 = 0x64, + /* ECSD: 14.5 kbit/s (DL) + 43.5 kbit/s (UL) */ + GSM48_CMODE_DATA_14k5_43k5 = 0x67, + /* ECSD: 14.5 kbit/s (DL) + 29.0 kbit/s (UL) */ + GSM48_CMODE_DATA_14k5_29k0 = 0x65, + /* ECSD: 29.0 kbit/s (DL) + 43.5 kbit/s (UL) */ + GSM48_CMODE_DATA_29k0_43k5 = 0x66, + + /*! ECSD: 43.5 kbit/s radio interface rate, 43.2 kbit/s services (E-TCH/F43.2) */ + GSM48_CMODE_DATA_43k5 = 0x27, + /*! ECSD: 32.0 kbit/s radio interface rate, 32.0 kbit/s services (E-TCH/F32.0) */ + GSM48_CMODE_DATA_32k0 = 0x63, + /*! ECSD: 29.0 kbit/s radio interface rate, 28.8 kbit/s services (E-TCH/F28.8) */ + GSM48_CMODE_DATA_29k0 = 0x43, + /*! CSD: 14.5 kbit/s radio interface rate, 14.4 kbit/s services (TCH/F14.4) */ GSM48_CMODE_DATA_14k5 = 0x0f, + /*! CSD: 12.0 kbit/s radio interface rate, 9.6 kbit/s services (TCH/F9.6) */ GSM48_CMODE_DATA_12k0 = 0x03, + /*! CSD: 6.0 kbit/s radio interface rate, 4.8 kbit/s services (TCH/{F,H}4.8) */ GSM48_CMODE_DATA_6k0 = 0x0b, + /*! CSD: 3.6 kbit/s radio interface rate, 2.4 kbit/s and less services (TCH/{F,H}2.4) */ GSM48_CMODE_DATA_3k6 = 0x13, + + /*! Same as GSM48_CMODE_SPEECH_V1, in VAMOS mode */ + GSM48_CMODE_SPEECH_V1_VAMOS = 0xc1, + /*! Same as GSM48_CMODE_SPEECH_EFR, in VAMOS mode */ + GSM48_CMODE_SPEECH_V2_VAMOS = 0xc2, + /*! Same as GSM48_CMODE_SPEECH_AMR, in VAMOS mode */ + GSM48_CMODE_SPEECH_V3_VAMOS = 0xc3, + /*! Speech: GSM48_CMODE_SPEECH_V5, in VAMOS mode */ + GSM48_CMODE_SPEECH_V5_VAMOS = 0xc5, }; extern const struct value_string gsm48_chan_mode_names[]; @@ -618,7 +837,7 @@ struct gsm48_cell_desc { arfcn_hi:2; uint8_t arfcn_lo; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t arfcn_hi:2, ncc:3, bcc:3; uint8_t arfcn_lo; #endif @@ -661,7 +880,7 @@ struct gsm48_pag_resp { uint8_t mi_len; uint8_t mi[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t key_seq:4, spare:4; union { uint32_t classmark2; @@ -688,7 +907,7 @@ struct gsm48_auth_req { spare:4; uint8_t rand[16]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t spare:4, key_seq:4; uint8_t rand[16]; #endif @@ -709,7 +928,7 @@ struct gsm48_loc_upd_req { uint8_t mi_len; uint8_t mi[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t key_seq:4, type:4; struct gsm48_loc_area_id lai; struct gsm48_classmark1 classmark1; @@ -725,6 +944,20 @@ struct gsm48_hdr { uint8_t data[0]; } __attribute__ ((packed)); +/* Short header */ +struct gsm48_hdr_sh { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t l2_header:2, /* < short layer 2 header : bit(2) > See 3GPP TS 44.006 §6.4a */ + msg_type:5, /* < message type : bit(5) > See 3GPP TS 44.018 Table 10.4.2 */ + rr_short_pd:1; /* < RR short PD : bit > See 3GPP TS 24.007 §11.3.2 */ + uint8_t data[0]; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t rr_short_pd:1, msg_type:5, l2_header:2; + uint8_t data[0]; +#endif +} __attribute__ ((packed)); + /* Section 9.1.3x System information Type header */ struct gsm48_system_information_type_header { #if OSMO_IS_LITTLE_ENDIAN @@ -733,7 +966,7 @@ struct gsm48_system_information_type_header { skip_indicator:4; uint8_t system_information; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t l2_plen; uint8_t skip_indicator:4, rr_protocol_discriminator:4; uint8_t system_information; @@ -749,7 +982,7 @@ struct gsm48_cell_sel_par { neci:1, acs:1; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t cell_resel_hyst:3, ms_txpwr_max_ccch:5; uint8_t acs:1, neci:1, rxlev_acc_min:6; #endif @@ -768,7 +1001,7 @@ struct gsm48_control_channel_descr { spare_2 :1; uint8_t t3212; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t mscr:1, att:1, bs_ag_blks_res:3, ccch_conf:3; uint8_t spare_2:1, cbq3:2, spare_1:2, bs_pa_mfrms:3; uint8_t t3212; @@ -791,7 +1024,7 @@ struct gsm48_cell_options { /* either DN-IND or top bit of DTX IND */ d:1; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t d:1, pwrc:1, dtx:2, radio_link_timeout:4; #endif } __attribute__ ((packed)); @@ -812,7 +1045,7 @@ struct gsm48_service_request { uint8_t mi[0]; /* optional priority level */ #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t cipher_key_seq:4, cm_service_type:4; union { uint32_t classmark; @@ -895,7 +1128,7 @@ struct gsm48_system_information_type_5 { uint8_t system_information; uint8_t bcch_frequency_list[16]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t skip_indicator:4, rr_protocol_discriminator:4; uint8_t system_information; uint8_t bcch_frequency_list[16]; @@ -910,7 +1143,7 @@ struct gsm48_system_information_type_5bis { uint8_t system_information; uint8_t bcch_frequency_list[16]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t skip_indicator:4, rr_protocol_discriminator:4; uint8_t system_information; uint8_t bcch_frequency_list[16]; @@ -925,7 +1158,7 @@ struct gsm48_system_information_type_5ter { uint8_t system_information; uint8_t bcch_frequency_list[16]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t skip_indicator:4, rr_protocol_discriminator:4; uint8_t system_information; uint8_t bcch_frequency_list[16]; @@ -944,7 +1177,7 @@ struct gsm48_system_information_type_6 { uint8_t ncc_permitted; uint8_t rest_octets[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t skip_indicator:4, rr_protocol_discriminator:4; uint8_t system_information; uint16_t cell_identity; @@ -955,6 +1188,27 @@ struct gsm48_system_information_type_6 { #endif } __attribute__ ((packed)); +/* Section 9.1.50 System Information type 10 (ASCI) */ +struct gsm48_system_information_type_10 { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t l2_header:2, /* < short layer 2 header : bit(2) > See 3GPP TS 44.006 §6.4a */ + msg_type:5, /* < message type : bit(5) > See 3GPP TS 44.018 Table 10.4.2 */ + rr_short_pd:1; /* < RR short PD : bit > See 3GPP TS 24.007 §11.3.2 */ + uint8_t rest_octets[0]; /* < SI10 Rest Octets : bit(160) > See 3GPP TS 44.018 §10.5.2.44 */ +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t rr_short_pd:1, msg_type:5, l2_header:2; + uint8_t rest_octets[0]; +#endif +} __attribute__ ((packed)); + +/* TS 44.018 Section 9.1.49 */ +struct gsm0408_vgcs_ul_grant { + struct gsm48_hdr hdr; + struct gsm48_req_ref req_ref; + uint8_t ta; +} __attribute__ ((packed)); + /* Section 9.1.43a System Information type 13 */ struct gsm48_system_information_type_13 { struct gsm48_system_information_type_header header; @@ -1010,7 +1264,7 @@ struct gsm48_cip_mode_cmd { cr:1, spare:3; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t spare:3, cr:1, alg_id:3, sc:1; #endif } __attribute__((packed)); @@ -1055,6 +1309,14 @@ struct gsm48_imm_ass_rej { uint8_t rest[0]; } __attribute__ ((packed)); +/* Section 9.1.21b */ +struct gsm48_notification_nch { + uint8_t l2_plen; + uint8_t proto_discr; + uint8_t msg_type; + uint8_t data[0]; +} __attribute__((packed)); + /* Section 9.1.22 */ struct gsm48_paging1 { #if OSMO_IS_LITTLE_ENDIAN @@ -1067,7 +1329,7 @@ struct gsm48_paging1 { cneed2:2; uint8_t data[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t l2_plen; uint8_t proto_discr; uint8_t msg_type; @@ -1090,7 +1352,7 @@ struct gsm48_paging2 { uint32_t tmsi2; uint8_t data[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t l2_plen; uint8_t proto_discr; uint8_t msg_type; @@ -1120,7 +1382,7 @@ struct gsm48_paging3 { spare2:4; uint8_t rest[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t l2_plen; uint8_t proto_discr; uint8_t msg_type; @@ -1143,7 +1405,7 @@ struct gsm48_pag_rsp { struct gsm48_classmark2 cm2; uint8_t data[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t spare:5, key_seq:3; uint8_t cm2_len; struct gsm48_classmark2 cm2; @@ -1156,6 +1418,18 @@ struct gsm48_rr_status { uint8_t rr_cause; } __attribute__((packed)); +/* Section 9.1.44 */ +struct gsm48_talker_indication { + uint8_t cm2_len; + struct gsm48_classmark2 cm2; + uint8_t data[0]; +} __attribute__((packed)); + +/* Section 9.1.48 */ +struct gsm48_uplink_release { + uint8_t rr_cause; +} __attribute__((packed)); + /* Section 10.2 + GSM 04.07 12.2.3.1.1 + 3GPP TS 24.007 11.2.3.1.1 */ #define GSM48_PDISC_GROUP_CC 0x00 #define GSM48_PDISC_BCAST_CC 0x01 @@ -1174,6 +1448,9 @@ struct gsm48_rr_status { #define GSM48_PDISC_TEST 0x0f /* as per 11.10, 04.14 */ #define GSM48_PDISC_MASK 0x0f +/* Section 11.3.2.1 3GPP TS 24.007: Short PDISC */ +#define GSM48_PDISC_SH_RR 0 + extern const struct value_string gsm48_pdisc_names[]; static inline const char *gsm48_pdisc_name(uint8_t val) { return get_value_string(gsm48_pdisc_names, val); } @@ -1361,6 +1638,21 @@ void gsm48_set_dtx(struct gsm48_cell_options *op, enum gsm48_dtx_mode full, #define GSM48_MT_RR_APP_INFO 0x38 +/* 3GPP TS 44.018 Table 10.4.2 */ +#define GSM48_MT_RR_SH_SI10 0x0 +#define GSM48_MT_RR_SH_FACCH 0x1 +#define GSM48_MT_RR_SH_UL_FREE 0x2 +#define GSM48_MT_RR_SH_MEAS_REP 0x4 +#define GSM48_MT_RR_SH_MEAS_INFO 0x5 +#define GSM48_MT_RR_SH_VGCS_RECON 0x6 +#define GSM48_MT_RR_SH_VGCS_RECON2 0x7 +#define GSM48_MT_RR_SH_VGCS_INFO 0x8 +#define GSM48_MT_RR_SH_VGCS_SMS 0x9 +#define GSM48_MT_RR_SH_SI10bis 0xA +#define GSM48_MT_RR_SH_SI10ter 0xB +#define GSM48_MT_RR_SH_VGCS_NEIGH 0xC +#define GSM48_MT_RR_SH_APP_DATA 0xD + /* Table 10.2/3GPP TS 04.08 */ #define GSM48_MT_MM_IMSI_DETACH_IND 0x01 #define GSM48_MT_MM_LOC_UPD_ACCEPT 0x02 @@ -1526,6 +1818,10 @@ static inline const char *osmo_lu_type_name(uint8_t lu_type) #define GSM48_IE_FRQSHORT_AFTER 0x02 #define GSM48_IE_MUL_RATE_CFG 0x03 /* 10.5.2.21aa */ #define GSM48_IE_FREQ_L_AFTER 0x05 +#define GSM48_IE_GROUP_CIP_SEQ_HO 0x08 /* HO = Half Octet Tag */ +#define GSM48_IE_CIP_MODE_SET_HO 0x09 /* HO = Half Octet Tag */ +#define GSM48_IE_GPRS_RESUMPT_HO 0xc0 /* HO = Half Octet Tag */ +#define GSM48_IE_SYNC_IND_HO 0x0d /* HO = Half Octet Tag */ #define GSM48_IE_MSLOT_DESC 0x10 #define GSM48_IE_CHANMODE_2 0x11 #define GSM48_IE_FRQSHORT_BEFORE 0x12 @@ -1556,6 +1852,7 @@ static inline const char *osmo_lu_type_name(uint8_t lu_type) #define GSM48_IE_CHDES_2_AFTER 0x64 #define GSM48_IE_MODE_SEC_CH 0x66 #define GSM48_IE_F_CH_SEQ_AFTER 0x69 +#define GSM48_IE_EXTENDED_TSC_SET 0x6d #define GSM48_IE_MA_AFTER 0x72 #define GSM48_IE_BA_RANGE 0x73 #define GSM48_IE_GROUP_CHDES 0x74 @@ -1566,20 +1863,21 @@ static inline const char *osmo_lu_type_name(uint8_t lu_type) #define GSM48_IE_START_TIME 0x7c #define GSM48_IE_INDIVIDUAL_PRIORITIES 0x7c /* 44.018 Section 9.1.7 */ #define GSM48_IE_TIMING_ADVANCE 0x7d -#define GSM48_IE_GROUP_CIP_SEQ 0x80 -#define GSM48_IE_CIP_MODE_SET 0x90 -#define GSM48_IE_GPRS_RESUMPT 0xc0 -#define GSM48_IE_SYNC_IND 0xd0 +#define GSM48_IE_GROUP_CIP_SEQ 0x80 /* DEPRECATED, use GSM48_IE_GROUP_CIP_SEQ_HO instead */ +#define GSM48_IE_CIP_MODE_SET 0x90 /* DEPRECATED, use GSM48_IE_CIP_MODE_SET_HO instead */ +#define GSM48_IE_GPRS_RESUMPT 0xc0 /* DEPRECATED, use GSM48_IE_GPRS_RESUMPT_HO instead */ +#define GSM48_IE_SYNC_IND 0xd0 /* DEPRECATED, use GSM48_IE_SYNC_IND_HO instead */ /* System Information 4 (types are equal IEs above) */ #define GSM48_IE_CBCH_CHAN_DESC 0x64 #define GSM48_IE_CBCH_MOB_AL 0x72 /* Additional MM elements */ +#define GSM48_IE_PRIORITY_LEV_HO 0x08 /* HO = Half Octet Tag */ #define GSM48_IE_LOCATION_AREA 0x13 #define GSM48_IE_AUTN 0x20 #define GSM48_IE_AUTH_RES_EXT 0x21 #define GSM48_IE_AUTS 0x22 -#define GSM48_IE_PRIORITY_LEV 0x80 +#define GSM48_IE_PRIORITY_LEV 0x80 /* DEPRECATED, use GSM48_IE_PRIORITY_LEV_HO instead */ #define GSM48_IE_FOLLOW_ON_PROC 0xa1 #define GSM48_IE_CTS_PERMISSION 0xa2 @@ -1638,9 +1936,12 @@ enum gsm48_rr_cause { GSM48_RR_CAUSE_ABNORMAL_TIMER = 0x03, GSM48_RR_CAUSE_ABNORMAL_NOACT = 0x04, GSM48_RR_CAUSE_PREMPTIVE_REL = 0x05, + GSM48_RR_CAUSE_UTRAN_CFG_UNK = 0x06, GSM48_RR_CAUSE_HNDOVER_IMP = 0x08, GSM48_RR_CAUSE_CHAN_MODE_UNACCT = 0x09, GSM48_RR_CAUSE_FREQ_NOT_IMPL = 0x0a, + GSM48_RR_CAUSE_LEAVE_GROUP_CA = 0x0b, + GSM48_RR_CAUSE_LOW_LEVEL_FAIL = 0x0c, GSM48_RR_CAUSE_CALL_CLEARED = 0x41, GSM48_RR_CAUSE_SEMANT_INCORR = 0x5f, GSM48_RR_CAUSE_INVALID_MAND_INF = 0x60, @@ -1909,8 +2210,31 @@ enum gsm48_bcap_modem_type { GSM48_BCAP_MT_AUTO_1 = 8, }; +/*! Table 10.5.112/3GPP TS 24.008: Other modem type (octet 6d) */ +enum gsm48_bcap_other_modem_type { + GSM48_BCAP_OTHER_MT_NONE = 0, /*!< No other modem type specified */ + GSM48_BCAP_OTHER_MT_V34 = 2, /*!< According to ITU-T Rec. V.34 */ +}; + +/*! Table 10.5.112/3GPP TS 24.008: Fixed network user rate (octet 6d) */ +enum gsm48_bcap_fixed_net_user_rate { + GSM48_BCAP_FNUR_NONE = 0, /*!< FNUR not applicable / No meaning associated */ + GSM48_BCAP_FNUR_X1_V110_9600 = 1, /*!< 9.6 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_14400 = 2, /*!< 14.4 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_19200 = 3, /*!< 19.2 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_28800 = 4, /*!< 28.8 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_38400 = 5, /*!< 38.4 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_48000 = 6, /*!< 48.0 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_56000 = 7, /*!< 56.0 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_BT_64000 = 8, /*!< 64.0 kbit/s bit transparent */ + GSM48_BCAP_FNUR_BT_33600 = 9, /*!< 33.6 kbit/s bit transparent */ + GSM48_BCAP_FNUR_I460_32000 = 10, /*!< 32.0 kbit/s (according to ITU-T Rec. I.460) */ + GSM48_BCAP_FNUR_V34_31200 = 11, /*!< 31.2 kbit/s (according to ITU-T Rec. V.34) */ +}; + /*! GSM 04.08 Bearer Capability: Speech Version Indication - * (See also 3GPP TS 24.008, Table 10.5.103) */ + * (See also 3GPP TS 24.008, Table 10.5.103 + * and 3GPP TS 26.103, Table 4.1 "Support of Codec Types in Radio Access Technologies") */ enum gsm48_bcap_speech_ver { GSM48_BCAP_SV_FR = 0, /*!< GSM FR V1 (GSM FR) */ GSM48_BCAP_SV_HR = 1, /*!< GSM HR V1 (GSM HR) */ diff --git a/include/osmocom/gsm/protocol/gsm_04_08_gprs.h b/include/osmocom/gsm/protocol/gsm_04_08_gprs.h index 86c5b016..2671aafb 100644 --- a/include/osmocom/gsm/protocol/gsm_04_08_gprs.h +++ b/include/osmocom/gsm/protocol/gsm_04_08_gprs.h @@ -1,7 +1,6 @@ /*! \file gsm_04_08_gprs.h */ -#ifndef _GSM48_GPRS_H -#define _GSM48_GPRS_H +#pragma once #include <stdint.h> #include <stdbool.h> @@ -83,6 +82,8 @@ extern const struct value_string *gprs_upd_t_strs; enum gsm48_gprs_ie_mm { GSM48_IE_GMM_CIPH_CKSN = 0x08, /* 10.5.1.2 */ + GSM48_IE_GMM_PTMSI_TYPE = 0x0e, /* 10.5.5.29 */ + GSM48_IE_GMM_TMSI_BASED_NRI_C = 0x10, /* 10.5.5.31 */ GSM48_IE_GMM_TIMER_READY = 0x17, /* 10.5.7.3 */ GSM48_IE_GMM_ALLOC_PTMSI = 0x18, /* 10.5.1.4 */ GSM48_IE_GMM_PTMSI_SIG = 0x19, /* 10.5.5.8 */ @@ -90,26 +91,39 @@ enum gsm48_gprs_ie_mm { GSM48_IE_GMM_AUTH_SRES = 0x22, /* 10.5.3.2 */ GSM48_IE_GMM_IMEISV = 0x23, /* 10.5.1.4 */ GSM48_IE_GMM_CAUSE = 0x25, /* 10.5.5.14 */ + GSM48_IE_GMM_RX_NPDU_NUM_LIST = 0x26, /* 10.5.5.11 */ GSM48_IE_GMM_DRX_PARAM = 0x27, /* 10.5.5.6 */ GSM48_IE_GMM_AUTN = 0x28, /* 10.5.3.1.1 */ GSM48_IE_GMM_AUTH_RES_EXT = 0x29, /* 10.5.3.2.1 */ + GSM48_IE_GMM_TIMER_T3302 = 0x2A, /* 10.5.7.4 */ GSM48_IE_GMM_AUTH_FAIL_PAR = 0x30, /* 10.5.3.2.2 */ GSM48_IE_GMM_MS_NET_CAPA = 0x31, /* 10.5.5.12 */ GSM48_IE_GMM_PDP_CTX_STATUS = 0x32, /* 10.5.7.1 */ GSM48_IE_GMM_PS_LCS_CAPA = 0x33, /* 10.5.5.22 */ GSM48_IE_GMM_GMM_MBMS_CTX_ST = 0x35, /* 10.5.7.6 */ + GSM48_IE_GMM_TIMER_T3346 = 0x3A, /* 10.5.7.4 */ + GSM48_IE_GMM_NET_FEAT_SUPPORT = 0xB0, /* 10.5.5.23 */ }; enum gsm48_gprs_ie_sm { + GSM48_IE_GSM_RADIO_PRIO = 0x08, /* 10.5.7.2 */ + GSM48_IE_GSM_DEV_PROP = 0x0C, /* 10.5.7.8 */ GSM48_IE_GSM_APN = 0x28, /* 10.5.6.1 */ GSM48_IE_GSM_PROTO_CONF_OPT = 0x27, /* 10.5.6.3 */ GSM48_IE_GSM_PDP_ADDR = 0x2b, /* 10.5.6.4 */ GSM48_IE_GSM_AA_TMR = 0x29, /* 10.5.7.3 */ + GSM48_IE_GSM_QOS = 0x30, /* 10.5.6.5 */ + GSM48_IE_GSM_TFT = 0x31, /* 10.5.6.12 */ + GSM48_IE_GSM_LLC_SAPI = 0x32, /* 10.5.6.9 */ + GSM48_IE_GSM_MBIFOM_CONT = 0x33, /* 10.5.6.21 */ + GSM48_IE_GSM_PFI = 0x34, /* 10.5.6.11 */ GSM48_IE_GSM_NAME_FULL = 0x43, /* 10.5.3.5a */ GSM48_IE_GSM_NAME_SHORT = 0x45, /* 10.5.3.5a */ GSM48_IE_GSM_TIMEZONE = 0x46, /* 10.5.3.8 */ GSM48_IE_GSM_UTC_AND_TZ = 0x47, /* 10.5.3.9 */ GSM48_IE_GSM_LSA_ID = 0x48, /* 10.5.3.11 */ + GSM48_IE_GSM_EXT_QOS = 0x5C, /* 10.5.6.5B */ + GSM48_IE_GSM_EXT_PROTO_CONF_OPT = 0x7B, /* 10.5.6.3a */ /* Fake IEs that are not present on the Layer3 air interface, * but which we use to simplify internal APIs */ @@ -128,7 +142,7 @@ struct gsm48_ra_upd_ack { struct gsm48_ra_id ra_id; /* 10.5.5.15 */ uint8_t data[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t upd_result:4, force_stby:4; uint8_t ra_upd_timer; struct gsm48_ra_id ra_id; @@ -157,7 +171,7 @@ struct gsm48_attach_ack { struct gsm48_ra_id ra_id; /* 10.5.5.15 */ uint8_t data[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t force_stby:4, att_result:4; uint8_t ra_upd_timer; uint8_t radio_prio; @@ -175,7 +189,7 @@ struct gsm48_auth_ciph_req { ac_ref_nr:4; /* 10.5.5.19 */ uint8_t data[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t imeisv_req:4, ciph_alg:4; uint8_t ac_ref_nr:4, force_stby:4; uint8_t data[0]; @@ -189,7 +203,7 @@ struct gsm48_auth_ciph_resp { spare:4; uint8_t data[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t spare:4, ac_ref_nr:4; uint8_t data[0]; #endif @@ -280,17 +294,52 @@ enum gsm48_pdp_state { PDP_S_MODIFY_PENDING, }; -/* Table 10.5.155/3GPP TS 24.008 */ +/* TS 24.008 Table 10.5.155/3GPP */ enum gsm48_pdp_type_org { PDP_TYPE_ORG_ETSI = 0x00, PDP_TYPE_ORG_IETF = 0x01, + PDP_TYPE_ORG_EMPTY = 0x0f, }; enum gsm48_pdp_type_nr { PDP_TYPE_N_ETSI_RESERVED = 0x00, PDP_TYPE_N_ETSI_PPP = 0x01, PDP_TYPE_N_IETF_IPv4 = 0x21, PDP_TYPE_N_IETF_IPv6 = 0x57, + PDP_TYPE_N_IETF_IPv4v6 = 0x8D, }; +/* TS 24.008 10.5.6.4 "Packet data protocol address" value + * Note: This can be reused for 3GPP TS 29.060 7.7.27 "End User Address" + * with minor changes in the values, like spare being 1111 instead. +*/ +struct gsm48_pdp_address { +#if OSMO_IS_LITTLE_ENDIAN +uint8_t organization:4, /* enum gsm48_pdp_type_org */ + spare:4; /* 0000 */ +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ +uint8_t spare:4, organization:4; +#endif +uint8_t type; /* enum gsm48_pdp_type_nr */ + union { + /* PDP_TYPE_ORG_ETSI */ + union { + } etsi; + /* PDP_TYPE_ORG_IETF */ + union { + /* PDP_TYPE_N_IETF_IPv4 */ + uint32_t v4; + + /* PDP_TYPE_N_IETF_IPv6 */ + uint8_t v6[16]; + + /* PDP_TYPE_N_IETF_IPv4v6 */ + struct { + uint32_t v4; + uint8_t v6[16]; + } __attribute__ ((packed)) v4v6; + } ietf; + }; +} __attribute__ ((packed)); /* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ enum gsm48_qos_reliab_class { @@ -463,6 +512,3 @@ struct gsm48_qos { /* octet 16 */ uint8_t guar_bitrate_down_ext; }; - - -#endif /* _GSM48_GPRS_H */ diff --git a/include/osmocom/gsm/protocol/gsm_04_11.h b/include/osmocom/gsm/protocol/gsm_04_11.h index 31f25acb..90543020 100644 --- a/include/osmocom/gsm/protocol/gsm_04_11.h +++ b/include/osmocom/gsm/protocol/gsm_04_11.h @@ -62,6 +62,16 @@ enum gsm411_rp_ie { GSM411_IE_RP_CAUSE = 0x42, /* 8.2.5.4 */ }; +/* Sections 8.2.5.1 and 8.2.5.2 set limits on the length of an SMSC-address. + * The spec states these limits in terms of min and max values of the length + * octet in type 4 IEs SM-RP-OA and SM-RP-DA; these IE length limits translate + * into a minimum of 1 digit and a maximum of 20 digits. + */ +#define GSM411_SMSC_ADDR_MIN_OCTETS 2 +#define GSM411_SMSC_ADDR_MAX_OCTETS 11 +#define GSM411_SMSC_ADDR_MIN_DIGITS 1 +#define GSM411_SMSC_ADDR_MAX_DIGITS 20 + /* Chapter 8.2.5.4 Table 8.4 */ enum gsm411_rp_cause { /* valid only for MO */ diff --git a/include/osmocom/gsm/protocol/gsm_04_12.h b/include/osmocom/gsm/protocol/gsm_04_12.h index 3f34ee7f..17ac6454 100644 --- a/include/osmocom/gsm/protocol/gsm_04_12.h +++ b/include/osmocom/gsm/protocol/gsm_04_12.h @@ -23,7 +23,7 @@ struct gsm412_block_type { lpd : 2, spare : 1; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t spare:1, lpd:2, lb:1, seq_nr:4; #endif } __attribute__((packed)); @@ -37,7 +37,7 @@ struct gsm412_sched_msg { uint8_t cbsms_msg_map[6]; uint8_t data[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t type:2, beg_slot_nr:6; uint8_t spare2:1, spare1:1, end_slot_nr:6; uint8_t cbsms_msg_map[6]; diff --git a/include/osmocom/gsm/protocol/gsm_04_14.h b/include/osmocom/gsm/protocol/gsm_04_14.h index deb474ec..dddec519 100644 --- a/include/osmocom/gsm/protocol/gsm_04_14.h +++ b/include/osmocom/gsm/protocol/gsm_04_14.h @@ -30,7 +30,7 @@ struct gsm414_close_mslot_loop_cmd { loop_mech:3, tn:3; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t tn:3, loop_mech:3, chc:2; #endif } __attribute__((packed)); @@ -43,7 +43,7 @@ struct gsm414_close_mslot_loop_ack { chc:2, spare:2; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t spare:2, chc:2, loop_mech:3, err_ind:1; #endif } __attribute__((packed)); @@ -70,7 +70,7 @@ struct gsm414_gprs_test_mode_cmd { dl_tx_offset:3, _spare:4; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint16_t d:12, spare:3, l:1; @@ -86,7 +86,7 @@ struct gsm414_egprs_st_sb_loop_cmd { dl_tx_offset:3, m:1; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t m:1, dl_tx_offset:3, _spare:4; #endif } __attribute__((packed)); diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h index 1390f0e8..45396566 100644 --- a/include/osmocom/gsm/protocol/gsm_08_08.h +++ b/include/osmocom/gsm/protocol/gsm_08_08.h @@ -25,6 +25,10 @@ enum CELL_IDENT { CELL_IDENT_UTRAN_PLMN_LAC_RNC = 8, CELL_IDENT_UTRAN_RNC = 9, CELL_IDENT_UTRAN_LAC_RNC = 10, + CELL_IDENT_SAI = 11, + + /* Not in 03.03 nor 08.08. Place them > 0x0f (discr_id is 4 bits) */ + CELL_IDENT_WHOLE_GLOBAL_PS = 128, /* CGI + RAC, TS 48.018 8c.1.4.1.1 */ }; /* Keep this misnamed CELL_IDENT for API backwards compatibility (see OS#3124). */ #define CELL_IDENT_LAI_AND_LAC CELL_IDENT_LAI @@ -46,12 +50,12 @@ struct dtap_header { uint8_t link_id; /* Backward compatibility */ struct { #if OSMO_IS_LITTLE_ENDIAN - uint8_t dlci_cc:2, + uint8_t dlci_sapi:3, /* enum gsm0406_dlci_sapi */ dlci_spare:3, - dlci_sapi:3; /* enum gsm0406_dlc_sapi */ + dlci_cc:2; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ - uint8_t dlci_sapi:3, dlci_spare:3, dlci_cc:2; +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t dlci_cc:2, dlci_spare:3, dlci_sapi:3; #endif }; }; @@ -164,12 +168,15 @@ enum BSS_MAP_MSG_TYPE { BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION = 30, BSS_MAP_MSG_UPLINK_RQST = 31, BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE = 39, + BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_STATUS = 59, + BSS_MAP_MSG_VGCS_VBS_AREA_CELL_INFO = 60, BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION = 73, BSS_MAP_MSG_UPLINK_RELEASE_INDICATION = 74, BSS_MAP_MSG_UPLINK_REJECT_CMD = 75, BSS_MAP_MSG_UPLINK_RELEASE_CMD = 76, BSS_MAP_MSG_UPLINK_SEIZED_CMD = 77, BSS_MAP_MSG_VGCS_ADDL_INFO = 0x60, + BSS_MAP_MSG_VGCS_SMS = 0x61, BSS_MAP_MSG_NOTIFICATION_DATA = 0x62, BSS_MAP_MSG_UPLINK_APP_DATA = 0x63, @@ -262,7 +269,7 @@ enum GSM0808_IE_CODING { GSM0808_IE_SEGMENTATION = 79, GSM0808_IE_SERVICE_HANDOVER = 80, GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_UMTS = 81, - GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000= 82, + GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000 = 82, GSM0808_IE_RESERVED_5 = 65, GSM0808_IE_RESERVED_6 = 66, GSM0808_IE_GERAN_CLASSMARK = 0x53, @@ -325,12 +332,14 @@ enum GSM0808_IE_CODING { GSM0808_IE_PS_REGISTERED_OPERATOR = 0x99, GSM0808_IE_CS_REGISTERED_OPERATOR = 0x9a, - /* Osmocom extensions: */ + /* Osmocom and Themyscira extensions: */ GSM0808_IE_OSMO_OSMUX_SUPPORT = 0xf0, GSM0808_IE_OSMO_OSMUX_CID = 0xf1, + GSM0808_IE_THEMWI_RTP_EXTENSIONS = 0xf2, }; -/* 3GPP TS 48.008 3.2.3 Signalling Field Element Coding */ +/* 3GPP TS 48.008 3.2.3 Signalling Field Element Coding. + See also extra fields in 3.2.2.58 and 3.2.2.80 */ enum GSM0808_SIGNALLING_FIELD_ELEMENT_CODING { GSM0808_FE_IE_EXTRA_INFORMATION = 0x01, /*< 3.2.3.1 */ GSM0808_FE_IE_CURRENT_CHANNEL_TYPE_2 = 0x02, /*< 3.2.3.2 */ @@ -350,6 +359,8 @@ enum GSM0808_SIGNALLING_FIELD_ELEMENT_CODING { GSM0808_FE_IE_IRAT_MEASUREMENT_CONFIGURATION = 0x0f, /*< 3.2.3.16 */ GSM0808_FE_IE_SOURCE_CELL_ID = 0x10, /*< 3.2.3.17 */ GSM0808_FE_IE_IRAT_MEASUREMENT_CONFIGURATION_EXTENDED_E_ARFCNS = 0x11, /*< 3.2.3.18 */ + GSM0808_FE_IE_VGCS_TALKER_MODE = 0x6f, /*< 3.2.2.93 */ + GSM0808_FE_IE_LAST_USED_EUTRAN_PLMN_ID = 0x95, /*< 3.2.2.127 */ }; /* 3GPP TS 48.008 3.2.2.5 Cause */ @@ -436,13 +447,15 @@ enum gsm0808_chan_indicator { GSM0808_CHAN_SPEECH = 1, GSM0808_CHAN_DATA = 2, GSM0808_CHAN_SIGN = 3, + GSM0808_CHAN_SPEECH_CTM_TEXT_TELEPHONY = 4, }; /* GSM 08.08 3.2.2.11 Channel Type */ +#define GSM0808_DATA_FULL_RPREF GSM0808_DATA_FULL_PREF enum gsm0808_chan_rate_type_data { GSM0808_DATA_FULL_BM = 0x8, GSM0808_DATA_HALF_LM = 0x9, - GSM0808_DATA_FULL_RPREF = 0xa, + GSM0808_DATA_FULL_PREF = 0xa, GSM0808_DATA_HALF_PREF = 0xb, GSM0808_DATA_FULL_PREF_NO_CHANGE = 0x1a, GSM0808_DATA_HALF_PREF_NO_CHANGE = 0x1b, @@ -491,6 +504,42 @@ enum gsm0808_permitted_speech { GSM0808_PERM_HR6 = 0x45, /*!< OHR AMR */ }; +/* 3GPP TS 48.008 3.2.2.11 Channel Type + * Transparent: Data Rate */ +enum gsm0808_data_rate_transp { + GSM0808_DATA_RATE_TRANSP_32k0 = 0x3a, + GSM0808_DATA_RATE_TRANSP_28k8 = 0x39, + GSM0808_DATA_RATE_TRANSP_14k4 = 0x18, + GSM0808_DATA_RATE_TRANSP_9k6 = 0x10, + GSM0808_DATA_RATE_TRANSP_4k8 = 0x11, + GSM0808_DATA_RATE_TRANSP_2k4 = 0x12, + GSM0808_DATA_RATE_TRANSP_1k2 = 0x13, + GSM0808_DATA_RATE_TRANSP_600 = 0x14, + GSM0808_DATA_RATE_TRANSP_1200_75 = 0x15, +}; + +/* 3GPP TS 48.008 3.2.2.11 Channel Type + * Non-Transparent: Radio Interface Data Rate (preferred) */ +enum gsm0808_data_rate_non_transp { + GSM0808_DATA_RATE_NON_TRANSP_12000_6000 = 0x00, + GSM0808_DATA_RATE_NON_TRANSP_43k5 = 0x34, + GSM0808_DATA_RATE_NON_TRANSP_29k0 = 0x31, + GSM0808_DATA_RATE_NON_TRANSP_14k5 = 0x14, + GSM0808_DATA_RATE_NON_TRANSP_12k0 = 0x10, + GSM0808_DATA_RATE_NON_TRANSP_6k0 = 0x11, +}; + +/* 3GPP TS 48.008 3.2.2.11 Channel Type + * Non-Transparent: Allowed Radio Interface Data Rate (all possible allowed) */ +enum gsm0808_data_rate_allowed_r_if { + GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_43k5 = 0x40, + GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_32k0 = 0x20, + GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_29k0 = 0x10, + GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_14k5 = 0x08, + GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_12k0 = 0x02, + GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_6k0 = 0x01, +}; + extern const struct value_string gsm0808_permitted_speech_names[]; static inline const char *gsm0808_permitted_speech_name(enum gsm0808_permitted_speech val) { return get_value_string(gsm0808_permitted_speech_names, val); } @@ -509,6 +558,12 @@ enum gsm0808_speech_codec_type { GSM0808_SCT_CSD = 0xfd, /*!< CSData (see also TS 26.103) */ }; +/* Codec Extension (the real Codec Type follows in the next octet). + * This value is intentionally not included in gsm0808_speech_codec_type, + * because {enc,dec}_speech_codec() functions take care of the extended + * encoding internally. It shall not be used in struct gsm0808_speech_codec. */ +#define GSM0808_SCT_EXT 0x0f + extern const struct value_string gsm0808_speech_codec_type_names[]; static inline const char *gsm0808_speech_codec_type_name(enum gsm0808_speech_codec_type val) { return get_value_string(gsm0808_speech_codec_type_names, val); } @@ -533,11 +588,16 @@ enum gsm0808_paging_info { GSM0808_PAGINF_FOR_USSD = 0x02, }; -/*! 3GPP TS 48.008 3.2.2.104 Speech Codec */ +/*! 3GPP TS 48.008 3.2.2.104 Speech Codec. + * Valid if (fi || pi || pt) == true, otherwise ignore. */ struct gsm0808_speech_codec { + /*! Full IP: AoIP with compressed speech via RTP/UDP/IP. */ bool fi; + /*! PCMoIP: PCM over A-Interface via RTP/UPD/IP. */ bool pi; + /*! PCMoTDM: PCM over A-Interface with TDM as transport. */ bool pt; + /*! TFO (Inband Tandem Free Operation). Only valid if (pi || pt) == true. */ bool tf; /*! See enum gsm0808_speech_codec_type. */ uint8_t type; @@ -556,7 +616,44 @@ struct gsm0808_speech_codec { * * Default values for FR_AMR_WB, OFR_AMR_WB and OHR_AMR_WB: * See also: 3GPP TS 26.103, Table 5.7-1: Allowed Configurations - * for the Adaptive Multi-Rate - Wideband Codec Types */ + * for the Adaptive Multi-Rate - Wideband Codec Types + * + * This is a copy of 3GPP TS 28.062, Table 7.11.3.1.3-2: + * + * S0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + * 12,20 (x) x x x + * 10,20 x x x + * 7,95 x x x + * 7,40 x x x x + * 6,70 x x x x x x + * 5,90 x x x x x x x x x x + * 5,15 + * 4,75 x x x x x x x x x x + * + * OM F F F F F F F F F F F A F A F A + * + * HR Y Y Y Y Y Y Y Y Y + * FR Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y + * + * Each bit allows one Codec Configuration. + * E.g. when bit S3 is set, look at column labeled "3", and see that only 6,7k is active in this configuration; it is + * "F" forbidden to change in Optimisation Mode, "Y" HR AMR supports this mode, and "Y" FR AMR can also do it. + * + * This means that whichever configuration is chosen from S0 thru S15, there are never more than four rates active. + * + * The spec praises S1 as the most desired configuration: "because it leads in all call cases to TFO/TrFO compatible + * connections with optimal voice quality." (Since HR AMR supports up to 7.95k, it seems that S14 would be more optimal + * voice quality, but it is not marked as supported by HR AMR.) + * + * For FR_AMR below, the default of 0x57ff means: + * 0x57ff = 0101 0111 1111 1111 + * ^14 ^10 ^0 + * allow config 0 thru 10, and configs 12 and 14. + * + * For HR_AMR, drop all those where there is no "Y" in the HR row: + * 0x073f = 0000 0111 0011 1111 + * ^15 ^11 ^6 ^0 + */ enum gsm0808_speech_codec_defaults { GSM0808_SC_CFG_DEFAULT_FR_AMR = 0x57ff, GSM0808_SC_CFG_DEFAULT_HR_AMR = 0x073f, @@ -566,9 +663,12 @@ enum gsm0808_speech_codec_defaults { GSM0808_SC_CFG_DEFAULT_OHR_AMR_WB = 0x01, }; -/*! Default speech codec configurations broken down by reate. +/*! Default speech codec configurations broken down by rate. * See also: 3GPP TS 28.062, Table 7.11.3.1.3-2: Preferred Configurations for - * the Adaptive Multi-Rate Codec Types. */ + * the Adaptive Multi-Rate Codec Types. + * + * Set all Sn bits that have this rate listed as active. + */ enum gsm0808_speech_codec_rate_defaults { GSM0808_SC_CFG_DEFAULT_AMR_4_75 = 0xff03, GSM0808_SC_CFG_DEFAULT_AMR_5_15 = 0x0000, @@ -580,9 +680,12 @@ enum gsm0808_speech_codec_rate_defaults { GSM0808_SC_CFG_DEFAULT_AMR_12_2 = 0xc082 }; -/*! Single speech codec configurations broken down by reate. +/*! Single speech codec configurations broken down by rate. * See also: 3GPP TS 28.062, Table 7.11.3.1.3-2: Preferred Configurations for - * the Adaptive Multi-Rate Codec Types. */ + * the Adaptive Multi-Rate Codec Types. + * + * Set bit Sn (S0 = 0x01), where Sn is identified by a descriptive name. + */ enum gsm0808_speech_codec_rate { GSM0808_SC_CFG_AMR_4_75 = 0x0001, GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20 = 0x0002, @@ -594,6 +697,29 @@ enum gsm0808_speech_codec_rate { GSM0808_SC_CFG_AMR_12_2 = 0x0080, }; +/* Bit index of a mode as returned by gsm0808_amr_modes_from_cfg[]. + * Example: + * if (gsm0808_amr_modes_from_cfg[full_rate ? 1 : 0][9] & GSM0808_AMR_MODE_4_75) + * printf("S9 supports 4k75"); + */ +enum gsm0808_amr_mode { + GSM0808_AMR_MODE_4_75 = 0, + GSM0808_AMR_MODE_5_15, + GSM0808_AMR_MODE_5_90, + GSM0808_AMR_MODE_6_70, + GSM0808_AMR_MODE_7_40, + GSM0808_AMR_MODE_7_95, + GSM0808_AMR_MODE_10_2, + GSM0808_AMR_MODE_12_2, +}; +extern const struct value_string gsm0808_amr_mode_names[]; +static inline const char *gsm0808_amr_mode_name(enum gsm0808_amr_mode val) +{ + return get_value_string(gsm0808_amr_mode_names, val); +} + +extern const uint8_t gsm0808_amr_modes_from_cfg[2][16]; + /* 3GPP TS 48.008 3.2.2.103 Speech Codec List */ #define SPEECH_CODEC_MAXLEN 255 struct gsm0808_speech_codec_list { @@ -601,13 +727,32 @@ struct gsm0808_speech_codec_list { uint8_t len; }; +/* 3GPP TS 48.008 3.2.2.11 Channel Type + * Asymmetry Preference (used for data, non-transparent service) */ +enum gsm0808_channel_type_asym_pref { + GSM0808_CT_ASYM_PREF_NOT_APPLICABLE = 0, + GSM0808_CT_ASYM_PREF_UL = 1, + GSM0808_CT_ASYM_PREF_DL = 2, + GSM0808_CT_ASYM_PREF_SPARE = 3, +}; + /* 3GPP TS 48.008 3.2.2.11 Channel Type */ #define CH_TYPE_PERM_SPCH_MAXLEN 9 struct gsm0808_channel_type { uint8_t ch_indctr; uint8_t ch_rate_type; + + /* Speech only */ uint8_t perm_spch[CH_TYPE_PERM_SPCH_MAXLEN]; unsigned int perm_spch_len; + + /* Data only */ + bool data_transparent; + uint8_t data_rate; + bool data_rate_allowed_is_set; + uint8_t data_rate_allowed; + bool data_asym_pref_is_set; + enum gsm0808_channel_type_asym_pref data_asym_pref; }; /* 3GPP TS 48.008 3.2.2.10 Encryption Information */ @@ -671,7 +816,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 da55a8d9..13e84bad 100644 --- a/include/osmocom/gsm/protocol/gsm_08_58.h +++ b/include/osmocom/gsm/protocol/gsm_08_58.h @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * */ #pragma once @@ -33,6 +29,7 @@ /* Channel Number 9.3.1 */ union abis_rsl_chan_nr { + struct { #if OSMO_IS_BIG_ENDIAN uint8_t cbits:5, tn:3; @@ -40,7 +37,8 @@ union abis_rsl_chan_nr { uint8_t tn:3, cbits:5; #endif - uint8_t chan_nr; + } __attribute__ ((packed)); + uint8_t chan_nr; } __attribute__ ((packed)); #define ABIS_RSL_CHAN_NR_CBITS_Bm_ACCHs 0x01 #define ABIS_RSL_CHAN_NR_CBITS_Lm_ACCHs(ss) (0x02 + (ss)) @@ -53,8 +51,13 @@ union abis_rsl_chan_nr { #define ABIS_RSL_CHAN_NR_CBITS_OSMO_CBCH4 0x19 /*< non-standard, for CBCH/SDCCH4 */ #define ABIS_RSL_CHAN_NR_CBITS_OSMO_CBCH8 0x1a /*< non-standard, for CBCH/SDCCH8 */ +/* non-standard, Osmocom specific Bm/Lm equivalents for VAMOS */ +#define ABIS_RSL_CHAN_NR_CBITS_OSMO_VAMOS_Bm_ACCHs 0x1d /*< VAMOS TCH/F */ +#define ABIS_RSL_CHAN_NR_CBITS_OSMO_VAMOS_Lm_ACCHs(ss) (0x1e + (ss)) /*< VAMOS TCH/H */ + /* Link Identifier 9.3.2 */ union abis_rsl_link_id { + struct { #if OSMO_IS_BIG_ENDIAN uint8_t cbits:2, na:1, @@ -66,7 +69,8 @@ union abis_rsl_link_id { na:1, cbits:2; #endif - uint8_t link_id; + } __attribute__ ((packed)); + uint8_t link_id; } __attribute__ ((packed)); #define ABIS_RSL_LINK_ID_CBITS_FACCH_SDCCH 0x00 #define ABIS_RSL_LINK_ID_CBITS_SACCH 0x01 @@ -116,6 +120,33 @@ struct abis_rsl_cchan_hdr { uint8_t data[0]; /*!< message payload data */ } __attribute__ ((packed)); +/* Osmocom specific IE to negotiate repeated ACCH capabilities */ +struct abis_rsl_osmo_rep_acch_cap { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t dl_facch_cmd:1, + dl_facch_all:1, + dl_sacch:1, + ul_sacch:1, + rxqual:3, + reserved:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t reserved:1, rxqual:3, ul_sacch:1, dl_sacch:1, dl_facch_all:1, dl_facch_cmd:1; +#endif +} __attribute__ ((packed)); + +/* Osmocom specific IE to negotiate temporary overpower of ACCH channels */ +struct abis_rsl_osmo_temp_ovp_acch_cap { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t overpower_db:3, + rxqual:3, + facch_enable:1, + sacch_enable:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t sacch_enable:1, facch_enable:1, rxqual:3, overpower_db:3; +#endif +} __attribute__ ((packed)); /* Chapter 9.1 */ /* RSL Message Discriminator: RLL */ @@ -337,6 +368,13 @@ enum abis_rsl_ie { RSL_IE_SIEMENS_HIGHEST_RATE = 0x4e, RSL_IE_SIEMENS_SUGGESTED_RATE = 0x4f, + /* Osmocom specific */ + RSL_IE_OSMO_REP_ACCH_CAP = 0x60, + RSL_IE_OSMO_TRAINING_SEQUENCE = 0x61, + RSL_IE_OSMO_TEMP_OVP_ACCH_CAP = 0x62, + RSL_IE_OSMO_OSMUX_CID = 0x63, + RSL_IE_OSMO_RTP_EXTENSIONS = 0x64, + /* ip.access */ RSL_IE_IPAC_SRTP_CONFIG = 0xe0, RSL_IE_IPAC_PROXY_UDP = 0xe1, @@ -353,9 +391,9 @@ enum abis_rsl_ie { RSL_IE_IPAC_RTP_CSD_FMT = 0xf9, RSL_IE_IPAC_RTP_JIT_BUF = 0xfa, RSL_IE_IPAC_RTP_COMPR = 0xfb, - RSL_IE_IPAC_RTP_PAYLOAD2= 0xfc, + RSL_IE_IPAC_RTP_PAYLOAD2 = 0xfc, RSL_IE_IPAC_RTP_MPLEX = 0xfd, - RSL_IE_IPAC_RTP_MPLEX_ID= 0xfe, + RSL_IE_IPAC_RTP_MPLEX_ID = 0xfe, }; /* Ericsson specific IEs, clash with above partially, so they're not @@ -385,10 +423,12 @@ enum abis_rsl_ie { enum { IPAC_UNWEIGHTED_AVE = 0, IPAC_WEIGHTED_AVE, - IPAC_MEDIAN_AVE + IPAC_MEDIAN_AVE, + /* EWMA is an Osmocom specific extension */ + IPAC_OSMO_EWMA_AVE, }; -/* IPAC MEAS_PREPROC AVERAGING PARAMID */ +/* IPAC MEAS_PREPROC AVERAGING PARAM ID */ enum { IPAC_RXLEV_AVE = 0, IPAC_RXQUAL_AVE, @@ -431,6 +471,11 @@ enum { #define RSL_CHAN_OSMO_CBCH4 0xc8 /*< non-standard, for CBCH/SDCCH4 */ #define RSL_CHAN_OSMO_CBCH8 0xd0 /*< non-standard, for CBCH/SDCCH8 */ +/* non-standard, Osmocom specific Bm/Lm equivalents for VAMOS */ +#define RSL_CHAN_OSMO_VAMOS_Bm_ACCHs 0xe8 /* VAMOS TCH/F */ +#define RSL_CHAN_OSMO_VAMOS_Lm_ACCHs 0xf0 /* VAMOS TCH/H */ +#define RSL_CHAN_OSMO_VAMOS_MASK 0xe0 /* VAMOS TCH/{F,H} */ + /* Chapter 9.3.3 */ #define RSL_ACT_TYPE_INITIAL 0x00 #define RSL_ACT_TYPE_REACT 0x80 @@ -456,34 +501,66 @@ enum rsl_cmod_spd { RSL_CMOD_SPD_DATA = 0x02, RSL_CMOD_SPD_SIGN = 0x03, }; -#define RSL_CMOD_CRT_SDCCH 0x01 -#define RSL_CMOD_CRT_TCH_Bm 0x08 /* full-rate */ -#define RSL_CMOD_CRT_TCH_Lm 0x09 /* half-rate */ -/* FIXME: More CRT types */ -/* Speech */ -#define RSL_CMOD_SP_GSM1 0x01 -#define RSL_CMOD_SP_GSM2 0x11 -#define RSL_CMOD_SP_GSM3 0x21 -/* non-transparent data */ -#define RSL_CMOD_CSD_NT_43k5 0x74 -#define RSL_CMOD_CSD_NT_28k8 0x71 -#define RSL_CMOD_CSD_NT_14k5 0x58 -#define RSL_CMOD_CSD_NT_12k0 0x50 -#define RSL_CMOD_CSD_NT_6k0 0x51 +/*! Channel rate and type */ +enum rsl_cmod_crt { + RSL_CMOD_CRT_SDCCH = 0x01, + RSL_CMOD_CRT_TCH_Bm = 0x08, /* full-rate */ + RSL_CMOD_CRT_TCH_Lm = 0x09, /* half-rate */ + RSL_CMOD_CRT_TCH_BI_Bm = 0x0a, /* full-rate: bi-directional (multislot) */ + RSL_CMOD_CRT_TCH_UNI_Bm = 0x1a, /* full-rate: uni-directional (multislot) */ + RSL_CMOD_CRT_TCH_GROUP_Bm = 0x18, /* full-rate: group call channel */ + RSL_CMOD_CRT_TCH_GROUP_Lm = 0x19, /* half-rate: group call channel */ + RSL_CMOD_CRT_TCH_BCAST_Bm = 0x28, /* full-rate: broadcast call channel */ + RSL_CMOD_CRT_TCH_BCAST_Lm = 0x29, /* half-rate: broadcast call channel */ + RSL_CMOD_CRT_OSMO_TCH_VAMOS_Bm = 0x88, /* full-rate in VAMOS mode */ + RSL_CMOD_CRT_OSMO_TCH_VAMOS_Lm = 0x89, /* half-rate in VAMOS mode */ +}; +/*! Speech */ +enum rsl_cmod_sp { + RSL_CMOD_SP_GSM1 = 0x01, + RSL_CMOD_SP_GSM2 = 0x11, + RSL_CMOD_SP_GSM3 = 0x21, + RSL_CMOD_SP_GSM4 = 0x31, + RSL_CMOD_SP_GSM5 = 0x09, + RSL_CMOD_SP_GSM6 = 0x0d, +}; +/*! Non-transparent data */ +enum rsl_cmod_csd_nt { + RSL_CMOD_CSD_NTA_43k5_14k5 = 0x61, /* asymmetric 43.5 kbit/s (DL) + 14.5 kbit/s (UL) */ + RSL_CMOD_CSD_NTA_29k0_14k5 = 0x62, /* asymmetric 29.0 kbit/s (DL) + 14.5 kbit/s (UL) */ + RSL_CMOD_CSD_NTA_43k5_29k0 = 0x63, /* asymmetric 43.5 kbit/s (DL) + 29.0 kbit/s (UL) */ + RSL_CMOD_CSD_NTA_14k5_43k5 = 0x69, /* asymmetric 14.5 kbit/s (DL) + 43.5 kbit/s (UL) */ + RSL_CMOD_CSD_NTA_14k5_29k0 = 0x6a, /* asymmetric 14.5 kbit/s (DL) + 29.0 kbit/s (UL) */ + RSL_CMOD_CSD_NTA_29k0_43k5 = 0x6b, /* asymmetric 29.0 kbit/s (DL) + 43.5 kbit/s (UL) */ + RSL_CMOD_CSD_NT_43k5 = 0x74, + RSL_CMOD_CSD_NT_28k8 = 0x71, + RSL_CMOD_CSD_NT_14k5 = 0x58, + RSL_CMOD_CSD_NT_12k0 = 0x50, + RSL_CMOD_CSD_NT_6k0 = 0x51, +}; /* legacy #defines with wrong name */ #define RSL_CMOD_SP_NT_14k5 RSL_CMOD_CSD_NT_14k5 #define RSL_CMOD_SP_NT_12k0 RSL_CMOD_CSD_NT_12k0 #define RSL_CMOD_SP_NT_6k0 RSL_CMOD_CSD_NT_6k0 -/* transparent data */ -#define RSL_CMOD_CSD_T_32000 0x38 -#define RSL_CMOD_CSD_T_29000 0x39 -#define RSL_CMOD_CSD_T_14400 0x18 -#define RSL_CMOD_CSD_T_9600 0x10 -#define RSL_CMOD_CSD_T_4800 0x11 -#define RSL_CMOD_CSD_T_2400 0x12 -#define RSL_CMOD_CSD_T_1200 0x13 -#define RSL_CMOD_CSD_T_600 0x14 -#define RSL_CMOD_CSD_T_1200_75 0x15 +#define RSL_CMOD_CSD_T_32000 RSL_CMOD_CSD_T_32k0 +#define RSL_CMOD_CSD_T_29000 RSL_CMOD_CSD_T_29k0 +#define RSL_CMOD_CSD_T_14400 RSL_CMOD_CSD_T_14k4 +#define RSL_CMOD_CSD_T_9600 RSL_CMOD_CSD_T_9k6 +#define RSL_CMOD_CSD_T_4800 RSL_CMOD_CSD_T_4k8 +#define RSL_CMOD_CSD_T_2400 RSL_CMOD_CSD_T_2k4 +#define RSL_CMOD_CSD_T_1200 RSL_CMOD_CSD_T_1k2 +/*! Transparent data */ +enum rsl_cmod_csd_t { + RSL_CMOD_CSD_T_32k0 = 0x38, + RSL_CMOD_CSD_T_29k0 = 0x39, + RSL_CMOD_CSD_T_14k4 = 0x18, + RSL_CMOD_CSD_T_9k6 = 0x10, + RSL_CMOD_CSD_T_4k8 = 0x11, + RSL_CMOD_CSD_T_2k4 = 0x12, + RSL_CMOD_CSD_T_1k2 = 0x13, + RSL_CMOD_CSD_T_600 = 0x14, + RSL_CMOD_CSD_T_1200_75 = 0x15, +}; /*! RSL Channel Identification IE (Chapter 9.3.5) */ struct rsl_ie_chan_ident { @@ -542,6 +619,9 @@ struct rsl_ie_chan_ident { #define RSL_ERR_CCCH_OVERLOAD 0x23 #define RSL_ERR_ACCH_OVERLOAD 0x24 #define RSL_ERR_PROCESSOR_OVERLOAD 0x25 +#define RSL_ERR_BTS_NOT_EQUIPPED 0x27 +#define RSL_ERR_REMOTE_TRANSC_FAIL 0x28 +#define RSL_ERR_NOTIFICATION_OVERFL 0x29 #define RSL_ERR_RES_UNAVAIL 0x2f /* service or option not available */ #define RSL_ERR_TRANSC_UNAVAIL 0x30 @@ -598,7 +678,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; @@ -606,7 +686,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)); @@ -624,6 +704,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 @@ -669,10 +766,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 { @@ -740,8 +837,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, @@ -749,13 +852,67 @@ struct ipac_preproc_ave_cfg { reserved:1; uint8_t h_reqt:5, ave_method:3; + uint8_t params[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t reserved:1, param_id:2, h_reqave:5; uint8_t ave_method:3, h_reqt:5; + uint8_t params[0]; #endif }__attribute__ ((packed)); + +struct osmo_preproc_ave_cfg_field { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t h_reqave:5, + ave_enabled:1, + reserved:2; + uint8_t h_reqt:5, + ave_method:3; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t reserved:2, ave_enabled:1, h_reqave:5; + uint8_t ave_method:3, h_reqt:5; +#endif +}__attribute__ ((packed)); +/* Value of TLV IE RSL_IPAC_EIE_OSMO_MEAS_AVG_CFG: */ +struct osmo_preproc_ave_cfg { + struct osmo_preproc_ave_cfg_field ci_fr; + struct osmo_preproc_ave_cfg_field ci_hr; + struct osmo_preproc_ave_cfg_field ci_amr_fr; + struct osmo_preproc_ave_cfg_field ci_amr_hr; + struct osmo_preproc_ave_cfg_field ci_sdcch; + struct osmo_preproc_ave_cfg_field ci_gprs; + uint8_t params[0]; /* Contains params for each above, appended one after the other */ +}__attribute__ ((packed)); + +/*! MS/BS Power Control Thresholds (RSL_IPAC_EIE_MS_PWR_CTL) */ +struct ipac_preproc_pc_thresh { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t l_rxlev:6, reserved_l_rxlev:2; + uint8_t u_rxlev:6, reserved_u_rxlev:2; + uint8_t u_rxqual:3, reserved_u_rxqual:1, + l_rxqual:3, reserved_l_rxqual:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t reserved_l_rxlev:2, l_rxlev:6; + uint8_t reserved_u_rxlev:2, u_rxlev:6; + uint8_t reserved_l_rxqual:1, l_rxqual:3, reserved_u_rxqual:1, u_rxqual:3; +#endif +}__attribute__ ((packed)); + +/*! Osmocom extension for: MS/BS Power Control Thresholds (RSL_IPAC_EIE_OSMO_MS_PWR_CTL) */ +struct osmo_preproc_pc_thresh { + /* Carrier-to-Interference (C/I), in dB: */ + int8_t l_ci_fr; int8_t u_ci_fr; /* FR/EFR */ + int8_t l_ci_hr; int8_t u_ci_hr; /* HR */ + int8_t l_ci_amr_fr; int8_t u_ci_amr_fr; /* AMR FR */ + int8_t l_ci_amr_hr; int8_t u_ci_amr_hr; /* AMR HR */ + int8_t l_ci_sdcch; int8_t u_ci_sdcch; /* SDCCH */ + int8_t l_ci_gprs; int8_t u_ci_gprs; /* GPRS */ +}__attribute__ ((packed)); + +/*! Handover Thresholds */ struct ipac_preproc_ho_thresh { #if OSMO_IS_LITTLE_ENDIAN uint8_t l_rxlev_ul_h:6, @@ -773,7 +930,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; @@ -783,6 +940,60 @@ struct ipac_preproc_ho_thresh { #endif }__attribute__ ((packed)); +/*! PC Threshold Comparators (RSL_IPAC_EIE_PC_THRESH_COMP) */ +struct ipac_preproc_pc_comp { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t p1:5, reserved_p1:3; + uint8_t n1:5, reserved_n1:3; + uint8_t p2:5, reserved_p2:3; + uint8_t n2:5, reserved_n2:3; + uint8_t p3:5, reserved_p3:3; + uint8_t n3:5, reserved_n3:3; + uint8_t p4:5, reserved_p4:3; + uint8_t n4:5, reserved_n4:3; + uint8_t pc_interval:5, reserved_pc:3; + uint8_t red_step_size:4, inc_step_size:4; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t reserved_p1:3, p1:5; + uint8_t reserved_n1:3, n1:5; + uint8_t reserved_p2:3, p2:5; + uint8_t reserved_n2:3, n2:5; + uint8_t reserved_p3:3, p3:5; + uint8_t reserved_n3:3, n3:5; + uint8_t reserved_p4:3, p4:5; + uint8_t reserved_n4:3, n4:5; + uint8_t reserved_pc:3, pc_interval:5; + uint8_t inc_step_size:4, red_step_size:4; +#endif +}__attribute__ ((packed)); + +/*! Osmocom extension for: PC Threshold Comparators (RSL_IPAC_EIE_OSMO_PC_THRESH_COMP) */ +struct ipac_preproc_pc_comp_field { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t lower_p:5, reserved_lower_p:3; + uint8_t lower_n:5, reserved_lower_n:3; + uint8_t upper_p:5, reserved_upper_p:3; + uint8_t upper_n:5, reserved_upper_n:3; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t reserved_lower_p:3, lower_p:5; + uint8_t reserved_lower_n:3, lower_n:5; + uint8_t reserved_upper_p:3, upper_p:5; + uint8_t reserved_upper_n:3, upper_n:5; +#endif +}__attribute__ ((packed)); +struct osmo_preproc_pc_comp { + /* Used for Carrier-to-Interference (C/I), in dB: */ + struct ipac_preproc_pc_comp_field ci_fr; + struct ipac_preproc_pc_comp_field ci_hr; + struct ipac_preproc_pc_comp_field ci_amr_fr; + struct ipac_preproc_pc_comp_field ci_amr_hr; + struct ipac_preproc_pc_comp_field ci_sdcch; + struct ipac_preproc_pc_comp_field ci_gprs; +}__attribute__ ((packed)); + +/*! HO Threshold Comparators */ struct ipac_preproc_ho_comp { #if OSMO_IS_LITTLE_ENDIAN uint8_t p5:5, @@ -806,7 +1017,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; @@ -829,7 +1040,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 @@ -844,7 +1055,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; @@ -857,7 +1068,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)); @@ -873,4 +1084,18 @@ struct ipac_preproc_cfg { struct ipac_preproc_ho_ctl_param ho_ctl_param; }; +struct rsl_l1_info { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t reserved:1, + srr_sro:1, + fpc_epc:1, + ms_pwr:5; + uint8_t ta; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t ms_pwr:5, fpc_epc:1, srr_sro:1, reserved:1; + uint8_t ta; +#endif +} __attribute__ ((packed)); + /*! @} */ diff --git a/include/osmocom/gsm/protocol/gsm_09_02.h b/include/osmocom/gsm/protocol/gsm_09_02.h index 0b54fb74..4d5ff13c 100644 --- a/include/osmocom/gsm/protocol/gsm_09_02.h +++ b/include/osmocom/gsm/protocol/gsm_09_02.h @@ -1,8 +1,7 @@ /*! \file gsm_09_02.h * GSM TS 09.02 definitions (MAP). */ -#ifndef PROTO_GSM_09_02_H -#define PROTO_GSM_09_02_H +#pragma once /* Section 17.7.4 */ /* SS-Status */ @@ -134,5 +133,3 @@ #define GSM0902_TS_CODE_PLMN_SPECIFIC_TS_C 0xDC #define GSM0902_TS_CODE_PLMN_SPECIFIC_TS_D 0xDD #define GSM0902_TS_CODE_PLMN_SPECIFIC_TS_E 0xDE - -#endif /* PROTO_GSM_09_02_H */ diff --git a/include/osmocom/gsm/protocol/gsm_12_21.h b/include/osmocom/gsm/protocol/gsm_12_21.h index 86d12ea7..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, @@ -511,6 +508,7 @@ enum abis_nm_attr { /* osmocom (osmo-bts) specific attributes, used in combination * with the "org.osmocom" manufacturer identification */ + NM_ATT_OSMO_NS_LINK_CFG = 0xfd, /* osmocom version supports IPv4 & IPv6 in difference to IPACC */ NM_ATT_OSMO_REDUCEPOWER = 0xfe, /* TLV_TYPE_TV */ }; #define NM_ATT_BS11_FILE_DATA NM_ATT_EVENT_TYPE @@ -525,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, @@ -563,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 { @@ -773,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), @@ -788,6 +882,69 @@ enum ipac_bcch_info_type { IPAC_BINF_CELL_ALLOC = (1 << 2), }; +/*! ip.access NM_ATT_IPACC_NS_CFG value */ +struct abis_nm_ipacc_att_ns_cfg { + uint8_t un_blocking_timer; /* (un)blocking Timer (Tns-block) timeout */ + uint8_t un_blocking_retries; /* (un)blocking Timer (Tns-block) number of retries */ + uint8_t reset_timer; /* Reset Timer (Tns-reset) timeout */ + uint8_t reset_retries; /* Reset Timer (Tns-reset) number of retries */ + uint8_t test_timer; /* Test Timer (Tns-test) timeout */ + uint8_t alive_timer; /* Alive Timer (Tns-alive) timeout */ + uint8_t alive_retries; /* Alive Timer (Tns-alive) number of retries */ +} __attribute__((packed)); + +/*! ip.access NM_ATT_IPACC_BSSGP_CFG value */ +struct abis_nm_ipacc_att_bssgp_cfg { + uint8_t t1_s; /* blocking timer (T1) */ + uint8_t t1_blocking_retries; /* blocking retries */ + uint8_t t1_unblocking_retries; /* unblocking retries */ + uint8_t t2_s; /* reset timer (T2) */ + uint8_t t2_retries; /* reset retries */ + uint8_t t3_100ms; /* suspend timer (T3) in 100ms */ + uint8_t t3_retries; /* suspend retries */ + uint8_t t4_100ms; /* resume timer (T4) in 100ms */ + uint8_t t4_retries; /* resume retries */ + uint8_t t5_s; /* capability update timer (T5) */ + uint8_t t5_retries; /* capability update retries */ +} __attribute__((packed)); + +/*! ip.access NM_ATT_IPACC_RLC_CFG value */ +struct abis_nm_ipacc_att_rlc_cfg { + uint8_t t3142; + uint8_t t3169; + uint8_t t3191; + uint8_t t3193_10ms; + uint8_t t3195; + uint8_t n3101; + uint8_t n3103; + uint8_t n3105; + uint8_t rlc_cv_countdown; +} __attribute__((packed)); + +/*! ip.access NM_ATT_IPACC_RLC_CFG_2 value */ +struct abis_nm_ipacc_att_rlc_cfg_2 { + /* T downlink TBF extension (0..500, network order) */ + uint16_t t_dl_tbf_ext_10ms; + /* T uplink TBF extension (0..500, network order) */ + uint16_t t_ul_tbf_ext_10ms; + /* Initial CS to use: CS1 -> 1, CS2 -> 2, CS3 -> 3, CS4 -> 4 */ + uint8_t initial_cs; +} __attribute__((packed)); + +/*! ip.access NM_ATT_IPACC_RLC_CFG_3 value */ +struct abis_nm_ipacc_att_rlc_cfg_3 { + /* Initial MCS to use when EGPRS is used: + * MCS1 -> 1, MCS2 -> 2, ..., MCS9 -> 9 */ + uint8_t initial_mcs; +} __attribute__((packed)); + +/*! Osmocom NSVC address type for NM_ATT_OSMO_NS_LINK_CFG */ +enum osmo_oml_nsvc_address_type { + OSMO_NSVC_ADDR_UNSPEC = 0x00, + OSMO_NSVC_ADDR_IPV4 = 0x04, + OSMO_NSVC_ADDR_IPV6 = 0x29, +}; + /*! 3GPP TS 52.021 §9.4.62 SW Description */ struct abis_nm_sw_desc { uint8_t file_id[UINT8_MAX]; diff --git a/include/osmocom/gsm/protocol/gsm_23_032.h b/include/osmocom/gsm/protocol/gsm_23_032.h new file mode 100644 index 00000000..6eb65ca2 --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_23_032.h @@ -0,0 +1,252 @@ +/*! \defgroup gad 3GPP TS 23.032 GAD: Universal Geographical Area Description. + * @{ + * \file gsm_23_032.h + */ +/* + * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * + * All Rights Reserved + * + * Author: Neels Hofmeyr <neels@hofmeyr.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#pragma once + +#include <stdint.h> +#include <osmocom/core/endian.h> + +enum gad_type { + /*! Ellipsoid point */ + GAD_TYPE_ELL_POINT = 0, + /*! Ellipsoid point with uncertainty circle. */ + GAD_TYPE_ELL_POINT_UNC_CIRCLE = 1, + /*! Ellipsoid point with uncertainty ellipse. */ + GAD_TYPE_ELL_POINT_UNC_ELLIPSE = 3, + GAD_TYPE_POLYGON = 5, + /*! Ellipsoid point with altitude. */ + GAD_TYPE_ELL_POINT_ALT = 8, + /*! Ellipsoid point with altitude and uncertainty ellipsoid. */ + GAD_TYPE_ELL_POINT_ALT_UNC_ELL = 9, + /*! Ellipsoid arc */ + GAD_TYPE_ELL_ARC = 10, + /*! High accuracy ellipsoid point with uncertainty ellipse. */ + GAD_TYPE_HA_ELL_POINT_UNC_ELLIPSE = 11, + /*! High accuracy ellipsoid point with altitude and uncertainty ellipsoid. */ + GAD_TYPE_HA_ELL_POINT_ALT_UNC_ELL = 12, +}; + +struct gad_raw_head { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t spare:4, + type:4; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t type:4, spare:4; +#endif +} __attribute__ ((packed)); + +struct gad_raw_ell_point { + struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT */ + uint8_t lat[3]; + uint8_t lon[3]; +} __attribute__ ((packed)); + +struct gad_raw_ell_point_unc_circle { +#if OSMO_IS_LITTLE_ENDIAN + struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_UNC_CIRCLE */ + uint8_t lat[3]; + uint8_t lon[3]; + uint8_t unc:7, + spare2:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + struct gad_raw_head h; + uint8_t lat[3]; + uint8_t lon[3]; + uint8_t spare2:1, unc:7; +#endif +} __attribute__ ((packed)); + +struct gad_raw_ell_point_unc_ellipse { +#if OSMO_IS_LITTLE_ENDIAN + struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_UNC_ELLIPSE */ + uint8_t lat[3]; + uint8_t lon[3]; + uint8_t unc_semi_major:7, + spare1:1; + uint8_t unc_semi_minor:7, + spare2:1; + uint8_t major_ori; + uint8_t confidence:7, + spare3:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + struct gad_raw_head h; + uint8_t lat[3]; + uint8_t lon[3]; + uint8_t spare1:1, unc_semi_major:7; + uint8_t spare2:1, unc_semi_minor:7; + uint8_t major_ori; + uint8_t spare3:1, confidence:7; +#endif +} __attribute__ ((packed)); + +struct gad_raw_polygon { + struct { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t num_points:4; + uint8_t type:4; /*!< type = GAD_TYPE_POLYGON */ +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t type:4, num_points:4; +#endif + } h; + struct { + uint8_t lat[3]; + uint8_t lon[3]; + } point[15]; +} __attribute__ ((packed)); + +struct gad_raw_ell_point_alt { + struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_ALT */ + uint8_t lat[3]; + uint8_t lon[3]; + uint8_t alt[2]; +} __attribute__ ((packed)); + +struct gad_raw_ell_point_alt_unc_ell { +#if OSMO_IS_LITTLE_ENDIAN + struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_ALT_UNC_ELL */ + uint8_t lat[3]; + uint8_t lon[3]; + uint8_t alt[2]; + uint8_t unc_semi_major:7, + spare1:1; + uint8_t unc_semi_minor:7, + spare2:1; + uint8_t major_ori; + uint8_t unc_alt:7, + spare3:1; + uint8_t confidence:7, + spare4:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + struct gad_raw_head h; + uint8_t lat[3]; + uint8_t lon[3]; + uint8_t alt[2]; + uint8_t spare1:1, unc_semi_major:7; + uint8_t spare2:1, unc_semi_minor:7; + uint8_t major_ori; + uint8_t spare3:1, unc_alt:7; + uint8_t spare4:1, confidence:7; +#endif +} __attribute__ ((packed)); + +struct gad_raw_ell_arc { +#if OSMO_IS_LITTLE_ENDIAN + struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_ARC */ + uint8_t lat[3]; + uint8_t lon[3]; + uint8_t inner_r[2]; + uint8_t unc_r:7, + spare1:1; + uint8_t ofs_angle; + uint8_t incl_angle; + uint8_t confidence:7, + spare2:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + struct gad_raw_head h; + uint8_t lat[3]; + uint8_t lon[3]; + uint8_t inner_r[2]; + uint8_t spare1:1, unc_r:7; + uint8_t ofs_angle; + uint8_t incl_angle; + uint8_t spare2:1, confidence:7; +#endif +} __attribute__ ((packed)); + +struct gad_raw_ha_ell_point_unc_ell { +#if OSMO_IS_LITTLE_ENDIAN + struct gad_raw_head h; /*!< type = GAD_TYPE_HA_ELL_POINT_UNC_ELLIPSE */ + uint8_t lat[4]; + uint8_t lon[4]; + uint8_t alt[3]; + uint8_t unc_semi_major; + uint8_t unc_semi_minor; + uint8_t major_ori; + uint8_t confidence:7, + spare1:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + struct gad_raw_head h; + uint8_t lat[4]; + uint8_t lon[4]; + uint8_t alt[3]; + uint8_t unc_semi_major; + uint8_t unc_semi_minor; + uint8_t major_ori; + uint8_t spare1:1, confidence:7; +#endif +} __attribute__ ((packed)); + +struct gad_raw_ha_ell_point_alt_unc_ell { +#if OSMO_IS_LITTLE_ENDIAN + struct gad_raw_head h; /*!< type = GAD_TYPE_HA_ELL_POINT_ALT_UNC_ELL */ + uint8_t lat[4]; + uint8_t lon[4]; + uint8_t alt[3]; + uint8_t unc_semi_major; + uint8_t unc_semi_minor; + uint8_t major_ori; + uint8_t h_confidence:7, + spare1:1; + uint8_t unc_alt; + uint8_t v_confidence:7, + spare2:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + struct gad_raw_head h; + uint8_t lat[4]; + uint8_t lon[4]; + uint8_t alt[3]; + uint8_t unc_semi_major; + uint8_t unc_semi_minor; + uint8_t major_ori; + uint8_t spare1:1, h_confidence:7; + uint8_t unc_alt; + uint8_t spare2:1, v_confidence:7; +#endif +} __attribute__ ((packed)); + +/*! GAD PDU in network-byte-order according to 3GPP TS 23.032 GAD: Universal Geographical Area Description. */ +union gad_raw { + struct gad_raw_head h; + struct gad_raw_ell_point ell_point; + struct gad_raw_ell_point_unc_circle ell_point_unc_circle; + struct gad_raw_ell_point_unc_ellipse ell_point_unc_ellipse; + struct gad_raw_polygon polygon; + struct gad_raw_ell_point_alt ell_point_alt; + struct gad_raw_ell_point_alt_unc_ell ell_point_alt_unc_ell; + struct gad_raw_ell_arc ell_arc; + struct gad_raw_ha_ell_point_unc_ell ha_ell_point_unc_ell; + struct gad_raw_ha_ell_point_alt_unc_ell ha_ell_point_alt_unc_ell; +} __attribute__ ((packed)); + +/*! @} */ diff --git a/include/osmocom/gsm/protocol/gsm_23_041.h b/include/osmocom/gsm/protocol/gsm_23_041.h index e726cff2..2a2b006f 100644 --- a/include/osmocom/gsm/protocol/gsm_23_041.h +++ b/include/osmocom/gsm/protocol/gsm_23_041.h @@ -2,6 +2,16 @@ #include <osmocom/core/endian.h> +/* Section 9.3.24: Warning-Type */ +enum gsm23041_warning_type_value { + CBS_ETWS_WARN_TYPE_EARTHQUAKE = 0, + CBS_ETWS_WARN_TYPE_TSUNAMI = 1, + CBS_ETWS_WARN_TYPE_EARTHQUAKE_AND_TSUNAMI = 2, + CBS_ETWS_WARN_TYPE_TEST = 3, + CBS_ETWS_WARN_TYPE_OTHER = 4, + /* 0000101-1111111 Reserved for future use */ +}; + /* Section 9.4.1.2: GSM Message Format */ struct gsm23041_msg_param_gsm { uint16_t serial_nr; @@ -12,7 +22,7 @@ struct gsm23041_msg_param_gsm { uint8_t num_pages:4, page_nr:4; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t page_nr:4, num_pages:4; #endif } page_param; diff --git a/include/osmocom/gsm/protocol/gsm_25_415.h b/include/osmocom/gsm/protocol/gsm_25_415.h new file mode 100644 index 00000000..5c4dd2bb --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_25_415.h @@ -0,0 +1,222 @@ +#pragma once +/* Iu User Plane (IuUP) Definitions as per 3GPP TS 25.415 */ +/* (C) 2017 by Harald Welte <laforge@gnumonks.org> + * All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <stdint.h> +#include <osmocom/core/endian.h> + +/* 3GPP TS 25.415 Section 6.6.2.1 */ +struct iuup_pdutype0_hdr { +#if OSMO_IS_LITTLE_ENDIAN + /* control part */ + uint8_t frame_nr:4, + pdu_type:4; + uint8_t rfci:6, + fqc:2; + /* checksum part */ + uint8_t payload_crc_hi:2, header_crc:6; + uint8_t payload_crc_lo; + + /* payload part */ + uint8_t payload[0]; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t pdu_type:4, frame_nr:4; + uint8_t fqc:2, rfci:6; + uint8_t header_crc:6, payload_crc_hi:2; + uint8_t payload_crc_lo; + uint8_t payload[0]; +#endif +} __attribute__((packed)); + +/* 3GPP TS 25.415 Section 6.6.2.2 */ +struct iuup_pdutype1_hdr { +#if OSMO_IS_LITTLE_ENDIAN + /* control part */ + uint8_t frame_nr:4, + pdu_type:4; + uint8_t rfci:6, + fqc:2; + /* checksum part */ + uint8_t spare:2, + header_crc:6; + /* payload part */ + uint8_t payload[0]; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t pdu_type:4, frame_nr:4; + uint8_t fqc:2, rfci:6; + uint8_t header_crc:6, spare:2; + uint8_t payload[0]; +#endif +} __attribute__((packed)); + +/* 3GPP TS 25.415 Section 6.6.2.3 */ +struct iuup_pdutype14_hdr { +#if OSMO_IS_LITTLE_ENDIAN + /* control part */ + uint8_t frame_nr:2, + ack_nack:2, + pdu_type:4; + uint8_t proc_ind:4, + mode_version:4; + /* checksum part */ + uint8_t payload_crc_hi:2, header_crc:6; + uint8_t payload_crc_lo; + /* payload part */ + uint8_t payload[0]; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t pdu_type:4, ack_nack:2, frame_nr:2; + uint8_t mode_version:4, proc_ind:4; + uint8_t header_crc:6, payload_crc_hi:2; + uint8_t payload_crc_lo; + uint8_t payload[0]; +#endif +} __attribute__((packed)); + +/* 3GPP TS 25.415 Section 6.6.2.3.4.1 */ +struct iuup_ctrl_init_rfci_hdr { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t rfci:6, + li:1, + lri:1; + uint8_t subflow_length[0]; /* 1 or 2 bytes depending on li */ +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t lri:1, li:1, rfci:6; + uint8_t subflow_length[0]; +#endif +} __attribute__((packed)); +struct iuup_ctrl_init_hdr { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t chain_ind:1, + num_subflows_per_rfci:3, + ti:1, + spare:3; + uint8_t rfci_data[0]; /* struct iuup_ctrl_init_rfci_hdr* */ +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t spare:3, ti:1, num_subflows_per_rfci:3, chain_ind:1; + uint8_t rfci_data[0]; /* struct iuup_ctrl_init_rfci_hdr* */ +; +#endif +} __attribute__((packed)); +struct iuup_ctrl_init_tail { +#if OSMO_IS_LITTLE_ENDIAN + uint16_t versions_supported; + uint8_t spare:4, + data_pdu_type:4; + uint8_t spare_extension[0]; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint16_t versions_supported; + uint8_t data_pdu_type:4, spare:4; + uint8_t spare_extension[0]; +#endif +} __attribute__((packed)); + +/* 3GPP TS 25.415 Section 6.6.2.3.4.4 */ +struct iuup_ctrl_error_event { +#if OSMO_IS_LITTLE_ENDIAN + struct iuup_pdutype14_hdr hdr; + uint8_t error_cause:6, + error_distance:2; + uint8_t spare_extension[0]; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + struct iuup_pdutype14_hdr hdr; + uint8_t error_distance:2, error_cause:6; + uint8_t spare_extension[0]; +#endif +} __attribute__((packed)); + +/* 3GPP TS 25.415 Section 6.6.2.3.2 */ +struct iuup_ctrl_ack { + struct iuup_pdutype14_hdr hdr; + uint8_t spare_extension[0]; +} __attribute__((packed)); + +/* 3GPP TS 25.415 Section 6.6.2.3.3 */ +struct iuup_ctrl_nack { +#if OSMO_IS_LITTLE_ENDIAN + struct iuup_pdutype14_hdr hdr; + uint8_t spare:2, + error_cause:6; + uint8_t spare_extension[0]; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + struct iuup_pdutype14_hdr hdr; + uint8_t error_cause:6, spare:2; + uint8_t spare_extension[0]; +#endif +} __attribute__((packed)); + +/* 3GPP TS 25.415 Section 6.6.2 + 6.6.3.1 */ +enum iuup_pdu_type { + IUUP_PDU_T_DATA_CRC = 0, + IUUP_PDU_T_DATA_NOCRC = 1, + IUUP_PDU_T_CONTROL = 14, +}; + +/* 3GPP TS 25.415 Section 6.6.3.2 */ +enum iuup_ack_nack { + IUUP_AN_PROCEDURE = 0, + IUUP_AN_ACK = 1, + IUUP_AN_NACK = 2, +}; + +/* 3GPP TS 25.415 Section 6.6.3.5 */ +enum iuup_fqc { + IUUP_FQC_FRAME_GOOD = 0, + IUUP_FQC_FRAME_BAD = 1, + IUUP_FQC_FRAME_BAD_RADIO = 2, +}; + +/* 3GPP TS 25.415 Section 6.6.3.7 */ +enum iuup_procedure { + IUUP_PROC_INIT = 0, + IUUP_PROC_RATE_CTRL = 1, + IUUP_PROC_TIME_ALIGN = 2, + IUUP_PROC_ERR_EVENT = 3, +}; + + +/* 3GPP TS 25.415 Section 6.6.3.15 */ +enum iuup_error_distance { + IUUP_ERR_DIST_LOCAL = 0, + IUUP_ERR_DIST_FIRST_FWD = 1, + IUUP_ERR_DIST_SECOND_FWD = 2, + IUUP_ERR_DIST_RESERVED = 3, +}; + + +/* 3GPP TS 25.415 Section 6.6.3.16 */ +enum iuup_error_cause { + IUUP_ERR_CAUSE_CRC_ERR_HDR = 0, + IUUP_ERR_CAUSE_CRC_ERR_DATA = 1, + IUUP_ERR_CAUSE_UNEXPECTED_FN = 2, + IUUP_ERR_CAUSE_FRAME_LOSS = 3, + IUUP_ERR_CAUSE_UNKNOWN_PDUTYPE = 4, + IUUP_ERR_CAUSE_UNKNOWN_PROC = 5, + IUUP_ERR_CAUSE_UNKNNOWN_RES_VAL = 6, + IUUP_ERR_CAUSE_UNKNNOWN_FIELD = 7, + IUUP_ERR_CAUSE_FRAME_TOO_SHORT = 8, + IUUP_ERR_CAUSE_MISSING_FIELDS = 9, + IUUP_ERR_CAUSE_UNEXPECTED_PDU_T = 16, + IUUP_ERR_CAUSE_UNEXPECTED_PROC = 18, + IUUP_ERR_CAUSE_UNEXPECTED_RFCI = 19, + IUUP_ERR_CAUSE_UNEXPECTED_VALUE = 20, + IUUP_ERR_CAUSE_INIT_FAILURE = 42, + IUUP_ERR_CAUSE_INIT_FAILURE_NET_TMR = 43, + IUUP_ERR_CAUSE_INIT_FAILURE_REP_NACK = 44, + IUUP_ERR_CAUSE_RATE_CTRL_FAILURE = 45, + IUUP_ERR_CAUSE_ERR_EVENT_FAIL = 46, + IUUP_ERR_CAUSE_TIME_ALIGN_NOTSUPP = 47, + IUUP_ERR_CAUSE_REQ_TIME_ALIGN_NOTPOSS = 48, + IUUP_ERR_CAUSE_MODE_VERSION_NOT_SUPPORTED = 49, +}; diff --git a/include/osmocom/gsm/protocol/gsm_44_004.h b/include/osmocom/gsm/protocol/gsm_44_004.h new file mode 100644 index 00000000..c30ba0c9 --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_44_004.h @@ -0,0 +1,19 @@ +#pragma once + +#include <osmocom/core/endian.h> + +/* TS 44.004 Section 7.1 */ + +struct gsm_sacch_l1_hdr { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t ms_pwr:5, + fpc_epc:1, + srr_sro:1, + reserved:1; + uint8_t ta; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t reserved:1, srr_sro:1, fpc_epc:1, ms_pwr:5; + uint8_t ta; +#endif +} __attribute__ ((packed)); diff --git a/include/osmocom/gsm/protocol/gsm_44_060.h b/include/osmocom/gsm/protocol/gsm_44_060.h new file mode 100644 index 00000000..1df2f800 --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_44_060.h @@ -0,0 +1,252 @@ +/*! \file gsm_44_060.h + * General Packet Radio Service (GPRS). + * Radio Link Control / Medium Access Control (RLC/MAC) protocol + * 3GPP TS 44.060 + */ + +#pragma once + +#include <stdint.h> +#include <osmocom/core/endian.h> + +/* TS 44.060 10.3a.4.1.1 */ +struct gprs_rlc_ul_header_egprs_1 { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t r:1, + si:1, + cv:4, + tfi_hi:2; + uint8_t tfi_lo:3, + bsn1_hi:5; + uint8_t bsn1_lo:6, + bsn2_hi:2; + uint8_t bsn2_lo:8; + uint8_t cps:5, + rsb:1, + pi:1, + spare_hi:1; + uint8_t spare_lo:6, + dummy:2; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t tfi_hi:2, cv:4, si:1, r:1; + uint8_t bsn1_hi:5, tfi_lo:3; + uint8_t bsn2_hi:2, bsn1_lo:6; + uint8_t bsn2_lo:8; + uint8_t spare_hi:1, pi:1, rsb:1, cps:5; + uint8_t dummy:2, spare_lo:6; +#endif +} __attribute__ ((packed)); + +/* TS 44.060 10.3a.4.2.1 */ +struct gprs_rlc_ul_header_egprs_2 { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t r:1, + si:1, + cv:4, + tfi_hi:2; + uint8_t tfi_lo:3, + bsn1_hi:5; + uint8_t bsn1_lo:6, + cps_hi:2; + uint8_t cps_lo:1, + rsb:1, + pi:1, + spare_hi:5; + uint8_t spare_lo:5, + dummy:3; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t tfi_hi:2, cv:4, si:1, r:1; + uint8_t bsn1_hi:5, tfi_lo:3; + uint8_t cps_hi:2, bsn1_lo:6; + uint8_t spare_hi:5, pi:1, rsb:1, cps_lo:1; + uint8_t dummy:3, spare_lo:5; +#endif +} __attribute__ ((packed)); + +/* TS 44.060 10.3a.4.3.1 */ +struct gprs_rlc_ul_header_egprs_3 { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t r:1, + si:1, + cv:4, + tfi_hi:2; + uint8_t tfi_lo:3, + bsn1_hi:5; + uint8_t bsn1_lo:6, + cps_hi:2; + uint8_t cps_lo:2, + spb:2, + rsb:1, + pi:1, + spare:1, + dummy:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t tfi_hi:2, cv:4, si:1, r:1; + uint8_t bsn1_hi:5, tfi_lo:3; + uint8_t cps_hi:2, bsn1_lo:6; + uint8_t dummy:1, spare:1, pi:1, rsb:1, spb:2, cps_lo:2; +#endif +} __attribute__ ((packed)); + +struct gprs_rlc_dl_header_egprs_1 { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t usf:3, + es_p:2, + rrbp:2, + tfi_hi:1; + uint8_t tfi_lo:4, + pr:2, + bsn1_hi:2; + uint8_t bsn1_mid:8; + uint8_t bsn1_lo:1, + bsn2_hi:7; + uint8_t bsn2_lo:3, + cps:5; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t tfi_hi:1, rrbp:2, es_p:2, usf:3; + uint8_t bsn1_hi:2, pr:2, tfi_lo:4; + uint8_t bsn1_mid:8; + uint8_t bsn2_hi:7, bsn1_lo:1; + uint8_t cps:5, bsn2_lo:3; +#endif +} __attribute__ ((packed)); + +struct gprs_rlc_dl_header_egprs_2 { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t usf:3, + es_p:2, + rrbp:2, + tfi_hi:1; + uint8_t tfi_lo:4, + pr:2, + bsn1_hi:2; + uint8_t bsn1_mid:8; + uint8_t bsn1_lo:1, + cps:3, + dummy:4; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t tfi_hi:1, rrbp:2, es_p:2, usf:3; + uint8_t bsn1_hi:2, pr:2, tfi_lo:4; + uint8_t bsn1_mid:8; + uint8_t dummy:4, cps:3, bsn1_lo:1; +#endif +} __attribute__ ((packed)); + +struct gprs_rlc_dl_header_egprs_3 { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t usf:3, + es_p:2, + rrbp:2, + tfi_hi:1; + uint8_t tfi_lo:4, + pr:2, + bsn1_hi:2; + uint8_t bsn1_mid:8; + uint8_t bsn1_lo:1, + cps:4, + spb:2, + dummy:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t tfi_hi:1, rrbp:2, es_p:2, usf:3; + uint8_t bsn1_hi:2, pr:2, tfi_lo:4; + uint8_t bsn1_mid:8; + uint8_t dummy:1, spb:2, cps:4, bsn1_lo:1; +#endif +} __attribute__ ((packed)); + +/* TS 44.060 Table 12.24.2 +* Meaning of values documented in TS 23.060 Chapter 6.3.3.1: Network Mode of Operation */ +enum osmo_gprs_nmo { + GPRS_NMO_I = 0, /* CS pagin on GPRS paging or traffic channel */ + GPRS_NMO_II = 1, /* all paging on CCCH */ + GPRS_NMO_III = 2, /* no paging coordination */ +}; + +/* TS 44.060 12.24 */ +struct osmo_gprs_cell_options { + enum osmo_gprs_nmo nmo; + /* T3168: wait for packet uplink assignment message */ + uint32_t t3168; /* in milliseconds */ + /* T3192: wait for release of the TBF after reception of the final block */ + uint32_t t3192; /* in milliseconds */ + uint32_t drx_timer_max;/* in seconds */ + uint32_t bs_cv_max; + uint8_t supports_egprs_11bit_rach; + bool ctrl_ack_type_use_block; /* use PACKET CONTROL ACKNOWLEDGMENT */ + + uint8_t ext_info_present; + struct { + uint8_t egprs_supported; + uint8_t use_egprs_p_ch_req; + uint8_t bep_period; + uint8_t pfc_supported; + uint8_t dtm_supported; + uint8_t bss_paging_coordination; + bool ccn_active; + } ext_info; +}; + +/* TS 44.060 Table 12.9.2 */ +struct osmo_gprs_power_ctrl_pars { + uint8_t alpha; + uint8_t t_avg_w; + uint8_t t_avg_t; + uint8_t pc_meas_chan; + uint8_t n_avg_i; +}; + + +/*! Structure for CPS coding and puncturing scheme (TS 44.060 10.4.8a) */ +struct egprs_cps { + uint8_t bits; + uint8_t mcs; + uint8_t p[2]; +}; + +/*! CPS puncturing table selection (TS 44.060 10.4.8a) */ +enum egprs_cps_punc { + EGPRS_CPS_P1, + EGPRS_CPS_P2, + EGPRS_CPS_P3, + EGPRS_CPS_NONE = -1, +}; + +/*! EGPRS header types (TS 44.060 10.0a.2) */ +enum egprs_hdr_type { + EGPRS_HDR_TYPE1, + EGPRS_HDR_TYPE2, + EGPRS_HDR_TYPE3, +}; + +enum osmo_gprs_cs { + OSMO_GPRS_CS_NONE, + OSMO_GPRS_CS1, + OSMO_GPRS_CS2, + OSMO_GPRS_CS3, + OSMO_GPRS_CS4, + OSMO_GPRS_MCS1, + OSMO_GPRS_MCS2, + OSMO_GPRS_MCS3, + OSMO_GPRS_MCS4, + OSMO_GPRS_MCS5, + OSMO_GPRS_MCS6, + OSMO_GPRS_MCS7, + OSMO_GPRS_MCS8, + OSMO_GPRS_MCS9, + _NUM_OSMO_GPRS_CS +}; + +int egprs_get_cps(struct egprs_cps *cps, uint8_t type, uint8_t bits); + +int osmo_gprs_ul_block_size_bits(enum osmo_gprs_cs cs); +int osmo_gprs_dl_block_size_bits(enum osmo_gprs_cs cs); +int osmo_gprs_ul_block_size_bytes(enum osmo_gprs_cs cs); +int osmo_gprs_dl_block_size_bytes(enum osmo_gprs_cs cs); +enum osmo_gprs_cs osmo_gprs_ul_cs_by_block_bytes(uint8_t block_size); +enum osmo_gprs_cs osmo_gprs_dl_cs_by_block_bytes(uint8_t block_size); diff --git a/include/osmocom/gsm/protocol/gsm_44_068.h b/include/osmocom/gsm/protocol/gsm_44_068.h new file mode 100644 index 00000000..3a33c163 --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_44_068.h @@ -0,0 +1,136 @@ +#pragma once +#include <stdint.h> +#include <osmocom/core/utils.h> + +/* Group Call Control (GCC) is an ETSI/3GPP standard protocol used between + * MS (Mobile Station) and MSC (Mobile Switchting Center) in 2G/GSM-R network. + * It is specified in 3GPP TS 44.068. + * + * (C) 2023 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Andreas Eversberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* 9 Information Element Identifiers */ +enum osmo_gsm44068_iei { + OSMO_GSM44068_IEI_MOBILE_IDENTITY = 0x17, + OSMO_GSM44068_IEI_USER_USER = 0x7E, + OSMO_GSM44068_IEI_CALL_STATE = 0xA0, + OSMO_GSM44068_IEI_STATE_ATTRIBUTES = 0xB0, + OSMO_GSM44068_IEI_TALKER_PRIORITY = 0xC0, + OSMO_GSM44068_IEI_SMS_INDICATIONS = 0xD0, +}; + +/* 9.3 Message Type */ +enum osmo_gsm44068_msg_type { + OSMO_GSM44068_MSGT_IMMEDIATE_SETUP = 0x31, + OSMO_GSM44068_MSGT_SETUP = 0x32, + OSMO_GSM44068_MSGT_CONNECT = 0x33, + OSMO_GSM44068_MSGT_TERMINATION = 0x34, + OSMO_GSM44068_MSGT_TERMINATION_REQUEST = 0x35, + OSMO_GSM44068_MSGT_TERMINATION_REJECT = 0x36, + OSMO_GSM44068_MSGT_STATUS = 0x38, + OSMO_GSM44068_MSGT_GET_STATUS = 0x39, + OSMO_GSM44068_MSGT_SET_PARAMETER = 0x3a, + OSMO_GSM44068_MSGT_IMMEDIATE_SETUP_2 = 0x3b, +}; + +/* Table 9.2 priority */ +enum osmo_gsm44068_priority_level { + OSMO_GSM44068_PRIO_LEVEL_4 = 0x1, + OSMO_GSM44068_PRIO_LEVEL_3 = 0x2, + OSMO_GSM44068_PRIO_LEVEL_2 = 0x3, + OSMO_GSM44068_PRIO_LEVEL_1 = 0x4, + OSMO_GSM44068_PRIO_LEVEL_0 = 0x5, + OSMO_GSM44068_PRIO_LEVEL_B = 0x6, + OSMO_GSM44068_PRIO_LEVEL_A = 0x7, +}; + +/* 9.4.2 Call State */ +enum osmo_gsm44068_call_state { + OSMO_GSM44068_CSTATE_U0 = 0x0, + OSMO_GSM44068_CSTATE_U1 = 0x1, + OSMO_GSM44068_CSTATE_U2sl_U2 = 0x2, + OSMO_GSM44068_CSTATE_U3 = 0x3, + OSMO_GSM44068_CSTATE_U4 = 0x4, + OSMO_GSM44068_CSTATE_U5 = 0x5, + OSMO_GSM44068_CSTATE_U0p = 0x6, + OSMO_GSM44068_CSTATE_U2wr_U6 = 0x7, + OSMO_GSM44068_CSTATE_U2r = 0x8, + OSMO_GSM44068_CSTATE_U2ws = 0x9, + OSMO_GSM44068_CSTATE_U2sr = 0xa, + OSMO_GSM44068_CSTATE_U2nc = 0xb, +}; + +/* 9.4.3 Cause */ +enum osmo_gsm44068_cause { + OSMO_GSM44068_CAUSE_ILLEGAL_MS = 0x03, + OSMO_GSM44068_CAUSE_IMEI_NOT_ACCEPTED = 0x05, + OSMO_GSM44068_CAUSE_ILLEGAL_ME = 0x06, + OSMO_GSM44068_CAUSE_SERVICE_NOT_AUTHORIZED = 0x08, + OSMO_GSM44068_CAUSE_APP_NOT_SUPPORTED_ON_PROTO = 0x09, + OSMO_GSM44068_CAUSE_RR_CONNECTION_ABORTED = 0x0a, + OSMO_GSM44068_CAUSE_NORMAL_CALL_CLEARING = 0x10, + OSMO_GSM44068_CAUSE_NETWORK_FAILURE = 0x11, + OSMO_GSM44068_CAUSE_BUSY = 0x14, + OSMO_GSM44068_CAUSE_CONGESTION = 0x16, + OSMO_GSM44068_CAUSE_USER_NOT_ORIGINATOR = 0x17, + OSMO_GSM44068_CAUSE_NET_WANTS_TO_MAINTAIN_CALL = 0x18, + OSMO_GSM44068_CAUSE_RESPONSE_TO_GET_STATUS = 0x1e, + OSMO_GSM44068_CAUSE_SERVICE_OPTION_NOT_SUBSCR = 0x20, + OSMO_GSM44068_CAUSE_REQUESTED_SERVICE_NOT_SUB = 0x21, + OSMO_GSM44068_CAUSE_SERVICE_OPTION_OOO = 0x22, + OSMO_GSM44068_CAUSE_CALL_CANNOT_BE_IDENTIFIED = 0x26, + OSMO_GSM44068_CAUSE_RETRY_UPON_ENTRY_NEW_CALL = 0x30, /* up to 0x3f */ + OSMO_GSM44068_CAUSE_INVALID_TRANSACTION_ID = 0x51, + OSMO_GSM44068_CAUSE_SEMANTICALLY_INCORRECT_MSG = 0x5f, + OSMO_GSM44068_CAUSE_INVALID_MANDATORY_INFO = 0x60, + OSMO_GSM44068_CAUSE_MESSAGE_TYPE_NON_EXISTENT = 0x61, + OSMO_GSM44068_CAUSE_MESSAGE_TYPE_NOT_COMPAT = 0x62, + OSMO_GSM44068_CAUSE_IE_NON_EXISTENT = 0x63, + OSMO_GSM44068_CAUSE_IE_NOT_COMPAT = 0x64, + OSMO_GSM44068_CAUSE_PROTOCOL_ERROR = 0x70, +}; + +/* 9.4.4 Originator Indication */ +#define OSMO_GSM44068_OI_MS_IS_ORIGINATOR 0x01 + +/* 9.4.7 State Attributes */ +#define OSMO_GSM44068_DA_DOWNLINK_ATTACHED 0x08 +#define OSMO_GSM44068_UA_UPLINK_ATTACHED 0x04 +#define OSMO_GSM44068_COMM_T 0x02 + +/* 9.4.9 Talker Priority */ +enum osmo_gsm44068_talker_priority { + OSMO_GSM44068_PRIO_NORMAL = 0x0, + OSMO_GSM44068_PRIO_PRIVILEGED = 0x1, + OSMO_GSM44068_PRIO_EMERGENCY = 0x2, +}; + +/* 9.4.10 SMS Indications */ +#define OSMO_GSM44068_DC_DATA_CONFIDENTALLY_RQD 0x02 +#define OSMO_GSM44068_GP_GUARANTEED_PRIVACY_RQD 0x01 + +extern const struct value_string osmo_gsm44068_msg_type_names[]; +extern const struct value_string osmo_gsm44068_priority_level_names[]; +extern const struct value_string osmo_gsm44068_cause_names[]; +extern const struct value_string osmo_gsm44068_call_state_names[]; +extern const struct value_string osmo_gsm44068_talker_priority_names[]; + +extern const struct tlv_definition osmo_gsm44068_att_tlvdef; diff --git a/include/osmocom/gsm/protocol/gsm_44_318.h b/include/osmocom/gsm/protocol/gsm_44_318.h index b3942be2..f31a80ae 100644 --- a/include/osmocom/gsm/protocol/gsm_44_318.h +++ b/include/osmocom/gsm/protocol/gsm_44_318.h @@ -162,7 +162,7 @@ struct gan_rc_csr_hdr { uint8_t msg_type; uint8_t data[0]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint16_t len; uint8_t skip_ind:4, pdisc:4; uint8_t msg_type; @@ -190,7 +190,7 @@ struct gan_cch_desc_ie { spare2:2; uint8_t access_class[2]; #elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t mscr:1, att:1, dtm:1, gprs:1, nmo:2, ecmc:1, spare:1; uint8_t t3212; uint8_t rac; diff --git a/include/osmocom/gsm/protocol/gsm_48_071.h b/include/osmocom/gsm/protocol/gsm_48_071.h new file mode 100644 index 00000000..961211b3 --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_48_071.h @@ -0,0 +1,118 @@ +/*! \defgroup bsslap 3GPP TS 48.071 BSS LCS Assistance Protocol (BSSLAP). + * @{ + * \file gsm_48_071.h + */ +/* + * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr <neels@hofmeyr.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#pragma once + +#include <osmocom/gsm/protocol/gsm_04_08.h> + +enum bsslap_msgt { + BSSLAP_MSGT_TA_REQUEST = 0x1, + BSSLAP_MSGT_TA_RESPONSE = 0x2, + BSSLAP_MSGT_REJECT = 0xa, + BSSLAP_MSGT_RESET = 0xb, + BSSLAP_MSGT_ABORT = 0xc, + BSSLAP_MSGT_TA_LAYER3 = 0xd, + BSSLAP_MSGT_MS_POS_CMD = 0xf, + BSSLAP_MSGT_MS_POS_RESP = 0x10, + BSSLAP_MSGT_UTDOA_REQ = 0x11, + BSSLAP_MSGT_UTDOA_RESP = 0x12, +}; + +enum bsslap_cause { + BSSLAP_CAUSE_CONGESTION = 0x0, + BSSLAP_CAUSE_CHAN_MODE_NOT_SUPP = 0x1, + BSSLAP_CAUSE_POS_PROC_NOT_SUPP = 0x2, + BSSLAP_CAUSE_OTHER_RADIO_EVT_FAIL = 0x3, + BSSLAP_CAUSE_INTRA_BSS_HO = 0x4, + BSSLAP_CAUSE_SUPERV_TIMER_EXPIRED = 0x5, + BSSLAP_CAUSE_INTER_BSS_HO = 0x6, + BSSLAP_CAUSE_LOSS_SIG_CONN_MS = 0x7, + BSSLAP_CAUSE_INCORR_SERV_CELL_ID = 0x8, + BSSLAP_CAUSE_BSSAP_LE_SEGMENT_ERR = 0x9, + BSSLAP_CAUSE_CONCUR_POS_PROC_NOT_EN = 0xa, +}; + +enum bsslap_iei { + BSSLAP_IEI_TA = 0x1, + BSSLAP_IEI_CELL_ID = 0x9, + BSSLAP_IEI_CHAN_DESC = 0x10, + BSSLAP_IEI_MEAS_REP = 0x14, + BSSLAP_IEI_CAUSE = 0x18, + BSSLAP_IEI_RRLP_FLAG = 0x19, + BSSLAP_IEI_RRLP = 0x1b, + BSSLAP_IEI_CELL_ID_LIST = 0x1c, + BSSLAP_IEI_ENH_MEAS_REP = 0x1d, + BSSLAP_IEI_LAC = 0x1e, + BSSLAP_IEI_FREQ_LIST = 0x21, + BSSLAP_IEI_MS_POWER = 0x22, + BSSLAP_IEI_DELTA_TIMER = 0x23, + BSSLAP_IEI_SERVING_CELL_ID = 0x24, + BSSLAP_IEI_ENCR_KEY = 0x25, + BSSLAP_IEI_CIPH_MODE_SET = 0x26, + BSSLAP_IEI_CHAN_MODE = 0x27, + BSSLAP_IEI_MR_CONFIG = 0x28, + BSSLAP_IEI_POLLING_REPETITION = 0x29, + BSSLAP_IEI_PACKET_CHAN_DESC = 0x2a, + BSSLAP_IEI_TLLI = 0x2b, + BSSLAP_IEI_TFI = 0x2c, + BSSLAP_IEI_TBF_START_TIME = 0x2d, + BSSLAP_IEI_PWRUP_START_TIME = 0x2e, + BSSLAP_IEI_LONG_ENCR_KEY = 0x2f, + BSSLAP_IEI_CONCUR_POS_PROC_F = 0x30, +}; + +struct bsslap_ta_response { + uint16_t cell_id; + uint8_t ta; + + bool more_items; /*!< always set this to false */ +}; + +struct bsslap_ta_layer3 { + uint8_t ta; + + bool more_items; /*!< always set this to false */ +}; + +struct bsslap_reset { + uint16_t cell_id; + uint8_t ta; + struct gsm48_chan_desc chan_desc; + enum bsslap_cause cause; + + bool more_items; /*!< always set this to false */ +}; + +struct bsslap_pdu { + enum bsslap_msgt msg_type; + union { + /* ta_request: a TA Request message consists only of the message type. */ + struct bsslap_ta_response ta_response; + enum bsslap_cause reject; + struct bsslap_reset reset; + enum bsslap_cause abort; + struct bsslap_ta_layer3 ta_layer3; + }; +}; + +/*! @} */ diff --git a/include/osmocom/gsm/protocol/gsm_49_031.h b/include/osmocom/gsm/protocol/gsm_49_031.h new file mode 100644 index 00000000..463fabf5 --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_49_031.h @@ -0,0 +1,234 @@ +/*! \defgroup bssmap_le 3GPP TS 49.031 BSSMAP-LE. + * @{ + * \file gsm_49_031.h + */ +/* + * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr <neels@hofmeyr.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#pragma once + +#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/endian.h> +#include <osmocom/gsm/protocol/gsm_48_071.h> +#include <osmocom/gsm/protocol/gsm_23_032.h> +#include <osmocom/gsm/gsm0808_utils.h> +#include <osmocom/gsm/gsm48.h> + +/*! 3GPP TS 49.031 10.13 LCS Cause, also in 3GPP TS 48.008 3.2.2.66, which simply refers to the former. */ +enum lcs_cause { + LCS_CAUSE_UNSPECIFIED = 0, + LCS_CAUSE_SYSTEM_FAILURE = 1, + LCS_CAUSE_PROTOCOL_ERROR = 2, + LCS_CAUSE_DATA_MISSING_IN_REQ = 3, + LCS_CAUSE_UNEXP_DATA_IN_REQ = 4, + LCS_CAUSE_POS_METH_FAILURE = 5, + LCS_CAUSE_TGT_MS_UNREACHABLE = 6, + LCS_CAUSE_REQUEST_ABORTED = 7, + LCS_CAUSE_FACILITY_NOTSUPP = 8, + LCS_CAUSE_INTER_BSC_HO = 9, + LCS_CAUSE_INTRA_BSC_HO = 10, + LCS_CAUSE_CONGESTION = 11, + LCS_CAUSE_INTER_NSE_CHG = 12, + LCS_CAUSE_RA_UPDAT = 13, + LCS_CAUSE_PTMSI_REALLOC = 14, + LCS_CAUSE_GPRS_SUSPENSION = 15, +}; + +/*! 3GPP TS 49.031 10.13 LCS Cause, also in 3GPP TS 48.008 3.2.2.66, which simply refers to the former. */ +struct lcs_cause_ie { + bool present; + enum lcs_cause cause_val; + bool diag_val_present; + uint8_t diag_val; +}; + +/* 3GPP TS 49.031 10.16 LCS QoS IE */ +struct osmo_bssmap_le_lcs_qos { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t vert:1, vel:1, spare1:6; + uint8_t ha_val:7, ha_ind:1; + uint8_t va_val:7, va_ind:1; + uint8_t spare3:6, rt:2; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t spare1:6, vel:1, vert:1; + uint8_t ha_ind:1, ha_val:7; + uint8_t va_ind:1, va_val:7; + uint8_t rt:2, spare3:6; +#endif +} __attribute__ ((packed)); + +enum bssap_le_msg_discr { + BSSAP_LE_MSG_DISCR_BSSMAP_LE = 0, +}; + +enum bssmap_le_msgt { + BSSMAP_LE_MSGT_PERFORM_LOC_REQ = 0x2b, + BSSMAP_LE_MSGT_PERFORM_LOC_RESP = 0x2d, + BSSMAP_LE_MSGT_PERFORM_LOC_ABORT = 0x2e, + BSSMAP_LE_MSGT_PERFORM_LOC_INFO = 0x2f, + BSSMAP_LE_MSGT_ASSIST_INFO_REQ = 0x20, + BSSMAP_LE_MSGT_ASSIST_INFO_RESP = 0x21, + BSSMAP_LE_MSGT_CONN_ORIENTED_INFO = 0x2a, + BSSMAP_LE_MSGT_CONN_LESS_INFO = 0x3a, + BSSMAP_LE_MSGT_RESET = 0x30, + BSSMAP_LE_MSGT_RESET_ACK = 0x31, +}; + +enum bssmap_le_iei { + BSSMAP_LE_IEI_LCS_QoS = 0x3e, + BSSMAP_LE_IEI_LCS_PRIORITY = 0x43, + BSSMAP_LE_IEI_LOCATION_TYPE = 0x44, + BSSMAP_LE_IEI_GANSS_LOCATION_TYPE = 0x82, + BSSMAP_LE_IEI_GEO_LOCATION = 0x45, + BSSMAP_LE_IEI_POSITIONING_DATA = 0x46, + BSSMAP_LE_IEI_GANSS_POS_DATA = 0x83, + BSSMAP_LE_IEI_VELOCITY_DATA = 0x55, + BSSMAP_LE_IEI_LCS_CAUSE = 0x47, + BSSMAP_LE_IEI_LCS_CLIENT_TYPE = 0x48, + BSSMAP_LE_IEI_APDU = 0x49, + BSSMAP_LE_IEI_NET_ELEM_ID = 0x4a, + BSSMAP_LE_IEI_REQ_GPS_ASS_D = 0x4b, + BSSMAP_LE_IEI_REQ_GANSS_ASS_D = 0x41, + BSSMAP_LE_IEI_DECIPH_KEYS = 0x4c, + BSSMAP_LE_IEI_RET_ERR_REQ = 0x4d, + BSSMAP_LE_IEI_RET_ERR_CAUSE = 0x4e, + BSSMAP_LE_IEI_SEGMENTATION = 0x4f, + BSSMAP_LE_IEI_CLASSMARK3_INFO = 0x13, + BSSMAP_LE_IEI_CAUSE = 0x4, + BSSMAP_LE_IEI_CELL_ID = 0x5, + BSSMAP_LE_IEI_CHOSEN_CHAN = 0x21, + BSSMAP_LE_IEI_IMSI = 0x0, + BSSMAP_LE_IEI_LCS_CAPABILITY = 0x50, + BSSMAP_LE_IEI_PKT_MEAS_REP = 0x51, + BSSMAP_LE_IEI_CELL_ID_LIST = 0x52, + BSSMAP_LE_IEI_IMEI = 0x80, + BSSMAP_LE_IEI_BSS_MLAT_CAP = 0x84, + BSSMAP_LE_IEI_CELL_INFO_LIST = 0x85, + BSSMAP_LE_IEI_BTS_RX_ACC_LVL = 0x86, + BSSMAP_LE_IEI_MLAT_METHOD = 0x87, + BSSMAP_LE_IEI_MLAT_TA = 0x88, + BSSMAP_LE_IEI_MS_SYNC_ACC = 0x89, + BSSMAP_LE_IEI_SHORT_ID_SET = 0x8a, + BSSMAP_LE_IEI_RANDOM_ID_SET = 0x8b, + BSSMAP_LE_IEI_SHORT_BSS_ID = 0x8c, + BSSMAP_LE_IEI_RANDOM_ID = 0x8d, + BSSMAP_LE_IEI_SHORT_ID = 0x8e, + BSSMAP_LE_IEI_COVERAGE_CLASS = 0x8f, + BSSMAP_LE_IEI_MTA_ACC_SEC_RQD = 0x90, +}; + +enum bssmap_le_apdu_proto { + BSSMAP_LE_APDU_PROT_RESERVED = 0, + BSSMAP_LE_APDU_PROT_BSSLAP = 1, + BSSMAP_LE_APDU_PROT_LLP = 2, + BSSMAP_LE_APDU_PROT_SMLCPP = 3, +}; + +enum bssmap_le_location_information { + BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC = 0x0, + BSSMAP_LE_LOC_INFO_ASSIST_TARGET_MS = 0x1, + BSSMAP_LE_LOC_INFO_BC_DECIPHER_KEYS = 0x2, +}; + +enum bssmap_le_positioning_method { + BSSMAP_LE_POS_METHOD_OMITTED = 0x0, + BSSMAP_LE_POS_METHOD_MOBILE_ASSISTED_E_OTD = 0x1, + BSSMAP_LE_POS_METHOD_MOBILE_BASED_E_OTD = 0x2, + BSSMAP_LE_POS_METHOD_ASSISTED_GPS = 0x3, +}; + +struct bssmap_le_location_type { + enum bssmap_le_location_information location_information; + enum bssmap_le_positioning_method positioning_method; +}; + +enum bssmap_le_lcs_client_type { + BSSMAP_LE_LCS_CTYPE_VALUE_ADDED_UNSPECIFIED = 0x0, + BSSMAP_LE_LCS_CTYPE_PLMN_OPER_UNSPECIFIED = 0x20, + BSSMAP_LE_LCS_CTYPE_PLMN_OPER_BCAST_SERVICE = 0x21, + BSSMAP_LE_LCS_CTYPE_PLMN_OPER_OAM = 0x22, + BSSMAP_LE_LCS_CTYPE_PLMN_OPER_ANON_STATS = 0x23, + BSSMAP_LE_LCS_CTYPE_PLMN_OPER_TGT_MS_SVC = 0x24, + BSSMAP_LE_LCS_CTYPE_EMERG_SVC_UNSPECIFIED = 0x30, + BSSMAP_LE_LCS_CTYPE_LI_UNSPECIFIED = 0x40, +}; + +struct bssmap_le_perform_loc_req { + struct bssmap_le_location_type location_type; + struct gsm0808_cell_id cell_id; + + bool lcs_client_type_present; + enum bssmap_le_lcs_client_type lcs_client_type; + + struct osmo_mobile_identity imsi; + struct osmo_mobile_identity imei; + + bool apdu_present; + struct bsslap_pdu apdu; + + bool more_items; /*!< set this to true iff any fields below are used */ + + bool lcs_priority_present; + uint8_t lcs_priority; /*!< see in 3GPP TS 29.002 */ + + bool lcs_qos_present; + struct osmo_bssmap_le_lcs_qos lcs_qos; + + bool more_items2; /*!< always set this to false */ +}; + +struct bssmap_le_perform_loc_resp { + bool location_estimate_present; + union gad_raw location_estimate; + + struct lcs_cause_ie lcs_cause; + + bool more_items; /*!< always set this to false */ +}; + +struct bssmap_le_conn_oriented_info { + struct bsslap_pdu apdu; + + bool more_items; /*!< always set this to false */ +}; + +struct bssmap_le_pdu { + enum bssmap_le_msgt msg_type; + union { + enum gsm0808_cause reset; + /* reset_ack consists only of the message type */ + struct bssmap_le_perform_loc_req perform_loc_req; + struct bssmap_le_perform_loc_resp perform_loc_resp; + struct lcs_cause_ie perform_loc_abort; + struct bssmap_le_conn_oriented_info conn_oriented_info; + }; +}; + +struct bssap_le_pdu { + enum bssap_le_msg_discr discr; + union { + struct bssmap_le_pdu bssmap_le; + /* future: add DTAP PDU, currently not implemented */ + }; +}; + +/*! @} */ diff --git a/include/osmocom/gsm/protocol/ipaccess.h b/include/osmocom/gsm/protocol/ipaccess.h index 80413d10..51827607 100644 --- a/include/osmocom/gsm/protocol/ipaccess.h +++ b/include/osmocom/gsm/protocol/ipaccess.h @@ -39,29 +39,39 @@ enum ipaccess_proto_ext { IPAC_PROTO_EXT_GSUP = 0x05, /* GSUP GPRS extension */ IPAC_PROTO_EXT_OAP = 0x06, /* Osmocom Authn Protocol */ IPAC_PROTO_EXT_RSPRO = 0x07, /* Remote SIM protocol */ + IPAC_PROTO_EXT_PCU = 0x08, /* BSC<->BTS<->PCU communication */ }; enum ipaccess_msgtype { - IPAC_MSGT_PING = 0x00, - IPAC_MSGT_PONG = 0x01, - IPAC_MSGT_ID_GET = 0x04, - IPAC_MSGT_ID_RESP = 0x05, - IPAC_MSGT_ID_ACK = 0x06, + IPAC_MSGT_PING = 0x00, /* Heartbeet */ + IPAC_MSGT_PONG = 0x01, /* Heartbeat Ack */ + IPAC_MSGT_ID_GET = 0x04, /* Identity Request */ + IPAC_MSGT_ID_RESP = 0x05, /* Identity */ + IPAC_MSGT_ID_ACK = 0x06, /* Identity Ack */ + IPAC_MSGT_ID_NACK = 0x07, /* Identity Nack */ + IPAC_MSGT_PROXY = 0x08, /* Proxy */ + IPAC_MSGT_PROXY_ACK = 0x09, /* Proxy Ack */ + IPAC_MSGT_PROXY_NACK = 0x0a, /* Proxy Nack */ + IPAC_MSGT_SSL_INFO = 0x0b, /* SSL Info */ /* OpenBSC extension */ IPAC_MSGT_SCCP_OLD = 0xff, }; enum ipaccess_id_tags { - IPAC_IDTAG_SERNR = 0x00, - IPAC_IDTAG_UNITNAME = 0x01, - IPAC_IDTAG_LOCATION1 = 0x02, - IPAC_IDTAG_LOCATION2 = 0x03, - IPAC_IDTAG_EQUIPVERS = 0x04, - IPAC_IDTAG_SWVERSION = 0x05, - IPAC_IDTAG_IPADDR = 0x06, - IPAC_IDTAG_MACADDR = 0x07, - IPAC_IDTAG_UNIT = 0x08, + IPAC_IDTAG_SERNR = 0x00, /* Unit Serial Number */ + IPAC_IDTAG_UNITNAME = 0x01, /* Unit Name */ + IPAC_IDTAG_LOCATION1 = 0x02, /* Unit Location */ + IPAC_IDTAG_LOCATION2 = 0x03, /* Unit Type */ + IPAC_IDTAG_EQUIPVERS = 0x04, /* Hardware Version */ + IPAC_IDTAG_SWVERSION = 0x05, /* Software Version */ + IPAC_IDTAG_IPADDR = 0x06, /* IP Address */ + IPAC_IDTAG_MACADDR = 0x07, /* Ethernet Address */ + IPAC_IDTAG_UNIT = 0x08, /* Unit ID */ + IPAC_IDTAG_USERNAME = 0x09, /* User Name */ + IPAC_IDTAG_PASSWORD = 0x0a, /* Password */ + IPAC_IDTAG_ACCESS_CLASS = 0x0b, /* Access Class */ + IPAC_IDTG_APP_PROTO_VER = 0x0c, /* Application Protocol Version */ }; /* 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/rtp_extensions.h b/include/osmocom/gsm/rtp_extensions.h new file mode 100644 index 00000000..edea4316 --- /dev/null +++ b/include/osmocom/gsm/rtp_extensions.h @@ -0,0 +1,23 @@ +/* + * Themyscira Wireless Technical Specification TW-TS-003 defines a BSSMAP + * extension whereby a CN implementation and a BSS implementation can + * negotiate the use of non-3GPP-standard extensions to RTP user plane, + * extensions that modify RTP formats counter to the stipulations of + * 3GPP TS 48.103. There is also a private Osmocom-defined IE in Abis RSL + * that communicates the same RTP extensions from OsmoBSC to OsmoBTS. + * + * This header file defines the meaning of the bits in the first (and currently + * only) value octet of the TLV IE added to BSSMAP and RSL interfaces, + * namely, GSM0808_IE_THEMWI_RTP_EXTENSIONS and RSL_IE_OSMO_RTP_EXTENSIONS. + * It is based on this authoritative definition: + * + * https://www.freecalypso.org/specs/tw-ts-003-v010002.txt + * + * Section 5.3 in the above specification defines the assignment of + * individual bits in the single value octet. + */ + +#pragma once + +#define OSMO_RTP_EXT_TWTS001 0x01 +#define OSMO_RTP_EXT_TWTS002 0x02 diff --git a/include/osmocom/gsm/tlv.h b/include/osmocom/gsm/tlv.h index 254c21bc..28e897d7 100644 --- a/include/osmocom/gsm/tlv.h +++ b/include/osmocom/gsm/tlv.h @@ -4,6 +4,7 @@ #include <string.h> #include <osmocom/core/msgb.h> +#include <osmocom/core/byteswap.h> #include <osmocom/core/bit16gen.h> #include <osmocom/core/bit32gen.h> @@ -40,6 +41,16 @@ /*! maximum length of TLV of one byte length */ #define TVLV_MAX_ONEBYTE 0x7f +/*! error return codes of various TLV parser functions */ +enum osmo_tlv_parser_error { + OSMO_TLVP_ERR_OFS_BEYOND_BUFFER = -1, + OSMO_TLVP_ERR_OFS_LEN_BEYOND_BUFFER = -2, + OSMO_TLVP_ERR_UNKNOWN_TLV_TYPE = -3, + + OSMO_TLVP_ERR_MAND_IE_MISSING = -50, + OSMO_TLVP_ERR_IE_TOO_SHORT = -51, +}; + /*! gross length of a TVLV type field */ static inline uint16_t TVLV_GROSS_LEN(uint16_t len) { @@ -137,7 +148,7 @@ static inline uint8_t *tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len, *buf++ = len >> 8; *buf++ = len & 0xff; memcpy(buf, val, len); - return buf + len*2; + return buf + len; } /*! put (append) a TL16 field. */ @@ -157,7 +168,7 @@ static inline uint8_t *t16lv_put(uint8_t *buf, uint16_t tag, uint8_t len, *buf++ = tag & 0xff; *buf++ = len; memcpy(buf, val, len); - return buf + len + 2; + return buf + len; } /*! put (append) a TvLV field */ @@ -268,6 +279,20 @@ static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len return tvlv_put(buf, tag, len, val); } +/*! put (append) a TvLV field containing a big-endian 16bit value to msgb. */ +static inline uint8_t *msgb_tvlv_put_16be(struct msgb *msg, uint8_t tag, uint16_t val) +{ + uint16_t val_be = osmo_htons(val); + return msgb_tvlv_put(msg, tag, 2, (const uint8_t *)&val_be); +} + +/*! put (append) a TvLV field containing a big-endian 16bit value to msgb. */ +static inline uint8_t *msgb_tvlv_put_32be(struct msgb *msg, uint8_t tag, uint32_t val) +{ + uint32_t val_be = osmo_htonl(val); + return msgb_tvlv_put(msg, tag, 4, (const uint8_t *)&val_be); +} + /*! put (append) a vTvLV field to \ref msgb */ static inline uint8_t *msgb_vtvlv_gan_put(struct msgb *msg, uint16_t tag, uint16_t len, const uint8_t *val) @@ -297,7 +322,7 @@ static inline uint8_t *v_put(uint8_t *buf, uint8_t val) } /*! put (append) a TV field */ -static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag, +static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag, uint8_t val) { *buf++ = tag; @@ -319,7 +344,7 @@ static inline uint8_t *tv_fixed_put(uint8_t *buf, uint8_t tag, * \param[in] tag Tag value * \param[in] val Value (in host byte order!) */ -static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag, +static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag, uint16_t val) { *buf++ = tag; @@ -381,7 +406,7 @@ static inline uint8_t *msgb_tl_put(struct msgb *msg, uint8_t tag) return len; } -/*! put (append) a TV16 field to a \ref msgb +/*! put (append) a TV16 field (network order) to the given msgb * \returns pointer to first byte after newly-put information */ static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val) { @@ -389,6 +414,16 @@ static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val return tv16_put(buf, tag, val); } +/*! put (append) a TV32 field (network order) to the given msgb + * \returns pointer to first byte after newly-put information */ +static inline uint8_t *msgb_tv32_put(struct msgb *msg, uint8_t tag, uint32_t val) +{ + uint8_t *buf = msgb_put(msg, 1 + 4); + *buf++ = tag; + osmo_store32be(val, buf); + return msg->tail; +} + /*! push (prepend) a TLV field to a \ref msgb * \returns pointer to first byte of newly-pushed information */ static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val) @@ -422,6 +457,16 @@ static inline uint8_t *msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t va return buf; } +/*! push (prepend) a TV32 field to a \ref msgb + * \returns pointer to first byte of newly-pushed information */ +static inline uint8_t *msgb_tv32_push(struct msgb *msg, uint8_t tag, uint32_t val) +{ + uint8_t *buf = msgb_push(msg, 5); + *buf++ = tag; + osmo_store32be(val, buf); + return buf; +} + /*! push (prepend) a TvLV field to a \ref msgb * \returns pointer to first byte of newly-pushed information */ static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t len, @@ -508,7 +553,7 @@ int tlv_encode(struct msgb *msg, const struct tlv_definition *def, const struct int tlv_encode_ordered(struct msgb *msg, const struct tlv_definition *def, const struct tlv_parsed *tp, const uint8_t *tag_order, unsigned int tag_order_len); -#define TLVP_PRESENT(x, y) ((x)->lv[y].val) +#define TLVP_PRESENT(x, y) (!!((x)->lv[y].val)) #define TLVP_LEN(x, y) (x)->lv[y].len #define TLVP_VAL(x, y) (x)->lv[y].val @@ -620,4 +665,54 @@ int osmo_match_shift_tlv(uint8_t **data, size_t *data_len, int osmo_shift_lv(uint8_t **data, size_t *data_len, uint8_t **value, size_t *value_len); +#define MSG_DEF(name, mand_ies, flags) { name, mand_ies, ARRAY_SIZE(mand_ies), flags } + +struct osmo_tlv_prot_msg_def { + /*! human-readable name of message type (optional) */ + const char *name; + /*! array of mandatory IEs */ + const uint8_t *mand_ies; + /*! number of entries in 'mand_ies' above */ + uint8_t mand_count; + /*! user-defined flags (like uplink/downlink/...) */ + uint32_t flags; +}; +struct osmo_tlv_prot_ie_def { + /*! minimum length of IE value part, in octets */ + uint16_t min_len; + /*! huamn-readable name (optional) */ + const char *name; +}; + +/*! Osmocom TLV protocol definition */ +struct osmo_tlv_prot_def { + /*! human-readable name of protocol */ + const char *name; + /*! TLV parser definition (optional) */ + const struct tlv_definition *tlv_def; + /*! definition of each message (8-bit message type) */ + struct osmo_tlv_prot_msg_def msg_def[256]; + /*! definition of IE for each 8-bit tag */ + struct osmo_tlv_prot_ie_def ie_def[256]; + /*! value_string array of message type names (legacy, if not populated in msg_def) */ + const struct value_string *msgt_names; +}; + +const char *osmo_tlv_prot_msg_name(const struct osmo_tlv_prot_def *pdef, uint8_t msg_type); +const char *osmo_tlv_prot_ie_name(const struct osmo_tlv_prot_def *pdef, uint8_t iei); + +int osmo_tlv_prot_validate_tp(const struct osmo_tlv_prot_def *pdef, uint8_t msg_type, + const struct tlv_parsed *tp, int log_subsys, const char *log_pfx); + +int osmo_tlv_prot_parse(const struct osmo_tlv_prot_def *pdef, + struct tlv_parsed *dec, unsigned int dec_multiples, uint8_t msg_type, + const uint8_t *buf, unsigned int buf_len, uint8_t lv_tag, uint8_t lv_tag2, + int log_subsys, const char *log_pfx); + +static inline uint32_t osmo_tlv_prot_msgt_flags(const struct osmo_tlv_prot_def *pdef, uint8_t msg_type) +{ + return pdef->msg_def[msg_type].flags; +} + + /*! @} */ |