aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc/codec_pref.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bsc/codec_pref.c')
-rw-r--r--src/osmo-bsc/codec_pref.c85
1 files changed, 56 insertions, 29 deletions
diff --git a/src/osmo-bsc/codec_pref.c b/src/osmo-bsc/codec_pref.c
index a94d6a834..412ed9afd 100644
--- a/src/osmo-bsc/codec_pref.c
+++ b/src/osmo-bsc/codec_pref.c
@@ -264,6 +264,47 @@ static uint16_t gen_bss_supported_amr_s15_s0(const struct bsc_msc_data *msc, con
return amr_s15_s0_bts & amr_s15_s0_msc;
}
+/* Special handling for AMR rate configuration bits (S15-S0) */
+static int match_amr_s15_s0(struct channel_mode_and_rate *ch_mode_rate, const struct bsc_msc_data *msc, const struct gsm_bts *bts, const struct gsm0808_speech_codec *sc_match, uint8_t perm_spch)
+{
+ uint16_t amr_s15_s0_supported;
+
+ /* Normally the MSC should never try to advertise an AMR codec
+ * configuration that we did not previously advertised as supported.
+ * However, to ensure that no unsupported AMR codec configuration
+ * enters the further processing steps we again lookup what we support
+ * and generate an intersection. All further processing is then done
+ * with this intersection result. At the same time we will make sure
+ * that the intersection contains at least one rate setting. */
+
+ amr_s15_s0_supported = gen_bss_supported_amr_s15_s0(msc, bts, (perm_spch == GSM0808_PERM_HR3));
+
+ /* NOTE: The sc_match pointer points to a speech codec from the speech
+ * codec list that has been communicated with the ASSIGNMENT COMMAND.
+ * However, only AoIP based networks will include a speech codec list
+ * into the ASSIGNMENT COMMAND. For non AoIP based networks, no speech
+ * codec (sc_match) will be available, so we will fully rely on the
+ * local configuration for thoses cases. */
+ if (sc_match)
+ ch_mode_rate->s15_s0 = sc_match->cfg & amr_s15_s0_supported;
+ else
+ ch_mode_rate->s15_s0 = amr_s15_s0_supported;
+
+ /* Prefer "Config-NB-Code = 1" (S1) over all other AMR rates setttings.
+ * When S1 is set, the active set will automatically include 12.2k, 7.4k,
+ * 5.9k, 4.75k, in case of HR 12,2k is left out. */
+ if (ch_mode_rate->s15_s0 & GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20) {
+ ch_mode_rate->s15_s0 &= 0xff00;
+ ch_mode_rate->s15_s0 |= GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20;
+ }
+
+ /* Make sure at least one rate is set. */
+ if ((ch_mode_rate->s15_s0 & 0x00ff) == 0x0000)
+ return -EINVAL;
+
+ return 0;
+}
+
/*! Match the codec preferences from local config with a received codec preferences IEs received from the
* MSC and the BTS' codec configuration.
* \param[out] ch_mode_rate resulting codec and rate information
@@ -283,7 +324,6 @@ int match_codec_pref(struct channel_mode_and_rate *ch_mode_rate,
uint8_t perm_spch;
bool match = false;
const struct gsm0808_speech_codec *sc_match = NULL;
- uint16_t amr_s15_s0_supported;
int rc;
/* Note: Normally the MSC should never try to advertise a codec that
@@ -313,10 +353,22 @@ int match_codec_pref(struct channel_mode_and_rate *ch_mode_rate,
/* Match the permitted speech value against the codec lists that were
* advertised by the MS and the MSC */
- if (test_codec_pref(&sc_match, scl, ct, perm_spch)) {
- match = true;
- break;
+ if (!test_codec_pref(&sc_match, scl, ct, perm_spch)) {
+ continue;
}
+
+ /* Special handling for AMR */
+ if (perm_spch == GSM0808_PERM_HR3 || perm_spch == GSM0808_PERM_FR3) {
+ rc = match_amr_s15_s0(ch_mode_rate, msc, bts, sc_match, perm_spch);
+ if (rc < 0) {
+ ch_mode_rate->s15_s0 = 0;
+ continue;
+ }
+ } else
+ ch_mode_rate->s15_s0 = 0;
+
+ match = true;
+ break;
}
/* Exit without result, in case no match can be deteched */
@@ -330,31 +382,6 @@ int match_codec_pref(struct channel_mode_and_rate *ch_mode_rate,
/* Lookup a channel mode for the selected codec */
ch_mode_rate->chan_mode = gsm88_to_chan_mode(perm_spch);
- /* Special handling for AMR */
- if (perm_spch == GSM0808_PERM_HR3 || perm_spch == GSM0808_PERM_FR3) {
- /* Normally the MSC should never try to advertise an AMR codec
- * configuration that we did not previously advertise as
- * supported. However, to ensure that no unsupported AMR codec
- * configuration enters the further processing steps we again
- * lookup what we support and generate an intersection. All
- * further processing is then done with this intersection
- * result */
- amr_s15_s0_supported = gen_bss_supported_amr_s15_s0(msc, bts, (perm_spch == GSM0808_PERM_HR3));
- if (sc_match)
- ch_mode_rate->s15_s0 = sc_match->cfg & amr_s15_s0_supported;
- else
- ch_mode_rate->s15_s0 = amr_s15_s0_supported;
-
- /* NOTE: The function test_codec_pref() will populate the
- * sc_match pointer from the searched speech codec list. For
- * AoIP based networks, no speech codec list will be present
- * and therefore no sc_match will be populated. For those
- * cases only the local configuration will influence s15_s0.
- * However s15_s0 is always populated with a meaningful value,
- * regardless if AoIP is in use or not. */
- } else
- ch_mode_rate->s15_s0 = 0;
-
return 0;
}