summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-03-31 12:01:25 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2013-07-29 12:39:55 +0200
commitbb3e01db4cdff50ed66688ae2b41d7a82c417ee4 (patch)
treeb50654fe44f426ccb9999f15e5b9c9a9f6b7a1de
parent521e1a41c63847cfb58b5c0704252ba6475e4426 (diff)
osmo-nitb support for codec negotiation
Since codec negotiation is done automatically, there is no need to define codec for TCH/F and TCH/H via VTY anymore.
-rw-r--r--openbsc/include/openbsc/mncc.h4
-rw-r--r--openbsc/include/openbsc/mncc_int.h6
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c15
-rw-r--r--openbsc/src/libmsc/mncc_builtin.c106
-rw-r--r--openbsc/src/libmsc/vty_interface_layer3.c47
5 files changed, 109 insertions, 69 deletions
diff --git a/openbsc/include/openbsc/mncc.h b/openbsc/include/openbsc/mncc.h
index 804766920..23e812bd1 100644
--- a/openbsc/include/openbsc/mncc.h
+++ b/openbsc/include/openbsc/mncc.h
@@ -44,6 +44,10 @@ struct gsm_call {
uint32_t callref;
/* the 'remote' transaction */
uint32_t remote_ref;
+
+ /* the capabilities */
+ uint8_t lchan_type;
+ struct gsm_mncc_bearer_cap bcap;
};
#define MNCC_SETUP_REQ 0x0101
diff --git a/openbsc/include/openbsc/mncc_int.h b/openbsc/include/openbsc/mncc_int.h
index 4f30f08c0..92012c101 100644
--- a/openbsc/include/openbsc/mncc_int.h
+++ b/openbsc/include/openbsc/mncc_int.h
@@ -3,10 +3,4 @@
#include <stdint.h>
-struct mncc_int {
- uint8_t def_codec[2];
-};
-
-extern struct mncc_int mncc_int;
-
#endif
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index 463a09cae..d0509f9de 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -3143,6 +3143,8 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
/* If subscriber has no lchan */
if (!conn) {
+ uint8_t type;
+
/* find transaction with this subscriber already paging */
llist_for_each_entry(transt, &net->trans_list, entry) {
/* Transaction of our lchan? */
@@ -3172,7 +3174,18 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
}
*trans->paging_request = subscr->net;
- subscr_get_channel(subscr, RSL_CHANNEED_TCH_F, setup_trig_pag_evt, trans->paging_request);
+
+ switch (data->lchan_type) {
+ case GSM_LCHAN_TCH_F:
+ type = RSL_CHANNEED_TCH_F;
+ break;
+ case GSM_LCHAN_TCH_H:
+ type = RSL_CHANNEED_TCH_ForH;
+ break;
+ default:
+ type = RSL_CHANNEED_SDCCH;
+ }
+ subscr_get_channel(subscr, type, setup_trig_pag_evt, trans->paging_request);
subscr_put(subscr);
return 0;
diff --git a/openbsc/src/libmsc/mncc_builtin.c b/openbsc/src/libmsc/mncc_builtin.c
index 69daab32c..d20f41046 100644
--- a/openbsc/src/libmsc/mncc_builtin.c
+++ b/openbsc/src/libmsc/mncc_builtin.c
@@ -42,10 +42,6 @@ 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);
@@ -65,14 +61,48 @@ static struct gsm_call *get_call_ref(uint32_t callref)
return NULL;
}
-static uint8_t determine_lchan_mode(struct gsm_mncc *setup)
+static void store_bearer_cap(struct gsm_call *call, struct gsm_mncc *mncc)
{
- /* FIXME: check codec capabilities of the phone */
+ call->lchan_type = mncc->lchan_type;
+ memcpy(&call->bcap, &mncc->bearer_cap, sizeof(struct gsm_mncc_bearer_cap));
+}
+
+static int determine_lchan_mode(struct gsm_call *calling,
+ struct gsm_call *called)
+{
+ int i, j;
+
+ /* FIXME: dynamic channel configuration */
+ if (calling->lchan_type != called->lchan_type) {
+ LOGP(DMNCC, LOGL_NOTICE, "Not equal lchan_types\n");
+ return -ENOTSUP;
+ }
+ if (calling->lchan_type != GSM_LCHAN_TCH_F
+ && calling->lchan_type != GSM_LCHAN_TCH_H) {
+ LOGP(DMNCC, LOGL_NOTICE, "Not TCH lchan_types\n");
+ return -ENOTSUP;
+ }
+
+ /* select best codec, as prefered by the caller and supporte by both. */
+ for (i = 0; calling->bcap.speech_ver[i] >= 0; i++) {
+ /* omit capability of different channel type
+ * FIXME: dynamic channel configuration */
+ if (calling->lchan_type == GSM_LCHAN_TCH_F
+ && (calling->bcap.speech_ver[i] & 1) == 1)
+ continue;
+ if (calling->lchan_type == GSM_LCHAN_TCH_H
+ && (calling->bcap.speech_ver[i] & 1) == 0)
+ continue;
+ for (j = 0; called->bcap.speech_ver[j] >= 0; j++) {
+ if (calling->bcap.speech_ver[i]
+ == called->bcap.speech_ver[j]) {
+ /* convert speech version to lchan mode */
+ return ((calling->bcap.speech_ver[i] & 0xe) << 4) | 1;
+ }
+ }
+ }
- if (setup->lchan_type == GSM_LCHAN_TCH_F)
- return mncc_int.def_codec[0];
- else
- return mncc_int.def_codec[1];
+ return -ENOTSUP;
}
/* on incoming call, look up database and send setup to remote subscr. */
@@ -129,12 +159,8 @@ static int mncc_setup_ind(struct gsm_call *call, int msg_type,
DEBUGP(DMNCC, "(call %x) Accepting call.\n", call->callref);
mncc_tx_to_cc(call->net, MNCC_CALL_PROC_REQ, &mncc);
- /* modify mode */
- memset(&mncc, 0, sizeof(struct gsm_mncc));
- mncc.callref = call->callref;
- 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);
+ /* store bearer capabilites of supported modes */
+ store_bearer_cap(call, setup);
/* send setup to remote */
// setup->fields |= MNCC_F_SIGNAL;
@@ -149,6 +175,50 @@ out_reject:
return 0;
}
+static int mncc_call_conf_ind(struct gsm_call *call, int msg_type,
+ struct gsm_mncc *conf)
+{
+ struct gsm_call *remote;
+ struct gsm_mncc mncc;
+ int mode;
+
+ memset(&mncc, 0, sizeof(struct gsm_mncc));
+ mncc.callref = call->callref;
+
+ /* send alerting to remote */
+ if (!(remote = get_call_ref(call->remote_ref)))
+ return 0;
+
+ /* store bearer capabilites of supported modes */
+ store_bearer_cap(call, conf);
+
+ mode = determine_lchan_mode(call, remote);
+ if (mode < 0) {
+ LOGP(DMNCC, LOGL_NOTICE, "(call %x,%x) There is no commonly "
+ "supported speech version\n", call->callref,
+ remote->callref);
+ mncc_set_cause(&mncc, GSM48_CAUSE_LOC_PRN_S_LU,
+ GSM48_CC_CAUSE_BEARER_CA_UNAVAIL);
+ goto out_release;
+ }
+
+ /* modify mode */
+ mncc.lchan_mode = mode;
+ DEBUGP(DMNCC, "(call %x) Modify channel mode.\n", call->callref);
+ mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, &mncc);
+ mncc.callref = remote->callref;
+ DEBUGP(DMNCC, "(call %x) Modify channel mode.\n", remote->callref);
+ mncc_tx_to_cc(remote->net, MNCC_LCHAN_MODIFY, &mncc);
+
+ return 0;
+
+out_release:
+ mncc_tx_to_cc(call->net, MNCC_REL_REQ, &mncc);
+ free_call(call);
+ mncc_tx_to_cc(remote->net, MNCC_REL_REQ, &mncc);
+ free_call(remote);
+ return 0;
+}
static int mncc_alert_ind(struct gsm_call *call, int msg_type,
struct gsm_mncc *alert)
{
@@ -353,9 +423,7 @@ int int_mncc_recv(struct gsm_network *net, struct msgb *msg)
case MNCC_SETUP_COMPL_IND:
break;
case MNCC_CALL_CONF_IND:
- /* we now need to MODIFY the channel */
- data->lchan_mode = determine_lchan_mode(data);
- mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, data);
+ rc = mncc_call_conf_ind(call, msg_type, arg);
break;
case MNCC_ALERT_IND:
rc = mncc_alert_ind(call, msg_type, arg);
diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c
index 79c345771..d90b4c4f3 100644
--- a/openbsc/src/libmsc/vty_interface_layer3.c
+++ b/openbsc/src/libmsc/vty_interface_layer3.c
@@ -864,6 +864,7 @@ DEFUN(smsqueue_fail,
}
+#if 0
DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
"mncc-int", "Configure internal MNCC handler")
{
@@ -878,53 +879,13 @@ static struct cmd_node mncc_int_node = {
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;
}
+#endif
#define OBSOLETE_MSG "Obsolete\n"
/* this is just for backwards compatibility as the sms code moved into
@@ -973,13 +934,13 @@ int bsc_vty_init_extra(void)
install_element(ENABLE_NODE, &smsqueue_fail_cmd);
install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
+#if 0
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, &ournode_exit_cmd);
install_element(MNCC_INT_NODE, &ournode_end_cmd);
- install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
- install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
+#endif
install_element(CFG_LOG_NODE, &log_level_sms_cmd);