diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2013-08-30 08:48:38 +0200 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2014-04-05 12:48:11 +0200 |
commit | 639eb730e5a007ae69cd8d389c990e22f92057dc (patch) | |
tree | 840318a553a4c41fa2709ed090eaa4e2cce86cb7 /src | |
parent | 05ea21a82c05be3cff91fc7c78443df9c4105c67 (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.
Diffstat (limited to 'src')
-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 | 152 |
3 files changed, 172 insertions, 77 deletions
diff --git a/src/common/l1sap.c b/src/common/l1sap.c index 99825311..90709099 100644 --- a/src/common/l1sap.c +++ b/src/common/l1sap.c @@ -90,6 +90,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 " @@ -153,6 +166,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) @@ -203,6 +264,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; @@ -225,3 +289,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 412c3d59..080f682f 100644 --- a/src/osmo-bts-sysmo/l1_if.c +++ b/src/osmo-bts-sysmo/l1_if.c @@ -390,7 +390,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 @@ -501,6 +511,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; } @@ -593,13 +632,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; } @@ -831,6 +863,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); @@ -840,14 +876,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), @@ -929,27 +973,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 */ @@ -960,7 +984,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, @@ -1035,8 +1084,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; @@ -1480,46 +1528,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; -} - /* get those femtol1_hdl.hw_info elements that sre in EEPROM */ static int get_hwinfo_eeprom(struct femtol1_hdl *fl1h) { |