aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/gsm_data_shared.h9
-rw-r--r--openbsc/src/libbsc/bsc_vty.c81
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c28
-rw-r--r--openbsc/src/libmsc/mncc_builtin.c2
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)