summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2011-09-01 18:18:43 +0200
committerHarald Welte <laforge@gnumonks.org>2011-09-03 18:23:20 +0200
commitab386e6120559ef2deb6a27f4455539cba920c9d (patch)
tree425cb2f19eac173c8d59c719143735865f94740b
parent6b353778c4329deb27f69301c050e0b6e55d4df6 (diff)
Add VTY command to specify default speech codec
In order to have the MNCC application reliably decide on the codec type, it needs to know if we are running on a TCH/F or TCH/H. Thus, we pass lchan_mode as a new parameter to the 'struct gsm_mncc'
-rw-r--r--openbsc/include/openbsc/Makefile.am2
-rw-r--r--openbsc/include/openbsc/mncc.h1
-rw-r--r--openbsc/include/openbsc/mncc_int.h12
-rw-r--r--openbsc/include/openbsc/vty.h1
-rw-r--r--openbsc/src/libcommon/common_vty.c7
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c4
-rw-r--r--openbsc/src/libmsc/mncc_builtin.c18
-rw-r--r--openbsc/src/libmsc/vty_interface_layer3.c70
8 files changed, 109 insertions, 6 deletions
diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index 7717efb36..bb78535d8 100644
--- a/openbsc/include/openbsc/Makefile.am
+++ b/openbsc/include/openbsc/Makefile.am
@@ -11,7 +11,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \
gprs_ns_frgre.h auth.h osmo_msc.h bsc_msc.h bsc_nat.h \
osmo_bsc_rf.h osmo_bsc.h network_listen.h bsc_nat_sccp.h \
osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h \
- bss.h gsm_data_shared.h control_cmd.h ipaccess.h
+ bss.h gsm_data_shared.h control_cmd.h ipaccess.h mncc_int.h
openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
openbscdir = $(includedir)/openbsc
diff --git a/openbsc/include/openbsc/mncc.h b/openbsc/include/openbsc/mncc.h
index ed1bfd652..8c59fe2c6 100644
--- a/openbsc/include/openbsc/mncc.h
+++ b/openbsc/include/openbsc/mncc.h
@@ -148,6 +148,7 @@ struct gsm_mncc {
int emergency;
char imsi[16];
+ unsigned char lchan_type;
unsigned char lchan_mode;
};
diff --git a/openbsc/include/openbsc/mncc_int.h b/openbsc/include/openbsc/mncc_int.h
new file mode 100644
index 000000000..4f30f08c0
--- /dev/null
+++ b/openbsc/include/openbsc/mncc_int.h
@@ -0,0 +1,12 @@
+#ifndef _MNCC_INT_H
+#define _MNCC_INT_H
+
+#include <stdint.h>
+
+struct mncc_int {
+ uint8_t def_codec[2];
+};
+
+extern struct mncc_int mncc_int;
+
+#endif
diff --git a/openbsc/include/openbsc/vty.h b/openbsc/include/openbsc/vty.h
index d455a2b81..19b168fac 100644
--- a/openbsc/include/openbsc/vty.h
+++ b/openbsc/include/openbsc/vty.h
@@ -35,6 +35,7 @@ enum bsc_vty_node {
OM2K_NODE,
TRUNK_NODE,
PGROUP_NODE,
+ MNCC_INT_NODE,
};
extern int bsc_vty_is_config_node(struct vty *vty, int node);
diff --git a/openbsc/src/libcommon/common_vty.c b/openbsc/src/libcommon/common_vty.c
index 5b4b296cb..e8486f4f1 100644
--- a/openbsc/src/libcommon/common_vty.c
+++ b/openbsc/src/libcommon/common_vty.c
@@ -86,12 +86,11 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
case PGROUP_NODE:
vty->node = NAT_NODE;
break;
- case MSC_NODE:
- vty->node = CONFIG_NODE;
- break;
case TRUNK_NODE:
vty->node = MGCP_NODE;
break;
+ case MSC_NODE:
+ case MNCC_INT_NODE:
default:
vty->node = CONFIG_NODE;
}
@@ -161,6 +160,7 @@ gDEFUN(ournode_exit,
vty->index = NULL;
break;
case MSC_NODE:
+ case MNCC_INT_NODE:
vty->node = CONFIG_NODE;
break;
case TRUNK_NODE:
@@ -197,6 +197,7 @@ gDEFUN(ournode_end,
case NAT_BSC_NODE:
case PGROUP_NODE:
case MSC_NODE:
+ case MNCC_INT_NODE:
vty_config_unlock(vty);
vty->node = ENABLE_NODE;
vty->index = NULL;
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index dcb6e113d..0cd707d57 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -1839,6 +1839,8 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
memset(&setup, 0, sizeof(struct gsm_mncc));
setup.callref = trans->callref;
+ if (trans->conn && trans->conn->lchan)
+ setup.lchan_type = trans->conn->lchan->type;
tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
/* emergency setup is identified by msg_type */
if (msg_type == GSM48_MT_CC_EMERG_SETUP)
@@ -1995,6 +1997,8 @@ static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
memset(&call_conf, 0, sizeof(struct gsm_mncc));
call_conf.callref = trans->callref;
+ if (trans->conn && trans->conn->lchan)
+ call_conf.lchan_type = trans->conn->lchan->type;
tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
#if 0
/* repeat */
diff --git a/openbsc/src/libmsc/mncc_builtin.c b/openbsc/src/libmsc/mncc_builtin.c
index 105f1dd96..31d9b4325 100644
--- a/openbsc/src/libmsc/mncc_builtin.c
+++ b/openbsc/src/libmsc/mncc_builtin.c
@@ -30,6 +30,7 @@
#include <openbsc/gsm_04_08.h>
#include <openbsc/debug.h>
#include <openbsc/mncc.h>
+#include <openbsc/mncc_int.h>
#include <osmocom/core/talloc.h>
#include <openbsc/gsm_data.h>
#include <openbsc/transaction.h>
@@ -41,6 +42,10 @@ static LLIST_HEAD(call_list);
static uint32_t new_callref = 0x00000001;
+struct mncc_int mncc_int = {
+ .def_codec = { GSM48_CMODE_SPEECH_EFR, GSM48_CMODE_SPEECH_V1 },
+};
+
static void free_call(struct gsm_call *call)
{
llist_del(&call->entry);
@@ -60,6 +65,15 @@ static struct gsm_call *get_call_ref(uint32_t callref)
return NULL;
}
+static uint8_t determine_lchan_mode(struct gsm_mncc *setup)
+{
+ /* FIXME: check codec capabilities of the phone */
+
+ if (setup->lchan_type == GSM_LCHAN_TCH_F)
+ return mncc_int.def_codec[0];
+ else
+ return mncc_int.def_codec[1];
+}
/* on incoming call, look up database and send setup to remote subscr. */
static int mncc_setup_ind(struct gsm_call *call, int msg_type,
@@ -112,7 +126,7 @@ static int mncc_setup_ind(struct gsm_call *call, int msg_type,
/* modify mode */
memset(&mncc, 0, sizeof(struct gsm_mncc));
mncc.callref = call->callref;
- mncc.lchan_mode = GSM48_CMODE_SPEECH_EFR;
+ mncc.lchan_mode = determine_lchan_mode(setup);
DEBUGP(DMNCC, "(call %x) Modify channel mode.\n", call->callref);
mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, &mncc);
@@ -346,7 +360,7 @@ int int_mncc_recv(struct gsm_network *net, struct msgb *msg)
break;
case MNCC_CALL_CONF_IND:
/* we now need to MODIFY the channel */
- data->lchan_mode = GSM48_CMODE_SPEECH_EFR;
+ data->lchan_mode = determine_lchan_mode(data);
mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, data);
break;
case MNCC_ALERT_IND:
diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c
index 1d3ffe98c..cdda7e4a4 100644
--- a/openbsc/src/libmsc/vty_interface_layer3.c
+++ b/openbsc/src/libmsc/vty_interface_layer3.c
@@ -45,6 +45,7 @@
#include <openbsc/gsm_04_80.h>
#include <openbsc/chan_alloc.h>
#include <openbsc/sms_queue.h>
+#include <openbsc/mncc_int.h>
extern struct gsm_network *gsmnet_from_vty(struct vty *v);
@@ -762,6 +763,69 @@ DEFUN(smsqueue_fail,
return CMD_SUCCESS;
}
+
+DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
+ "mncc-int", "Configure internal MNCC handler")
+{
+ vty->node = MNCC_INT_NODE;
+
+ return CMD_SUCCESS;
+}
+
+static struct cmd_node mncc_int_node = {
+ MNCC_INT_NODE,
+ "%s(mncc-int)#",
+ 1,
+};
+
+static const struct value_string tchf_codec_names[] = {
+ { GSM48_CMODE_SPEECH_V1, "fr" },
+ { GSM48_CMODE_SPEECH_EFR, "efr" },
+ { GSM48_CMODE_SPEECH_AMR, "amr" },
+ { 0, NULL }
+};
+
+static const struct value_string tchh_codec_names[] = {
+ { GSM48_CMODE_SPEECH_V1, "hr" },
+ { GSM48_CMODE_SPEECH_AMR, "amr" },
+ { 0, NULL }
+};
+
+static int config_write_mncc_int(struct vty *vty)
+{
+ vty_out(vty, "mncc-int%s", VTY_NEWLINE);
+ vty_out(vty, " default-codec tch-f %s%s",
+ get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
+ VTY_NEWLINE);
+ vty_out(vty, " default-codec tch-h %s%s",
+ get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
+ VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(mnccint_def_codec_f,
+ mnccint_def_codec_f_cmd,
+ "default-codec tch-f (fr|efr|amr)",
+ "Set default codec\n" "Codec for TCH/F\n"
+ "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
+{
+ mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(mnccint_def_codec_h,
+ mnccint_def_codec_h_cmd,
+ "default-codec tch-h (hr|amr)",
+ "Set default codec\n" "Codec for TCH/H\n"
+ "Half-Rate\n" "Adaptive Multi-Rate\n")
+{
+ mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
+
+ return CMD_SUCCESS;
+}
+
int bsc_vty_init_extra(void)
{
osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
@@ -794,5 +858,11 @@ int bsc_vty_init_extra(void)
install_element(ENABLE_NODE, &smsqueue_fail_cmd);
install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
+ install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
+ install_node(&mncc_int_node, config_write_mncc_int);
+ install_default(MNCC_INT_NODE);
+ install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
+ install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
+
return 0;
}