[PATCH] libosmocore[master]: gsm0808: Add utils for Speech Codec List and Speech Codec

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

dexter gerrit-no-reply at lists.osmocom.org
Thu Mar 30 16:44:52 UTC 2017


Review at  https://gerrit.osmocom.org/2177

gsm0808: Add utils for Speech Codec List and Speech Codec

The planned support for true A over IP requires the encoding and
decoding of a so called "Speech Codec Element" element.

This commt adds parsing functionality and tests for the element
mentioned above, however, it is not yet actively used.

Change-Id: I0e1e2edf47adaa45b22d4b0bcae3640dba7ca200
---
M include/osmocom/gsm/gsm0808_utils.h
M include/osmocom/gsm/protocol/gsm_08_08.h
M src/gsm/gsm0808_utils.c
M src/gsm/libosmogsm.map
M tests/gsm0808/gsm0808_test.c
5 files changed, 367 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/77/2177/1

diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h
index d4d8618..4049a2f 100644
--- a/include/osmocom/gsm/gsm0808_utils.h
+++ b/include/osmocom/gsm/gsm0808_utils.h
@@ -21,9 +21,25 @@
 
 #include <sys/socket.h>
 
+#include <osmocom/gsm/protocol/gsm_08_08.h>
+
 /* Encode AoIP transport address element */
 struct msgb *gsm0808_enc_aoip_trasp_addr(struct sockaddr_storage *ss);
 
 /* Decode AoIP transport address element */
 struct sockaddr_storage *gsm0808_dec_aoip_trasp_addr(const void *ctx,
 						     struct msgb *msg);
+
+/* Encode Speech Codec element */
+struct msgb *gsm0808_enc_speech_codec(struct gsm0808_speech_codec *sc);
+
+/* Decode Speech Codec element */
+struct gsm0808_speech_codec *gsm0808_dec_speech_codec(const void *ctx,
+						      struct msgb *msg);
+
+/* Encode Speech Codec list */
+struct msgb *gsm0808_enc_speech_codec_list(struct llist_head *scl);
+
+/* Decode Speech Codec list */
+struct llist_head *gsm0808_dec_speech_codec_list(const void *ctx,
+						 struct msgb *msg);
diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h
index 6fb4e9e..ad5e633 100644
--- a/include/osmocom/gsm/protocol/gsm_08_08.h
+++ b/include/osmocom/gsm/protocol/gsm_08_08.h
@@ -3,6 +3,9 @@
 #pragma once
 
 #include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
 
 /*
  * this is from GSM 03.03 CGI but is copied in GSM 08.08
@@ -416,3 +419,17 @@
 	GSM0808_PAGINF_FOR_SMS		= 0x01,
 	GSM0808_PAGINF_FOR_USSD		= 0x02,
 };
+
+/* 3GPP TS 48.008 3.2.2.103 Speech Codec List */
+/* 3GPP TS 48.008 3.2.2.104 Speech Codec */
+struct gsm0808_speech_codec {
+	struct llist_head list;
+	bool fi;
+	bool pi;
+	bool pt;
+	bool tf;
+	uint8_t type;
+	uint16_t cfg;
+	bool type_extended;
+	bool cfg_present;
+};
diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c
index d1897cf4..202f1ac 100644
--- a/src/gsm/gsm0808_utils.c
+++ b/src/gsm/gsm0808_utils.c
@@ -20,6 +20,7 @@
 
 #include <osmocom/core/utils.h>
 #include <osmocom/core/msgb.h>
+#include <osmocom/gsm/protocol/gsm_08_08.h>
 #include <string.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -30,6 +31,7 @@
 #define IP_V4_ADDR_LEN 4
 #define IP_V6_ADDR_LEN 16
 #define IP_PORT_LEN 2
+
 
 /* Encode AoIP transport address element */
 struct msgb *gsm0808_enc_aoip_trasp_addr(struct sockaddr_storage *ss)
@@ -113,3 +115,175 @@
 
 	return ss;
 }
+
+/* Helper function for gsm0808_enc_speech_codec()
+ * and gsm0808_enc_speech_codec_list() */
+static void enc_speech_codec(struct msgb *msg, struct gsm0808_speech_codec *sc)
+{
+	/* See also 3GPP TS 48.008 3.2.2.103 Speech Codec List */
+	uint8_t header = 0;
+
+	if (sc->fi)
+		header |= (1 << 7);
+	if (sc->pi)
+		header |= (1 << 6);
+	if (sc->pt)
+		header |= (1 << 5);
+	if (sc->tf)
+		header |= (1 << 4);
+	if (sc->type_extended) {
+		header |= 0x0f;
+		msgb_put_u8(msg, header);
+	} else {
+		OSMO_ASSERT(sc->type < 0x0f);
+		header |= sc->type;
+		msgb_put_u8(msg, header);
+		return;
+	}
+
+	msgb_put_u8(msg, sc->type);
+
+	if (sc->cfg_present)
+		msgb_put_u16(msg, sc->cfg);
+}
+
+/* Encode Speech Codec element */
+struct msgb *gsm0808_enc_speech_codec(struct gsm0808_speech_codec *sc)
+{
+	struct msgb *msg;
+
+	OSMO_ASSERT(sc);
+
+	msg = msgb_alloc(ELEMENT_MSGB_MAXLEN, "Speech Codec Element");
+	if (!msg)
+		return NULL;
+
+	enc_speech_codec(msg, sc);
+
+	return msg;
+}
+
+/* Decode Speech Codec element */
+struct gsm0808_speech_codec *gsm0808_dec_speech_codec(const void *ctx,
+						      struct msgb *msg)
+{
+	/* See also 3GPP TS 48.008 3.2.2.103 Speech Codec List */
+	uint8_t header;
+	struct gsm0808_speech_codec *sc;
+
+	if (!msg)
+		return NULL;
+
+	/* Malformed elements */
+	if ((msg->data[0] & 0x0F) == 0x0F && msg->len < 2)
+		return NULL;
+	else if ((msg->data[0] & 0x0F) != 0x0F && msg->len < 1)
+		return NULL;
+
+	header = msgb_pull_u8(msg);
+	sc = talloc_zero(ctx, struct gsm0808_speech_codec);
+	if (!sc)
+		return NULL;
+
+	if (header & (1 << 7))
+		sc->fi = true;
+	if (header & (1 << 6))
+		sc->pi = true;
+	if (header & (1 << 5))
+		sc->pt = true;
+	if (header & (1 << 4))
+		sc->tf = true;
+
+	if ((header & 0x0F) != 0x0F) {
+		sc->type = (header & 0x0F);
+		return sc;
+	}
+
+	sc->type = msgb_pull_u8(msg);
+	sc->type_extended = true;
+
+	if (msg->len < 2)
+		return sc;
+
+	sc->cfg = msgb_pull_u16(msg);
+	sc->cfg_present = true;
+
+	return sc;
+}
+
+/* Encode Speech Codec list */
+struct msgb *gsm0808_enc_speech_codec_list(struct llist_head *scl)
+{
+	struct gsm0808_speech_codec *sc;
+	unsigned int scl_len;
+	struct msgb *msg;
+
+	OSMO_ASSERT(scl);
+
+	scl_len = llist_count(scl);
+
+	/* Empty list */
+	if (scl_len < 1)
+		return NULL;
+
+	msg =
+	    msgb_alloc(ELEMENT_MSGB_MAXLEN * scl_len,
+		       "Speech Codec Element");
+	if (!msg)
+		return NULL;
+
+	llist_for_each_entry(sc, scl, list) {
+		enc_speech_codec(msg, sc);
+	}
+
+	/* Prevent generating oversized TLV elements */
+	if (msg->len > ELEMENT_MSGB_MAXLEN) {
+		free(msg);
+		return NULL;
+	}
+
+	return msg;
+}
+
+/* Decode Speech Codec list */
+struct llist_head *gsm0808_dec_speech_codec_list(const void *ctx,
+						 struct msgb *msg)
+{
+	struct llist_head *scl = NULL;
+	struct gsm0808_speech_codec *sc;
+	unsigned int loopcount = 0;
+	unsigned int scl_len;
+
+	if (!msg)
+		return NULL;
+
+	scl = talloc_zero(ctx, struct llist_head);
+	if (!scl)
+		return NULL;
+
+	INIT_LLIST_HEAD(scl);
+
+	while (1) {
+		/* Ensure loop exit */
+		if (loopcount > 255)
+			break;
+
+		sc = gsm0808_dec_speech_codec(scl, msg);
+		if (sc == NULL)
+			break;
+
+		llist_add(&sc->list, scl);
+
+		loopcount++;
+	}
+
+	scl_len = llist_count(scl);
+
+	/* Empty list */
+	if (scl_len < 1) {
+		talloc_free(scl);
+		return NULL;
+	}
+
+	return scl;
+}
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 3ad847d..c89cbe4 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -139,6 +139,10 @@
 gsm0808_prepend_dtap_header;
 gsm0808_enc_aoip_trasp_addr;
 gsm0808_dec_aoip_trasp_addr;
+gsm0808_enc_speech_codec;
+gsm0808_dec_speech_codec;
+gsm0808_enc_speech_codec_list;
+gsm0808_dec_speech_codec_list;
 
 gsm0858_rsl_ul_meas_enc;
 
diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c
index 99605d8..7f2cff1 100644
--- a/tests/gsm0808/gsm0808_test.c
+++ b/tests/gsm0808/gsm0808_test.c
@@ -307,6 +307,158 @@
 	msgb_free(msg);
 }
 
+static void test_gsm0808_enc_dec_speech_codec(const void *ctx)
+{
+	struct gsm0808_speech_codec enc_sc;
+	struct gsm0808_speech_codec *dec_sc;
+	struct msgb *msg;
+
+	memset(&enc_sc, 0, sizeof(enc_sc));
+	enc_sc.fi = true;
+	enc_sc.pt = true;
+	enc_sc.type = 0x05;
+
+	msg = gsm0808_enc_speech_codec(&enc_sc);
+	OSMO_ASSERT(msg);
+	dec_sc = gsm0808_dec_speech_codec(ctx, msg);
+	OSMO_ASSERT(dec_sc);
+	OSMO_ASSERT(msg->len == 0);
+
+	OSMO_ASSERT(memcmp(&enc_sc, dec_sc, sizeof(enc_sc)) == 0);
+
+	talloc_free(dec_sc);
+	msgb_free(msg);
+}
+
+static void test_gsm0808_enc_dec_speech_codec_ext_with_cfg(const void *ctx)
+{
+	struct gsm0808_speech_codec enc_sc;
+	struct gsm0808_speech_codec *dec_sc;
+	struct msgb *msg;
+
+	enc_sc.pi = true;
+	enc_sc.tf = true;
+	enc_sc.type = 0xab;
+	enc_sc.type_extended = true;
+	enc_sc.cfg_present = true;
+	enc_sc.cfg = 0xcdef;
+
+	msg = gsm0808_enc_speech_codec(&enc_sc);
+	OSMO_ASSERT(msg);
+	dec_sc = gsm0808_dec_speech_codec(ctx, msg);
+	OSMO_ASSERT(dec_sc);
+	OSMO_ASSERT(msg->len == 0);
+
+	OSMO_ASSERT(memcmp(&enc_sc, dec_sc, sizeof(enc_sc)) == 0);
+
+	talloc_free(dec_sc);
+	msgb_free(msg);
+}
+
+static void test_gsm0808_enc_dec_speech_codec_ext(const void *ctx)
+{
+	struct gsm0808_speech_codec enc_sc;
+	struct gsm0808_speech_codec *dec_sc;
+	struct msgb *msg;
+
+	enc_sc.fi = true;
+	enc_sc.tf = true;
+	enc_sc.type = 0xf2;
+	enc_sc.type_extended = true;
+
+	msg = gsm0808_enc_speech_codec(&enc_sc);
+	OSMO_ASSERT(msg);
+	dec_sc = gsm0808_dec_speech_codec(ctx, msg);
+	OSMO_ASSERT(dec_sc);
+	OSMO_ASSERT(msg->len == 0);
+
+	OSMO_ASSERT(memcmp(&enc_sc, dec_sc, sizeof(enc_sc)) == 0);
+
+	talloc_free(dec_sc);
+	msgb_free(msg);
+}
+
+static bool speech_codec_cmp(struct gsm0808_speech_codec *a,
+			     struct gsm0808_speech_codec *b)
+{
+	if (a->fi != b->fi)
+		return false;
+	if (a->pi != b->pi)
+		return false;
+	if (a->pt != b->pt)
+		return false;
+	if (a->tf != b->tf)
+		return false;
+	if (a->type != b->type)
+		return false;
+	if (a->cfg != b->cfg)
+		return false;
+	if (a->type_extended != b->type_extended)
+		return false;
+	if (a->cfg_present != b->cfg_present)
+		return false;
+
+	return true;
+}
+
+static void test_gsm0808_enc_dec_speech_codec_list(const void *ctx)
+{
+	struct gsm0808_speech_codec enc_sc1;
+	struct gsm0808_speech_codec enc_sc2;
+	struct gsm0808_speech_codec enc_sc3;
+	struct msgb *msg;
+	struct llist_head sc_list;
+	struct llist_head *sc_list_decoded;
+	struct gsm0808_speech_codec *sc;
+
+	INIT_LLIST_HEAD(&sc_list);
+
+	memset(&enc_sc1, 0, sizeof(enc_sc1));
+	enc_sc1.pi = true;
+	enc_sc1.tf = true;
+	enc_sc1.type = 0xab;
+	enc_sc1.type_extended = true;
+	enc_sc1.cfg_present = true;
+	enc_sc1.cfg = 0xcdef;
+
+	memset(&enc_sc2, 0, sizeof(enc_sc2));
+	enc_sc2.fi = true;
+	enc_sc2.pt = true;
+	enc_sc2.type = 0x05;
+
+	memset(&enc_sc3, 0, sizeof(enc_sc3));
+	enc_sc3.fi = true;
+	enc_sc3.tf = true;
+	enc_sc3.type = 0xf2;
+	enc_sc3.type_extended = true;
+
+	llist_add(&enc_sc3.list, &sc_list);
+	llist_add(&enc_sc2.list, &sc_list);
+	llist_add(&enc_sc1.list, &sc_list);
+
+	msg = gsm0808_enc_speech_codec_list(&sc_list);
+	sc_list_decoded = gsm0808_dec_speech_codec_list(ctx, msg);
+	OSMO_ASSERT(msg->len == 0);
+
+	llist_for_each_entry(sc, sc_list_decoded, list) {
+		if(sc->type == 0xab) {
+			OSMO_ASSERT(speech_codec_cmp(&enc_sc1,sc) == true);
+		}
+		else if(sc->type == 0x05) {
+			OSMO_ASSERT(speech_codec_cmp(&enc_sc2,sc) == true);
+		}
+		else if(sc->type == 0xf2) {
+			OSMO_ASSERT(speech_codec_cmp(&enc_sc3,sc) == true);
+		}
+		else {
+			OSMO_ASSERT(false);
+		}
+	}
+
+	talloc_free(sc_list_decoded);
+	msgb_free(msg);
+}
+
 int main(int argc, char **argv)
 {
 	void *ctx;
@@ -329,6 +481,10 @@
 	test_prepend_dtap();
 	test_enc_dec_aoip_trasp_addr_v4(ctx);
 	test_enc_dec_aoip_trasp_addr_v6(ctx);
+	test_gsm0808_enc_dec_speech_codec(ctx);
+	test_gsm0808_enc_dec_speech_codec_ext(ctx);
+	test_gsm0808_enc_dec_speech_codec_ext_with_cfg(ctx);
+	test_gsm0808_enc_dec_speech_codec_list(ctx);
 
 	printf("Done\n");
 

-- 
To view, visit https://gerrit.osmocom.org/2177
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0e1e2edf47adaa45b22d4b0bcae3640dba7ca200
Gerrit-PatchSet: 1
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Owner: dexter <pmaier at sysmocom.de>



More information about the gerrit-log mailing list