diff options
author | Max <msuraev@sysmocom.de> | 2016-10-26 17:28:42 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2016-10-28 13:42:29 +0000 |
commit | bce25a60f4bbd798b98727e66b25bf343031f7bc (patch) | |
tree | 5e71659c7f73d6db41f4897098fd6860c0957422 /src/osmo-bts-litecell15/l1_if.c | |
parent | efb4a4baeb8ecd13ff41f25d61fd91a1162e6fa9 (diff) |
DTX DL: split ONSET state handling
Handle ONSET cause by Voice and FACCH separately. In case of Voice we
have RTP payload which we have to cache and send later on in next
response to L1 RTS. FACCH have higher priority so it preempts both voice
and silence alike - hence we can send ONSET immediately but still have
to track previous state in order to get back to it gracefully.
This affects lc15 and sysmo hw as there's no FSM-based DTX
implementation for other models yet.
Note: this requires patch for OpenBSC which adds FACCH buffer to tch.dtx
struct.
Change-Id: Idba14dcd0cb12cd7aee86391fcc152c49fcd7052
Related: OS#1802
Diffstat (limited to 'src/osmo-bts-litecell15/l1_if.c')
-rw-r--r-- | src/osmo-bts-litecell15/l1_if.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/src/osmo-bts-litecell15/l1_if.c b/src/osmo-bts-litecell15/l1_if.c index edc5f5b7..795172bb 100644 --- a/src/osmo-bts-litecell15/l1_if.c +++ b/src/osmo-bts-litecell15/l1_if.c @@ -53,6 +53,7 @@ #include <osmo-bts/cbch.h> #include <osmo-bts/bts_model.h> #include <osmo-bts/l1sap.h> +#include <osmo-bts/dtx_dl_amr_fsm.h> #include <nrw/litecell15/litecell15.h> #include <nrw/litecell15/gsml1prim.h> @@ -330,13 +331,15 @@ empty_req_from_l1sap(GsmL1_Prim_t *l1p, struct lc15l1_hdl *fl1, } static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap) + struct osmo_phsap_prim *l1sap, bool use_cache) { struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx); struct msgb *l1msg = l1p_msgb_alloc(); + struct gsm_lchan *lchan; uint32_t u32Fn; uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi = 0; uint8_t chan_nr, link_id; + bool rec = false; int len; if (!msg) { @@ -401,14 +404,46 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, if (len) { /* data request */ GsmL1_Prim_t *l1p = msgb_l1prim(l1msg); + lchan = get_lchan_by_chan_nr(trx, chan_nr); + + if (use_cache) + memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, + lchan->tch.dtx.facch, msgb_l2len(msg)); + else if (trx->bts->dtxd && lchan->tch.dtx.dl_amr_fsm && + lchan->tch.dtx.dl_amr_fsm->state == ST_FACCH) { + if (sapi == GsmL1_Sapi_FacchF) { + sapi = GsmL1_Sapi_TchF; + } + if (sapi == GsmL1_Sapi_FacchH) { + sapi = GsmL1_Sapi_TchH; + } + if (sapi == GsmL1_Sapi_TchH || sapi == GsmL1_Sapi_TchF) { + /* FACCH interruption of DTX silence */ + /* cache FACCH data */ + memcpy(lchan->tch.dtx.facch, msg->l2h, + msgb_l2len(msg)); + /* prepare ONSET message */ + len = 3; + l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = + GsmL1_TchPlType_Amr_Onset; + /* ignored CMR/CMI pair */ + l1p->u.phDataReq.msgUnitParam.u8Buffer[1] = 0; + l1p->u.phDataReq.msgUnitParam.u8Buffer[2] = 0; + /* ONSET is ready, recursive call is necessary */ + rec = true; + } + } data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr, len); - OSMO_ASSERT(msgb_l2len(msg) <= sizeof(l1p->u.phDataReq.msgUnitParam.u8Buffer)); - memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, msg->l2h, msgb_l2len(msg)); + if (!rec && !use_cache) { + OSMO_ASSERT(msgb_l2len(msg) <= sizeof(l1p->u.phDataReq.msgUnitParam.u8Buffer)); + memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, msg->l2h, + msgb_l2len(msg)); + } LOGP(DL1P, LOGL_DEBUG, "PH-DATA.req(%s)\n", - osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer, - l1p->u.phDataReq.msgUnitParam.u8Size)); + osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer, + l1p->u.phDataReq.msgUnitParam.u8Size)); } else { /* empty frame */ GsmL1_Prim_t *l1p = msgb_l1prim(l1msg); @@ -422,6 +457,8 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, msgb_free(l1msg); } + if (rec) + ph_data_req(trx, msg, l1sap, true); return 0; } @@ -566,7 +603,7 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) * free()d below */ switch (OSMO_PRIM_HDR(&l1sap->oph)) { case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): - rc = ph_data_req(trx, msg, l1sap); + rc = ph_data_req(trx, msg, l1sap, false); break; case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST): rc = ph_tch_req(trx, msg, l1sap, false, l1sap->u.tch.marker); |