dexter has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/libosmocore/+/21120 )


Change subject: gsm_04_08: add parser for Mobile Station Classmark 3
......................................................................

gsm_04_08: add parser for Mobile Station Classmark 3

3GPP TS 24.008 section 10.5.1.7 describes a Mobile Station Classmark 3
IE, which is encoded as CSN.1 struct. This means that it can not be
parsed by just casting a memory location to a struct pointer, so lets
add a parser to parse the CM3 IE.

This is fixed version of Ic8b2bfd00330235f5bed00771e421588abfaac1f,
which got reverted because it used the keyword "class" as struct member,
which lead into problems with c++ builds. This is now fixed.

Change-Id: Id8732551b33616227609cd6fcf6c3133751a89eb
Related: OS#4796 SYS#5114
---
M include/osmocom/gsm/gsm48_ie.h
M include/osmocom/gsm/protocol/gsm_04_08.h
M src/gsm/gsm48_ie.c
M src/gsm/libosmogsm.map
M tests/gsm0408/gsm0408_test.c
M tests/gsm0408/gsm0408_test.ok
6 files changed, 960 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/20/21120/1

diff --git a/include/osmocom/gsm/gsm48_ie.h b/include/osmocom/gsm/gsm48_ie.h
index 339aa13..b79cbfc 100644
--- a/include/osmocom/gsm/gsm48_ie.h
+++ b/include/osmocom/gsm/gsm48_ie.h
@@ -119,3 +119,7 @@
 /* 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);
+
+/* 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/protocol/gsm_04_08.h 
b/include/osmocom/gsm/protocol/gsm_04_08.h
index df13b15..a103c32 100644
--- a/include/osmocom/gsm/protocol/gsm_04_08.h
+++ b/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -58,6 +58,175 @@
 #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;
diff --git a/src/gsm/gsm48_ie.c b/src/gsm/gsm48_ie.c
index 31028ba..6070e5c 100644
--- a/src/gsm/gsm48_ie.c
+++ b/src/gsm/gsm48_ie.c
@@ -34,6 +34,7 @@
 #include <osmocom/core/msgb.h>
 #include <osmocom/gsm/tlv.h>
 #include <osmocom/gsm/mncc.h>
+#include <osmocom/core/bitvec.h>
 #include <osmocom/gsm/protocol/gsm_04_08.h>
 #include <osmocom/gsm/gsm48_ie.h>

@@ -1299,4 +1300,249 @@

        return 0;
 }
+
+/*! Decode 3GPP TS 24.008 Mobile Station Classmark 3 (10.5.1.7).
+ *  \param[out] classmark3_out user provided memory to store decoded 
classmark3.
+ *  \param[in] classmark3 pointer to memory that contains the raw classmark 
bits.
+ *  \param[in] classmark3_len length in bytes of the memory where classmark3 
points to.
+ *  \returns 0 on success; negative on error. */
+int gsm48_decode_classmark3(struct gsm48_classmark3 *classmark3_out,
+                           const uint8_t *classmark3, size_t classmark3_len)
+{
+       struct bitvec bv;
+       uint8_t data[255];
+       struct gsm48_classmark3 *cm3 = classmark3_out;
+
+       /* if cm3 gets extended by spec, it will be truncated, but 255 bytes
+        * should be more than enough. */
+       if (classmark3_len > sizeof(data))
+               classmark3_len = sizeof(data);
+
+       memset(&bv, 0, sizeof(bv));
+       memset(data, 0, sizeof(data));
+       memset(classmark3_out, 0, sizeof(*classmark3_out));
+
+       memcpy(data, classmark3, classmark3_len);
+       bv.data = (uint8_t*) data;
+       bv.data_len = sizeof(data);
+
+       /* Parse bit vector, see also: 3GPP TS 24.008, section 10.5.1.7 */
+       bitvec_get_uint(&bv, 1);
+       cm3->mult_band_supp = bitvec_get_uint(&bv, 3);
+       switch (cm3->mult_band_supp) {
+       case 0x00:
+               cm3->a5_bits = bitvec_get_uint(&bv, 4);
+               break;
+       case 0x05:
+       case 0x06:
+               cm3->a5_bits = bitvec_get_uint(&bv, 4);
+               cm3->assoc_radio_cap_2 = bitvec_get_uint(&bv, 4);
+               cm3->assoc_radio_cap_1 = bitvec_get_uint(&bv, 4);
+               break;
+       case 0x01:
+       case 0x02:
+       case 0x04:
+               cm3->a5_bits = bitvec_get_uint(&bv, 4);
+               bitvec_get_uint(&bv, 4);
+               cm3->assoc_radio_cap_1 = bitvec_get_uint(&bv, 4);
+               break;
+       default:
+               return -1;
+       }
+
+       cm3->r_support.present = bitvec_get_uint(&bv, 1);
+       if (cm3->r_support.present)
+               cm3->r_support.r_gsm_assoc_radio_cap = bitvec_get_uint(&bv, 3);
+
+       cm3->hscsd_mult_slot_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->hscsd_mult_slot_cap.present)
+               cm3->hscsd_mult_slot_cap.mslot_class = bitvec_get_uint(&bv, 5);
+
+       cm3->ucs2_treatment = bitvec_get_uint(&bv, 1);
+       cm3->extended_meas_cap = bitvec_get_uint(&bv, 1);
+
+       cm3->ms_meas_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->ms_meas_cap.present) {
+               cm3->ms_meas_cap.sms_value = bitvec_get_uint(&bv, 4);
+               cm3->ms_meas_cap.sm_value = bitvec_get_uint(&bv, 4);
+       }
+
+       cm3->ms_pos_method_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->ms_pos_method_cap.present)
+               cm3->ms_pos_method_cap.method = bitvec_get_uint(&bv, 5);
+
+       cm3->ecsd_multislot_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->ecsd_multislot_cap.present)
+               cm3->ecsd_multislot_cap.mslot_class = bitvec_get_uint(&bv, 5);
+
+       cm3->psk8_struct.present = bitvec_get_uint(&bv, 1);
+       if (cm3->psk8_struct.present) {
+               cm3->psk8_struct.mod_cap = bitvec_get_uint(&bv, 1);
+
+               cm3->psk8_struct.rf_pwr_cap_1.present = bitvec_get_uint(&bv, 1);
+               if (cm3->psk8_struct.rf_pwr_cap_1.present) {
+                       cm3->psk8_struct.rf_pwr_cap_1.value =
+                           bitvec_get_uint(&bv, 2);
+               }
+
+               cm3->psk8_struct.rf_pwr_cap_2.present = bitvec_get_uint(&bv, 1);
+               if (cm3->psk8_struct.rf_pwr_cap_2.present) {
+                       cm3->psk8_struct.rf_pwr_cap_2.value =
+                           bitvec_get_uint(&bv, 2);
+               }
+       }
+
+       cm3->gsm_400_bands_supp.present = bitvec_get_uint(&bv, 1);
+       if (cm3->gsm_400_bands_supp.present) {
+               cm3->gsm_400_bands_supp.value = bitvec_get_uint(&bv, 2);
+               if (cm3->gsm_400_bands_supp.value == 0x00)
+                       return -1;
+               cm3->gsm_400_bands_supp.assoc_radio_cap =
+                   bitvec_get_uint(&bv, 4);
+       }
+
+       cm3->gsm_850_assoc_radio_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->gsm_850_assoc_radio_cap.present)
+               cm3->gsm_850_assoc_radio_cap.value = bitvec_get_uint(&bv, 4);
+
+       cm3->gsm_1900_assoc_radio_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->gsm_1900_assoc_radio_cap.present)
+               cm3->gsm_1900_assoc_radio_cap.value = bitvec_get_uint(&bv, 4);
+
+       cm3->umts_fdd_rat_cap = bitvec_get_uint(&bv, 1);
+       cm3->umts_tdd_rat_cap = bitvec_get_uint(&bv, 1);
+       cm3->cdma200_rat_cap = bitvec_get_uint(&bv, 1);
+
+       cm3->dtm_gprs_multislot_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->dtm_gprs_multislot_cap.present) {
+               cm3->dtm_gprs_multislot_cap.mslot_class = bitvec_get_uint(&bv, 
2);
+               cm3->dtm_gprs_multislot_cap.single_slot_dtm =
+                   bitvec_get_uint(&bv, 1);
+               cm3->dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present =
+                   bitvec_get_uint(&bv, 1);
+               if (cm3->dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present)
+                       cm3->dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.
+                           mslot_class = bitvec_get_uint(&bv, 2);
+       }
+
+       /* Release 4 starts here. */
+       cm3->single_band_supp.present = bitvec_get_uint(&bv, 1);
+       if (cm3->single_band_supp.present)
+               cm3->single_band_supp.value = bitvec_get_uint(&bv, 4);
+
+       cm3->gsm_750_assoc_radio_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->gsm_750_assoc_radio_cap.present)
+               cm3->gsm_750_assoc_radio_cap.value = bitvec_get_uint(&bv, 4);
+
+       cm3->umts_1_28_mcps_tdd_rat_cap = bitvec_get_uint(&bv, 1);
+       cm3->geran_feature_package = bitvec_get_uint(&bv, 1);
+
+       cm3->extended_dtm_gprs_multislot_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->extended_dtm_gprs_multislot_cap.present) {
+               cm3->extended_dtm_gprs_multislot_cap.mslot_class =
+                   bitvec_get_uint(&bv, 2);
+               cm3->extended_dtm_gprs_multislot_cap.
+                   extended_dtm_egprs_multislot_cap.present =
+                   bitvec_get_uint(&bv, 1);
+               if (cm3->extended_dtm_gprs_multislot_cap.
+                   extended_dtm_egprs_multislot_cap.present)
+                       cm3->extended_dtm_gprs_multislot_cap.
+                           extended_dtm_egprs_multislot_cap.mslot_class =
+                           bitvec_get_uint(&bv, 2);
+       }
+
+       /* Release 5 starts here */
+       cm3->high_multislot_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->high_multislot_cap.present)
+               cm3->high_multislot_cap.value = bitvec_get_uint(&bv, 2);
+
+       /* This used to be the GERAN Iu mode support bit, but the newer spec
+        * releases say that it should not be used (always zero), however
+        * we will just ignore tha state of this bit. */
+       bitvec_get_uint(&bv, 1);
+
+       cm3->geran_feature_package_2 = bitvec_get_uint(&bv, 1);
+       cm3->gmsk_multislot_power_prof = bitvec_get_uint(&bv, 2);
+       cm3->psk8_multislot_power_prof = bitvec_get_uint(&bv, 2);
+
+       /* Release 6 starts here */
+       cm3->t_gsm_400_bands_supp.present = bitvec_get_uint(&bv, 1);
+       if (cm3->t_gsm_400_bands_supp.present) {
+               cm3->t_gsm_400_bands_supp.value = bitvec_get_uint(&bv, 2);
+               cm3->t_gsm_400_bands_supp.assoc_radio_cap =
+                   bitvec_get_uint(&bv, 4);
+       }
+
+       /* This used to be T-GSM 900 associated radio capability, but the
+        * newer spec releases say that this bit should not be used, but if
+        * it is used by some MS anyway we must assume that there is data
+        * we have to override. */
+       if (bitvec_get_uint(&bv, 1))
+               bitvec_get_uint(&bv, 4);
+
+       cm3->dl_advanced_rx_perf = bitvec_get_uint(&bv, 2);
+       cm3->dtm_enhancements_cap = bitvec_get_uint(&bv, 1);
+
+       cm3->dtm_gprs_high_multislot_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->dtm_gprs_high_multislot_cap.present) {
+               cm3->dtm_gprs_high_multislot_cap.mslot_class =
+                   bitvec_get_uint(&bv, 3);
+               cm3->dtm_gprs_high_multislot_cap.offset_required =
+                   bitvec_get_uint(&bv, 1);
+               cm3->dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.
+                   present = bitvec_get_uint(&bv, 1);
+               if (cm3->dtm_gprs_high_multislot_cap.
+                   dtm_egprs_high_multislot_cap.present)
+                       cm3->dtm_gprs_high_multislot_cap.
+                           dtm_egprs_high_multislot_cap.mslot_class =
+                           bitvec_get_uint(&bv, 3);
+       }
+
+       cm3->repeated_acch_capability = bitvec_get_uint(&bv, 1);
+
+       /* Release 7 starts here */
+       cm3->gsm_710_assoc_radio_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->gsm_710_assoc_radio_cap.present)
+               cm3->gsm_710_assoc_radio_cap.value = bitvec_get_uint(&bv, 4);
+
+       cm3->t_gsm_810_assoc_radio_cap.present = bitvec_get_uint(&bv, 1);
+       if (cm3->t_gsm_810_assoc_radio_cap.present)
+               cm3->t_gsm_810_assoc_radio_cap.value = bitvec_get_uint(&bv, 4);
+
+       cm3->ciphering_mode_setting_cap = bitvec_get_uint(&bv, 1);
+       cm3->add_pos_cap = bitvec_get_uint(&bv, 1);
+
+       /* Release 8 starts here */
+       cm3->e_utra_fdd_supp = bitvec_get_uint(&bv, 1);
+       cm3->e_utra_tdd_supp = bitvec_get_uint(&bv, 1);
+       cm3->e_utra_meas_rep_supp = bitvec_get_uint(&bv, 1);
+       cm3->prio_resel_supp = bitvec_get_uint(&bv, 1);
+
+       /* Release 9 starts here */
+       cm3->utra_csg_cells_rep = bitvec_get_uint(&bv, 1);
+
+       cm3->vamos_level = bitvec_get_uint(&bv, 2);
+
+       /* Release 10 starts here */
+       cm3->tighter_capability = bitvec_get_uint(&bv, 2);
+       cm3->sel_ciph_dl_sacch = bitvec_get_uint(&bv, 1);
+
+       /* Release 11 starts here */
+       cm3->cs_ps_srvcc_geran_utra = bitvec_get_uint(&bv, 2);
+       cm3->cs_ps_srvcc_geran_eutra = bitvec_get_uint(&bv, 2);
+
+       cm3->geran_net_sharing = bitvec_get_uint(&bv, 1);
+       cm3->e_utra_wb_rsrq_meas_supp = bitvec_get_uint(&bv, 1);
+
+       /* Release 12 starts here */
+       cm3->er_band_support = bitvec_get_uint(&bv, 1);
+       cm3->utra_mult_band_ind_supp = bitvec_get_uint(&bv, 1);
+       cm3->e_utra_mult_band_ind_supp = bitvec_get_uint(&bv, 1);
+       cm3->extended_tsc_set_cap_supp = bitvec_get_uint(&bv, 1);
+
+       /* Late addition of a release 11 feature */
+       cm3->extended_earfcn_val_range = bitvec_get_uint(&bv, 1);
+
+       return 0;
+}
 /*! @} */
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 031cc20..f339120 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -339,6 +339,7 @@
 gsm48_decode_connected;
 gsm48_decode_facility;
 gsm48_decode_freq_list;
+gsm48_decode_classmark3;
 gsm48_decode_keypad;
 gsm48_decode_lai;
 gsm48_decode_notify;
diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c
index d2ae6f6..5a59639 100644
--- a/tests/gsm0408/gsm0408_test.c
+++ b/tests/gsm0408/gsm0408_test.c
@@ -327,6 +327,203 @@
        }
 }

+static void dump_cm3(struct gsm48_classmark3 *cm3)
+{
+       printf("mult_band_supp=%02x\n", cm3->mult_band_supp);
+       printf("a5_bits=%02x\n", cm3->a5_bits);
+       printf("assoc_radio_cap_1=%02x\n", cm3->assoc_radio_cap_1);
+       printf("assoc_radio_cap_2=%02x\n", cm3->assoc_radio_cap_2);
+       printf("\n");
+       printf("r_support.present=%u\n", cm3->r_support.present);
+       printf("r_support.r_gsm_assoc_radio_cap=%02x\n",
+              cm3->r_support.r_gsm_assoc_radio_cap);
+       printf("\n");
+       printf("hscsd_mult_slot_cap.present=%u\n",
+              cm3->hscsd_mult_slot_cap.present);
+       printf("hscsd_mult_slot_cap.mslot_class=%02x\n",
+              cm3->hscsd_mult_slot_cap.mslot_class);
+       printf("\n");
+       printf("ucs2_treatment=%u\n", cm3->ucs2_treatment);
+       printf("extended_meas_cap=%u\n", cm3->extended_meas_cap);
+       printf("\n");
+       printf("ms_meas_cap.present=%u\n", cm3->ms_meas_cap.present);
+       printf("ms_meas_cap.sms_value=%02x\n", cm3->ms_meas_cap.sms_value);
+       printf("ms_meas_cap.sm_value=%02x\n", cm3->ms_meas_cap.sm_value);
+       printf("\n");
+       printf("ms_pos_method_cap.present=%u\n",
+              cm3->ms_pos_method_cap.present);
+       printf("ms_pos_method_cap.method=%02x\n",
+              cm3->ms_pos_method_cap.method);
+       printf("\n");
+       printf("ecsd_multislot_cap.present=%u\n",
+              cm3->ecsd_multislot_cap.present);
+       printf("ecsd_multislot_cap.mslot_class=%02x\n",
+              cm3->ecsd_multislot_cap.mslot_class);
+       printf("\n");
+       printf("psk8_struct.present=%u\n", cm3->psk8_struct.present);
+       printf("psk8_struct.mod_cap=%u\n", cm3->psk8_struct.mod_cap);
+       printf("psk8_struct.rf_pwr_cap_1.present=%u\n",
+              cm3->psk8_struct.rf_pwr_cap_1.present);
+       printf("psk8_struct.rf_pwr_cap_1.value=%02x\n",
+              cm3->psk8_struct.rf_pwr_cap_1.value);
+       printf("psk8_struct.rf_pwr_cap_2.present=%u\n",
+              cm3->psk8_struct.rf_pwr_cap_2.present);
+       printf("psk8_struct.rf_pwr_cap_2.value=%02x\n",
+              cm3->psk8_struct.rf_pwr_cap_2.value);
+       printf("\n");
+       printf("gsm_400_bands_supp.present=%u\n",
+              cm3->gsm_400_bands_supp.present);
+       printf("gsm_400_bands_supp.value=%02x\n",
+              cm3->gsm_400_bands_supp.value);
+       printf("gsm_400_bands_supp.assoc_radio_cap=%02x\n",
+              cm3->gsm_400_bands_supp.assoc_radio_cap);
+       printf("\n");
+       printf("gsm_850_assoc_radio_cap.present=%u\n",
+              cm3->gsm_850_assoc_radio_cap.present);
+       printf("gsm_850_assoc_radio_cap.value=%02x\n",
+              cm3->gsm_850_assoc_radio_cap.value);
+       printf("\n");
+       printf("gsm_1900_assoc_radio_cap.present=%u\n",
+              cm3->gsm_1900_assoc_radio_cap.present);
+       printf("gsm_1900_assoc_radio_cap.value=%02x\n",
+              cm3->gsm_1900_assoc_radio_cap.value);
+       printf("\n");
+       printf("umts_fdd_rat_cap=%u\n", cm3->umts_fdd_rat_cap);
+       printf("umts_tdd_rat_cap=%u\n", cm3->umts_tdd_rat_cap);
+       printf("cdma200_rat_cap=%u\n", cm3->cdma200_rat_cap);
+       printf("\n");
+       printf("dtm_gprs_multislot_cap.present=%u\n",
+              cm3->dtm_gprs_multislot_cap.present);
+       printf("dtm_gprs_multislot_cap.mslot_class=%02x\n",
+              cm3->dtm_gprs_multislot_cap.mslot_class);
+       printf("dtm_gprs_multislot_cap.single_slot_dtm=%u\n",
+              cm3->dtm_gprs_multislot_cap.single_slot_dtm);
+       printf("dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present=%u\n",
+              cm3->dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present);
+       
printf("dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class=%02x\n",
+              cm3->dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class);
+       printf("\n");
+       printf("single_band_supp.present=%u\n", cm3->single_band_supp.present);
+       printf("single_band_supp.value=%u\n", cm3->single_band_supp.value);
+       printf("\n");
+       printf("gsm_750_assoc_radio_cap.present=%u\n",
+              cm3->gsm_750_assoc_radio_cap.present);
+       printf("gsm_750_assoc_radio_cap.value=%02x\n",
+              cm3->gsm_750_assoc_radio_cap.value);
+       printf("\n");
+       printf("umts_1_28_mcps_tdd_rat_cap=%u\n",
+              cm3->umts_1_28_mcps_tdd_rat_cap);
+       printf("geran_feature_package=%u\n", cm3->geran_feature_package);
+       printf("\n");
+       printf("extended_dtm_gprs_multislot_cap.present=%u\n",
+              cm3->extended_dtm_gprs_multislot_cap.present);
+       printf("extended_dtm_gprs_multislot_cap.mslot_class=%02x\n",
+              cm3->extended_dtm_gprs_multislot_cap.mslot_class);
+       printf
+           
("extended_dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present=%u\n",
+            cm3->extended_dtm_gprs_multislot_cap.
+            extended_dtm_egprs_multislot_cap.present);
+       printf
+           
("extended_dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class=%02x\n",
+            cm3->extended_dtm_gprs_multislot_cap.
+            extended_dtm_egprs_multislot_cap.mslot_class);
+       printf("\n");
+       printf("high_multislot_cap.present=%u\n",
+              cm3->high_multislot_cap.present);
+       printf("high_multislot_cap.value=%02x\n",
+              cm3->high_multislot_cap.value);
+       printf("\n");
+       printf("geran_feature_package_2=%u\n", cm3->geran_feature_package_2);
+       printf("gmsk_multislot_power_prof=%02x\n",
+              cm3->gmsk_multislot_power_prof);
+       printf("psk8_multislot_power_prof=%02x\n",
+              cm3->psk8_multislot_power_prof);
+       printf("\n");
+       printf("t_gsm_400_bands_supp.present=%u\n",
+              cm3->t_gsm_400_bands_supp.present);
+       printf("t_gsm_400_bands_supp.value=%02x\n",
+              cm3->t_gsm_400_bands_supp.value);
+       printf("t_gsm_400_bands_supp.assoc_radio_cap=%02x\n",
+              cm3->t_gsm_400_bands_supp.assoc_radio_cap);
+       printf("\n");
+       printf("dl_advanced_rx_perf=%02x\n", cm3->dl_advanced_rx_perf);
+       printf("dtm_enhancements_cap=%u\n", cm3->dtm_enhancements_cap);
+       printf("\n");
+       printf("dtm_gprs_high_multislot_cap.present=%u\n",
+              cm3->dtm_gprs_high_multislot_cap.present);
+       printf("dtm_gprs_high_multislot_cap.mslot_class=%02x\n",
+              cm3->dtm_gprs_high_multislot_cap.mslot_class);
+       printf("dtm_gprs_high_multislot_cap.offset_required=%u\n",
+              cm3->dtm_gprs_high_multislot_cap.offset_required);
+       printf
+           
("dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.present=%u\n",
+            cm3->dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.
+            present);
+       printf
+           
("dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.mslot_class=%02x\n",
+            cm3->dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.
+            mslot_class);
+       printf("\n");
+       printf("repeated_acch_capability=%u\n", cm3->repeated_acch_capability);
+       printf("\n");
+       printf("gsm_710_assoc_radio_cap.present=%u\n",
+              cm3->gsm_710_assoc_radio_cap.present);
+       printf("gsm_710_assoc_radio_cap.value=%02x\n",
+              cm3->gsm_710_assoc_radio_cap.value);
+       printf("\n");
+       printf("t_gsm_810_assoc_radio_cap.present=%u\n",
+              cm3->t_gsm_810_assoc_radio_cap.present);
+       printf("t_gsm_810_assoc_radio_cap.value=%02x\n",
+              cm3->t_gsm_810_assoc_radio_cap.value);
+       printf("\n");
+       printf("ciphering_mode_setting_cap=%u\n",
+              cm3->ciphering_mode_setting_cap);
+       printf("add_pos_cap=%u\n", cm3->add_pos_cap);
+       printf("e_utra_fdd_supp=%u\n", cm3->e_utra_fdd_supp);
+       printf("e_utra_tdd_supp=%u\n", cm3->e_utra_tdd_supp);
+       printf("e_utra_meas_rep_supp=%u\n", cm3->e_utra_meas_rep_supp);
+       printf("prio_resel_supp=%u\n", cm3->prio_resel_supp);
+       printf("utra_csg_cells_rep=%u\n", cm3->utra_csg_cells_rep);
+       printf("vamos_level=%02x\n", cm3->vamos_level);
+       printf("tighter_capability=%02x\n", cm3->tighter_capability);
+       printf("sel_ciph_dl_sacch=%u\n", cm3->sel_ciph_dl_sacch);
+       printf("cs_ps_srvcc_geran_utra=%02x\n", cm3->cs_ps_srvcc_geran_utra);
+       printf("cs_ps_srvcc_geran_eutra=%02x\n", cm3->cs_ps_srvcc_geran_eutra);
+       printf("geran_net_sharing=%u\n", cm3->geran_net_sharing);
+       printf("e_utra_wb_rsrq_meas_supp=%u\n", cm3->e_utra_wb_rsrq_meas_supp);
+       printf("er_band_support=%u\n", cm3->er_band_support);
+       printf("utra_mult_band_ind_supp=%u\n", cm3->utra_mult_band_ind_supp);
+       printf("e_utra_mult_band_ind_supp=%u\n",
+              cm3->e_utra_mult_band_ind_supp);
+       printf("extended_tsc_set_cap_supp=%u\n",
+              cm3->extended_tsc_set_cap_supp);
+       printf("extended_earfcn_val_range=%u\n",
+              cm3->extended_earfcn_val_range);
+}
+
+static void test_decode_classmark3(void)
+{
+       struct gsm48_classmark3 cm3;
+       const uint8_t cm3_1[] = { 0x60, 0x14, 0x04, 0x2f, 0x65, 0x00, 0x20, 
0x03, 0x40, 0x4a };
+       const uint8_t cm3_2[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
+       const uint8_t cm3_3[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
+
+       printf("=====cm3_1=====\n");
+        gsm48_decode_classmark3(&cm3, cm3_1, sizeof(cm3_1));
+       dump_cm3(&cm3);
+       printf("\n");
+
+       printf("=====cm3_2=====\n");
+        gsm48_decode_classmark3(&cm3, cm3_2, sizeof(cm3_2));
+       dump_cm3(&cm3);
+       printf("\n");
+
+       printf("=====cm3_3=====\n");
+        gsm48_decode_classmark3(&cm3, cm3_3, sizeof(cm3_3));
+       dump_cm3(&cm3);
+       printf("\n");
+}
+
 static void test_mid_from_tmsi(void)
 {
        static const uint8_t res[] = { 0x17, 0x05, 0xf4, 0xaa, 0xbb, 0xcc, 0xdd 
};
@@ -1550,6 +1747,7 @@
        test_bcd_number_encode_decode();
        test_ra_cap();
        test_lai_encode_decode();
+       test_decode_classmark3();

        test_si_range_helpers();
        test_arfcn_filter();
diff --git a/tests/gsm0408/gsm0408_test.ok b/tests/gsm0408/gsm0408_test.ok
index 3e6ae1f..52c4ea7 100644
--- a/tests/gsm0408/gsm0408_test.ok
+++ b/tests/gsm0408/gsm0408_test.ok
@@ -385,6 +385,348 @@
   Encoded 21 63 54 00 17
   gsm48_decode_lai2() gives  123-456-23 (3-digit MNC)
   passed
+=====cm3_1=====
+mult_band_supp=06
+a5_bits=00
+assoc_radio_cap_1=04
+assoc_radio_cap_2=01
+
+r_support.present=0
+r_support.r_gsm_assoc_radio_cap=00
+
+hscsd_mult_slot_cap.present=0
+hscsd_mult_slot_cap.mslot_class=00
+
+ucs2_treatment=0
+extended_meas_cap=0
+
+ms_meas_cap.present=0
+ms_meas_cap.sms_value=00
+ms_meas_cap.sm_value=00
+
+ms_pos_method_cap.present=1
+ms_pos_method_cap.method=01
+
+ecsd_multislot_cap.present=0
+ecsd_multislot_cap.mslot_class=00
+
+psk8_struct.present=1
+psk8_struct.mod_cap=1
+psk8_struct.rf_pwr_cap_1.present=1
+psk8_struct.rf_pwr_cap_1.value=02
+psk8_struct.rf_pwr_cap_2.present=1
+psk8_struct.rf_pwr_cap_2.value=02
+
+gsm_400_bands_supp.present=0
+gsm_400_bands_supp.value=00
+gsm_400_bands_supp.assoc_radio_cap=00
+
+gsm_850_assoc_radio_cap.present=1
+gsm_850_assoc_radio_cap.value=04
+
+gsm_1900_assoc_radio_cap.present=0
+gsm_1900_assoc_radio_cap.value=00
+
+umts_fdd_rat_cap=0
+umts_tdd_rat_cap=0
+cdma200_rat_cap=0
+
+dtm_gprs_multislot_cap.present=0
+dtm_gprs_multislot_cap.mslot_class=00
+dtm_gprs_multislot_cap.single_slot_dtm=0
+dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present=0
+dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class=00
+
+single_band_supp.present=0
+single_band_supp.value=0
+
+gsm_750_assoc_radio_cap.present=0
+gsm_750_assoc_radio_cap.value=00
+
+umts_1_28_mcps_tdd_rat_cap=0
+geran_feature_package=1
+
+extended_dtm_gprs_multislot_cap.present=0
+extended_dtm_gprs_multislot_cap.mslot_class=00
+extended_dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present=0
+extended_dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class=00
+
+high_multislot_cap.present=0
+high_multislot_cap.value=00
+
+geran_feature_package_2=0
+gmsk_multislot_power_prof=00
+psk8_multislot_power_prof=00
+
+t_gsm_400_bands_supp.present=0
+t_gsm_400_bands_supp.value=00
+t_gsm_400_bands_supp.assoc_radio_cap=00
+
+dl_advanced_rx_perf=01
+dtm_enhancements_cap=1
+
+dtm_gprs_high_multislot_cap.present=0
+dtm_gprs_high_multislot_cap.mslot_class=00
+dtm_gprs_high_multislot_cap.offset_required=0
+dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.present=0
+dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.mslot_class=00
+
+repeated_acch_capability=1
+
+gsm_710_assoc_radio_cap.present=0
+gsm_710_assoc_radio_cap.value=00
+
+t_gsm_810_assoc_radio_cap.present=0
+t_gsm_810_assoc_radio_cap.value=00
+
+ciphering_mode_setting_cap=0
+add_pos_cap=0
+e_utra_fdd_supp=0
+e_utra_tdd_supp=0
+e_utra_meas_rep_supp=0
+prio_resel_supp=1
+utra_csg_cells_rep=0
+vamos_level=01
+tighter_capability=01
+sel_ciph_dl_sacch=0
+cs_ps_srvcc_geran_utra=00
+cs_ps_srvcc_geran_eutra=00
+geran_net_sharing=0
+e_utra_wb_rsrq_meas_supp=0
+er_band_support=0
+utra_mult_band_ind_supp=0
+e_utra_mult_band_ind_supp=0
+extended_tsc_set_cap_supp=0
+extended_earfcn_val_range=0
+
+=====cm3_2=====
+mult_band_supp=05
+a5_bits=05
+assoc_radio_cap_1=05
+assoc_radio_cap_2=05
+
+r_support.present=0
+r_support.r_gsm_assoc_radio_cap=00
+
+hscsd_mult_slot_cap.present=1
+hscsd_mult_slot_cap.mslot_class=0a
+
+ucs2_treatment=1
+extended_meas_cap=0
+
+ms_meas_cap.present=1
+ms_meas_cap.sms_value=05
+ms_meas_cap.sm_value=05
+
+ms_pos_method_cap.present=0
+ms_pos_method_cap.method=00
+
+ecsd_multislot_cap.present=1
+ecsd_multislot_cap.mslot_class=0a
+
+psk8_struct.present=1
+psk8_struct.mod_cap=0
+psk8_struct.rf_pwr_cap_1.present=1
+psk8_struct.rf_pwr_cap_1.value=01
+psk8_struct.rf_pwr_cap_2.present=0
+psk8_struct.rf_pwr_cap_2.value=00
+
+gsm_400_bands_supp.present=1
+gsm_400_bands_supp.value=01
+gsm_400_bands_supp.assoc_radio_cap=05
+
+gsm_850_assoc_radio_cap.present=0
+gsm_850_assoc_radio_cap.value=00
+
+gsm_1900_assoc_radio_cap.present=1
+gsm_1900_assoc_radio_cap.value=05
+
+umts_fdd_rat_cap=0
+umts_tdd_rat_cap=1
+cdma200_rat_cap=0
+
+dtm_gprs_multislot_cap.present=1
+dtm_gprs_multislot_cap.mslot_class=01
+dtm_gprs_multislot_cap.single_slot_dtm=0
+dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present=1
+dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class=01
+
+single_band_supp.present=0
+single_band_supp.value=0
+
+gsm_750_assoc_radio_cap.present=1
+gsm_750_assoc_radio_cap.value=05
+
+umts_1_28_mcps_tdd_rat_cap=0
+geran_feature_package=1
+
+extended_dtm_gprs_multislot_cap.present=0
+extended_dtm_gprs_multislot_cap.mslot_class=00
+extended_dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present=0
+extended_dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class=00
+
+high_multislot_cap.present=1
+high_multislot_cap.value=01
+
+geran_feature_package_2=1
+gmsk_multislot_power_prof=01
+psk8_multislot_power_prof=01
+
+t_gsm_400_bands_supp.present=0
+t_gsm_400_bands_supp.value=00
+t_gsm_400_bands_supp.assoc_radio_cap=00
+
+dl_advanced_rx_perf=01
+dtm_enhancements_cap=0
+
+dtm_gprs_high_multislot_cap.present=1
+dtm_gprs_high_multislot_cap.mslot_class=02
+dtm_gprs_high_multislot_cap.offset_required=1
+dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.present=0
+dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.mslot_class=00
+
+repeated_acch_capability=1
+
+gsm_710_assoc_radio_cap.present=0
+gsm_710_assoc_radio_cap.value=00
+
+t_gsm_810_assoc_radio_cap.present=1
+t_gsm_810_assoc_radio_cap.value=05
+
+ciphering_mode_setting_cap=0
+add_pos_cap=1
+e_utra_fdd_supp=0
+e_utra_tdd_supp=0
+e_utra_meas_rep_supp=0
+prio_resel_supp=0
+utra_csg_cells_rep=0
+vamos_level=00
+tighter_capability=00
+sel_ciph_dl_sacch=0
+cs_ps_srvcc_geran_utra=00
+cs_ps_srvcc_geran_eutra=00
+geran_net_sharing=0
+e_utra_wb_rsrq_meas_supp=0
+er_band_support=0
+utra_mult_band_ind_supp=0
+e_utra_mult_band_ind_supp=0
+extended_tsc_set_cap_supp=0
+extended_earfcn_val_range=0
+
+=====cm3_3=====
+mult_band_supp=02
+a5_bits=0a
+assoc_radio_cap_1=0a
+assoc_radio_cap_2=00
+
+r_support.present=1
+r_support.r_gsm_assoc_radio_cap=02
+
+hscsd_mult_slot_cap.present=1
+hscsd_mult_slot_cap.mslot_class=0a
+
+ucs2_treatment=1
+extended_meas_cap=0
+
+ms_meas_cap.present=1
+ms_meas_cap.sms_value=05
+ms_meas_cap.sm_value=05
+
+ms_pos_method_cap.present=0
+ms_pos_method_cap.method=00
+
+ecsd_multislot_cap.present=1
+ecsd_multislot_cap.mslot_class=0a
+
+psk8_struct.present=1
+psk8_struct.mod_cap=0
+psk8_struct.rf_pwr_cap_1.present=1
+psk8_struct.rf_pwr_cap_1.value=01
+psk8_struct.rf_pwr_cap_2.present=0
+psk8_struct.rf_pwr_cap_2.value=00
+
+gsm_400_bands_supp.present=1
+gsm_400_bands_supp.value=01
+gsm_400_bands_supp.assoc_radio_cap=05
+
+gsm_850_assoc_radio_cap.present=0
+gsm_850_assoc_radio_cap.value=00
+
+gsm_1900_assoc_radio_cap.present=1
+gsm_1900_assoc_radio_cap.value=05
+
+umts_fdd_rat_cap=0
+umts_tdd_rat_cap=1
+cdma200_rat_cap=0
+
+dtm_gprs_multislot_cap.present=1
+dtm_gprs_multislot_cap.mslot_class=01
+dtm_gprs_multislot_cap.single_slot_dtm=0
+dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present=1
+dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class=01
+
+single_band_supp.present=0
+single_band_supp.value=0
+
+gsm_750_assoc_radio_cap.present=1
+gsm_750_assoc_radio_cap.value=05
+
+umts_1_28_mcps_tdd_rat_cap=0
+geran_feature_package=1
+
+extended_dtm_gprs_multislot_cap.present=0
+extended_dtm_gprs_multislot_cap.mslot_class=00
+extended_dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present=0
+extended_dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class=00
+
+high_multislot_cap.present=1
+high_multislot_cap.value=01
+
+geran_feature_package_2=1
+gmsk_multislot_power_prof=01
+psk8_multislot_power_prof=01
+
+t_gsm_400_bands_supp.present=0
+t_gsm_400_bands_supp.value=00
+t_gsm_400_bands_supp.assoc_radio_cap=00
+
+dl_advanced_rx_perf=01
+dtm_enhancements_cap=0
+
+dtm_gprs_high_multislot_cap.present=1
+dtm_gprs_high_multislot_cap.mslot_class=02
+dtm_gprs_high_multislot_cap.offset_required=1
+dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.present=0
+dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.mslot_class=00
+
+repeated_acch_capability=1
+
+gsm_710_assoc_radio_cap.present=0
+gsm_710_assoc_radio_cap.value=00
+
+t_gsm_810_assoc_radio_cap.present=1
+t_gsm_810_assoc_radio_cap.value=04
+
+ciphering_mode_setting_cap=0
+add_pos_cap=0
+e_utra_fdd_supp=0
+e_utra_tdd_supp=0
+e_utra_meas_rep_supp=0
+prio_resel_supp=0
+utra_csg_cells_rep=0
+vamos_level=00
+tighter_capability=00
+sel_ciph_dl_sacch=0
+cs_ps_srvcc_geran_utra=00
+cs_ps_srvcc_geran_eutra=00
+geran_net_sharing=0
+e_utra_wb_rsrq_meas_supp=0
+er_band_support=0
+utra_mult_band_ind_supp=0
+e_utra_mult_band_ind_supp=0
+extended_tsc_set_cap_supp=0
+extended_earfcn_val_range=0
+
 Element is: 2 => freqs[i] = 121
 Element is: 2 => freqs[i] = 1
 Element is: 0 => freqs[i] = 68

--
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/21120
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: Id8732551b33616227609cd6fcf6c3133751a89eb
Gerrit-Change-Number: 21120
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pma...@sysmocom.de>
Gerrit-MessageType: newchange

Reply via email to