pcu_sock: add basic pcu interface support

Adds a basic version of a pcu socket interface, similar
to the one that can be found in osmo-bts.

Change-Id: Ib13cb4099d12fa71e9e0b8727e19ab29e11909b2
diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c
index 20dd2b5..62c12a8 100644
--- a/openbsc/src/libbsc/abis_rsl.c
+++ b/openbsc/src/libbsc/abis_rsl.c
@@ -45,6 +45,7 @@
 #include <osmocom/abis/e1_input.h>
 #include <osmocom/gsm/rsl.h>
 #include <osmocom/core/talloc.h>
+#include <openbsc/pcu_if.h>
 
 #define RSL_ALLOC_SIZE		1024
 #define RSL_ALLOC_HEADROOM	128
@@ -1285,6 +1286,12 @@
 
 	send_lchan_signal(S_LCHAN_ACTIVATE_ACK, lchan, NULL);
 
+	/* Update bts attributes inside the PCU */
+	if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH ||
+	    ts->pchan == GSM_PCHAN_TCH_F_PDCH ||
+	    ts->pchan == GSM_PCHAN_PDCH)
+		pcu_info_update(ts->trx->bts);
+
 	return 0;
 }
 
@@ -1768,6 +1775,39 @@
 	return rsl_imm_assign_cmd(bts, sizeof(*iar), (uint8_t *) iar);
 }
 
+/* Handle packet channel rach requests */
+static int rsl_rx_pchan_rqd(struct msgb *msg, struct gsm_bts *bts)
+{
+	struct gsm48_req_ref *rqd_ref;
+	struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
+	rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
+	uint8_t ra = rqd_ref->ra;
+	uint8_t t1, t2, t3;
+	uint32_t fn;
+	uint8_t rqd_ta;
+	uint8_t is_11bit;
+
+	/* Process rach request and forward contained information to PCU */
+	if (ra == 0x7F) {
+		is_11bit = 1;
+
+		/* FIXME: Also handle 11 bit rach requests */
+		LOGP(DRSL, LOGL_ERROR, "BTS %d eleven bit access burst not supported yet!\n",bts->nr);
+		return -EINVAL;
+	} else {
+		is_11bit = 0;
+		t1 = rqd_ref->t1;
+		t2 = rqd_ref->t2;
+		t3 = rqd_ref->t3_low | (rqd_ref->t3_high << 3);
+		fn = (51 * ((t3-t2) % 26) + t3 + 51 * 26 * t1);
+
+		rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
+	}
+
+	return pcu_tx_rach_ind(bts, rqd_ta, ra, fn, is_11bit,
+			       GSM_L1_BURST_TYPE_ACCESS_0);
+}
+
 /* MS has requested a channel on the RACH */
 static int rsl_rx_chan_rqd(struct msgb *msg)
 {
@@ -1795,10 +1835,20 @@
 		return -EINVAL;
 	rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
 
+	/* Determine channel request cause code */
+	chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
+	LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: reason: %s (ra=0x%02x, neci=0x%02x, chreq_reason=0x%02x)\n",
+	     msg->lchan->ts->trx->bts->nr,
+	     get_value_string(gsm_chreq_descs, chreq_reason),
+	     rqd_ref->ra, bts->network->neci, chreq_reason);
+
+	/* Handle PDCH related rach requests (in case of BSC-co-located-PCU */
+	if (chreq_reason == GSM_CHREQ_REASON_PDCH)
+		return rsl_rx_pchan_rqd(msg, bts);
+
 	/* determine channel type (SDCCH/TCH_F/TCH_H) based on
 	 * request reference RA */
 	lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
-	chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
 
 	rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_CHREQ_TOTAL]);