blob: 84b7589a8be7157db7c8f12df0434b368a331380 [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
Pau Espin Pedrol908224c2020-12-14 17:11:19 +0100196 /* Serving Cell Priority Parameters Descr. is Present,
197 * see also: 3GPP TS 44.018, Table 10.5.2.33b.1 */
198 bitvec_set_bit(bv, 1);
199
200 /* GERAN_PRIORITY */
201 bitvec_set_uint(bv, 0, 3);
202
203 /* THRESH_Priority_Search */
204 bitvec_set_uint(bv, 0, 4);
205
206 /* THRESH_GSM_low */
207 bitvec_set_uint(bv, 0, 4);
208
209 /* H_PRIO */
210 bitvec_set_uint(bv, 0, 2);
211
212 /* T_Reselection */
213 bitvec_set_uint(bv, 0, 2);
214
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200215 /* No 3G Priority Parameters Description */
216 bitvec_set_bit(bv, 0);
217 /* E-UTRAN Parameters Description */
218 bitvec_set_bit(bv, 1);
219
220 /* E-UTRAN_CCN_ACTIVE */
221 bitvec_set_bit(bv, 0);
222 /* E-UTRAN_Start: 9.1.54 */
223 bitvec_set_bit(bv, 1);
224 /* E-UTRAN_Stop: 9.1.54 */
225 bitvec_set_bit(bv, 1);
226
227 /* No E-UTRAN Measurement Parameters Descr. */
228 bitvec_set_bit(bv, 0);
229 /* No GPRS E-UTRAN Measurement Param. Descr. */
230 bitvec_set_bit(bv, 0);
231
232 /* Note: each of next 3 "repeated" structures might be repeated any
233 (0, 1, 2...) times - we only support 1 and 0 */
234
235 /* Repeated E-UTRAN Neighbour Cells */
236 bitvec_set_bit(bv, 1);
237
238 appended = append_eutran_neib_cell(bv, e, e_offset, rem);
239 if (!appended) { /* appending is impossible within current budget: rollback */
240 bv->cur_bit = old;
241 return;
242 }
243
244 /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */
245 bitvec_set_bit(bv, 0);
246
247 /* Note: following 2 repeated structs are not supported ATM */
248 /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */
249 bitvec_set_bit(bv, 0);
250 /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */
251 bitvec_set_bit(bv, 0);
252
253 /* Priority and E-UTRAN Parameters Description ends here */
254 /* No 3G CSG Description */
255 bitvec_set_bit(bv, 0);
256 /* No E-UTRAN CSG Description */
257 bitvec_set_bit(bv, 0);
258 /* No Additions in Rel-9: */
259 bitvec_set_bit(bv, L);
260}
261
262static int range_encode(enum osmo_gsm48_range r, int *arfcns, int arfcns_used, int *w,
263 int f0, uint8_t *chan_list)
264{
265 /*
266 * Manipulate the ARFCN list according to the rules in J4 depending
267 * on the selected range.
268 */
269 int rc, f0_included;
270
271 osmo_gsm48_range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
272
273 rc = osmo_gsm48_range_enc_arfcns(r, arfcns, arfcns_used, w, 0);
274 if (rc < 0)
275 return rc;
276
277 /* Select the range and the amount of bits needed */
278 switch (r) {
279 case OSMO_GSM48_ARFCN_RANGE_128:
Harald Welte1276c172019-05-28 18:38:35 +0200280 return osmo_gsm48_range_enc_128(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200281 case OSMO_GSM48_ARFCN_RANGE_256:
Harald Welte1276c172019-05-28 18:38:35 +0200282 return osmo_gsm48_range_enc_256(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200283 case OSMO_GSM48_ARFCN_RANGE_512:
Harald Welte1276c172019-05-28 18:38:35 +0200284 return osmo_gsm48_range_enc_512(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200285 case OSMO_GSM48_ARFCN_RANGE_1024:
Harald Welte1276c172019-05-28 18:38:35 +0200286 return osmo_gsm48_range_enc_1024(chan_list, f0, f0_included, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200287 default:
288 return -ERANGE;
289 };
290
291 return f0_included;
292}
293
294static inline int f0_helper(int *sc, size_t length, uint8_t *chan_list)
295{
296 int w[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS] = { 0 };
297
298 return range_encode(OSMO_GSM48_ARFCN_RANGE_1024, sc, length, w, 0, chan_list);
299}
300
301/* Return p(n) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */
302static unsigned range1024_p(unsigned n)
303{
304 switch (n) {
305 case 0: return 0;
306 case 1: return 10;
307 case 2: return 19;
308 case 3: return 28;
309 case 4: return 36;
310 case 5: return 44;
311 case 6: return 52;
312 case 7: return 60;
313 case 8: return 67;
314 case 9: return 74;
315 case 10: return 81;
316 case 11: return 88;
317 case 12: return 95;
318 case 13: return 102;
319 case 14: return 109;
320 case 15: return 116;
321 case 16: return 122;
322 default: return 0;
323 }
324}
325
326/* Estimate how many bits it'll take to append single FDD UARFCN */
327static inline int append_utran_fdd_length(uint16_t u, const int *sc, size_t sc_len, size_t length)
328{
329 uint8_t chan_list[16] = { 0 };
330 int tmp[sc_len], f0;
331
332 memcpy(tmp, sc, sizeof(tmp));
333
334 f0 = f0_helper(tmp, length, chan_list);
335 if (f0 < 0)
336 return f0;
337
338 return 21 + range1024_p(length);
339}
340
341/* Append single FDD UARFCN */
342static inline int append_utran_fdd(struct bitvec *bv, uint16_t u, int *sc, size_t length)
343{
344 uint8_t chan_list[16] = { 0 };
345 int f0 = f0_helper(sc, length, chan_list);
346
347 if (f0 < 0)
348 return f0;
349
350 /* Repeated UTRAN FDD Neighbour Cells */
351 bitvec_set_bit(bv, 1);
352
353 /* FDD-ARFCN */
354 bitvec_set_bit(bv, 0);
355 bitvec_set_uint(bv, u, 14);
356
357 /* FDD_Indic0: parameter value '0000000000' is a member of the set? */
358 bitvec_set_bit(bv, f0);
359 /* NR_OF_FDD_CELLS */
360 bitvec_set_uint(bv, length, 5);
361
362 f0 = bv->cur_bit;
363 bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list);
364 bv->cur_bit = f0 + range1024_p(length);
365
366 return 21 + range1024_p(length);
367}
368
369static inline int try_adding_uarfcn(struct bitvec *bv, uint16_t *scramble_list,
370 size_t uarfcn_length, size_t *u_offset,
371 uint16_t uarfcn, uint8_t num_sc, uint8_t start_pos, uint8_t budget)
372{
373 int i, k, rc, a[uarfcn_length];
374
375 if (budget < 23)
376 return -ENOMEM;
377
378 /* copy corresponding Scrambling Codes: range encoder make in-place modifications */
379 for (i = start_pos, k = 0; i < num_sc; a[k++] = scramble_list[i++]);
380
381 /* estimate bit length requirements */
382 rc = append_utran_fdd_length(uarfcn, a, uarfcn_length, k);
383 if (rc < 0)
384 return rc; /* range encoder failure */
385
386 if (budget - rc <= 0)
387 return -ENOMEM; /* we have ran out of budget in current SI2q */
388
389 /* compute next offset */
390 *u_offset += k;
391
392 return budget - append_utran_fdd(bv, uarfcn, a, k);
393}
394
395/* Append multiple FDD UARFCNs */
396static inline void append_uarfcns(struct bitvec *bv, const uint16_t *uarfcn_list, size_t *u_offset,
397 size_t uarfcn_length, uint16_t *scramble_list, uint8_t budget)
398{
399 int i, rem = budget - 7, st = *u_offset; /* account for constant bits right away */
400 uint16_t cu = uarfcn_list[*u_offset]; /* caller ensures that length is positive */
401
402 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
403
404 if (budget <= 7)
405 return;
406
407 /* 3G Neighbour Cell Description */
408 bitvec_set_bit(bv, 1);
409 /* No Index_Start_3G */
410 bitvec_set_bit(bv, 0);
411 /* No Absolute_Index_Start_EMR */
412 bitvec_set_bit(bv, 0);
413
414 /* UTRAN FDD Description */
415 bitvec_set_bit(bv, 1);
416 /* No Bandwidth_FDD */
417 bitvec_set_bit(bv, 0);
418
419 for (i = *u_offset; i <= uarfcn_length; i++)
420 if (uarfcn_list[i] != cu) { /* we've reached new UARFCN */
421 rem = try_adding_uarfcn(bv, scramble_list, uarfcn_length, u_offset, cu, i, st, rem);
422 if (rem < 0)
423 break;
424
425 if (i < uarfcn_length) {
426 cu = uarfcn_list[i];
427 st = i;
Harald Welte65aabd42020-10-15 08:04:49 +0200428 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200429 break;
Harald Welte65aabd42020-10-15 08:04:49 +0200430 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200431 }
432
433 /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */
434 bitvec_set_bit(bv, 0);
435
436 /* UTRAN TDD Description */
437 bitvec_set_bit(bv, 0);
438}
439
440static size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e)
441{
442 unsigned i, ret = 0;
443
444 if (!e)
445 return 0;
446
447 for (i = 0; i < e->length; i++)
448 if (e->arfcn[i] != OSMO_EARFCN_INVALID)
449 ret++;
450
451 return ret;
452}
453
454/* generate SI2quater rest octets: 3GPP TS 44.018 § 10.5.2.33b */
Harald Welte428d03b2019-05-28 18:46:20 +0200455int osmo_gsm48_rest_octets_si2quater_encode(uint8_t *data, uint8_t si2q_index, uint8_t si2q_count,
456 const uint16_t *uarfcn_list, size_t *u_offset,
457 size_t uarfcn_length, uint16_t *scramble_list,
458 struct osmo_earfcn_si2q *si2quater_neigh_list,
459 size_t *e_offset)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200460{
461 int rc;
462 struct bitvec bv;
463
464 if (si2q_count < si2q_index)
465 return -EINVAL;
466
467 bv.data = data;
468 bv.data_len = 20;
469 bitvec_zero(&bv);
470
471 /* BA_IND: Set to '0' as that's what we use for SI2xxx type,
472 * whereas '1' is used for SI5xxx type messages. The point here
473 * is to be able to correlate whether a given MS measurement
474 * report was using the neighbor cells advertised in SI2 or in
475 * SI5, as those two could very well be different */
476 bitvec_set_bit(&bv, 0);
477 /* 3G_BA_IND */
478 bitvec_set_bit(&bv, 1);
479 /* MP_CHANGE_MARK */
480 bitvec_set_bit(&bv, 0);
481
482 /* SI2quater_INDEX */
483 bitvec_set_uint(&bv, si2q_index, 4);
484 /* SI2quater_COUNT */
485 bitvec_set_uint(&bv, si2q_count, 4);
486
487 /* No Measurement_Parameters Description */
488 bitvec_set_bit(&bv, 0);
489 /* No GPRS_Real Time Difference Description */
490 bitvec_set_bit(&bv, 0);
491 /* No GPRS_BSIC Description */
492 bitvec_set_bit(&bv, 0);
493 /* No GPRS_REPORT PRIORITY Description */
494 bitvec_set_bit(&bv, 0);
495 /* No GPRS_MEASUREMENT_Parameters Description */
496 bitvec_set_bit(&bv, 0);
497 /* No NC Measurement Parameters */
498 bitvec_set_bit(&bv, 0);
499 /* No extension (length) */
500 bitvec_set_bit(&bv, 0);
501
502 rc = SI2Q_MAX_LEN - (bv.cur_bit + 3);
503 if (rc > 0 && uarfcn_length - *u_offset > 0)
504 append_uarfcns(&bv, uarfcn_list, u_offset, uarfcn_length, scramble_list, rc);
505 else /* No 3G Neighbour Cell Description */
506 bitvec_set_bit(&bv, 0);
507
508 /* No 3G Measurement Parameters Description */
509 bitvec_set_bit(&bv, 0);
510 /* No GPRS_3G_MEASUREMENT Parameters Descr. */
511 bitvec_set_bit(&bv, 0);
512
513 rc = SI2Q_MAX_LEN - bv.cur_bit;
514 if (rc > 0 && si2q_earfcn_count(si2quater_neigh_list) - *e_offset > 0)
515 append_earfcn(&bv, si2quater_neigh_list, e_offset, rc);
516 else /* No Additions in Rel-5: */
517 bitvec_set_bit(&bv, L);
518
519 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
520 return bv.data_len;
521}
522
523/* Append selection parameters to bitvec */
524static void append_selection_params(struct bitvec *bv,
525 const struct osmo_gsm48_si_selection_params *sp)
526{
527 if (sp->present) {
528 bitvec_set_bit(bv, H);
529 bitvec_set_bit(bv, sp->cbq);
530 bitvec_set_uint(bv, sp->cell_resel_off, 6);
531 bitvec_set_uint(bv, sp->temp_offs, 3);
532 bitvec_set_uint(bv, sp->penalty_time, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200533 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200534 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200535 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200536}
537
538/* Append power offset to bitvec */
539static void append_power_offset(struct bitvec *bv,
540 const struct osmo_gsm48_si_power_offset *po)
541{
542 if (po->present) {
543 bitvec_set_bit(bv, H);
544 bitvec_set_uint(bv, po->power_offset, 2);
Harald Welte65aabd42020-10-15 08:04:49 +0200545 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200546 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200547 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200548}
549
550/* Append GPRS indicator to bitvec */
551static void append_gprs_ind(struct bitvec *bv,
552 const struct osmo_gsm48_si3_gprs_ind *gi)
553{
554 if (gi->present) {
555 bitvec_set_bit(bv, H);
556 bitvec_set_uint(bv, gi->ra_colour, 3);
557 /* 0 == SI13 in BCCH Norm, 1 == SI13 sent on BCCH Ext */
558 bitvec_set_bit(bv, gi->si13_position);
Harald Welte65aabd42020-10-15 08:04:49 +0200559 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200560 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200561 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200562}
563
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200564/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
Harald Welte428d03b2019-05-28 18:46:20 +0200565int osmo_gsm48_rest_octets_si3_encode(uint8_t *data, const struct osmo_gsm48_si_ro_info *si3)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200566{
567 struct bitvec bv;
568
569 memset(&bv, 0, sizeof(bv));
570 bv.data = data;
571 bv.data_len = 4;
572
573 /* Optional Selection Parameters */
574 append_selection_params(&bv, &si3->selection_params);
575
576 /* Optional Power Offset */
577 append_power_offset(&bv, &si3->power_offset);
578
579 /* Do we have a SI2ter on the BCCH? */
580 if (si3->si2ter_indicator)
581 bitvec_set_bit(&bv, H);
582 else
583 bitvec_set_bit(&bv, L);
584
585 /* Early Classmark Sending Control */
586 if (si3->early_cm_ctrl)
587 bitvec_set_bit(&bv, H);
588 else
589 bitvec_set_bit(&bv, L);
590
591 /* Do we have a SI Type 9 on the BCCH? */
592 if (si3->scheduling.present) {
593 bitvec_set_bit(&bv, H);
594 bitvec_set_uint(&bv, si3->scheduling.where, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200595 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200596 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200597 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200598
599 /* GPRS Indicator */
600 append_gprs_ind(&bv, &si3->gprs_ind);
601
602 /* 3G Early Classmark Sending Restriction. If H, then controlled by
603 * early_cm_ctrl above */
604 if (si3->early_cm_restrict_3g)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200605 bitvec_set_bit(&bv, H);
Vadim Yanitskiyc9eab822020-05-05 02:03:29 +0700606 else
607 bitvec_set_bit(&bv, L);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200608
609 if (si3->si2quater_indicator) {
610 bitvec_set_bit(&bv, H); /* indicator struct present */
611 bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */
612 }
613
614 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
615 return bv.data_len;
616}
617
618static int append_lsa_params(struct bitvec *bv,
619 const struct osmo_gsm48_lsa_params *lsa_params)
620{
621 /* FIXME */
622 return -1;
623}
624
625/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
Harald Welte428d03b2019-05-28 18:46:20 +0200626int 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 +0200627{
628 struct bitvec bv;
629
630 memset(&bv, 0, sizeof(bv));
631 bv.data = data;
632 bv.data_len = len;
633
634 /* SI4 Rest Octets O */
635 append_selection_params(&bv, &si4->selection_params);
636 append_power_offset(&bv, &si4->power_offset);
637 append_gprs_ind(&bv, &si4->gprs_ind);
638
639 if (0 /* FIXME */) {
640 /* H and SI4 Rest Octets S */
641 bitvec_set_bit(&bv, H);
642
643 /* LSA Parameters */
644 if (si4->lsa_params.present) {
645 bitvec_set_bit(&bv, H);
646 append_lsa_params(&bv, &si4->lsa_params);
Harald Welte65aabd42020-10-15 08:04:49 +0200647 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200648 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200649 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200650
651 /* Cell Identity */
652 if (1) {
653 bitvec_set_bit(&bv, H);
654 bitvec_set_uint(&bv, si4->cell_id, 16);
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 /* LSA ID Information */
660 if (0) {
661 bitvec_set_bit(&bv, H);
662 /* FIXME */
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 } else {
667 /* L and break indicator */
668 bitvec_set_bit(&bv, L);
669 bitvec_set_bit(&bv, si4->break_ind ? H : L);
670 }
671
672 return bv.data_len;
673}
674
675
676/* GSM 04.18 ETSI TS 101 503 V8.27.0 (2006-05)
677
678<SI6 rest octets> ::=
679{L | H <PCH and NCH info>}
680{L | H <VBS/VGCS options : bit(2)>}
681{ < DTM_support : bit == L > I < DTM_support : bit == H >
682< RAC : bit (8) >
683< MAX_LAPDm : bit (3) > }
684< Band indicator >
685{ L | H < GPRS_MS_TXPWR_MAX_CCH : bit (5) > }
686<implicit spare >;
687*/
Harald Welte86156de2019-05-28 19:49:47 +0200688int osmo_gsm48_rest_octets_si6_encode(uint8_t *data, const struct osmo_gsm48_si6_ro_info *in)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200689{
690 struct bitvec bv;
691
692 memset(&bv, 0, sizeof(bv));
693 bv.data = data;
694 bv.data_len = 1;
695
Harald Welte86156de2019-05-28 19:49:47 +0200696 if (in->pch_nch_info.present) {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200697 bitvec_set_bit(&bv, H);
Harald Welte86156de2019-05-28 19:49:47 +0200698 bitvec_set_bit(&bv, !!in->pch_nch_info.paging_channel_restructuring);
699 bitvec_set_uint(&bv, in->pch_nch_info.nln_sacch, 2);
700 if (in->pch_nch_info.call_priority_present) {
701 bitvec_set_bit(&bv, 1);
702 bitvec_set_uint(&bv, in->pch_nch_info.call_priority, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200703 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200704 bitvec_set_bit(&bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200705 }
Harald Welte86156de2019-05-28 19:49:47 +0200706 bitvec_set_bit(&bv, !!in->pch_nch_info.nln_status_sacch);
Harald Welte65aabd42020-10-15 08:04:49 +0200707 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200708 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200709 }
Harald Welte86156de2019-05-28 19:49:47 +0200710
711 if (in->vbs_vgcs_options.present) {
712 bitvec_set_bit(&bv, H);
713 bitvec_set_bit(&bv, !!in->vbs_vgcs_options.inband_notifications);
714 bitvec_set_bit(&bv, !!in->vbs_vgcs_options.inband_pagings);
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->dtm_support.present) {
720 bitvec_set_bit(&bv, H);
721 bitvec_set_uint(&bv, in->dtm_support.rac, 8);
722 bitvec_set_uint(&bv, in->dtm_support.max_lapdm, 3);
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->band_indicator_1900)
728 bitvec_set_bit(&bv, H);
729 else
730 bitvec_set_bit(&bv, L);
731
732 if (in->gprs_ms_txpwr_max_ccch.present) {
733 bitvec_set_bit(&bv, H);
734 bitvec_set_uint(&bv, in->gprs_ms_txpwr_max_ccch.max_txpwr, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200735 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200736 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200737 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200738
739 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
740 return bv.data_len;
741}
742
743/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
744 < GPRS Mobile Allocation IE > ::=
745 < HSN : bit (6) >
746 { 0 | 1 < RFL number list : < RFL number list struct > > }
747 { 0 < MA_LENGTH : bit (6) >
748 < MA_BITMAP: bit (val(MA_LENGTH) + 1) >
749 | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;
750
751 < RFL number list struct > :: =
752 < RFL_NUMBER : bit (4) >
753 { 0 | 1 < RFL number list struct > } ;
754 < ARFCN index list struct > ::=
755 < ARFCN_INDEX : bit(6) >
756 { 0 | 1 < ARFCN index list struct > } ;
757 */
758static int append_gprs_mobile_alloc(struct bitvec *bv)
759{
760 /* Hopping Sequence Number */
761 bitvec_set_uint(bv, 0, 6);
762
763 if (0) {
764 /* We want to use a RFL number list */
765 bitvec_set_bit(bv, 1);
766 /* FIXME: RFL number list */
Harald Welte65aabd42020-10-15 08:04:49 +0200767 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200768 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200769 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200770
771 if (0) {
772 /* We want to use a MA_BITMAP */
773 bitvec_set_bit(bv, 0);
774 /* FIXME: MA_LENGTH, MA_BITMAP, ... */
775 } else {
776 bitvec_set_bit(bv, 1);
777 if (0) {
778 /* We want to provide an ARFCN index list */
779 bitvec_set_bit(bv, 1);
780 /* FIXME */
Harald Welte65aabd42020-10-15 08:04:49 +0200781 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200782 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200783 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200784 }
785 return 0;
786}
787
788static int encode_t3192(unsigned int t3192)
789{
790 /* See also 3GPP TS 44.060
791 Table 12.24.2: GPRS Cell Options information element details */
792 if (t3192 == 0)
793 return 3;
794 else if (t3192 <= 80)
795 return 4;
796 else if (t3192 <= 120)
797 return 5;
798 else if (t3192 <= 160)
799 return 6;
800 else if (t3192 <= 200)
801 return 7;
802 else if (t3192 <= 500)
803 return 0;
804 else if (t3192 <= 1000)
805 return 1;
806 else if (t3192 <= 1500)
807 return 2;
808 else
809 return -EINVAL;
810}
811
812static int encode_drx_timer(unsigned int drx)
813{
814 if (drx == 0)
815 return 0;
816 else if (drx == 1)
817 return 1;
818 else if (drx == 2)
819 return 2;
820 else if (drx <= 4)
821 return 3;
822 else if (drx <= 8)
823 return 4;
824 else if (drx <= 16)
825 return 5;
826 else if (drx <= 32)
827 return 6;
828 else if (drx <= 64)
829 return 7;
830 else
831 return -EINVAL;
832}
833
834/* GPRS Cell Options as per TS 04.60 Chapter 12.24
835 < GPRS Cell Options IE > ::=
836 < NMO : bit(2) >
837 < T3168 : bit(3) >
838 < T3192 : bit(3) >
839 < DRX_TIMER_MAX: bit(3) >
840 < ACCESS_BURST_TYPE: bit >
841 < CONTROL_ACK_TYPE : bit >
842 < BS_CV_MAX: bit(4) >
843 { 0 | 1 < PAN_DEC : bit(3) >
844 < PAN_INC : bit(3) >
845 < PAN_MAX : bit(3) >
846 { 0 | 1 < Extension Length : bit(6) >
847 < bit (val(Extension Length) + 1
848 & { < Extension Information > ! { bit ** = <no string> } } ;
849 < Extension Information > ::=
850 { 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit >
851 < BEP_PERIOD : bit(4) > }
852 < PFC_FEATURE_MODE : bit >
853 < DTM_SUPPORT : bit >
854 <BSS_PAGING_COORDINATION: bit >
855 <spare bit > ** ;
856 */
857static int append_gprs_cell_opt(struct bitvec *bv,
858 const struct osmo_gprs_cell_options *gco)
859{
860 int t3192, drx_timer_max;
861
862 t3192 = encode_t3192(gco->t3192);
863 if (t3192 < 0)
864 return t3192;
865
866 drx_timer_max = encode_drx_timer(gco->drx_timer_max);
867 if (drx_timer_max < 0)
868 return drx_timer_max;
869
870 bitvec_set_uint(bv, gco->nmo, 2);
871
872 /* See also 3GPP TS 44.060
873 Table 12.24.2: GPRS Cell Options information element details */
874 bitvec_set_uint(bv, gco->t3168 / 500 - 1, 3);
875
876 bitvec_set_uint(bv, t3192, 3);
877 bitvec_set_uint(bv, drx_timer_max, 3);
878 /* ACCESS_BURST_TYPE: Hard-code 8bit */
879 bitvec_set_bit(bv, 0);
880 /* CONTROL_ACK_TYPE: */
881 bitvec_set_bit(bv, gco->ctrl_ack_type_use_block);
882 bitvec_set_uint(bv, gco->bs_cv_max, 4);
883
884 if (0) {
885 /* hard-code no PAN_{DEC,INC,MAX} */
886 bitvec_set_bit(bv, 0);
887 } else {
888 /* copied from ip.access BSC protocol trace */
889 bitvec_set_bit(bv, 1);
890 bitvec_set_uint(bv, 1, 3); /* DEC */
891 bitvec_set_uint(bv, 1, 3); /* INC */
892 bitvec_set_uint(bv, 15, 3); /* MAX */
893 }
894
895 if (!gco->ext_info_present) {
896 /* no extension information */
897 bitvec_set_bit(bv, 0);
898 } else {
899 /* extension information */
900 bitvec_set_bit(bv, 1);
901 if (!gco->ext_info.egprs_supported) {
902 /* 6bit length of extension */
903 bitvec_set_uint(bv, (1 + 3)-1, 6);
904 /* EGPRS supported in the cell */
905 bitvec_set_bit(bv, 0);
906 } else {
907 /* 6bit length of extension */
908 bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);
909 /* EGPRS supported in the cell */
910 bitvec_set_bit(bv, 1);
911
Pau Espin Pedrol30bf0e62020-12-14 17:13:47 +0100912 /* 1bit EGPRS PACKET CHANNEL REQUEST (inverted logic) */
913 bitvec_set_bit(bv, !gco->ext_info.use_egprs_p_ch_req);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200914
915 /* 4bit BEP PERIOD */
916 bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
917 }
918 bitvec_set_bit(bv, gco->ext_info.pfc_supported);
919 bitvec_set_bit(bv, gco->ext_info.dtm_supported);
920 bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
921 }
922
923 return 0;
924}
925
926static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
927 const struct osmo_gprs_power_ctrl_pars *pcp)
928{
929 bitvec_set_uint(bv, pcp->alpha, 4);
930 bitvec_set_uint(bv, pcp->t_avg_w, 5);
931 bitvec_set_uint(bv, pcp->t_avg_t, 5);
932 bitvec_set_uint(bv, pcp->pc_meas_chan, 1);
933 bitvec_set_uint(bv, pcp->n_avg_i, 4);
934}
935
936/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
Harald Welte428d03b2019-05-28 18:46:20 +0200937int osmo_gsm48_rest_octets_si13_encode(uint8_t *data, const struct osmo_gsm48_si13_info *si13)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200938{
939 struct bitvec bv;
940
941 memset(&bv, 0, sizeof(bv));
942 bv.data = data;
943 bv.data_len = 20;
944
945 if (0) {
946 /* No rest octets */
947 bitvec_set_bit(&bv, L);
948 } else {
949 bitvec_set_bit(&bv, H);
950 bitvec_set_uint(&bv, si13->bcch_change_mark, 3);
951 bitvec_set_uint(&bv, si13->si_change_field, 4);
952 if (1) {
953 bitvec_set_bit(&bv, 0);
954 } else {
955 bitvec_set_bit(&bv, 1);
956 bitvec_set_uint(&bv, si13->bcch_change_mark, 2);
957 append_gprs_mobile_alloc(&bv);
958 }
959 /* PBCCH not present in cell:
960 it shall never be indicated according to 3GPP TS 44.018 Table 10.5.2.37b.1 */
961 bitvec_set_bit(&bv, 0);
962 bitvec_set_uint(&bv, si13->rac, 8);
963 bitvec_set_bit(&bv, si13->spgc_ccch_sup);
964 bitvec_set_uint(&bv, si13->prio_acc_thr, 3);
965 bitvec_set_uint(&bv, si13->net_ctrl_ord, 2);
966 append_gprs_cell_opt(&bv, &si13->cell_opts);
967 append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);
968
969 /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
970 bitvec_set_bit(&bv, H); /* added Release 99 */
971 /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
972 * was only added in this Release */
973 bitvec_set_bit(&bv, 1);
974 }
975 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
976 return bv.data_len;
977}
Harald Weltef85b33f2019-05-28 17:56:21 +0200978
979
980/***********************************************************************
981 * Decoder
982 ***********************************************************************/
983
984/*! Decode SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72).
985 * \param[out] si3 decoded SI3 rest octets
986 * \param[in] encoded SI3 rest octets, 4 octets long */
987void osmo_gsm48_rest_octets_si3_decode(struct osmo_gsm48_si_ro_info *si3, const uint8_t *data)
988{
989 struct osmo_gsm48_si_selection_params *sp = &si3->selection_params;
990 struct osmo_gsm48_si_power_offset *po = &si3->power_offset;
991 struct osmo_gsm48_si3_gprs_ind *gi = &si3->gprs_ind;
992 struct bitvec bv;
993
994 memset(&bv, 0, sizeof(bv));
995 bv.data = (uint8_t *) data;
996 bv.data_len = 4;
997
998 memset(si3, 0, sizeof(*si3));
999
Vadim Yanitskiy74474cf2019-07-17 16:40:11 +07001000 /* Optional Selection Parameters */
Harald Weltef85b33f2019-05-28 17:56:21 +02001001 if (bitvec_get_bit_high(&bv) == H) {
1002 sp->present = 1;
1003 sp->cbq = bitvec_get_uint(&bv, 1);
1004 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
1005 sp->temp_offs = bitvec_get_uint(&bv, 3);
1006 sp->penalty_time = bitvec_get_uint(&bv, 5);
Harald Welte65aabd42020-10-15 08:04:49 +02001007 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001008 sp->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001009 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001010
1011 /* Optional Power Offset */
1012 if (bitvec_get_bit_high(&bv) == H) {
1013 po->present = 1;
1014 po->power_offset = bitvec_get_uint(&bv, 2);
Harald Welte65aabd42020-10-15 08:04:49 +02001015 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001016 po->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001017 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001018
1019 /* System Information 2ter Indicator */
1020 if (bitvec_get_bit_high(&bv) == H)
1021 si3->si2ter_indicator = 1;
1022 else
1023 si3->si2ter_indicator = 0;
1024
1025 /* Early Classmark Sending Control */
1026 if (bitvec_get_bit_high(&bv) == H)
1027 si3->early_cm_ctrl = 1;
1028 else
1029 si3->early_cm_ctrl = 0;
1030
1031 /* Scheduling if and where */
1032 if (bitvec_get_bit_high(&bv) == H) {
1033 si3->scheduling.present = 1;
1034 si3->scheduling.where = bitvec_get_uint(&bv, 3);
Harald Welte65aabd42020-10-15 08:04:49 +02001035 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001036 si3->scheduling.present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001037 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001038
1039 /* GPRS Indicator */
1040 if (bitvec_get_bit_high(&bv) == H) {
1041 gi->present = 1;
1042 gi->ra_colour = bitvec_get_uint(&bv, 3);
1043 gi->si13_position = bitvec_get_uint(&bv, 1);
Harald Welte65aabd42020-10-15 08:04:49 +02001044 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001045 gi->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001046 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001047
1048 /* 3G Early Classmark Sending Restriction. If H, then controlled by
1049 * early_cm_ctrl above */
1050 if (bitvec_get_bit_high(&bv) == H)
1051 si3->early_cm_restrict_3g = 1;
1052 else
1053 si3->early_cm_restrict_3g = 0;
1054
1055 if (bitvec_get_bit_high(&bv) == H)
1056 si3->si2quater_indicator = 1;
1057 else
1058 si3->si2quater_indicator = 0;
1059}
Harald Welte5e1cd5e2020-10-11 20:04:04 +02001060
1061
1062void osmo_gsm48_rest_octets_si4_decode(struct osmo_gsm48_si_ro_info *si4, const uint8_t *data, int len)
1063{
1064 struct osmo_gsm48_si_selection_params *sp = &si4->selection_params;
1065 struct osmo_gsm48_si_power_offset *po = &si4->power_offset;
1066 struct osmo_gsm48_si3_gprs_ind *gi = &si4->gprs_ind;
1067 struct bitvec bv;
1068
1069 memset(&bv, 0, sizeof(bv));
1070 bv.data = (uint8_t *) data;
1071 bv.data_len = len;
1072
1073 memset(si4, 0, sizeof(*si4));
1074
1075 /* Optional Selection Parameters */
1076 if (bitvec_get_bit_high(&bv) == H) {
1077 sp->present = 1;
1078 sp->cbq = bitvec_get_uint(&bv, 1);
1079 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
1080 sp->temp_offs = bitvec_get_uint(&bv, 3);
1081 sp->penalty_time = bitvec_get_uint(&bv, 5);
1082 } else {
1083 sp->present = 0;
1084 }
1085
1086 /* Optional Power Offset */
1087 if (bitvec_get_bit_high(&bv) == H) {
1088 po->present = 1;
1089 po->power_offset = bitvec_get_uint(&bv, 2);
1090 } else {
1091 po->present = 0;
1092 }
1093
1094 /* GPRS Indicator */
1095 if (bitvec_get_bit_high(&bv) == H) {
1096 gi->present = 1;
1097 gi->ra_colour = bitvec_get_uint(&bv, 3);
1098 gi->si13_position = bitvec_get_uint(&bv, 1);
1099 } else {
1100 gi->present = 0;
1101 }
1102}