aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rwxr-xr-xcontrib/struct_endianess.py4
-rw-r--r--include/osmocom/codec/codec.h6
-rw-r--r--include/osmocom/gsm/gsm0502.h4
-rw-r--r--include/osmocom/gsm/gsm0808.h7
-rw-r--r--include/osmocom/gsm/gsm0808_utils.h5
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_08.h242
-rw-r--r--include/osmocom/gsm/protocol/gsm_08_08.h25
-rw-r--r--include/osmocom/gsm/protocol/gsm_23_041.h8
-rw-r--r--include/osmocom/usb/libusb.h30
-rw-r--r--src/codec/Makefile.am2
-rw-r--r--src/codec/gsm690.c110
-rw-r--r--src/coding/gsm0503_amr_dtx.c8
-rw-r--r--src/exec.c3
-rw-r--r--src/gsm/gsm0502.c64
-rw-r--r--src/gsm/gsm0808.c54
-rw-r--r--src/gsm/gsm0808_utils.c13
-rw-r--r--src/gsm/libosmogsm.map4
-rw-r--r--src/logging.c29
-rw-r--r--src/usb/osmo_libusb.c96
-rw-r--r--tests/codec/codec_test.c39
-rw-r--r--tests/codec/codec_test.ok9
-rw-r--r--tests/dtx/dtx_gsm0503_test.ok4
-rw-r--r--tests/gsm0808/gsm0808_test.c53
-rw-r--r--tests/gsm0808/gsm0808_test.ok6
25 files changed, 541 insertions, 287 deletions
diff --git a/README.md b/README.md
index 623804b1..07c1a2af 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ communications.
There is no clear scope of it. We simply move all shared code between
the various Osmocom projects in this library to avoid code duplication.
-The libosmcoore.git repository build multiple libraries:
+The libosmocore.git repository build multiple libraries:
* **libosmocore** contains some general-purpose functions like select-loop
abstraction, message buffers, timers, linked lists
@@ -28,7 +28,6 @@ The libosmcoore.git repository build multiple libraries:
* **libosmocodec** contains an implementation of GSM voice codecs
* **libosmocoding** contains an implementation of GSM channel coding
* **libosmosim** contains infrastructure to interface SIM/UICC/USIM cards
-* **libosmotrau** contains encoding/decoding functions for A-bis TRAU frames
Homepage
diff --git a/contrib/struct_endianess.py b/contrib/struct_endianess.py
index be73fbe2..6ce75fcb 100755
--- a/contrib/struct_endianess.py
+++ b/contrib/struct_endianess.py
@@ -17,6 +17,7 @@ re_struct_end = re.compile(r'^}[^;]*;\s*$')
re_substruct_start = re.compile(r'^\s+struct\s*{\s*$')
re_substruct_end = re.compile(r'^\s+}\s*([^;]*\s)[a-zA-Z_][a-zA-Z_0-9]*\s*;\s*$')
+re_unnamed_substruct_end = re.compile(r'^\s+}\s*;\s*$')
re_int_def = re.compile(r'(^\s*((const|unsigned|signed|char|int|long|int[0-9]+_t|uint[0-9]_t)\s+)+\s*)([^;]*;)',
re.DOTALL | re.MULTILINE)
@@ -73,7 +74,8 @@ def section_struct_body(struct_body_lines):
line = struct_body_lines[j]
if (re_substruct_start.fullmatch(line)
- or re_substruct_end.fullmatch(line)):
+ or re_substruct_end.fullmatch(line)
+ or re_unnamed_substruct_end.fullmatch(line)):
end_def()
arbitrary_part.append(line)
j += 1
diff --git a/include/osmocom/codec/codec.h b/include/osmocom/codec/codec.h
index 6a1bf9fb..cbdad75e 100644
--- a/include/osmocom/codec/codec.h
+++ b/include/osmocom/codec/codec.h
@@ -6,6 +6,7 @@
#include <stdbool.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/bits.h>
/* TS 101318 Chapter 5.1: 260 bits + 4bit sig */
#define GSM_FR_BYTES 33
@@ -51,6 +52,11 @@ enum osmo_amr_quality {
AMR_GOOD = 1
};
+extern const uint8_t gsm690_bitlength[AMR_NO_DATA+1];
+
+int osmo_amr_s_to_d(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode);
+int osmo_amr_d_to_s(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode);
+
/*! Check if given AMR Frame Type is a speech frame
* \param[in] ft AMR Frame Type
* \returns true if AMR with given Frame Type contains voice, false otherwise
diff --git a/include/osmocom/gsm/gsm0502.h b/include/osmocom/gsm/gsm0502.h
index c9901dfd..cb993dce 100644
--- a/include/osmocom/gsm/gsm0502.h
+++ b/include/osmocom/gsm/gsm0502.h
@@ -47,3 +47,7 @@ enum gsm0502_fn_remap_channel {
};
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);
diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h
index 373b4341..34cec3ca 100644
--- a/include/osmocom/gsm/gsm0808.h
+++ b/include/osmocom/gsm/gsm0808.h
@@ -315,6 +315,13 @@ const char *gsm0808_bssap_name(uint8_t msg_type);
const char *gsm0808_cause_name(enum gsm0808_cause cause);
const char *gsm0808_cause_class_name(enum gsm0808_cause_class class);
+/*! Parse Cause TLV 3GPP TS 08.08 §3.2.2.5
+ * \returns Cause value */
+enum gsm0808_cause gsm0808_get_cause(const struct tlv_parsed *tp);
+
+const char *gsm0808_diagnostics_octet_location_str(uint8_t pointer);
+const char *gsm0808_diagnostics_bit_location_str(uint8_t bit_pointer);
+
extern const struct value_string gsm0808_lcls_config_names[];
extern const struct value_string gsm0808_lcls_control_names[];
extern const struct value_string gsm0808_lcls_status_names[];
diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h
index ccdf5ed9..59db6edc 100644
--- a/include/osmocom/gsm/gsm0808_utils.h
+++ b/include/osmocom/gsm/gsm0808_utils.h
@@ -145,7 +145,7 @@ int gsm48_mr_cfg_from_gsm0808_sc_cfg(struct gsm48_multi_rate_conf *cfg, uint16_t
/*! \returns 3GPP TS 08.08 §3.2.2.5 Class of a given Cause */
static inline enum gsm0808_cause_class gsm0808_cause_class(enum gsm0808_cause cause)
{
- return (cause << 1) >> 4;
+ return (cause >> 4) & 0x7;
}
/*! \returns true if 3GPP TS 08.08 §3.2.2.5 Class has extended bit set */
@@ -155,7 +155,8 @@ static inline bool gsm0808_cause_ext(enum gsm0808_cause cause)
return (cause & 0x80) && !(cause & 0x0F);
}
-int gsm0808_get_cipher_reject_cause(const struct tlv_parsed *tp);
+int gsm0808_get_cipher_reject_cause(const struct tlv_parsed *tp)
+OSMO_DEPRECATED("Use gsm0808_get_cause() instead");
/*! \returns 3GPP TS 48.008 3.2.2.49 Current Channel Type 1 from enum gsm_chan_t. */
static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type)
diff --git a/include/osmocom/gsm/protocol/gsm_04_08.h b/include/osmocom/gsm/protocol/gsm_04_08.h
index 8370eca1..f8f2eabd 100644
--- a/include/osmocom/gsm/protocol/gsm_04_08.h
+++ b/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -77,7 +77,6 @@ char *osmo_gsm48_classmark_a5_name_c(const void *ctx, const struct osmo_gsm48_cl
void osmo_gsm48_classmark_update(struct osmo_gsm48_classmark *dst, const struct osmo_gsm48_classmark *src);
int8_t osmo_gsm48_rfpowercap2powerclass(enum gsm_band band, uint8_t rf_power_cap);
/* Chapter 10.5.2.1b.3 */
-#if OSMO_IS_LITTLE_ENDIAN == 1
struct gsm48_range_1024 {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t w1_hi:2,
@@ -131,64 +130,8 @@ struct gsm48_range_1024 {
uint8_t w15_lo:2, w16:6;
#endif
} __attribute__ ((packed));
-#else
-struct gsm48_range_1024 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t form_id:5,
- f0:1,
- w1_hi:2;
- uint8_t w1_lo;
- uint8_t w2_hi;
- uint8_t w2_lo:1,
- w3_hi:7;
- uint8_t w3_lo:2,
- w4_hi:6;
- uint8_t w4_lo:2,
- w5_hi:6;
- uint8_t w5_lo:2,
- w6_hi:6;
- uint8_t w6_lo:2,
- w7_hi:6;
- uint8_t w7_lo:2,
- w8_hi:6;
- uint8_t w8_lo:1,
- w9:7;
- uint8_t w10:7,
- w11_hi:1;
- uint8_t w11_lo:6,
- w12_hi:2;
- uint8_t w12_lo:5,
- w13_hi:3;
- uint8_t w13_lo:4,
- w14_hi:4;
- uint8_t w14_lo:3,
- w15_hi:5;
- uint8_t w15_lo:2,
- w16:6;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t w1_hi:2, f0:1, form_id:5;
- uint8_t w1_lo;
- uint8_t w2_hi;
- uint8_t w3_hi:7, w2_lo:1;
- uint8_t w4_hi:6, w3_lo:2;
- uint8_t w5_hi:6, w4_lo:2;
- uint8_t w6_hi:6, w5_lo:2;
- uint8_t w7_hi:6, w6_lo:2;
- uint8_t w8_hi:6, w7_lo:2;
- uint8_t w9:7, w8_lo:1;
- uint8_t w11_hi:1, w10:7;
- uint8_t w12_hi:2, w11_lo:6;
- uint8_t w13_hi:3, w12_lo:5;
- uint8_t w14_hi:4, w13_lo:4;
- uint8_t w15_hi:5, w14_lo:3;
- uint8_t w16:6, w15_lo:2;
-#endif
-} __attribute__ ((packed));
-#endif
/* Chapter 10.5.2.1b.4 */
-#if OSMO_IS_LITTLE_ENDIAN == 1
struct gsm48_range_512 {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t orig_arfcn_hi:1,
@@ -242,64 +185,8 @@ struct gsm48_range_512 {
uint8_t w16_lo:3, w17:5;
#endif
} __attribute__ ((packed));
-#else
-struct gsm48_range_512 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t form_id:7,
- orig_arfcn_hi:1;
- uint8_t orig_arfcn_mid;
- uint8_t orig_arfcn_lo:1,
- w1_hi:7;
- uint8_t w1_lo:2,
- w2_hi:6;
- uint8_t w2_lo:2,
- w3_hi:6;
- uint8_t w3_lo:2,
- w4_hi:6;
- uint8_t w4_lo:1,
- w5:7;
- uint8_t w6:7,
- w7_hi:1;
- uint8_t w7_lo:6,
- w8_hi:2;
- uint8_t w8_lo:4,
- w9_hi:4;
- uint8_t w9_lo:2,
- w10:6;
- uint8_t w11:6,
- w12_hi:2;
- uint8_t w12_lo:4,
- w13_hi:4;
- uint8_t w13_lo:2,
- w14:6;
- uint8_t w15:6,
- w16_hi:2;
- uint8_t w16_lo:3,
- w17:5;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t orig_arfcn_hi:1, form_id:7;
- uint8_t orig_arfcn_mid;
- uint8_t w1_hi:7, orig_arfcn_lo:1;
- uint8_t w2_hi:6, w1_lo:2;
- uint8_t w3_hi:6, w2_lo:2;
- uint8_t w4_hi:6, w3_lo:2;
- uint8_t w5:7, w4_lo:1;
- uint8_t w7_hi:1, w6:7;
- uint8_t w8_hi:2, w7_lo:6;
- uint8_t w9_hi:4, w8_lo:4;
- uint8_t w10:6, w9_lo:2;
- uint8_t w12_hi:2, w11:6;
- uint8_t w13_hi:4, w12_lo:4;
- uint8_t w14:6, w13_lo:2;
- uint8_t w16_hi:2, w15:6;
- uint8_t w17:5, w16_lo:3;
-#endif
-} __attribute__ ((packed));
-#endif
/* Chapter 10.5.2.1b.5 */
-#if OSMO_IS_LITTLE_ENDIAN == 1
struct gsm48_range_256 {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t orig_arfcn_hi:1,
@@ -359,70 +246,8 @@ struct gsm48_range_256 {
uint8_t w20_lo:3, w21:4, spare:1;
#endif
} __attribute__ ((packed));
-#else
-struct gsm48_range_256 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t form_id:7,
- orig_arfcn_hi:1;
- uint8_t orig_arfcn_mid;
- uint8_t orig_arfcn_lo:1,
- w1_hi:7;
- uint8_t w1_lo:1,
- w2:7;
- uint8_t w3:7,
- w4_hi:1;
- uint8_t w4_lo:5,
- w5_hi:3;
- uint8_t w5_lo:3,
- w6_hi:5;
- uint8_t w6_lo:1,
- w7:6,
- w8_hi:1;
- uint8_t w8_lo:4,
- w9_hi:4;
- uint8_t w9_lo:1,
- w10:5,
- w11_hi:2;
- uint8_t w11_lo:3,
- w12:5;
- uint8_t w13:5,
- w14_hi:3;
- uint8_t w14_lo:2,
- w15:5,
- w16_hi:1;
- uint8_t w16_lo:3,
- w17:4,
- w18_hi:1;
- uint8_t w18_lo:3,
- w19:4,
- w20_hi:1;
- uint8_t w20_lo:3,
- w21:4,
- spare:1;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t orig_arfcn_hi:1, form_id:7;
- uint8_t orig_arfcn_mid;
- uint8_t w1_hi:7, orig_arfcn_lo:1;
- uint8_t w2:7, w1_lo:1;
- uint8_t w4_hi:1, w3:7;
- uint8_t w5_hi:3, w4_lo:5;
- uint8_t w6_hi:5, w5_lo:3;
- uint8_t w8_hi:1, w7:6, w6_lo:1;
- uint8_t w9_hi:4, w8_lo:4;
- uint8_t w11_hi:2, w10:5, w9_lo:1;
- uint8_t w12:5, w11_lo:3;
- uint8_t w14_hi:3, w13:5;
- uint8_t w16_hi:1, w15:5, w14_lo:2;
- uint8_t w18_hi:1, w17:4, w16_lo:3;
- uint8_t w20_hi:1, w19:4, w18_lo:3;
- uint8_t spare:1, w21:4, w20_lo:3;
-#endif
-} __attribute__ ((packed));
-#endif
/* Chapter 10.5.2.1b.6 */
-#if OSMO_IS_LITTLE_ENDIAN == 1
struct gsm48_range_128 {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t orig_arfcn_hi:1,
@@ -484,69 +309,6 @@ struct gsm48_range_128 {
uint8_t w26_lo:1, w27:3, w28:3, spare:1;
#endif
} __attribute__ ((packed));
-#else
-struct gsm48_range_128 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t form_id:7,
- orig_arfcn_hi:1;
- uint8_t orig_arfcn_mid;
- uint8_t orig_arfcn_lo:1,
- w1:7;
- uint8_t w2:6,
- w3_hi:2;
- uint8_t w3_lo:4,
- w4_hi:4;
- uint8_t w4_lo:1,
- w5:5,
- w6_hi:2;
- uint8_t w6_lo:3,
- w7:5;
- uint8_t w8:4,
- w9:4;
- uint8_t w10:4,
- w11:4;
- uint8_t w12:4,
- w13:4;
- uint8_t w14:4,
- w15:4;
- uint8_t w16:3,
- w17:3,
- w18_hi:2;
- uint8_t w18_lo:1,
- w19:3,
- w20:3,
- w21_hi:1;
- uint8_t w21_lo:2,
- w22:3,
- w23:3;
- uint8_t w24:3,
- w25:3,
- w26_hi:2;
- uint8_t w26_lo:1,
- w27:3,
- w28:3,
- spare:1;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t orig_arfcn_hi:1, form_id:7;
- uint8_t orig_arfcn_mid;
- uint8_t w1:7, orig_arfcn_lo:1;
- uint8_t w3_hi:2, w2:6;
- uint8_t w4_hi:4, w3_lo:4;
- uint8_t w6_hi:2, w5:5, w4_lo:1;
- uint8_t w7:5, w6_lo:3;
- uint8_t w9:4, w8:4;
- uint8_t w11:4, w10:4;
- uint8_t w13:4, w12:4;
- uint8_t w15:4, w14:4;
- uint8_t w18_hi:2, w17:3, w16:3;
- uint8_t w21_hi:1, w20:3, w19:3, w18_lo:1;
- uint8_t w23:3, w22:3, w21_lo:2;
- uint8_t w26_hi:2, w25:3, w24:3;
- uint8_t spare:1, w28:3, w27:3, w26_lo:1;
-#endif
-} __attribute__ ((packed));
-#endif
/* Chapter 10.5.2.1b.7 */
struct gsm48_var_bit {
@@ -902,7 +664,7 @@ struct gsm48_pag_resp {
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
uint8_t key_seq:4, spare:4;
union {
- uint32_t classmark2; /* Backward compatibility */
+ uint32_t classmark2;
struct {
uint8_t cm2_len;
struct gsm48_classmark2 cm2;
@@ -1053,7 +815,7 @@ struct gsm48_service_request {
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
uint8_t cipher_key_seq:4, cm_service_type:4;
union {
- uint32_t classmark; /* Backward compatibility */
+ uint32_t classmark;
struct {
uint8_t cm2_len;
struct gsm48_classmark2 classmark2;
diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h
index e791b070..1390f0e8 100644
--- a/include/osmocom/gsm/protocol/gsm_08_08.h
+++ b/include/osmocom/gsm/protocol/gsm_08_08.h
@@ -41,27 +41,21 @@ struct bssmap_header {
} __attribute__((packed));
struct dtap_header {
-#if OSMO_IS_LITTLE_ENDIAN
uint8_t type;
union {
uint8_t link_id; /* Backward compatibility */
struct {
+#if OSMO_IS_LITTLE_ENDIAN
uint8_t dlci_cc:2,
dlci_spare:3,
dlci_sapi:3; /* enum gsm0406_dlc_sapi */
- };
- };
- uint8_t length;
#elif OSMO_IS_BIG_ENDIAN
- uint8_t type;
- union {
- uint8_t link_id;
- struct {
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
uint8_t dlci_sapi:3, dlci_spare:3, dlci_cc:2;
+#endif
};
};
uint8_t length;
-#endif
} __attribute__((packed));
/* Data Link Control SAPI, GSM 08.06 § 6.3.2, GSM 04.06 § 3.3.3 */
@@ -669,3 +663,16 @@ enum gsm0808_lcls_status {
GSM0808_LCLS_STS_LOCALLY_SWITCHED = 0x04,
GSM0808_LCLS_STS_NA = 0xFF
};
+
+/* 3GPP TS 48.008 3.2.2.32 Diagnostics */
+struct gsm0808_diagnostics {
+ uint8_t error_pointer_octet;
+#if OSMO_IS_LITTLE_ENDIAN
+ 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) */
+ uint8_t error_pointer_bit:4, error_pointer_bit_spare:4;
+#endif
+ uint8_t msg[0]; /*! received message which provoked the error */
+} __attribute__((packed));
diff --git a/include/osmocom/gsm/protocol/gsm_23_041.h b/include/osmocom/gsm/protocol/gsm_23_041.h
index c75c0883..e726cff2 100644
--- a/include/osmocom/gsm/protocol/gsm_23_041.h
+++ b/include/osmocom/gsm/protocol/gsm_23_041.h
@@ -1,5 +1,7 @@
#pragma once
+#include <osmocom/core/endian.h>
+
/* Section 9.4.1.2: GSM Message Format */
struct gsm23041_msg_param_gsm {
uint16_t serial_nr;
@@ -9,9 +11,9 @@ struct gsm23041_msg_param_gsm {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t num_pages:4,
page_nr:4;
-#else
- uint8_t page_nr:4,
- num_pages:4;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+ uint8_t page_nr:4, num_pages:4;
#endif
} page_param;
uint8_t content[0];
diff --git a/include/osmocom/usb/libusb.h b/include/osmocom/usb/libusb.h
index 2220e03d..9ad3f71a 100644
--- a/include/osmocom/usb/libusb.h
+++ b/include/osmocom/usb/libusb.h
@@ -55,6 +55,31 @@ struct usb_interface_match {
uint8_t string_idx;
};
+/*! Description of the USB device+interface we're looking for */
+struct osmo_usb_matchspec {
+ /*! specify the USB device */
+ struct {
+ int vendor_id; /*!< typically -1 for compile time defaults */
+ int product_id; /*!< typically -1 for compile time defaults */
+ char *path; /*!< used for disambiguation when multiple matches; can be NULL */
+ } dev;
+
+ /*! specify the USB configuration */
+ int config_id; /*!< typically -1 unless user selects specific configuration */
+
+ /*! specify the USB interface */
+ struct {
+ /* typically those three are set to application defaults */
+ int class; /*!< -1 or a user-specified class */
+ int subclass; /*!< -1 or a user-specified subclass */
+ int proto; /*!< -1 or a user-specified protocol */
+
+ /* typically those two are -1; but user can override them */
+ int num;
+ int altsetting;
+ } intf;
+};
+
char *osmo_libusb_dev_get_path_buf(char *buf, size_t bufsize, libusb_device *dev);
char *osmo_libusb_dev_get_path_c(void *ctx, libusb_device *dev);
@@ -81,6 +106,11 @@ int osmo_libusb_find_matching_interfaces(libusb_context *luctx, const struct dev
libusb_device_handle *osmo_libusb_open_claim_interface(void *ctx, libusb_context *luctx,
const struct usb_interface_match *ifm);
+void osmo_libusb_match_init(struct osmo_usb_matchspec *cfg, int if_class, int if_subclass, int if_proto);
+
+libusb_device_handle *osmo_libusb_find_open_claim(const struct osmo_usb_matchspec *cfg,
+ const struct dev_id *default_dev_ids);
+
int osmo_libusb_get_ep_addrs(libusb_device_handle *devh, unsigned int if_num,
uint8_t *out, uint8_t *in, uint8_t *irq);
diff --git a/src/codec/Makefile.am b/src/codec/Makefile.am
index ac33aa01..778eb2ad 100644
--- a/src/codec/Makefile.am
+++ b/src/codec/Makefile.am
@@ -3,7 +3,7 @@
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
LIBVERSION=2:0:2
-AM_CPPFLAGS = -I$(top_srcdir)/include $(TALLOC_CFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include $(TALLOC_CFLAGS)
AM_CFLAGS = -Wall
if ENABLE_PSEUDOTALLOC
diff --git a/src/codec/gsm690.c b/src/codec/gsm690.c
index 8ab1df12..cc6cdf0c 100644
--- a/src/codec/gsm690.c
+++ b/src/codec/gsm690.c
@@ -2,6 +2,7 @@
* GSM 06.90 - GSM AMR Codec. */
/*
* (C) 2010 Sylvain Munaut <tnt@246tNt.com>
+ * (C) 2020 Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -29,6 +30,7 @@
#include <stdlib.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/bits.h>
#include <osmocom/codec/codec.h>
/*
* These table map between the raw encoder parameter output and
@@ -216,6 +218,114 @@ const uint16_t gsm690_4_75_bitorder[95] = {
92, 31, 52, 65, 86,
};
+/*! These constants refer to the length of one "AMR core frame" as per
+ * TS 26.101 Section 4.2.2 / Table 2. */
+const uint8_t gsm690_bitlength[AMR_NO_DATA+1] = {
+ [AMR_4_75] = 95,
+ [AMR_5_15] = 103,
+ [AMR_5_90] = 118,
+ [AMR_6_70] = 134,
+ [AMR_7_40] = 148,
+ [AMR_7_95] = 159,
+ [AMR_10_2] = 204,
+ [AMR_12_2] = 244,
+ [AMR_SID] = 39,
+};
+
+struct ts26101_reorder_table {
+ /*! Table as per TS 26.101 Annex B to compute d-bits from s-bits */
+ const uint16_t *s_to_d;
+ /*! size of table */
+ uint8_t len;
+};
+
+static const struct ts26101_reorder_table ts26101_reorder_tables[8] = {
+ [AMR_4_75] = {
+ .s_to_d = gsm690_4_75_bitorder,
+ .len = ARRAY_SIZE(gsm690_4_75_bitorder),
+ },
+ [AMR_5_15] = {
+ .s_to_d = gsm690_5_15_bitorder,
+ .len = ARRAY_SIZE(gsm690_5_15_bitorder),
+ },
+ [AMR_5_90] = {
+ .s_to_d = gsm690_5_9_bitorder,
+ .len = ARRAY_SIZE(gsm690_5_9_bitorder),
+ },
+ [AMR_6_70] = {
+ .s_to_d = gsm690_6_7_bitorder,
+ .len = ARRAY_SIZE(gsm690_6_7_bitorder),
+ },
+ [AMR_7_40] = {
+ .s_to_d = gsm690_7_4_bitorder,
+ .len = ARRAY_SIZE(gsm690_7_4_bitorder),
+ },
+ [AMR_7_95] = {
+ .s_to_d = gsm690_7_95_bitorder,
+ .len = ARRAY_SIZE(gsm690_7_95_bitorder),
+ },
+ [AMR_10_2] = {
+ .s_to_d = gsm690_10_2_bitorder,
+ .len = ARRAY_SIZE(gsm690_10_2_bitorder),
+ },
+ [AMR_12_2] = {
+ .s_to_d = gsm690_12_2_bitorder,
+ .len = ARRAY_SIZE(gsm690_12_2_bitorder),
+ },
+};
+
+/*! Convert from S-bits (codec output) to d-bits.
+ * \param[out] out user-provided output buffer for generated unpacked d-bits
+ * \param[in] in input buffer for unpacked s-bits
+ * \param[in] n_bits number of bits (in both in and out)
+ * \param[in] AMR mode (0..7) */
+int osmo_amr_s_to_d(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode)
+{
+ const struct ts26101_reorder_table *tbl;
+ int i;
+
+ if (amr_mode >= ARRAY_SIZE(ts26101_reorder_tables))
+ return -ENODEV;
+
+ tbl = &ts26101_reorder_tables[amr_mode];
+
+ if (n_bits > tbl->len)
+ return -EINVAL;
+
+ for (i = 0; i < n_bits; i++) {
+ uint16_t n = tbl->s_to_d[i];
+ out[i] = in[n];
+ }
+
+ return n_bits;
+}
+
+/*! Convert from d-bits to s-bits (codec input).
+ * \param[out] out user-provided output buffer for generated unpacked s-bits
+ * \param[in] in input buffer for unpacked d-bits
+ * \param[in] n_bits number of bits (in both in and out)
+ * \param[in] AMR mode (0..7) */
+int osmo_amr_d_to_s(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode)
+{
+ const struct ts26101_reorder_table *tbl;
+ int i;
+
+ if (amr_mode >= ARRAY_SIZE(ts26101_reorder_tables))
+ return -ENODEV;
+
+ tbl = &ts26101_reorder_tables[amr_mode];
+
+ if (n_bits > tbl->len)
+ return -EINVAL;
+
+ for (i = 0; i < n_bits; i++) {
+ uint16_t n = tbl->s_to_d[i];
+ out[n] = in[i];
+ }
+
+ return n_bits;
+}
+
/* See also RFC 4867 §3.6, Table 1, Column "Total speech bits" */
static const uint8_t amr_len_by_ft[16] = {
12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0
diff --git a/src/coding/gsm0503_amr_dtx.c b/src/coding/gsm0503_amr_dtx.c
index 724cf091..7069b967 100644
--- a/src/coding/gsm0503_amr_dtx.c
+++ b/src/coding/gsm0503_amr_dtx.c
@@ -45,16 +45,18 @@ static const ubit_t codec_mode_3_sid[] = { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0
static const ubit_t codec_mode_4_sid[] = { 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1 };
const struct value_string gsm0503_amr_dtx_frame_names[] = {
+ { AMR_OTHER, "AMR_OTHER (audio)" },
{ AFS_SID_FIRST, "AFS_SID_FIRST" },
- { AFS_SID_UPDATE, "AFS_SID_UPDATE" },
+ { AFS_SID_UPDATE, "AFS_SID_UPDATE (marker)" },
+ { AFS_SID_UPDATE_CN, "AFS_SID_UPDATE_CN (audio)" },
{ AFS_ONSET, "AFS_ONSET" },
- { AHS_SID_UPDATE, "AHS_SID_UPDATE" },
+ { AHS_SID_UPDATE, "AHS_SID_UPDATE (marker)" },
+ { AHS_SID_UPDATE_CN, "AHS_SID_UPDATE_CN (audio)" },
{ AHS_SID_FIRST_P1, "AHS_SID_FIRST_P1" },
{ AHS_SID_FIRST_P2, "AHS_SID_FIRST_P2" },
{ AHS_ONSET, "AHS_ONSET" },
{ AHS_SID_FIRST_INH, "AHS_SID_FIRST_INH" },
{ AHS_SID_UPDATE_INH, "AHS_SID_UPDATE_INH" },
- { AMR_OTHER, "NON DTX FRAME (OTHER)" },
{ 0, NULL }
};
diff --git a/src/exec.c b/src/exec.c
index 578e2b11..2a03ba80 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -211,7 +211,8 @@ extern char **environ;
*/
int osmo_system_nowait2(const char *command, const char **env_whitelist, char **addl_env, const char *user)
{
- struct passwd _pw, *pw;
+ struct passwd _pw;
+ struct passwd *pw = NULL;
int getpw_buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
int rc;
diff --git a/src/gsm/gsm0502.c b/src/gsm/gsm0502.c
index 1a71e617..e34d3f57 100644
--- a/src/gsm/gsm0502.c
+++ b/src/gsm/gsm0502.c
@@ -2,6 +2,8 @@
* Paging helper code */
/*
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by Sylvain Munaut <tnt@246tNt.com>
+ *
* All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+
@@ -193,7 +195,7 @@ uint32_t gsm0502_fn_remap(uint32_t fn, enum gsm0502_fn_remap_channel channel)
}
if (sub == -1) {
- LOGP(DLGLOBAL, LOGL_ERROR, "could not remap frame number!, fn=%"PRIu32"\n", fn);
+ LOGP(DLGLOBAL, LOGL_ERROR, "could not remap frame number!, fn=%" PRIu32 "\n", fn);
return fn;
}
@@ -201,3 +203,63 @@ uint32_t gsm0502_fn_remap(uint32_t fn, enum gsm0502_fn_remap_channel channel)
return fn_map;
}
+
+/* Magic numbers (RNTABLE) for pseudo-random hopping sequence generation. */
+static const uint8_t rn_table[114] = {
+ 48, 98, 63, 1, 36, 95, 78, 102, 94, 73,
+ 0, 64, 25, 81, 76, 59, 124, 23, 104, 100,
+ 101, 47, 118, 85, 18, 56, 96, 86, 54, 2,
+ 80, 34, 127, 13, 6, 89, 57, 103, 12, 74,
+ 55, 111, 75, 38, 109, 71, 112, 29, 11, 88,
+ 87, 19, 3, 68, 110, 26, 33, 31, 8, 45,
+ 82, 58, 40, 107, 32, 5, 106, 92, 62, 67,
+ 77, 108, 122, 37, 60, 66, 121, 42, 51, 126,
+ 117, 114, 4, 90, 43, 52, 53, 113, 120, 72,
+ 16, 49, 7, 79, 119, 61, 22, 84, 9, 97,
+ 91, 15, 21, 24, 46, 39, 93, 105, 65, 70,
+ 125, 99, 17, 123,
+};
+
+/*! Hopping sequence generation as per 3GPP TS 45.002, section 6.2.3.
+ * \param[in] t GSM time (TDMA frame number, T1/T2/T3).
+ * \param[in] hsn Hopping Sequence Number.
+ * \param[in] maio Mobile Allocation Index Offset.
+ * \param[in] n number of entries in mobile allocation (arfcn table).
+ * \param[in] ma array of ARFCNs (sorted in ascending order)
+ * representing the Mobile Allocation.
+ * \returns ARFCN to use for given input parameters at time 't'
+ * or Mobile Allocation Index if ma == NULL.
+ */
+uint16_t gsm0502_hop_seq_gen(const struct gsm_time *t,
+ uint8_t hsn, uint8_t maio,
+ size_t n, const uint16_t *ma)
+{
+ unsigned int mai;
+
+ if (hsn == 0) {
+ /* cyclic hopping */
+ mai = (t->fn + maio) % n;
+ } else {
+ /* pseudo random hopping */
+ int m, mp, tp, s, pnm;
+
+ pnm = (n >> 0) | (n >> 1)
+ | (n >> 2) | (n >> 3)
+ | (n >> 4) | (n >> 5)
+ | (n >> 6);
+
+ m = t->t2 + rn_table[(hsn ^ (t->t1 & 63)) + t->t3];
+ mp = m & pnm;
+
+ if (mp < n)
+ s = mp;
+ else {
+ tp = t->t3 & pnm;
+ s = (mp + tp) % n;
+ }
+
+ mai = (s + maio) % n;
+ }
+
+ return ma ? ma[mai] : mai;
+}
diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c
index 02288e6c..23468c3e 100644
--- a/src/gsm/gsm0808.c
+++ b/src/gsm/gsm0808.c
@@ -21,6 +21,8 @@
*
*/
+#include <string.h>
+
#include <osmocom/core/byteswap.h>
#include <osmocom/gsm/gsm0808.h>
#include <osmocom/gsm/gsm0808_utils.h>
@@ -34,6 +36,9 @@
* message generation/encoding.
*/
+/*! Char buffer to return strings from functions */
+static __thread char str_buff[512];
+
/*! Create "Complete L3 Info" for AoIP, legacy implementation.
* Instead use gsm0808_create_layer3_aoip2(), which is capable of three-digit MNC with leading zeros.
* \param[in] msg_l3 msgb containing Layer 3 Message
@@ -1654,6 +1659,55 @@ const char *gsm0808_cause_name(enum gsm0808_cause cause)
return get_value_string(gsm0808_cause_names, cause);
}
+enum gsm0808_cause gsm0808_get_cause(const struct tlv_parsed *tp)
+{
+ const uint8_t *buf = TLVP_VAL_MINLEN(tp, GSM0808_IE_CAUSE, 1);
+
+ if (!buf)
+ return -EBADMSG;
+
+ if (TLVP_LEN(tp, GSM0808_IE_CAUSE) > 1) {
+ if (!gsm0808_cause_ext(buf[0]))
+ return -EINVAL;
+ return buf[1];
+ }
+
+ return buf[0];
+}
+
+const char *gsm0808_diagnostics_octet_location_str(uint8_t pointer)
+{
+ switch (pointer) {
+ case 0:
+ return "Error location not determined";
+ case 1:
+ return "The first octet of the message received (i.e. the message type) was found erroneous (unknown)";
+ case 0xfd:
+ return "The first octet of the BSSAP header (Discrimination) was found erroneous";
+ case 0xfe:
+ return "(DTAP only) The DLCI (second) octet of the BSSAP header was found erroneous";
+ case 0xff:
+ return "The last octet of the BSSAP header (length indicator) was found erroneous";
+ default:
+ snprintf(str_buff, sizeof(str_buff), "The %d octet of the message received was found erroneous", pointer);
+ return str_buff;
+ }
+}
+
+const char *gsm0808_diagnostics_bit_location_str(uint8_t bit_pointer)
+{
+ if (bit_pointer == 0) {
+ return "No particular part of the octet is indicated";
+ } else if (bit_pointer > 8) {
+ return "Reserved value";
+ }
+
+ snprintf(str_buff, sizeof(str_buff),
+ "An error was provoked by the field whose most significant bit is in bit position %d",
+ bit_pointer);
+ return str_buff;
+}
+
const struct value_string gsm0808_lcls_config_names[] = {
{ GSM0808_LCLS_CFG_BOTH_WAY, "Connect both-way" },
{ GSM0808_LCLS_CFG_BOTH_WAY_AND_BICAST_UL,
diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c
index 7416d8f5..6bf771f8 100644
--- a/src/gsm/gsm0808_utils.c
+++ b/src/gsm/gsm0808_utils.c
@@ -1565,18 +1565,7 @@ int gsm48_mr_cfg_from_gsm0808_sc_cfg(struct gsm48_multi_rate_conf *cfg,
int gsm0808_get_cipher_reject_cause(const struct tlv_parsed *tp)
{
- const uint8_t *buf = TLVP_VAL_MINLEN(tp, GSM0808_IE_CAUSE, 1);
-
- if (!buf)
- return -EBADMSG;
-
- if (TLVP_LEN(tp, GSM0808_IE_CAUSE) > 1) {
- if (!gsm0808_cause_ext(buf[0]))
- return -EINVAL;
- return buf[1];
- }
-
- return buf[0];
+ return gsm0808_get_cause(tp);
}
/*! Print a human readable name of the cell identifier to the char buffer.
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index a518b289..70b39163 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -110,6 +110,7 @@ gsm0480_gen_reject;
gsm0502_calc_paging_group;
gsm0502_fn_remap;
+gsm0502_hop_seq_gen;
gsm0503_xcch;
gsm0503_rach;
@@ -157,6 +158,9 @@ gsm0808_bssap_name;
gsm0808_bssmap_name;
gsm0808_cause_name;
gsm0808_cause_class_name;
+gsm0808_get_cause;
+gsm0808_diagnostics_octet_location_str;
+gsm0808_diagnostics_bit_location_str;
gsm0808_create_ass;
gsm0808_create_ass2;
gsm0808_create_assignment_completed;
diff --git a/src/logging.c b/src/logging.c
index 4d6224d5..c14e6961 100644
--- a/src/logging.c
+++ b/src/logging.c
@@ -1026,6 +1026,10 @@ int log_targets_reopen(void)
int log_init(const struct log_info *inf, void *ctx)
{
int i;
+ struct log_info_cat *cat_ptr;
+
+ /* Ensure that log_init is not called multiple times */
+ OSMO_ASSERT(tall_log_ctx == NULL)
tall_log_ctx = talloc_named_const(ctx, 1, "logging");
if (!tall_log_ctx)
@@ -1043,29 +1047,36 @@ int log_init(const struct log_info *inf, void *ctx)
osmo_log_info->num_cat += inf->num_cat;
}
- osmo_log_info->cat = talloc_zero_array(osmo_log_info,
- struct log_info_cat,
- osmo_log_info->num_cat);
- if (!osmo_log_info->cat) {
+ cat_ptr = talloc_zero_array(osmo_log_info, struct log_info_cat,
+ osmo_log_info->num_cat);
+ if (!cat_ptr) {
talloc_free(osmo_log_info);
osmo_log_info = NULL;
return -ENOMEM;
}
- if (inf) { /* copy over the user part */
+ /* copy over the user part and sanitize loglevel */
+ if (inf) {
for (i = 0; i < inf->num_cat; i++) {
- memcpy((struct log_info_cat *) &osmo_log_info->cat[i],
- &inf->cat[i], sizeof(struct log_info_cat));
+ memcpy(&cat_ptr[i], &inf->cat[i],
+ sizeof(struct log_info_cat));
+
+ /* Make sure that the loglevel is set to NOTICE in case
+ * no loglevel has been preset. */
+ if (!cat_ptr[i].loglevel) {
+ cat_ptr[i].loglevel = LOGL_NOTICE;
+ }
}
}
/* copy over the library part */
for (i = 0; i < ARRAY_SIZE(internal_cat); i++) {
unsigned int cn = osmo_log_info->num_cat_user + i;
- memcpy((struct log_info_cat *) &osmo_log_info->cat[cn],
- &internal_cat[i], sizeof(struct log_info_cat));
+ memcpy(&cat_ptr[cn], &internal_cat[i], sizeof(struct log_info_cat));
}
+ osmo_log_info->cat = cat_ptr;
+
return 0;
}
diff --git a/src/usb/osmo_libusb.c b/src/usb/osmo_libusb.c
index 3c8a22a8..bb862067 100644
--- a/src/usb/osmo_libusb.c
+++ b/src/usb/osmo_libusb.c
@@ -590,6 +590,102 @@ libusb_device_handle *osmo_libusb_open_claim_interface(void *ctx, libusb_context
return usb_devh;
}
+void osmo_libusb_match_init(struct osmo_usb_matchspec *cfg, int if_class, int if_subclass, int if_proto)
+{
+ cfg->dev.vendor_id = -1;
+ cfg->dev.product_id = -1;
+ cfg->dev.path = NULL;
+
+ cfg->config_id = -1;
+
+ cfg->intf.class = if_class;
+ cfg->intf.subclass = if_subclass;
+ cfg->intf.proto = if_proto;
+
+ cfg->intf.num = cfg->intf.altsetting = -1;
+}
+
+
+/*! high-level all-in-one function for USB device, config + interface matching + opening.
+ * This function offers the highest level of API among all libosmousb helper functions. It
+ * is intended as a one-stop shop for everything related to grabbing an interface.
+ *
+ * 1) looks for a device matching either the VID/PID from 'cfg' or 'default_dev_ids',
+ * if more than one is found, the user is expected to fill in cfg->dev.path to disambiguate.
+ * 2) find any interfaces on the device that match the specification in 'cfg'. The match
+ * could be done based on any of (class, subclass, proto, interface number). If there
+ * are multiple matches, the caller must disambiguate by specifying the interface number.
+ * 3) open the USB device; set the configuration (if needed); claim the interface and set
+ * the altsetting
+ *
+ * \param[in] cfg user-supplied match configuration (from command line or config file)
+ * \param[in] default_dev_ids Default list of supported VendorId/ProductIds
+ * \returns libusb_device_handle on success, NULL on error
+ */
+libusb_device_handle *osmo_libusb_find_open_claim(const struct osmo_usb_matchspec *cfg,
+ const struct dev_id *default_dev_ids)
+{
+ struct usb_interface_match if_matches[16];
+ struct usb_interface_match *ifm = NULL;
+ libusb_device_handle *usb_devh = NULL;
+ struct dev_id user_dev_ids[2] = {
+ { cfg->dev.vendor_id, cfg->dev.product_id },
+ { 0, 0 }
+ };
+ const struct dev_id *dev_ids = default_dev_ids;
+ libusb_device *dev;
+ int rc, i;
+
+ /* Stage 1: Find a device matching either the user-specified VID/PID or
+ * the list of IDs in default_dev_ids plus optionally the user-specified path */
+ if (cfg->dev.vendor_id != -1 || cfg->dev.product_id != -1)
+ dev_ids = user_dev_ids;
+ dev = osmo_libusb_find_matching_dev_path(NULL, dev_ids, cfg->dev.path);
+ if (!dev)
+ goto close_exit;
+
+ /* Stage 2: Find any interfaces matching the class/subclass/proto as specified */
+ rc = osmo_libusb_dev_find_matching_interfaces(dev, cfg->intf.class, cfg->intf.subclass,
+ cfg->intf.proto, if_matches, sizeof(if_matches));
+ if (rc < 1) {
+ LOGP(DLUSB, LOGL_NOTICE, "can't find matching USB interface at device\n");
+ goto close_exit;
+ } else if (rc == 1) {
+ ifm = if_matches;
+ } else if (rc > 1) {
+ if (cfg->intf.num == -1) {
+ LOGP(DLUSB, LOGL_ERROR, "Found %d matching USB interfaces, you "
+ "have to specify the interface number\n", rc);
+ goto close_exit;
+ }
+ for (i = 0; i < rc; i++) {
+ if (if_matches[i].interface == cfg->intf.num) {
+ ifm = &if_matches[i];
+ break;
+ }
+ /* FIXME: match altsetting */
+ }
+ }
+ if (!ifm) {
+ LOGP(DLUSB, LOGL_NOTICE, "Couldn't find matching interface\n");
+ goto close_exit;
+ }
+
+ /* Stage 3: Open device; set config (if required); claim interface; set altsetting */
+ usb_devh = osmo_libusb_open_claim_interface(NULL, NULL, ifm);
+ if (!usb_devh) {
+ LOGP(DLUSB, LOGL_ERROR, "can't open USB device (permissions issue?)\n");
+ goto close_exit;
+ }
+ return usb_devh;
+close_exit:
+ /* release if_matches */
+ if (usb_devh)
+ libusb_close(usb_devh);
+
+ return NULL;
+}
+
/*! obtain the endpoint addresses for a given USB interface.
* \param[in] devh USB device handle on which to operate
* \param[in] if_num USB Interface number on which to operate
diff --git a/tests/codec/codec_test.c b/tests/codec/codec_test.c
index 7a10fc57..5579e996 100644
--- a/tests/codec/codec_test.c
+++ b/tests/codec/codec_test.c
@@ -190,6 +190,42 @@ static void test_sid_fr(void)
}
}
+
+
+static void test_amr_s_d(void)
+{
+ ubit_t in[244];
+ ubit_t mid[244];
+ ubit_t out[244];
+ int i, j;
+
+ for (j = AMR_4_75; j <= AMR_12_2; j++) {
+ unsigned int n_bits = gsm690_bitlength[j];
+
+ printf("=> AMR Mode %d (%d bits)\n", j, n_bits);
+ /* set a single bit in the input buffer */
+ for (i = 0; i < n_bits; i++) {
+
+ memset(in, 0, sizeof(in));
+ in[i] = 1;
+
+ /* re-order from s to d */
+ osmo_amr_s_to_d(mid, in, n_bits, j);
+
+ /* and back to d */
+ osmo_amr_d_to_s(out, mid, n_bits, j);
+
+ if (memcmp(in, out, n_bits)) {
+ printf("Error in bit %d of mode %d!\n", i, j);
+ printf("inp s-bits: %s\n", osmo_ubit_dump(in, n_bits));
+ printf("mid d-bits: %s\n", osmo_ubit_dump(mid, n_bits));
+ printf("out s-bits: %s\n", osmo_ubit_dump(out, n_bits));
+ //OSMO_ASSERT(0);
+ }
+ }
+ }
+}
+
int main(int argc, char **argv)
{
printf("AMR RTP payload decoder test:\n");
@@ -213,6 +249,9 @@ int main(int argc, char **argv)
printf("FR RTP payload SID test:\n");
test_sid_fr();
+ printf("AMR s/d bit re-ordering test:\n");
+ test_amr_s_d();
+
return 0;
}
diff --git a/tests/codec/codec_test.ok b/tests/codec/codec_test.ok
index b8cba19c..7d8609ba 100644
--- a/tests/codec/codec_test.ok
+++ b/tests/codec/codec_test.ok
@@ -30,3 +30,12 @@ FR SID d9 23 ba e5 e2 00 00 80 41 20 00 01 00 00 10 00 04 00 00 00 00 00 48 00 0
FR SID d8 62 a2 61 60 00 00 10 00 00 92 00 00 00 00 40 00 00 08 00 00 00 01 00 00 01 00 00 80 00 40 02 40 : 1
FR SID d9 e4 c3 6d 12 00 00 80 00 20 00 40 00 00 00 00 00 10 00 00 00 10 48 00 10 48 00 00 00 00 2d 04 00 : 1
FR SID d9 a4 c3 29 59 00 00 10 00 00 12 00 00 00 00 41 00 00 01 00 00 00 01 00 80 00 00 00 00 42 00 12 02 : 1
+AMR s/d bit re-ordering test:
+=> AMR Mode 0 (95 bits)
+=> AMR Mode 1 (103 bits)
+=> AMR Mode 2 (118 bits)
+=> AMR Mode 3 (134 bits)
+=> AMR Mode 4 (148 bits)
+=> AMR Mode 5 (159 bits)
+=> AMR Mode 6 (204 bits)
+=> AMR Mode 7 (244 bits)
diff --git a/tests/dtx/dtx_gsm0503_test.ok b/tests/dtx/dtx_gsm0503_test.ok
index a95a18bb..77a49360 100644
--- a/tests/dtx/dtx_gsm0503_test.ok
+++ b/tests/dtx/dtx_gsm0503_test.ok
@@ -1,9 +1,9 @@
FR AMR DTX FRAMES:
==> AFS_SID_FIRST, n_errors=0, n_bits_total=212
- ==> AFS_SID_UPDATE, n_errors=0, n_bits_total=212
+ ==> AFS_SID_UPDATE (marker), n_errors=0, n_bits_total=212
==> AFS_ONSET, n_errors=0, n_bits_total=228
HR AMR DTX FRAMES:
- ==> AHS_SID_UPDATE, n_errors=0, n_bits_total=212
+ ==> AHS_SID_UPDATE (marker), n_errors=0, n_bits_total=212
==> AHS_SID_FIRST_P1, n_errors=0, n_bits_total=212
==> AHS_SID_FIRST_P2, n_errors=0, n_bits_total=114
==> AHS_ONSET, n_errors=0, n_bits_total=114
diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c
index ec249148..d9640aa3 100644
--- a/tests/gsm0808/gsm0808_test.c
+++ b/tests/gsm0808/gsm0808_test.c
@@ -306,7 +306,7 @@ static inline void parse_cipher_reject(struct msgb *msg, uint8_t exp)
if (rc < 0)
printf("FIXME: failed (%d) to parse created message %s\n", rc, msgb_hexdump(msg));
- rc = gsm0808_get_cipher_reject_cause(&tp);
+ rc = gsm0808_get_cause(&tp);
if (rc < 0)
printf("FIXME: failed (%s) to extract Cause from created message %s\n",
strerror(-rc), msgb_hexdump(msg));
@@ -379,6 +379,55 @@ static void test_create_sapi_reject()
msgb_free(msg);
}
+static void test_dec_confusion()
+{
+ static const uint8_t hex[] =
+ { 0x26, 0x04, 0x01, 0x52, 0x1f, 0x07, 0x00, 0xff, 0x00, 0x03, 0x25, 0x03, 0x25 };
+ struct tlv_parsed tp;
+ int diag_len;
+ enum gsm0808_cause cause;
+ enum gsm0808_cause_class cause_class;
+ struct gsm0808_diagnostics *diag;
+
+ printf("Testing decoding CONFUSION\n");
+
+ tlv_parse(&tp, gsm0808_att_tlvdef(), hex+1, sizeof(hex)-1, 0, 0);
+
+ /* Check for the Cause and Diagnostic mandatory elements */
+ if (!TLVP_PRESENT(&tp, GSM0808_IE_CAUSE) || !TLVP_PRESENT(&tp, GSM0808_IE_DIAGNOSTIC)) {
+ printf("Either Cause or Diagnostic mandatory IE are not detected\n");
+ return;
+ }
+
+ diag_len = TLVP_LEN(&tp, GSM0808_IE_DIAGNOSTIC);
+ if (diag_len < 5) {
+ printf("Diagnostic length is too short: %d (expected > 5)\n",
+ diag_len);
+ return;
+ }
+
+ cause = gsm0808_get_cause(&tp);
+ if ((int)cause < 0) {
+ printf("ERROR: failed (%s) to extract Cause, aborting\n", strerror(-(int)cause));
+ return;
+ }
+ cause_class = gsm0808_cause_class(cause);
+ printf(" Cause class %d/0x%x (%s)\n",
+ cause_class, cause_class, gsm0808_cause_class_name(cause_class));
+ printf(" Cause %d/0x%x (%s)\n",
+ cause, cause, gsm0808_cause_name(cause));
+
+ diag = (struct gsm0808_diagnostics *)TLVP_VAL(&tp, GSM0808_IE_DIAGNOSTIC);
+ printf(" Diagnostics error octet location %d (%s)\n",
+ diag->error_pointer_octet,
+ gsm0808_diagnostics_octet_location_str(diag->error_pointer_octet));
+ printf(" Diagnostics error bit location %d (%s)\n",
+ diag->error_pointer_bit,
+ gsm0808_diagnostics_bit_location_str(diag->error_pointer_bit));
+ printf(" Diagnostics message that provoked the error: %s\n",
+ osmo_hexdump(diag->msg, diag_len-2));
+}
+
static void test_create_ass()
{
static const uint8_t res1[] =
@@ -2422,6 +2471,8 @@ int main(int argc, char **argv)
test_gsm0808_cell_id_to_from_cgi();
+ test_dec_confusion();
+
printf("Done\n");
return EXIT_SUCCESS;
}
diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok
index b620e369..eaae7a69 100644
--- a/tests/gsm0808/gsm0808_test.ok
+++ b/tests/gsm0808/gsm0808_test.ok
@@ -910,4 +910,10 @@ cid unknown 0x1a7:unknown 0x1a7 -> cgi 777-007-7777-7777 -> cid unknown 0x1a7:un
--> gsm0808_cell_id{LAC-CI} = LAC-CI:7777-7777
--> gsm0808_cell_id{LAI} = LAI:777-007-7777
--> gsm0808_cell_id{CGI} = CGI:777-007-7777-7777
+Testing decoding CONFUSION
+ Cause class 5/0x5 (Invalid message)
+ Cause 82/0x52 (INFORMATION ELEMENT OR FIELD MISSING)
+ Diagnostics error octet location 0 (Error location not determined)
+ Diagnostics error bit location 15 (Reserved value)
+ Diagnostics message that provoked the error: 00 03 25 03 25
Done