diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2013-08-30 08:48:38 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2015-09-22 16:39:03 +0200 |
commit | 75be092b99a8dd693fe7fdc35b6c124d730f66cd (patch) | |
tree | 181d8e387f1282cbc9cc766b84869eab3fa426f0 | |
parent | c9441b3c0b898d09d9e8d6ad4c616a62a905f1d7 (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.c | 90 | ||||
-rw-r--r-- | src/common/pcu_sock.c | 7 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/l1_if.c | 160 |
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) { |