From ab386e6120559ef2deb6a27f4455539cba920c9d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 1 Sep 2011 18:18:43 +0200 Subject: [PATCH] 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' --- openbsc/include/openbsc/Makefile.am | 2 +- openbsc/include/openbsc/mncc.h | 1 + openbsc/include/openbsc/mncc_int.h | 12 ++++ openbsc/include/openbsc/vty.h | 1 + openbsc/src/libcommon/common_vty.c | 7 ++- openbsc/src/libmsc/gsm_04_08.c | 4 ++ openbsc/src/libmsc/mncc_builtin.c | 18 +++++- openbsc/src/libmsc/vty_interface_layer3.c | 70 +++++++++++++++++++++++ 8 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 openbsc/include/openbsc/mncc_int.h 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 + +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 #include #include +#include #include #include #include @@ -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 #include #include +#include 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; }