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