jolly has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmocom-bb/+/34614?usp=email )


Change subject: ASCI: Add decoding of SYSTEM INFORMATION TYPE 10 $(ASCI)$
......................................................................

ASCI: Add decoding of SYSTEM INFORMATION TYPE 10 $(ASCI)$

This information can be used by the MS to get infos about neighbor
cells with the same voice group/broadcast call.

Related: OS#5782
Change-Id: I81c7929f6d951d8eef7d08624f0b72830370c448
---
M src/host/layer23/include/osmocom/bb/common/sysinfo.h
M src/host/layer23/src/common/sysinfo.c
M src/host/layer23/src/mobile/gsm48_rr.c
3 files changed, 335 insertions(+), 4 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/14/34614/1

diff --git a/src/host/layer23/include/osmocom/bb/common/sysinfo.h 
b/src/host/layer23/include/osmocom/bb/common/sysinfo.h
index 0368901..594d336 100644
--- a/src/host/layer23/include/osmocom/bb/common/sysinfo.h
+++ b/src/host/layer23/include/osmocom/bb/common/sysinfo.h
@@ -18,12 +18,27 @@
 #define        FREQ_TYPE_REP_5bis      0x40 /* sub channel of SI 5bis */
 #define        FREQ_TYPE_REP_5ter      0x80 /* sub channel of SI 5ter */

+struct si10_cell_info {
+       uint8_t                         index; /* frequency index of the 
frequencies received in SI5* */
+       int16_t                         arfcn; /* ARFCN or -1 (if not found in 
SI5*) */
+       uint8_t                         bsic;
+       bool                            barred; /* Cell is barred, values below 
are invalid. */
+       bool                            la_different; /* Location area is 
different, so CRH is valid. */
+       uint8_t                         cell_resel_hyst_db;
+       uint8_t                         ms_txpwr_max_cch;
+       uint8_t                         rxlev_acc_min_db;
+       uint8_t                         cell_resel_offset;
+       uint8_t                         temp_offset;
+       uint8_t                         penalty_time;
+};
+
 /* structure of all received system information */
 struct gsm48_sysinfo {
        /* flags of available information */
        uint8_t                         si1, si2, si2bis, si2ter, si3,
                                        si4, si5, si5bis, si5ter, si6,
                                        si13;
+       bool                            si10;

        /* memory maps to simply detect change in system info messages */
        uint8_t                         si1_msg[23];
@@ -36,6 +51,7 @@
        uint8_t                         si5b_msg[18];
        uint8_t                         si5t_msg[18];
        uint8_t                         si6_msg[18];
+       uint8_t                         si10_msg[21];
        uint8_t                         si13_msg[23];

        struct  gsm_sysinfo_freq        freq[1024]; /* all frequencies */
@@ -158,6 +174,10 @@
        uint8_t                         nb_reest_denied; /* 1 = denied */
        uint8_t                         nb_cell_barr; /* 1 = barred */
        uint16_t                        nb_class_barr; /* bit 10 is emergency */
+
+       /* SI 10 */
+       uint8_t                         si10_cells; /* number neighbor cells 
found in SI 10 */
+       struct si10_cell_info           si10_cell[32];  /* 32 neighbor cell 
descriptions */
 };

 char *gsm_print_arfcn(uint16_t arfcn);
@@ -191,6 +211,8 @@
                             const struct gsm48_system_information_type_5ter 
*si, int len);
 int gsm48_decode_sysinfo6(struct gsm48_sysinfo *s,
                          const struct gsm48_system_information_type_6 *si, int 
len);
+int gsm48_decode_sysinfo10(struct gsm48_sysinfo *s,
+                          const struct gsm48_system_information_type_10 *si, 
int len);
 int gsm48_decode_sysinfo13(struct gsm48_sysinfo *s,
                           const struct gsm48_system_information_type_13 *si, 
int len);
 int gsm48_decode_mobile_alloc(struct gsm_sysinfo_freq *freq,
diff --git a/src/host/layer23/src/common/sysinfo.c 
b/src/host/layer23/src/common/sysinfo.c
index 12780c2..d2ed792 100644
--- a/src/host/layer23/src/common/sysinfo.c
+++ b/src/host/layer23/src/common/sysinfo.c
@@ -601,6 +601,188 @@
        return 0;
 }

+/* Decode "SI 10 Rest Octets" (10.5.2.44) */
+static int gsm48_decode_si10_rest_first(struct gsm48_sysinfo *s, struct bitvec 
*bv,
+                                       struct si10_cell_info *c)
+{
+       uint8_t ba_ind;
+
+       /* <BA ind : bit(1)> */
+       ba_ind = bitvec_get_uint(bv, 1);
+       if (ba_ind != s->nb_ba_ind_si5) {
+               LOGP(DRR, LOGL_NOTICE, "SI10: Band indicator %u != band 
indicator %u of SI5!\n", ba_ind,
+                    s->nb_ba_ind_si5);
+               return EOF;
+       }
+
+       /* { L <spare padding> | H <neighbour information> } */
+       if (bitvec_get_bit_high(bv) != H) {
+               LOGP(DRR, LOGL_INFO, "SI10: No neighbor cell defined.\n");
+               return EOF;
+       }
+
+       /* <first frequency: bit(5)> */
+       c->index = bitvec_get_uint(bv, 5);
+
+       /* <bsic : bit(6)> */
+       c->bsic = bitvec_get_uint(bv, 6);
+
+       /* { H <cell parameters> | L } */
+       if (bitvec_get_bit_high(bv) != H) {
+               LOGP(DRR, LOGL_NOTICE, "SI10: No cell parameter for first cell, 
cannot continue to decode!\n");
+               return EOF;
+       }
+
+       /* <cell barred (H)> | L <further cell info> */
+       if (bitvec_get_bit_high(bv) == H) {
+               c->barred = true;
+               return 0;
+       }
+
+       /* { H <cell reselect hysteresis : bit(3)> | L } */
+       if (bitvec_get_bit_high(bv) == H) {
+               c->la_different = true;
+               c->cell_resel_hyst_db = bitvec_get_uint(bv, 3) * 2;
+       }
+
+       /* <ms txpwr max cch : bit(5)> */
+       c->ms_txpwr_max_cch = bitvec_get_uint(bv, 5);
+       /* <rxlev access min : bit(6)> */
+       c->rxlev_acc_min_db = bitvec_get_uint(bv, 6) - 110;
+       /* <cell reselect offset : bit(6)> */
+       c->cell_resel_offset = bitvec_get_uint(bv, 6);
+       /* <temporary offset : bit(3)> */
+       c->temp_offset = bitvec_get_uint(bv, 3);
+       /* <penalty time : bit(5)> */
+       c->penalty_time = bitvec_get_uint(bv, 5);
+
+       return 0;
+}
+
+static int gsm48_decode_si10_rest_other(struct gsm48_sysinfo *s, struct bitvec 
*bv,
+                                       struct si10_cell_info *c)
+{
+       int rc;
+
+       /* { H <info field> }** L <spare padding> */
+       if (bitvec_get_bit_high(bv) != H)
+               return EOF;
+
+       c->index = (c->index + 1) & 0x1f;
+       /* <next frequency (H)>** L <differential cell info> */
+       /* Increment frequency number for every <info field> and every <next 
frequency> occurence. */
+       while ((rc = bitvec_get_bit_high(bv)) == H)
+               c->index = (c->index + 1) & 0x1f;
+       if (rc < 0)
+               goto short_read;
+
+       /* { H <BCC : bit(3)> | L <bsic : bit(6)> } */
+       rc = bitvec_get_bit_high(bv);
+       if (rc < 0)
+               goto short_read;
+       if (rc == H) {
+               rc = bitvec_get_uint(bv, 3);
+               if (rc < 0)
+                       goto short_read;
+               c->bsic = (c->bsic & 0x07) | rc;
+       } else {
+               rc = bitvec_get_uint(bv, 6);
+               if (rc < 0)
+                       goto short_read;
+               c->bsic = rc;
+       }
+
+       /* { H <diff cell pars> | L } */
+       rc = bitvec_get_bit_high(bv);
+       if (rc < 0)
+               goto short_read;
+       if (rc != H)
+               return 0;
+
+       /* <cell barred (H)> | L <further cell info> */
+       rc = bitvec_get_bit_high(bv);
+       if (rc < 0)
+               goto short_read;
+       if (rc == H) {
+               c->barred = true;
+               return 0;
+       }
+
+       /* { H <cell reselect hysteresis : bit(3)> | L } */
+       rc = bitvec_get_bit_high(bv);
+       if (rc < 0)
+               goto short_read;
+       if (rc == H) {
+               c->la_different = true;
+               rc = bitvec_get_uint(bv, 3);
+               if (rc < 0)
+                       goto short_read;
+               c->cell_resel_hyst_db = bitvec_get_uint(bv, 3) * 2;
+       }
+
+       /* { H <ms txpwr max cch : bit(5)> | L } */
+       rc = bitvec_get_bit_high(bv);
+       if (rc < 0)
+               goto short_read;
+       if (rc == H) {
+               rc = bitvec_get_uint(bv, 5);
+               if (rc < 0)
+                       goto short_read;
+               c->ms_txpwr_max_cch = rc;
+       }
+
+       /* { H <rxlev access min : bit(6)> | L } */
+       rc = bitvec_get_bit_high(bv);
+       if (rc < 0)
+               goto short_read;
+       if (rc == H) {
+               rc = bitvec_get_uint(bv, 6);
+               if (rc < 0)
+                       goto short_read;
+               c->rxlev_acc_min_db = rc - 110;
+       } else
+               c->rxlev_acc_min_db = - 110;
+
+       /* { H <cell reselect offset : bit(6)> | L } */
+       rc = bitvec_get_bit_high(bv);
+       if (rc < 0)
+               goto short_read;
+       if (rc == H) {
+               rc = bitvec_get_uint(bv, 6);
+               if (rc < 0)
+                       goto short_read;
+               c->cell_resel_offset = rc;
+       }
+
+       /* { H <temporary offset : bit(3)> | L } */
+       rc = bitvec_get_bit_high(bv);
+       if (rc < 0)
+               goto short_read;
+       if (rc == H) {
+               rc = bitvec_get_uint(bv, 3);
+               if (rc < 0)
+                       goto short_read;
+               c->temp_offset = rc;
+       }
+
+       /* { H <penalty time : bit(5)> | L } */
+       rc = bitvec_get_bit_high(bv);
+       if (rc < 0)
+               goto short_read;
+       if (rc == H) {
+               rc = bitvec_get_uint(bv, 5);
+               if (rc < 0)
+                       goto short_read;
+               c->penalty_time = rc;
+       }
+
+       return 0;
+
+short_read:
+       LOGP(DRR, LOGL_NOTICE, "SI10: Short read of differential cell info.\n");
+       return -EINVAL;
+}
+
 int gsm48_decode_sysinfo1(struct gsm48_sysinfo *s,
                          const struct gsm48_system_information_type_1 *si, int 
len)
 {
@@ -787,6 +969,7 @@
                         0xce, FREQ_TYPE_REP_5);

        s->si5 = 1;
+       s->si10 = false;

        return 0;
 }
@@ -804,6 +987,7 @@
                         0xce, FREQ_TYPE_REP_5bis);

        s->si5bis = 1;
+       s->si10 = false;

        return 0;
 }
@@ -821,6 +1005,7 @@
                         0x8e, FREQ_TYPE_REP_5ter);

        s->si5ter = 1;
+       s->si10 = false;

        return 0;
 }
@@ -852,6 +1037,90 @@
        return 0;
 }

+static int16_t arfcn_from_freq(struct gsm48_sysinfo *s, uint16_t index)
+{
+       uint16_t arfcn, i = 0;
+
+       /* First, search for the P-GSM ARFCN. */
+       for (arfcn = 1; arfcn < 124; arfcn++) {
+               if (!(s->freq[arfcn].mask & FREQ_TYPE_REP))
+                       continue;
+               if (index == i++)
+                       return arfcn;
+       }
+
+       /* Second, search for ARFCN 0. */
+       if ((s->freq[arfcn].mask & FREQ_TYPE_REP)) {
+               if (index == i++)
+                       return arfcn;
+       }
+
+       /* Third, search for all other ARFCN. */
+       for (arfcn = 125; arfcn < 1024; arfcn++) {
+               if (!(s->freq[arfcn].mask & FREQ_TYPE_REP))
+                       continue;
+               if (index == i++)
+                       return arfcn;
+       }
+
+       /* If not found, return EOF (-1) as idicator. */
+       return EOF;
+}
+
+int gsm48_decode_sysinfo10(struct gsm48_sysinfo *s,
+                          const struct gsm48_system_information_type_10 *si, 
int len)
+{
+       int payload_len = len - sizeof(*si);
+       struct bitvec bv;
+       int i;
+       int rc;
+
+       bv = (struct bitvec) {
+               .data_len = payload_len,
+               .data = (uint8_t *)si->rest_octets,
+       };
+
+       memcpy(s->si10_msg, si, OSMO_MIN(len, sizeof(s->si10_msg)));
+
+       /* Clear cell list. */
+       s->si10_cells = 0;
+       memset(s->si10_cell, 0, sizeof(s->si10_cell));
+
+       /* SI 10 Rest Octets of first neighbor cell, if included. */
+       rc = gsm48_decode_si10_rest_first(s, &bv, &s->si10_cell[0]);
+       puts("1");
+       if (rc == EOF) {
+       puts("2");
+               s->si10 = true;
+               return 0;
+       }
+       puts("3");
+       if (rc < 0)
+               return rc;
+       puts("5");
+       s->si10_cell[0].arfcn = arfcn_from_freq(s, s->si10_cell[0].index);
+       s->si10_cells++;
+
+       for (i = 1; i < ARRAY_SIZE(s->si10_cell); i++) {
+               /* Clone last cell info and then store differential elements. */
+               memcpy(&s->si10_cell[i], &s->si10_cell[i - 1], 
sizeof(s->si10_cell[i]));
+               /* SI 10 Rest Octets of other neighbor cell, if included. */
+               rc = gsm48_decode_si10_rest_other(s, &bv, &s->si10_cell[i]);
+               if (rc == EOF)
+                       break;
+       puts("6");
+               if (rc < 0)
+                       return rc;
+       puts("7");
+               s->si10_cell[i].arfcn = arfcn_from_freq(s, 
s->si10_cell[i].index);
+               s->si10_cells++;
+       }
+       puts("8");
+
+       s->si10 = true;
+       return 0;
+}
+
 int gsm48_decode_sysinfo13(struct gsm48_sysinfo *s,
                           const struct gsm48_system_information_type_13 *si, 
int len)
 {
diff --git a/src/host/layer23/src/mobile/gsm48_rr.c 
b/src/host/layer23/src/mobile/gsm48_rr.c
index a515338..502d7fe 100644
--- a/src/host/layer23/src/mobile/gsm48_rr.c
+++ b/src/host/layer23/src/mobile/gsm48_rr.c
@@ -2897,13 +2897,40 @@
        return gsm48_new_sysinfo(ms, si->system_information);
 }

-/* Receive "SYSTEM INFORMATION TYPE 10" message (9.1.50). */
+/* receive "SYSTEM INFORMATION 10" message (9.1.50) */
 static int gsm48_rr_rx_sysinfo_10(struct osmocom_ms *ms, struct msgb *msg)
 {
-       LOGP(DRR, LOGL_INFO, "SYSINFO 10\n");
+       /* NOTE: Short L2 header is included in this structure */
+       struct gsm48_system_information_type_10 *si = msgb_l3(msg);
+       struct gsm48_sysinfo *s = ms->cellsel.si;
+       int payload_len = msgb_l3len(msg) - sizeof(*si);

-       /* Ignore content. */
-       return -ENOTSUP;
+       if (!s) {
+               LOGP(DRR, LOGL_INFO, "No cell selected, SYSTEM INFORMATION 10 "
+                       "ignored\n");
+               return -EINVAL;
+       }
+
+       if (payload_len < 20) {
+               LOGP(DRR, LOGL_NOTICE, "Short read of SYSTEM INFORMATION 10 "
+                       "message.\n");
+               return -EINVAL;
+       }
+
+       /* No complete SI5, cannot decode yet. */
+       if (!s->si5 || !(s->si5bis || !s->nb_ext_ind_si5))
+               return 0;
+
+       /* We decode when changed or when SI10 could not decoded, due to 
missing neighbor cell infos. */
+       if (!memcmp(si, s->si10_msg, OSMO_MIN(msgb_l3len(msg), 
sizeof(s->si10_msg))) && s->si10)
+               return 0;
+
+       LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 10\n");
+
+       gsm48_decode_sysinfo10(s, si, msgb_l3len(msg));
+
+       /* We cannot call gsm48_new_sysinfo, because it requires regular 
message types. */
+       return 0;
 }

 /* receive "SYSTEM INFORMATION 13" message (9.1.43a) */

--
To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/34614?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: I81c7929f6d951d8eef7d08624f0b72830370c448
Gerrit-Change-Number: 34614
Gerrit-PatchSet: 1
Gerrit-Owner: jolly <andr...@eversberg.eu>
Gerrit-MessageType: newchange

Reply via email to