From 7da5e87d0a76b16a30d084accf091913d7b3e347 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 31 Mar 2013 12:01:25 +0200 Subject: 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. --- include/osmocom/bsc/mncc.h | 4 ++ include/osmocom/bsc/mncc_int.h | 6 --- src/libmsc/gsm_04_08.c | 15 +++++- src/libmsc/mncc_builtin.c | 106 +++++++++++++++++++++++++++++++------- src/libmsc/vty_interface_layer3.c | 47 ++--------------- 5 files changed, 109 insertions(+), 69 deletions(-) diff --git a/include/osmocom/bsc/mncc.h b/include/osmocom/bsc/mncc.h index 804766920..23e812bd1 100644 --- a/include/osmocom/bsc/mncc.h +++ b/include/osmocom/bsc/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/include/osmocom/bsc/mncc_int.h b/include/osmocom/bsc/mncc_int.h index 4f30f08c0..92012c101 100644 --- a/include/osmocom/bsc/mncc_int.h +++ b/include/osmocom/bsc/mncc_int.h @@ -3,10 +3,4 @@ #include -struct mncc_int { - uint8_t def_codec[2]; -}; - -extern struct mncc_int mncc_int; - #endif diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c index 463a09cae..d0509f9de 100644 --- a/src/libmsc/gsm_04_08.c +++ b/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/src/libmsc/mncc_builtin.c b/src/libmsc/mncc_builtin.c index 69daab32c..d20f41046 100644 --- a/src/libmsc/mncc_builtin.c +++ b/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/src/libmsc/vty_interface_layer3.c b/src/libmsc/vty_interface_layer3.c index 79c345771..d90b4c4f3 100644 --- a/src/libmsc/vty_interface_layer3.c +++ b/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); -- cgit v1.2.3