fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/34762?usp=email )
Change subject: mobile: add support for Circuit Switched Data calls ......................................................................
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"))