From a8bf666a099ecc7bb8436f31b7f30e246ef50015 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 28 May 2017 16:00:36 +0200 Subject: sysmobts: Re-order the bit-endianness of every HR codec parameter The so-called "RTP mode" of the DSP contains a bug on all firmware versions < 5.3.3 which causes the bit-order within each of the non-aligned codec parameters to be wrong. Introduce a function originally written by Sylvain Munaut during 32C3 in http://git.osmocom.org/openbsc/commit/?h=sylvain/32c3_codec&id=5b4a16bbe93a7b1ace65cc23d6cce56ecf4f1275 to bring the bits into [the correct] order. This has never been seen in a "pure sysmoBTS" setup, as all BTSs would use the same (wrong) bit-ordering and thus interoperate. This patch now checks for an affected DSP firmware version and then jumbles (old DSP firmware version) or does nothing (new DSP firmware version). Change-Id: Ia0eee4f514fb8fd81c052bb44a4facba898d6afb Closes: SYS#2452 --- src/osmo-bts-sysmo/l1_if.c | 3 +++ src/osmo-bts-sysmo/l1_if.h | 1 + src/osmo-bts-sysmo/tch.c | 59 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c index 8820f083..60638e18 100644 --- a/src/osmo-bts-sysmo/l1_if.c +++ b/src/osmo-bts-sysmo/l1_if.c @@ -1460,6 +1460,9 @@ static int info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, LOGP(DL1C, LOGL_FATAL, "BTS band %s not supported by hw\n", gsm_band_name(trx->bts->band)); + if (l1if_dsp_ver(fl1h) < L1_VER_SHIFT(5,3,3)) + fl1h->rtp_hr_jumble_needed = true; + /* Request the activation */ l1if_activate_rf(fl1h, 1); diff --git a/src/osmo-bts-sysmo/l1_if.h b/src/osmo-bts-sysmo/l1_if.h index 961e5853..033e7f58 100644 --- a/src/osmo-bts-sysmo/l1_if.h +++ b/src/osmo-bts-sysmo/l1_if.h @@ -74,6 +74,7 @@ struct femtol1_hdl { } hw_info; int fixup_needed; + bool rtp_hr_jumble_needed; struct calib_send_state st; diff --git a/src/osmo-bts-sysmo/tch.c b/src/osmo-bts-sysmo/tch.c index 55c4049c..475652ee 100644 --- a/src/osmo-bts-sysmo/tch.c +++ b/src/osmo-bts-sysmo/tch.c @@ -157,6 +157,43 @@ static int rtppayload_to_l1_efr(uint8_t *l1_payload, const uint8_t *rtp_payload, #warning No EFR support in L1 #endif /* L1_HAS_EFR */ +#ifdef USE_L1_RTP_MODE +/* change the bit-order of each unaligned field inside the HR codec + * payload from little-endian bit-ordering to bit-endian and vice-versa. + * This is required on all sysmoBTS DSP versions < 5.3.3 in order to + * be compliant with ETSI TS 101 318 Chapter 5.2 */ +static void hr_jumble(uint8_t *dst, const uint8_t *src) +{ + /* Table 2 / Section 5.2.1 of ETSI TS 101 381 */ + const int p_unvoiced[] = + { 5, 11, 9, 8, 1, 2, 7, 7, 5, 7, 7, 5, 7, 7, 5, 7, 7, 5 }; + /* Table 3 / Section 5.2.1 of ETSI TS 101 381 */ + const int p_voiced[] = + { 5, 11, 9, 8, 1, 2, 8, 9, 5, 4, 9, 5, 4, 9, 5, 4, 9, 5 }; + + int base, i, j, l, si, di; + const int *p; + + memset(dst, 0x00, GSM_HR_BYTES); + + p = (src[4] & 0x30) ? p_voiced : p_unvoiced; + + base = 0; + for (i = 0; i < 18; i++) { + l = p[i]; + for (j = 0; j < l; j++) { + si = base + j; + di = base + l - j - 1; + + if (src[si >> 3] & (1 << (7 - (si & 7)))) + dst[di >> 3] |= (1 << (7 - (di & 7))); + } + + base += l; + } +} +#endif /* USE_L1_RTP_MODE */ + static struct msgb *l1_to_rtppayload_hr(uint8_t *l1_payload, uint8_t payload_len, struct gsm_lchan *lchan) { @@ -174,9 +211,14 @@ static struct msgb *l1_to_rtppayload_hr(uint8_t *l1_payload, uint8_t payload_len } cur = msgb_put(msg, GSM_HR_BYTES); +#ifdef USE_L1_RTP_MODE + struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx); + if (fl1h->rtp_hr_jumble_needed) + hr_jumble(cur, l1_payload); + else + memcpy(cur, l1_payload, GSM_HR_BYTES); +#else /* USE_L1_RTP_MODE */ memcpy(cur, l1_payload, GSM_HR_BYTES); - -#ifndef USE_L1_RTP_MODE /* reverse the bit-order of each payload byte */ osmo_revbytebits_buf(cur, GSM_HR_BYTES); #endif /* USE_L1_RTP_MODE */ @@ -193,7 +235,7 @@ static struct msgb *l1_to_rtppayload_hr(uint8_t *l1_payload, uint8_t payload_len * \returns number of \a l1_payload bytes filled */ static int rtppayload_to_l1_hr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) + unsigned int payload_len, struct gsm_lchan *lchan) { if (payload_len != GSM_HR_BYTES) { @@ -202,9 +244,14 @@ static int rtppayload_to_l1_hr(uint8_t *l1_payload, const uint8_t *rtp_payload, return 0; } +#ifdef USE_L1_RTP_MODE + struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx); + if (fl1h->rtp_hr_jumble_needed) + hr_jumble(l1_payload, rtp_payload); + else + memcpy(l1_payload, rtp_payload, GSM_HR_BYTES); +#else /* USE_L1_RTP_MODE */ memcpy(l1_payload, rtp_payload, GSM_HR_BYTES); - -#ifndef USE_L1_RTP_MODE /* reverse the bit-order of each payload byte */ osmo_revbytebits_buf(l1_payload, GSM_HR_BYTES); #endif /* USE_L1_RTP_MODE */ @@ -345,7 +392,7 @@ int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, } else{ *payload_type = GsmL1_TchPlType_Hr; rc = rtppayload_to_l1_hr(l1_payload, - rtp_pl, rtp_pl_len); + rtp_pl, rtp_pl_len, lchan); if (rc && lchan->ts->trx->bts->dtxd) is_sid = osmo_hr_check_sid(rtp_pl, rtp_pl_len); } -- cgit v1.2.3