diff options
-rw-r--r-- | openbsc/include/openbsc/gsm_data_shared.h | 9 | ||||
-rw-r--r-- | openbsc/src/libbsc/bsc_vty.c | 81 | ||||
-rw-r--r-- | openbsc/src/libmsc/gsm_04_08.c | 28 | ||||
-rw-r--r-- | openbsc/src/libmsc/mncc_builtin.c | 2 |
4 files changed, 119 insertions, 1 deletions
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index b49a539a9..3bf05e4b3 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -144,6 +144,12 @@ struct bts_ul_meas { uint8_t inv_rssi; }; +struct bts_codec_conf { + uint8_t hr; + uint8_t efr; + uint8_t amr; +}; + struct amr_mode { uint8_t mode; uint8_t threshold; @@ -707,6 +713,9 @@ struct gsm_bts { /* exclude the BTS from the global RF Lock handling */ int excl_from_rf_lock; + + /* supported codecs beside FR */ + struct bts_codec_conf codec; #endif /* ROLE_BSC */ void *role; }; diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 7fa5ea7da..b27184be3 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -631,6 +631,15 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) } } + vty_out(vty, " codec-support fr"); + if (bts->codec.hr) + vty_out(vty, " hr"); + if (bts->codec.efr) + vty_out(vty, " efr"); + if (bts->codec.amr) + vty_out(vty, " amr"); + vty_out(vty, "%s", VTY_NEWLINE); + config_write_bts_gprs(vty, bts); if (bts->excl_from_rf_lock) @@ -2658,6 +2667,73 @@ DEFUN(cfg_bts_no_excl_rf_lock, return CMD_SUCCESS; } +static void _get_codec_from_arg(struct vty *vty, int argc, const char *argv[]) +{ + struct gsm_bts *bts = vty->index; + struct bts_codec_conf *codec = &bts->codec; + int i; + + codec->hr = 0; + codec->efr = 0; + codec->amr = 0; + for (i = 0; i < argc; i++) { + if (!strcmp(argv[i], "hr")) + codec->hr = 1; + if (!strcmp(argv[i], "efr")) + codec->efr = 1; + if (!strcmp(argv[i], "amr")) + codec->amr = 1; + } +} + +#define CODEC_PAR_STR " (hr|efr|amr)" +#define CODEC_HELP_STR "Half Rate\n" \ + "Enhanced Full Rate\nAdaptive Multirate\n" + +DEFUN(cfg_bts_codec0, cfg_bts_codec0_cmd, + "codec-support fr", + "Codec Support settings\nFullrate\n") +{ + _get_codec_from_arg(vty, 0, argv); + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_codec1, cfg_bts_codec1_cmd, + "codec-support fr" CODEC_PAR_STR, + "Codec Support settings\nFullrate\n" + CODEC_HELP_STR) +{ + _get_codec_from_arg(vty, 1, argv); + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_codec2, cfg_bts_codec2_cmd, + "codec-support fr" CODEC_PAR_STR CODEC_PAR_STR, + "Codec Support settings\nFullrate\n" + CODEC_HELP_STR CODEC_HELP_STR) +{ + _get_codec_from_arg(vty, 2, argv); + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_codec3, cfg_bts_codec3_cmd, + "codec-support fr" CODEC_PAR_STR CODEC_PAR_STR CODEC_PAR_STR, + "Codec Support settings\nFullrate\n" + CODEC_HELP_STR CODEC_HELP_STR CODEC_HELP_STR) +{ + _get_codec_from_arg(vty, 3, argv); + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_codec4, cfg_bts_codec4_cmd, + "codec-support fr" CODEC_PAR_STR CODEC_PAR_STR CODEC_PAR_STR CODEC_PAR_STR, + "Codec Support settings\nFullrate\n" + CODEC_HELP_STR CODEC_HELP_STR CODEC_HELP_STR CODEC_HELP_STR) +{ + _get_codec_from_arg(vty, 4, argv); + return CMD_SUCCESS; +} + #define TRX_TEXT "Radio Transceiver\n" /* per TRX configuration */ @@ -3255,6 +3331,11 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd); install_element(BTS_NODE, &cfg_bts_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_no_excl_rf_lock_cmd); + install_element(BTS_NODE, &cfg_bts_codec0_cmd); + install_element(BTS_NODE, &cfg_bts_codec1_cmd); + install_element(BTS_NODE, &cfg_bts_codec2_cmd); + install_element(BTS_NODE, &cfg_bts_codec3_cmd); + install_element(BTS_NODE, &cfg_bts_codec4_cmd); install_element(BTS_NODE, &cfg_trx_cmd); install_node(&trx_node, dummy_config_write); diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 9063f9815..54f5f7072 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -79,6 +79,29 @@ struct gsm_lai { uint16_t lac; }; +static int apply_codec_restrictions(struct gsm_bts *bts, + struct gsm_mncc_bearer_cap *bcap) +{ + int i, j; + + /* remove unsupported speech versions from list */ + for (i = 0, j = 0; bcap->speech_ver[i] >= 0; i++) { + if (bcap->speech_ver[i] == GSM48_BCAP_SV_FR) + bcap->speech_ver[j++] = GSM48_BCAP_SV_FR; + if (bcap->speech_ver[i] == GSM48_BCAP_SV_EFR && bts->codec.efr) + bcap->speech_ver[j++] = GSM48_BCAP_SV_EFR; + if (bcap->speech_ver[i] == GSM48_BCAP_SV_AMR_F && bts->codec.amr) + bcap->speech_ver[j++] = GSM48_BCAP_SV_AMR_F; + if (bcap->speech_ver[i] == GSM48_BCAP_SV_HR && bts->codec.hr) + bcap->speech_ver[j++] = GSM48_BCAP_SV_HR; + if (bcap->speech_ver[i] == GSM48_BCAP_SV_AMR_H && bts->codec.amr) + bcap->speech_ver[j++] = GSM48_BCAP_SV_AMR_H; + } + bcap->speech_ver[j] = -1; + + return 0; +} + static uint32_t new_callref = 0x80000001; void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg) @@ -1799,6 +1822,7 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) setup.fields |= MNCC_F_BEARER_CAP; gsm48_decode_bearer_cap(&setup.bearer_cap, TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); + apply_codec_restrictions(trans->conn->bts, &setup.bearer_cap); } /* facility */ if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { @@ -1952,6 +1976,7 @@ static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg) call_conf.fields |= MNCC_F_BEARER_CAP; gsm48_decode_bearer_cap(&call_conf.bearer_cap, TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); + apply_codec_restrictions(trans->conn->bts, &call_conf.bearer_cap); } /* cause */ if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { @@ -2640,6 +2665,7 @@ static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg) modify.fields |= MNCC_F_BEARER_CAP; gsm48_decode_bearer_cap(&modify.bearer_cap, TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); + apply_codec_restrictions(trans->conn->bts, &modify.bearer_cap); } new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY); @@ -2682,6 +2708,7 @@ static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg modify.fields |= MNCC_F_BEARER_CAP; gsm48_decode_bearer_cap(&modify.bearer_cap, TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); + apply_codec_restrictions(trans->conn->bts, &modify.bearer_cap); } new_cc_state(trans, GSM_CSTATE_ACTIVE); @@ -2722,6 +2749,7 @@ static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg) modify.fields |= GSM48_IE_BEARER_CAP; gsm48_decode_bearer_cap(&modify.bearer_cap, TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); + apply_codec_restrictions(trans->conn->bts, &modify.bearer_cap); } /* cause */ if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { diff --git a/openbsc/src/libmsc/mncc_builtin.c b/openbsc/src/libmsc/mncc_builtin.c index 617cbf25f..be3545475 100644 --- a/openbsc/src/libmsc/mncc_builtin.c +++ b/openbsc/src/libmsc/mncc_builtin.c @@ -43,7 +43,7 @@ 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 }, + .def_codec = { GSM48_CMODE_SPEECH_V1, GSM48_CMODE_SPEECH_V1 }, }; static void free_call(struct gsm_call *call) |