fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/30812 )
Change subject: layer23/sysinfo: implement decoding of SI13 Rest Octets ......................................................................
layer23/sysinfo: implement decoding of SI13 Rest Octets
Change-Id: Ia6ff7d4e37816c6321b54c1f7f8d7110e557f8c5 Related: SYS#5500 --- 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, 169 insertions(+), 12 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/12/30812/1
diff --git a/src/host/layer23/include/osmocom/bb/common/sysinfo.h b/src/host/layer23/include/osmocom/bb/common/sysinfo.h index 6a915d0..429b90d 100644 --- a/src/host/layer23/include/osmocom/bb/common/sysinfo.h +++ b/src/host/layer23/include/osmocom/bb/common/sysinfo.h @@ -21,7 +21,8 @@ struct gsm48_sysinfo { /* flags of available information */ uint8_t si1, si2, si2bis, si2ter, si3, - si4, si5, si5bis, si5ter, si6; + si4, si5, si5bis, si5ter, si6, + si13;
/* memory maps to simply detect change in system info messages */ uint8_t si1_msg[23]; @@ -34,6 +35,7 @@ uint8_t si5b_msg[18]; uint8_t si5t_msg[18]; uint8_t si6_msg[18]; + uint8_t si13_msg[23];
struct gsm_sysinfo_freq freq[1024]; /* all frequencies */ uint16_t hopping[64]; /* hopping arfcn */ @@ -66,9 +68,46 @@ uint8_t ecsm; uint8_t sched; uint8_t sched_where; - uint8_t gprs; - uint8_t gprs_ra_colour; - uint8_t gprs_si13_pos; + + struct { + /* si3/si4 rest */ + uint8_t supported; + uint8_t ra_colour; + uint8_t si13_pos; + + /* si13 rest */ + uint8_t hopping; + uint8_t hsn; + uint8_t rfl_num_len; + uint8_t rfl_num[4]; + + uint8_t ma_bitlen; + uint8_t ma_bitmap[64 / 8]; + uint8_t arfcn_idx_len; + uint8_t arfcn_idx[16]; + + /* PBCCH is not present */ + uint8_t rac; + uint8_t prio_acc_thresh; + uint8_t nco; + + /* GPRS Cell Options */ + uint8_t nmo; + uint8_t T3168; + uint8_t T3192; + uint8_t ab_type; + uint8_t ctrl_ack_type; + uint8_t bs_cv_max; + uint8_t pan_params_present; + uint8_t pan_dec; + uint8_t pan_inc; + uint8_t pan_max; + + /* EGPRS Cell Options */ + uint8_t egprs_supported; + uint8_t egprs_pkt_chan_req; + uint8_t egprs_bep_period; + } gprs;
/* cell selection */ int8_t ms_txpwr_max_cch; @@ -151,6 +190,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_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, const uint8_t *ma, uint8_t len, uint16_t *hopping, uint8_t *hopp_len, int si4); diff --git a/src/host/layer23/src/common/sysinfo.c b/src/host/layer23/src/common/sysinfo.c index a912e9c..7f86b57 100644 --- a/src/host/layer23/src/common/sysinfo.c +++ b/src/host/layer23/src/common/sysinfo.c @@ -23,6 +23,8 @@ #include <osmocom/core/utils.h> #include <osmocom/core/bitvec.h>
+#include <osmocom/gprs/rlcmac/gprs_rlcmac.h> + #include <osmocom/bb/common/osmocom_data.h> #include <osmocom/bb/common/networks.h> #include <osmocom/bb/common/logging.h> @@ -536,11 +538,11 @@ s->sched = 0; /* GPRS Indicator */ if (bitvec_get_bit_high(&bv) == H) { - s->gprs = 1; - s->gprs_ra_colour = bitvec_get_uint(&bv, 3); - s->gprs_si13_pos = bitvec_get_uint(&bv, 1); + s->gprs.supported = 1; + s->gprs.ra_colour = bitvec_get_uint(&bv, 3); + s->gprs.si13_pos = bitvec_get_uint(&bv, 1); } else - s->gprs = 0; + s->gprs.supported = 0;
return 0; } @@ -571,11 +573,11 @@ s->po = 0; /* GPRS Indicator */ if (bitvec_get_bit_high(&bv) == H) { - s->gprs = 1; - s->gprs_ra_colour = bitvec_get_uint(&bv, 3); - s->gprs_si13_pos = bitvec_get_uint(&bv, 1); + s->gprs.supported = 1; + s->gprs.ra_colour = bitvec_get_uint(&bv, 3); + s->gprs.si13_pos = bitvec_get_uint(&bv, 1); } else - s->gprs = 0; + s->gprs.supported = 0; // todo: more rest octet bits
return 0; @@ -840,6 +842,86 @@ return 0; }
+int gsm48_decode_sysinfo13(struct gsm48_sysinfo *s, + const struct gsm48_system_information_type_13 *si, int len) +{ + SI13_RestOctets_t si13ro; + int rc; + + rc = osmo_gprs_rlcmac_decode_si13ro(&si13ro, si->rest_octets, sizeof(s->si13_msg)); + if (rc != 0) { + LOGP(DRR, LOGL_ERROR, "Failed to parse SI13 Rest Octets\n"); + return rc; + } + + if (si13ro.UnionType != 0) { + LOGP(DRR, LOGL_NOTICE, "PBCCH is deprecated and not supported\n"); + return -ENOTSUP; + } + + s->gprs.hopping = si13ro.Exist_MA; + if (s->gprs.hopping) { + const GPRS_Mobile_Allocation_t *gma = &si13ro.GPRS_Mobile_Allocation; + + s->gprs.hsn = gma->HSN; + s->gprs.rfl_num_len = gma->ElementsOf_RFL_NUMBER; + memcpy(&s->gprs.rfl_num[0], &gma->RFL_NUMBER[0], sizeof(gma->RFL_NUMBER)); + + if (gma->UnionType == 0) { /* MA Bitmap */ + const MobileAllocation_t *ma = &gma->u.MA; + s->gprs.ma_bitlen = ma->MA_BitLength; + memcpy(&s->gprs.ma_bitmap[0], &ma->MA_BITMAP[0], sizeof(ma->MA_BITMAP)); + } else { /* ARFCN Index List */ + const ARFCN_index_list_t *ai = &gma->u.ARFCN_index_list; + s->gprs.arfcn_idx_len = ai->ElementsOf_ARFCN_INDEX; + memcpy(&s->gprs.arfcn_idx[0], &ai->ARFCN_INDEX[0], sizeof(ai->ARFCN_INDEX)); + } + } + + const PBCCH_Not_present_t *np = &si13ro.u.PBCCH_Not_present; + + s->gprs.rac = np->RAC; + s->gprs.prio_acc_thresh = np->PRIORITY_ACCESS_THR; + s->gprs.nco = np->NETWORK_CONTROL_ORDER; + + const GPRS_Cell_Options_t *gco = &np->GPRS_Cell_Options; + + s->gprs.nmo = gco->NMO; + s->gprs.T3168 = gco->T3168; + s->gprs.T3192 = gco->T3192; + s->gprs.ab_type = gco->ACCESS_BURST_TYPE; + s->gprs.ctrl_ack_type = !gco->CONTROL_ACK_TYPE; /* inversed */ + s->gprs.bs_cv_max = gco->BS_CV_MAX; + + s->gprs.pan_params_present = gco->Exist_PAN; + if (s->gprs.pan_params_present) { + s->gprs.pan_dec = gco->PAN_DEC; + s->gprs.pan_dec = gco->PAN_INC; + s->gprs.pan_dec = gco->PAN_MAX; + } + + s->gprs.egprs_supported = 0; + if (gco->Exist_Extension_Bits) { + /* CSN.1 codec is not powerful enough (yet?) to decode this part :( */ + unsigned int ext_len = gco->Extension_Bits.extension_length; + const uint8_t *ext = &gco->Extension_Bits.Extension_Info[0]; + + s->gprs.egprs_supported = (ext[0] >> 7); + if (s->gprs.egprs_supported) { + if (ext_len < 6) + return -EINVAL; + s->gprs.egprs_pkt_chan_req = ~ext[0] & (1 << 6); /* inversed */ + s->gprs.egprs_bep_period = (ext[0] >> 2) & 0x0f; + } + } + + /* TODO: GPRS_Power_Control_Parameters */ + + s->si13 = 1; + + return 0; +} + int gsm48_encode_lai_hex(struct gsm48_loc_area_id *lai, uint16_t mcc, uint16_t mnc, uint16_t lac) { diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c index 8a920ee..deb76c9 100644 --- a/src/host/layer23/src/mobile/gsm48_rr.c +++ b/src/host/layer23/src/mobile/gsm48_rr.c @@ -2086,6 +2086,38 @@ return gsm48_new_sysinfo(ms, si->system_information); }
+/* receive "SYSTEM INFORMATION 13" message (9.1.43a) */ +static int gsm48_rr_rx_sysinfo13(struct osmocom_ms *ms, struct msgb *msg) +{ + const struct gsm48_system_information_type_13 *si = msgb_l3(msg); + int rest_octets_len = msgb_l3len(msg) - sizeof(si->header); + struct gsm48_sysinfo *s = ms->cellsel.si; + + if (!s) { + LOGP(DRR, LOGL_INFO, + "No cell selected, SYSTEM INFORMATION 13 ignored\n"); + return -EINVAL; + } + + if (rest_octets_len < 0) { + LOGP(DRR, LOGL_NOTICE, + "Short read of SYSTEM INFORMATION 13 message.\n"); + return -EINVAL; + } + + if (!memcmp(si, s->si13_msg, MIN(msgb_l3len(msg), sizeof(s->si6_msg)))) + return 0; + + gsm48_decode_sysinfo13(s, si, msgb_l3len(msg)); + + LOGP(DRR, LOGL_INFO, + "New SYSTEM INFORMATION 13 (%s, RAC 0x%02x, NCO %u, MNO %u)\n", + s->gprs.egprs_supported ? "EGPRS" : "GPRS only", + s->gprs.rac, s->gprs.nco, s->gprs.nmo); + + return gsm48_new_sysinfo(ms, si->header.system_information); +} + /* * paging */ @@ -4820,6 +4852,8 @@ return gsm48_rr_rx_sysinfo3(ms, msg); case GSM48_MT_RR_SYSINFO_4: return gsm48_rr_rx_sysinfo4(ms, msg); + case GSM48_MT_RR_SYSINFO_13: + return gsm48_rr_rx_sysinfo13(ms, msg); default: #if 0 LOGP(DRR, LOGL_NOTICE, "BCCH message type 0x%02x not sup.\n",