diff --git a/include/osmo-bts/dtx_dl_amr_fsm.h b/include/osmo-bts/dtx_dl_amr_fsm.h index f747f9f15..c66ac7d68 100644 --- a/include/osmo-bts/dtx_dl_amr_fsm.h +++ b/include/osmo-bts/dtx_dl_amr_fsm.h @@ -12,11 +12,15 @@ enum dtx_dl_amr_fsm_states { ST_VOICE, ST_SID_F1, ST_SID_F2, - ST_F1_INH, - ST_U_INH, + ST_F1_INH_V, + ST_F1_INH_F, + ST_U_INH_V, + ST_U_INH_F, ST_U_NOINH, - ST_F1_INH_REC, - ST_U_INH_REC, + ST_F1_INH_V_REC, + ST_F1_INH_F_REC, + ST_U_INH_V_REC, + ST_U_INH_F_REC, ST_SID_U, ST_ONSET_V, ST_ONSET_F, diff --git a/include/osmo-bts/rsl.h b/include/osmo-bts/rsl.h index a2a6e3d9d..d5d0f1a3f 100644 --- a/include/osmo-bts/rsl.h +++ b/include/osmo-bts/rsl.h @@ -13,6 +13,7 @@ enum { }; #define LCHAN_FN_DUMMY 0xFFFFFFFF +#define LCHAN_FN_WAIT 0xFFFFFFFE int msgb_queue_flush(struct llist_head *list); diff --git a/src/common/dtx_dl_amr_fsm.c b/src/common/dtx_dl_amr_fsm.c index 832e8b4e2..d5990489f 100644 --- a/src/common/dtx_dl_amr_fsm.c +++ b/src/common/dtx_dl_amr_fsm.c @@ -29,9 +29,14 @@ void dtx_fsm_voice(struct osmo_fsm_inst *fi, uint32_t event, void *data) case E_FACCH: break; case E_SID_F: - case E_SID_U: osmo_fsm_inst_state_chg(fi, ST_SID_F1, 0, 0); break; + case E_SID_U: + osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0); + break; + case E_INHIB: + osmo_fsm_inst_state_chg(fi, ST_F1_INH_V, 0, 0); + break; default: LOGP(DL1P, LOGL_ERROR, "Inexpected event %d\n", event); OSMO_ASSERT(0); @@ -49,18 +54,12 @@ void dtx_fsm_sid_f1(struct osmo_fsm_inst *fi, uint32_t event, void *data) case E_SID_U: osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0); break; - case E_VOICE: - osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0); - break; case E_FACCH: - osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0); + osmo_fsm_inst_state_chg(fi, ST_F1_INH_F, 0, 0); break; case E_FIRST: osmo_fsm_inst_state_chg(fi, ST_SID_F2, 0, 0); break; - case E_INHIB: - osmo_fsm_inst_state_chg(fi, ST_F1_INH, 0, 0); - break; case E_ONSET: osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0); break; @@ -75,10 +74,7 @@ void dtx_fsm_sid_f2(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { case E_COMPL: - osmo_fsm_inst_state_chg(fi, ST_SID_U, 0, 0); - break; - case E_VOICE: - osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0); + osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0); break; case E_FACCH: osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0); @@ -93,11 +89,11 @@ void dtx_fsm_sid_f2(struct osmo_fsm_inst *fi, uint32_t event, void *data) } } -void dtx_fsm_f1_inh(struct osmo_fsm_inst *fi, uint32_t event, void *data) +void dtx_fsm_f1_inh_v(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { case E_COMPL: - osmo_fsm_inst_state_chg(fi, ST_F1_INH_REC, 0, 0); + osmo_fsm_inst_state_chg(fi, ST_F1_INH_V_REC, 0, 0); break; default: LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event); @@ -106,11 +102,11 @@ void dtx_fsm_f1_inh(struct osmo_fsm_inst *fi, uint32_t event, void *data) } } -void dtx_fsm_u_inh(struct osmo_fsm_inst *fi, uint32_t event, void *data) +void dtx_fsm_f1_inh_f(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { case E_COMPL: - osmo_fsm_inst_state_chg(fi, ST_U_INH_REC, 0, 0); + osmo_fsm_inst_state_chg(fi, ST_F1_INH_F_REC, 0, 0); break; default: LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event); @@ -119,9 +115,36 @@ void dtx_fsm_u_inh(struct osmo_fsm_inst *fi, uint32_t event, void *data) } } -void dtx_fsm_f1_inh_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data) +void dtx_fsm_u_inh_v(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { + case E_COMPL: + osmo_fsm_inst_state_chg(fi, ST_U_INH_V_REC, 0, 0); + break; + default: + LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event); + OSMO_ASSERT(0); + break; + } +} + +void dtx_fsm_u_inh_f(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case E_COMPL: + osmo_fsm_inst_state_chg(fi, ST_U_INH_F_REC, 0, 0); + break; + default: + LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event); + OSMO_ASSERT(0); + break; + } +} + +void dtx_fsm_f1_inh_v_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case E_VOICE: case E_COMPL: osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0); break; @@ -132,9 +155,24 @@ void dtx_fsm_f1_inh_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data) } } -void dtx_fsm_u_inh_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data) +void dtx_fsm_f1_inh_f_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { + case E_FACCH: + case E_COMPL: + osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0); + break; + default: + LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event); + OSMO_ASSERT(0); + break; + } +} + +void dtx_fsm_u_inh_v_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case E_VOICE: case E_COMPL: osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0); break; @@ -145,6 +183,20 @@ void dtx_fsm_u_inh_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data) } } +void dtx_fsm_u_inh_f_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case E_FACCH: + case E_COMPL: + osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0); + break; + default: + LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event); + OSMO_ASSERT(0); + break; + } +} + void dtx_fsm_u_noinh(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { @@ -176,13 +228,13 @@ void dtx_fsm_sid_upd(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { case E_FACCH: - osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0); + osmo_fsm_inst_state_chg(fi, ST_U_INH_F, 0, 0); break; case E_VOICE: osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0); break; case E_INHIB: - osmo_fsm_inst_state_chg(fi, ST_U_INH, 0, 0); + osmo_fsm_inst_state_chg(fi, ST_U_INH_V, 0, 0); break; case E_SID_U: case E_SID_F: @@ -270,40 +322,54 @@ void dtx_fsm_facch(struct osmo_fsm_inst *fi, uint32_t event, void *data) static struct osmo_fsm_state dtx_dl_amr_fsm_states[] = { /* default state for non-DTX and DTX when SPEECH is in progress */ [ST_VOICE] = { - .in_event_mask = X(E_SID_F) | X(E_SID_U) | X(E_VOICE) | X(E_FACCH), - .out_state_mask = X(ST_SID_F1), + .in_event_mask = X(E_SID_F) | X(E_SID_U) | X(E_VOICE) | X(E_FACCH) | X(E_INHIB), + .out_state_mask = X(ST_SID_F1) | X(ST_U_NOINH) | X(ST_F1_INH_V), .name = "Voice", .action = dtx_fsm_voice, }, /* SID-FIRST or SID-FIRST-P1 in case of AMR HR: start of silence period (might be interrupted in case of AMR HR) */ [ST_SID_F1]= { - .in_event_mask = X(E_SID_F) | X(E_SID_U) | X(E_VOICE) | X(E_FACCH) | X(E_FIRST) | X(E_INHIB) | X(E_ONSET), - .out_state_mask = X(ST_U_NOINH) | X(ST_VOICE) | X(ST_ONSET_F) | X(ST_SID_F2) | X(ST_F1_INH) | X(ST_ONSET_V), + .in_event_mask = X(E_SID_F) | X(E_SID_U) | X(E_FACCH) | X(E_FIRST) | X(E_ONSET), + .out_state_mask = X(ST_U_NOINH) | X(ST_ONSET_F) | X(ST_SID_F2) | X(ST_ONSET_V), .name = "SID-FIRST (P1)", .action = dtx_fsm_sid_f1, }, /* SID-FIRST P2 (only for AMR HR): actual start of silence period in case of AMR HR */ [ST_SID_F2]= { - .in_event_mask = X(E_COMPL) | X(E_VOICE) | X(E_FACCH) | X(E_ONSET), - .out_state_mask = X(ST_SID_U) | X(ST_VOICE) | X(ST_ONSET_F) | X(ST_ONSET_V), + .in_event_mask = X(E_COMPL) | X(E_FACCH) | X(E_ONSET), + .out_state_mask = X(ST_U_NOINH) | X(ST_ONSET_F) | X(ST_ONSET_V), .name = "SID-FIRST (P2)", .action = dtx_fsm_sid_f2, }, /* SID-FIRST Inhibited: incoming SPEECH (only for AMR HR) */ - [ST_F1_INH]= { + [ST_F1_INH_V]= { .in_event_mask = X(E_COMPL), - .out_state_mask = X(ST_F1_INH_REC), - .name = "SID-FIRST (Inh)", - .action = dtx_fsm_f1_inh, + .out_state_mask = X(ST_F1_INH_V_REC), + .name = "SID-FIRST (Inh, SPEECH)", + .action = dtx_fsm_f1_inh_v, + }, + /* SID-FIRST Inhibited: incoming FACCH frame (only for AMR HR) */ + [ST_F1_INH_F]= { + .in_event_mask = X(E_COMPL), + .out_state_mask = X(ST_F1_INH_F_REC), + .name = "SID-FIRST (Inh, FACCH)", + .action = dtx_fsm_f1_inh_f, }, /* SID-UPDATE Inhibited: incoming SPEECH (only for AMR HR) */ - [ST_U_INH]= { + [ST_U_INH_V]= { .in_event_mask = X(E_COMPL), - .out_state_mask = X(ST_U_INH_REC), - .name = "SID-UPDATE (Inh)", - .action = dtx_fsm_u_inh, + .out_state_mask = X(ST_U_INH_V_REC), + .name = "SID-UPDATE (Inh, SPEECH)", + .action = dtx_fsm_u_inh_v, + }, + /* SID-UPDATE Inhibited: incoming FACCH frame (only for AMR HR) */ + [ST_U_INH_F]= { + .in_event_mask = X(E_COMPL), + .out_state_mask = X(ST_U_INH_F_REC), + .name = "SID-UPDATE (Inh, FACCH)", + .action = dtx_fsm_u_inh_f, }, /* SID-UPDATE: Inhibited not allowed (only for AMR HR) */ [ST_U_NOINH]= { @@ -314,24 +380,40 @@ static struct osmo_fsm_state dtx_dl_amr_fsm_states[] = { }, /* SID-FIRST Inhibition recursion in progress: Inhibit itself was already sent, now have to send the voice that caused it */ - [ST_F1_INH_REC]= { - .in_event_mask = X(E_COMPL), + [ST_F1_INH_V_REC]= { + .in_event_mask = X(E_COMPL) | X(E_VOICE), .out_state_mask = X(ST_VOICE), - .name = "SID-FIRST (Inh, Rec)", - .action = dtx_fsm_f1_inh_rec, + .name = "SID-FIRST (Inh, SPEECH, Rec)", + .action = dtx_fsm_f1_inh_v_rec, + }, + /* SID-FIRST Inhibition recursion in progress: + Inhibit itself was already sent, now have to send the data that caused it */ + [ST_F1_INH_F_REC]= { + .in_event_mask = X(E_COMPL) | X(E_FACCH), + .out_state_mask = X(ST_FACCH), + .name = "SID-FIRST (Inh, FACCH, Rec)", + .action = dtx_fsm_f1_inh_f_rec, }, /* SID-UPDATE Inhibition recursion in progress: Inhibit itself was already sent, now have to send the voice that caused it */ - [ST_U_INH_REC]= { - .in_event_mask = X(E_COMPL), + [ST_U_INH_V_REC]= { + .in_event_mask = X(E_COMPL) | X(E_VOICE), .out_state_mask = X(ST_VOICE), - .name = "SID-UPDATE (Inh, Rec)", - .action = dtx_fsm_u_inh_rec, + .name = "SID-UPDATE (Inh, SPEECH, Rec)", + .action = dtx_fsm_u_inh_v_rec, + }, + /* SID-UPDATE Inhibition recursion in progress: + Inhibit itself was already sent, now have to send the data that caused it */ + [ST_U_INH_F_REC]= { + .in_event_mask = X(E_COMPL) | X(E_FACCH), + .out_state_mask = X(ST_FACCH), + .name = "SID-UPDATE (Inh, FACCH, Rec)", + .action = dtx_fsm_u_inh_f_rec, }, /* Silence period with periodic comfort noise data updates */ [ST_SID_U]= { .in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_INHIB) | X(E_SID_U) | X(E_SID_F), - .out_state_mask = X(ST_ONSET_F) | X(ST_VOICE) | X(ST_U_INH) | X(ST_U_NOINH), + .out_state_mask = X(ST_ONSET_F) | X(ST_VOICE) | X(ST_U_INH_V) | X(ST_U_INH_F) | X(ST_U_NOINH), .name = "SID-UPDATE (AMR/HR)", .action = dtx_fsm_sid_upd, }, @@ -365,8 +447,7 @@ static struct osmo_fsm_state dtx_dl_amr_fsm_states[] = { .name = "ONSET (FACCH, Rec)", .action = dtx_fsm_onset_f_rec, }, - /* FACCH sending state: no SPEECH was observed before so once we're done - FSM should get back to silent period via SID-FIRST */ + /* FACCH sending state */ [ST_FACCH]= { .in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_COMPL) | X(E_SID_U) | X(E_SID_F), .out_state_mask = X(ST_VOICE) | X(ST_SID_F1), diff --git a/src/common/msg_utils.c b/src/common/msg_utils.c index 062f5e3a7..f936c9838 100644 --- a/src/common/msg_utils.c +++ b/src/common/msg_utils.c @@ -137,7 +137,7 @@ void dtx_cache_payload(struct gsm_lchan *lchan, const uint8_t *l1_payload, size_t length, uint32_t fn, int update) { size_t amr = (update < 0) ? 0 : 2, - copy_len = OSMO_MIN(length + 1, + copy_len = OSMO_MIN(length, ARRAY_SIZE(lchan->tch.dtx.cache) - amr); lchan->tch.dtx.len = copy_len + amr; @@ -230,7 +230,7 @@ int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl, if (osmo_amr_is_speech(ft)) { /* AMR HR - SID-FIRST_P1 Inhibition */ - if (marker && dtx_is_first_p1(lchan)) + if (marker && lchan->tch.dtx.dl_amr_fsm->state == ST_VOICE) return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm, E_INHIB, (void *)lchan); @@ -261,7 +261,8 @@ int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl, as FIRST regardless of actually decoded type */ dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, false); return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm, - E_SID_F, (void *)lchan); + sti ? E_SID_U : E_SID_F, + (void *)lchan); } else if (lchan->tch.dtx.dl_amr_fsm->state != ST_FACCH) dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, sti); if (lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F2) @@ -319,12 +320,24 @@ static inline bool dtx_amr_sid_optional(struct gsm_lchan *lchan, uint32_t fn) already: we rely here on the order of RTS arrival from L1 - we expect that PH-DATA.req ALWAYS comes before PH-TCH.req for the same FN */ - if (lchan->tch.dtx.fn != LCHAN_FN_DUMMY) { - /* FACCH interruption is over */ - dtx_dispatch(lchan, E_COMPL); - return false; - } else - lchan->tch.dtx.fn = fn; + if(lchan->type == GSM_LCHAN_TCH_H) { + if (lchan->tch.dtx.fn != LCHAN_FN_DUMMY && + lchan->tch.dtx.fn != LCHAN_FN_WAIT) { + /* FACCH interruption is over */ + dtx_dispatch(lchan, E_COMPL); + return false; + } else if(lchan->tch.dtx.fn == LCHAN_FN_DUMMY) { + lchan->tch.dtx.fn = LCHAN_FN_WAIT; + } else + lchan->tch.dtx.fn = fn; + } else if(lchan->type == GSM_LCHAN_TCH_F) { + if (lchan->tch.dtx.fn != LCHAN_FN_DUMMY) { + /* FACCH interruption is over */ + dtx_dispatch(lchan, E_COMPL); + return false; + } else + lchan->tch.dtx.fn = fn; + } /* this FN was already used for FACCH or ONSET message so we just prepare things for next one */ return true; @@ -401,9 +414,14 @@ bool dtx_recursion(const struct gsm_lchan *lchan) if (!dtx_dl_amr_enabled(lchan)) return false; - if (lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH || - lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_REC || - lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH || + if (lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_V || + lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F || + lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_V_REC || + lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F_REC || + lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_V || + lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F || + lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_V_REC || + lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F_REC || lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F || lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_V || lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F_REC || diff --git a/src/osmo-bts-litecell15/l1_if.c b/src/osmo-bts-litecell15/l1_if.c index e1dcecfd3..5977aa9f6 100644 --- a/src/osmo-bts-litecell15/l1_if.c +++ b/src/osmo-bts-litecell15/l1_if.c @@ -410,7 +410,9 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, lchan->tch.dtx.facch, msgb_l2len(msg)); else if (dtx_dl_amr_enabled(lchan) && - lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) { + ((lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) || + (lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) || + (lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F))) { if (sapi == GsmL1_Sapi_FacchF) { sapi = GsmL1_Sapi_TchF; } @@ -424,9 +426,16 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, /* cache FACCH data */ memcpy(lchan->tch.dtx.facch, msg->l2h, msgb_l2len(msg)); - /* prepare ONSET message */ - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_Onset; + /* prepare ONSET or INH message */ + if(lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) + l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = + GsmL1_TchPlType_Amr_Onset; + else if(lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) + l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = + GsmL1_TchPlType_Amr_SidUpdateInH; + else if(lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F) + l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = + GsmL1_TchPlType_Amr_SidFirstInH; /* ignored CMR/CMI pair */ l1p->u.phDataReq.msgUnitParam.u8Buffer[1] = 0; l1p->u.phDataReq.msgUnitParam.u8Buffer[2] = 0; diff --git a/src/osmo-bts-litecell15/tch.c b/src/osmo-bts-litecell15/tch.c index 4b22b64f8..ffc1eb381 100644 --- a/src/osmo-bts-litecell15/tch.c +++ b/src/osmo-bts-litecell15/tch.c @@ -311,12 +311,12 @@ int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, ft); return 0; - case ST_F1_INH: + case ST_F1_INH_V: *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: + case ST_U_INH_V: *payload_type = GsmL1_TchPlType_Amr_SidUpdateInH; *len = 3; dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c index ef965d43d..c02136840 100644 --- a/src/osmo-bts-sysmo/l1_if.c +++ b/src/osmo-bts-sysmo/l1_if.c @@ -405,7 +405,9 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, lchan->tch.dtx.facch, msgb_l2len(msg)); else if (dtx_dl_amr_enabled(lchan) && - lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) { + ((lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) || + (lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) || + (lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F))) { if (sapi == GsmL1_Sapi_FacchF) { sapi = GsmL1_Sapi_TchF; } @@ -419,9 +421,16 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, /* cache FACCH data */ memcpy(lchan->tch.dtx.facch, msg->l2h, msgb_l2len(msg)); - /* prepare ONSET message */ - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_Onset; + /* prepare ONSET or INH message */ + if(lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) + l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = + GsmL1_TchPlType_Amr_Onset; + else if(lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) + l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = + GsmL1_TchPlType_Amr_SidUpdateInH; + else if(lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F) + l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = + GsmL1_TchPlType_Amr_SidFirstInH; /* ignored CMR/CMI pair */ l1p->u.phDataReq.msgUnitParam.u8Buffer[1] = 0; l1p->u.phDataReq.msgUnitParam.u8Buffer[2] = 0; diff --git a/src/osmo-bts-sysmo/tch.c b/src/osmo-bts-sysmo/tch.c index 8eb419b4b..55c4049c6 100644 --- a/src/osmo-bts-sysmo/tch.c +++ b/src/osmo-bts-sysmo/tch.c @@ -409,12 +409,12 @@ int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, ft); return 0; - case ST_F1_INH: + case ST_F1_INH_V: *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: + case ST_U_INH_V: *payload_type = GsmL1_TchPlType_Amr_SidUpdateInH; *len = 3; dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0);