Instead of handling primitves itself, sysmo-bts code sends and receives
PH-/MPH-/TCH primitves to and from common code.
---
src/osmo-bts-sysmo/l1_if.c | 1092 +++++++++++++++++--------------------
src/osmo-bts-sysmo/l1_if.h | 13 +-
src/osmo-bts-sysmo/main.c | 3 +-
src/osmo-bts-sysmo/oml.c | 46 +-
src/osmo-bts-sysmo/sysmobts_vty.c | 94 ----
src/osmo-bts-sysmo/tch.c | 117 +---
6 files changed, 559 insertions(+), 806 deletions(-)
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c
index 6efb9d6..f2e4440 100644
--- a/src/osmo-bts-sysmo/l1_if.c
+++ b/src/osmo-bts-sysmo/l1_if.c
@@ -32,21 +32,17 @@
#include <osmocom/core/select.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/write_queue.h>
-#include <osmocom/core/gsmtap.h>
-#include <osmocom/core/gsmtap_util.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/lapdm.h>
-#include <osmocom/trau/osmo_ortp.h>
-
#include <osmo-bts/logging.h>
#include <osmo-bts/bts.h>
#include <osmo-bts/oml.h>
-#include <osmo-bts/rsl.h>
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/paging.h>
#include <osmo-bts/measurement.h>
#include <osmo-bts/pcu_if.h>
+#include <osmo-bts/l1sap.h>
#include <sysmocom/femtobts/superfemto.h>
#include <sysmocom/femtobts/gsml1prim.h>
@@ -63,98 +59,6 @@ extern int pcu_direct;
#define MIN_QUAL_RACH 5.0f /* at least 5 dB C/I */
#define MIN_QUAL_NORM -0.5f /* at least -1 dB C/I */
-/* mapping from femtobts L1 SAPI to GSMTAP channel type */
-static const uint8_t l1sapi2gsmtap_cht[GsmL1_Sapi_NUM] = {
- [GsmL1_Sapi_Idle] = 255,
- [GsmL1_Sapi_Fcch] = 255,
- [GsmL1_Sapi_Sch] = 255,
- [GsmL1_Sapi_Sacch] = GSMTAP_CHANNEL_SDCCH | GSMTAP_CHANNEL_ACCH,
- [GsmL1_Sapi_Sdcch] = GSMTAP_CHANNEL_SDCCH,
- [GsmL1_Sapi_Bcch] = GSMTAP_CHANNEL_BCCH,
- [GsmL1_Sapi_Pch] = GSMTAP_CHANNEL_PCH,
- [GsmL1_Sapi_Agch] = GSMTAP_CHANNEL_AGCH,
- [GsmL1_Sapi_Cbch] = GSMTAP_CHANNEL_CBCH51,
- [GsmL1_Sapi_Rach] = GSMTAP_CHANNEL_RACH,
- [GsmL1_Sapi_TchF] = 255,
- [GsmL1_Sapi_FacchF] = GSMTAP_CHANNEL_TCH_F,
- [GsmL1_Sapi_TchH] = 255,
- [GsmL1_Sapi_FacchH] = GSMTAP_CHANNEL_TCH_H,
- [GsmL1_Sapi_Nch] = GSMTAP_CHANNEL_CCCH,
- [GsmL1_Sapi_Pdtch] = GSMTAP_CHANNEL_PACCH,
- [GsmL1_Sapi_Pacch] = GSMTAP_CHANNEL_PACCH,
- [GsmL1_Sapi_Pbcch] = 255,
- [GsmL1_Sapi_Pagch] = 255,
- [GsmL1_Sapi_Ppch] = 255,
- [GsmL1_Sapi_Pnch] = 255,
- [GsmL1_Sapi_Ptcch] = GSMTAP_CHANNEL_PTCCH,
- [GsmL1_Sapi_Prach] = 255,
-};
-
-static void tx_to_gsmtap(struct femtol1_hdl *fl1h, struct msgb *msg)
-{
- struct gsm_bts_trx *trx = fl1h->priv;
- GsmL1_Prim_t *l1p = msgb_l1prim(msg);
- GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq;
-
- if (fl1h->gsmtap) {
- uint8_t ss, chan_type;
- if (data_req->subCh == 0x1f)
- ss = 0;
- else
- ss = data_req->subCh;
-
- if (!(fl1h->gsmtap_sapi_mask & (1 << data_req->sapi)))
- return;
-
- chan_type = l1sapi2gsmtap_cht[data_req->sapi];
- if (chan_type == 255)
- return;
-
- gsmtap_send(fl1h->gsmtap, trx->arfcn, data_req->u8Tn,
- chan_type, ss, data_req->u32Fn, 0, 0,
- data_req->msgUnitParam.u8Buffer,
- data_req->msgUnitParam.u8Size);
- }
-}
-
-static void ul_to_gsmtap(struct femtol1_hdl *fl1h, struct msgb *msg)
-{
- struct gsm_bts_trx *trx = fl1h->priv;
- GsmL1_Prim_t *l1p = msgb_l1prim(msg);
- GsmL1_PhDataInd_t *data_ind = &l1p->u.phDataInd;
- int skip = 0;
-
- if (fl1h->gsmtap) {
- uint8_t ss, chan_type;
- if (data_ind->subCh == 0x1f)
- ss = 0;
- else
- ss = data_ind->subCh;
-
- if (!(fl1h->gsmtap_sapi_mask & (1 << data_ind->sapi)))
- return;
-
- chan_type = l1sapi2gsmtap_cht[data_ind->sapi];
- if (chan_type == 255)
- return;
- if (chan_type == GSMTAP_CHANNEL_PACCH
- || chan_type == GSMTAP_CHANNEL_PDCH) {
- if (data_ind->msgUnitParam.u8Buffer[0]
- != GsmL1_PdtchPlType_Full)
- return;
- skip = 1;
- }
-
- gsmtap_send(fl1h->gsmtap, trx->arfcn | GSMTAP_ARFCN_F_UPLINK,
- data_ind->u8Tn, chan_type, ss, data_ind->u32Fn,
- data_ind->measParam.fRssi,
- data_ind->measParam.fLinkQuality,
- data_ind->msgUnitParam.u8Buffer + skip,
- data_ind->msgUnitParam.u8Size - skip);
- }
-}
-
-
struct wait_l1_conf {
struct llist_head list; /* internal linked list */
struct osmo_timer_list timer; /* timer for L1 timeout */
@@ -314,74 +218,442 @@ empty_req_from_rts_ind(GsmL1_Prim_t *l1p,
return empty_req;
}
-/* obtain a ptr to the lapdm_channel for a given hLayer2 */
-static struct lapdm_channel *
-get_lapdm_chan_by_hl2(struct gsm_bts_trx *trx, uint32_t hLayer2)
-{
- struct gsm_lchan *lchan;
+static const uint8_t fill_frame[GSM_MACBLOCK_LEN] = {
+ 0x03, 0x03, 0x01, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
+ 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
+ 0x2B, 0x2B, 0x2B
+};
- lchan = l1if_hLayer_to_lchan(trx, hLayer2);
- if (!lchan)
- return NULL;
+static void dump_meas_res(int ll, GsmL1_MeasParam_t *m)
+{
+ LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, "
+ "BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality,
+ m->fBer, m->i16BurstTiming);
+}
- return &lchan->lapdm_ch;
+static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr,
+ GsmL1_MeasParam_t *m)
+{
+ struct osmo_phsap_prim l1sap;
+
+ memset(&l1sap, 0, sizeof(l1sap));
+ osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO,
+ PRIM_OP_INDICATION, NULL);
+ l1sap.u.info.type = PRIM_INFO_MEAS;
+ l1sap.u.info.u.meas_ind.chan_nr = chan_nr;
+ l1sap.u.info.u.meas_ind.ta_offs_qbits = m->i16BurstTiming;
+ l1sap.u.info.u.meas_ind.ber10k = (unsigned int) (m->fBer * 100);
+ l1sap.u.info.u.meas_ind.inv_rssi = (uint8_t) (m->fRssi * -1);
+
+ return l1sap_up(trx, &l1sap);
}
-/* check if the message is a GSM48_MT_RR_CIPH_M_CMD, and if yes, enable
- * uni-directional de-cryption on the uplink. We need this ugly layering
- * violation as we have no way of passing down L3 metadata (RSL CIPHERING CMD)
- * to this point in L1 */
-static int check_for_ciph_cmd(struct femtol1_hdl *fl1h,
- struct msgb *msg, struct gsm_lchan *lchan)
+/* primitive from common part */
+int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
{
+ struct femtol1_hdl *fl1 = trx_femtol1_hdl(trx);
+ struct msgb *msg = l1sap->oph.msg;
+ uint32_t u32Fn;
+ uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi, ss;
+ uint8_t chan_nr, link_id;
+ int rc = 0;
+ struct msgb *nmsg = NULL;
+ GsmL1_Prim_t *l1p;
+ struct gsm_lchan *lchan;
+
+ switch (OSMO_PRIM_HDR(&l1sap->oph)) {
+ case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST):
+ if (!msg) {
+ LOGP(DL1C, LOGL_FATAL, "PH-DATA.req without msg. "
+ "Please fix!\n");
+ abort();
+ }
+ chan_nr = l1sap->u.data.chan_nr;
+ link_id = l1sap->u.data.link_id;
+ u32Fn = l1sap->u.data.fn;
+ u8Tn = L1SAP_CHAN2TS(chan_nr);
+ subCh = 0x1f;
+ if (L1SAP_IS_LINK_SACCH(link_id)) {
+ sapi = GsmL1_Sapi_Sacch;
+ if (!L1SAP_IS_CHAN_TCHF(chan_nr))
+ subCh = l1sap_chan2ss(chan_nr);
+ } else if (L1SAP_IS_CHAN_TCHF(chan_nr)) {
+ if (trx->ts[u8Tn].pchan == GSM_PCHAN_PDCH) {
+ if (L1SAP_IS_PTCCH(u32Fn)) {
+ sapi = GsmL1_Sapi_Ptcch;
+ u8BlockNbr = L1SAP_FN2PTCCHBLOCK(u32Fn);
+ } else {
+ sapi = GsmL1_Sapi_Pdtch;
+ u8BlockNbr = L1SAP_FN2MACBLOCK(u32Fn);
+ }
+ } else {
+ sapi = GsmL1_Sapi_FacchF;
+ u8BlockNbr = (u32Fn % 13) >> 2;
+ }
+ } else if (L1SAP_IS_CHAN_TCHH(chan_nr)) {
+ subCh = L1SAP_CHAN2SS_TCHH(chan_nr);
+ sapi = GsmL1_Sapi_FacchH;
+ u8BlockNbr = (u32Fn % 26) >> 3;
+ } else if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) {
+ subCh = L1SAP_CHAN2SS_SDCCH4(chan_nr);
+ sapi = GsmL1_Sapi_Sdcch;
+ } else if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) {
+ subCh = L1SAP_CHAN2SS_SDCCH8(chan_nr);
+ sapi = GsmL1_Sapi_Sdcch;
+ } else if (L1SAP_IS_CHAN_BCCH(chan_nr)) {
+ sapi = GsmL1_Sapi_Bcch;
+ } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) {
+#warning Set BS_AG_BLKS_RES
+ /* The sapi depends on DSP configuration, not
+ * on the actual SYSTEM INFORMATION 3. */
+ u8BlockNbr = L1SAP_FN2CCCHBLOCK(u32Fn);
+ if (u8BlockNbr >= 1)
+ sapi = GsmL1_Sapi_Pch;
+ else
+ sapi = GsmL1_Sapi_Agch;
+ } else {
+ LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d "
+ "chan_nr %d link_id %d\n", l1sap->oph.primitive,
+ l1sap->oph.operation, chan_nr, link_id);
+ rc = -EINVAL;
+ goto done;
+ }
+
+ msgb_pull(msg, sizeof(*l1sap));
+
+ /* create new message */
+ nmsg = l1p_msgb_alloc();
+ l1p = msgb_l1prim(nmsg);
+ if (msg->len) {
+ /* data request */
+ GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq;
+ GsmL1_MsgUnitParam_t *msu_param;
+
+ l1p->id = GsmL1_PrimId_PhDataReq;
+
+ data_req->hLayer1 = fl1->hLayer1;
+ data_req->u8Tn = u8Tn;
+ data_req->u32Fn = u32Fn;
+ data_req->sapi = sapi;
+ data_req->subCh = subCh;
+ data_req->u8BlockNbr = u8BlockNbr;
+ msu_param = &data_req->msgUnitParam;
+ msu_param->u8Size = msg->len;
+ memcpy(msu_param->u8Buffer, msg->data, msg->len);
+ } else {
+ /* empty frame */
+ GsmL1_PhEmptyFrameReq_t *empty_req =
+ &l1p->u.phEmptyFrameReq;
+
+ l1p->id = GsmL1_PrimId_PhEmptyFrameReq;
+
+ empty_req->hLayer1 = fl1->hLayer1;
+ empty_req->u8Tn = u8Tn;
+ empty_req->u32Fn = u32Fn;
+ empty_req->sapi = sapi;
+ empty_req->subCh = subCh;
+ empty_req->u8BlockNbr = u8BlockNbr;
+ }
+
+ /* send message to DSP's queue */
+ osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], nmsg);
+ break;
+ case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST):
+ chan_nr = l1sap->u.tch.chan_nr;
+ u32Fn = l1sap->u.tch.fn;
+ u8Tn = L1SAP_CHAN2TS(chan_nr);
+ u8BlockNbr = (u32Fn % 13) >> 2;
+ if (L1SAP_IS_CHAN_TCHH(chan_nr)) {
+ ss = subCh = L1SAP_CHAN2SS_TCHH(chan_nr);
+ sapi = GsmL1_Sapi_TchH;
+ } else {
+ subCh = 0x1f;
+ ss = 0;
+ sapi = GsmL1_Sapi_TchF;
+ }
+
+ lchan = &trx->ts[u8Tn].lchan[ss];
+
+ /* create new message and fill data */
+ if (msg) {
+ msgb_pull(msg, sizeof(*l1sap));
+ /* create new message */
+ nmsg = l1p_msgb_alloc();
+ if (!nmsg) {
+ rc = -ENOMEM;
+ goto done;
+ }
+ l1p = msgb_l1prim(nmsg);
+ l1if_tch_encode(lchan,
+ l1p->u.phDataReq.msgUnitParam.u8Buffer,
+ &l1p->u.phDataReq.msgUnitParam.u8Size,
+ msg->data, msg->len);
+ }
+
+ /* no message/data, we generate an empty traffic msg */
+ if (!nmsg)
+ nmsg = gen_empty_tch_msg(lchan);
+
+ /* no traffic message, we generate an empty msg */
+ if (!nmsg) {
+ nmsg = l1p_msgb_alloc();
+ if (!nmsg) {
+ rc = -ENOMEM;
+ goto done;
+ }
+ }
+
+ l1p = msgb_l1prim(nmsg);
- /* only do this if we are in the right state */
- switch (lchan->ciph_state) {
- case LCHAN_CIPH_NONE:
- case LCHAN_CIPH_RX_REQ:
+ /* if we provide data, or if data is already in nmsg */
+ if (l1p->u.phDataReq.msgUnitParam.u8Size) {
+ /* data request */
+ GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq;
+
+ l1p->id = GsmL1_PrimId_PhDataReq;
+
+ data_req->hLayer1 = fl1->hLayer1;
+ data_req->u8Tn = u8Tn;
+ data_req->u32Fn = u32Fn;
+ data_req->sapi = sapi;
+ data_req->subCh = subCh;
+ data_req->u8BlockNbr = u8BlockNbr;
+ } else {
+ /* empty frame */
+ GsmL1_PhEmptyFrameReq_t *empty_req =
+ &l1p->u.phEmptyFrameReq;
+
+ l1p->id = GsmL1_PrimId_PhEmptyFrameReq;
+
+ empty_req->hLayer1 = fl1->hLayer1;
+ empty_req->u8Tn = u8Tn;
+ empty_req->u32Fn = u32Fn;
+ empty_req->sapi = sapi;
+ empty_req->subCh = subCh;
+ empty_req->u8BlockNbr = u8BlockNbr;
+ }
+ /* send message to DSP's queue */
+ osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], nmsg);
+ break;
+ case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST):
+ switch (l1sap->u.info.type) {
+ case PRIM_INFO_ACT_CIPH:
+ chan_nr = l1sap->u.info.u.ciph_req.chan_nr;
+ u8Tn = L1SAP_CHAN2TS(chan_nr);
+ ss = l1sap_chan2ss(chan_nr);
+ lchan = &trx->ts[u8Tn].lchan[ss];
+ if (l1sap->u.info.u.ciph_req.downlink) {
+ l1if_set_ciphering(fl1, lchan, 1);
+ lchan->ciph_state = LCHAN_CIPH_RX_REQ;
+ }
+ if (l1sap->u.info.u.ciph_req.uplink) {
+ l1if_set_ciphering(fl1, lchan, 0);
+ lchan->ciph_state = LCHAN_CIPH_TXRX_REQ;
+ }
+ break;
+ case PRIM_INFO_ACTIVATE:
+ case PRIM_INFO_DEACTIVATE:
+ case PRIM_INFO_MODIFY:
+ chan_nr = l1sap->u.info.u.act_req.chan_nr;
+ u8Tn = L1SAP_CHAN2TS(chan_nr);
+ ss = l1sap_chan2ss(chan_nr);
+ lchan = &trx->ts[u8Tn].lchan[ss];
+ if (l1sap->u.info.type == PRIM_INFO_ACTIVATE)
+ l1if_rsl_chan_act(lchan);
+ else if (l1sap->u.info.type == PRIM_INFO_MODIFY)
+ l1if_rsl_mode_modify(lchan);
+ else if (l1sap->u.info.u.act_req.sacch_only)
+ l1if_rsl_deact_sacch(lchan);
+ else
+ l1if_rsl_chan_rel(lchan);
+ break;
+ default:
+ LOGP(DL1C, LOGL_NOTICE, "unknown MPH-INFO.req %d\n",
+ l1sap->u.info.type);
+ rc = -EINVAL;
+ goto done;
+ }
break;
default:
- return 0;
+ LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d\n",
+ l1sap->oph.primitive, l1sap->oph.operation);
+ rc = -EINVAL;
+ goto done;
}
- /* First byte (Address Field) of LAPDm header) */
- if (msg->data[0] != 0x03)
- return 0;
- /* First byte (protocol discriminator) of RR */
- if ((msg->data[3] & 0xF) != GSM48_PDISC_RR)
- return 0;
- /* 2nd byte (msg type) of RR */
- if ((msg->data[4] & 0x3F) != GSM48_MT_RR_CIPH_M_CMD)
+done:
+ if (msg)
+ msgb_free(msg);
+ return rc;
+}
+
+static int handle_mph_time_ind(struct femtol1_hdl *fl1,
+ GsmL1_MphTimeInd_t *time_ind)
+{
+ struct gsm_bts_trx *trx = fl1->priv;
+ struct gsm_bts *bts = trx->bts;
+ struct osmo_phsap_prim l1sap;
+ uint32_t fn;
+
+ /* increment the primitive count for the alive timer */
+ fl1->alive_prim_cnt++;
+
+ /* ignore every time indication, except for c0 */
+ if (trx != bts->c0) {
return 0;
+ }
- lchan->ciph_state = LCHAN_CIPH_RX_REQ;
- l1if_set_ciphering(fl1h, lchan, 0);
+ fn = time_ind->u32Fn;
- return 1;
+ memset(&l1sap, 0, sizeof(l1sap));
+ osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO,
+ PRIM_OP_INDICATION, NULL);
+ l1sap.u.info.type = PRIM_INFO_TIME;
+ l1sap.u.info.u.time_ind.fn = fn;
+
+ return l1sap_up(trx, &l1sap);
}
-static const uint8_t fill_frame[GSM_MACBLOCK_LEN] = {
- 0x03, 0x03, 0x01, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
- 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
- 0x2B, 0x2B, 0x2B
-};
+static uint8_t chan_nr_by_sapi(enum gsm_phys_chan_config pchan,
+ GsmL1_Sapi_t sapi, GsmL1_SubCh_t subCh,
+ uint8_t u8Tn, uint32_t u32Fn)
+{
+ uint8_t cbits = 0;
+ switch (sapi) {
+ case GsmL1_Sapi_Bcch:
+ cbits = 0x10;
+ break;
+ case GsmL1_Sapi_Sacch:
+ switch(pchan) {
+ case GSM_PCHAN_TCH_F:
+ cbits = 0x01;
+ break;
+ case GSM_PCHAN_TCH_H:
+ cbits = 0x02 + subCh;
+ break;
+ case GSM_PCHAN_CCCH_SDCCH4:
+ cbits = 0x04 + subCh;
+ break;
+ case GSM_PCHAN_SDCCH8_SACCH8C:
+ cbits = 0x08 + subCh;
+ break;
+ default:
+ LOGP(DL1C, LOGL_ERROR, "SACCH for pchan %d?\n",
+ pchan);
+ return 0;
+ }
+ break;
+ case GsmL1_Sapi_Sdcch:
+ switch(pchan) {
+ case GSM_PCHAN_CCCH_SDCCH4:
+ cbits = 0x04 + subCh;
+ break;
+ case GSM_PCHAN_SDCCH8_SACCH8C:
+ cbits = 0x08 + subCh;
+ break;
+ default:
+ LOGP(DL1C, LOGL_ERROR, "SDCCH for pchan %d?\n",
+ pchan);
+ return 0;
+ }
+ break;
+ case GsmL1_Sapi_Agch:
+ case GsmL1_Sapi_Pch:
+ cbits = 0x12;
+ break;
+ case GsmL1_Sapi_TchF:
+ cbits = 0x01;
+ break;
+ case GsmL1_Sapi_TchH:
+ cbits = 0x02 + subCh;
+ break;
+ case GsmL1_Sapi_FacchF:
+ cbits = 0x01;
+ break;
+ case GsmL1_Sapi_FacchH:
+ cbits = 0x02 + subCh;
+ break;
+ case GsmL1_Sapi_Pdtch:
+ case GsmL1_Sapi_Pacch:
+ switch(pchan) {
+ case GSM_PCHAN_PDCH:
+ cbits = 0x01;
+ break;
+ default:
+ LOGP(DL1C, LOGL_ERROR, "PDTCH for pchan %d?\n",
+ pchan);
+ return 0;
+ }
+ break;
+ case GsmL1_Sapi_Ptcch:
+ if (!L1SAP_IS_PTCCH(u32Fn)) {
+ LOGP(DL1C, LOGL_FATAL, "Not expecting PTCCH at frame "
+ "number other than 12, got it at %u (%u). "
+ "Please fix!\n", u32Fn % 52, u32Fn);
+ abort();
+ }
+ switch(pchan) {
+ case GSM_PCHAN_PDCH:
+ cbits = 0x01;
+ break;
+ default:
+ LOGP(DL1C, LOGL_ERROR, "PTCCH for pchan %d?\n",
+ pchan);
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return (cbits << 3) | u8Tn;
+}
static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1,
- GsmL1_PhReadyToSendInd_t *rts_ind)
+ GsmL1_PhReadyToSendInd_t *rts_ind,
+ struct msgb *l1p_msg)
{
struct gsm_bts_trx *trx = fl1->priv;
struct gsm_bts *bts = trx->bts;
- struct gsm_bts_role_bts *btsb = bts->role;
+ struct osmo_phsap_prim *l1sap;
+ struct gsm_time g_time;
+ uint8_t chan_nr, link_id;
+ uint32_t fn;
+ int rc;
struct msgb *resp_msg;
GsmL1_PhDataReq_t *data_req;
GsmL1_MsgUnitParam_t *msu_param;
- struct lapdm_entity *le;
- struct gsm_lchan *lchan;
- struct gsm_time g_time;
uint32_t t3p;
- uint8_t *si;
- struct osmo_phsap_prim pp;
- int rc;
+
+ /* in case we need to forward primitive to common part*/
+ chan_nr = chan_nr_by_sapi(trx->ts[rts_ind->u8Tn].pchan, rts_ind->sapi,
+ rts_ind->subCh, rts_ind->u8Tn, rts_ind->u32Fn);
+ if (chan_nr) {
+ fn = rts_ind->u32Fn;
+ if (rts_ind->sapi == GsmL1_Sapi_Sacch)
+ link_id = 0x40;
+ else
+ link_id = 0;
+ rc = msgb_trim(l1p_msg, sizeof(*l1sap));
+ if (rc < 0)
+ MSGB_ABORT(l1p_msg, "No room for primitive\n");
+ l1sap = msgb_l1sap_prim(l1p_msg);
+ if (rts_ind->sapi == GsmL1_Sapi_TchF
+ || rts_ind->sapi == GsmL1_Sapi_TchH) {
+ osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_TCH_RTS,
+ PRIM_OP_INDICATION, l1p_msg);
+ l1sap->u.tch.chan_nr = chan_nr;
+ l1sap->u.tch.fn = fn;
+ } else {
+ osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RTS,
+ PRIM_OP_INDICATION, l1p_msg);
+ l1sap->u.data.link_id = link_id;
+ l1sap->u.data.chan_nr = chan_nr;
+ l1sap->u.data.fn = fn;
+ }
+
+ return l1sap_up(trx, l1sap);
+ }
gsm_fn2gsmtime(&g_time, rts_ind->u32Fn);
@@ -389,57 +661,6 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1,
g_time.t1, g_time.t2, g_time.t3,
get_value_string(femtobts_l1sapi_names, rts_ind->sapi));
- /* In case of TCH downlink trasnmission, we already have a l1
- * primitive msgb pre-allocated and pre-formatted in the
- * dl_tch_queue. All we need to do is to pull it off the queue
- * and transmit it */
- switch (rts_ind->sapi) {
- case GsmL1_Sapi_TchF:
- case GsmL1_Sapi_TchH:
- /* resolve the L2 entity using rts_ind->hLayer2 */
- lchan = l1if_hLayer_to_lchan(trx, rts_ind->hLayer2);
- if (!lchan)
- break;
-
- if (!lchan->loopback && lchan->abis_ip.rtp_socket) {
- osmo_rtp_socket_poll(lchan->abis_ip.rtp_socket);
- /* FIXME: we _assume_ that we never miss TDMA
- * frames and that we always get to this point
- * for every to-be-transmitted voice frame. A
- * better solution would be to compute
- * rx_user_ts based on how many TDMA frames have
- * elapsed since the last call */
- lchan->abis_ip.rtp_socket->rx_user_ts += GSM_RTP_DURATION;
- }
- /* get a msgb from the dl_tx_queue */
- resp_msg = msgb_dequeue(&lchan->dl_tch_queue);
- /* if there is none, try to generate empty TCH frame
- * like AMR SID_BAD */
- if (!resp_msg) {
- LOGP(DL1C, LOGL_DEBUG, "%s DL TCH Tx queue underrun\n",
- gsm_lchan_name(lchan));
- resp_msg = gen_empty_tch_msg(lchan);
- /* if there really is none, break here and send empty */
- if (!resp_msg)
- break;
- }
-
- /* fill header */
- data_req_from_rts_ind(msgb_l1prim(resp_msg), rts_ind);
- /* actually transmit it */
- goto tx;
- break;
- case GsmL1_Sapi_Pdtch:
- case GsmL1_Sapi_Pacch:
- return pcu_tx_rts_req(&trx->ts[rts_ind->u8Tn], 0,
- rts_ind->u32Fn, rts_ind->u16Arfcn, rts_ind->u8BlockNbr);
- case GsmL1_Sapi_Ptcch:
- return pcu_tx_rts_req(&trx->ts[rts_ind->u8Tn], 1,
- rts_ind->u32Fn, rts_ind->u16Arfcn, rts_ind->u8BlockNbr);
- default:
- break;
- }
-
/* in all other cases, we need to allocate a new PH-DATA.ind
* primitive msgb and start to fill it */
resp_msg = l1p_msgb_alloc();
@@ -451,6 +672,7 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1,
switch (rts_ind->sapi) {
case GsmL1_Sapi_Sch:
+ gsm_fn2gsmtime(&g_time, rts_ind->u32Fn);
/* compute T3prime */
t3p = (g_time.t3 - 1) / 10;
/* fill SCH burst with data */
@@ -460,87 +682,6 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1,
msu_param->u8Buffer[2] = (g_time.t1 << 7) | (g_time.t2 << 2) | (t3p
>> 1);
msu_param->u8Buffer[3] = (t3p & 1);
break;
- case GsmL1_Sapi_Bcch:
- /* get them from bts->si_buf[] */
- si = bts_sysinfo_get(bts, &g_time);
- if (si)
- memcpy(msu_param->u8Buffer, si, GSM_MACBLOCK_LEN);
- else
- memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN);
- break;
- case GsmL1_Sapi_Sacch:
- /* resolve the L2 entity using rts_ind->hLayer2 */
- lchan = l1if_hLayer_to_lchan(trx, rts_ind->hLayer2);
- le = &lchan->lapdm_ch.lapdm_acch;
- /* if the DSP is taking care of power control
- * (ul_power_target==0), then this value will be
- * overridden. */
- msu_param->u8Buffer[0] = lchan->ms_power;
- rc = lapdm_phsap_dequeue_prim(le, &pp);
- if (rc < 0) {
- /* No SACCH data from LAPDM pending, send SACCH filling */
- uint8_t *si = lchan_sacch_get(lchan, &g_time);
- if (si) {
- /* The +2 is empty space where the DSP inserts the L1 hdr */
- memcpy(msu_param->u8Buffer+2, si, GSM_MACBLOCK_LEN-2);
- } else
- memcpy(msu_param->u8Buffer+2, fill_frame, GSM_MACBLOCK_LEN-2);
- } else {
- /* The +2 is empty space where the DSP inserts the L1 hdr */
- memcpy(msu_param->u8Buffer+2, pp.oph.msg->data, GSM_MACBLOCK_LEN-2);
- msgb_free(pp.oph.msg);
- }
- break;
- case GsmL1_Sapi_Sdcch:
- /* resolve the L2 entity using rts_ind->hLayer2 */
- lchan = l1if_hLayer_to_lchan(trx, rts_ind->hLayer2);
- le = &lchan->lapdm_ch.lapdm_dcch;
- rc = lapdm_phsap_dequeue_prim(le, &pp);
- if (rc < 0)
- memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN);
- else {
- memcpy(msu_param->u8Buffer, pp.oph.msg->data, GSM_MACBLOCK_LEN);
- /* check if it is a RR CIPH MODE CMD. if yes, enable RX ciphering */
- check_for_ciph_cmd(fl1, pp.oph.msg, lchan);
- msgb_free(pp.oph.msg);
- }
- break;
- case GsmL1_Sapi_Agch:
- /* special queue of messages from IMM ASS CMD */
- {
- struct msgb *msg = bts_agch_dequeue(bts);
- if (!msg)
- memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN);
- else {
- memcpy(msu_param->u8Buffer, msg->data, msg->len);
- msgb_free(msg);
- }
- }
- break;
- case GsmL1_Sapi_Pch:
- rc = paging_gen_msg(btsb->paging_state, msu_param->u8Buffer, &g_time);
- break;
- case GsmL1_Sapi_TchF:
- case GsmL1_Sapi_TchH:
- /* only hit in case we have a RTP underflow, as real TCH
- * frames are handled way above */
- goto empty_frame;
- break;
- case GsmL1_Sapi_FacchF:
- case GsmL1_Sapi_FacchH:
- /* resolve the L2 entity using rts_ind->hLayer2 */
- lchan = l1if_hLayer_to_lchan(trx, rts_ind->hLayer2);
- le = &lchan->lapdm_ch.lapdm_dcch;
- rc = lapdm_phsap_dequeue_prim(le, &pp);
- if (rc < 0)
- goto empty_frame;
- else {
- memcpy(msu_param->u8Buffer, pp.oph.msg->data, GSM_MACBLOCK_LEN);
- /* check if it is a RR CIPH MODE CMD. if yes, enable RX ciphering */
- check_for_ciph_cmd(fl1, pp.oph.msg, lchan);
- msgb_free(pp.oph.msg);
- }
- break;
case GsmL1_Sapi_Prach:
goto empty_frame;
break;
@@ -548,13 +689,12 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1,
memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN);
break;
}
-tx:
-
- tx_to_gsmtap(fl1, resp_msg);
+tx:
/* transmit */
osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], resp_msg);
+ msgb_free(l1p_msg);
return 0;
empty_frame:
@@ -564,143 +704,38 @@ empty_frame:
goto tx;
}
-static int handle_mph_time_ind(struct femtol1_hdl *fl1,
- GsmL1_MphTimeInd_t *time_ind)
-{
- struct gsm_bts_trx *trx = fl1->priv;
- struct gsm_bts *bts = trx->bts;
- struct gsm_bts_role_bts *btsb = bts->role;
-
- int frames_expired = time_ind->u32Fn - fl1->gsm_time.fn;
-
- /* update time on PCU interface */
- pcu_tx_time_ind(time_ind->u32Fn);
-
- /* Update our data structures with the current GSM time */
- gsm_fn2gsmtime(&fl1->gsm_time, time_ind->u32Fn);
-
- /* check if the measurement period of some lchan has ended
- * and pre-compute the respective measurement */
- trx_meas_check_compute(fl1->priv, time_ind->u32Fn -1);
-
- /* increment the primitive count for the alive timer */
- fl1->alive_prim_cnt++;
-
- /* increment number of RACH slots that have passed by since the
- * last time indication */
- if (trx == bts->c0) {
- unsigned int num_rach_per_frame;
- /* 27 / 51 taken from TS 05.01 Figure 3 */
- if (bts->c0->ts[0].pchan == GSM_PCHAN_CCCH_SDCCH4)
- num_rach_per_frame = 27;
- else
- num_rach_per_frame = 51;
-
- btsb->load.rach.total += frames_expired * num_rach_per_frame;
- }
-
- return 0;
-}
-
-/* determine LAPDm entity inside LAPDm channel for given L1 sapi */
-static struct lapdm_entity *le_by_l1_sapi(struct lapdm_channel *lc, GsmL1_Sapi_t sapi)
-{
- switch (sapi) {
- case GsmL1_Sapi_Sacch:
- return &lc->lapdm_acch;
- default:
- return &lc->lapdm_dcch;
- }
-}
-
-static uint8_t gen_link_id(GsmL1_Sapi_t l1_sapi, uint8_t lapdm_sapi)
-{
- uint8_t c_bits = 0;
-
- if (l1_sapi == GsmL1_Sapi_Sacch)
- c_bits = 0x40;
-
- return c_bits | (lapdm_sapi & 7);
-}
-
-static void dump_meas_res(int ll, GsmL1_MeasParam_t *m)
-{
- LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, "
- "BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality,
- m->fBer, m->i16BurstTiming);
-}
-
-static int process_meas_res(struct gsm_lchan *lchan, GsmL1_MeasParam_t *m)
-{
- struct bts_ul_meas ulm;
-
- /* in the GPRS case we are not interested in measurement
- * processing. The PCU will take care of it */
- if (lchan->type == GSM_LCHAN_PDTCH)
- return 0;
-
- ulm.ta_offs_qbits = m->i16BurstTiming;
- ulm.ber10k = (unsigned int) (m->fBer * 100);
- ulm.inv_rssi = (uint8_t) (m->fRssi * -1);
-
- return lchan_new_ul_meas(lchan, &ulm);
-}
-
-/* process radio link timeout counter S */
-static void radio_link_timeout(struct gsm_lchan *lchan, int bad_frame)
-{
- struct gsm_bts_role_bts *btsb = lchan->ts->trx->bts->role;
-
- /* if link loss criterion already reached */
- if (lchan->s == 0) {
- DEBUGP(DMEAS, "%s radio link counter S already 0.\n",
- gsm_lchan_name(lchan));
- return;
- }
-
- if (bad_frame) {
- /* count down radio link counter S */
- lchan->s--;
- DEBUGP(DMEAS, "%s counting down radio link counter S=%d\n",
- gsm_lchan_name(lchan), lchan->s);
- if (lchan->s == 0)
- rsl_tx_conn_fail(lchan, RSL_ERR_RADIO_LINK_FAIL);
- return;
- }
-
- if (lchan->s < btsb->radio_link_timeout) {
- /* count up radio link counter S */
- lchan->s += 2;
- if (lchan->s > btsb->radio_link_timeout)
- lchan->s = btsb->radio_link_timeout;
- DEBUGP(DMEAS, "%s counting up radio link counter S=%d\n",
- gsm_lchan_name(lchan), lchan->s);
- }
-}
-
static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_ind,
struct msgb *l1p_msg)
{
struct gsm_bts_trx *trx = fl1->priv;
- struct osmo_phsap_prim pp;
- struct gsm_lchan *lchan;
- struct lapdm_entity *le;
- struct msgb *msg;
- int rc = 0;
-
- ul_to_gsmtap(fl1, l1p_msg);
+ struct osmo_phsap_prim *l1sap;
+ uint8_t chan_nr, link_id;
+ uint32_t fn;
+ uint8_t *data, len;
+ int rc;
- lchan = l1if_hLayer_to_lchan(fl1->priv, data_ind->hLayer2);
- if (!lchan) {
- LOGP(DL1C, LOGL_ERROR, "unable to resolve lchan by hLayer2\n");
- return -ENODEV;
+ /* chan_nr and link_id */
+ chan_nr = chan_nr_by_sapi(trx->ts[data_ind->u8Tn].pchan, data_ind->sapi,
+ data_ind->subCh, data_ind->u8Tn, data_ind->u32Fn);
+ if (!chan_nr) {
+ LOGP(DL1C, LOGL_ERROR, "PH-DATA-INDICATION for unknown sapi "
+ "%d\n", data_ind->sapi);
+ return ENOTSUP;
}
+ fn = data_ind->u32Fn;
+ if (data_ind->sapi == GsmL1_Sapi_Sacch)
+ link_id = 0x40;
+ else
+ link_id = 0;
- process_meas_res(lchan, &data_ind->measParam);
+ /* uplink measurement */
+ process_meas_res(trx, chan_nr, &data_ind->measParam);
if (data_ind->measParam.fLinkQuality < fl1->min_qual_norm
- && data_ind->msgUnitParam.u8Size != 0)
- return 0;
+ && data_ind->msgUnitParam.u8Size != 0) {
+ msgb_free(l1p_msg);
+ return 0;
+ }
DEBUGP(DL1C, "Rx PH-DATA.ind %s (hL2 %08x): %s",
get_value_string(femtobts_l1sapi_names, data_ind->sapi),
@@ -709,165 +744,85 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1,
GsmL1_PhDataInd_t *data_i
data_ind->msgUnitParam.u8Size));
dump_meas_res(LOGL_DEBUG, &data_ind->measParam);
- switch (data_ind->sapi) {
- case GsmL1_Sapi_Sacch:
- radio_link_timeout(lchan, (data_ind->msgUnitParam.u8Size == 0));
- if (data_ind->msgUnitParam.u8Size == 0)
- break;
- /* save the SACCH L1 header in the lchan struct for RSL MEAS RES */
- if (data_ind->msgUnitParam.u8Size < 2) {
- LOGP(DL1C, LOGL_NOTICE, "SACCH with size %u<2 !?!\n",
- data_ind->msgUnitParam.u8Size);
- break;
- }
- /* Some brilliant engineer decided that the ordering of
- * fields on the Um interface is different from the
- * order of fields in RLS. See TS 04.04 (Chapter 7.2)
- * vs. TS 08.58 (Chapter 9.3.10). */
- lchan->meas.l1_info[0] = data_ind->msgUnitParam.u8Buffer[0] << 3;
- lchan->meas.l1_info[0] |= ((data_ind->msgUnitParam.u8Buffer[0] >> 5) &
1) << 2;
- lchan->meas.l1_info[1] = data_ind->msgUnitParam.u8Buffer[1];
- lchan->meas.flags |= LC_UL_M_F_L1_VALID;
- /* fall-through */
- case GsmL1_Sapi_Sdcch:
- case GsmL1_Sapi_FacchF:
- case GsmL1_Sapi_FacchH:
- /* Check and Re-check for the SACCH */
- if (data_ind->msgUnitParam.u8Size == 0) {
- LOGP(DL1C, LOGL_NOTICE, "%s %s data is null.\n",
- gsm_lchan_name(lchan),
- get_value_string(femtobts_l1sapi_names, data_ind->sapi));
- break;
- }
-
- /* if this is the first valid message after enabling Rx
- * decryption, we have to enable Tx encryption */
- if (lchan->ciph_state == LCHAN_CIPH_RX_CONF) {
- /* HACK: check if it's an I frame, in order to
- * ignore some still buffered/queued UI frames received
- * before decryption was enabled */
- if (data_ind->msgUnitParam.u8Buffer[0] == 0x01 &&
- (data_ind->msgUnitParam.u8Buffer[1] & 0x01) == 0) {
- l1if_set_ciphering(fl1, lchan, 1);
- lchan->ciph_state = LCHAN_CIPH_TXRX_REQ;
- }
- }
-
- /* SDCCH, SACCH and FACCH all go to LAPDm */
- le = le_by_l1_sapi(&lchan->lapdm_ch, data_ind->sapi);
- /* allocate and fill LAPDm primitive */
- msg = msgb_alloc_headroom(128, 64, "PH-DATA.ind");
- osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA,
- PRIM_OP_INDICATION, msg);
-
- /* copy over actual MAC block */
- msg->l2h = msgb_put(msg, data_ind->msgUnitParam.u8Size);
- memcpy(msg->l2h, data_ind->msgUnitParam.u8Buffer,
- data_ind->msgUnitParam.u8Size);
-
- /* LAPDm requires those... */
- pp.u.data.chan_nr = gsm_lchan2chan_nr(lchan);
- pp.u.data.link_id = gen_link_id(data_ind->sapi, 0);
-
- /* feed into the LAPDm code of libosmogsm */
- rc = lapdm_phsap_up(&pp.oph, le);
- break;
- case GsmL1_Sapi_TchF:
- case GsmL1_Sapi_TchH:
- /* TCH speech frame handling */
- rc = l1if_tch_rx(lchan, l1p_msg);
- break;
- case GsmL1_Sapi_Pdtch:
- case GsmL1_Sapi_Pacch:
- /* drop incomplete UL block */
- if (!data_ind->msgUnitParam.u8Size
- || data_ind->msgUnitParam.u8Buffer[0]
- != GsmL1_PdtchPlType_Full)
- break;
- /* PDTCH / PACCH frame handling */
- rc = pcu_tx_data_ind(&trx->ts[data_ind->u8Tn], 0,
- data_ind->u32Fn, data_ind->u16Arfcn,
- data_ind->u8BlockNbr,
- data_ind->msgUnitParam.u8Buffer + 1,
- data_ind->msgUnitParam.u8Size - 1,
- (int8_t) (data_ind->measParam.fRssi));
- break;
- case GsmL1_Sapi_Ptcch:
- /* PTCCH frame handling */
- rc = pcu_tx_data_ind(&trx->ts[data_ind->u8Tn], 1,
- data_ind->u32Fn, data_ind->u16Arfcn,
- data_ind->u8BlockNbr,
- data_ind->msgUnitParam.u8Buffer,
- data_ind->msgUnitParam.u8Size,
- (int8_t) (data_ind->measParam.fRssi));
- break;
- default:
- LOGP(DL1C, LOGL_NOTICE, "Rx PH-DATA.ind for unknown L1 SAPI %s\n",
- get_value_string(femtobts_l1sapi_names, data_ind->sapi));
- break;
- }
-
- return rc;
+ /* check for TCH */
+ if (data_ind->sapi == GsmL1_Sapi_TchF
+ || data_ind->sapi == GsmL1_Sapi_TchH) {
+ /* TCH speech frame handling */
+ return l1if_tch_rx(trx, chan_nr, l1p_msg);
+ }
+
+ /* get data pointer and length */
+ data = data_ind->msgUnitParam.u8Buffer;
+ len = data_ind->msgUnitParam.u8Size;
+ /* pull lower header part before data */
+ msgb_pull(l1p_msg, data - l1p_msg->data);
+ /* trim remaining data to it's size, to get rid of upper header part */
+ rc = msgb_trim(l1p_msg, len);
+ if (rc < 0)
+ MSGB_ABORT(l1p_msg, "No room for primitive data\n");
+ l1p_msg->l2h = l1p_msg->data;
+ /* push new l1 header */
+ l1p_msg->l1h = msgb_push(l1p_msg, sizeof(*l1sap));
+ /* fill header */
+ l1sap = msgb_l1sap_prim(l1p_msg);
+ osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, PRIM_OP_INDICATION,
+ l1p_msg);
+ l1sap->u.data.link_id = link_id;
+ l1sap->u.data.chan_nr = chan_nr;
+ l1sap->u.data.fn = fn;
+
+ return l1sap_up(trx, l1sap);
}
-static int handle_ph_ra_ind(struct femtol1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind)
+static int handle_ph_ra_ind(struct femtol1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
+ struct msgb *l1p_msg)
{
struct gsm_bts_trx *trx = fl1->priv;
struct gsm_bts *bts = trx->bts;
struct gsm_bts_role_bts *btsb = bts->role;
- struct osmo_phsap_prim pp;
- struct lapdm_channel *lc;
- uint8_t acc_delay;
+ struct osmo_phsap_prim *l1sap;
+ uint32_t fn;
+ uint8_t ra, acc_delay;
+ int rc;
/* increment number of busy RACH slots, if required */
if (trx == bts->c0 &&
ra_ind->measParam.fRssi >= btsb->load.rach.busy_thresh)
btsb->load.rach.busy++;
- if (ra_ind->measParam.fLinkQuality < fl1->min_qual_rach)
+ if (ra_ind->measParam.fLinkQuality < fl1->min_qual_rach) {
+ msgb_free(l1p_msg);
return 0;
+ }
- /* increment number of RACH slots with valid RACH burst */
- if (trx == bts->c0)
- btsb->load.rach.access++;
-
- DEBUGP(DL1C, "Rx PH-RA.ind");
dump_meas_res(LOGL_DEBUG, &ra_ind->measParam);
- lc = get_lapdm_chan_by_hl2(fl1->priv, ra_ind->hLayer2);
- if (!lc) {
- LOGP(DL1C, LOGL_ERROR, "unable to resolve LAPD channel by hLayer2\n");
- return -ENODEV;
+ if (ra_ind->msgUnitParam.u8Size != 1) {
+ LOGP(DL1C, LOGL_ERROR, "PH-RACH-INDICATION has %d bits\n",
+ ra_ind->sapi);
+ msgb_free(l1p_msg);
+ return 0;
}
+ fn = ra_ind->u32Fn;
+ ra = ra_ind->msgUnitParam.u8Buffer[0];
/* check for under/overflow / sign */
if (ra_ind->measParam.i16BurstTiming < 0)
acc_delay = 0;
else
acc_delay = ra_ind->measParam.i16BurstTiming >> 2;
- if (acc_delay > btsb->max_ta) {
- LOGP(DL1C, LOGL_INFO, "ignoring RACH request %u > max_ta(%u)\n",
- acc_delay, btsb->max_ta);
- return 0;
- }
-
- /* check for packet access */
- if (trx == bts->c0
- && (ra_ind->msgUnitParam.u8Buffer[0] & 0xf0) == 0x70) {
- LOGP(DL1C, LOGL_INFO, "RACH for packet access\n");
- return pcu_tx_rach_ind(bts, ra_ind->measParam.i16BurstTiming,
- ra_ind->msgUnitParam.u8Buffer[0], ra_ind->u32Fn);
- }
-
- osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_RACH,
- PRIM_OP_INDICATION, NULL);
-
- pp.u.rach_ind.ra = ra_ind->msgUnitParam.u8Buffer[0];
- pp.u.rach_ind.fn = ra_ind->u32Fn;
- pp.u.rach_ind.acc_delay = acc_delay;
-
- return lapdm_phsap_up(&pp.oph, &lc->lapdm_dcch);
+ rc = msgb_trim(l1p_msg, sizeof(*l1sap));
+ if (rc < 0)
+ MSGB_ABORT(l1p_msg, "No room for primitive data\n");
+ l1sap = msgb_l1sap_prim(l1p_msg);
+ osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION,
+ l1p_msg);
+ l1sap->u.rach_ind.ra = ra;
+ l1sap->u.rach_ind.acc_delay = acc_delay;
+ l1sap->u.rach_ind.fn = fn;
+
+ return l1sap_up(trx, l1sap);
}
/* handle any random indication from the L1 */
@@ -885,21 +840,19 @@ static int l1if_handle_ind(struct femtol1_hdl *fl1, struct msgb
*msg)
case GsmL1_PrimId_PhConnectInd:
break;
case GsmL1_PrimId_PhReadyToSendInd:
- rc = handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd);
+ return handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd, msg);
break;
case GsmL1_PrimId_PhDataInd:
- rc = handle_ph_data_ind(fl1, &l1p->u.phDataInd, msg);
+ return handle_ph_data_ind(fl1, &l1p->u.phDataInd, msg);
break;
case GsmL1_PrimId_PhRaInd:
- rc = handle_ph_ra_ind(fl1, &l1p->u.phRaInd);
+ return handle_ph_ra_ind(fl1, &l1p->u.phRaInd, msg);
break;
default:
break;
}
- /* Special return value '1' means: do not free */
- if (rc != 1)
- msgb_free(msg);
+ msgb_free(msg);
return rc;
}
@@ -1203,46 +1156,6 @@ int l1if_set_trace_flags(struct femtol1_hdl *hdl, uint32_t flags)
return osmo_wqueue_enqueue(&hdl->write_q[MQ_SYS_WRITE], msg);
}
-/* send packet data request to L1 */
-int l1if_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn,
- uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len)
-{
- struct gsm_bts_trx *trx = ts->trx;
- struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
- struct msgb *msg;
- GsmL1_Prim_t *l1p;
- GsmL1_PhDataReq_t *data_req;
- GsmL1_MsgUnitParam_t *msu_param;
- struct gsm_time g_time;
-
- gsm_fn2gsmtime(&g_time, fn);
-
- DEBUGP(DL1P, "TX packet data %02u/%02u/%02u is_ptcch=%d trx=%d ts=%d "
- "block_nr=%d, arfcn=%d, len=%d\n", g_time.t1, g_time.t2,
- g_time.t3, is_ptcch, ts->trx->nr, ts->nr, block_nr, arfcn, len);
-
- msg = l1p_msgb_alloc();
- l1p = msgb_l1prim(msg);
- l1p->id = GsmL1_PrimId_PhDataReq;
- data_req = &l1p->u.phDataReq;
- data_req->hLayer1 = fl1h->hLayer1;
- data_req->sapi = (is_ptcch) ? GsmL1_Sapi_Ptcch : GsmL1_Sapi_Pdtch;
- data_req->subCh = GsmL1_SubCh_NA;
- data_req->u8BlockNbr = block_nr;
- data_req->u8Tn = ts->nr;
- data_req->u32Fn = fn;
- msu_param = &data_req->msgUnitParam;
- msu_param->u8Size = len;
- memcpy(msu_param->u8Buffer, data, len);
-
- tx_to_gsmtap(fl1h, msg);
-
- /* transmit */
- osmo_wqueue_enqueue(&fl1h->write_q[MQ_L1_WRITE], msg);
-
- return 0;
-}
-
struct femtol1_hdl *l1if_open(void *priv)
{
struct femtol1_hdl *fl1h;
@@ -1290,10 +1203,6 @@ struct femtol1_hdl *l1if_open(void *priv)
return NULL;
}
- fl1h->gsmtap = gsmtap_source_init("localhost", GSMTAP_UDP_PORT, 1);
- if (fl1h->gsmtap)
- gsmtap_source_add_sink(fl1h->gsmtap);
-
return fl1h;
}
@@ -1304,8 +1213,3 @@ int l1if_close(struct femtol1_hdl *fl1h)
return 0;
}
-/* temporary stub to make this patch compile */
-int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
-{
- return -ENOTSUP;
-}
diff --git a/src/osmo-bts-sysmo/l1_if.h b/src/osmo-bts-sysmo/l1_if.h
index 7947ea2..388f1fb 100644
--- a/src/osmo-bts-sysmo/l1_if.h
+++ b/src/osmo-bts-sysmo/l1_if.h
@@ -50,9 +50,6 @@ struct femtol1_hdl {
char *calib_path;
struct llist_head wlc_list;
- struct gsmtap_inst *gsmtap;
- uint32_t gsmtap_sapi_mask;
-
void *priv; /* user reference */
struct osmo_timer_list alive_timer;
@@ -97,7 +94,9 @@ uint32_t l1if_lchan_to_hLayer(struct gsm_lchan *lchan);
struct gsm_lchan *l1if_hLayer_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer);
/* tch.c */
-int l1if_tch_rx(struct gsm_lchan *lchan, struct msgb *l1p_msg);
+void l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len,
+ const uint8_t *rtp_pl, unsigned int rtp_pl_len);
+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);
@@ -106,6 +105,12 @@ int l1if_set_ciphering(struct femtol1_hdl *fl1h,
struct gsm_lchan *lchan,
int dir_downlink);
+/* channel control */
+int l1if_rsl_chan_act(struct gsm_lchan *lchan);
+int l1if_rsl_chan_rel(struct gsm_lchan *lchan);
+int l1if_rsl_deact_sacch(struct gsm_lchan *lchan);
+int l1if_rsl_mode_modify(struct gsm_lchan *lchan);
+
/* calibration loading */
int calib_load(struct femtol1_hdl *fl1h);
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c
index 7e7f761..465f99d 100644
--- a/src/osmo-bts-sysmo/main.c
+++ b/src/osmo-bts-sysmo/main.c
@@ -45,6 +45,7 @@
#include <osmo-bts/vty.h>
#include <osmo-bts/bts_model.h>
#include <osmo-bts/pcu_if.h>
+#include <osmo-bts/l1sap.h>
#define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock"
@@ -254,6 +255,7 @@ int main(int argc, char **argv)
bts_log_init(NULL);
+ bts = gsm_bts_alloc(tall_bts_ctx);
vty_init(&bts_vty_info);
bts_vty_init(bts, &bts_log_info);
@@ -271,7 +273,6 @@ int main(int argc, char **argv)
}
}
- bts = gsm_bts_alloc(tall_bts_ctx);
if (bts_init(bts) < 0) {
fprintf(stderr, "unable to to open bts\n");
exit(1);
diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c
index aeddad7..399576e 100644
--- a/src/osmo-bts-sysmo/oml.c
+++ b/src/osmo-bts-sysmo/oml.c
@@ -35,11 +35,27 @@
#include <osmo-bts/amr.h>
#include <osmo-bts/bts.h>
#include <osmo-bts/bts_model.h>
+#include <osmo-bts/l1sap.h>
#include "l1_if.h"
#include "femtobts.h"
#include "utils.h"
+static int mph_info_chan_confirm(struct gsm_lchan *lchan,
+ enum osmo_mph_info_type type, uint8_t cause)
+{
+ struct osmo_phsap_prim l1sap;
+
+ memset(&l1sap, 0, sizeof(l1sap));
+ osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_CONFIRM,
+ NULL);
+ l1sap.u.info.type = type;
+ l1sap.u.info.u.act_cnf.chan_nr = gsm_lchan2chan_nr(lchan);
+ l1sap.u.info.u.act_cnf.cause = cause;
+
+ return l1sap_up(lchan->ts->trx, &l1sap);
+}
+
enum sapi_cmd_type {
SAPI_CMD_ACTIVATE,
SAPI_CMD_CONFIG_CIPHERING,
@@ -858,7 +874,7 @@ static int sapi_activate_cb(struct gsm_lchan *lchan, int status)
if (status != GsmL1_Status_Success) {
lchan_set_state(lchan, LCHAN_S_BROKEN);
sapi_clear_queue(&lchan->sapi_cmds);
- rsl_tx_chan_act_nack(lchan, RSL_ERR_EQUIPMENT_FAIL);
+ mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, RSL_ERR_EQUIPMENT_FAIL);
return -1;
}
@@ -869,7 +885,7 @@ static int sapi_activate_cb(struct gsm_lchan *lchan, int status)
return 0;
lchan_set_state(lchan, LCHAN_S_ACTIVE);
- rsl_tx_chan_act_ack(lchan);
+ mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, 0);
/* set the initial ciphering parameters for both directions */
l1if_set_ciphering(fl1h, lchan, 0);
@@ -891,7 +907,6 @@ static void enqueue_sapi_act_cmd(struct gsm_lchan *lchan, int sapi,
int dir)
int lchan_activate(struct gsm_lchan *lchan, enum gsm_lchan_state lchan_state)
{
- struct gsm_bts_role_bts *btsb = lchan->ts->trx->bts->role;
struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx);
const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type];
unsigned int i;
@@ -920,8 +935,6 @@ int lchan_activate(struct gsm_lchan *lchan, enum gsm_lchan_state
lchan_state)
#warning "FIXME: Should this be in sapi_activate_cb?"
lchan_init_lapdm(lchan);
- lchan->s = btsb->radio_link_timeout;
-
return 0;
}
@@ -1177,7 +1190,7 @@ int l1if_set_ciphering(struct femtol1_hdl *fl1h,
return 0;
}
-int bts_model_rsl_mode_modify(struct gsm_lchan *lchan)
+int l1if_rsl_mode_modify(struct gsm_lchan *lchan)
{
if (lchan->state != LCHAN_S_ACTIVE)
return -1;
@@ -1286,7 +1299,7 @@ static int sapi_deactivate_cb(struct gsm_lchan *lchan, int status)
gsm_lchan_name(lchan));
lchan_set_state(lchan, LCHAN_S_BROKEN);
sapi_clear_queue(&lchan->sapi_cmds);
- rsl_tx_rf_rel_ack(lchan);
+ mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0);
return -1;
}
@@ -1298,7 +1311,7 @@ static int sapi_deactivate_cb(struct gsm_lchan *lchan, int status)
return 0;
lchan_set_state(lchan, LCHAN_S_NONE);
- rsl_tx_rf_rel_ack(lchan);
+ mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0);
return 0;
}
@@ -1358,7 +1371,7 @@ static int lchan_deactivate_sapis(struct gsm_lchan *lchan)
LOGP(DL1C, LOGL_ERROR, "%s all SAPIs already released?\n",
gsm_lchan_name(lchan));
lchan_set_state(lchan, LCHAN_S_BROKEN);
- rsl_tx_rf_rel_ack(lchan);
+ mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0);
}
return res;
@@ -1398,13 +1411,6 @@ static int lchan_deactivate_sacch(struct gsm_lchan *lchan)
return 0;
}
-struct gsm_time *bts_model_get_time(struct gsm_bts *bts)
-{
- struct femtol1_hdl *fl1h = trx_femtol1_hdl(bts->c0);
-
- return &fl1h->gsm_time;
-}
-
/* callback from OML */
int bts_model_check_oml(struct gsm_bts *bts, uint8_t msg_type,
struct tlv_parsed *old_attr, struct tlv_parsed *new_attr,
@@ -1457,17 +1463,17 @@ int bts_model_chg_adm_state(struct gsm_bts *bts, struct
gsm_abis_mo *mo,
mo->nm_state.administrative = adm_state;
return oml_mo_statechg_ack(mo);
}
-int bts_model_rsl_chan_act(struct gsm_lchan *lchan, struct tlv_parsed *tp)
+
+int l1if_rsl_chan_act(struct gsm_lchan *lchan)
{
//uint8_t mode = *TLVP_VAL(tp, RSL_IE_CHAN_MODE);
//uint8_t type = *TLVP_VAL(tp, RSL_IE_ACT_TYPE);
- lchan->sacch_deact = 0;
lchan_activate(lchan, LCHAN_S_ACT_REQ);
return 0;
}
-int bts_model_rsl_chan_rel(struct gsm_lchan *lchan)
+int l1if_rsl_chan_rel(struct gsm_lchan *lchan)
{
/* A duplicate RF Release Request, ignore it */
if (lchan->state == LCHAN_S_REL_REQ)
@@ -1476,7 +1482,7 @@ int bts_model_rsl_chan_rel(struct gsm_lchan *lchan)
return 0;
}
-int bts_model_rsl_deact_sacch(struct gsm_lchan *lchan)
+int l1if_rsl_deact_sacch(struct gsm_lchan *lchan)
{
/* Only de-activate the SACCH if the lchan is active */
if (lchan->state != LCHAN_S_ACTIVE)
diff --git a/src/osmo-bts-sysmo/sysmobts_vty.c b/src/osmo-bts-sysmo/sysmobts_vty.c
index 61deda4..998ed80 100644
--- a/src/osmo-bts-sysmo/sysmobts_vty.c
+++ b/src/osmo-bts-sysmo/sysmobts_vty.c
@@ -83,34 +83,6 @@ DEFUN(cfg_bts_no_auto_band, cfg_bts_no_auto_band_cmd,
return CMD_SUCCESS;
}
-DEFUN(cfg_trx_gsmtap_sapi, cfg_trx_gsmtap_sapi_cmd,
- "HIDDEN", "HIDDEN")
-{
- struct gsm_bts_trx *trx = vty->index;
- struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
- int sapi;
-
- sapi = get_string_value(femtobts_l1sapi_names, argv[0]);
-
- fl1h->gsmtap_sapi_mask |= (1 << sapi);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trx_no_gsmtap_sapi, cfg_trx_no_gsmtap_sapi_cmd,
- "HIDDEN", "HIDDEN")
-{
- struct gsm_bts_trx *trx = vty->index;
- struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
- int sapi;
-
- sapi = get_string_value(femtobts_l1sapi_names, argv[0]);
-
- fl1h->gsmtap_sapi_mask &= ~(1 << sapi);
-
- return CMD_SUCCESS;
-}
-
DEFUN(cfg_trx_clkcal_def, cfg_trx_clkcal_def_cmd,
"clock-calibration default",
"Set the clock calibration value\n" "Default Clock DAC value\n")
@@ -397,44 +369,6 @@ DEFUN(set_tx_power, set_tx_power_cmd,
return CMD_SUCCESS;
}
-DEFUN(loopback, loopback_cmd,
- "trx <0-0> <0-7> loopback <0-1>",
- TRX_STR
- "Timeslot number\n"
- "Set TCH loopback\n"
- "Logical Channel Number\n")
-{
- int trx_nr = atoi(argv[0]);
- int ts_nr = atoi(argv[1]);
- int lchan_nr = atoi(argv[2]);
- struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr);
- struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
- struct gsm_lchan *lchan = &ts->lchan[lchan_nr];
-
- lchan->loopback = 1;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(no_loopback, no_loopback_cmd,
- "no trx <0-0> <0-7> loopback <0-1>",
- NO_STR TRX_STR
- "Timeslot number\n"
- "Set TCH loopback\n"
- "Logical Channel Number\n")
-{
- int trx_nr = atoi(argv[0]);
- int ts_nr = atoi(argv[1]);
- int lchan_nr = atoi(argv[2]);
- struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr);
- struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
- struct gsm_lchan *lchan = &ts->lchan[lchan_nr];
-
- lchan->loopback = 0;
-
- return CMD_SUCCESS;
-}
-
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
{
@@ -447,7 +381,6 @@ void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
{
struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
- int i;
vty_out(vty, " clock-calibration %d%s", fl1h->clk_cal,
VTY_NEWLINE);
@@ -463,14 +396,6 @@ void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx
*trx)
VTY_NEWLINE);
vty_out(vty, " min-qual-norm %.0f%s", fl1h->min_qual_norm * 10.0f,
VTY_NEWLINE);
-
- for (i = 0; i < 32; i++) {
- if (fl1h->gsmtap_sapi_mask & (1 << i)) {
- const char *name = get_value_string(femtobts_l1sapi_names, i);
- vty_out(vty, " gsmtap-sapi %s%s", osmo_str_tolower(name),
- VTY_NEWLINE);
- }
- }
}
int bts_model_vty_init(struct gsm_bts *bts)
@@ -492,20 +417,6 @@ int bts_model_vty_init(struct gsm_bts *bts)
NO_STR TRX_STR DSP_TRACE_F_STR,
"\n", "", 0);
- cfg_trx_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts, femtobts_l1sapi_names,
- "gsmtap-sapi (",
- "|",")", VTY_DO_LOWER);
- cfg_trx_gsmtap_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, femtobts_l1sapi_names,
- "GSMTAP SAPI\n",
- "\n", "", 0);
-
- cfg_trx_no_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts,
femtobts_l1sapi_names,
- "no gsmtap-sapi (",
- "|",")", VTY_DO_LOWER);
- cfg_trx_no_gsmtap_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, femtobts_l1sapi_names,
- NO_STR "GSMTAP SAPI\n",
- "\n", "", 0);
-
install_element_ve(&show_dsp_trace_f_cmd);
install_element_ve(&show_sys_info_cmd);
install_element_ve(&show_trx_clksrc_cmd);
@@ -515,9 +426,6 @@ int bts_model_vty_init(struct gsm_bts *bts)
install_element(ENABLE_NODE, &activate_lchan_cmd);
install_element(ENABLE_NODE, &set_tx_power_cmd);
- install_element(ENABLE_NODE, &loopback_cmd);
- install_element(ENABLE_NODE, &no_loopback_cmd);
-
install_element(BTS_NODE, &cfg_bts_auto_band_cmd);
install_element(BTS_NODE, &cfg_bts_no_auto_band_cmd);
@@ -525,8 +433,6 @@ int bts_model_vty_init(struct gsm_bts *bts)
install_element(TRX_NODE, &cfg_trx_clkcal_def_cmd);
install_element(TRX_NODE, &cfg_trx_clksrc_cmd);
install_element(TRX_NODE, &cfg_trx_cal_path_cmd);
- install_element(TRX_NODE, &cfg_trx_gsmtap_sapi_cmd);
- install_element(TRX_NODE, &cfg_trx_no_gsmtap_sapi_cmd);
install_element(TRX_NODE, &cfg_trx_ul_power_target_cmd);
install_element(TRX_NODE, &cfg_trx_min_qual_rach_cmd);
install_element(TRX_NODE, &cfg_trx_min_qual_norm_cmd);
diff --git a/src/osmo-bts-sysmo/tch.c b/src/osmo-bts-sysmo/tch.c
index c6c782f..da62c84 100644
--- a/src/osmo-bts-sysmo/tch.c
+++ b/src/osmo-bts-sysmo/tch.c
@@ -39,6 +39,7 @@
#include <osmo-bts/bts.h>
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/measurement.h>
+#include <osmo-bts/l1sap.h>
#include <sysmocom/femtobts/superfemto.h>
#include <sysmocom/femtobts/gsml1prim.h>
@@ -416,7 +417,7 @@ static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t
*rtp_payload,
#define RTP_MSGB_ALLOC_SIZE 512
-/*! \brief call-back function for incoming RTP
+/*! \brief function for incoming RTP via TCH.req
* \param rs RTP Socket
* \param[in] rtp_pl buffer containing RTP payload
* \param[in] rtp_pl_len length of \a rtp_pl
@@ -428,14 +429,9 @@ static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t
*rtp_payload,
* yet, as things like the frame number, etc. are unknown at the time we
* pre-fill the primtive.
*/
-void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
- unsigned int rtp_pl_len)
+void l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len,
+ const uint8_t *rtp_pl, unsigned int rtp_pl_len)
{
- struct gsm_lchan *lchan = rs->priv;
- struct msgb *msg;
- GsmL1_Prim_t *l1p;
- GsmL1_PhDataReq_t *data_req;
- GsmL1_MsgUnitParam_t *msu_param;
uint8_t *payload_type;
uint8_t *l1_payload;
int rc;
@@ -443,22 +439,8 @@ void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t
*rtp_pl,
DEBUGP(DRTP, "%s RTP IN: %s\n", gsm_lchan_name(lchan),
osmo_hexdump(rtp_pl, rtp_pl_len));
- /* skip processing of incoming RTP frames if we are in loopback mode */
- if (lchan->loopback)
- return;
-
- msg = l1p_msgb_alloc();
- if (!msg) {
- LOGP(DRTP, LOGL_ERROR, "%s: Failed to allocate Rx payload.\n",
- gsm_lchan_name(lchan));
- return;
- }
-
- l1p = msgb_l1prim(msg);
- data_req = &l1p->u.phDataReq;
- msu_param = &data_req->msgUnitParam;
- payload_type = &msu_param->u8Buffer[0];
- l1_payload = &msu_param->u8Buffer[1];
+ payload_type = &data[0];
+ l1_payload = &data[1];
switch (lchan->tch_mode) {
case GSM48_CMODE_SPEECH_V1:
@@ -493,40 +475,17 @@ void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t
*rtp_pl,
if (rc < 0) {
LOGP(DRTP, LOGL_ERROR, "%s unable to parse RTP payload\n",
gsm_lchan_name(lchan));
- msgb_free(msg);
return;
}
- msu_param->u8Size = rc + 1;
+ *len = rc + 1;
DEBUGP(DRTP, "%s RTP->L1: %s\n", gsm_lchan_name(lchan),
- osmo_hexdump(msu_param->u8Buffer, msu_param->u8Size));
-
- /* make sure the number of entries in the dl_tch_queue is never
- * more than 3 */
- {
- struct msgb *tmp;
- int count = 0;
-
- llist_for_each_entry(tmp, &lchan->dl_tch_queue, list)
- count++;
-
- DEBUGP(DL1C, "%s DL TCH queue length = %u\n",
- gsm_lchan_name(lchan), count);
-
- while (count >= 2) {
- tmp = msgb_dequeue(&lchan->dl_tch_queue);
- msgb_free(tmp);
- count--;
- }
- }
-
- /* enqueue msgb to be transmitted to L1 */
- msgb_enqueue(&lchan->dl_tch_queue, msg);
+ osmo_hexdump(data, *len));
}
/*! \brief receive a traffic L1 primitive for a given lchan */
-int l1if_tch_rx(struct gsm_lchan *lchan, struct msgb *l1p_msg)
+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;
@@ -534,50 +493,15 @@ int l1if_tch_rx(struct gsm_lchan *lchan, struct msgb *l1p_msg)
uint8_t *payload = data_ind->msgUnitParam.u8Buffer + 1;
uint8_t payload_len;
struct msgb *rmsg = NULL;
+ struct gsm_lchan *lchan =
&trx->ts[L1SAP_CHAN2TS(chan_nr)].lchan[l1sap_chan2ss(chan_nr)];
if (data_ind->msgUnitParam.u8Size < 1) {
- LOGP(DL1C, LOGL_ERROR, "%s Rx Payload size 0\n",
- gsm_lchan_name(lchan));
+ LOGP(DL1C, LOGL_ERROR, "chan_nr %d Rx Payload size 0\n",
+ chan_nr);
return -EINVAL;
}
payload_len = data_ind->msgUnitParam.u8Size - 1;
- if (lchan->loopback) {
- GsmL1_Prim_t *rl1p;
- GsmL1_PhDataReq_t *data_req;
- GsmL1_MsgUnitParam_t *msu_param;
-
- struct msgb *tmp;
- int count = 0;
-
- /* generate a new msgb from the paylaod */
- rmsg = l1p_msgb_alloc();
- if (!rmsg)
- return -ENOMEM;
-
- rl1p = msgb_l1prim(rmsg);
- data_req = &rl1p->u.phDataReq;
- msu_param = &data_req->msgUnitParam;
-
- memcpy(msu_param->u8Buffer,
- data_ind->msgUnitParam.u8Buffer,
- data_ind->msgUnitParam.u8Size);
- msu_param->u8Size = data_ind->msgUnitParam.u8Size;
-
- /* make sure the queue doesn't get too long */
- llist_for_each_entry(tmp, &lchan->dl_tch_queue, list)
- count++;
- while (count >= 1) {
- tmp = msgb_dequeue(&lchan->dl_tch_queue);
- msgb_free(tmp);
- count--;
- }
-
- msgb_enqueue(&lchan->dl_tch_queue, rmsg);
-
- return 0;
- }
-
switch (payload_type) {
case GsmL1_TchPlType_Fr:
#if defined(L1_HAS_EFR) && defined(USE_L1_RTP_MODE)
@@ -624,13 +548,20 @@ int l1if_tch_rx(struct gsm_lchan *lchan, struct msgb *l1p_msg)
}
if (rmsg) {
+ struct osmo_phsap_prim *l1sap;
+
LOGP(DL1C, LOGL_DEBUG, "%s Rx -> RTP: %s\n",
gsm_lchan_name(lchan), osmo_hexdump(rmsg->data, rmsg->len));
- /* hand rmsg to RTP code for transmission */
- if (lchan->abis_ip.rtp_socket)
- osmo_rtp_send_frame(lchan->abis_ip.rtp_socket,
- rmsg->data, rmsg->len, 160);
- msgb_free(rmsg);
+
+ /* add l1sap header */
+ rmsg->l2h = rmsg->data;
+ msgb_push(rmsg, sizeof(*l1sap));
+ rmsg->l1h = rmsg->data;
+ l1sap = msgb_l1sap_prim(rmsg);
+ osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_INDICATION, rmsg);
+ l1sap->u.tch.chan_nr = chan_nr;
+
+ return l1sap_up(trx, l1sap);
}
return 0;
--
1.8.1.5