fixeria has uploaded this change for review.
mobile: add support for Circuit Switched Data calls
TODO: for now MO calls only, add support for MT calls
TODO: add VTY command(s) for changing the Bearer Capability
Change-Id: I1995fa0a7a68d9b980852b664d472d4633777ac6
Related: OS#4396
---
M src/host/layer23/include/osmocom/bb/common/settings.h
M src/host/layer23/include/osmocom/bb/common/support.h
M src/host/layer23/include/osmocom/bb/mobile/mncc_ms.h
M src/host/layer23/src/common/settings.c
M src/host/layer23/src/common/support.c
M src/host/layer23/src/mobile/gsm48_rr.c
M src/host/layer23/src/mobile/mnccms.c
M src/host/layer23/src/mobile/vty_interface.c
8 files changed, 166 insertions(+), 13 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/62/34762/1
diff --git a/src/host/layer23/include/osmocom/bb/common/settings.h b/src/host/layer23/include/osmocom/bb/common/settings.h
index 884578b..d9b055d 100644
--- a/src/host/layer23/include/osmocom/bb/common/settings.h
+++ b/src/host/layer23/include/osmocom/bb/common/settings.h
@@ -161,6 +161,14 @@
uint8_t ch_cap; /* channel capability */
int8_t min_rxlev_dbm; /* min dBm to access */
+ /* CSD modes */
+ uint8_t csd_tch_f144;
+ uint8_t csd_tch_f96;
+ uint8_t csd_tch_f48;
+ uint8_t csd_tch_h48;
+ uint8_t csd_tch_f24;
+ uint8_t csd_tch_h24;
+
/* support for ASCI */
bool vgcs; /* support of VGCS */
bool vbs; /* support of VBS */
diff --git a/src/host/layer23/include/osmocom/bb/common/support.h b/src/host/layer23/include/osmocom/bb/common/support.h
index 2fae57e..b0c71f5 100644
--- a/src/host/layer23/include/osmocom/bb/common/support.h
+++ b/src/host/layer23/include/osmocom/bb/common/support.h
@@ -91,6 +91,14 @@
uint8_t half_v1;
uint8_t half_v3;
+ /* CSD modes */
+ uint8_t csd_tch_f144;
+ uint8_t csd_tch_f96;
+ uint8_t csd_tch_f48;
+ uint8_t csd_tch_h48;
+ uint8_t csd_tch_f24;
+ uint8_t csd_tch_h24;
+
/* EDGE / UMTS / CDMA */
uint8_t edge_ms_sup;
uint8_t edge_psk_sup;
diff --git a/src/host/layer23/include/osmocom/bb/mobile/mncc_ms.h b/src/host/layer23/include/osmocom/bb/mobile/mncc_ms.h
index 705c681..00b8ec4 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/mncc_ms.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/mncc_ms.h
@@ -1,6 +1,6 @@
#pragma once
-int mncc_call(struct osmocom_ms *ms, const char *number);
+int mncc_call(struct osmocom_ms *ms, const char *number, bool data);
int mncc_hangup(struct osmocom_ms *ms);
int mncc_answer(struct osmocom_ms *ms);
int mncc_hold(struct osmocom_ms *ms);
diff --git a/src/host/layer23/src/common/settings.c b/src/host/layer23/src/common/settings.c
index 395d239..10ae1d9 100644
--- a/src/host/layer23/src/common/settings.c
+++ b/src/host/layer23/src/common/settings.c
@@ -100,6 +100,14 @@
set->ch_cap = sup->ch_cap;
set->min_rxlev_dbm = sup->min_rxlev_dbm;
set->dsc_max = sup->dsc_max;
+
+ set->csd_tch_f144 = sup->csd_tch_f144;
+ set->csd_tch_f96 = sup->csd_tch_f96;
+ set->csd_tch_f48 = sup->csd_tch_f48;
+ set->csd_tch_h48 = sup->csd_tch_h48;
+ set->csd_tch_f24 = sup->csd_tch_f24;
+ set->csd_tch_h24 = sup->csd_tch_h24;
+
set->vgcs = sup->vgcs;
set->vbs = sup->vbs;
diff --git a/src/host/layer23/src/common/support.c b/src/host/layer23/src/common/support.c
index 2f93016..ed51465 100644
--- a/src/host/layer23/src/common/support.c
+++ b/src/host/layer23/src/common/support.c
@@ -97,6 +97,14 @@
sup->full_v3 = 0;
sup->half_v1 = 1;
sup->half_v3 = 0;
+
+ /* CSD modes */
+ sup->csd_tch_f144 = 1;
+ sup->csd_tch_f96 = 1;
+ sup->csd_tch_f48 = 1;
+ sup->csd_tch_h48 = 1;
+ sup->csd_tch_f24 = 1;
+ sup->csd_tch_h24 = 1;
}
/* (3.2.1) maximum channels to scan within each band */
@@ -173,6 +181,14 @@
print(priv, " Full-Rate V3 : %s\n", SUP_SET(full_v3));
print(priv, " Half-Rate V1 : %s\n", SUP_SET(half_v1));
print(priv, " Half-Rate V3 : %s\n", SUP_SET(half_v3));
+
+ print(priv, " CSD TCH/F14.4: %s\n", SUP_SET(csd_tch_f144));
+ print(priv, " CSD TCH/F9.6 : %s\n", SUP_SET(csd_tch_f96));
+ print(priv, " CSD TCH/F4.8 : %s\n", SUP_SET(csd_tch_f48));
+ print(priv, " CSD TCH/H4.8 : %s\n", SUP_SET(csd_tch_h48));
+ print(priv, " CSD TCH/F2.4 : %s\n", SUP_SET(csd_tch_f24));
+ print(priv, " CSD TCH/H2.4 : %s\n", SUP_SET(csd_tch_h24));
+
print(priv, " Min RXLEV : %d\n", set->min_rxlev_dbm);
}
diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c
index 3200412..38f3309 100644
--- a/src/host/layer23/src/mobile/gsm48_rr.c
+++ b/src/host/layer23/src/mobile/gsm48_rr.c
@@ -374,6 +374,62 @@
LOGP(DRR, LOGL_INFO, "Mode: half-rate speech V3\n");
}
break;
+ case GSM48_CMODE_DATA_14k5:
+ if (ch_type != RSL_CHAN_Bm_ACCHs) {
+ LOGP(DRR, LOGL_ERROR,
+ "TCH/F is expected for mode %s\n",
+ gsm48_chan_mode_name(mode));
+ return GSM48_RR_CAUSE_CHAN_MODE_UNACCT;
+ } else if (!set->csd_tch_f144) {
+ LOGP(DRR, LOGL_ERROR,
+ "Not supporting TCH/F14.4 data (%s)\n",
+ gsm48_chan_mode_name(mode));
+ return GSM48_RR_CAUSE_CHAN_MODE_UNACCT;
+ }
+ LOGP(DRR, LOGL_INFO, "Mode: TCH/F14.4 data (%s)\n",
+ gsm48_chan_mode_name(mode));
+ break;
+ case GSM48_CMODE_DATA_12k0:
+ if (ch_type != RSL_CHAN_Bm_ACCHs) {
+ LOGP(DRR, LOGL_ERROR,
+ "TCH/F is expected for mode %s\n",
+ gsm48_chan_mode_name(mode));
+ return GSM48_RR_CAUSE_CHAN_MODE_UNACCT;
+ } else if (!set->csd_tch_f96) {
+ LOGP(DRR, LOGL_ERROR,
+ "Not supporting TCH/F9.6 data (%s)\n",
+ gsm48_chan_mode_name(mode));
+ return GSM48_RR_CAUSE_CHAN_MODE_UNACCT;
+ }
+ LOGP(DRR, LOGL_INFO, "Mode: TCH/F9.6 data (%s)\n",
+ gsm48_chan_mode_name(mode));
+ break;
+ case GSM48_CMODE_DATA_6k0:
+ if ((ch_type == RSL_CHAN_Bm_ACCHs && !set->csd_tch_f48)
+ || (ch_type == RSL_CHAN_Lm_ACCHs && !set->csd_tch_h48)) {
+ LOGP(DRR, LOGL_ERROR,
+ "Not supporting TCH/%c4.8 data (%s)\n",
+ ch_type == RSL_CHAN_Bm_ACCHs ? 'F' : 'H',
+ gsm48_chan_mode_name(mode));
+ return GSM48_RR_CAUSE_CHAN_MODE_UNACCT;
+ }
+ LOGP(DRR, LOGL_INFO, "Mode: TCH/%c4.8 data (%s)\n",
+ ch_type == RSL_CHAN_Bm_ACCHs ? 'F' : 'H',
+ gsm48_chan_mode_name(mode));
+ break;
+ case GSM48_CMODE_DATA_3k6:
+ if ((ch_type == RSL_CHAN_Bm_ACCHs && !set->csd_tch_f24)
+ || (ch_type == RSL_CHAN_Lm_ACCHs && !set->csd_tch_h24)) {
+ LOGP(DRR, LOGL_ERROR,
+ "Not supporting TCH/%c2.4 data (%s)\n",
+ ch_type == RSL_CHAN_Bm_ACCHs ? 'F' : 'H',
+ gsm48_chan_mode_name(mode));
+ return GSM48_RR_CAUSE_CHAN_MODE_UNACCT;
+ }
+ LOGP(DRR, LOGL_INFO, "Mode: TCH/%c2.4 data (%s)\n",
+ ch_type == RSL_CHAN_Bm_ACCHs ? 'F' : 'H',
+ gsm48_chan_mode_name(mode));
+ break;
default:
LOGP(DRR, LOGL_ERROR, "Mode 0x%02x not supported!\n", mode);
return GSM48_RR_CAUSE_CHAN_MODE_UNACCT;
diff --git a/src/host/layer23/src/mobile/mnccms.c b/src/host/layer23/src/mobile/mnccms.c
index c269ab4..7d14625 100644
--- a/src/host/layer23/src/mobile/mnccms.c
+++ b/src/host/layer23/src/mobile/mnccms.c
@@ -132,10 +132,48 @@
return speech_ver;
}
-static void mncc_set_bearer(struct osmocom_ms *ms, int8_t speech_ver,
- struct gsm_mncc *mncc)
+static void mncc_set_bcap_data(struct gsm_mncc *mncc,
+ const struct gsm_settings *set)
{
- struct gsm_settings *set = &ms->settings;
+ struct gsm_mncc_bearer_cap *bcap = &mncc->bearer_cap;
+
+ mncc->fields |= MNCC_F_BEARER_CAP;
+
+ *bcap = (struct gsm_mncc_bearer_cap) {
+ .transfer = GSM_MNCC_BCAP_UNR_DIG,
+ .mode = GSM48_BCAP_TMOD_CIRCUIT,
+ .coding = GSM48_BCAP_CODING_GSM_STD,
+ /* .radio is set below */
+ .data = {
+ /* TODO: make these fields configurable via *set */
+ .rate_adaption = GSM48_BCAP_RA_V110_X30,
+ .sig_access = GSM48_BCAP_SA_I440_I450,
+ .async = 1,
+ .transp = GSM48_BCAP_TR_TRANSP,
+ .nr_data_bits = 8,
+ .parity = GSM48_BCAP_PAR_NONE,
+ .nr_stop_bits = 1,
+ .user_rate = GSM48_BCAP_UR_9600,
+ .interm_rate = GSM48_BCAP_IR_16k,
+ },
+ };
+
+ if (set->ch_cap == GSM_CAP_SDCCH_TCHF_TCHH) {
+ if (set->half_prefer)
+ bcap->radio = GSM48_BCAP_RRQ_DUAL_HR;
+ else
+ bcap->radio = GSM48_BCAP_RRQ_DUAL_FR;
+ LOGP(DMNCC, LOGL_INFO, " support TCH/H also\n");
+ } else {
+ bcap->radio = GSM48_BCAP_RRQ_FR_ONLY;
+ LOGP(DMNCC, LOGL_INFO, " support TCH/F only\n");
+ }
+}
+
+static void mncc_set_bcap_speech(struct gsm_mncc *mncc,
+ const struct gsm_settings *set,
+ int speech_ver)
+{
int i = 0;
mncc->fields |= MNCC_F_BEARER_CAP;
@@ -461,11 +499,12 @@
* or if not only full rate
* or if given codec is unimplemented
*/
+ /* TODO: handle incoming data calls properly */
if (!(data->fields & MNCC_F_BEARER_CAP) || speech_ver < 0)
- mncc_set_bearer(ms, -1, &mncc);
+ mncc_set_bcap_speech(&mncc, &ms->settings, -1);
else if (data->bearer_cap.speech_ver[1] >= 0
|| speech_ver != 0)
- mncc_set_bearer(ms, speech_ver, &mncc);
+ mncc_set_bcap_speech(&mncc, &ms->settings, speech_ver);
/* CC capabilities (optional) */
if (ms->settings.cc_dtmf) {
mncc.fields |= MNCC_F_CCCAP;
@@ -532,7 +571,7 @@
return 0;
}
-int mncc_call(struct osmocom_ms *ms, const char *number)
+int mncc_call(struct osmocom_ms *ms, const char *number, bool data)
{
struct gsm_call *call;
struct gsm_mncc setup;
@@ -563,7 +602,8 @@
/* emergency */
setup.emergency = 1;
} else {
- LOGP(DMNCC, LOGL_INFO, "Make call to %s\n", number);
+ LOGP(DMNCC, LOGL_INFO, "Make %s call to %s\n",
+ data ? "data" : "speech", number);
/* called number */
setup.fields |= MNCC_F_CALLED;
if (number[0] == '+') {
@@ -576,7 +616,10 @@
OSMO_STRLCPY_ARRAY(setup.called.number, number);
/* bearer capability (mandatory) */
- mncc_set_bearer(ms, -1, &setup);
+ if (data)
+ mncc_set_bcap_data(&setup, &ms->settings);
+ else
+ mncc_set_bcap_speech(&setup, &ms->settings, -1);
/* CLIR */
if (ms->settings.clir)
diff --git a/src/host/layer23/src/mobile/vty_interface.c b/src/host/layer23/src/mobile/vty_interface.c
index 28f8a1b..4a95e21 100644
--- a/src/host/layer23/src/mobile/vty_interface.c
+++ b/src/host/layer23/src/mobile/vty_interface.c
@@ -494,10 +494,11 @@
"Name of MS (see \"show ms\")\n"
DEFUN(call_num, call_num_cmd,
- CALL_CMD " NUMBER",
+ CALL_CMD " NUMBER [data]",
CALL_CMD_DESC
"Phone number to call "
- "(Use digits '0123456789*#abc', and '+' to dial international)\n")
+ "(Use digits '0123456789*#abc', and '+' to dial international)\n"
+ "Initiate a CSD (Circuit Switched Data) call\n")
{
struct osmocom_ms *ms;
struct gsm_settings *set;
@@ -527,7 +528,7 @@
if (vty_check_number(vty, number))
return CMD_WARNING;
- mncc_call(ms, number);
+ mncc_call(ms, number, argc > 2);
return CMD_SUCCESS;
}
@@ -557,7 +558,7 @@
number = argv[1];
if (!strcmp(number, "emergency"))
- mncc_call(ms, number);
+ mncc_call(ms, number, false);
else if (!strcmp(number, "answer"))
mncc_answer(ms);
else if (!strcmp(number, "hangup"))
To view, visit change 34762. To unsubscribe, or for help writing mail filters, visit settings.