Commit b32834b0 authored by Minh-Quang Nguyen's avatar Minh-Quang Nguyen

LC15: Fix missing fill frame and GSM 05.08 mandatory frame

Change-Id: I40e9bf9438c0b400e4d29eb39ffae37207e34db6
parent dd93cb43
......@@ -32,6 +32,17 @@ enum {
OML_MSG_TYPE_OSMO,
};
static const uint8_t gsm_speech_zero[GSM_FR_BYTES] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00
};
static const uint8_t amr_sid_first_zero[9] = {
0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
};
void lchan_set_marker(bool t, struct gsm_lchan *lchan);
bool dtx_dl_amr_enabled(const struct gsm_lchan *lchan);
void dtx_dispatch(struct gsm_lchan *lchan, enum dtx_dl_amr_fsm_events e);
......
......@@ -379,7 +379,7 @@ static inline bool dtx_sched_optional(struct gsm_lchan *lchan, uint32_t fn)
static const uint8_t f[] = { 52, 53, 54, 55, 56, 57, 58, 59 },
h0[] = { 0, 2, 4, 6, 52, 54, 56, 58 },
h1[] = { 14, 16, 18, 20, 66, 68, 70, 72 };
if (lchan->tch_mode == GSM48_CMODE_SPEECH_V1) {
if ((lchan->tch_mode == GSM48_CMODE_SPEECH_V1) || (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)){
if (lchan->type == GSM_LCHAN_TCH_F)
return fn_chk(f, fn, ARRAY_SIZE(f));
else
......@@ -465,6 +465,7 @@ void dtx_int_signal(struct gsm_lchan *lchan)
*/
uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn)
{
uint8_t pl_len;
/* FIXME: add EFR support */
if (lchan->tch_mode == GSM48_CMODE_SPEECH_EFR)
return 0;
......@@ -472,11 +473,54 @@ uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn)
if (lchan->tch_mode != GSM48_CMODE_SPEECH_AMR) {
if (dtx_sched_optional(lchan, fn))
return 0;
} else
else {
if (lchan->ts->trx->bts->dtxd) {
/* Need to send zeroed TCH frame on mandatory Fn defined in GSM 05.08, section 8.3 */
switch (lchan->type) {
case GSM_LCHAN_TCH_F:
pl_len = GSM_FR_BYTES;
break;
case GSM_LCHAN_TCH_H:
pl_len = GSM_HR_BYTES;
break;
default:
return 0;
}
memcpy(dst, gsm_speech_zero, pl_len);
LOGP(DL1C, LOGL_DEBUG, "%s Have to send %s %s zero speech frame, Fn=%d, Fn mod 104=%d, dump=%s\n",
gsm_lchan_name(lchan),
get_value_string(gsm_chan_t_names, lchan->type),
get_value_string(gsm48_chan_mode_names, lchan->tch_mode),
fn,
fn%104,
osmo_hexdump(dst, pl_len));
return pl_len + 1;
}
}
} else {
if (!dtx_sched_optional(lchan, fn) && (lchan->rsl_cmode == RSL_CMOD_SPD_SPEECH)) {
if (!(lchan->tch.dtx.len)) {
pl_len = 9;
/* Send zero SID FIRST frame */
memcpy(dst, amr_sid_first_zero, pl_len);
LOGP(DL1C, LOGL_DEBUG, "%s Have to send %s %s zero speech frame, Fn=%d, Fn mod 104=%d, dump=%s\n",
gsm_lchan_name(lchan),
get_value_string(gsm_chan_t_names, lchan->type),
get_value_string(gsm48_chan_mode_names, lchan->tch_mode),
fn,
fn%104,
osmo_hexdump(dst, pl_len));
return pl_len + 1; /* plus one to take into account of payload type */
}
}
if (dtx_amr_sid_optional(lchan, fn))
return 0;
}
if (lchan->tch.dtx.len) {
if (dtx_dl_amr_enabled(lchan)) {
if ((lchan->type == GSM_LCHAN_TCH_H &&
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F2) ||
......@@ -502,11 +546,17 @@ uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn)
}
memcpy(dst, lchan->tch.dtx.cache, lchan->tch.dtx.len);
lchan->tch.dtx.fn = fn;
LOGP(DL1C, LOGL_DEBUG, "%s Have to send %s SID buffer "
"%s\n",
gsm_lchan_name(lchan),
get_value_string(gsm48_chan_mode_names, lchan->tch_mode),
osmo_hexdump(lchan->tch.dtx.cache, lchan->tch.dtx.len));
return lchan->tch.dtx.len + 1;
}
LOGP(DL1C, LOGL_DEBUG, "Have to send %s frame on TCH but SID buffer "
LOGP(DL1C, LOGL_DEBUG, "%s Have to send %s frame on TCH but SID buffer "
"is empty - sent nothing\n",
gsm_lchan_name(lchan),
get_value_string(gsm48_chan_mode_names, lchan->tch_mode));
return 0;
......
......@@ -332,6 +332,49 @@ empty_req_from_l1sap(GsmL1_Prim_t *l1p, struct lc15l1_hdl *fl1,
return empty_req;
}
/* fill frame PH-DATA.req from l1sap primitive */
static GsmL1_PhDataReq_t *
fill_req_from_l1sap(GsmL1_Prim_t *l1p, struct lc15l1_hdl *fl1,
uint8_t tn, uint32_t fn, uint8_t sapi, uint8_t sub_ch,
uint8_t block_nr)
{
GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq;
GsmL1_MsgUnitParam_t *msu_param;
uint8_t *l1_payload;
msu_param = &data_req->msgUnitParam;
l1_payload = &msu_param->u8Buffer[0];
l1p->id = GsmL1_PrimId_PhDataReq;
memset(l1_payload, 0x2B, GSM_MACBLOCK_LEN);
/* address field */
l1_payload[0] = 0x03;
/* control field */
l1_payload[1] = 0x03;
/* length field */
l1_payload[2] = 0x01;
/* copy fields from PH-RTS.ind */
data_req->hLayer1 = (HANDLE)fl1->hLayer1;
data_req->u8Tn = tn;
data_req->u32Fn = fn;
data_req->sapi = sapi;
data_req->subCh = sub_ch;
data_req->u8BlockNbr = block_nr;
data_req->msgUnitParam.u8Size = GSM_MACBLOCK_LEN;
LOGP(DL1C, LOGL_DEBUG, "Send fill frame on in none DTX mode Tn=%d, Fn=%d, SAPI=%d, SubCh=%d, BlockNr=%d dump=%s\n",
tn,
fn,
sapi,
sub_ch,
block_nr,
osmo_hexdump(data_req->msgUnitParam.u8Buffer, data_req->msgUnitParam.u8Size));
return data_req;
}
static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
struct osmo_phsap_prim *l1sap, bool use_cache)
{
......@@ -462,10 +505,19 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer,
l1p->u.phDataReq.msgUnitParam.u8Size));
} else {
/* empty frame */
GsmL1_Prim_t *l1p = msgb_l1prim(l1msg);
empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr);
GsmL1_Prim_t *l1p = msgb_l1prim(l1msg);
if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN)
/* fill frame */
fill_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr);
else {
if (lchan->ts->trx->bts->dtxd)
/* empty frame */
empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr);
else
/* fill frame */
fill_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr);
}
}
/* send message to DSP's queue */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment