blob: a527598560d156033014a75503977155308c49a9 [file] [log] [blame]
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface,
2 * rest octet handling according to
3 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
4
5/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
6 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
Harald Welte912d96d2019-05-27 23:17:46 +020010 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +020012 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte912d96d2019-05-27 23:17:46 +020017 * GNU General Public License for more details.
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +020018 *
Harald Welte912d96d2019-05-27 23:17:46 +020019 * You should have received a copy of the GNU General Public License
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +020020 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
Harald Welte912d96d2019-05-27 23:17:46 +020022 * SPDX-License-Identifier: GPL-2.0+
23 *
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +020024 */
25
26#include <string.h>
27#include <stdlib.h>
28#include <errno.h>
29#include <stdbool.h>
30
31#include <osmocom/core/bitvec.h>
32#include <osmocom/gsm/bitvec_gsm.h>
33#include <osmocom/gsm/sysinfo.h>
34#include <osmocom/gsm/gsm48_arfcn_range_encode.h>
35#include <osmocom/gsm/gsm48_rest_octets.h>
36
37/* generate SI1 rest octets */
Harald Welte428d03b2019-05-28 18:46:20 +020038int osmo_gsm48_rest_octets_si1_encode(uint8_t *data, uint8_t *nch_pos, int is1800_net)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +020039{
40 struct bitvec bv;
41
42 memset(&bv, 0, sizeof(bv));
43 bv.data = data;
44 bv.data_len = 1;
45
46 if (nch_pos) {
47 bitvec_set_bit(&bv, H);
48 bitvec_set_uint(&bv, *nch_pos, 5);
Harald Welte65aabd42020-10-15 08:04:49 +020049 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +020050 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +020051 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +020052
53 if (is1800_net)
54 bitvec_set_bit(&bv, L);
55 else
56 bitvec_set_bit(&bv, H);
57
58 bitvec_spare_padding(&bv, 6);
59 return bv.data_len;
60}
61
62/* Append Repeated E-UTRAN Neighbour Cell to bitvec: see 3GPP TS 44.018 Table 10.5.2.33b.1 */
63static inline bool append_eutran_neib_cell(struct bitvec *bv, const struct osmo_earfcn_si2q *e, size_t *e_offset,
64 uint8_t budget)
65{
66 unsigned i, skip = 0;
67 int16_t rem = budget - 6; /* account for mandatory stop bit and THRESH_E-UTRAN_high */
68 uint8_t earfcn_budget;
69
70 if (budget <= 6)
71 return false;
72
73 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
74
75 /* first we have to properly adjust budget requirements */
76 if (e->prio_valid) /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
77 rem -= 4;
78 else
79 rem--;
80
81 if (e->thresh_lo_valid) /* THRESH_E-UTRAN_low: */
82 rem -= 6;
83 else
84 rem--;
85
86 if (e->qrxlm_valid) /* E-UTRAN_QRXLEVMIN: */
87 rem -= 6;
88 else
89 rem--;
90
91 if (rem < 0)
92 return false;
93
94 /* now we can proceed with actually adding EARFCNs within adjusted budget limit */
95 for (i = 0; i < e->length; i++) {
96 if (e->arfcn[i] != OSMO_EARFCN_INVALID) {
97 if (skip < *e_offset) {
98 skip++; /* ignore EARFCNs added on previous calls */
99 } else {
100 earfcn_budget = 17; /* compute budget per-EARFCN */
101 if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
102 earfcn_budget++;
103 else
104 earfcn_budget += 4;
105
106 if (rem - earfcn_budget < 0)
107 break;
108 else {
109 (*e_offset)++;
110 rem -= earfcn_budget;
111
112 if (rem < 0)
113 return false;
114
115 bitvec_set_bit(bv, 1); /* EARFCN: */
116 bitvec_set_uint(bv, e->arfcn[i], 16);
117
118 if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
119 bitvec_set_bit(bv, 0);
120 else { /* Measurement Bandwidth: 9.1.54 */
121 bitvec_set_bit(bv, 1);
122 bitvec_set_uint(bv, e->meas_bw[i], 3);
123 }
124 }
125 }
126 }
127 }
128
129 /* stop bit - end of EARFCN + Measurement Bandwidth sequence */
130 bitvec_set_bit(bv, 0);
131
132 /* Note: we don't support different EARFCN arrays each with different priority, threshold etc. */
133
134 if (e->prio_valid) {
135 /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
136 bitvec_set_bit(bv, 1);
137 bitvec_set_uint(bv, e->prio, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200138 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200139 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200140 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200141
142 /* THRESH_E-UTRAN_high */
143 bitvec_set_uint(bv, e->thresh_hi, 5);
144
145 if (e->thresh_lo_valid) {
146 /* THRESH_E-UTRAN_low: */
147 bitvec_set_bit(bv, 1);
148 bitvec_set_uint(bv, e->thresh_lo, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200149 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200150 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200151 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200152
153 if (e->qrxlm_valid) {
154 /* E-UTRAN_QRXLEVMIN: */
155 bitvec_set_bit(bv, 1);
156 bitvec_set_uint(bv, e->qrxlm, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200157 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200158 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200159 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200160
161 return true;
162}
163
164static inline void append_earfcn(struct bitvec *bv, const struct osmo_earfcn_si2q *e, size_t *e_offset, uint8_t budget)
165{
166 bool appended;
167 unsigned int old = bv->cur_bit; /* save current position to make rollback possible */
168 int rem = budget - 25;
169 if (rem <= 0)
170 return;
171
172 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
173
174 /* Additions in Rel-5: */
175 bitvec_set_bit(bv, H);
176 /* No 3G Additional Measurement Param. Descr. */
177 bitvec_set_bit(bv, 0);
178 /* No 3G ADDITIONAL MEASUREMENT Param. Descr. 2 */
179 bitvec_set_bit(bv, 0);
180 /* Additions in Rel-6: */
181 bitvec_set_bit(bv, H);
182 /* 3G_CCN_ACTIVE */
183 bitvec_set_bit(bv, 0);
184 /* Additions in Rel-7: */
185 bitvec_set_bit(bv, H);
186 /* No 700_REPORTING_OFFSET */
187 bitvec_set_bit(bv, 0);
188 /* No 810_REPORTING_OFFSET */
189 bitvec_set_bit(bv, 0);
190 /* Additions in Rel-8: */
191 bitvec_set_bit(bv, H);
192
193 /* Priority and E-UTRAN Parameters Description */
194 bitvec_set_bit(bv, 1);
195
196 /* No Serving Cell Priority Parameters Descr. */
197 bitvec_set_bit(bv, 0);
198 /* No 3G Priority Parameters Description */
199 bitvec_set_bit(bv, 0);
200 /* E-UTRAN Parameters Description */
201 bitvec_set_bit(bv, 1);
202
203 /* E-UTRAN_CCN_ACTIVE */
204 bitvec_set_bit(bv, 0);
205 /* E-UTRAN_Start: 9.1.54 */
206 bitvec_set_bit(bv, 1);
207 /* E-UTRAN_Stop: 9.1.54 */
208 bitvec_set_bit(bv, 1);
209
210 /* No E-UTRAN Measurement Parameters Descr. */
211 bitvec_set_bit(bv, 0);
212 /* No GPRS E-UTRAN Measurement Param. Descr. */
213 bitvec_set_bit(bv, 0);
214
215 /* Note: each of next 3 "repeated" structures might be repeated any
216 (0, 1, 2...) times - we only support 1 and 0 */
217
218 /* Repeated E-UTRAN Neighbour Cells */
219 bitvec_set_bit(bv, 1);
220
221 appended = append_eutran_neib_cell(bv, e, e_offset, rem);
222 if (!appended) { /* appending is impossible within current budget: rollback */
223 bv->cur_bit = old;
224 return;
225 }
226
227 /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */
228 bitvec_set_bit(bv, 0);
229
230 /* Note: following 2 repeated structs are not supported ATM */
231 /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */
232 bitvec_set_bit(bv, 0);
233 /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */
234 bitvec_set_bit(bv, 0);
235
236 /* Priority and E-UTRAN Parameters Description ends here */
237 /* No 3G CSG Description */
238 bitvec_set_bit(bv, 0);
239 /* No E-UTRAN CSG Description */
240 bitvec_set_bit(bv, 0);
241 /* No Additions in Rel-9: */
242 bitvec_set_bit(bv, L);
243}
244
245static int range_encode(enum osmo_gsm48_range r, int *arfcns, int arfcns_used, int *w,
246 int f0, uint8_t *chan_list)
247{
248 /*
249 * Manipulate the ARFCN list according to the rules in J4 depending
250 * on the selected range.
251 */
252 int rc, f0_included;
253
254 osmo_gsm48_range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
255
256 rc = osmo_gsm48_range_enc_arfcns(r, arfcns, arfcns_used, w, 0);
257 if (rc < 0)
258 return rc;
259
260 /* Select the range and the amount of bits needed */
261 switch (r) {
262 case OSMO_GSM48_ARFCN_RANGE_128:
Harald Welte1276c172019-05-28 18:38:35 +0200263 return osmo_gsm48_range_enc_128(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200264 case OSMO_GSM48_ARFCN_RANGE_256:
Harald Welte1276c172019-05-28 18:38:35 +0200265 return osmo_gsm48_range_enc_256(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200266 case OSMO_GSM48_ARFCN_RANGE_512:
Harald Welte1276c172019-05-28 18:38:35 +0200267 return osmo_gsm48_range_enc_512(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200268 case OSMO_GSM48_ARFCN_RANGE_1024:
Harald Welte1276c172019-05-28 18:38:35 +0200269 return osmo_gsm48_range_enc_1024(chan_list, f0, f0_included, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200270 default:
271 return -ERANGE;
272 };
273
274 return f0_included;
275}
276
277static inline int f0_helper(int *sc, size_t length, uint8_t *chan_list)
278{
279 int w[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS] = { 0 };
280
281 return range_encode(OSMO_GSM48_ARFCN_RANGE_1024, sc, length, w, 0, chan_list);
282}
283
284/* Return p(n) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */
285static unsigned range1024_p(unsigned n)
286{
287 switch (n) {
288 case 0: return 0;
289 case 1: return 10;
290 case 2: return 19;
291 case 3: return 28;
292 case 4: return 36;
293 case 5: return 44;
294 case 6: return 52;
295 case 7: return 60;
296 case 8: return 67;
297 case 9: return 74;
298 case 10: return 81;
299 case 11: return 88;
300 case 12: return 95;
301 case 13: return 102;
302 case 14: return 109;
303 case 15: return 116;
304 case 16: return 122;
305 default: return 0;
306 }
307}
308
309/* Estimate how many bits it'll take to append single FDD UARFCN */
310static inline int append_utran_fdd_length(uint16_t u, const int *sc, size_t sc_len, size_t length)
311{
312 uint8_t chan_list[16] = { 0 };
313 int tmp[sc_len], f0;
314
315 memcpy(tmp, sc, sizeof(tmp));
316
317 f0 = f0_helper(tmp, length, chan_list);
318 if (f0 < 0)
319 return f0;
320
321 return 21 + range1024_p(length);
322}
323
324/* Append single FDD UARFCN */
325static inline int append_utran_fdd(struct bitvec *bv, uint16_t u, int *sc, size_t length)
326{
327 uint8_t chan_list[16] = { 0 };
328 int f0 = f0_helper(sc, length, chan_list);
329
330 if (f0 < 0)
331 return f0;
332
333 /* Repeated UTRAN FDD Neighbour Cells */
334 bitvec_set_bit(bv, 1);
335
336 /* FDD-ARFCN */
337 bitvec_set_bit(bv, 0);
338 bitvec_set_uint(bv, u, 14);
339
340 /* FDD_Indic0: parameter value '0000000000' is a member of the set? */
341 bitvec_set_bit(bv, f0);
342 /* NR_OF_FDD_CELLS */
343 bitvec_set_uint(bv, length, 5);
344
345 f0 = bv->cur_bit;
346 bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list);
347 bv->cur_bit = f0 + range1024_p(length);
348
349 return 21 + range1024_p(length);
350}
351
352static inline int try_adding_uarfcn(struct bitvec *bv, uint16_t *scramble_list,
353 size_t uarfcn_length, size_t *u_offset,
354 uint16_t uarfcn, uint8_t num_sc, uint8_t start_pos, uint8_t budget)
355{
356 int i, k, rc, a[uarfcn_length];
357
358 if (budget < 23)
359 return -ENOMEM;
360
361 /* copy corresponding Scrambling Codes: range encoder make in-place modifications */
362 for (i = start_pos, k = 0; i < num_sc; a[k++] = scramble_list[i++]);
363
364 /* estimate bit length requirements */
365 rc = append_utran_fdd_length(uarfcn, a, uarfcn_length, k);
366 if (rc < 0)
367 return rc; /* range encoder failure */
368
369 if (budget - rc <= 0)
370 return -ENOMEM; /* we have ran out of budget in current SI2q */
371
372 /* compute next offset */
373 *u_offset += k;
374
375 return budget - append_utran_fdd(bv, uarfcn, a, k);
376}
377
378/* Append multiple FDD UARFCNs */
379static inline void append_uarfcns(struct bitvec *bv, const uint16_t *uarfcn_list, size_t *u_offset,
380 size_t uarfcn_length, uint16_t *scramble_list, uint8_t budget)
381{
382 int i, rem = budget - 7, st = *u_offset; /* account for constant bits right away */
383 uint16_t cu = uarfcn_list[*u_offset]; /* caller ensures that length is positive */
384
385 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
386
387 if (budget <= 7)
388 return;
389
390 /* 3G Neighbour Cell Description */
391 bitvec_set_bit(bv, 1);
392 /* No Index_Start_3G */
393 bitvec_set_bit(bv, 0);
394 /* No Absolute_Index_Start_EMR */
395 bitvec_set_bit(bv, 0);
396
397 /* UTRAN FDD Description */
398 bitvec_set_bit(bv, 1);
399 /* No Bandwidth_FDD */
400 bitvec_set_bit(bv, 0);
401
402 for (i = *u_offset; i <= uarfcn_length; i++)
403 if (uarfcn_list[i] != cu) { /* we've reached new UARFCN */
404 rem = try_adding_uarfcn(bv, scramble_list, uarfcn_length, u_offset, cu, i, st, rem);
405 if (rem < 0)
406 break;
407
408 if (i < uarfcn_length) {
409 cu = uarfcn_list[i];
410 st = i;
Harald Welte65aabd42020-10-15 08:04:49 +0200411 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200412 break;
Harald Welte65aabd42020-10-15 08:04:49 +0200413 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200414 }
415
416 /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */
417 bitvec_set_bit(bv, 0);
418
419 /* UTRAN TDD Description */
420 bitvec_set_bit(bv, 0);
421}
422
423static size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e)
424{
425 unsigned i, ret = 0;
426
427 if (!e)
428 return 0;
429
430 for (i = 0; i < e->length; i++)
431 if (e->arfcn[i] != OSMO_EARFCN_INVALID)
432 ret++;
433
434 return ret;
435}
436
437/* generate SI2quater rest octets: 3GPP TS 44.018 § 10.5.2.33b */
Harald Welte428d03b2019-05-28 18:46:20 +0200438int osmo_gsm48_rest_octets_si2quater_encode(uint8_t *data, uint8_t si2q_index, uint8_t si2q_count,
439 const uint16_t *uarfcn_list, size_t *u_offset,
440 size_t uarfcn_length, uint16_t *scramble_list,
441 struct osmo_earfcn_si2q *si2quater_neigh_list,
442 size_t *e_offset)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200443{
444 int rc;
445 struct bitvec bv;
446
447 if (si2q_count < si2q_index)
448 return -EINVAL;
449
450 bv.data = data;
451 bv.data_len = 20;
452 bitvec_zero(&bv);
453
454 /* BA_IND: Set to '0' as that's what we use for SI2xxx type,
455 * whereas '1' is used for SI5xxx type messages. The point here
456 * is to be able to correlate whether a given MS measurement
457 * report was using the neighbor cells advertised in SI2 or in
458 * SI5, as those two could very well be different */
459 bitvec_set_bit(&bv, 0);
460 /* 3G_BA_IND */
461 bitvec_set_bit(&bv, 1);
462 /* MP_CHANGE_MARK */
463 bitvec_set_bit(&bv, 0);
464
465 /* SI2quater_INDEX */
466 bitvec_set_uint(&bv, si2q_index, 4);
467 /* SI2quater_COUNT */
468 bitvec_set_uint(&bv, si2q_count, 4);
469
470 /* No Measurement_Parameters Description */
471 bitvec_set_bit(&bv, 0);
472 /* No GPRS_Real Time Difference Description */
473 bitvec_set_bit(&bv, 0);
474 /* No GPRS_BSIC Description */
475 bitvec_set_bit(&bv, 0);
476 /* No GPRS_REPORT PRIORITY Description */
477 bitvec_set_bit(&bv, 0);
478 /* No GPRS_MEASUREMENT_Parameters Description */
479 bitvec_set_bit(&bv, 0);
480 /* No NC Measurement Parameters */
481 bitvec_set_bit(&bv, 0);
482 /* No extension (length) */
483 bitvec_set_bit(&bv, 0);
484
485 rc = SI2Q_MAX_LEN - (bv.cur_bit + 3);
486 if (rc > 0 && uarfcn_length - *u_offset > 0)
487 append_uarfcns(&bv, uarfcn_list, u_offset, uarfcn_length, scramble_list, rc);
488 else /* No 3G Neighbour Cell Description */
489 bitvec_set_bit(&bv, 0);
490
491 /* No 3G Measurement Parameters Description */
492 bitvec_set_bit(&bv, 0);
493 /* No GPRS_3G_MEASUREMENT Parameters Descr. */
494 bitvec_set_bit(&bv, 0);
495
496 rc = SI2Q_MAX_LEN - bv.cur_bit;
497 if (rc > 0 && si2q_earfcn_count(si2quater_neigh_list) - *e_offset > 0)
498 append_earfcn(&bv, si2quater_neigh_list, e_offset, rc);
499 else /* No Additions in Rel-5: */
500 bitvec_set_bit(&bv, L);
501
502 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
503 return bv.data_len;
504}
505
506/* Append selection parameters to bitvec */
507static void append_selection_params(struct bitvec *bv,
508 const struct osmo_gsm48_si_selection_params *sp)
509{
510 if (sp->present) {
511 bitvec_set_bit(bv, H);
512 bitvec_set_bit(bv, sp->cbq);
513 bitvec_set_uint(bv, sp->cell_resel_off, 6);
514 bitvec_set_uint(bv, sp->temp_offs, 3);
515 bitvec_set_uint(bv, sp->penalty_time, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200516 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200517 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200518 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200519}
520
521/* Append power offset to bitvec */
522static void append_power_offset(struct bitvec *bv,
523 const struct osmo_gsm48_si_power_offset *po)
524{
525 if (po->present) {
526 bitvec_set_bit(bv, H);
527 bitvec_set_uint(bv, po->power_offset, 2);
Harald Welte65aabd42020-10-15 08:04:49 +0200528 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200529 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200530 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200531}
532
533/* Append GPRS indicator to bitvec */
534static void append_gprs_ind(struct bitvec *bv,
535 const struct osmo_gsm48_si3_gprs_ind *gi)
536{
537 if (gi->present) {
538 bitvec_set_bit(bv, H);
539 bitvec_set_uint(bv, gi->ra_colour, 3);
540 /* 0 == SI13 in BCCH Norm, 1 == SI13 sent on BCCH Ext */
541 bitvec_set_bit(bv, gi->si13_position);
Harald Welte65aabd42020-10-15 08:04:49 +0200542 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200543 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200544 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200545}
546
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200547/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
Harald Welte428d03b2019-05-28 18:46:20 +0200548int osmo_gsm48_rest_octets_si3_encode(uint8_t *data, const struct osmo_gsm48_si_ro_info *si3)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200549{
550 struct bitvec bv;
551
552 memset(&bv, 0, sizeof(bv));
553 bv.data = data;
554 bv.data_len = 4;
555
556 /* Optional Selection Parameters */
557 append_selection_params(&bv, &si3->selection_params);
558
559 /* Optional Power Offset */
560 append_power_offset(&bv, &si3->power_offset);
561
562 /* Do we have a SI2ter on the BCCH? */
563 if (si3->si2ter_indicator)
564 bitvec_set_bit(&bv, H);
565 else
566 bitvec_set_bit(&bv, L);
567
568 /* Early Classmark Sending Control */
569 if (si3->early_cm_ctrl)
570 bitvec_set_bit(&bv, H);
571 else
572 bitvec_set_bit(&bv, L);
573
574 /* Do we have a SI Type 9 on the BCCH? */
575 if (si3->scheduling.present) {
576 bitvec_set_bit(&bv, H);
577 bitvec_set_uint(&bv, si3->scheduling.where, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200578 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200579 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200580 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200581
582 /* GPRS Indicator */
583 append_gprs_ind(&bv, &si3->gprs_ind);
584
585 /* 3G Early Classmark Sending Restriction. If H, then controlled by
586 * early_cm_ctrl above */
587 if (si3->early_cm_restrict_3g)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200588 bitvec_set_bit(&bv, H);
Vadim Yanitskiyc9eab822020-05-05 02:03:29 +0700589 else
590 bitvec_set_bit(&bv, L);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200591
592 if (si3->si2quater_indicator) {
593 bitvec_set_bit(&bv, H); /* indicator struct present */
594 bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */
595 }
596
597 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
598 return bv.data_len;
599}
600
601static int append_lsa_params(struct bitvec *bv,
602 const struct osmo_gsm48_lsa_params *lsa_params)
603{
604 /* FIXME */
605 return -1;
606}
607
608/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
Harald Welte428d03b2019-05-28 18:46:20 +0200609int osmo_gsm48_rest_octets_si4_encode(uint8_t *data, const struct osmo_gsm48_si_ro_info *si4, int len)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200610{
611 struct bitvec bv;
612
613 memset(&bv, 0, sizeof(bv));
614 bv.data = data;
615 bv.data_len = len;
616
617 /* SI4 Rest Octets O */
618 append_selection_params(&bv, &si4->selection_params);
619 append_power_offset(&bv, &si4->power_offset);
620 append_gprs_ind(&bv, &si4->gprs_ind);
621
622 if (0 /* FIXME */) {
623 /* H and SI4 Rest Octets S */
624 bitvec_set_bit(&bv, H);
625
626 /* LSA Parameters */
627 if (si4->lsa_params.present) {
628 bitvec_set_bit(&bv, H);
629 append_lsa_params(&bv, &si4->lsa_params);
Harald Welte65aabd42020-10-15 08:04:49 +0200630 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200631 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200632 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200633
634 /* Cell Identity */
635 if (1) {
636 bitvec_set_bit(&bv, H);
637 bitvec_set_uint(&bv, si4->cell_id, 16);
Harald Welte65aabd42020-10-15 08:04:49 +0200638 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200639 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200640 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200641
642 /* LSA ID Information */
643 if (0) {
644 bitvec_set_bit(&bv, H);
645 /* FIXME */
Harald Welte65aabd42020-10-15 08:04:49 +0200646 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200647 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200648 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200649 } else {
650 /* L and break indicator */
651 bitvec_set_bit(&bv, L);
652 bitvec_set_bit(&bv, si4->break_ind ? H : L);
653 }
654
655 return bv.data_len;
656}
657
658
659/* GSM 04.18 ETSI TS 101 503 V8.27.0 (2006-05)
660
661<SI6 rest octets> ::=
662{L | H <PCH and NCH info>}
663{L | H <VBS/VGCS options : bit(2)>}
664{ < DTM_support : bit == L > I < DTM_support : bit == H >
665< RAC : bit (8) >
666< MAX_LAPDm : bit (3) > }
667< Band indicator >
668{ L | H < GPRS_MS_TXPWR_MAX_CCH : bit (5) > }
669<implicit spare >;
670*/
Harald Welte86156de2019-05-28 19:49:47 +0200671int osmo_gsm48_rest_octets_si6_encode(uint8_t *data, const struct osmo_gsm48_si6_ro_info *in)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200672{
673 struct bitvec bv;
674
675 memset(&bv, 0, sizeof(bv));
676 bv.data = data;
677 bv.data_len = 1;
678
Harald Welte86156de2019-05-28 19:49:47 +0200679 if (in->pch_nch_info.present) {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200680 bitvec_set_bit(&bv, H);
Harald Welte86156de2019-05-28 19:49:47 +0200681 bitvec_set_bit(&bv, !!in->pch_nch_info.paging_channel_restructuring);
682 bitvec_set_uint(&bv, in->pch_nch_info.nln_sacch, 2);
683 if (in->pch_nch_info.call_priority_present) {
684 bitvec_set_bit(&bv, 1);
685 bitvec_set_uint(&bv, in->pch_nch_info.call_priority, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200686 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200687 bitvec_set_bit(&bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200688 }
Harald Welte86156de2019-05-28 19:49:47 +0200689 bitvec_set_bit(&bv, !!in->pch_nch_info.nln_status_sacch);
Harald Welte65aabd42020-10-15 08:04:49 +0200690 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200691 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200692 }
Harald Welte86156de2019-05-28 19:49:47 +0200693
694 if (in->vbs_vgcs_options.present) {
695 bitvec_set_bit(&bv, H);
696 bitvec_set_bit(&bv, !!in->vbs_vgcs_options.inband_notifications);
697 bitvec_set_bit(&bv, !!in->vbs_vgcs_options.inband_pagings);
Harald Welte65aabd42020-10-15 08:04:49 +0200698 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200699 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200700 }
Harald Welte86156de2019-05-28 19:49:47 +0200701
702 if (in->dtm_support.present) {
703 bitvec_set_bit(&bv, H);
704 bitvec_set_uint(&bv, in->dtm_support.rac, 8);
705 bitvec_set_uint(&bv, in->dtm_support.max_lapdm, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200706 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200707 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200708 }
Harald Welte86156de2019-05-28 19:49:47 +0200709
710 if (in->band_indicator_1900)
711 bitvec_set_bit(&bv, H);
712 else
713 bitvec_set_bit(&bv, L);
714
715 if (in->gprs_ms_txpwr_max_ccch.present) {
716 bitvec_set_bit(&bv, H);
717 bitvec_set_uint(&bv, in->gprs_ms_txpwr_max_ccch.max_txpwr, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200718 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200719 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200720 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200721
722 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
723 return bv.data_len;
724}
725
726/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
727 < GPRS Mobile Allocation IE > ::=
728 < HSN : bit (6) >
729 { 0 | 1 < RFL number list : < RFL number list struct > > }
730 { 0 < MA_LENGTH : bit (6) >
731 < MA_BITMAP: bit (val(MA_LENGTH) + 1) >
732 | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;
733
734 < RFL number list struct > :: =
735 < RFL_NUMBER : bit (4) >
736 { 0 | 1 < RFL number list struct > } ;
737 < ARFCN index list struct > ::=
738 < ARFCN_INDEX : bit(6) >
739 { 0 | 1 < ARFCN index list struct > } ;
740 */
741static int append_gprs_mobile_alloc(struct bitvec *bv)
742{
743 /* Hopping Sequence Number */
744 bitvec_set_uint(bv, 0, 6);
745
746 if (0) {
747 /* We want to use a RFL number list */
748 bitvec_set_bit(bv, 1);
749 /* FIXME: RFL number list */
Harald Welte65aabd42020-10-15 08:04:49 +0200750 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200751 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200752 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200753
754 if (0) {
755 /* We want to use a MA_BITMAP */
756 bitvec_set_bit(bv, 0);
757 /* FIXME: MA_LENGTH, MA_BITMAP, ... */
758 } else {
759 bitvec_set_bit(bv, 1);
760 if (0) {
761 /* We want to provide an ARFCN index list */
762 bitvec_set_bit(bv, 1);
763 /* FIXME */
Harald Welte65aabd42020-10-15 08:04:49 +0200764 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200765 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200766 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200767 }
768 return 0;
769}
770
771static int encode_t3192(unsigned int t3192)
772{
773 /* See also 3GPP TS 44.060
774 Table 12.24.2: GPRS Cell Options information element details */
775 if (t3192 == 0)
776 return 3;
777 else if (t3192 <= 80)
778 return 4;
779 else if (t3192 <= 120)
780 return 5;
781 else if (t3192 <= 160)
782 return 6;
783 else if (t3192 <= 200)
784 return 7;
785 else if (t3192 <= 500)
786 return 0;
787 else if (t3192 <= 1000)
788 return 1;
789 else if (t3192 <= 1500)
790 return 2;
791 else
792 return -EINVAL;
793}
794
795static int encode_drx_timer(unsigned int drx)
796{
797 if (drx == 0)
798 return 0;
799 else if (drx == 1)
800 return 1;
801 else if (drx == 2)
802 return 2;
803 else if (drx <= 4)
804 return 3;
805 else if (drx <= 8)
806 return 4;
807 else if (drx <= 16)
808 return 5;
809 else if (drx <= 32)
810 return 6;
811 else if (drx <= 64)
812 return 7;
813 else
814 return -EINVAL;
815}
816
817/* GPRS Cell Options as per TS 04.60 Chapter 12.24
818 < GPRS Cell Options IE > ::=
819 < NMO : bit(2) >
820 < T3168 : bit(3) >
821 < T3192 : bit(3) >
822 < DRX_TIMER_MAX: bit(3) >
823 < ACCESS_BURST_TYPE: bit >
824 < CONTROL_ACK_TYPE : bit >
825 < BS_CV_MAX: bit(4) >
826 { 0 | 1 < PAN_DEC : bit(3) >
827 < PAN_INC : bit(3) >
828 < PAN_MAX : bit(3) >
829 { 0 | 1 < Extension Length : bit(6) >
830 < bit (val(Extension Length) + 1
831 & { < Extension Information > ! { bit ** = <no string> } } ;
832 < Extension Information > ::=
833 { 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit >
834 < BEP_PERIOD : bit(4) > }
835 < PFC_FEATURE_MODE : bit >
836 < DTM_SUPPORT : bit >
837 <BSS_PAGING_COORDINATION: bit >
838 <spare bit > ** ;
839 */
840static int append_gprs_cell_opt(struct bitvec *bv,
841 const struct osmo_gprs_cell_options *gco)
842{
843 int t3192, drx_timer_max;
844
845 t3192 = encode_t3192(gco->t3192);
846 if (t3192 < 0)
847 return t3192;
848
849 drx_timer_max = encode_drx_timer(gco->drx_timer_max);
850 if (drx_timer_max < 0)
851 return drx_timer_max;
852
853 bitvec_set_uint(bv, gco->nmo, 2);
854
855 /* See also 3GPP TS 44.060
856 Table 12.24.2: GPRS Cell Options information element details */
857 bitvec_set_uint(bv, gco->t3168 / 500 - 1, 3);
858
859 bitvec_set_uint(bv, t3192, 3);
860 bitvec_set_uint(bv, drx_timer_max, 3);
861 /* ACCESS_BURST_TYPE: Hard-code 8bit */
862 bitvec_set_bit(bv, 0);
863 /* CONTROL_ACK_TYPE: */
864 bitvec_set_bit(bv, gco->ctrl_ack_type_use_block);
865 bitvec_set_uint(bv, gco->bs_cv_max, 4);
866
867 if (0) {
868 /* hard-code no PAN_{DEC,INC,MAX} */
869 bitvec_set_bit(bv, 0);
870 } else {
871 /* copied from ip.access BSC protocol trace */
872 bitvec_set_bit(bv, 1);
873 bitvec_set_uint(bv, 1, 3); /* DEC */
874 bitvec_set_uint(bv, 1, 3); /* INC */
875 bitvec_set_uint(bv, 15, 3); /* MAX */
876 }
877
878 if (!gco->ext_info_present) {
879 /* no extension information */
880 bitvec_set_bit(bv, 0);
881 } else {
882 /* extension information */
883 bitvec_set_bit(bv, 1);
884 if (!gco->ext_info.egprs_supported) {
885 /* 6bit length of extension */
886 bitvec_set_uint(bv, (1 + 3)-1, 6);
887 /* EGPRS supported in the cell */
888 bitvec_set_bit(bv, 0);
889 } else {
890 /* 6bit length of extension */
891 bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);
892 /* EGPRS supported in the cell */
893 bitvec_set_bit(bv, 1);
894
895 /* 1bit EGPRS PACKET CHANNEL REQUEST */
896 if (gco->supports_egprs_11bit_rach == 0) {
897 bitvec_set_bit(bv,
898 gco->ext_info.use_egprs_p_ch_req);
899 } else {
900 bitvec_set_bit(bv, 0);
901 }
902
903 /* 4bit BEP PERIOD */
904 bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
905 }
906 bitvec_set_bit(bv, gco->ext_info.pfc_supported);
907 bitvec_set_bit(bv, gco->ext_info.dtm_supported);
908 bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
909 }
910
911 return 0;
912}
913
914static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
915 const struct osmo_gprs_power_ctrl_pars *pcp)
916{
917 bitvec_set_uint(bv, pcp->alpha, 4);
918 bitvec_set_uint(bv, pcp->t_avg_w, 5);
919 bitvec_set_uint(bv, pcp->t_avg_t, 5);
920 bitvec_set_uint(bv, pcp->pc_meas_chan, 1);
921 bitvec_set_uint(bv, pcp->n_avg_i, 4);
922}
923
924/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
Harald Welte428d03b2019-05-28 18:46:20 +0200925int osmo_gsm48_rest_octets_si13_encode(uint8_t *data, const struct osmo_gsm48_si13_info *si13)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200926{
927 struct bitvec bv;
928
929 memset(&bv, 0, sizeof(bv));
930 bv.data = data;
931 bv.data_len = 20;
932
933 if (0) {
934 /* No rest octets */
935 bitvec_set_bit(&bv, L);
936 } else {
937 bitvec_set_bit(&bv, H);
938 bitvec_set_uint(&bv, si13->bcch_change_mark, 3);
939 bitvec_set_uint(&bv, si13->si_change_field, 4);
940 if (1) {
941 bitvec_set_bit(&bv, 0);
942 } else {
943 bitvec_set_bit(&bv, 1);
944 bitvec_set_uint(&bv, si13->bcch_change_mark, 2);
945 append_gprs_mobile_alloc(&bv);
946 }
947 /* PBCCH not present in cell:
948 it shall never be indicated according to 3GPP TS 44.018 Table 10.5.2.37b.1 */
949 bitvec_set_bit(&bv, 0);
950 bitvec_set_uint(&bv, si13->rac, 8);
951 bitvec_set_bit(&bv, si13->spgc_ccch_sup);
952 bitvec_set_uint(&bv, si13->prio_acc_thr, 3);
953 bitvec_set_uint(&bv, si13->net_ctrl_ord, 2);
954 append_gprs_cell_opt(&bv, &si13->cell_opts);
955 append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);
956
957 /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
958 bitvec_set_bit(&bv, H); /* added Release 99 */
959 /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
960 * was only added in this Release */
961 bitvec_set_bit(&bv, 1);
962 }
963 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
964 return bv.data_len;
965}
Harald Weltef85b33f2019-05-28 17:56:21 +0200966
967
968/***********************************************************************
969 * Decoder
970 ***********************************************************************/
971
972/*! Decode SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72).
973 * \param[out] si3 decoded SI3 rest octets
974 * \param[in] encoded SI3 rest octets, 4 octets long */
975void osmo_gsm48_rest_octets_si3_decode(struct osmo_gsm48_si_ro_info *si3, const uint8_t *data)
976{
977 struct osmo_gsm48_si_selection_params *sp = &si3->selection_params;
978 struct osmo_gsm48_si_power_offset *po = &si3->power_offset;
979 struct osmo_gsm48_si3_gprs_ind *gi = &si3->gprs_ind;
980 struct bitvec bv;
981
982 memset(&bv, 0, sizeof(bv));
983 bv.data = (uint8_t *) data;
984 bv.data_len = 4;
985
986 memset(si3, 0, sizeof(*si3));
987
Vadim Yanitskiy74474cf2019-07-17 16:40:11 +0700988 /* Optional Selection Parameters */
Harald Weltef85b33f2019-05-28 17:56:21 +0200989 if (bitvec_get_bit_high(&bv) == H) {
990 sp->present = 1;
991 sp->cbq = bitvec_get_uint(&bv, 1);
992 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
993 sp->temp_offs = bitvec_get_uint(&bv, 3);
994 sp->penalty_time = bitvec_get_uint(&bv, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200995 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +0200996 sp->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +0200997 }
Harald Weltef85b33f2019-05-28 17:56:21 +0200998
999 /* Optional Power Offset */
1000 if (bitvec_get_bit_high(&bv) == H) {
1001 po->present = 1;
1002 po->power_offset = bitvec_get_uint(&bv, 2);
Harald Welte65aabd42020-10-15 08:04:49 +02001003 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001004 po->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001005 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001006
1007 /* System Information 2ter Indicator */
1008 if (bitvec_get_bit_high(&bv) == H)
1009 si3->si2ter_indicator = 1;
1010 else
1011 si3->si2ter_indicator = 0;
1012
1013 /* Early Classmark Sending Control */
1014 if (bitvec_get_bit_high(&bv) == H)
1015 si3->early_cm_ctrl = 1;
1016 else
1017 si3->early_cm_ctrl = 0;
1018
1019 /* Scheduling if and where */
1020 if (bitvec_get_bit_high(&bv) == H) {
1021 si3->scheduling.present = 1;
1022 si3->scheduling.where = bitvec_get_uint(&bv, 3);
Harald Welte65aabd42020-10-15 08:04:49 +02001023 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001024 si3->scheduling.present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001025 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001026
1027 /* GPRS Indicator */
1028 if (bitvec_get_bit_high(&bv) == H) {
1029 gi->present = 1;
1030 gi->ra_colour = bitvec_get_uint(&bv, 3);
1031 gi->si13_position = bitvec_get_uint(&bv, 1);
Harald Welte65aabd42020-10-15 08:04:49 +02001032 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001033 gi->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001034 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001035
1036 /* 3G Early Classmark Sending Restriction. If H, then controlled by
1037 * early_cm_ctrl above */
1038 if (bitvec_get_bit_high(&bv) == H)
1039 si3->early_cm_restrict_3g = 1;
1040 else
1041 si3->early_cm_restrict_3g = 0;
1042
1043 if (bitvec_get_bit_high(&bv) == H)
1044 si3->si2quater_indicator = 1;
1045 else
1046 si3->si2quater_indicator = 0;
1047}
Harald Welte5e1cd5e2020-10-11 20:04:04 +02001048
1049
1050void osmo_gsm48_rest_octets_si4_decode(struct osmo_gsm48_si_ro_info *si4, const uint8_t *data, int len)
1051{
1052 struct osmo_gsm48_si_selection_params *sp = &si4->selection_params;
1053 struct osmo_gsm48_si_power_offset *po = &si4->power_offset;
1054 struct osmo_gsm48_si3_gprs_ind *gi = &si4->gprs_ind;
1055 struct bitvec bv;
1056
1057 memset(&bv, 0, sizeof(bv));
1058 bv.data = (uint8_t *) data;
1059 bv.data_len = len;
1060
1061 memset(si4, 0, sizeof(*si4));
1062
1063 /* Optional Selection Parameters */
1064 if (bitvec_get_bit_high(&bv) == H) {
1065 sp->present = 1;
1066 sp->cbq = bitvec_get_uint(&bv, 1);
1067 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
1068 sp->temp_offs = bitvec_get_uint(&bv, 3);
1069 sp->penalty_time = bitvec_get_uint(&bv, 5);
1070 } else {
1071 sp->present = 0;
1072 }
1073
1074 /* Optional Power Offset */
1075 if (bitvec_get_bit_high(&bv) == H) {
1076 po->present = 1;
1077 po->power_offset = bitvec_get_uint(&bv, 2);
1078 } else {
1079 po->present = 0;
1080 }
1081
1082 /* GPRS Indicator */
1083 if (bitvec_get_bit_high(&bv) == H) {
1084 gi->present = 1;
1085 gi->ra_colour = bitvec_get_uint(&bv, 3);
1086 gi->si13_position = bitvec_get_uint(&bv, 1);
1087 } else {
1088 gi->present = 0;
1089 }
1090}