From: Andreas Eversberg <[email protected]>

This part moves TCH handling from osmo-bts-sysmo to common part. The RTP
handling is done at the common part, so they can be used by other BTS
models.
---
 include/osmo-bts/bts_model.h |   3 -
 src/common/l1sap.c           | 151 ++++++++++++++++++++++++++++++++++++++
 src/common/rsl.c             |   3 +-
 src/osmo-bts-sysmo/l1_if.c   | 169 ++++++++++++++++++++++++++++---------------
 src/osmo-bts-sysmo/l1_if.h   |   4 +-
 src/osmo-bts-sysmo/tch.c     | 120 ++++++++----------------------
 6 files changed, 294 insertions(+), 156 deletions(-)

diff --git a/include/osmo-bts/bts_model.h b/include/osmo-bts/bts_model.h
index a219d5b..a0f4542 100644
--- a/include/osmo-bts/bts_model.h
+++ b/include/osmo-bts/bts_model.h
@@ -28,9 +28,6 @@ int bts_model_chg_adm_state(struct gsm_bts *bts, struct 
gsm_abis_mo *mo,
 int bts_model_trx_deact_rf(struct gsm_bts_trx *trx);
 int bts_model_trx_close(struct gsm_bts_trx *trx);
 
-void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
-                        unsigned int rtp_pl_len);
-
 int bts_model_vty_init(struct gsm_bts *bts);
 
 void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts);
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index c631860..9068bb8 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -286,6 +286,72 @@ static int l1sap_handover_rach(struct gsm_bts_trx *trx,
        return 0;
 }
 
+/* TCH-RTS-IND prim recevied from bts model */
+static int l1sap_tch_rts_ind(struct gsm_bts_trx *trx,
+       struct osmo_phsap_prim *l1sap, struct ph_tch_param *rts_ind)
+{
+       struct msgb *resp_msg;
+       struct osmo_phsap_prim *resp_l1sap, empty_l1sap;
+       struct gsm_time g_time;
+       struct gsm_lchan *lchan;
+       uint8_t chan_nr;
+       uint8_t tn, ss;
+       uint32_t fn;
+
+       chan_nr = rts_ind->chan_nr;
+       fn = rts_ind->fn;
+       tn = L1SAP_CHAN2TS(chan_nr);
+
+       gsm_fn2gsmtime(&g_time, fn);
+
+       DEBUGP(DL1P, "Rx TCH-RTS.ind %02u/%02u/%02u chan_nr=%d\n",
+               g_time.t1, g_time.t2, g_time.t3, chan_nr);
+
+       /* get timeslot and subslot */
+       tn = L1SAP_CHAN2TS(chan_nr);
+       if (L1SAP_IS_CHAN_TCHH(chan_nr))
+               ss = L1SAP_CHAN2SS_TCHH(chan_nr); /* TCH/H */
+       else
+               ss = 0; /* TCH/F */
+       lchan = &trx->ts[tn].lchan[ss];
+
+       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 (!resp_msg) {
+               LOGP(DL1P, LOGL_DEBUG, "%s DL TCH Tx queue underrun\n",
+                       gsm_lchan_name(lchan));
+               resp_l1sap = &empty_l1sap;
+       } else {
+               resp_msg->l2h = resp_msg->data;
+               msgb_push(resp_msg, sizeof(*resp_l1sap));
+               resp_msg->l1h = resp_msg->data;
+               resp_l1sap = msgb_l1sap_prim(resp_msg);
+       }
+
+       memset(resp_l1sap, 0, sizeof(*resp_l1sap));
+       osmo_prim_init(&resp_l1sap->oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_REQUEST,
+               resp_msg);
+       resp_l1sap->u.tch.chan_nr = chan_nr;
+       resp_l1sap->u.tch.fn = fn;
+
+       DEBUGP(DL1P, "Tx TCH.req %02u/%02u/%02u chan_nr=%d\n",
+               g_time.t1, g_time.t2, g_time.t3, chan_nr);
+
+       l1sap_down(trx, resp_l1sap);
+
+       return 0;
+}
+
 /* DATA received from bts model */
 static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
         struct osmo_phsap_prim *l1sap, struct ph_data_param *data_ind)
@@ -334,6 +400,57 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
        return 0;
 }
 
+/* TCH received from bts model */
+static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim 
*l1sap,
+       struct ph_tch_param *tch_ind)
+{
+       struct msgb *msg = l1sap->oph.msg;
+       struct gsm_time g_time;
+       struct gsm_lchan *lchan;
+       uint8_t tn, ss, chan_nr;
+       uint32_t fn;
+
+       chan_nr = tch_ind->chan_nr;
+       fn = tch_ind->fn;
+       tn = L1SAP_CHAN2TS(chan_nr);
+       if (L1SAP_IS_CHAN_TCHH(chan_nr))
+               ss = L1SAP_CHAN2SS_TCHH(chan_nr);
+       else
+               ss = 0;
+       lchan = &trx->ts[tn].lchan[ss];
+
+       gsm_fn2gsmtime(&g_time, fn);
+
+       DEBUGP(DL1P, "Rx TCH.ind %02u/%02u/%02u chan_nr=%d\n",
+               g_time.t1, g_time.t2, g_time.t3, chan_nr);
+
+       msgb_pull(msg, sizeof(*l1sap));
+
+       /* hand msg to RTP code for transmission */
+       if (lchan->abis_ip.rtp_socket)
+               osmo_rtp_send_frame(lchan->abis_ip.rtp_socket,
+                       msg->data, msg->len, 160);
+
+       /* if loopback is enabled, also queue received RTP data */
+       if (lchan->loopback) {
+               struct msgb *tmp;
+               int count = 0;
+
+                /* 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, msg);
+       }
+
+       return 0;
+}
+
 /* RACH received from bts model */
 static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx,
         struct osmo_phsap_prim *l1sap, struct ph_rach_ind_param *rach_ind)
@@ -389,9 +506,15 @@ int l1sap_up(struct gsm_bts_trx *trx, struct 
osmo_phsap_prim *l1sap)
        case OSMO_PRIM(PRIM_PH_RTS, PRIM_OP_INDICATION):
                rc = l1sap_ph_rts_ind(trx, l1sap, &l1sap->u.data);
                break;
+       case OSMO_PRIM(PRIM_TCH_RTS, PRIM_OP_INDICATION):
+               rc = l1sap_tch_rts_ind(trx, l1sap, &l1sap->u.tch);
+               break;
        case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_INDICATION):
                rc = l1sap_ph_data_ind(trx, l1sap, &l1sap->u.data);
                break;
+       case OSMO_PRIM(PRIM_TCH, PRIM_OP_INDICATION):
+               rc = l1sap_tch_ind(trx, l1sap, &l1sap->u.tch);
+               break;
        case OSMO_PRIM(PRIM_PH_RACH, PRIM_OP_INDICATION):
                rc = l1sap_ph_rach_ind(trx, l1sap, &l1sap->u.rach_ind);
                break;
@@ -441,6 +564,34 @@ int l1sap_pdch_req(struct gsm_bts_trx_ts *ts, int 
is_ptcch, uint32_t fn,
        return l1sap_down(ts->trx, l1sap);
 }
 
+/*! \brief call-back function for incoming RTP */
+void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
+                     unsigned int rtp_pl_len)
+{
+       struct gsm_lchan *lchan = rs->priv;
+       struct msgb *msg, *tmp;
+       struct osmo_phsap_prim *l1sap;
+       int count = 0;
+
+       msg = l1sap_msgb_alloc(rtp_pl_len);
+       if (!msg)
+               return;
+       memcpy(msgb_put(msg, rtp_pl_len), rtp_pl, rtp_pl_len);
+       msgb_pull(msg, sizeof(*l1sap));
+
+
+        /* make sure the queue doesn't get too long */
+       llist_for_each_entry(tmp, &lchan->dl_tch_queue, list)
+       count++;
+       while (count >= 2) {
+               tmp = msgb_dequeue(&lchan->dl_tch_queue);
+               msgb_free(tmp);
+               count--;
+       }
+
+       msgb_enqueue(&lchan->dl_tch_queue, msg);
+}
+
 static int l1sap_chan_act_dact_modify(struct gsm_bts_trx *trx, uint8_t chan_nr,
                enum osmo_mph_info_type type, uint8_t sacch_only)
 {
diff --git a/src/common/rsl.c b/src/common/rsl.c
index 1a52c6e..dc49177 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -42,7 +42,6 @@
 #include <osmo-bts/oml.h>
 #include <osmo-bts/amr.h>
 #include <osmo-bts/signal.h>
-#include <osmo-bts/bts_model.h>
 #include <osmo-bts/measurement.h>
 #include <osmo-bts/pcu_if.h>
 #include <osmo-bts/handover.h>
@@ -1395,7 +1394,7 @@ static int rsl_rx_ipac_XXcx(struct msgb *msg)
                                          OSMO_RTP_P_JITBUF,
                                          btsb->rtp_jitter_buf_ms);
                lchan->abis_ip.rtp_socket->priv = lchan;
-               lchan->abis_ip.rtp_socket->rx_cb = &bts_model_rtp_rx_cb;
+               lchan->abis_ip.rtp_socket->rx_cb = &l1sap_rtp_rx_cb;
 
                if (connect_ip && connect_port) {
                        /* if CRCX specifies a remote IP, we can bind()
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c
index 4a398ea..5f7b8cf 100644
--- a/src/osmo-bts-sysmo/l1_if.c
+++ b/src/osmo-bts-sysmo/l1_if.c
@@ -38,8 +38,6 @@
 #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>
@@ -532,6 +530,93 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct 
msgb *msg,
        return 0;
 }
 
+static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg,
+                      struct osmo_phsap_prim *l1sap)
+{
+       struct femtol1_hdl *fl1 = trx_femtol1_hdl(trx);
+       struct gsm_lchan *lchan;
+       uint32_t u32Fn;
+       uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi, ss;
+       uint8_t chan_nr;
+       GsmL1_Prim_t *l1p;
+       struct msgb *nmsg;
+
+       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)
+                       return -ENOMEM;
+               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)
+                       return -ENOMEM;
+       }
+
+       l1p = msgb_l1prim(nmsg);
+
+       /* 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);
+
+       msgb_free(msg);
+       return 0;
+}
+
 static int mph_info_req(struct gsm_bts_trx *trx, struct msgb *msg,
                        struct osmo_phsap_prim *l1sap)
 {
@@ -580,6 +665,9 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct 
osmo_phsap_prim *l1sap)
        case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST):
                rc = ph_data_req(trx, msg, l1sap);
                break;
+       case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST):
+               rc = ph_tch_req(trx, msg, l1sap);
+               break;
        case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST):
                rc = mph_info_req(trx, msg, l1sap);
                break;
@@ -646,6 +734,12 @@ static uint8_t chan_nr_by_sapi(enum gsm_phys_chan_config 
pchan,
                        return 0;
                }
                break;
+       case GsmL1_Sapi_TchF:
+               cbits = 0x01;
+               break;
+       case GsmL1_Sapi_TchH:
+               cbits = 0x02 + subCh;
+               break;
        case GsmL1_Sapi_Ptcch:
                if (!L1SAP_IS_PTCCH(u32Fn)) {
                        LOGP(DL1C, LOGL_FATAL, "Not expecting PTCCH at frame "
@@ -690,7 +784,6 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl 
*fl1,
        uint8_t chan_nr, link_id;
        uint32_t fn;
 
-
        /* check if primitive should be handled by 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);
@@ -701,11 +794,19 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl 
*fl1,
                if (rc < 0)
                        MSGB_ABORT(l1p_msg, "No room for primitive\n");
                l1sap = msgb_l1sap_prim(l1p_msg);
-               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;
+               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);
        }
@@ -716,50 +817,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;
-       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();
@@ -820,12 +877,6 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl 
*fl1,
                        msgb_free(pp.oph.msg);
                }
                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 */
@@ -1044,7 +1095,7 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, 
GsmL1_PhDataInd_t *data_i
        case GsmL1_Sapi_TchF:
        case GsmL1_Sapi_TchH:
                /* TCH speech frame handling */
-               rc = l1if_tch_rx(lchan, l1p_msg);
+               rc = l1if_tch_rx(trx, chan_nr, l1p_msg);
                break;
        case GsmL1_Sapi_Pdtch:
        case GsmL1_Sapi_Pacch:
diff --git a/src/osmo-bts-sysmo/l1_if.h b/src/osmo-bts-sysmo/l1_if.h
index b0a624d..6f58e95 100644
--- a/src/osmo-bts-sysmo/l1_if.h
+++ b/src/osmo-bts-sysmo/l1_if.h
@@ -110,7 +110,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);
 
diff --git a/src/osmo-bts-sysmo/tch.c b/src/osmo-bts-sysmo/tch.c
index d101b47..997b45b 100644
--- a/src/osmo-bts-sysmo/tch.c
+++ b/src/osmo-bts-sysmo/tch.c
@@ -40,6 +40,7 @@
 #include <osmo-bts/gsm_data.h>
 #include <osmo-bts/measurement.h>
 #include <osmo-bts/amr.h>
+#include <osmo-bts/l1sap.h>
 
 #include <sysmocom/femtobts/superfemto.h>
 #include <sysmocom/femtobts/gsml1prim.h>
@@ -422,7 +423,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
@@ -434,34 +435,18 @@ 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;
 
-       /* 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;
-       }
+       DEBUGP(DRTP, "%s RTP IN: %s\n", gsm_lchan_name(lchan),
+               osmo_hexdump(rtp_pl, rtp_pl_len));
 
-       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:
@@ -496,38 +481,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;
 
-       /* 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);
+       DEBUGP(DRTP, "%s RTP->L1: %s\n", gsm_lchan_name(lchan),
+               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;
@@ -535,50 +499,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)
@@ -622,11 +551,20 @@ int l1if_tch_rx(struct gsm_lchan *lchan, struct msgb 
*l1p_msg)
        }
 
        if (rmsg) {
-               /* 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);
+               struct osmo_phsap_prim *l1sap;
+
+               LOGP(DL1C, LOGL_DEBUG, "%s Rx -> RTP: %s\n",
+                       gsm_lchan_name(lchan), osmo_hexdump(rmsg->data, 
rmsg->len));
+
+               /* 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;
-- 
2.1.0


Reply via email to