dexter has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-bsc/+/30749 )


Change subject: WIP Ericsson GPRS support
......................................................................

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 https://gerrit.osmocom.org/c/osmo-bsc/+/30749
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: If96b3f1e26a7206fcd2658b6faf6afe556cfbb14
Gerrit-Change-Number: 30749
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <[email protected]>
Gerrit-MessageType: newchange

Reply via email to