aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-sysmo/tch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bts-sysmo/tch.c')
-rw-r--r--src/osmo-bts-sysmo/tch.c92
1 files changed, 57 insertions, 35 deletions
diff --git a/src/osmo-bts-sysmo/tch.c b/src/osmo-bts-sysmo/tch.c
index 54e73136..2cf784e6 100644
--- a/src/osmo-bts-sysmo/tch.c
+++ b/src/osmo-bts-sysmo/tch.c
@@ -12,7 +12,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -77,7 +77,7 @@ static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len
cur[0] |= 0xD0;
#endif /* USE_L1_RTP_MODE */
- lchan_set_marker(osmo_fr_check_sid(l1_payload, payload_len), lchan);
+ lchan_set_marker(osmo_fr_is_any_sid(l1_payload), lchan);
return msg;
}
@@ -131,12 +131,8 @@ static struct msgb *l1_to_rtppayload_efr(uint8_t *l1_payload,
cur[0] |= 0xC0;
#endif /* USE_L1_RTP_MODE */
- enum osmo_amr_type ft;
- enum osmo_amr_quality bfi;
- uint8_t cmr;
- int8_t sti, cmi;
- osmo_amr_rtp_dec(l1_payload, payload_len, &cmr, &cmi, &ft, &bfi, &sti);
- lchan_set_marker(ft == AMR_GSM_EFR_SID, lchan);
+
+ lchan_set_marker(osmo_efr_is_any_sid(l1_payload), lchan);
return msg;
}
@@ -298,7 +294,7 @@ static struct msgb *l1_to_rtppayload_amr(uint8_t *l1_payload, uint8_t payload_le
LOGP(DL1P, LOGL_NOTICE, "L1->RTP: overriding CMR IDX %u\n", cmr_idx);
cmr = AMR_CMR_NONE;
} else {
- cmr = amr_mrc->bts_mode[cmr_idx].mode;
+ cmr = amr_mrc->mode[cmr_idx].mode;
lchan->tch.last_cmr = cmr;
}
@@ -403,7 +399,10 @@ int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len,
*payload_type = GsmL1_TchPlType_Efr;
rc = rtppayload_to_l1_efr(l1_payload, rtp_pl,
rtp_pl_len);
- /* FIXME: detect and save EFR SID */
+ if (rc && lchan->ts->trx->bts->dtxd)
+ is_sid = osmo_efr_check_sid(rtp_pl, rtp_pl_len);
+ if (is_sid)
+ dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, -1);
break;
#endif
case GSM48_CMODE_SPEECH_AMR:
@@ -505,7 +504,7 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
{
GsmL1_Prim_t *l1p = msgb_l1prim(l1p_msg);
GsmL1_PhDataInd_t *data_ind = &l1p->u.phDataInd;
- uint8_t *payload, payload_type, payload_len, sid_first[9] = { 0 };
+ uint8_t *payload, payload_type, payload_len;
struct msgb *rmsg = NULL;
struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)].lchan[l1sap_chan2ss(chan_nr)];
@@ -513,12 +512,15 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
return -EAGAIN;
if (data_ind->msgUnitParam.u8Size < 1) {
- LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "chan_nr %d Rx Payload size 0\n", chan_nr);
+ LOGPLCFN(lchan, data_ind->u32Fn, DL1P, LOGL_DEBUG, "chan_nr %d Rx Payload size 0\n", chan_nr);
/* Push empty payload to upper layers */
rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP");
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
data_ind->measParam.fBer * 10000,
- data_ind->measParam.fLinkQuality * 10);
+ data_ind->measParam.fLinkQuality * 10,
+ data_ind->measParam.fRssi,
+ data_ind->measParam.i16BurstTiming * 64,
+ 0);
}
payload_type = data_ind->msgUnitParam.u8Buffer[0];
@@ -546,6 +548,8 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
if (lchan->type != GSM_LCHAN_TCH_H &&
lchan->type != GSM_LCHAN_TCH_F)
goto err_payload_match;
+ LOGPLCFN(lchan, data_ind->u32Fn, DL1P, LOGL_DEBUG, "DTX: received ONSET from L1 " "(%d bytes)\n",
+ payload_len);
/* according to 3GPP TS 26.093 ONSET frames precede the first
speech frame of a speech burst - set the marker for next RTP
frame */
@@ -554,33 +558,32 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
case GsmL1_TchPlType_Amr_SidFirstP1:
if (lchan->type != GSM_LCHAN_TCH_H)
goto err_payload_match;
- LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_P1 from L1 "
- "(%d bytes)\n", payload_len);
+ LOGPLCFN(lchan, data_ind->u32Fn, DL1P, LOGL_DEBUG, "DTX: received SID_FIRST_P1 from L1 "
+ "(%d bytes)\n", payload_len);
break;
case GsmL1_TchPlType_Amr_SidFirstP2:
if (lchan->type != GSM_LCHAN_TCH_H)
goto err_payload_match;
- LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_P2 from L1 "
- "(%d bytes)\n", payload_len);
+ LOGPLCFN(lchan, data_ind->u32Fn, DL1P, LOGL_DEBUG, "DTX: received SID_FIRST_P2 from L1 "
+ "(%d bytes)\n", payload_len);
break;
case GsmL1_TchPlType_Amr_SidFirstInH:
if (lchan->type != GSM_LCHAN_TCH_H)
goto err_payload_match;
lchan->rtp_tx_marker = true;
- LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_INH from L1 "
- "(%d bytes)\n", payload_len);
+ LOGPLCFN(lchan, data_ind->u32Fn, DL1P, LOGL_DEBUG, "DTX: received SID_FIRST_INH from L1 "
+ "(%d bytes)\n", payload_len);
break;
case GsmL1_TchPlType_Amr_SidUpdateInH:
if (lchan->type != GSM_LCHAN_TCH_H)
goto err_payload_match;
lchan->rtp_tx_marker = true;
- LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_UPDATE_INH from L1 "
- "(%d bytes)\n", payload_len);
+ LOGPLCFN(lchan, data_ind->u32Fn, DL1P, LOGL_DEBUG, "DTX: received SID_UPDATE_INH from L1 "
+ "(%d bytes)\n", payload_len);
break;
default:
- LOGPFN(DL1P, LOGL_NOTICE, data_ind->u32Fn, "%s Rx Payload Type %s is unsupported\n",
- gsm_lchan_name(lchan),
- get_value_string(femtobts_tch_pl_names, payload_type));
+ LOGPLCFN(lchan, data_ind->u32Fn, DL1P, LOGL_NOTICE, "%s Rx Payload Type %s is unsupported\n",
+ gsm_lchan_name(lchan), get_value_string(femtobts_tch_pl_names, payload_type));
break;
}
@@ -598,14 +601,8 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
break;
#endif
case GsmL1_TchPlType_Amr:
- rmsg = l1_to_rtppayload_amr(payload, payload_len, lchan);
- break;
case GsmL1_TchPlType_Amr_SidFirstP1:
- memcpy(sid_first, payload, payload_len);
- int len = osmo_amr_rtp_enc(sid_first, 0, AMR_SID, AMR_GOOD);
- if (len < 0)
- return 0;
- rmsg = l1_to_rtppayload_amr(sid_first, len, lchan);
+ rmsg = l1_to_rtppayload_amr(payload, payload_len, lchan);
break;
/* FIXME: what about GsmL1_TchPlType_Amr_SidBad? not well documented. */
}
@@ -613,17 +610,42 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
if (rmsg)
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
data_ind->measParam.fBer * 10000,
- data_ind->measParam.fLinkQuality * 10);
+ data_ind->measParam.fLinkQuality * 10,
+ data_ind->measParam.fRssi,
+ data_ind->measParam.i16BurstTiming * 64,
+ 0);
return 0;
err_payload_match:
- LOGPFN(DL1P, LOGL_ERROR, data_ind->u32Fn, "%s Rx Payload Type %s incompatible with lchan\n",
- gsm_lchan_name(lchan),
- get_value_string(femtobts_tch_pl_names, payload_type));
+ LOGPLCFN(lchan, data_ind->u32Fn, DL1P, LOGL_ERROR, "%s Rx Payload Type %s incompatible with lchan\n",
+ gsm_lchan_name(lchan), get_value_string(femtobts_tch_pl_names, payload_type));
return -EINVAL;
}
+/*! \brief provide an RTP empty payload "tick" to upper layers upon FACCH */
+int l1if_tch_rx_facch(struct gsm_bts_trx *trx, uint8_t chan_nr,
+ struct msgb *l1p_msg)
+{
+ GsmL1_Prim_t *l1p = msgb_l1prim(l1p_msg);
+ GsmL1_PhDataInd_t *data_ind = &l1p->u.phDataInd;
+ struct msgb *rmsg = NULL;
+ struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)].lchan[l1sap_chan2ss(chan_nr)];
+
+ if (is_recv_only(lchan->abis_ip.speech_mode))
+ return -EAGAIN;
+
+ LOGPLCFN(lchan, data_ind->u32Fn, DL1P, LOGL_DEBUG, "chan_nr %d Rx FACCH\n", chan_nr);
+ /* Push empty payload to upper layers */
+ rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP");
+ return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
+ data_ind->measParam.fBer * 10000,
+ data_ind->measParam.fLinkQuality * 10,
+ 0, /* suppress RSSI like in osmo-bts-trx */
+ data_ind->measParam.i16BurstTiming * 64,
+ 0);
+}
+
struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn)
{
struct msgb *msg;