Each BTS can be configured for speech support (other than GSM full rate)

Speech codings which are not supported by BTS will be removed from the
bearer capability information element after parsing. This way it is not
required for the MNCC application to consider support of each BTS.

Only GSM full rate is supported by default.
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index 9063f98..54f5f70 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -79,6 +79,29 @@
 	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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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)) {