blob: 5c7d77a4ef2ce4415ce9fce3fb4745ec51d8debc [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 */
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100168 int rem = ((int)budget) - 40;
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200169 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
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100196 /* budget: 10 bits used above */
197
Pau Espin Pedrol908224c2020-12-14 17:11:19 +0100198 /* Serving Cell Priority Parameters Descr. is Present,
199 * see also: 3GPP TS 44.018, Table 10.5.2.33b.1 */
200 bitvec_set_bit(bv, 1);
201
202 /* GERAN_PRIORITY */
203 bitvec_set_uint(bv, 0, 3);
204
205 /* THRESH_Priority_Search */
206 bitvec_set_uint(bv, 0, 4);
207
208 /* THRESH_GSM_low */
209 bitvec_set_uint(bv, 0, 4);
210
211 /* H_PRIO */
212 bitvec_set_uint(bv, 0, 2);
213
214 /* T_Reselection */
215 bitvec_set_uint(bv, 0, 2);
216
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100217 /* budget: 26 bits used above */
218
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200219 /* No 3G Priority Parameters Description */
220 bitvec_set_bit(bv, 0);
221 /* E-UTRAN Parameters Description */
222 bitvec_set_bit(bv, 1);
223
224 /* E-UTRAN_CCN_ACTIVE */
225 bitvec_set_bit(bv, 0);
226 /* E-UTRAN_Start: 9.1.54 */
227 bitvec_set_bit(bv, 1);
228 /* E-UTRAN_Stop: 9.1.54 */
229 bitvec_set_bit(bv, 1);
230
231 /* No E-UTRAN Measurement Parameters Descr. */
232 bitvec_set_bit(bv, 0);
233 /* No GPRS E-UTRAN Measurement Param. Descr. */
234 bitvec_set_bit(bv, 0);
235
236 /* Note: each of next 3 "repeated" structures might be repeated any
237 (0, 1, 2...) times - we only support 1 and 0 */
238
239 /* Repeated E-UTRAN Neighbour Cells */
240 bitvec_set_bit(bv, 1);
241
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100242 /* budget: 34 bits used above */
243
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200244 appended = append_eutran_neib_cell(bv, e, e_offset, rem);
245 if (!appended) { /* appending is impossible within current budget: rollback */
246 bv->cur_bit = old;
247 return;
248 }
249
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100250 /* budget: further 6 bits used below, totalling 40 bits */
251
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200252 /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */
253 bitvec_set_bit(bv, 0);
254
255 /* Note: following 2 repeated structs are not supported ATM */
256 /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */
257 bitvec_set_bit(bv, 0);
258 /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */
259 bitvec_set_bit(bv, 0);
260
261 /* Priority and E-UTRAN Parameters Description ends here */
262 /* No 3G CSG Description */
263 bitvec_set_bit(bv, 0);
264 /* No E-UTRAN CSG Description */
265 bitvec_set_bit(bv, 0);
266 /* No Additions in Rel-9: */
267 bitvec_set_bit(bv, L);
268}
269
270static int range_encode(enum osmo_gsm48_range r, int *arfcns, int arfcns_used, int *w,
271 int f0, uint8_t *chan_list)
272{
273 /*
274 * Manipulate the ARFCN list according to the rules in J4 depending
275 * on the selected range.
276 */
277 int rc, f0_included;
278
279 osmo_gsm48_range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
280
281 rc = osmo_gsm48_range_enc_arfcns(r, arfcns, arfcns_used, w, 0);
282 if (rc < 0)
283 return rc;
284
285 /* Select the range and the amount of bits needed */
286 switch (r) {
287 case OSMO_GSM48_ARFCN_RANGE_128:
Harald Welte1276c172019-05-28 18:38:35 +0200288 return osmo_gsm48_range_enc_128(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200289 case OSMO_GSM48_ARFCN_RANGE_256:
Harald Welte1276c172019-05-28 18:38:35 +0200290 return osmo_gsm48_range_enc_256(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200291 case OSMO_GSM48_ARFCN_RANGE_512:
Harald Welte1276c172019-05-28 18:38:35 +0200292 return osmo_gsm48_range_enc_512(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200293 case OSMO_GSM48_ARFCN_RANGE_1024:
Harald Welte1276c172019-05-28 18:38:35 +0200294 return osmo_gsm48_range_enc_1024(chan_list, f0, f0_included, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200295 default:
296 return -ERANGE;
297 };
298
299 return f0_included;
300}
301
302static inline int f0_helper(int *sc, size_t length, uint8_t *chan_list)
303{
304 int w[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS] = { 0 };
305
306 return range_encode(OSMO_GSM48_ARFCN_RANGE_1024, sc, length, w, 0, chan_list);
307}
308
309/* Return p(n) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */
310static unsigned range1024_p(unsigned n)
311{
312 switch (n) {
313 case 0: return 0;
314 case 1: return 10;
315 case 2: return 19;
316 case 3: return 28;
317 case 4: return 36;
318 case 5: return 44;
319 case 6: return 52;
320 case 7: return 60;
321 case 8: return 67;
322 case 9: return 74;
323 case 10: return 81;
324 case 11: return 88;
325 case 12: return 95;
326 case 13: return 102;
327 case 14: return 109;
328 case 15: return 116;
329 case 16: return 122;
330 default: return 0;
331 }
332}
333
334/* Estimate how many bits it'll take to append single FDD UARFCN */
335static inline int append_utran_fdd_length(uint16_t u, const int *sc, size_t sc_len, size_t length)
336{
337 uint8_t chan_list[16] = { 0 };
338 int tmp[sc_len], f0;
339
340 memcpy(tmp, sc, sizeof(tmp));
341
342 f0 = f0_helper(tmp, length, chan_list);
343 if (f0 < 0)
344 return f0;
345
346 return 21 + range1024_p(length);
347}
348
349/* Append single FDD UARFCN */
350static inline int append_utran_fdd(struct bitvec *bv, uint16_t u, int *sc, size_t length)
351{
352 uint8_t chan_list[16] = { 0 };
353 int f0 = f0_helper(sc, length, chan_list);
354
355 if (f0 < 0)
356 return f0;
357
358 /* Repeated UTRAN FDD Neighbour Cells */
359 bitvec_set_bit(bv, 1);
360
361 /* FDD-ARFCN */
362 bitvec_set_bit(bv, 0);
363 bitvec_set_uint(bv, u, 14);
364
365 /* FDD_Indic0: parameter value '0000000000' is a member of the set? */
366 bitvec_set_bit(bv, f0);
367 /* NR_OF_FDD_CELLS */
368 bitvec_set_uint(bv, length, 5);
369
370 f0 = bv->cur_bit;
371 bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list);
372 bv->cur_bit = f0 + range1024_p(length);
373
374 return 21 + range1024_p(length);
375}
376
377static inline int try_adding_uarfcn(struct bitvec *bv, uint16_t *scramble_list,
378 size_t uarfcn_length, size_t *u_offset,
379 uint16_t uarfcn, uint8_t num_sc, uint8_t start_pos, uint8_t budget)
380{
381 int i, k, rc, a[uarfcn_length];
382
383 if (budget < 23)
384 return -ENOMEM;
385
386 /* copy corresponding Scrambling Codes: range encoder make in-place modifications */
387 for (i = start_pos, k = 0; i < num_sc; a[k++] = scramble_list[i++]);
388
389 /* estimate bit length requirements */
390 rc = append_utran_fdd_length(uarfcn, a, uarfcn_length, k);
391 if (rc < 0)
392 return rc; /* range encoder failure */
393
394 if (budget - rc <= 0)
395 return -ENOMEM; /* we have ran out of budget in current SI2q */
396
397 /* compute next offset */
398 *u_offset += k;
399
400 return budget - append_utran_fdd(bv, uarfcn, a, k);
401}
402
403/* Append multiple FDD UARFCNs */
404static inline void append_uarfcns(struct bitvec *bv, const uint16_t *uarfcn_list, size_t *u_offset,
405 size_t uarfcn_length, uint16_t *scramble_list, uint8_t budget)
406{
407 int i, rem = budget - 7, st = *u_offset; /* account for constant bits right away */
408 uint16_t cu = uarfcn_list[*u_offset]; /* caller ensures that length is positive */
409
410 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
411
412 if (budget <= 7)
413 return;
414
415 /* 3G Neighbour Cell Description */
416 bitvec_set_bit(bv, 1);
417 /* No Index_Start_3G */
418 bitvec_set_bit(bv, 0);
419 /* No Absolute_Index_Start_EMR */
420 bitvec_set_bit(bv, 0);
421
422 /* UTRAN FDD Description */
423 bitvec_set_bit(bv, 1);
424 /* No Bandwidth_FDD */
425 bitvec_set_bit(bv, 0);
426
427 for (i = *u_offset; i <= uarfcn_length; i++)
428 if (uarfcn_list[i] != cu) { /* we've reached new UARFCN */
429 rem = try_adding_uarfcn(bv, scramble_list, uarfcn_length, u_offset, cu, i, st, rem);
430 if (rem < 0)
431 break;
432
433 if (i < uarfcn_length) {
434 cu = uarfcn_list[i];
435 st = i;
Harald Welte65aabd42020-10-15 08:04:49 +0200436 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200437 break;
Harald Welte65aabd42020-10-15 08:04:49 +0200438 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200439 }
440
441 /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */
442 bitvec_set_bit(bv, 0);
443
444 /* UTRAN TDD Description */
445 bitvec_set_bit(bv, 0);
446}
447
448static size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e)
449{
450 unsigned i, ret = 0;
451
452 if (!e)
453 return 0;
454
455 for (i = 0; i < e->length; i++)
456 if (e->arfcn[i] != OSMO_EARFCN_INVALID)
457 ret++;
458
459 return ret;
460}
461
462/* generate SI2quater rest octets: 3GPP TS 44.018 § 10.5.2.33b */
Harald Welte428d03b2019-05-28 18:46:20 +0200463int osmo_gsm48_rest_octets_si2quater_encode(uint8_t *data, uint8_t si2q_index, uint8_t si2q_count,
464 const uint16_t *uarfcn_list, size_t *u_offset,
465 size_t uarfcn_length, uint16_t *scramble_list,
466 struct osmo_earfcn_si2q *si2quater_neigh_list,
467 size_t *e_offset)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200468{
469 int rc;
470 struct bitvec bv;
471
472 if (si2q_count < si2q_index)
473 return -EINVAL;
474
475 bv.data = data;
476 bv.data_len = 20;
477 bitvec_zero(&bv);
478
479 /* BA_IND: Set to '0' as that's what we use for SI2xxx type,
480 * whereas '1' is used for SI5xxx type messages. The point here
481 * is to be able to correlate whether a given MS measurement
482 * report was using the neighbor cells advertised in SI2 or in
483 * SI5, as those two could very well be different */
484 bitvec_set_bit(&bv, 0);
485 /* 3G_BA_IND */
486 bitvec_set_bit(&bv, 1);
487 /* MP_CHANGE_MARK */
488 bitvec_set_bit(&bv, 0);
489
490 /* SI2quater_INDEX */
491 bitvec_set_uint(&bv, si2q_index, 4);
492 /* SI2quater_COUNT */
493 bitvec_set_uint(&bv, si2q_count, 4);
494
495 /* No Measurement_Parameters Description */
496 bitvec_set_bit(&bv, 0);
497 /* No GPRS_Real Time Difference Description */
498 bitvec_set_bit(&bv, 0);
499 /* No GPRS_BSIC Description */
500 bitvec_set_bit(&bv, 0);
501 /* No GPRS_REPORT PRIORITY Description */
502 bitvec_set_bit(&bv, 0);
503 /* No GPRS_MEASUREMENT_Parameters Description */
504 bitvec_set_bit(&bv, 0);
505 /* No NC Measurement Parameters */
506 bitvec_set_bit(&bv, 0);
507 /* No extension (length) */
508 bitvec_set_bit(&bv, 0);
509
510 rc = SI2Q_MAX_LEN - (bv.cur_bit + 3);
511 if (rc > 0 && uarfcn_length - *u_offset > 0)
512 append_uarfcns(&bv, uarfcn_list, u_offset, uarfcn_length, scramble_list, rc);
513 else /* No 3G Neighbour Cell Description */
514 bitvec_set_bit(&bv, 0);
515
516 /* No 3G Measurement Parameters Description */
517 bitvec_set_bit(&bv, 0);
518 /* No GPRS_3G_MEASUREMENT Parameters Descr. */
519 bitvec_set_bit(&bv, 0);
520
521 rc = SI2Q_MAX_LEN - bv.cur_bit;
522 if (rc > 0 && si2q_earfcn_count(si2quater_neigh_list) - *e_offset > 0)
523 append_earfcn(&bv, si2quater_neigh_list, e_offset, rc);
524 else /* No Additions in Rel-5: */
525 bitvec_set_bit(&bv, L);
526
527 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
528 return bv.data_len;
529}
530
531/* Append selection parameters to bitvec */
532static void append_selection_params(struct bitvec *bv,
533 const struct osmo_gsm48_si_selection_params *sp)
534{
535 if (sp->present) {
536 bitvec_set_bit(bv, H);
537 bitvec_set_bit(bv, sp->cbq);
538 bitvec_set_uint(bv, sp->cell_resel_off, 6);
539 bitvec_set_uint(bv, sp->temp_offs, 3);
540 bitvec_set_uint(bv, sp->penalty_time, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200541 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200542 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200543 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200544}
545
546/* Append power offset to bitvec */
547static void append_power_offset(struct bitvec *bv,
548 const struct osmo_gsm48_si_power_offset *po)
549{
550 if (po->present) {
551 bitvec_set_bit(bv, H);
552 bitvec_set_uint(bv, po->power_offset, 2);
Harald Welte65aabd42020-10-15 08:04:49 +0200553 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200554 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200555 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200556}
557
558/* Append GPRS indicator to bitvec */
559static void append_gprs_ind(struct bitvec *bv,
560 const struct osmo_gsm48_si3_gprs_ind *gi)
561{
562 if (gi->present) {
563 bitvec_set_bit(bv, H);
564 bitvec_set_uint(bv, gi->ra_colour, 3);
565 /* 0 == SI13 in BCCH Norm, 1 == SI13 sent on BCCH Ext */
566 bitvec_set_bit(bv, gi->si13_position);
Harald Welte65aabd42020-10-15 08:04:49 +0200567 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200568 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200569 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200570}
571
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200572/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
Harald Welte428d03b2019-05-28 18:46:20 +0200573int osmo_gsm48_rest_octets_si3_encode(uint8_t *data, const struct osmo_gsm48_si_ro_info *si3)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200574{
575 struct bitvec bv;
576
577 memset(&bv, 0, sizeof(bv));
578 bv.data = data;
579 bv.data_len = 4;
580
581 /* Optional Selection Parameters */
582 append_selection_params(&bv, &si3->selection_params);
583
584 /* Optional Power Offset */
585 append_power_offset(&bv, &si3->power_offset);
586
587 /* Do we have a SI2ter on the BCCH? */
588 if (si3->si2ter_indicator)
589 bitvec_set_bit(&bv, H);
590 else
591 bitvec_set_bit(&bv, L);
592
593 /* Early Classmark Sending Control */
594 if (si3->early_cm_ctrl)
595 bitvec_set_bit(&bv, H);
596 else
597 bitvec_set_bit(&bv, L);
598
599 /* Do we have a SI Type 9 on the BCCH? */
600 if (si3->scheduling.present) {
601 bitvec_set_bit(&bv, H);
602 bitvec_set_uint(&bv, si3->scheduling.where, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200603 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200604 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200605 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200606
607 /* GPRS Indicator */
608 append_gprs_ind(&bv, &si3->gprs_ind);
609
610 /* 3G Early Classmark Sending Restriction. If H, then controlled by
611 * early_cm_ctrl above */
612 if (si3->early_cm_restrict_3g)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200613 bitvec_set_bit(&bv, H);
Vadim Yanitskiyc9eab822020-05-05 02:03:29 +0700614 else
615 bitvec_set_bit(&bv, L);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200616
617 if (si3->si2quater_indicator) {
618 bitvec_set_bit(&bv, H); /* indicator struct present */
619 bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */
620 }
621
622 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
623 return bv.data_len;
624}
625
626static int append_lsa_params(struct bitvec *bv,
627 const struct osmo_gsm48_lsa_params *lsa_params)
628{
629 /* FIXME */
630 return -1;
631}
632
633/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
Harald Welte428d03b2019-05-28 18:46:20 +0200634int 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 +0200635{
636 struct bitvec bv;
637
638 memset(&bv, 0, sizeof(bv));
639 bv.data = data;
640 bv.data_len = len;
641
642 /* SI4 Rest Octets O */
643 append_selection_params(&bv, &si4->selection_params);
644 append_power_offset(&bv, &si4->power_offset);
645 append_gprs_ind(&bv, &si4->gprs_ind);
646
647 if (0 /* FIXME */) {
648 /* H and SI4 Rest Octets S */
649 bitvec_set_bit(&bv, H);
650
651 /* LSA Parameters */
652 if (si4->lsa_params.present) {
653 bitvec_set_bit(&bv, H);
654 append_lsa_params(&bv, &si4->lsa_params);
Harald Welte65aabd42020-10-15 08:04:49 +0200655 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200656 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200657 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200658
659 /* Cell Identity */
660 if (1) {
661 bitvec_set_bit(&bv, H);
662 bitvec_set_uint(&bv, si4->cell_id, 16);
Harald Welte65aabd42020-10-15 08:04:49 +0200663 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200664 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200665 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200666
667 /* LSA ID Information */
668 if (0) {
669 bitvec_set_bit(&bv, H);
670 /* FIXME */
Harald Welte65aabd42020-10-15 08:04:49 +0200671 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200672 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200673 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200674 } else {
675 /* L and break indicator */
676 bitvec_set_bit(&bv, L);
677 bitvec_set_bit(&bv, si4->break_ind ? H : L);
678 }
679
680 return bv.data_len;
681}
682
683
684/* GSM 04.18 ETSI TS 101 503 V8.27.0 (2006-05)
685
686<SI6 rest octets> ::=
687{L | H <PCH and NCH info>}
688{L | H <VBS/VGCS options : bit(2)>}
689{ < DTM_support : bit == L > I < DTM_support : bit == H >
690< RAC : bit (8) >
691< MAX_LAPDm : bit (3) > }
692< Band indicator >
693{ L | H < GPRS_MS_TXPWR_MAX_CCH : bit (5) > }
694<implicit spare >;
695*/
Harald Welte86156de2019-05-28 19:49:47 +0200696int osmo_gsm48_rest_octets_si6_encode(uint8_t *data, const struct osmo_gsm48_si6_ro_info *in)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200697{
698 struct bitvec bv;
699
700 memset(&bv, 0, sizeof(bv));
701 bv.data = data;
702 bv.data_len = 1;
703
Harald Welte86156de2019-05-28 19:49:47 +0200704 if (in->pch_nch_info.present) {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200705 bitvec_set_bit(&bv, H);
Harald Welte86156de2019-05-28 19:49:47 +0200706 bitvec_set_bit(&bv, !!in->pch_nch_info.paging_channel_restructuring);
707 bitvec_set_uint(&bv, in->pch_nch_info.nln_sacch, 2);
708 if (in->pch_nch_info.call_priority_present) {
709 bitvec_set_bit(&bv, 1);
710 bitvec_set_uint(&bv, in->pch_nch_info.call_priority, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200711 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200712 bitvec_set_bit(&bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200713 }
Harald Welte86156de2019-05-28 19:49:47 +0200714 bitvec_set_bit(&bv, !!in->pch_nch_info.nln_status_sacch);
Harald Welte65aabd42020-10-15 08:04:49 +0200715 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200716 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200717 }
Harald Welte86156de2019-05-28 19:49:47 +0200718
719 if (in->vbs_vgcs_options.present) {
720 bitvec_set_bit(&bv, H);
721 bitvec_set_bit(&bv, !!in->vbs_vgcs_options.inband_notifications);
722 bitvec_set_bit(&bv, !!in->vbs_vgcs_options.inband_pagings);
Harald Welte65aabd42020-10-15 08:04:49 +0200723 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200724 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200725 }
Harald Welte86156de2019-05-28 19:49:47 +0200726
727 if (in->dtm_support.present) {
728 bitvec_set_bit(&bv, H);
729 bitvec_set_uint(&bv, in->dtm_support.rac, 8);
730 bitvec_set_uint(&bv, in->dtm_support.max_lapdm, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200731 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200732 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200733 }
Harald Welte86156de2019-05-28 19:49:47 +0200734
735 if (in->band_indicator_1900)
736 bitvec_set_bit(&bv, H);
737 else
738 bitvec_set_bit(&bv, L);
739
740 if (in->gprs_ms_txpwr_max_ccch.present) {
741 bitvec_set_bit(&bv, H);
742 bitvec_set_uint(&bv, in->gprs_ms_txpwr_max_ccch.max_txpwr, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200743 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200744 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200745 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200746
747 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
748 return bv.data_len;
749}
750
751/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
752 < GPRS Mobile Allocation IE > ::=
753 < HSN : bit (6) >
754 { 0 | 1 < RFL number list : < RFL number list struct > > }
755 { 0 < MA_LENGTH : bit (6) >
756 < MA_BITMAP: bit (val(MA_LENGTH) + 1) >
757 | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;
758
759 < RFL number list struct > :: =
760 < RFL_NUMBER : bit (4) >
761 { 0 | 1 < RFL number list struct > } ;
762 < ARFCN index list struct > ::=
763 < ARFCN_INDEX : bit(6) >
764 { 0 | 1 < ARFCN index list struct > } ;
765 */
766static int append_gprs_mobile_alloc(struct bitvec *bv)
767{
768 /* Hopping Sequence Number */
769 bitvec_set_uint(bv, 0, 6);
770
771 if (0) {
772 /* We want to use a RFL number list */
773 bitvec_set_bit(bv, 1);
774 /* FIXME: RFL number list */
Harald Welte65aabd42020-10-15 08:04:49 +0200775 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200776 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200777 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200778
779 if (0) {
780 /* We want to use a MA_BITMAP */
781 bitvec_set_bit(bv, 0);
782 /* FIXME: MA_LENGTH, MA_BITMAP, ... */
783 } else {
784 bitvec_set_bit(bv, 1);
785 if (0) {
786 /* We want to provide an ARFCN index list */
787 bitvec_set_bit(bv, 1);
788 /* FIXME */
Harald Welte65aabd42020-10-15 08:04:49 +0200789 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200790 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200791 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200792 }
793 return 0;
794}
795
796static int encode_t3192(unsigned int t3192)
797{
798 /* See also 3GPP TS 44.060
799 Table 12.24.2: GPRS Cell Options information element details */
800 if (t3192 == 0)
801 return 3;
802 else if (t3192 <= 80)
803 return 4;
804 else if (t3192 <= 120)
805 return 5;
806 else if (t3192 <= 160)
807 return 6;
808 else if (t3192 <= 200)
809 return 7;
810 else if (t3192 <= 500)
811 return 0;
812 else if (t3192 <= 1000)
813 return 1;
814 else if (t3192 <= 1500)
815 return 2;
816 else
817 return -EINVAL;
818}
819
820static int encode_drx_timer(unsigned int drx)
821{
822 if (drx == 0)
823 return 0;
824 else if (drx == 1)
825 return 1;
826 else if (drx == 2)
827 return 2;
828 else if (drx <= 4)
829 return 3;
830 else if (drx <= 8)
831 return 4;
832 else if (drx <= 16)
833 return 5;
834 else if (drx <= 32)
835 return 6;
836 else if (drx <= 64)
837 return 7;
838 else
839 return -EINVAL;
840}
841
842/* GPRS Cell Options as per TS 04.60 Chapter 12.24
843 < GPRS Cell Options IE > ::=
844 < NMO : bit(2) >
845 < T3168 : bit(3) >
846 < T3192 : bit(3) >
847 < DRX_TIMER_MAX: bit(3) >
848 < ACCESS_BURST_TYPE: bit >
849 < CONTROL_ACK_TYPE : bit >
850 < BS_CV_MAX: bit(4) >
851 { 0 | 1 < PAN_DEC : bit(3) >
852 < PAN_INC : bit(3) >
853 < PAN_MAX : bit(3) >
854 { 0 | 1 < Extension Length : bit(6) >
855 < bit (val(Extension Length) + 1
856 & { < Extension Information > ! { bit ** = <no string> } } ;
857 < Extension Information > ::=
858 { 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit >
859 < BEP_PERIOD : bit(4) > }
860 < PFC_FEATURE_MODE : bit >
861 < DTM_SUPPORT : bit >
862 <BSS_PAGING_COORDINATION: bit >
863 <spare bit > ** ;
864 */
865static int append_gprs_cell_opt(struct bitvec *bv,
866 const struct osmo_gprs_cell_options *gco)
867{
868 int t3192, drx_timer_max;
869
870 t3192 = encode_t3192(gco->t3192);
871 if (t3192 < 0)
872 return t3192;
873
874 drx_timer_max = encode_drx_timer(gco->drx_timer_max);
875 if (drx_timer_max < 0)
876 return drx_timer_max;
877
878 bitvec_set_uint(bv, gco->nmo, 2);
879
880 /* See also 3GPP TS 44.060
881 Table 12.24.2: GPRS Cell Options information element details */
882 bitvec_set_uint(bv, gco->t3168 / 500 - 1, 3);
883
884 bitvec_set_uint(bv, t3192, 3);
885 bitvec_set_uint(bv, drx_timer_max, 3);
886 /* ACCESS_BURST_TYPE: Hard-code 8bit */
887 bitvec_set_bit(bv, 0);
888 /* CONTROL_ACK_TYPE: */
889 bitvec_set_bit(bv, gco->ctrl_ack_type_use_block);
890 bitvec_set_uint(bv, gco->bs_cv_max, 4);
891
892 if (0) {
893 /* hard-code no PAN_{DEC,INC,MAX} */
894 bitvec_set_bit(bv, 0);
895 } else {
896 /* copied from ip.access BSC protocol trace */
897 bitvec_set_bit(bv, 1);
898 bitvec_set_uint(bv, 1, 3); /* DEC */
899 bitvec_set_uint(bv, 1, 3); /* INC */
900 bitvec_set_uint(bv, 15, 3); /* MAX */
901 }
902
903 if (!gco->ext_info_present) {
904 /* no extension information */
905 bitvec_set_bit(bv, 0);
906 } else {
907 /* extension information */
908 bitvec_set_bit(bv, 1);
909 if (!gco->ext_info.egprs_supported) {
910 /* 6bit length of extension */
911 bitvec_set_uint(bv, (1 + 3)-1, 6);
912 /* EGPRS supported in the cell */
913 bitvec_set_bit(bv, 0);
914 } else {
915 /* 6bit length of extension */
916 bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);
917 /* EGPRS supported in the cell */
918 bitvec_set_bit(bv, 1);
919
Pau Espin Pedrol30bf0e62020-12-14 17:13:47 +0100920 /* 1bit EGPRS PACKET CHANNEL REQUEST (inverted logic) */
921 bitvec_set_bit(bv, !gco->ext_info.use_egprs_p_ch_req);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200922
923 /* 4bit BEP PERIOD */
924 bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
925 }
926 bitvec_set_bit(bv, gco->ext_info.pfc_supported);
927 bitvec_set_bit(bv, gco->ext_info.dtm_supported);
928 bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
929 }
930
931 return 0;
932}
933
934static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
935 const struct osmo_gprs_power_ctrl_pars *pcp)
936{
937 bitvec_set_uint(bv, pcp->alpha, 4);
938 bitvec_set_uint(bv, pcp->t_avg_w, 5);
939 bitvec_set_uint(bv, pcp->t_avg_t, 5);
940 bitvec_set_uint(bv, pcp->pc_meas_chan, 1);
941 bitvec_set_uint(bv, pcp->n_avg_i, 4);
942}
943
944/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
Harald Welte428d03b2019-05-28 18:46:20 +0200945int osmo_gsm48_rest_octets_si13_encode(uint8_t *data, const struct osmo_gsm48_si13_info *si13)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200946{
947 struct bitvec bv;
948
949 memset(&bv, 0, sizeof(bv));
950 bv.data = data;
951 bv.data_len = 20;
952
953 if (0) {
954 /* No rest octets */
955 bitvec_set_bit(&bv, L);
956 } else {
957 bitvec_set_bit(&bv, H);
958 bitvec_set_uint(&bv, si13->bcch_change_mark, 3);
959 bitvec_set_uint(&bv, si13->si_change_field, 4);
960 if (1) {
961 bitvec_set_bit(&bv, 0);
962 } else {
963 bitvec_set_bit(&bv, 1);
964 bitvec_set_uint(&bv, si13->bcch_change_mark, 2);
965 append_gprs_mobile_alloc(&bv);
966 }
967 /* PBCCH not present in cell:
968 it shall never be indicated according to 3GPP TS 44.018 Table 10.5.2.37b.1 */
969 bitvec_set_bit(&bv, 0);
970 bitvec_set_uint(&bv, si13->rac, 8);
971 bitvec_set_bit(&bv, si13->spgc_ccch_sup);
972 bitvec_set_uint(&bv, si13->prio_acc_thr, 3);
973 bitvec_set_uint(&bv, si13->net_ctrl_ord, 2);
974 append_gprs_cell_opt(&bv, &si13->cell_opts);
975 append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);
976
977 /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
978 bitvec_set_bit(&bv, H); /* added Release 99 */
979 /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
980 * was only added in this Release */
981 bitvec_set_bit(&bv, 1);
982 }
983 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
984 return bv.data_len;
985}
Harald Weltef85b33f2019-05-28 17:56:21 +0200986
987
988/***********************************************************************
989 * Decoder
990 ***********************************************************************/
991
992/*! Decode SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72).
993 * \param[out] si3 decoded SI3 rest octets
994 * \param[in] encoded SI3 rest octets, 4 octets long */
995void osmo_gsm48_rest_octets_si3_decode(struct osmo_gsm48_si_ro_info *si3, const uint8_t *data)
996{
997 struct osmo_gsm48_si_selection_params *sp = &si3->selection_params;
998 struct osmo_gsm48_si_power_offset *po = &si3->power_offset;
999 struct osmo_gsm48_si3_gprs_ind *gi = &si3->gprs_ind;
1000 struct bitvec bv;
1001
1002 memset(&bv, 0, sizeof(bv));
1003 bv.data = (uint8_t *) data;
1004 bv.data_len = 4;
1005
1006 memset(si3, 0, sizeof(*si3));
1007
Vadim Yanitskiy74474cf2019-07-17 16:40:11 +07001008 /* Optional Selection Parameters */
Harald Weltef85b33f2019-05-28 17:56:21 +02001009 if (bitvec_get_bit_high(&bv) == H) {
1010 sp->present = 1;
1011 sp->cbq = bitvec_get_uint(&bv, 1);
1012 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
1013 sp->temp_offs = bitvec_get_uint(&bv, 3);
1014 sp->penalty_time = bitvec_get_uint(&bv, 5);
Harald Welte65aabd42020-10-15 08:04:49 +02001015 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001016 sp->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001017 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001018
1019 /* Optional Power Offset */
1020 if (bitvec_get_bit_high(&bv) == H) {
1021 po->present = 1;
1022 po->power_offset = bitvec_get_uint(&bv, 2);
Harald Welte65aabd42020-10-15 08:04:49 +02001023 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001024 po->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001025 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001026
1027 /* System Information 2ter Indicator */
1028 if (bitvec_get_bit_high(&bv) == H)
1029 si3->si2ter_indicator = 1;
1030 else
1031 si3->si2ter_indicator = 0;
1032
1033 /* Early Classmark Sending Control */
1034 if (bitvec_get_bit_high(&bv) == H)
1035 si3->early_cm_ctrl = 1;
1036 else
1037 si3->early_cm_ctrl = 0;
1038
1039 /* Scheduling if and where */
1040 if (bitvec_get_bit_high(&bv) == H) {
1041 si3->scheduling.present = 1;
1042 si3->scheduling.where = bitvec_get_uint(&bv, 3);
Harald Welte65aabd42020-10-15 08:04:49 +02001043 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001044 si3->scheduling.present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001045 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001046
1047 /* GPRS Indicator */
1048 if (bitvec_get_bit_high(&bv) == H) {
1049 gi->present = 1;
1050 gi->ra_colour = bitvec_get_uint(&bv, 3);
1051 gi->si13_position = bitvec_get_uint(&bv, 1);
Harald Welte65aabd42020-10-15 08:04:49 +02001052 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001053 gi->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001054 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001055
1056 /* 3G Early Classmark Sending Restriction. If H, then controlled by
1057 * early_cm_ctrl above */
1058 if (bitvec_get_bit_high(&bv) == H)
1059 si3->early_cm_restrict_3g = 1;
1060 else
1061 si3->early_cm_restrict_3g = 0;
1062
1063 if (bitvec_get_bit_high(&bv) == H)
1064 si3->si2quater_indicator = 1;
1065 else
1066 si3->si2quater_indicator = 0;
1067}
Harald Welte5e1cd5e2020-10-11 20:04:04 +02001068
1069
1070void osmo_gsm48_rest_octets_si4_decode(struct osmo_gsm48_si_ro_info *si4, const uint8_t *data, int len)
1071{
1072 struct osmo_gsm48_si_selection_params *sp = &si4->selection_params;
1073 struct osmo_gsm48_si_power_offset *po = &si4->power_offset;
1074 struct osmo_gsm48_si3_gprs_ind *gi = &si4->gprs_ind;
1075 struct bitvec bv;
1076
1077 memset(&bv, 0, sizeof(bv));
1078 bv.data = (uint8_t *) data;
1079 bv.data_len = len;
1080
1081 memset(si4, 0, sizeof(*si4));
1082
1083 /* Optional Selection Parameters */
1084 if (bitvec_get_bit_high(&bv) == H) {
1085 sp->present = 1;
1086 sp->cbq = bitvec_get_uint(&bv, 1);
1087 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
1088 sp->temp_offs = bitvec_get_uint(&bv, 3);
1089 sp->penalty_time = bitvec_get_uint(&bv, 5);
1090 } else {
1091 sp->present = 0;
1092 }
1093
1094 /* Optional Power Offset */
1095 if (bitvec_get_bit_high(&bv) == H) {
1096 po->present = 1;
1097 po->power_offset = bitvec_get_uint(&bv, 2);
1098 } else {
1099 po->present = 0;
1100 }
1101
1102 /* GPRS Indicator */
1103 if (bitvec_get_bit_high(&bv) == H) {
1104 gi->present = 1;
1105 gi->ra_colour = bitvec_get_uint(&bv, 3);
1106 gi->si13_position = bitvec_get_uint(&bv, 1);
1107 } else {
1108 gi->present = 0;
1109 }
1110}