aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-sysmo/tch.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2011-09-07 12:42:15 +0200
committerHarald Welte <laforge@gnumonks.org>2011-09-07 12:42:15 +0200
commitf49e3dd3af9db41c4b4314ad3c97c1dd9e7ff81c (patch)
treeae6cd3aaf779c59ea74d0523a4790186e9ece322 /src/osmo-bts-sysmo/tch.c
parente5d082f3566bedf0b5b6e6aa3761cc5ce77da754 (diff)
store the last SID frame of a given LCHAN so we can repeat it
repeating the last SID frame is required during 20ms intervals where we don't get a new SID update (SID RTP frames are valid up to 160ms)
Diffstat (limited to 'src/osmo-bts-sysmo/tch.c')
-rw-r--r--src/osmo-bts-sysmo/tch.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/osmo-bts-sysmo/tch.c b/src/osmo-bts-sysmo/tch.c
index df1ad4c6..77fd4f87 100644
--- a/src/osmo-bts-sysmo/tch.c
+++ b/src/osmo-bts-sysmo/tch.c
@@ -264,8 +264,9 @@ int get_amr_mode_idx(const struct amr_multirate_conf *amr_mrc, uint8_t cmi)
*/
static int rtppayload_to_l1_amr(uint8_t *l1_payload, uint8_t *rtp_payload,
uint8_t payload_len,
- struct amr_multirate_conf *amr_mrc)
+ struct gsm_lchan *lchan)
{
+ struct amr_multirate_conf *amr_mrc = &lchan->tch.amr_mr;
uint8_t ft = (rtp_payload[1] >> 3) & 0xf;
uint8_t cmr = rtp_payload[0] >> 4;
uint8_t cmi, sti;
@@ -343,6 +344,15 @@ static int rtppayload_to_l1_amr(uint8_t *l1_payload, uint8_t *rtp_payload,
/* lower 4 bit of first FR2 byte contains FT */
l1_payload[2] |= ft;
+ if (ft == AMR_FT_SID_AMR) {
+ /* store the last SID frame in lchan context */
+ unsigned int copy_len;
+ copy_len = OSMO_MIN(payload_len+1,
+ ARRAY_SIZE(lchan->tch.last_sid.buf));
+ lchan->tch.last_sid.len = copy_len;
+ memcpy(lchan->tch.last_sid.buf, l1_payload, copy_len);
+ }
+
return payload_len+1;
}
@@ -396,7 +406,7 @@ void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, uint8_t *rtp_pl,
case GSM48_CMODE_SPEECH_AMR:
*payload_type = GsmL1_TchPlType_Amr;
rc = rtppayload_to_l1_amr(l1_payload, rtp_pl,
- rtp_pl_len, &lchan->tch.amr_mr);
+ rtp_pl_len, lchan);
break;
default:
/* we don't support CSD modes */
@@ -519,3 +529,41 @@ err_payload_match:
get_value_string(femtobts_tch_pl_names, payload_type));
return -EINVAL;
}
+
+struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan)
+{
+ struct msgb *msg = l1p_msgb_alloc();
+ GsmL1_Prim_t *l1p = msgb_l1prim(msg);
+ GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq;
+ GsmL1_MsgUnitParam_t *msu_param = &data_req->msgUnitParam;
+ uint8_t *payload_type = &msu_param->u8Buffer[0];
+ uint8_t *l1_payload = &msu_param->u8Buffer[1];
+
+ switch (lchan->tch_mode) {
+ case GSM48_CMODE_SPEECH_AMR:
+ *payload_type = GsmL1_TchPlType_Amr;
+ if (lchan->tch.last_sid.len) {
+ memcpy(l1_payload, lchan->tch.last_sid.buf,
+ lchan->tch.last_sid.len);
+ msu_param->u8Size = lchan->tch.last_sid.len+1;
+ } else {
+ /* FIXME: decide if we should send SPEECH_BAD or
+ * SID_BAD */
+#if 0
+ *payload_type = GsmL1_TchPlType_Amr_SidBad;
+ memset(l1_payload, 0xFF, 5);
+ msu_param->u8Size = 5 + 3;
+#else
+ /* send an all-zero SID */
+ msu_param->u8Size = 8;
+#endif
+ }
+ break;
+ default:
+ msgb_free(msg);
+ msg = NULL;
+ break;
+ }
+
+ return msg;
+}