dexter has uploaded this change for review.
WIP Ericsson GPRS support
Change-Id: If96b3f1e26a7206fcd2658b6faf6afe556cfbb14
---
M include/osmocom/bsc/abis_rsl.h
M include/osmocom/bsc/pcuif_proto.h
M src/osmo-bsc/abis_rsl.c
M src/osmo-bsc/pcu_sock.c
4 files changed, 348 insertions(+), 38 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/49/30749/1
diff --git a/include/osmocom/bsc/abis_rsl.h b/include/osmocom/bsc/abis_rsl.h
index dcae348..b3aef7c 100644
--- a/include/osmocom/bsc/abis_rsl.h
+++ b/include/osmocom/bsc/abis_rsl.h
@@ -66,6 +66,9 @@
/* Ericcson vendor specific RSL extensions */
int rsl_ericsson_imm_assign_cmd(struct gsm_bts *bts, uint32_t tlli, uint8_t len, uint8_t *val);
+int rsl_ericsson_imm_assign_via_pch_cmd(struct gsm_bts *bts, uint8_t len,
+ uint8_t *val, uint32_t tlli,
+ uint8_t pag_grp);
/* Siemens vendor-specific RSL extensions */
int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci);
diff --git a/include/osmocom/bsc/pcuif_proto.h b/include/osmocom/bsc/pcuif_proto.h
index fef0f88..78f56c9 100644
--- a/include/osmocom/bsc/pcuif_proto.h
+++ b/include/osmocom/bsc/pcuif_proto.h
@@ -2,6 +2,7 @@
#define _PCUIF_PROTO_H
#include <osmocom/gsm/l1sap.h>
+#include <osmocom/abis/e1_input.h>
#include <arpa/inet.h>
#define PCU_SOCK_DEFAULT "/tmp/pcu_bts"
@@ -9,6 +10,7 @@
#define PCU_IF_VERSION 0x0a
#define TXT_MAX_LEN 128
+
/* msg_type */
#define PCU_IF_MSG_DATA_REQ 0x00 /* send data to given channel */
#define PCU_IF_MSG_DATA_CNF 0x01 /* confirm (e.g. transmission on PCH) */
@@ -19,6 +21,7 @@
#define PCU_IF_MSG_DATA_CNF_DT 0x11 /* confirm (with direct tlli) */
#define PCU_IF_MSG_RACH_IND 0x22 /* receive RACH */
#define PCU_IF_MSG_INFO_IND 0x32 /* retrieve BTS info */
+#define PCU_IF_MSG_E1_CCU_IND 0x33 /* retrieve E1 CCU comm. parameters */
#define PCU_IF_MSG_ACT_REQ 0x40 /* activate/deactivate PDCH */
#define PCU_IF_MSG_TIME_IND 0x52 /* GSM time indication */
#define PCU_IF_MSG_INTERF_IND 0x53 /* interference report */
@@ -257,6 +260,13 @@
} cgi_ps;
} __attribute__ ((packed));
+/* E1 CCU connection parameters */
+struct gsm_pcu_if_e1_ccu_ind {
+ uint8_t pdch_trx_no;
+ uint8_t pdch_ts;
+ struct gsm_e1_subslot e1_link;
+} __attribute__ ((packed));
+
struct gsm_pcu_if {
/* context based information */
uint8_t msg_type; /* message type */
@@ -273,6 +283,7 @@
struct gsm_pcu_if_rach_ind rach_ind;
struct gsm_pcu_if_txt_ind txt_ind;
struct gsm_pcu_if_info_ind info_ind;
+ struct gsm_pcu_if_e1_ccu_ind e1_ccu_ind;
struct gsm_pcu_if_act_req act_req;
struct gsm_pcu_if_time_ind time_ind;
struct gsm_pcu_if_pag_req pag_req;
diff --git a/src/osmo-bsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c
index 3d18447..b933442 100644
--- a/src/osmo-bsc/abis_rsl.c
+++ b/src/osmo-bsc/abis_rsl.c
@@ -978,6 +978,24 @@
return abis_rsl_sendmsg(msg);
}
+/* Chapter 8.5.6 Immediate Assignment Command (with Ericcson vendor specific RSL extension) */
+int rsl_ericsson_imm_assign_via_pch_cmd(struct gsm_bts *bts, uint8_t len,
+ uint8_t *val, uint32_t tlli,
+ uint8_t pag_grp)
+{
+ struct msgb *msg = rsl_imm_assign_cmd_common(bts, len, val);
+
+ /* Append ericsson propritary paging group field */
+ msgb_put_u8(msg, RSL_IE_ERIC_PAGING_GROUP);
+ msgb_put_u8(msg, pag_grp);
+
+ /* Append ericsson propritary mobile identity field (see also comment above) */
+ msgb_put_u8(msg, RSL_IE_ERIC_MOBILE_ID);
+ msgb_put_u32(msg, tlli);
+
+ return abis_rsl_sendmsg(msg);
+}
+
/* Send Siemens specific MS RF Power Capability Indication */
int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
{
diff --git a/src/osmo-bsc/pcu_sock.c b/src/osmo-bsc/pcu_sock.c
index 81198bd..659cd8e 100644
--- a/src/osmo-bsc/pcu_sock.c
+++ b/src/osmo-bsc/pcu_sock.c
@@ -33,6 +33,7 @@
#include <osmocom/core/logging.h>
#include <osmocom/gsm/l1sap.h>
#include <osmocom/gsm/gsm0502.h>
+#include <osmocom/bsc/abis_nm.h>
#include <osmocom/bsc/gsm_data.h>
#include <osmocom/bsc/pcu_if.h>
@@ -44,8 +45,10 @@
#include <osmocom/bsc/bts.h>
#include <osmocom/bsc/bts_sm.h>
+#define LOGPTRX(trx, ss, lvl, fmt, args...) LOGP(ss, lvl, "%s " fmt, gsm_trx_name(trx), ## args)
+
static int pcu_sock_send(struct gsm_bts *bts, struct msgb *msg);
-uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx);
+//uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx);
int pcu_direct = 1;
static const char *sapi_string[] = {
@@ -93,6 +96,13 @@
return msg;
}
+static bool ts_should_be_pdch(const struct gsm_bts_trx_ts *ts)
+{
+ if (ts->pchan_is == GSM_PCHAN_PDCH)
+ return true;
+ return false;
+}
+
/* Fill the frequency hopping parameter */
static void info_ind_fill_fhp(struct gsm_pcu_if_info_trx_ts *ts_info,
const struct gsm_bts_trx_ts *ts)
@@ -105,6 +115,51 @@
ts_info->ma_bit_len = ts->hopping.ma_len * 8 - ts->hopping.ma.cur_bit;
}
+static void info_ind_fill_trx(struct gsm_pcu_if_info_trx *trx_info,
+ const struct gsm_bts_trx *trx)
+{
+ unsigned int tn;
+
+ trx_info->pdch_mask = 0;
+ trx_info->arfcn = trx->arfcn;
+ trx_info->hlayer1 = 0x2342;
+
+#if 0
+ if (trx->mo.nm_state.operational != NM_OPSTATE_ENABLED ||
+ trx->mo.nm_state.administrative != NM_STATE_UNLOCKED)
+ {
+ LOGPTRX(trx, DPCU, LOGL_INFO, "unavailable for PCU (op=%s adm=%s)\n",
+ abis_nm_opstate_name(trx->mo.nm_state.operational),
+ abis_nm_admin_name(trx->mo.nm_state.administrative));
+ return;
+ }
+#endif
+
+ for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) {
+ const struct gsm_bts_trx_ts *ts = &trx->ts[tn];
+
+ if (ts->mo.nm_state.operational != NM_OPSTATE_ENABLED)
+ continue;
+ if (!ts_should_be_pdch(ts))
+ continue;
+
+ trx_info->pdch_mask |= (1 << tn);
+ trx_info->ts[tn].tsc = ts->tsc;
+
+ if (ts->hopping.enabled)
+ info_ind_fill_fhp(&trx_info->ts[tn], ts);
+
+ LOGPTRX(trx, DPCU, LOGL_INFO, "PDCH on ts=%u is available "
+ "(tsc=%u ", ts->nr, trx_info->ts[tn].tsc);
+ if (ts->hopping.enabled) {
+ LOGPC(DPCU, LOGL_INFO, "hopping=yes hsn=%u maio=%u ma_bit_len=%u)\n",
+ ts->hopping.hsn, ts->hopping.maio, trx_info->ts[tn].ma_bit_len);
+ } else {
+ LOGPC(DPCU, LOGL_INFO, "hopping=no arfcn=%u)\n", trx->arfcn);
+ }
+ }
+}
+
/* Send BTS properties to the PCU */
static int pcu_tx_info_ind(struct gsm_bts *bts)
{
@@ -115,13 +170,14 @@
struct gsm_bts_sm *bts_sm;
struct gsm_gprs_nsvc *nsvc;
struct gsm_bts_trx *trx;
- struct gsm_bts_trx_ts *ts;
- int i, tn;
+ int i;
OSMO_ASSERT(bts);
OSMO_ASSERT(bts->network);
OSMO_ASSERT(bts->site_mgr);
+ LOGP(DPCU, LOGL_INFO, "Sending info\n");
+
bts_sm = bts->site_mgr;
LOGP(DPCU, LOGL_INFO, "Sending info for BTS %d\n",bts->nr);
@@ -131,7 +187,6 @@
msg = pcu_msgb_alloc(PCU_IF_MSG_INFO_IND, bts->nr);
if (!msg)
return -ENOMEM;
-
pcu_prim = (struct gsm_pcu_if *) msg->data;
info_ind = &pcu_prim->u.info_ind;
info_ind->version = PCU_IF_VERSION;
@@ -140,6 +195,7 @@
if (pcu_direct)
info_ind->flags |= PCU_IF_FLAG_SYSMO;
+ info_ind->bsic = bts->bsic;
/* RAI */
info_ind->mcc = bts->network->plmn.mcc;
info_ind->mnc = bts->network->plmn.mnc;
@@ -194,9 +250,9 @@
if (rlcc->cs_mask & (1 << GPRS_MCS9))
info_ind->flags |= PCU_IF_FLAG_MCS9;
}
- /* TODO: isn't dl_tbf_ext wrong?: * 10 and no ntohs */
+ /* FIXME: isn't dl_tbf_ext wrong?: * 10 and no ntohs */
info_ind->dl_tbf_ext = rlcc->parameter[T_DL_TBF_EXT];
- /* TODO: isn't ul_tbf_ext wrong?: * 10 and no ntohs */
+ /* FIXME: isn't ul_tbf_ext wrong?: * 10 and no ntohs */
info_ind->ul_tbf_ext = rlcc->parameter[T_UL_TBF_EXT];
info_ind->initial_cs = rlcc->initial_cs;
info_ind->initial_mcs = rlcc->initial_mcs;
@@ -211,14 +267,14 @@
case AF_INET:
info_ind->address_type[i] = PCU_IF_ADDR_TYPE_IPV4;
info_ind->remote_ip[i].v4 = nsvc->remote.u.sin.sin_addr;
- info_ind->remote_port[i] = nsvc->remote.u.sin.sin_port;
+ info_ind->remote_port[i] = ntohs(nsvc->remote.u.sin.sin_port);
break;
case AF_INET6:
info_ind->address_type[i] = PCU_IF_ADDR_TYPE_IPV6;
memcpy(&info_ind->remote_ip[i].v6,
&nsvc->remote.u.sin6.sin6_addr,
sizeof(struct in6_addr));
- info_ind->remote_port[i] = nsvc->remote.u.sin6.sin6_port;
+ info_ind->remote_port[i] = ntohs(nsvc->remote.u.sin6.sin6_port);
break;
default:
info_ind->address_type[i] = PCU_IF_ADDR_TYPE_UNSPEC;
@@ -230,40 +286,126 @@
trx = gsm_bts_trx_num(bts, i);
if (!trx)
continue;
- info_ind->trx[i].hlayer1 = 0x2342;
- info_ind->trx[i].pdch_mask = 0;
- info_ind->trx[i].arfcn = trx->arfcn;
- for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) {
- ts = &trx->ts[tn];
- if (ts->mo.nm_state.operational != NM_OPSTATE_ENABLED ||
- ts->pchan_is != GSM_PCHAN_PDCH)
- continue;
-
- info_ind->trx[i].pdch_mask |= (1 << tn);
- info_ind->trx[i].ts[tn].tsc =
- (ts->tsc >= 0) ? ts->tsc : bts->bsic & 7;
-
- if (ts->hopping.enabled)
- info_ind_fill_fhp(&info_ind->trx[i].ts[tn], ts);
-
- LOGP(DPCU, LOGL_INFO, "trx=%d ts=%d: PDCH is available "
- "(tsc=%u ", trx->nr, ts->nr, info_ind->trx[i].ts[tn].tsc);
- if (ts->hopping.enabled)
- LOGPC(DPCU, LOGL_INFO, "hopping=yes hsn=%u maio=%u ma_bit_len=%u)\n",
- ts->hopping.hsn, ts->hopping.maio, trx->ts[tn].hopping.ma.data_len - trx->ts[tn].hopping.ma.cur_bit);
- else
- LOGPC(DPCU, LOGL_INFO, "hopping=no arfcn=%u)\n", trx->arfcn);
+ if (trx->nr >= ARRAY_SIZE(info_ind->trx)) {
+ LOGPTRX(trx, DPCU, LOGL_NOTICE, "PCU interface (version %u) "
+ "cannot handle more than %zu transceivers => skipped\n",
+ PCU_IF_VERSION, ARRAY_SIZE(info_ind->trx));
+ continue;
}
+ info_ind_fill_trx(&info_ind->trx[trx->nr], trx);
}
return pcu_sock_send(bts, msg);
}
+static int pcu_tx_e1_ccu_ind(struct gsm_bts *bts)
+{
+ struct msgb *msg;
+ struct gsm_pcu_if *pcu_prim;
+ struct gsm_pcu_if_e1_ccu_ind *e1_ccu_ind;
+ int i;
+ int k;
+ struct gsm_bts_trx *trx;
+ struct gsm_bts_trx_ts *ts;
+ int rc;
+
+ OSMO_ASSERT(bts);
+ OSMO_ASSERT(bts->network);
+ OSMO_ASSERT(bts->site_mgr);
+
+ for (i = 0; i < PCU_IF_NUM_TRX; i++) {
+ trx = gsm_bts_trx_num(bts, i);
+ if (!trx)
+ continue;
+ if (trx->nr >= PCU_IF_NUM_TRX) {
+ LOGPTRX(trx, DPCU, LOGL_NOTICE, "PCU interface (version %u) "
+ "cannot handle more than %u transceivers => skipped\n",
+ PCU_IF_VERSION, PCU_IF_NUM_TRX);
+ continue;
+ }
+
+ for (k = 0; k < 8; k++) {
+ ts = &trx->ts[k];
+
+ if (ts->mo.nm_state.operational != NM_OPSTATE_ENABLED)
+ continue;
+ if (!ts_should_be_pdch(ts))
+ continue;
+
+ msg = pcu_msgb_alloc(PCU_IF_MSG_E1_CCU_IND, bts->nr);
+ if (!msg)
+ return -ENOMEM;
+ pcu_prim = (struct gsm_pcu_if *)msg->data;
+ e1_ccu_ind = &pcu_prim->u.e1_ccu_ind;
+ e1_ccu_ind->pdch_ts = ts->nr;
+ e1_ccu_ind->pdch_trx_no = trx->nr;
+ memcpy(&e1_ccu_ind->e1_link, &ts->e1_link, sizeof(e1_ccu_ind->e1_link));
+
+ LOGP(DPCU, LOGL_INFO, "Sending E1 CCU info for BTS %d, TRX %d, TS %d\n", bts->nr,
+ e1_ccu_ind->pdch_trx_no, e1_ccu_ind->pdch_ts);
+
+ rc = pcu_sock_send(bts, msg);
+ if (rc < 0)
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
/* Allow test to overwrite it */
__attribute__((weak)) void pcu_info_update(struct gsm_bts *bts)
{
- if (pcu_connected(bts))
+ if (pcu_connected(bts)) {
+ /* In cases where the CCU is connected via an E1 line, we
+ * transmit the connection parameters for the PDCH before
+ * we announce the other BTS related parameters. */
+ pcu_tx_e1_ccu_ind(bts);
+
pcu_tx_info_ind(bts);
+ }
+}
+
+int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t sapi, uint32_t fn,
+ uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len,
+ int8_t rssi, uint16_t ber10k, int16_t bto, int16_t lqual)
+{
+ struct msgb *msg;
+ struct gsm_pcu_if *pcu_prim;
+ struct gsm_pcu_if_data *data_ind;
+ struct gsm_bts *bts = ts->trx->bts;
+
+ LOGP(DPCU, LOGL_DEBUG, "Sending data indication: sapi=%s arfcn=%d block=%d data=%s\n",
+ sapi_string[sapi], arfcn, block_nr, osmo_hexdump(data, len));
+
+// TODO: Do we care? We are not using the pcu_sock for air interface traffic here
+// if (lqual < bts->min_qual_norm) {
+// LOGP(DPCU, LOGL_DEBUG, "Link quality %"PRId16" is below threshold %d, dropping packet\n",
+// lqual, bts->min_qual_norm);
+// return 0;
+// }
+
+ msg = pcu_msgb_alloc(PCU_IF_MSG_DATA_IND, bts->nr);
+ if (!msg)
+ return -ENOMEM;
+ pcu_prim = (struct gsm_pcu_if *) msg->data;
+ data_ind = &pcu_prim->u.data_ind;
+
+ data_ind->sapi = sapi;
+ data_ind->rssi = rssi;
+ data_ind->fn = fn;
+ data_ind->arfcn = arfcn;
+ data_ind->trx_nr = ts->trx->nr;
+ data_ind->ts_nr = ts->nr;
+ data_ind->block_nr = block_nr;
+ data_ind->ber10k = ber10k;
+ data_ind->ta_offs_qbits = bto;
+ data_ind->lqual_cb = lqual;
+ if (len)
+ memcpy(data_ind->data, data, len);
+ data_ind->len = len;
+
+ return pcu_sock_send(bts, msg);
}
/* Forward rach indication to PCU */
@@ -343,6 +485,7 @@
rc = -EINVAL;
break;
}
+
LOGP(DPCU, LOGL_ERROR, "PCU Sends paging "
"request type %02x (chan_needed=%02x, mi=%s)\n",
p1->msg_type, chan_needed, osmo_mobile_identity_to_str_c(OTC_SELECT, &mi));
@@ -370,6 +513,27 @@
return rc;
}
+/* Helper function for pcu_rx_data_req() to extract paging group info */
+static uint8_t extract_paging_group(struct gsm_bts *bts, uint8_t *data)
+{
+ char imsi_digit_buf[4];
+ uint8_t pag_grp;
+
+ /* the first three bytes are the last three digits of
+ * the IMSI, which we need to compute the paging group */
+ imsi_digit_buf[0] = data[0];
+ imsi_digit_buf[1] = data[1];
+ imsi_digit_buf[2] = data[2];
+ imsi_digit_buf[3] = '\0';
+
+ pag_grp = gsm0502_calc_paging_group(&bts->si_common.chan_desc,
+ str_to_imsi(imsi_digit_buf));
+
+ LOGP(DPCU, LOGL_DEBUG, "Calculating paging group: imsi_digit_buf=%s ==> pag_grp=0x%02x\n", imsi_digit_buf, pag_grp);
+
+ return pag_grp;
+}
+
static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
struct gsm_pcu_if_data *data_req)
{
@@ -415,22 +579,26 @@
/* DT = direct tlli. A tlli is prefixed */
if (data_req->len < 5) {
- LOGP(DPCU, LOGL_ERROR, "Received PCU data request with "
- "invalid/small length %d\n", data_req->len);
+ LOGP(DPCU, LOGL_ERROR, "Received PCU data request with invalid/small length %d\n",
+ data_req->len);
break;
}
memcpy(&tlli, data_req->data, 4);
+ pag_grp = extract_paging_group(bts, data_req->data + 4);
- msg = msgb_alloc(data_req->len - 4, "pcu_agch");
+ msg = msgb_alloc(data_req->len - 7, "pcu_agch");
if (!msg) {
rc = -ENOMEM;
break;
}
- msg->l3h = msgb_put(msg, data_req->len - 4);
- memcpy(msg->l3h, data_req->data + 4, data_req->len - 4);
+ msg->l3h = msgb_put(msg, data_req->len - 7);
+ memcpy(msg->l3h, data_req->data + 7, data_req->len - 7);
+
+ LOGP(DPCU, LOGL_DEBUG, "PCU Sends immediate assignment via PCH (tlli=0x%08x, pag_grp=0x%02x)\n",
+ tlli, pag_grp);
if (bts->type == GSM_BTS_TYPE_RBS2000)
- rc = rsl_ericsson_imm_assign_cmd(bts, tlli, msg->len, msg->data);
+ rc = rsl_ericsson_imm_assign_via_pch_cmd(bts, msg->len, msg->data, tlli, pag_grp);
else
rc = rsl_imm_assign_cmd(bts, msg->len, msg->data);
@@ -448,6 +616,106 @@
return rc;
}
+int pcu_tx_si(const struct gsm_bts *bts, enum osmo_sysinfo_type si_type,
+ bool enable)
+{
+ /* the SI is per-BTS so it doesn't matter which TRX we use */
+ struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, 0);
+
+ uint8_t si_buf[GSM_MACBLOCK_LEN];
+ uint8_t len;
+ int rc;
+
+ if (enable) {
+ memcpy(si_buf, GSM_BTS_SI(bts, si_type), GSM_MACBLOCK_LEN);
+ len = GSM_MACBLOCK_LEN;
+ LOGP(DPCU, LOGL_DEBUG, "Updating SI%s to PCU: %s\n",
+ get_value_string(osmo_sitype_strs, si_type),
+ osmo_hexdump_nospc(si_buf, GSM_MACBLOCK_LEN));
+ } else {
+ si_buf[0] = si_type;
+ len = 1;
+
+ /* Note: SI13 is the only system information type that is revked
+ * by just sending a completely empty message. This is due to
+ * historical reasons */
+ if (si_type != SYSINFO_TYPE_13)
+ len = 0;
+
+ LOGP(DPCU, LOGL_DEBUG, "Revoking SI%s from PCU\n",
+ get_value_string(osmo_sitype_strs, si_buf[0]));
+ }
+
+ /* The low-level data like FN, ARFCN etc will be ignored but we have to
+ * set lqual high enough to bypass the check at lower levels */
+ rc = pcu_tx_data_ind(&trx->ts[0], PCU_IF_SAPI_BCCH, 0, 0, 0, si_buf, len,
+ 0, 0, 0, INT16_MAX);
+ if (rc < 0)
+ LOGP(DPCU, LOGL_NOTICE, "Failed to send SI%s to PCU: rc=%d\n",
+ get_value_string(osmo_sitype_strs, si_type), rc);
+
+ return rc;
+}
+
+static int pcu_tx_si_all(struct gsm_bts *bts)
+{
+ const enum osmo_sysinfo_type si_types[] =
+ { SYSINFO_TYPE_1, SYSINFO_TYPE_2, SYSINFO_TYPE_3, SYSINFO_TYPE_13 };
+ unsigned int i;
+ int rc = 0;
+
+ for (i = 0; i < ARRAY_SIZE(si_types); i++) {
+ if (GSM_BTS_HAS_SI(bts, si_types[i])) {
+ rc = pcu_tx_si(bts, si_types[i], true);
+ if (rc < 0)
+ return rc;
+ } else {
+ LOGP(DPCU, LOGL_INFO,
+ "SI%s is not available on PCU connection\n",
+ get_value_string(osmo_sitype_strs, si_types[i]));
+ }
+ }
+
+ return 0;
+}
+
+static int pcu_rx_txt_ind(struct gsm_bts *bts,
+ struct gsm_pcu_if_txt_ind *txt)
+{
+ int rc;
+
+ switch (txt->type) {
+ case PCU_VERSION:
+ LOGP(DPCU, LOGL_INFO, "OsmoPCU version %s connected\n",
+ txt->text);
+//TODO: can we somehow regenerate the si restoctets or can we make the BTS to do so?
+// probably regeneration of the si is not even needed since its different with ericsson anyway
+// oml_tx_failure_event_rep(&bts->gprs.cell.mo, NM_SEVER_CEASED, OSMO_EVT_PCU_VERS, txt->text);
+// osmo_strlcpy(bts->pcu_version, txt->text, MAX_VERSION_LENGTH);
+
+ /* patch SI to advertise GPRS, *if* the SI sent by BSC said so */
+// regenerate_si3_restoctets(bts);
+// regenerate_si4_restoctets(bts);
+
+ rc = pcu_tx_si_all(bts);
+ if (rc < 0)
+ return -EINVAL;
+
+ break;
+ case PCU_OML_ALERT:
+//TODO: Make BSC aware of this event locally
+// oml_tx_failure_event_rep(&bts->gprs.cell.mo, NM_SEVER_INDETERMINATE, OSMO_EVT_EXT_ALARM,
+// txt->text);
+ break;
+ default:
+ LOGP(DPCU, LOGL_ERROR, "Unknown TXT_IND type %u received\n",
+ txt->type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
#define CHECK_IF_MSG_SIZE(prim_len, prim_msg) \
do { \
size_t _len = PCUIF_HDR_SIZE + sizeof(prim_msg); \
@@ -472,6 +740,16 @@
CHECK_IF_MSG_SIZE(prim_len, pcu_prim->u.data_req);
rc = pcu_rx_data_req(bts, msg_type, &pcu_prim->u.data_req);
break;
+ case PCU_IF_MSG_TXT_IND:
+ CHECK_IF_MSG_SIZE(prim_len, pcu_prim->u.txt_ind);
+ rc = pcu_rx_txt_ind(bts, &pcu_prim->u.txt_ind);
+ break;
+ case PCU_IF_SAPI_AGCH_DT:
+ printf("============> GOT PCU_IF_SAPI_AGCH_DT, but don't know what to do with it!\n");
+ break;
+ case PCU_IF_MSG_ACT_REQ:
+ printf("============> GOT PCU_IF_MSG_ACT_REQ, but don't know what to do with it!\n");
+ break;
default:
LOGP(DPCU, LOGL_ERROR, "Received unknown PCU msg type %d\n",
msg_type);
To view, visit change 30749. To unsubscribe, or for help writing mail filters, visit settings.