/* GSM 04.18 ETSI TS 101 503 V8.27.0 (2006-05) <SI6 rest octets> ::= {L | H <PCH and NCH info>} {L | H <VBS/VGCS options : bit(2)>} { < DTM_support : bit == L > I < DTM_support : bit == H > < RAC : bit (8) > < MAX_LAPDm : bit (3) > } < Band indicator > { L | H < GPRS_MS_TXPWR_MAX_CCH : bit (5) > } <implicit spare >; */ int rest_octets_si6(uint8_t *data, bool is1800_net) { struct bitvec bv; memset(&bv, 0, sizeof(bv)); bv.data = data; bv.data_len = 1; /* no PCH/NCH info */ bitvec_set_bit(&bv, L); /* no VBS/VGCS options */ bitvec_set_bit(&bv, L); /* no DTM_support */ bitvec_set_bit(&bv, L); /* band indicator */ if (is1800_net) bitvec_set_bit(&bv, L); else bitvec_set_bit(&bv, H); /* no GPRS_MS_TXPWR_MAX_CCH */ bitvec_set_bit(&bv, L); bitvec_spare_padding(&bv, (bv.data_len * 8) - 1); return bv.data_len; }
static inline void test_spare(struct bitvec *bv, unsigned n) { bitvec_to_string_r(bv, lol); unsigned bvlen = bv->cur_bit; int sp = bitvec_spare_padding(bv, n); printf("%c> SPARE %s [%d] -%d-> [%d]:\n", bit_value_to_char(L), lol, bvlen, n, sp); bitvec_to_string_r(bv, lol); printf(" %s [%d]\n\n", lol, bv->cur_bit); }
/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */ int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3) { struct bitvec bv; memset(&bv, 0, sizeof(bv)); bv.data = data; bv.data_len = 4; /* Optional Selection Parameters */ append_selection_params(&bv, &si3->selection_params); /* Optional Power Offset */ append_power_offset(&bv, &si3->power_offset); /* Do we have a SI2ter on the BCCH? */ if (si3->si2ter_indicator) bitvec_set_bit(&bv, H); else bitvec_set_bit(&bv, L); /* Early Classmark Sending Control */ if (si3->early_cm_ctrl) bitvec_set_bit(&bv, H); else bitvec_set_bit(&bv, L); /* Do we have a SI Type 9 on the BCCH? */ if (si3->scheduling.present) { bitvec_set_bit(&bv, H); bitvec_set_uint(&bv, si3->scheduling.where, 3); } else bitvec_set_bit(&bv, L); /* GPRS Indicator */ append_gprs_ind(&bv, &si3->gprs_ind); /* 3G Early Classmark Sending Restriction. If H, then controlled by * early_cm_ctrl above */ if (si3->early_cm_restrict_3g) bitvec_set_bit(&bv, L); else bitvec_set_bit(&bv, H); if (si3->si2quater_indicator) { bitvec_set_bit(&bv, H); /* indicator struct present */ bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */ } bitvec_spare_padding(&bv, (bv.data_len*8)-1); return bv.data_len; }
/* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos) { struct bitvec bv; memset(&bv, 0, sizeof(bv)); bv.data = data; bv.data_len = 1; if (nch_pos) { bitvec_set_bit(&bv, H); bitvec_set_uint(&bv, *nch_pos, 5); } else bitvec_set_bit(&bv, L); bitvec_spare_padding(&bv, 7); return bv.data_len; }
/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */ int rest_octets_si13(uint8_t *data, const struct gsm48_si13_info *si13) { struct bitvec bv; memset(&bv, 0, sizeof(bv)); bv.data = data; bv.data_len = 20; if (0) { /* No rest octets */ bitvec_set_bit(&bv, L); } else { bitvec_set_bit(&bv, H); bitvec_set_uint(&bv, si13->bcch_change_mark, 3); bitvec_set_uint(&bv, si13->si_change_field, 4); if (1) { bitvec_set_bit(&bv, 0); } else { bitvec_set_bit(&bv, 1); bitvec_set_uint(&bv, si13->bcch_change_mark, 2); append_gprs_mobile_alloc(&bv); } /* PBCCH not present in cell: it shall never be indicated according to 3GPP TS 44.018 Table 10.5.2.37b.1 */ bitvec_set_bit(&bv, 0); bitvec_set_uint(&bv, si13->rac, 8); bitvec_set_bit(&bv, si13->spgc_ccch_sup); bitvec_set_uint(&bv, si13->prio_acc_thr, 3); bitvec_set_uint(&bv, si13->net_ctrl_ord, 2); append_gprs_cell_opt(&bv, &si13->cell_opts); append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars); /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */ bitvec_set_bit(&bv, H); /* added Release 99 */ /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS * was only added in this Release */ bitvec_set_bit(&bv, 1); } bitvec_spare_padding(&bv, (bv.data_len*8)-1); return bv.data_len; }
/* generate SI2quater rest octets: 3GPP TS 44.018 § 10.5.2.33b */ int rest_octets_si2quater(uint8_t *data, struct gsm_bts *bts) { int rc; struct bitvec bv; if (bts->si2q_count < bts->si2q_index) return -EINVAL; bv.data = data; bv.data_len = 20; bitvec_zero(&bv); /* BA_IND: Set to '0' as that's what we use for SI2xxx type, * whereas '1' is used for SI5xxx type messages. The point here * is to be able to correlate whether a given MS measurement * report was using the neighbor cells advertised in SI2 or in * SI5, as those two could very well be different */ bitvec_set_bit(&bv, 0); /* 3G_BA_IND */ bitvec_set_bit(&bv, 1); /* MP_CHANGE_MARK */ bitvec_set_bit(&bv, 0); /* SI2quater_INDEX */ bitvec_set_uint(&bv, bts->si2q_index, 4); /* SI2quater_COUNT */ bitvec_set_uint(&bv, bts->si2q_count, 4); /* No Measurement_Parameters Description */ bitvec_set_bit(&bv, 0); /* No GPRS_Real Time Difference Description */ bitvec_set_bit(&bv, 0); /* No GPRS_BSIC Description */ bitvec_set_bit(&bv, 0); /* No GPRS_REPORT PRIORITY Description */ bitvec_set_bit(&bv, 0); /* No GPRS_MEASUREMENT_Parameters Description */ bitvec_set_bit(&bv, 0); /* No NC Measurement Parameters */ bitvec_set_bit(&bv, 0); /* No extension (length) */ bitvec_set_bit(&bv, 0); rc = SI2Q_MAX_LEN - (bv.cur_bit + 3); if (rc > 0 && bts->si_common.uarfcn_length - bts->u_offset > 0) { rc = append_uarfcns(&bv, bts, rc); if (rc < 0) { LOGP(DRR, LOGL_ERROR, "SI2quater [%u/%u]: failed to append %zu UARFCNs due to range encoding " "failure: %s\n", bts->si2q_index, bts->si2q_count, bts->si_common.uarfcn_length, strerror(-rc)); return rc; } } else /* No 3G Neighbour Cell Description */ bitvec_set_bit(&bv, 0); /* No 3G Measurement Parameters Description */ bitvec_set_bit(&bv, 0); /* No GPRS_3G_MEASUREMENT Parameters Descr. */ bitvec_set_bit(&bv, 0); rc = SI2Q_MAX_LEN - bv.cur_bit; if (rc > 0 && si2q_earfcn_count(&bts->si_common.si2quater_neigh_list) - bts->e_offset > 0) append_earfcn(&bv, bts, rc); else /* No Additions in Rel-5: */ bitvec_set_bit(&bv, L); bitvec_spare_padding(&bv, (bv.data_len * 8) - 1); return bv.data_len; }
/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */ int rest_octets_si13(uint8_t *data, const struct gsm48_si13_info *si13) { struct bitvec bv; memset(&bv, 0, sizeof(bv)); bv.data = data; bv.data_len = 20; if (0) { /* No rest octets */ bitvec_set_bit(&bv, L); } else { bitvec_set_bit(&bv, H); bitvec_set_uint(&bv, si13->bcch_change_mark, 3); bitvec_set_uint(&bv, si13->si_change_field, 4); if (1) { bitvec_set_bit(&bv, 0); } else { bitvec_set_bit(&bv, 1); bitvec_set_uint(&bv, si13->bcch_change_mark, 2); append_gprs_mobile_alloc(&bv); } if (!si13->pbcch_present) { /* PBCCH not present in cell */ bitvec_set_bit(&bv, 0); bitvec_set_uint(&bv, si13->no_pbcch.rac, 8); bitvec_set_bit(&bv, si13->no_pbcch.spgc_ccch_sup); bitvec_set_uint(&bv, si13->no_pbcch.prio_acc_thr, 3); bitvec_set_uint(&bv, si13->no_pbcch.net_ctrl_ord, 2); append_gprs_cell_opt(&bv, &si13->cell_opts); append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars); } else { /* PBCCH present in cell */ bitvec_set_bit(&bv, 1); bitvec_set_uint(&bv, si13->pbcch.psi1_rep_per, 4); /* PBCCH Descripiton */ bitvec_set_uint(&bv, si13->pbcch.pb, 4); bitvec_set_uint(&bv, si13->pbcch.tsc, 3); bitvec_set_uint(&bv, si13->pbcch.tn, 3); switch (si13->pbcch.carrier_type) { case PBCCH_BCCH: bitvec_set_bit(&bv, 0); bitvec_set_bit(&bv, 0); break; case PBCCH_ARFCN: bitvec_set_bit(&bv, 0); bitvec_set_bit(&bv, 1); bitvec_set_uint(&bv, si13->pbcch.arfcn, 10); break; case PBCCH_MAIO: bitvec_set_bit(&bv, 1); bitvec_set_uint(&bv, si13->pbcch.maio, 6); break; } } /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */ bitvec_set_bit(&bv, H); /* added Release 99 */ /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS * was only added in this Release */ bitvec_set_bit(&bv, 1); } bitvec_spare_padding(&bv, (bv.data_len*8)-1); return bv.data_len; }