aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-08-30 08:48:38 +0200
committerHarald Welte <laforge@gnumonks.org>2015-09-06 12:37:05 +0200
commitb199a80a9955661fbcc53bfc3044d121b7d56342 (patch)
tree062ab5d821f0db13e85a63f4e82f4370938f151d
parent370f6616ff0de8514fa2394f18ed80035faf8880 (diff)
Add PDCH messages to PH-/MPH-/TCH-SAP interface
This part moves PDTCH, PACCH and PTCCH message primitives from osmo-bts-sysmo to common part.
-rw-r--r--src/common/l1sap.c90
-rw-r--r--src/common/pcu_sock.c7
-rw-r--r--src/osmo-bts-sysmo/l1_if.c160
3 files changed, 176 insertions, 81 deletions
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index 12be383c..633a5a5b 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -91,6 +91,19 @@ static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx,
DEBUGP(DL1P, "Rx PH-RTS.ind %02u/%02u/%02u chan_nr=%d link_id=%d\n",
g_time.t1, g_time.t2, g_time.t3, chan_nr, link_id);
+ if (trx->ts[tn].pchan == GSM_PCHAN_PDCH) {
+ if (L1SAP_IS_PTCCH(rts_ind->fn)) {
+ pcu_tx_rts_req(&trx->ts[tn], 1, fn, 1 /* ARFCN */,
+ L1SAP_FN2PTCCHBLOCK(fn));
+
+ return 0;
+ }
+ pcu_tx_rts_req(&trx->ts[tn], 0, fn, 0 /* ARFCN */,
+ L1SAP_FN2MACBLOCK(fn));
+
+ return 0;
+ }
+
/* reuse PH-RTS.ind for PH-DATA.req */
if (!msg) {
LOGP(DL1P, LOGL_FATAL, "RTS without msg to be reused. Please "
@@ -155,6 +168,54 @@ static int l1sap_handover_rach(struct gsm_bts_trx *trx,
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)
+{
+ struct msgb *msg = l1sap->oph.msg;
+ struct gsm_time g_time;
+ uint8_t *data = msg->l2h;
+ int len = msgb_l2len(msg);
+ uint8_t chan_nr, link_id;
+ uint8_t tn, ss;
+ uint32_t fn;
+ int8_t rssi;
+
+ rssi = data_ind->rssi;
+ chan_nr = data_ind->chan_nr;
+ link_id = data_ind->link_id;
+ fn = data_ind->fn;
+ tn = L1SAP_CHAN2TS(chan_nr);
+ ss = l1sap_chan2ss(chan_nr);
+
+ gsm_fn2gsmtime(&g_time, fn);
+
+ DEBUGP(DL1P, "Rx PH-DATA.ind %02u/%02u/%02u chan_nr=%d link_id=%d\n",
+ g_time.t1, g_time.t2, g_time.t3, chan_nr, link_id);
+
+ if (trx->ts[tn].pchan == GSM_PCHAN_PDCH) {
+ if (len == 0)
+ return -EINVAL;
+ if (L1SAP_IS_PTCCH(fn)) {
+ pcu_tx_data_ind(&trx->ts[tn], 1, fn,
+ 0 /* ARFCN */, L1SAP_FN2PTCCHBLOCK(fn),
+ data, len, rssi);
+
+ return 0;
+ }
+ /* drop incomplete UL block */
+ if (data[0] != 7)
+ return 0;
+ /* PDTCH / PACCH frame handling */
+ pcu_tx_data_ind(&trx->ts[tn], 0, fn, 0 /* ARFCN */,
+ L1SAP_FN2MACBLOCK(fn), data + 1, len - 1, rssi);
+
+ return 0;
+ }
+
+ 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)
@@ -204,6 +265,9 @@ 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_PH_DATA, PRIM_OP_INDICATION):
+ rc = l1sap_ph_data_ind(trx, l1sap, &l1sap->u.data);
+ break;
case OSMO_PRIM(PRIM_PH_RACH, PRIM_OP_INDICATION):
rc = l1sap_ph_rach_ind(trx, l1sap, &l1sap->u.rach_ind);
break;
@@ -226,3 +290,29 @@ static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
return bts_model_l1sap_down(trx, l1sap);
}
+/* pcu (socket interface) sends us a data request primitive */
+int l1sap_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 msgb *msg;
+ struct osmo_phsap_prim *l1sap;
+ 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 = l1sap_msgb_alloc(len);
+ l1sap = msgb_l1sap_prim(msg);
+ osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, PRIM_OP_REQUEST,
+ msg);
+ l1sap->u.data.chan_nr = 0x08 | ts->nr;
+ l1sap->u.data.link_id = 0x00;
+ l1sap->u.data.fn = fn;
+ msg->l2h = msgb_put(msg, len);
+ memcpy(msg->l2h, data, len);
+
+ return l1sap_down(ts->trx, l1sap);
+}
diff --git a/src/common/pcu_sock.c b/src/common/pcu_sock.c
index a978e469..515993ed 100644
--- a/src/common/pcu_sock.c
+++ b/src/common/pcu_sock.c
@@ -40,6 +40,7 @@
#include <osmo-bts/rsl.h>
#include <osmo-bts/signal.h>
#include <osmo-bts/bts_model.h>
+#include <osmo-bts/l1sap.h>
uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx);
@@ -57,10 +58,6 @@ static const char *sapi_string[] = {
[PCU_IF_SAPI_PTCCH] = "PTCCH",
};
-/* FIXME: common l1if include ? */
-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);
-
static int pcu_sock_send(struct gsm_network *net, struct msgb *msg);
/* FIXME: move this to libosmocore */
int osmo_unixsock_listen(struct osmo_fd *bfd, int type, const char *path);
@@ -512,7 +509,7 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
}
ts = &trx->ts[data_req->ts_nr];
is_ptcch = (data_req->sapi == PCU_IF_SAPI_PTCCH);
- rc = l1if_pdch_req(ts, is_ptcch, data_req->fn, data_req->arfcn,
+ rc = l1sap_pdch_req(ts, is_ptcch, data_req->fn, data_req->arfcn,
data_req->block_nr, data_req->data, data_req->len);
break;
default:
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c
index 26c954d8..5c217d5a 100644
--- a/src/osmo-bts-sysmo/l1_if.c
+++ b/src/osmo-bts-sysmo/l1_if.c
@@ -473,7 +473,17 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
u32Fn = l1sap->u.data.fn;
u8Tn = L1SAP_CHAN2TS(chan_nr);
subCh = 0x1f;
- if (L1SAP_IS_CHAN_BCCH(chan_nr)) {
+ 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 if (L1SAP_IS_CHAN_BCCH(chan_nr)) {
sapi = GsmL1_Sapi_Bcch;
} else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) {
/* The sapi depends on DSP configuration, not
@@ -524,7 +534,10 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
}
/* send message to DSP's queue */
- osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], msg);
+ if (osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], msg) != 0) {
+ LOGP(DL1P, LOGL_ERROR, "MQ_L1_WRITE queue full. Dropping msg.\n");
+ msgb_free(msg);
+ }
return 0;
}
@@ -563,6 +576,35 @@ static uint8_t chan_nr_by_sapi(enum gsm_phys_chan_config pchan,
case GsmL1_Sapi_Pch:
cbits = 0x12;
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;
}
@@ -655,13 +697,6 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1,
/* 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;
}
@@ -901,6 +936,10 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_i
struct gsm_lchan *lchan;
struct lapdm_entity *le;
struct msgb *msg;
+ uint8_t chan_nr, link_id;
+ struct osmo_phsap_prim *l1sap;
+ uint32_t fn;
+ uint8_t *data, len;
int rc = 0;
ul_to_gsmtap(fl1, l1p_msg);
@@ -910,14 +949,22 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_i
LOGP(DL1C, LOGL_ERROR,
"unable to resolve lchan by hLayer2 for 0x%x\n",
data_ind->hLayer2);
+ msgb_free(l1p_msg);
return -ENODEV;
}
+ chan_nr = chan_nr_by_sapi(trx->ts[data_ind->u8Tn].pchan, data_ind->sapi,
+ data_ind->subCh, data_ind->u8Tn, data_ind->u32Fn);
+ fn = data_ind->u32Fn;
+ link_id = (data_ind->sapi == GsmL1_Sapi_Sacch) ? 0x40 : 0x00;
+
process_meas_res(lchan, &data_ind->measParam);
if (data_ind->measParam.fLinkQuality < fl1->min_qual_norm
- && data_ind->msgUnitParam.u8Size != 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),
@@ -996,27 +1043,7 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_i
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;
case GsmL1_Sapi_Idle:
/* nothing to send */
@@ -1027,7 +1054,32 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_i
break;
}
- return rc;
+ if (!chan_nr) {
+ msgb_free(l1p_msg);
+ return rc;
+ }
+
+ /* 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,
@@ -1107,8 +1159,7 @@ static int l1if_handle_ind(struct femtol1_hdl *fl1, struct msgb *msg)
return handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd,
msg);
case GsmL1_PrimId_PhDataInd:
- rc = handle_ph_data_ind(fl1, &l1p->u.phDataInd, msg);
- break;
+ return handle_ph_data_ind(fl1, &l1p->u.phDataInd, msg);
case GsmL1_PrimId_PhRaInd:
return handle_ph_ra_ind(fl1, &l1p->u.phRaInd, msg);
break;
@@ -1566,49 +1617,6 @@ int l1if_set_trace_flags(struct femtol1_hdl *hdl, uint32_t flags)
return 0;
}
-/* 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 */
- if (osmo_wqueue_enqueue(&fl1h->write_q[MQ_L1_WRITE], msg) != 0) {
- LOGP(DL1P, LOGL_ERROR, "MQ_L1_WRITE queue full. Dropping msg.\n");
- msgb_free(msg);
- }
-
- return 0;
-}
-
/* get those femtol1_hdl.hw_info elements that sre in EEPROM */
static int get_hwinfo_eeprom(struct femtol1_hdl *fl1h)
{