summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <vyanitskiy@sysmocom.de>2023-10-11 05:14:19 +0700
committerVadim Yanitskiy <vyanitskiy@sysmocom.de>2023-10-19 19:31:17 +0700
commit3a4c4e8f0e24d081f9f3e44bc34d0401f51611a7 (patch)
tree24b9b8853f03ea4261931626376df9986e1ffc6b
parent1c7c71376024aa9cbfb415cf712ff2f83062acea (diff)
mobile: add support for Circuit Switched Data calls
TODO: add VTY command(s) for changing the Bearer Capability Change-Id: I1995fa0a7a68d9b980852b664d472d4633777ac6 Related: OS#4396
-rw-r--r--src/host/layer23/include/osmocom/bb/common/settings.h10
-rw-r--r--src/host/layer23/include/osmocom/bb/common/support.h8
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/mncc_ms.h2
-rw-r--r--src/host/layer23/src/common/settings.c8
-rw-r--r--src/host/layer23/src/common/support.c16
-rw-r--r--src/host/layer23/src/mobile/gsm48_rr.c56
-rw-r--r--src/host/layer23/src/mobile/mnccms.c116
-rw-r--r--src/host/layer23/src/mobile/vty_interface.c39
8 files changed, 241 insertions, 14 deletions
diff --git a/src/host/layer23/include/osmocom/bb/common/settings.h b/src/host/layer23/include/osmocom/bb/common/settings.h
index 884578b0..8f03d531 100644
--- a/src/host/layer23/include/osmocom/bb/common/settings.h
+++ b/src/host/layer23/include/osmocom/bb/common/settings.h
@@ -1,6 +1,8 @@
#ifndef _settings_h
#define _settings_h
+#include <stdbool.h>
+
#include <osmocom/core/utils.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
@@ -161,6 +163,14 @@ struct gsm_settings {
uint8_t ch_cap; /* channel capability */
int8_t min_rxlev_dbm; /* min dBm to access */
+ /* CSD modes */
+ bool csd_tch_f144;
+ bool csd_tch_f96;
+ bool csd_tch_f48;
+ bool csd_tch_h48;
+ bool csd_tch_f24;
+ bool 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 2fae57ec..b0c71f5a 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 @@ struct gsm_support {
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 705c681e..00b8ec44 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 395d2394..10ae1d9e 100644
--- a/src/host/layer23/src/common/settings.c
+++ b/src/host/layer23/src/common/settings.c
@@ -100,6 +100,14 @@ int gsm_settings_init(struct osmocom_ms *ms)
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 2f93016c..ed514651 100644
--- a/src/host/layer23/src/common/support.c
+++ b/src/host/layer23/src/common/support.c
@@ -97,6 +97,14 @@ void gsm_support_init(struct osmocom_ms *ms)
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 @@ void gsm_support_dump(struct osmocom_ms *ms,
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 3200412f..38f3309e 100644
--- a/src/host/layer23/src/mobile/gsm48_rr.c
+++ b/src/host/layer23/src/mobile/gsm48_rr.c
@@ -374,6 +374,62 @@ static uint8_t gsm48_rr_check_mode(struct osmocom_ms *ms, uint8_t chan_nr,
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 d23fbb70..fb09778c 100644
--- a/src/host/layer23/src/mobile/mnccms.c
+++ b/src/host/layer23/src/mobile/mnccms.c
@@ -134,9 +134,9 @@ static int8_t mncc_get_bearer(const struct gsm_settings *set, uint8_t speech_ver
return speech_ver;
}
-static void mncc_set_bearer(struct gsm_mncc *mncc,
- const struct gsm_settings *set,
- int8_t speech_ver)
+static void mncc_set_bcap_speech(struct gsm_mncc *mncc,
+ const struct gsm_settings *set,
+ int speech_ver)
{
int i = 0;
@@ -192,6 +192,44 @@ static void mncc_set_bearer(struct gsm_mncc *mncc,
mncc->bearer_cap.mode = GSM48_BCAP_TMOD_CIRCUIT;
}
+static void mncc_set_bcap_data(struct gsm_mncc *mncc,
+ const struct gsm_settings *set)
+{
+ 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");
+ }
+}
+
/* Check the given Bearer Capability, select first supported speech codec version.
* The choice between half-rate and full-rate is made based on current settings.
* Return a selected codec or -1 if no speech codec was selected. */
@@ -249,6 +287,59 @@ static int mncc_handle_bcap_speech(const struct gsm_mncc_bearer_cap *bcap,
return speech_ver;
}
+/* Check the given Bearer Capability for a data call (CSD).
+ * Return 0 if the bearer is accepted, otherwise return -1. */
+static int mncc_handle_bcap_data(const struct gsm_mncc_bearer_cap *bcap,
+ const struct gsm_settings *set)
+{
+ if (bcap->data.rate_adaption != GSM48_BCAP_RA_V110_X30) {
+ LOGP(DMNCC, LOGL_ERROR,
+ "%s(): Rate adaption (octet 5) 0x%02x is not supported\n",
+ __func__, bcap->data.rate_adaption);
+ return -ENOTSUP;
+ }
+ if (bcap->data.sig_access != GSM48_BCAP_SA_I440_I450) {
+ LOGP(DMNCC, LOGL_ERROR,
+ "%s(): Signalling access protocol (octet 5) 0x%02x is not supported\n",
+ __func__, bcap->data.sig_access);
+ return -ENOTSUP;
+ }
+
+#define BCAP_RATE(interm_rate, user_rate) \
+ ((interm_rate << 8) | (user_rate << 0))
+
+ switch (BCAP_RATE(bcap->data.interm_rate, bcap->data.user_rate)) {
+ case BCAP_RATE(GSM48_BCAP_IR_8k, GSM48_BCAP_UR_300):
+ case BCAP_RATE(GSM48_BCAP_IR_8k, GSM48_BCAP_UR_1200):
+ case BCAP_RATE(GSM48_BCAP_IR_8k, GSM48_BCAP_UR_2400):
+ if (bcap->data.transp != GSM48_BCAP_TR_TRANSP) {
+ LOGP(DMNCC, LOGL_ERROR,
+ "%s(): wrong user-rate 0x%02x for a non-transparent call\n",
+ __func__, bcap->data.user_rate);
+ return -EINVAL;
+ }
+ /* fall-through */
+ case BCAP_RATE(GSM48_BCAP_IR_8k, GSM48_BCAP_UR_4800):
+ case BCAP_RATE(GSM48_BCAP_IR_16k, GSM48_BCAP_UR_9600):
+ if (bcap->data.transp != GSM48_BCAP_TR_TRANSP) {
+ LOGP(DMNCC, LOGL_ERROR,
+ "%s(): only transparent calls are supported so far\n",
+ __func__);
+ return -ENOTSUP;
+ }
+ break;
+ default:
+ LOGP(DMNCC, LOGL_ERROR,
+ "%s(): User rate 0x%02x (octets 6a) is not supported (IR=0x%02x)\n",
+ __func__, bcap->data.user_rate, bcap->data.interm_rate);
+ return -ENOTSUP;
+ }
+
+#undef BCAP_RATE
+
+ return 0;
+}
+
static int mncc_handle_bcap(struct gsm_mncc *mncc_out, /* CC Call Confirmed */
const struct gsm_mncc *mncc_in, /* CC Setup */
const struct gsm_settings *set)
@@ -262,7 +353,7 @@ static int mncc_handle_bcap(struct gsm_mncc *mncc_out, /* CC Call Confirmed */
/* if the Bearer Capability 1 IE is not present */
if (~mncc_in->fields & MNCC_F_BEARER_CAP) {
/* ... include our own Bearer Capability, assuming a speech call */
- mncc_set_bearer(mncc_out, set, -1);
+ mncc_set_bcap_speech(mncc_out, set, -1);
return 0;
}
@@ -289,12 +380,15 @@ static int mncc_handle_bcap(struct gsm_mncc *mncc_out, /* CC Call Confirmed */
* or if given codec is unimplemented
*/
if (speech_ver < 0)
- mncc_set_bearer(mncc_out, set, -1);
+ mncc_set_bcap_speech(mncc_out, set, -1);
else if (bcap->speech_ver[1] >= 0 || speech_ver != 0)
- mncc_set_bearer(mncc_out, set, speech_ver);
+ mncc_set_bcap_speech(mncc_out, set, speech_ver);
break;
}
case GSM48_BCAP_ITCAP_UNR_DIG_INF:
+ if (mncc_handle_bcap_data(bcap, set) != 0)
+ return -ENOTSUP;
+ break;
default:
LOGP(DMNCC, LOGL_ERROR,
"%s(): Information transfer capability 0x%02x is not supported\n",
@@ -596,7 +690,7 @@ int mncc_recv_internal(struct osmocom_ms *ms, int msg_type, void *arg)
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;
@@ -627,7 +721,8 @@ int mncc_call(struct osmocom_ms *ms, const char *number)
/* 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" : "voice", number);
/* called number */
setup.fields |= MNCC_F_CALLED;
if (number[0] == '+') {
@@ -640,7 +735,10 @@ int mncc_call(struct osmocom_ms *ms, const char *number)
OSMO_STRLCPY_ARRAY(setup.called.number, number);
/* bearer capability (mandatory) */
- mncc_set_bearer(&setup, &ms->settings, -1);
+ 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 17660712..d128f2df 100644
--- a/src/host/layer23/src/mobile/vty_interface.c
+++ b/src/host/layer23/src/mobile/vty_interface.c
@@ -494,10 +494,12 @@ DEFUN(network_select, network_select_cmd,
"Name of MS (see \"show ms\")\n"
DEFUN(call_num, call_num_cmd,
- CALL_CMD " NUMBER",
+ CALL_CMD " NUMBER [(voice|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 regular voice call (default)\n"
+ "Initiate a CSD (Circuit Switched Data) call\n")
{
struct osmocom_ms *ms;
struct gsm_settings *set;
@@ -527,7 +529,11 @@ DEFUN(call_num, call_num_cmd,
if (vty_check_number(vty, number))
return CMD_WARNING;
- mncc_call(ms, number);
+
+ if (argc > 2 && !strcmp(argv[2], "data")) /* data call: explicit selection */
+ mncc_call(ms, number, true);
+ else /* voice call: explicit selection or implicit default */
+ mncc_call(ms, number, false);
return CMD_SUCCESS;
}
@@ -557,7 +563,7 @@ DEFUN(call, call_cmd,
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"))
@@ -1311,6 +1317,12 @@ static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
SUP_WRITE(full_v3, "full-speech-v3");
SUP_WRITE(half_v1, "half-speech-v1");
SUP_WRITE(half_v3, "half-speech-v3");
+ SUP_WRITE(csd_tch_f144, "full-data-14400");
+ SUP_WRITE(csd_tch_f96, "full-data-9600");
+ SUP_WRITE(csd_tch_f48, "full-data-4800");
+ SUP_WRITE(csd_tch_h48, "half-data-4800");
+ SUP_WRITE(csd_tch_f24, "full-data-2400");
+ SUP_WRITE(csd_tch_h24, "half-data-2400");
if (!l23_vty_hide_default || sup->min_rxlev_dbm != set->min_rxlev_dbm)
vty_out(vty, " min-rxlev %d%s", set->min_rxlev_dbm,
VTY_NEWLINE);
@@ -2248,6 +2260,13 @@ SUP_EN_DI(full_v3, "full-speech-v3", "Full rate speech V3 (AMR)", 0);
SUP_EN_DI(half_v1, "half-speech-v1", "Half rate speech V1", 0);
SUP_EN_DI(half_v3, "half-speech-v3", "Half rate speech V3 (AMR)", 0);
+SUP_EN_DI(csd_tch_f144, "full-data-14400", "CSD TCH/F14.4", 0);
+SUP_EN_DI(csd_tch_f96, "full-data-9600", "CSD TCH/F9.6", 0);
+SUP_EN_DI(csd_tch_f48, "full-data-4800", "CSD TCH/F4.8", 0);
+SUP_EN_DI(csd_tch_h48, "half-data-4800", "CSD TCH/H4.8", 0);
+SUP_EN_DI(csd_tch_f24, "full-data-2400", "CSD TCH/F2.4", 0);
+SUP_EN_DI(csd_tch_h24, "half-data-2400", "CSD TCH/H2.4", 0);
+
DEFUN(cfg_ms_sup_min_rxlev, cfg_ms_sup_min_rxlev_cmd, "min-rxlev <-110--47>",
"Set the minimum receive level to select a cell\n"
"Minimum receive level from -110 dBm to -47 dBm")
@@ -2638,6 +2657,18 @@ int ms_vty_init(void)
install_element(SUPPORT_NODE, &cfg_ms_sup_di_half_v1_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_en_half_v3_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_di_half_v3_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_en_csd_tch_f144_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_di_csd_tch_f144_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_en_csd_tch_f96_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_di_csd_tch_f96_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_en_csd_tch_f48_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_di_csd_tch_f48_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_en_csd_tch_h48_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_di_csd_tch_h48_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_en_csd_tch_f24_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_di_csd_tch_f24_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_en_csd_tch_h24_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_di_csd_tch_h24_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_min_rxlev_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_dsc_max_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_skip_max_per_band_cmd);