diff options
author | Philipp Maier <pmaier@sysmocom.de> | 2017-05-31 17:17:59 +0200 |
---|---|---|
committer | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2017-06-18 17:50:08 +0200 |
commit | 9f15ac5ba06c91086626eff4855848ee80b56d44 (patch) | |
tree | 74d4a6e2505e640a6a23bf31a5bbd01c018c491a /openbsc/src/libmsc/a_iface.c | |
parent | dfe085d979ba8b7266a6c66ecb13bf5a11a8d86f (diff) |
aoip: signal channel type to BSC
obtain the permitted speech and the prefered channel parameters
and signal it to the MSC with the channel type field.
Diffstat (limited to 'openbsc/src/libmsc/a_iface.c')
-rw-r--r-- | openbsc/src/libmsc/a_iface.c | 112 |
1 files changed, 106 insertions, 6 deletions
diff --git a/openbsc/src/libmsc/a_iface.c b/openbsc/src/libmsc/a_iface.c index 545cdaada..93dcf07ef 100644 --- a/openbsc/src/libmsc/a_iface.c +++ b/openbsc/src/libmsc/a_iface.c @@ -24,6 +24,7 @@ #include <osmocom/sigtran/sccp_helpers.h> #include <osmocom/gsm/gsm0808.h> #include <osmocom/gsm/protocol/gsm_08_08.h> +#include <osmocom/gsm/protocol/gsm_04_08.h> #include <openbsc/debug.h> #include <openbsc/msc_ifaces.h> #include <openbsc/a_iface.h> @@ -125,6 +126,109 @@ int a_page(const char *imsi, uint32_t tmsi, uint16_t lac) return page_count; } +/* Convert speech version field */ +static uint8_t convert_Abis_sv_to_A_sv(int speech_ver) +{ + /* The speech versions that are transmitted in the Bearer capability + * information element, that is transmitted on the Abis interfece + * use a different encoding than the permitted speech version + * identifier, that is signalled in the channel type element on the A + * interface. (See also 3GPP TS 48.008, 3.2.2.1 and 3GPP TS 24.008, + * 10.5.103 */ + + switch (speech_ver) { + case GSM48_BCAP_SV_FR: + return GSM0808_PERM_FR1; + break; + case GSM48_BCAP_SV_HR: + return GSM0808_PERM_HR1; + break; + case GSM48_BCAP_SV_EFR: + return GSM0808_PERM_FR2; + break; + case GSM48_BCAP_SV_AMR_F: + return GSM0808_PERM_FR3; + break; + case GSM48_BCAP_SV_AMR_H: + return GSM0808_PERM_HR3; + break; + case GSM48_BCAP_SV_AMR_OFW: + return GSM0808_PERM_FR4; + break; + case GSM48_BCAP_SV_AMR_OHW: + return GSM0808_PERM_HR4; + break; + case GSM48_BCAP_SV_AMR_FW: + return GSM0808_PERM_FR5; + break; + case GSM48_BCAP_SV_AMR_OH: + return GSM0808_PERM_HR6; + break; + } + + /* If nothing matches, tag the result as invalid */ + LOGP(DMSC, LOGL_ERROR, "Invalid permitted speech version / rate detected, discarding.\n"); + return 0xFF; +} + +/* Convert speech preference field */ +static uint8_t convert_Abis_prev_to_A_pref(int radio) +{ + /* The Radio channel requirement field that is transmitted in the + * Bearer capability information element, that is transmitted on the + * Abis interfece uses a different encoding than the Channel rate and + * type field that is signalled in the channel type element on the A + * interface. (See also 3GPP TS 48.008, 3.2.2.1 and 3GPP TS 24.008, + * 10.5.102 */ + + switch (radio) { + case GSM48_BCAP_RRQ_FR_ONLY: + return GSM0808_SPEECH_FULL_BM; + case GSM48_BCAP_RRQ_DUAL_FR: + return GSM0808_SPEECH_FULL_PREF; + case GSM48_BCAP_RRQ_DUAL_HR: + return GSM0808_SPEECH_HALF_PREF; + } + + LOGP(DMSC, LOGL_ERROR, "Invalid speech version / rate combination preference, defaulting to full rate.\n"); + return GSM0808_SPEECH_FULL_BM; +} + +/* Assemble the channel type field */ +static void make_channel_type(struct gsm_mncc_bearer_cap *bc, struct gsm0808_channel_type *ct) +{ + unsigned int i; + uint8_t sv; + unsigned int count = 0; + bool only_gsm_hr = true; + + ct->ch_indctr = GSM0808_CHAN_SPEECH; + + for (i = 0; i < ARRAY_SIZE(bc->speech_ver); i++) { + if (bc->speech_ver[i] == -1) + break; + sv = convert_Abis_sv_to_A_sv(bc->speech_ver[i]); + + if (sv != 0xFF) { + /* Detect if something else than + * GSM HR V1 is supported */ + if (sv == GSM0808_PERM_HR2 || + sv == GSM0808_PERM_HR3 || sv == GSM0808_PERM_HR4 || sv == GSM0808_PERM_HR6) + only_gsm_hr = false; + + ct->perm_spch[count] = sv; + count++; + } + } + ct->perm_spch_len = count; + + if (only_gsm_hr) + /* Default to full rate, in case only GSM HR V1 is available */ + ct->ch_rate_type = GSM0808_SPEECH_FULL_BM; + else + ct->ch_rate_type = convert_Abis_prev_to_A_pref(bc->radio); +} + /* Send assignment request via A-interface */ int a_assign(struct gsm_trans *trans) { @@ -139,12 +243,8 @@ int a_assign(struct gsm_trans *trans) conn = trans->conn; OSMO_ASSERT(conn); - /* FIXME: This is still work in progress */ - /* Some fake parameters for testing */ - ct.ch_indctr = GSM0808_CHAN_SPEECH; - ct.ch_rate_type = GSM0808_SPEECH_FULL_BM; - ct.perm_spch[0] = GSM0808_PERM_FR1; - ct.perm_spch_len = 1; + /* Channel type */ + make_channel_type(&trans->bearer_cap, &ct); /* Package RTP-Address data */ memset(&rtp_addr_in, 0, sizeof(rtp_addr_in)); |