diff options
Diffstat (limited to 'src/osmo-bts-litecell15')
-rw-r--r-- | src/osmo-bts-litecell15/l1_if.c | 14 | ||||
-rw-r--r-- | src/osmo-bts-litecell15/l1_if.h | 4 | ||||
-rw-r--r-- | src/osmo-bts-litecell15/tch.c | 122 |
3 files changed, 102 insertions, 38 deletions
diff --git a/src/osmo-bts-litecell15/l1_if.c b/src/osmo-bts-litecell15/l1_if.c index 1c989518..f47634ed 100644 --- a/src/osmo-bts-litecell15/l1_if.c +++ b/src/osmo-bts-litecell15/l1_if.c @@ -426,7 +426,7 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, } static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap) + struct osmo_phsap_prim *l1sap, bool use_cache, bool marker) { struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx); struct gsm_lchan *lchan; @@ -462,7 +462,7 @@ static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg, rc = l1if_tch_encode(lchan, l1p->u.phDataReq.msgUnitParam.u8Buffer, &l1p->u.phDataReq.msgUnitParam.u8Size, - msg->data, msg->len, u32Fn, + msg->data, msg->len, u32Fn, use_cache, l1sap->u.tch.marker); if (rc < 0) { /* no data encoded for L1: smth will be generated below */ @@ -494,16 +494,14 @@ static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg, } else { /* empty frame */ if (trx->bts->dtxd && trx != trx->bts->c0) - lchan->tch.dtxd_active = true; + lchan->tch.dtx.dl_active = true; empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr); } /* send message to DSP's queue */ osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], nmsg); - if (l1sap->u.tch.marker) { /* DTX: send voice after ONSET was sent */ - l1sap->u.tch.marker = 0; - return ph_tch_req(trx, l1sap->oph.msg, l1sap); - } + if (rc > 0 && trx->bts->dtxd) /* DTX: send voice after ONSET was sent */ + return ph_tch_req(trx, l1sap->oph.msg, l1sap, true, false); return 0; } @@ -571,7 +569,7 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) rc = ph_data_req(trx, msg, l1sap); break; case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST): - rc = ph_tch_req(trx, msg, l1sap); + rc = ph_tch_req(trx, msg, l1sap, false, l1sap->u.tch.marker); break; case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST): rc = mph_info_req(trx, msg, l1sap); diff --git a/src/osmo-bts-litecell15/l1_if.h b/src/osmo-bts-litecell15/l1_if.h index adb197d1..7feee560 100644 --- a/src/osmo-bts-litecell15/l1_if.h +++ b/src/osmo-bts-litecell15/l1_if.h @@ -90,8 +90,8 @@ struct gsm_lchan *l1if_hLayer_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer) /* tch.c */ int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, - const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, - bool marker); + const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, + bool use_cache, bool marker); int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg); int l1if_tch_fill(struct gsm_lchan *lchan, uint8_t *l1_buffer); struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn); diff --git a/src/osmo-bts-litecell15/tch.c b/src/osmo-bts-litecell15/tch.c index e246ffb1..b2513887 100644 --- a/src/osmo-bts-litecell15/tch.c +++ b/src/osmo-bts-litecell15/tch.c @@ -45,6 +45,7 @@ #include <osmo-bts/measurement.h> #include <osmo-bts/amr.h> #include <osmo-bts/l1sap.h> +#include <osmo-bts/dtx_dl_amr_fsm.h> #include <nrw/litecell15/litecell15.h> #include <nrw/litecell15/gsml1prim.h> @@ -198,8 +199,7 @@ static struct msgb *l1_to_rtppayload_amr(uint8_t *l1_payload, uint8_t payload_le * \returns number of \a l1_payload bytes filled */ static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t *rtp_payload, - uint8_t payload_len, - struct gsm_lchan *lchan, uint8_t ft) + uint8_t payload_len, uint8_t ft) { memcpy(l1_payload, rtp_payload, payload_len); return payload_len; @@ -210,10 +210,11 @@ static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t *rtp_payload, /*! \brief function for incoming RTP via TCH.req * \param[in] rtp_pl buffer containing RTP payload * \param[in] rtp_pl_len length of \a rtp_pl + * \param[in] use_cache Use cached payload instead of parsing RTP * \param[in] marker RTP header Marker bit (indicates speech onset) * \returns 0 if encoding result can be sent further to L1 without extra actions * positive value if data is ready AND extra actions are required - * negative value otherwise + * negative value otherwise (no data for L1 encoded) * * This function prepares a msgb with a L1 PH-DATA.req primitive and * queues it into lchan->dl_tch_queue. @@ -223,7 +224,8 @@ static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t *rtp_payload, * pre-fill the primtive. */ int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, - const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, bool marker) + const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, + bool use_cache, bool marker) { uint8_t *payload_type; uint8_t *l1_payload, ft; @@ -242,17 +244,17 @@ int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, *payload_type = GsmL1_TchPlType_Fr; rc = rtppayload_to_l1_fr(l1_payload, rtp_pl, rtp_pl_len); - if (rc) + if (rc && lchan->ts->trx->bts->dtxd) is_sid = osmo_fr_check_sid(rtp_pl, rtp_pl_len); } else{ *payload_type = GsmL1_TchPlType_Hr; rc = rtppayload_to_l1_hr(l1_payload, rtp_pl, rtp_pl_len); - if (rc) + if (rc && lchan->ts->trx->bts->dtxd) is_sid = osmo_hr_check_sid(rtp_pl, rtp_pl_len); } if (is_sid) - save_last_sid(lchan, rtp_pl, rtp_pl_len, fn, -1, 0, 0); + dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, -1); break; case GSM48_CMODE_SPEECH_EFR: *payload_type = GsmL1_TchPlType_Efr; @@ -261,25 +263,75 @@ int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, /* FIXME: detect and save EFR SID */ break; case GSM48_CMODE_SPEECH_AMR: - rc = dtx_amr_check_onset(lchan, rtp_pl, rtp_pl_len, fn, - l1_payload, &ft); + if (use_cache) { + *payload_type = GsmL1_TchPlType_Amr; + rtppayload_to_l1_amr(l1_payload, lchan->tch.dtx.cache, + lchan->tch.dtx.len, ft); + *len = lchan->tch.dtx.len + 1; + return 0; + } + + rc = dtx_dl_amr_fsm_step(lchan, rtp_pl, rtp_pl_len, fn, + l1_payload, marker, len, &ft); + if (rc < 0) + return rc; + if (!lchan->ts->trx->bts->dtxd) { + *payload_type = GsmL1_TchPlType_Amr; + rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, + ft); + return 0; + } - if (marker || rc > 0) { + /* DTX DL-specific logic below: */ + switch (lchan->tch.dtx.dl_amr_fsm->state) { + case ST_ONSET_V: + case ST_ONSET_F: *payload_type = GsmL1_TchPlType_Amr_Onset; + dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); *len = 1; - if (rc != 0) { - LOGP(DRTP, LOGL_NOTICE, "%s SPEECH frame without" - " Marker: ONSET forced\n", - get_value_string(osmo_amr_type_names, ft)); - return rc; + return 1; + case ST_VOICE: + *payload_type = GsmL1_TchPlType_Amr; + rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, + ft); + return 0; + case ST_SID_F1: + if (lchan->type == GSM_LCHAN_TCH_H) { /* AMR HR */ + *payload_type = GsmL1_TchPlType_Amr_SidFirstP1; + rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, + rtp_pl_len, ft); + return 0; } - LOGP(DRTP, LOGL_DEBUG, "%s SPEECH frame with Marker\n", - get_value_string(osmo_amr_type_names, ft)); - } - else { + /* AMR FR */ *payload_type = GsmL1_TchPlType_Amr; - rc = 2 + rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, - rtp_pl_len, lchan, ft); + rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, + ft); + return 0; + case ST_SID_F2: + *payload_type = GsmL1_TchPlType_Amr; + rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, + ft); + return 0; + case ST_F1_INH: + *payload_type = GsmL1_TchPlType_Amr_SidFirstInH; + *len = 3; + dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); + return 1; + case ST_U_INH: + *payload_type = GsmL1_TchPlType_Amr_SidUpdateInH; + *len = 3; + dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); + return 1; + case ST_SID_U: + return -EAGAIN; + case ST_FACCH_V: + case ST_FACCH: + /* FIXME: if this possible at all? */ + return 0; + default: + LOGP(DRTP, LOGL_ERROR, "Unhandled DTX DL AMR FSM state " + "%d\n", lchan->tch.dtx.dl_amr_fsm->state); + return -EINVAL; } break; default: @@ -442,7 +494,20 @@ struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn) switch (lchan->tch_mode) { case GSM48_CMODE_SPEECH_AMR: - *payload_type = GsmL1_TchPlType_Amr; + if (lchan->type == GSM_LCHAN_TCH_H && + lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F1 && + lchan->ts->trx->bts->dtxd) { + *payload_type = GsmL1_TchPlType_Amr_SidFirstP2; + rc = dtx_dl_amr_fsm_step(lchan, NULL, 0, fn, l1_payload, + false, &(msu_param->u8Size), + NULL); + if (rc < 0) { + msgb_free(msg); + return NULL; + } + return msg; + } else + *payload_type = GsmL1_TchPlType_Amr; break; case GSM48_CMODE_SPEECH_V1: if (lchan->type == GSM_LCHAN_TCH_F) @@ -458,12 +523,13 @@ struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn) return NULL; } - rc = repeat_last_sid(lchan, l1_payload, fn); - if (!rc) { - msgb_free(msg); - return NULL; + if (lchan->ts->trx->bts->dtxd) { + rc = repeat_last_sid(lchan, l1_payload, fn); + if (!rc) { + msgb_free(msg); + return NULL; + } + msu_param->u8Size = rc; } - msu_param->u8Size = rc; - return msg; } |