gsm0808_enc/dec_channel_type: support data
Related: OS#4393
Change-Id: Ib7b75c9d86aace329decf20003b68de459021c64
diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c
index 83d2ce7..4993539 100644
--- a/src/gsm/gsm0808_utils.c
+++ b/src/gsm/gsm0808_utils.c
@@ -499,12 +499,6 @@
OSMO_ASSERT(ct->perm_spch_len <= CHANNEL_TYPE_ELEMENT_MAXLEN - 2);
- /* FIXME: Implement encoding support for Data
- * and Speech + CTM Text Telephony */
- if ((ct->ch_indctr & 0x0f) != GSM0808_CHAN_SPEECH
- && (ct->ch_indctr & 0x0f) != GSM0808_CHAN_SIGN)
- OSMO_ASSERT(false);
-
msgb_put_u8(msg, GSM0808_IE_CHANNEL_TYPE);
tlv_len = msgb_put(msg, 1);
old_tail = msg->tail;
@@ -512,12 +506,44 @@
msgb_put_u8(msg, ct->ch_indctr & 0x0f);
msgb_put_u8(msg, ct->ch_rate_type);
- for (i = 0; i < ct->perm_spch_len; i++) {
- byte = ct->perm_spch[i];
+ switch (ct->ch_indctr) {
+ case GSM0808_CHAN_DATA:
+ byte = ct->data_rate;
- if (i < ct->perm_spch_len - 1)
- byte |= 0x80;
+ if (ct->data_transparent)
+ byte |= 0x40; /* Set T/NT */
+
+ if (ct->data_rate_allowed_is_set) {
+ OSMO_ASSERT(!ct->data_transparent);
+ byte |= 0x80; /* Set ext */
+ msgb_put_u8(msg, byte);
+
+ byte = ct->data_rate_allowed;
+ if (ct->data_asym_pref_is_set) {
+ byte |= 0x80; /* Set ext */
+ msgb_put_u8(msg, byte);
+
+ /* Set asymmetry indication, rest is spare */
+ byte = ct->data_asym_pref << 5;
+ }
+ }
msgb_put_u8(msg, byte);
+ break;
+ case GSM0808_CHAN_SPEECH:
+ case GSM0808_CHAN_SPEECH_CTM_TEXT_TELEPHONY:
+ for (i = 0; i < ct->perm_spch_len; i++) {
+ byte = ct->perm_spch[i];
+
+ if (i < ct->perm_spch_len - 1)
+ byte |= 0x80;
+ msgb_put_u8(msg, byte);
+ }
+ break;
+ case GSM0808_CHAN_SIGN:
+ /* Octet 5 is spare */
+ break;
+ default:
+ OSMO_ASSERT(false);
}
*tlv_len = (uint8_t) (msg->tail - old_tail);
@@ -549,17 +575,57 @@
ct->ch_rate_type = (*elem) & 0x0f;
elem++;
- for (i = 0; i < ARRAY_SIZE(ct->perm_spch); i++) {
- if (elem - old_elem >= len)
- return -EOVERFLOW;
-
+ switch (ct->ch_indctr) {
+ case GSM0808_CHAN_DATA:
byte = *elem;
elem++;
- ct->perm_spch[i] = byte & 0x7f;
- if ((byte & 0x80) == 0x00)
- break;
+ ct->data_transparent = byte & 0x40; /* T/NT */
+ ct->data_rate = byte & 0x3f;
+
+ /* Optional extension for non-transparent service */
+ if (byte & 0x80) {
+ if (ct->data_transparent)
+ return -EINVAL;
+ if (elem - old_elem >= len)
+ return -EOVERFLOW;
+ byte = *elem;
+ elem++;
+
+ ct->data_rate_allowed_is_set = true;
+ ct->data_rate_allowed = byte & 0x7f;
+
+ /* Optional extension */
+ if (byte & 0x80) {
+ if (elem - old_elem >= len)
+ return -EOVERFLOW;
+ byte = *elem;
+ elem++;
+
+ ct->data_asym_pref_is_set = true;
+ ct->data_asym_pref = byte & 0x60 >> 5;
+ }
+ }
+ break;
+ case GSM0808_CHAN_SPEECH:
+ case GSM0808_CHAN_SPEECH_CTM_TEXT_TELEPHONY:
+ for (i = 0; i < ARRAY_SIZE(ct->perm_spch); i++) {
+ if (elem - old_elem >= len)
+ return -EOVERFLOW;
+
+ byte = *elem;
+ elem++;
+ ct->perm_spch[i] = byte & 0x7f;
+ if ((byte & 0x80) == 0x00)
+ break;
+ }
+ ct->perm_spch_len = i + 1;
+ break;
+ case GSM0808_CHAN_SIGN:
+ /* Octet 5 is spare */
+ break;
+ default:
+ return -ENOTSUP;
}
- ct->perm_spch_len = i + 1;
return (int)(elem - old_elem);
}