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.

Change-Id: I642480fa408dee7a4f40f7aab95f40383b3e91af
This commit is contained in:
Philipp Maier
2017-05-31 17:17:59 +02:00
committed by Neels Hofmeyr
parent 2878423b95
commit ae819a1be4
3 changed files with 139 additions and 6 deletions

View File

@@ -46,6 +46,9 @@ struct gsm_trans {
/* is thats one paging? */
struct subscr_request *paging_request;
/* bearer capabilities (rate and codec) */
struct gsm_mncc_bearer_cap bearer_cap;
union {
struct {

View File

@@ -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));

View File

@@ -1538,6 +1538,12 @@ 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);
/* Create a copy of the bearer capability
* in the transaction struct, so we can use
* this information later */
memcpy(&trans->bearer_cap,&setup.bearer_cap,
sizeof(trans->bearer_cap));
}
/* facility */
if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
@@ -1691,6 +1697,12 @@ 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);
/* Create a copy of the bearer capability
* in the transaction struct, so we can use
* this information later */
memcpy(&trans->bearer_cap,&call_conf.bearer_cap,
sizeof(trans->bearer_cap));
}
/* cause */
if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
@@ -2387,6 +2399,12 @@ 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);
/* Create a copy of the bearer capability
* in the transaction struct, so we can use
* this information later */
memcpy(&trans->bearer_cap,&modify.bearer_cap,
sizeof(trans->bearer_cap));
}
new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
@@ -2429,6 +2447,12 @@ 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);
/* Create a copy of the bearer capability
* in the transaction struct, so we can use
* this information later */
memcpy(&trans->bearer_cap,&modify.bearer_cap,
sizeof(trans->bearer_cap));
}
new_cc_state(trans, GSM_CSTATE_ACTIVE);
@@ -2469,6 +2493,12 @@ 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);
/* Create a copy of the bearer capability
* in the transaction struct, so we can use
* this information later */
memcpy(&trans->bearer_cap,&modify.bearer_cap,
sizeof(trans->bearer_cap));
}
/* cause */
if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {