aboutsummaryrefslogtreecommitdiffstats
path: root/src/pcu_l1_if.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pcu_l1_if.cpp')
-rw-r--r--src/pcu_l1_if.cpp568
1 files changed, 342 insertions, 226 deletions
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index 4186e292..fd8b3c34 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -1,6 +1,6 @@
/* pcu_l1_if.cpp
*
- * Copyright (C) 2012 Ivan Klyuchnikov
+ * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -17,63 +17,25 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
#include <string.h>
-#include <gprs_rlcmac.h>
-#include <pcu_l1_if.h>
-#include <gprs_debug.h>
-#include <bitvector.h>
-#include <gsmL1prim.h>
+#include <errno.h>
+#include <assert.h>
#include <sys/socket.h>
-#include <linux/in.h>
+#include <sys/un.h>
extern "C" {
#include <osmocom/core/talloc.h>
-#include <osmocom/core/write_queue.h>
-#include <osmocom/core/socket.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/msgb.h>
}
-#define MAX_UDP_LENGTH 1500
-
-#define msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h)
-
-struct femtol1_hdl {
- struct gsm_time gsm_time;
- uint32_t hLayer1; /* handle to the L1 instance in the DSP */
- uint32_t dsp_trace_f;
- uint16_t clk_cal;
- struct llist_head wlc_list;
-
- void *priv; /* user reference */
-
- struct osmo_timer_list alive_timer;
- unsigned int alive_prim_cnt;
-
- struct osmo_fd read_ofd; /* osmo file descriptors */
- struct osmo_wqueue write_q;
-
- struct {
- uint16_t arfcn;
- uint8_t tn;
- uint8_t tsc;
- uint16_t ta;
- } channel_info;
-
-};
-
-struct l1fwd_hdl {
- struct sockaddr_storage remote_sa;
- socklen_t remote_sa_len;
-
- struct osmo_wqueue udp_wq;
-
- struct femtol1_hdl *fl1h;
-};
-
-struct l1fwd_hdl *l1fh = talloc_zero(NULL, struct l1fwd_hdl);
-
-struct pcu_l1if_bts pcu_l1if_bts;
+#include <gprs_rlcmac.h>
+#include <pcu_l1_if.h>
+#include <gprs_debug.h>
+#include <gprs_bssgp_pcu.h>
+#include <pcuif_proto.h>
// Variable for storage current FN.
int frame_number;
@@ -88,244 +50,398 @@ void set_current_fn(int fn)
frame_number = fn;
}
-struct msgb *l1p_msgb_alloc(void)
+/*
+ * PCU messages
+ */
+
+struct msgb *pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr)
{
- struct msgb *msg = msgb_alloc(sizeof(GsmL1_Prim_t), "l1_prim");
+ struct msgb *msg;
+ struct gsm_pcu_if *pcu_prim;
- if (msg)
- msg->l1h = msgb_put(msg, sizeof(GsmL1_Prim_t));
+ msg = msgb_alloc(sizeof(struct gsm_pcu_if), "pcu_sock_tx");
+ if (!msg)
+ return NULL;
+ msgb_put(msg, sizeof(struct gsm_pcu_if));
+ pcu_prim = (struct gsm_pcu_if *) msg->data;
+ pcu_prim->msg_type = msg_type;
+ pcu_prim->bts_nr = bts_nr;
return msg;
}
-// Send RLC/MAC block to OpenBTS.
-void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn,
- uint32_t fn, uint8_t block_nr)
+static int pcu_tx_act_req(uint8_t trx, uint8_t ts, uint8_t activate)
{
- struct msgb *nmsg = l1p_msgb_alloc();
- GsmL1_Prim_t *prim = msgb_l1prim(nmsg);
-
- prim->id = GsmL1_PrimId_PhDataReq;
- prim->u.phDataReq.sapi = GsmL1_Sapi_Pdtch;
- memcpy(prim->u.phDataReq.msgUnitParam.u8Buffer, msg->data, msg->len);
- prim->u.phDataReq.msgUnitParam.u8Size = msg->len;
- osmo_wqueue_enqueue(&l1fh->udp_wq, nmsg);
- msgb_free(msg);
+ struct msgb *msg;
+ struct gsm_pcu_if *pcu_prim;
+ struct gsm_pcu_if_act_req *act_req;
+
+ LOGP(DL1IF, LOGL_INFO, "Sending %s request: trx=%d ts=%d\n",
+ (activate) ? "activate" : "deactivate", trx, ts);
+
+ msg = pcu_msgb_alloc(PCU_IF_MSG_ACT_REQ, 0);
+ if (!msg)
+ return -ENOMEM;
+ pcu_prim = (struct gsm_pcu_if *) msg->data;
+ act_req = &pcu_prim->u.act_req;
+ act_req->activate = activate;
+ act_req->trx_nr = trx;
+ act_req->ts_nr = ts;
+
+ return pcu_sock_send(msg);
}
-void pcu_l1if_tx_agch(bitvec * block, int len)
+static int pcu_tx_data_req(uint8_t trx, uint8_t ts, uint8_t sapi,
+ uint16_t arfcn, uint32_t fn, uint8_t block_nr, uint8_t *data,
+ uint8_t len)
{
- struct msgb *msg = l1p_msgb_alloc();
- GsmL1_Prim_t *prim = msgb_l1prim(msg);
-
- prim->id = GsmL1_PrimId_PhDataReq;
- prim->u.phDataReq.sapi = GsmL1_Sapi_Agch;
- bitvec_pack(block, prim->u.phDataReq.msgUnitParam.u8Buffer);
- prim->u.phDataReq.msgUnitParam.u8Size = len;
- osmo_wqueue_enqueue(&l1fh->udp_wq, msg);
+ struct msgb *msg;
+ struct gsm_pcu_if *pcu_prim;
+ struct gsm_pcu_if_data *data_req;
+
+ LOGP(DL1IF, LOGL_DEBUG, "Sending data request: trx=%d ts=%d sapi=%d "
+ "arfcn=%d fn=%d block=%d data=%s\n", trx, ts, sapi, arfcn, fn,
+ block_nr, osmo_hexdump(data, len));
+
+ msg = pcu_msgb_alloc(PCU_IF_MSG_DATA_REQ, 0);
+ if (!msg)
+ return -ENOMEM;
+ pcu_prim = (struct gsm_pcu_if *) msg->data;
+ data_req = &pcu_prim->u.data_req;
+
+ data_req->sapi = sapi;
+ data_req->fn = fn;
+ data_req->arfcn = arfcn;
+ data_req->trx_nr = trx;
+ data_req->ts_nr = ts;
+ data_req->block_nr = block_nr;
+ memcpy(data_req->data, data, len);
+ data_req->len = len;
+
+ return pcu_sock_send(msg);
}
-void pcu_l1if_tx_pch(bitvec * block, int len)
+void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn,
+ uint32_t fn, uint8_t block_nr)
{
- struct msgb *msg = l1p_msgb_alloc();
- GsmL1_Prim_t *prim = msgb_l1prim(msg);
- prim->id = GsmL1_PrimId_PhDataReq;
- prim->u.phDataReq.sapi = GsmL1_Sapi_Pch;
- bitvec_pack(block, prim->u.phDataReq.msgUnitParam.u8Buffer);
- prim->u.phDataReq.msgUnitParam.u8Size = len;
- osmo_wqueue_enqueue(&l1fh->udp_wq, msg);
+ pcu_tx_data_req(trx, ts, PCU_IF_SAPI_PDTCH, arfcn, fn, block_nr,
+ msg->data, msg->len);
+ msgb_free(msg);
}
-int pcu_l1if_rx_pdch(GsmL1_PhDataInd_t *data_ind)
+void pcu_l1if_tx_ptcch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn,
+ uint32_t fn, uint8_t block_nr)
{
- bitvec *block = bitvec_alloc(data_ind->msgUnitParam.u8Size);
- bitvec_unpack(block, data_ind->msgUnitParam.u8Buffer);
- gprs_rlcmac_rcv_block(block);
- bitvec_free(block);
-
- return 0;
+ pcu_tx_data_req(trx, ts, PCU_IF_SAPI_PTCCH, arfcn, fn, block_nr,
+ msg->data, msg->len);
+ msgb_free(msg);
}
-static int handle_ph_connect_ind(struct femtol1_hdl *fl1, GsmL1_PhConnectInd_t *connect_ind)
+void pcu_l1if_tx_agch(bitvec * block, int plen)
{
- pcu_l1if_bts.trx[0].arfcn = connect_ind->u16Arfcn;
- pcu_l1if_bts.trx[0].ts[connect_ind->u8Tn].enable = 1;
- pcu_l1if_bts.trx[0].ts[connect_ind->u8Tn].tsc = connect_ind->u8Tsc;
- (l1fh->fl1h)->channel_info.arfcn = connect_ind->u16Arfcn;
- (l1fh->fl1h)->channel_info.tn = connect_ind->u8Tn;
- (l1fh->fl1h)->channel_info.tsc = connect_ind->u8Tsc;
- LOGP(DL1IF, LOGL_NOTICE, "RX: [ PCU <- BTS ] PhConnectInd: ARFCN: %u TN: %u TSC: %u \n",
- connect_ind->u16Arfcn, (unsigned)connect_ind->u8Tn, (unsigned)connect_ind->u8Tsc);
+ uint8_t data[23]; /* prefix PLEN */
+
+ /* FIXME: why does OpenBTS has no PLEN and no fill in message? */
+ bitvec_pack(block, data + 1);
+ data[0] = (plen << 2) | 0x01;
+ pcu_tx_data_req(0, 0, PCU_IF_SAPI_AGCH, 0, 0, 0, data, 23);
+}
- return 0;
+void pcu_l1if_tx_pch(bitvec * block, int plen, char *imsi)
+{
+ uint8_t data[23+3]; /* prefix PLEN */
+
+ /* paging group */
+ if (!imsi || strlen(imsi) < 3)
+ return;
+ imsi += strlen(imsi) - 3;
+ data[0] = imsi[0];
+ data[1] = imsi[1];
+ data[2] = imsi[2];
+
+ bitvec_pack(block, data + 3+1);
+ data[3] = (plen << 2) | 0x01;
+ pcu_tx_data_req(0, 0, PCU_IF_SAPI_PCH, 0, 0, 0, data, 23+3);
}
-static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1, GsmL1_PhReadyToSendInd_t *readytosend_ind)
+static void pcu_l1if_tx_bcch(uint8_t *data, int len)
{
- gprs_rlcmac_rcv_rts_block(0,0, (l1fh->fl1h)->channel_info.arfcn, readytosend_ind->u32Fn, 0);
- return 1;
+ pcu_tx_data_req(0, 0, PCU_IF_SAPI_BCCH, 0, 0, 0, data, len);
}
-static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_ind)
+static int pcu_rx_data_ind(struct gsm_pcu_if_data *data_ind)
{
int rc = 0;
+
+ LOGP(DL1IF, LOGL_DEBUG, "Data indication received: sapi=%d arfcn=%d "
+ "block=%d data=%s\n", data_ind->sapi,
+ data_ind->arfcn, data_ind->block_nr,
+ osmo_hexdump(data_ind->data, data_ind->len));
+
switch (data_ind->sapi) {
- case GsmL1_Sapi_Rach:
- break;
- case GsmL1_Sapi_Pdtch:
- case GsmL1_Sapi_Pacch:
- pcu_l1if_rx_pdch(data_ind);
- break;
- case GsmL1_Sapi_Pbcch:
- case GsmL1_Sapi_Pagch:
- case GsmL1_Sapi_Ppch:
- case GsmL1_Sapi_Pnch:
- case GsmL1_Sapi_Ptcch:
- case GsmL1_Sapi_Prach:
+ case PCU_IF_SAPI_PDTCH:
+ rc = gprs_rlcmac_rcv_block(data_ind->data, data_ind->len,
+ data_ind->fn);
break;
default:
- LOGP(DL1IF, LOGL_NOTICE, "Rx PH-DATA.ind for unknown L1 SAPI %u \n", data_ind->sapi);
- break;
+ LOGP(DL1IF, LOGL_ERROR, "Received PCU data indication with "
+ "unsupported sapi %d\n", data_ind->sapi);
+ rc = -EINVAL;
}
return rc;
}
-static int handle_ph_ra_ind(struct femtol1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind)
+static int pcu_rx_rts_req(struct gsm_pcu_if_rts_req *rts_req)
{
int rc = 0;
- (l1fh->fl1h)->channel_info.ta = ra_ind->measParam.i16BurstTiming;
- rc = gprs_rlcmac_rcv_rach(ra_ind->msgUnitParam.u8Buffer[0], ra_ind->u32Fn, ra_ind->measParam.i16BurstTiming);
- return rc;
-}
-/* handle any random indication from the L1 */
-int pcu_l1if_handle_l1prim(struct femtol1_hdl *fl1, struct msgb *msg)
-{
- GsmL1_Prim_t *l1p = msgb_l1prim(msg);
- int rc = 0;
+ LOGP(DL1IF, LOGL_DEBUG, "RTS request received: trx=%d ts=%d sapi=%d "
+ "arfcn=%d fn=%d block=%d\n", rts_req->trx_nr, rts_req->ts_nr,
+ rts_req->sapi, rts_req->arfcn, rts_req->fn, rts_req->block_nr);
- switch (l1p->id) {
- case GsmL1_PrimId_PhConnectInd:
- rc = handle_ph_connect_ind(fl1, &l1p->u.phConnectInd);
- break;
- case GsmL1_PrimId_PhReadyToSendInd:
- rc = handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd);
+ switch (rts_req->sapi) {
+ case PCU_IF_SAPI_PDTCH:
+ gprs_rlcmac_rcv_rts_block(rts_req->trx_nr, rts_req->ts_nr,
+ rts_req->arfcn, rts_req->fn, rts_req->block_nr);
break;
- case GsmL1_PrimId_PhDataInd:
- rc = handle_ph_data_ind(fl1, &l1p->u.phDataInd);
- break;
- case GsmL1_PrimId_PhRaInd:
- rc = handle_ph_ra_ind(fl1, &l1p->u.phRaInd);
+ case PCU_IF_SAPI_PTCCH:
+ /* FIXME */
+ {
+ struct msgb *msg = msgb_alloc(23, "l1_prim");
+ memset(msgb_put(msg, 23), 0x2b, 23);
+ pcu_l1if_tx_ptcch(msg, rts_req->trx_nr, rts_req->ts_nr,
+ rts_req->arfcn, rts_req->fn, rts_req->block_nr);
+ }
break;
default:
- break;
+ LOGP(DL1IF, LOGL_ERROR, "Received PCU RTS request with "
+ "unsupported sapi %d\n", rts_req->sapi);
+ rc = -EINVAL;
}
- /* Special return value '1' means: do not free */
- if (rc != 1)
- msgb_free(msg);
-
return rc;
}
-/* OpenBTS socket functions */
-
-// TODO: We should move this parameters to config file.
-#define PCU_L1_IF_PORT 5944
-
-/* data has arrived on the udp socket */
-static int udp_read_cb(struct osmo_fd *ofd)
+static int pcu_rx_rach_ind(struct gsm_pcu_if_rach_ind *rach_ind)
{
- struct msgb *msg = msgb_alloc_headroom(2048, 128, "udp_rx");
- struct l1fwd_hdl *l1fh = (l1fwd_hdl *)ofd->data;
- struct femtol1_hdl *fl1h = l1fh->fl1h;
- int rc;
-
- if (!msg)
- return -ENOMEM;
+ int rc = 0;
- msg->l1h = msg->data;
+ LOGP(DL1IF, LOGL_INFO, "RACH request received: sapi=%d "
+ "qta=%d, ra=%d, fn=%d\n", rach_ind->sapi, rach_ind->qta,
+ rach_ind->ra, rach_ind->fn);
- l1fh->remote_sa_len = sizeof(l1fh->remote_sa);
- rc = recvfrom(ofd->fd, msg->l1h, msgb_tailroom(msg), 0,
- (struct sockaddr *) &l1fh->remote_sa, &l1fh->remote_sa_len);
- if (rc < 0) {
- perror("read from udp");
- msgb_free(msg);
- return rc;
- } else if (rc == 0) {
- perror("len=0 read from udp");
- msgb_free(msg);
- return rc;
+ switch (rach_ind->sapi) {
+ case PCU_IF_SAPI_RACH:
+ rc = gprs_rlcmac_rcv_rach(rach_ind->ra, rach_ind->fn,
+ rach_ind->qta);
+ break;
+ default:
+ LOGP(DL1IF, LOGL_ERROR, "Received PCU rach request with "
+ "unsupported sapi %d\n", rach_ind->sapi);
+ rc = -EINVAL;
}
- msgb_put(msg, rc);
- rc = pcu_l1if_handle_l1prim(fl1h, msg);
return rc;
}
-/* callback when we can write to the UDP socket */
-static int udp_write_cb(struct osmo_fd *ofd, struct msgb *msg)
+static int pcu_rx_info_ind(struct gsm_pcu_if_info_ind *info_ind)
{
- int rc;
- struct l1fwd_hdl *l1fh = (l1fwd_hdl *)ofd->data;
-
- //DEBUGP(DGPRS, "UDP: Writing %u bytes for MQ_L1_WRITE queue\n", msgb_l1len(msg));
-
- rc = sendto(ofd->fd, msg->l1h, msgb_l1len(msg), 0,
- (const struct sockaddr *)&l1fh->remote_sa, l1fh->remote_sa_len);
+ struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
+ int rc = 0;
+ int trx, ts, tfi;
+ struct gprs_rlcmac_tbf *tbf;
+ int i;
+
+ LOGP(DL1IF, LOGL_DEBUG, "Info indication received:\n");
+
+ if (!(info_ind->flags & PCU_IF_FLAG_ACTIVE)) {
+ LOGP(DL1IF, LOGL_NOTICE, "BTS not available\n");
+bssgp_failed:
+ /* free all TBF */
+ for (trx = 0; trx < 8; trx++) {
+ bts->trx[trx].arfcn = info_ind->trx[trx].arfcn;
+ for (ts = 0; ts < 8; ts++) {
+ for (tfi = 0; tfi < 32; tfi++) {
+ tbf = bts->trx[trx].pdch[ts].tbf[tfi];
+ if (tbf)
+ tbf_free(tbf);
+ }
+ }
+ }
+ gprs_bssgp_destroy();
+ return 0;
+ }
+ LOGP(DL1IF, LOGL_INFO, "BTS available\n");
+ LOGP(DL1IF, LOGL_DEBUG, " mcc=%d\n", info_ind->mcc);
+ LOGP(DL1IF, LOGL_DEBUG, " mnc=%d\n", info_ind->mnc);
+ LOGP(DL1IF, LOGL_DEBUG, " lac=%d\n", info_ind->lac);
+ LOGP(DL1IF, LOGL_DEBUG, " rac=%d\n", info_ind->rac);
+ LOGP(DL1IF, LOGL_DEBUG, " cell_id=%d\n", info_ind->cell_id);
+ LOGP(DL1IF, LOGL_DEBUG, " nsei=%d\n", info_ind->nsei);
+ LOGP(DL1IF, LOGL_DEBUG, " nse_timer=%d %d %d %d %d %d %d\n",
+ info_ind->nse_timer[0], info_ind->nse_timer[1],
+ info_ind->nse_timer[2], info_ind->nse_timer[3],
+ info_ind->nse_timer[4], info_ind->nse_timer[5],
+ info_ind->nse_timer[6]);
+ LOGP(DL1IF, LOGL_DEBUG, " cell_timer=%d %d %d %d %d %d %d %d %d %d "
+ "%d\n",
+ info_ind->cell_timer[0], info_ind->cell_timer[1],
+ info_ind->cell_timer[2], info_ind->cell_timer[3],
+ info_ind->cell_timer[4], info_ind->cell_timer[5],
+ info_ind->cell_timer[6], info_ind->cell_timer[7],
+ info_ind->cell_timer[8], info_ind->cell_timer[9],
+ info_ind->cell_timer[10]);
+ LOGP(DL1IF, LOGL_DEBUG, " repeat_time=%d\n", info_ind->repeat_time);
+ LOGP(DL1IF, LOGL_DEBUG, " repeat_count=%d\n", info_ind->repeat_count);
+ LOGP(DL1IF, LOGL_DEBUG, " bvci=%d\n", info_ind->bvci);
+ LOGP(DL1IF, LOGL_DEBUG, " t3142=%d\n", info_ind->t3142);
+ LOGP(DL1IF, LOGL_DEBUG, " t3169=%d\n", info_ind->t3169);
+ LOGP(DL1IF, LOGL_DEBUG, " t3191=%d\n", info_ind->t3191);
+ LOGP(DL1IF, LOGL_DEBUG, " t3193=%d (ms)\n", info_ind->t3193_10ms * 10);
+ LOGP(DL1IF, LOGL_DEBUG, " t3195=%d\n", info_ind->t3195);
+ LOGP(DL1IF, LOGL_DEBUG, " n3101=%d\n", info_ind->n3101);
+ LOGP(DL1IF, LOGL_DEBUG, " n3103=%d\n", info_ind->n3103);
+ LOGP(DL1IF, LOGL_DEBUG, " n3105=%d\n", info_ind->n3105);
+ LOGP(DL1IF, LOGL_DEBUG, " cv_countdown=%d\n", info_ind->cv_countdown);
+ LOGP(DL1IF, LOGL_DEBUG, " dl_tbf_ext=%d\n", info_ind->dl_tbf_ext);
+ LOGP(DL1IF, LOGL_DEBUG, " ul_tbf_ext=%d\n", info_ind->ul_tbf_ext);
+ for (i = 0; i < 4; i++) {
+ if ((info_ind->flags & (PCU_IF_FLAG_CS1 << i)))
+ LOGP(DL1IF, LOGL_DEBUG, " Use CS%d\n", i+1);
+ }
+ for (i = 0; i < 9; i++) {
+ if ((info_ind->flags & (PCU_IF_FLAG_MCS1 << i)))
+ LOGP(DL1IF, LOGL_DEBUG, " Use MCS%d\n", i+1);
+ }
+ LOGP(DL1IF, LOGL_DEBUG, " initial_cs=%d\n", info_ind->initial_cs);
+ LOGP(DL1IF, LOGL_DEBUG, " initial_mcs=%d\n", info_ind->initial_mcs);
+ LOGP(DL1IF, LOGL_DEBUG, " nsvci=%d\n", info_ind->nsvci[0]);
+ LOGP(DL1IF, LOGL_DEBUG, " local_port=%d\n", info_ind->local_port[0]);
+ LOGP(DL1IF, LOGL_DEBUG, " remote_port=%d\n", info_ind->remote_port[0]);
+ LOGP(DL1IF, LOGL_DEBUG, " remote_ip=%d\n", info_ind->remote_ip[0]);
+
+ rc = gprs_bssgp_create(info_ind->remote_ip[0], info_ind->remote_port[0],
+ info_ind->nsei, info_ind->nsvci[0], info_ind->bvci,
+ info_ind->mcc, info_ind->mnc, info_ind->lac, info_ind->rac,
+ info_ind->cell_id);
if (rc < 0) {
- LOGP(DPCU, LOGL_ERROR, "error writing to L1 msg_queue: %s\n",
- strerror(errno));
- return rc;
- } else if (rc < (int)msgb_l1len(msg)) {
- LOGP(DPCU, LOGL_ERROR, "short write to L1 msg_queue: "
- "%u < %u\n", rc, msgb_l1len(msg));
- return -EIO;
+ LOGP(DL1IF, LOGL_NOTICE, "SGSN not available\n");
+ goto bssgp_failed;
}
- return 0;
+ bts->cs1 = !!(info_ind->flags & PCU_IF_FLAG_CS1);
+ bts->cs2 = !!(info_ind->flags & PCU_IF_FLAG_CS2);
+ bts->cs3 = !!(info_ind->flags & PCU_IF_FLAG_CS3);
+ bts->cs4 = !!(info_ind->flags & PCU_IF_FLAG_CS4);
+ if (!bts->cs1 && !bts->cs2 && !bts->cs3 && !bts->cs4)
+ bts->cs1 = 1;
+ if (info_ind->t3142) { /* if timer values are set */
+ bts->t3142 = info_ind->t3142;
+ bts->t3169 = info_ind->t3169;
+ bts->t3191 = info_ind->t3191;
+ bts->t3193_msec = info_ind->t3193_10ms * 10;
+ bts->t3195 = info_ind->t3195;
+ bts->n3101 = info_ind->n3101;
+ bts->n3103 = info_ind->n3103;
+ bts->n3105 = info_ind->n3105;
+ }
+ if (info_ind->initial_cs < 1 || info_ind->initial_cs > 4)
+ bts->initial_cs = 1;
+ else
+ bts->initial_cs = info_ind->initial_cs;
+
+ for (trx = 0; trx < 8; trx++) {
+ bts->trx[trx].arfcn = info_ind->trx[trx].arfcn;
+ for (ts = 0; ts < 8; ts++) {
+ if ((info_ind->trx[trx].pdch_mask & (1 << ts))) {
+ /* FIXME: activate dynamically at RLCMAC */
+ if (!bts->trx[trx].pdch[ts].enable)
+ pcu_tx_act_req(trx, ts, 1);
+ bts->trx[trx].pdch[ts].enable = 1;
+ bts->trx[trx].pdch[ts].tsc =
+ info_ind->trx[trx].tsc[ts];
+ LOGP(DL1IF, LOGL_INFO, "PDCH: trx=%d ts=%d\n",
+ trx, ts);
+ } else {
+ if (bts->trx[trx].pdch[ts].enable)
+ pcu_tx_act_req(trx, ts, 0);
+ bts->trx[trx].pdch[ts].enable = 0;
+ /* kick all tbf FIXME: multislot */
+ for (tfi = 0; tfi < 32; tfi++) {
+ tbf = bts->trx[trx].pdch[ts].tbf[tfi];
+ if (tbf)
+ tbf_free(tbf);
+ }
+ }
+ }
+ }
+
+ return rc;
}
-int pcu_l1if_open()
+static int pcu_rx_time_ind(struct gsm_pcu_if_time_ind *time_ind)
{
- //struct l1fwd_hdl *l1fh;
- struct femtol1_hdl *fl1h;
- int rc;
-
- memset(&pcu_l1if_bts, 0, sizeof(pcu_l1if_bts));
-
- /* allocate new femtol1_handle */
- fl1h = talloc_zero(NULL, struct femtol1_hdl);
- INIT_LLIST_HEAD(&fl1h->wlc_list);
-
- l1fh->fl1h = fl1h;
- fl1h->priv = l1fh;
-
- struct osmo_wqueue * queue = &((l1fh->fl1h)->write_q);
- osmo_wqueue_init(queue, 10);
- queue->bfd.when |= BSC_FD_READ;
- queue->bfd.data = l1fh;
- queue->bfd.priv_nr = 0;
-
- /* Open UDP */
- struct osmo_wqueue *wq = &l1fh->udp_wq;
-
- osmo_wqueue_init(wq, 10);
- wq->write_cb = udp_write_cb;
- wq->read_cb = udp_read_cb;
- wq->bfd.when |= BSC_FD_READ;
- wq->bfd.data = l1fh;
- wq->bfd.priv_nr = 0;
- rc = osmo_sock_init_ofd(&wq->bfd, AF_UNSPEC, SOCK_DGRAM,
- IPPROTO_UDP, NULL, PCU_L1_IF_PORT,
- OSMO_SOCK_F_BIND);
- if (rc < 0) {
- perror("sock_init");
- exit(1);
+ struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
+ int trx, ts, tfi;
+ struct gprs_rlcmac_tbf *tbf;
+ uint32_t elapsed;
+ uint8_t fn13 = time_ind->fn % 13;
+
+ /* omit frame numbers not starting at a MAC block */
+ if (fn13 != 0 && fn13 != 4 && fn13 != 8)
+ return 0;
+
+ LOGP(DL1IF, LOGL_DEBUG, "Time indication received: %d\n",
+ time_ind->fn % 52);
+
+ set_current_fn(time_ind->fn);
+
+ /* check for poll timeout */
+ for (trx = 0; trx < 8; trx++) {
+ for (ts = 0; ts < 8; ts++) {
+ for (tfi = 0; tfi < 32; tfi++) {
+ tbf = bts->trx[trx].pdch[ts].tbf[tfi];
+ if (!tbf)
+ continue;
+ if (tbf->poll_state != GPRS_RLCMAC_POLL_SCHED)
+ continue;
+ elapsed = (frame_number - tbf->poll_fn)
+ % 2715648;
+ if (elapsed >= 20 && elapsed < 200)
+ gprs_rlcmac_poll_timeout(tbf);
+ }
+ }
}
return 0;
}
+int pcu_rx(uint8_t msg_type, struct gsm_pcu_if *pcu_prim)
+{
+ int rc = 0;
+
+ switch (msg_type) {
+ case PCU_IF_MSG_DATA_IND:
+ rc = pcu_rx_data_ind(&pcu_prim->u.data_ind);
+ break;
+ case PCU_IF_MSG_RTS_REQ:
+ rc = pcu_rx_rts_req(&pcu_prim->u.rts_req);
+ break;
+ case PCU_IF_MSG_RACH_IND:
+ rc = pcu_rx_rach_ind(&pcu_prim->u.rach_ind);
+ break;
+ case PCU_IF_MSG_INFO_IND:
+ rc = pcu_rx_info_ind(&pcu_prim->u.info_ind);
+ break;
+ case PCU_IF_MSG_TIME_IND:
+ rc = pcu_rx_time_ind(&pcu_prim->u.time_ind);
+ break;
+ default:
+ LOGP(DL1IF, LOGL_ERROR, "Received unknwon PCU msg type %d\n",
+ msg_type);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}