blob: 1bab8e0c4f43a6ed986341b0cbe2e6dab5db9524 [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;
Pau Espin Pedrol0f619de2020-12-14 17:58:00 +010067 size_t offset = *e_offset;
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +020068 int16_t rem = budget - 6; /* account for mandatory stop bit and THRESH_E-UTRAN_high */
69 uint8_t earfcn_budget;
70
71 if (budget <= 6)
72 return false;
73
74 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
75
76 /* first we have to properly adjust budget requirements */
77 if (e->prio_valid) /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
78 rem -= 4;
79 else
80 rem--;
81
82 if (e->thresh_lo_valid) /* THRESH_E-UTRAN_low: */
83 rem -= 6;
84 else
85 rem--;
86
87 if (e->qrxlm_valid) /* E-UTRAN_QRXLEVMIN: */
88 rem -= 6;
89 else
90 rem--;
91
92 if (rem < 0)
93 return false;
94
95 /* now we can proceed with actually adding EARFCNs within adjusted budget limit */
96 for (i = 0; i < e->length; i++) {
97 if (e->arfcn[i] != OSMO_EARFCN_INVALID) {
Pau Espin Pedrol0f619de2020-12-14 17:58:00 +010098 if (skip < offset) {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +020099 skip++; /* ignore EARFCNs added on previous calls */
100 } else {
101 earfcn_budget = 17; /* compute budget per-EARFCN */
102 if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
103 earfcn_budget++;
104 else
105 earfcn_budget += 4;
106
107 if (rem - earfcn_budget < 0)
108 break;
109 else {
110 (*e_offset)++;
111 rem -= earfcn_budget;
112
113 if (rem < 0)
114 return false;
115
116 bitvec_set_bit(bv, 1); /* EARFCN: */
117 bitvec_set_uint(bv, e->arfcn[i], 16);
118
119 if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
120 bitvec_set_bit(bv, 0);
121 else { /* Measurement Bandwidth: 9.1.54 */
122 bitvec_set_bit(bv, 1);
123 bitvec_set_uint(bv, e->meas_bw[i], 3);
124 }
125 }
126 }
127 }
128 }
129
130 /* stop bit - end of EARFCN + Measurement Bandwidth sequence */
131 bitvec_set_bit(bv, 0);
132
133 /* Note: we don't support different EARFCN arrays each with different priority, threshold etc. */
134
135 if (e->prio_valid) {
136 /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
137 bitvec_set_bit(bv, 1);
138 bitvec_set_uint(bv, e->prio, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200139 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200140 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200141 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200142
143 /* THRESH_E-UTRAN_high */
144 bitvec_set_uint(bv, e->thresh_hi, 5);
145
146 if (e->thresh_lo_valid) {
147 /* THRESH_E-UTRAN_low: */
148 bitvec_set_bit(bv, 1);
149 bitvec_set_uint(bv, e->thresh_lo, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200150 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200151 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200152 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200153
154 if (e->qrxlm_valid) {
155 /* E-UTRAN_QRXLEVMIN: */
156 bitvec_set_bit(bv, 1);
157 bitvec_set_uint(bv, e->qrxlm, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200158 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200159 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200160 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200161
162 return true;
163}
164
165static inline void append_earfcn(struct bitvec *bv, const struct osmo_earfcn_si2q *e, size_t *e_offset, uint8_t budget)
166{
167 bool appended;
168 unsigned int old = bv->cur_bit; /* save current position to make rollback possible */
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100169 int rem = ((int)budget) - 40;
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200170 if (rem <= 0)
171 return;
172
173 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
174
175 /* Additions in Rel-5: */
176 bitvec_set_bit(bv, H);
177 /* No 3G Additional Measurement Param. Descr. */
178 bitvec_set_bit(bv, 0);
179 /* No 3G ADDITIONAL MEASUREMENT Param. Descr. 2 */
180 bitvec_set_bit(bv, 0);
181 /* Additions in Rel-6: */
182 bitvec_set_bit(bv, H);
183 /* 3G_CCN_ACTIVE */
184 bitvec_set_bit(bv, 0);
185 /* Additions in Rel-7: */
186 bitvec_set_bit(bv, H);
187 /* No 700_REPORTING_OFFSET */
188 bitvec_set_bit(bv, 0);
189 /* No 810_REPORTING_OFFSET */
190 bitvec_set_bit(bv, 0);
191 /* Additions in Rel-8: */
192 bitvec_set_bit(bv, H);
193
194 /* Priority and E-UTRAN Parameters Description */
195 bitvec_set_bit(bv, 1);
196
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100197 /* budget: 10 bits used above */
198
Pau Espin Pedrol908224c2020-12-14 17:11:19 +0100199 /* Serving Cell Priority Parameters Descr. is Present,
200 * see also: 3GPP TS 44.018, Table 10.5.2.33b.1 */
201 bitvec_set_bit(bv, 1);
202
203 /* GERAN_PRIORITY */
204 bitvec_set_uint(bv, 0, 3);
205
206 /* THRESH_Priority_Search */
207 bitvec_set_uint(bv, 0, 4);
208
209 /* THRESH_GSM_low */
210 bitvec_set_uint(bv, 0, 4);
211
212 /* H_PRIO */
213 bitvec_set_uint(bv, 0, 2);
214
215 /* T_Reselection */
216 bitvec_set_uint(bv, 0, 2);
217
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100218 /* budget: 26 bits used above */
219
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200220 /* No 3G Priority Parameters Description */
221 bitvec_set_bit(bv, 0);
222 /* E-UTRAN Parameters Description */
223 bitvec_set_bit(bv, 1);
224
225 /* E-UTRAN_CCN_ACTIVE */
226 bitvec_set_bit(bv, 0);
227 /* E-UTRAN_Start: 9.1.54 */
228 bitvec_set_bit(bv, 1);
229 /* E-UTRAN_Stop: 9.1.54 */
230 bitvec_set_bit(bv, 1);
231
232 /* No E-UTRAN Measurement Parameters Descr. */
233 bitvec_set_bit(bv, 0);
234 /* No GPRS E-UTRAN Measurement Param. Descr. */
235 bitvec_set_bit(bv, 0);
236
237 /* Note: each of next 3 "repeated" structures might be repeated any
238 (0, 1, 2...) times - we only support 1 and 0 */
239
240 /* Repeated E-UTRAN Neighbour Cells */
241 bitvec_set_bit(bv, 1);
242
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100243 /* budget: 34 bits used above */
244
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200245 appended = append_eutran_neib_cell(bv, e, e_offset, rem);
246 if (!appended) { /* appending is impossible within current budget: rollback */
247 bv->cur_bit = old;
248 return;
249 }
250
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100251 /* budget: further 6 bits used below, totalling 40 bits */
252
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200253 /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */
254 bitvec_set_bit(bv, 0);
255
256 /* Note: following 2 repeated structs are not supported ATM */
257 /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */
258 bitvec_set_bit(bv, 0);
259 /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */
260 bitvec_set_bit(bv, 0);
261
262 /* Priority and E-UTRAN Parameters Description ends here */
263 /* No 3G CSG Description */
264 bitvec_set_bit(bv, 0);
265 /* No E-UTRAN CSG Description */
266 bitvec_set_bit(bv, 0);
267 /* No Additions in Rel-9: */
268 bitvec_set_bit(bv, L);
269}
270
271static int range_encode(enum osmo_gsm48_range r, int *arfcns, int arfcns_used, int *w,
272 int f0, uint8_t *chan_list)
273{
274 /*
275 * Manipulate the ARFCN list according to the rules in J4 depending
276 * on the selected range.
277 */
278 int rc, f0_included;
279
280 osmo_gsm48_range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
281
282 rc = osmo_gsm48_range_enc_arfcns(r, arfcns, arfcns_used, w, 0);
283 if (rc < 0)
284 return rc;
285
286 /* Select the range and the amount of bits needed */
287 switch (r) {
288 case OSMO_GSM48_ARFCN_RANGE_128:
Harald Welte1276c172019-05-28 18:38:35 +0200289 return osmo_gsm48_range_enc_128(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200290 case OSMO_GSM48_ARFCN_RANGE_256:
Harald Welte1276c172019-05-28 18:38:35 +0200291 return osmo_gsm48_range_enc_256(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200292 case OSMO_GSM48_ARFCN_RANGE_512:
Harald Welte1276c172019-05-28 18:38:35 +0200293 return osmo_gsm48_range_enc_512(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200294 case OSMO_GSM48_ARFCN_RANGE_1024:
Harald Welte1276c172019-05-28 18:38:35 +0200295 return osmo_gsm48_range_enc_1024(chan_list, f0, f0_included, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200296 default:
297 return -ERANGE;
298 };
299
300 return f0_included;
301}
302
303static inline int f0_helper(int *sc, size_t length, uint8_t *chan_list)
304{
305 int w[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS] = { 0 };
306
307 return range_encode(OSMO_GSM48_ARFCN_RANGE_1024, sc, length, w, 0, chan_list);
308}
309
310/* Return p(n) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */
311static unsigned range1024_p(unsigned n)
312{
313 switch (n) {
314 case 0: return 0;
315 case 1: return 10;
316 case 2: return 19;
317 case 3: return 28;
318 case 4: return 36;
319 case 5: return 44;
320 case 6: return 52;
321 case 7: return 60;
322 case 8: return 67;
323 case 9: return 74;
324 case 10: return 81;
325 case 11: return 88;
326 case 12: return 95;
327 case 13: return 102;
328 case 14: return 109;
329 case 15: return 116;
330 case 16: return 122;
331 default: return 0;
332 }
333}
334
335/* Estimate how many bits it'll take to append single FDD UARFCN */
336static inline int append_utran_fdd_length(uint16_t u, const int *sc, size_t sc_len, size_t length)
337{
338 uint8_t chan_list[16] = { 0 };
339 int tmp[sc_len], f0;
340
341 memcpy(tmp, sc, sizeof(tmp));
342
343 f0 = f0_helper(tmp, length, chan_list);
344 if (f0 < 0)
345 return f0;
346
347 return 21 + range1024_p(length);
348}
349
350/* Append single FDD UARFCN */
351static inline int append_utran_fdd(struct bitvec *bv, uint16_t u, int *sc, size_t length)
352{
353 uint8_t chan_list[16] = { 0 };
354 int f0 = f0_helper(sc, length, chan_list);
355
356 if (f0 < 0)
357 return f0;
358
359 /* Repeated UTRAN FDD Neighbour Cells */
360 bitvec_set_bit(bv, 1);
361
362 /* FDD-ARFCN */
363 bitvec_set_bit(bv, 0);
364 bitvec_set_uint(bv, u, 14);
365
366 /* FDD_Indic0: parameter value '0000000000' is a member of the set? */
367 bitvec_set_bit(bv, f0);
368 /* NR_OF_FDD_CELLS */
369 bitvec_set_uint(bv, length, 5);
370
371 f0 = bv->cur_bit;
372 bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list);
373 bv->cur_bit = f0 + range1024_p(length);
374
375 return 21 + range1024_p(length);
376}
377
378static inline int try_adding_uarfcn(struct bitvec *bv, uint16_t *scramble_list,
379 size_t uarfcn_length, size_t *u_offset,
380 uint16_t uarfcn, uint8_t num_sc, uint8_t start_pos, uint8_t budget)
381{
382 int i, k, rc, a[uarfcn_length];
383
384 if (budget < 23)
385 return -ENOMEM;
386
387 /* copy corresponding Scrambling Codes: range encoder make in-place modifications */
388 for (i = start_pos, k = 0; i < num_sc; a[k++] = scramble_list[i++]);
389
390 /* estimate bit length requirements */
391 rc = append_utran_fdd_length(uarfcn, a, uarfcn_length, k);
392 if (rc < 0)
393 return rc; /* range encoder failure */
394
395 if (budget - rc <= 0)
396 return -ENOMEM; /* we have ran out of budget in current SI2q */
397
398 /* compute next offset */
399 *u_offset += k;
400
401 return budget - append_utran_fdd(bv, uarfcn, a, k);
402}
403
404/* Append multiple FDD UARFCNs */
405static inline void append_uarfcns(struct bitvec *bv, const uint16_t *uarfcn_list, size_t *u_offset,
406 size_t uarfcn_length, uint16_t *scramble_list, uint8_t budget)
407{
408 int i, rem = budget - 7, st = *u_offset; /* account for constant bits right away */
409 uint16_t cu = uarfcn_list[*u_offset]; /* caller ensures that length is positive */
410
411 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
412
413 if (budget <= 7)
414 return;
415
416 /* 3G Neighbour Cell Description */
417 bitvec_set_bit(bv, 1);
418 /* No Index_Start_3G */
419 bitvec_set_bit(bv, 0);
420 /* No Absolute_Index_Start_EMR */
421 bitvec_set_bit(bv, 0);
422
423 /* UTRAN FDD Description */
424 bitvec_set_bit(bv, 1);
425 /* No Bandwidth_FDD */
426 bitvec_set_bit(bv, 0);
427
428 for (i = *u_offset; i <= uarfcn_length; i++)
429 if (uarfcn_list[i] != cu) { /* we've reached new UARFCN */
430 rem = try_adding_uarfcn(bv, scramble_list, uarfcn_length, u_offset, cu, i, st, rem);
431 if (rem < 0)
432 break;
433
434 if (i < uarfcn_length) {
435 cu = uarfcn_list[i];
436 st = i;
Harald Welte65aabd42020-10-15 08:04:49 +0200437 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200438 break;
Harald Welte65aabd42020-10-15 08:04:49 +0200439 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200440 }
441
442 /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */
443 bitvec_set_bit(bv, 0);
444
445 /* UTRAN TDD Description */
446 bitvec_set_bit(bv, 0);
447}
448
449static size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e)
450{
451 unsigned i, ret = 0;
452
453 if (!e)
454 return 0;
455
456 for (i = 0; i < e->length; i++)
457 if (e->arfcn[i] != OSMO_EARFCN_INVALID)
458 ret++;
459
460 return ret;
461}
462
463/* generate SI2quater rest octets: 3GPP TS 44.018 § 10.5.2.33b */
Harald Welte428d03b2019-05-28 18:46:20 +0200464int osmo_gsm48_rest_octets_si2quater_encode(uint8_t *data, uint8_t si2q_index, uint8_t si2q_count,
465 const uint16_t *uarfcn_list, size_t *u_offset,
466 size_t uarfcn_length, uint16_t *scramble_list,
467 struct osmo_earfcn_si2q *si2quater_neigh_list,
468 size_t *e_offset)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200469{
470 int rc;
471 struct bitvec bv;
472
473 if (si2q_count < si2q_index)
474 return -EINVAL;
475
476 bv.data = data;
477 bv.data_len = 20;
478 bitvec_zero(&bv);
479
480 /* BA_IND: Set to '0' as that's what we use for SI2xxx type,
481 * whereas '1' is used for SI5xxx type messages. The point here
482 * is to be able to correlate whether a given MS measurement
483 * report was using the neighbor cells advertised in SI2 or in
484 * SI5, as those two could very well be different */
485 bitvec_set_bit(&bv, 0);
486 /* 3G_BA_IND */
487 bitvec_set_bit(&bv, 1);
488 /* MP_CHANGE_MARK */
489 bitvec_set_bit(&bv, 0);
490
491 /* SI2quater_INDEX */
492 bitvec_set_uint(&bv, si2q_index, 4);
493 /* SI2quater_COUNT */
494 bitvec_set_uint(&bv, si2q_count, 4);
495
496 /* No Measurement_Parameters Description */
497 bitvec_set_bit(&bv, 0);
498 /* No GPRS_Real Time Difference Description */
499 bitvec_set_bit(&bv, 0);
500 /* No GPRS_BSIC Description */
501 bitvec_set_bit(&bv, 0);
502 /* No GPRS_REPORT PRIORITY Description */
503 bitvec_set_bit(&bv, 0);
504 /* No GPRS_MEASUREMENT_Parameters Description */
505 bitvec_set_bit(&bv, 0);
506 /* No NC Measurement Parameters */
507 bitvec_set_bit(&bv, 0);
508 /* No extension (length) */
509 bitvec_set_bit(&bv, 0);
510
511 rc = SI2Q_MAX_LEN - (bv.cur_bit + 3);
512 if (rc > 0 && uarfcn_length - *u_offset > 0)
513 append_uarfcns(&bv, uarfcn_list, u_offset, uarfcn_length, scramble_list, rc);
514 else /* No 3G Neighbour Cell Description */
515 bitvec_set_bit(&bv, 0);
516
517 /* No 3G Measurement Parameters Description */
518 bitvec_set_bit(&bv, 0);
519 /* No GPRS_3G_MEASUREMENT Parameters Descr. */
520 bitvec_set_bit(&bv, 0);
521
522 rc = SI2Q_MAX_LEN - bv.cur_bit;
523 if (rc > 0 && si2q_earfcn_count(si2quater_neigh_list) - *e_offset > 0)
524 append_earfcn(&bv, si2quater_neigh_list, e_offset, rc);
525 else /* No Additions in Rel-5: */
526 bitvec_set_bit(&bv, L);
527
528 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
529 return bv.data_len;
530}
531
532/* Append selection parameters to bitvec */
533static void append_selection_params(struct bitvec *bv,
534 const struct osmo_gsm48_si_selection_params *sp)
535{
536 if (sp->present) {
537 bitvec_set_bit(bv, H);
538 bitvec_set_bit(bv, sp->cbq);
539 bitvec_set_uint(bv, sp->cell_resel_off, 6);
540 bitvec_set_uint(bv, sp->temp_offs, 3);
541 bitvec_set_uint(bv, sp->penalty_time, 5);
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
547/* Append power offset to bitvec */
548static void append_power_offset(struct bitvec *bv,
549 const struct osmo_gsm48_si_power_offset *po)
550{
551 if (po->present) {
552 bitvec_set_bit(bv, H);
553 bitvec_set_uint(bv, po->power_offset, 2);
Harald Welte65aabd42020-10-15 08:04:49 +0200554 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200555 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200556 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200557}
558
559/* Append GPRS indicator to bitvec */
560static void append_gprs_ind(struct bitvec *bv,
561 const struct osmo_gsm48_si3_gprs_ind *gi)
562{
563 if (gi->present) {
564 bitvec_set_bit(bv, H);
565 bitvec_set_uint(bv, gi->ra_colour, 3);
566 /* 0 == SI13 in BCCH Norm, 1 == SI13 sent on BCCH Ext */
567 bitvec_set_bit(bv, gi->si13_position);
Harald Welte65aabd42020-10-15 08:04:49 +0200568 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200569 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200570 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200571}
572
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200573/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
Harald Welte428d03b2019-05-28 18:46:20 +0200574int osmo_gsm48_rest_octets_si3_encode(uint8_t *data, const struct osmo_gsm48_si_ro_info *si3)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200575{
576 struct bitvec bv;
577
578 memset(&bv, 0, sizeof(bv));
579 bv.data = data;
580 bv.data_len = 4;
581
582 /* Optional Selection Parameters */
583 append_selection_params(&bv, &si3->selection_params);
584
585 /* Optional Power Offset */
586 append_power_offset(&bv, &si3->power_offset);
587
588 /* Do we have a SI2ter on the BCCH? */
589 if (si3->si2ter_indicator)
590 bitvec_set_bit(&bv, H);
591 else
592 bitvec_set_bit(&bv, L);
593
594 /* Early Classmark Sending Control */
595 if (si3->early_cm_ctrl)
596 bitvec_set_bit(&bv, H);
597 else
598 bitvec_set_bit(&bv, L);
599
600 /* Do we have a SI Type 9 on the BCCH? */
601 if (si3->scheduling.present) {
602 bitvec_set_bit(&bv, H);
603 bitvec_set_uint(&bv, si3->scheduling.where, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200604 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200605 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200606 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200607
608 /* GPRS Indicator */
609 append_gprs_ind(&bv, &si3->gprs_ind);
610
611 /* 3G Early Classmark Sending Restriction. If H, then controlled by
612 * early_cm_ctrl above */
613 if (si3->early_cm_restrict_3g)
Vadim Yanitskiyc9eab822020-05-05 02:03:29 +0700614 bitvec_set_bit(&bv, L);
Pau Espin Pedrol3f6a2822020-12-18 17:19:29 +0100615 else
616 bitvec_set_bit(&bv, H);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200617
618 if (si3->si2quater_indicator) {
619 bitvec_set_bit(&bv, H); /* indicator struct present */
620 bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */
621 }
622
623 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
624 return bv.data_len;
625}
626
627static int append_lsa_params(struct bitvec *bv,
628 const struct osmo_gsm48_lsa_params *lsa_params)
629{
630 /* FIXME */
631 return -1;
632}
633
634/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
Harald Welte428d03b2019-05-28 18:46:20 +0200635int 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 +0200636{
637 struct bitvec bv;
638
639 memset(&bv, 0, sizeof(bv));
640 bv.data = data;
641 bv.data_len = len;
642
643 /* SI4 Rest Octets O */
644 append_selection_params(&bv, &si4->selection_params);
645 append_power_offset(&bv, &si4->power_offset);
646 append_gprs_ind(&bv, &si4->gprs_ind);
647
648 if (0 /* FIXME */) {
649 /* H and SI4 Rest Octets S */
650 bitvec_set_bit(&bv, H);
651
652 /* LSA Parameters */
653 if (si4->lsa_params.present) {
654 bitvec_set_bit(&bv, H);
655 append_lsa_params(&bv, &si4->lsa_params);
Harald Welte65aabd42020-10-15 08:04:49 +0200656 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200657 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200658 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200659
660 /* Cell Identity */
661 if (1) {
662 bitvec_set_bit(&bv, H);
663 bitvec_set_uint(&bv, si4->cell_id, 16);
Harald Welte65aabd42020-10-15 08:04:49 +0200664 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200665 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200666 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200667
668 /* LSA ID Information */
669 if (0) {
670 bitvec_set_bit(&bv, H);
671 /* FIXME */
Harald Welte65aabd42020-10-15 08:04:49 +0200672 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200673 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200674 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200675 } else {
676 /* L and break indicator */
677 bitvec_set_bit(&bv, L);
678 bitvec_set_bit(&bv, si4->break_ind ? H : L);
679 }
680
681 return bv.data_len;
682}
683
684
685/* GSM 04.18 ETSI TS 101 503 V8.27.0 (2006-05)
686
687<SI6 rest octets> ::=
688{L | H <PCH and NCH info>}
689{L | H <VBS/VGCS options : bit(2)>}
690{ < DTM_support : bit == L > I < DTM_support : bit == H >
691< RAC : bit (8) >
692< MAX_LAPDm : bit (3) > }
693< Band indicator >
694{ L | H < GPRS_MS_TXPWR_MAX_CCH : bit (5) > }
695<implicit spare >;
696*/
Harald Welte86156de2019-05-28 19:49:47 +0200697int osmo_gsm48_rest_octets_si6_encode(uint8_t *data, const struct osmo_gsm48_si6_ro_info *in)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200698{
699 struct bitvec bv;
700
701 memset(&bv, 0, sizeof(bv));
702 bv.data = data;
703 bv.data_len = 1;
704
Harald Welte86156de2019-05-28 19:49:47 +0200705 if (in->pch_nch_info.present) {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200706 bitvec_set_bit(&bv, H);
Harald Welte86156de2019-05-28 19:49:47 +0200707 bitvec_set_bit(&bv, !!in->pch_nch_info.paging_channel_restructuring);
708 bitvec_set_uint(&bv, in->pch_nch_info.nln_sacch, 2);
709 if (in->pch_nch_info.call_priority_present) {
710 bitvec_set_bit(&bv, 1);
711 bitvec_set_uint(&bv, in->pch_nch_info.call_priority, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200712 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200713 bitvec_set_bit(&bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200714 }
Harald Welte86156de2019-05-28 19:49:47 +0200715 bitvec_set_bit(&bv, !!in->pch_nch_info.nln_status_sacch);
Harald Welte65aabd42020-10-15 08:04:49 +0200716 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200717 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200718 }
Harald Welte86156de2019-05-28 19:49:47 +0200719
720 if (in->vbs_vgcs_options.present) {
721 bitvec_set_bit(&bv, H);
722 bitvec_set_bit(&bv, !!in->vbs_vgcs_options.inband_notifications);
723 bitvec_set_bit(&bv, !!in->vbs_vgcs_options.inband_pagings);
Harald Welte65aabd42020-10-15 08:04:49 +0200724 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200725 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200726 }
Harald Welte86156de2019-05-28 19:49:47 +0200727
728 if (in->dtm_support.present) {
729 bitvec_set_bit(&bv, H);
730 bitvec_set_uint(&bv, in->dtm_support.rac, 8);
731 bitvec_set_uint(&bv, in->dtm_support.max_lapdm, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200732 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200733 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200734 }
Harald Welte86156de2019-05-28 19:49:47 +0200735
736 if (in->band_indicator_1900)
737 bitvec_set_bit(&bv, H);
738 else
739 bitvec_set_bit(&bv, L);
740
741 if (in->gprs_ms_txpwr_max_ccch.present) {
742 bitvec_set_bit(&bv, H);
743 bitvec_set_uint(&bv, in->gprs_ms_txpwr_max_ccch.max_txpwr, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200744 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200745 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200746 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200747
748 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
749 return bv.data_len;
750}
751
752/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
753 < GPRS Mobile Allocation IE > ::=
754 < HSN : bit (6) >
755 { 0 | 1 < RFL number list : < RFL number list struct > > }
756 { 0 < MA_LENGTH : bit (6) >
757 < MA_BITMAP: bit (val(MA_LENGTH) + 1) >
758 | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;
759
760 < RFL number list struct > :: =
761 < RFL_NUMBER : bit (4) >
762 { 0 | 1 < RFL number list struct > } ;
763 < ARFCN index list struct > ::=
764 < ARFCN_INDEX : bit(6) >
765 { 0 | 1 < ARFCN index list struct > } ;
766 */
767static int append_gprs_mobile_alloc(struct bitvec *bv)
768{
769 /* Hopping Sequence Number */
770 bitvec_set_uint(bv, 0, 6);
771
772 if (0) {
773 /* We want to use a RFL number list */
774 bitvec_set_bit(bv, 1);
775 /* FIXME: RFL number list */
Harald Welte65aabd42020-10-15 08:04:49 +0200776 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200777 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200778 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200779
780 if (0) {
781 /* We want to use a MA_BITMAP */
782 bitvec_set_bit(bv, 0);
783 /* FIXME: MA_LENGTH, MA_BITMAP, ... */
784 } else {
785 bitvec_set_bit(bv, 1);
786 if (0) {
787 /* We want to provide an ARFCN index list */
788 bitvec_set_bit(bv, 1);
789 /* FIXME */
Harald Welte65aabd42020-10-15 08:04:49 +0200790 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200791 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200792 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200793 }
794 return 0;
795}
796
797static int encode_t3192(unsigned int t3192)
798{
799 /* See also 3GPP TS 44.060
800 Table 12.24.2: GPRS Cell Options information element details */
801 if (t3192 == 0)
802 return 3;
803 else if (t3192 <= 80)
804 return 4;
805 else if (t3192 <= 120)
806 return 5;
807 else if (t3192 <= 160)
808 return 6;
809 else if (t3192 <= 200)
810 return 7;
811 else if (t3192 <= 500)
812 return 0;
813 else if (t3192 <= 1000)
814 return 1;
815 else if (t3192 <= 1500)
816 return 2;
817 else
818 return -EINVAL;
819}
820
821static int encode_drx_timer(unsigned int drx)
822{
823 if (drx == 0)
824 return 0;
825 else if (drx == 1)
826 return 1;
827 else if (drx == 2)
828 return 2;
829 else if (drx <= 4)
830 return 3;
831 else if (drx <= 8)
832 return 4;
833 else if (drx <= 16)
834 return 5;
835 else if (drx <= 32)
836 return 6;
837 else if (drx <= 64)
838 return 7;
839 else
840 return -EINVAL;
841}
842
843/* GPRS Cell Options as per TS 04.60 Chapter 12.24
844 < GPRS Cell Options IE > ::=
845 < NMO : bit(2) >
846 < T3168 : bit(3) >
847 < T3192 : bit(3) >
848 < DRX_TIMER_MAX: bit(3) >
849 < ACCESS_BURST_TYPE: bit >
850 < CONTROL_ACK_TYPE : bit >
851 < BS_CV_MAX: bit(4) >
852 { 0 | 1 < PAN_DEC : bit(3) >
853 < PAN_INC : bit(3) >
854 < PAN_MAX : bit(3) >
855 { 0 | 1 < Extension Length : bit(6) >
856 < bit (val(Extension Length) + 1
857 & { < Extension Information > ! { bit ** = <no string> } } ;
858 < Extension Information > ::=
859 { 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit >
860 < BEP_PERIOD : bit(4) > }
861 < PFC_FEATURE_MODE : bit >
862 < DTM_SUPPORT : bit >
863 <BSS_PAGING_COORDINATION: bit >
864 <spare bit > ** ;
865 */
866static int append_gprs_cell_opt(struct bitvec *bv,
867 const struct osmo_gprs_cell_options *gco)
868{
869 int t3192, drx_timer_max;
870
871 t3192 = encode_t3192(gco->t3192);
872 if (t3192 < 0)
873 return t3192;
874
875 drx_timer_max = encode_drx_timer(gco->drx_timer_max);
876 if (drx_timer_max < 0)
877 return drx_timer_max;
878
879 bitvec_set_uint(bv, gco->nmo, 2);
880
881 /* See also 3GPP TS 44.060
882 Table 12.24.2: GPRS Cell Options information element details */
883 bitvec_set_uint(bv, gco->t3168 / 500 - 1, 3);
884
885 bitvec_set_uint(bv, t3192, 3);
886 bitvec_set_uint(bv, drx_timer_max, 3);
887 /* ACCESS_BURST_TYPE: Hard-code 8bit */
888 bitvec_set_bit(bv, 0);
889 /* CONTROL_ACK_TYPE: */
890 bitvec_set_bit(bv, gco->ctrl_ack_type_use_block);
891 bitvec_set_uint(bv, gco->bs_cv_max, 4);
892
893 if (0) {
894 /* hard-code no PAN_{DEC,INC,MAX} */
895 bitvec_set_bit(bv, 0);
896 } else {
897 /* copied from ip.access BSC protocol trace */
898 bitvec_set_bit(bv, 1);
899 bitvec_set_uint(bv, 1, 3); /* DEC */
900 bitvec_set_uint(bv, 1, 3); /* INC */
901 bitvec_set_uint(bv, 15, 3); /* MAX */
902 }
903
904 if (!gco->ext_info_present) {
905 /* no extension information */
906 bitvec_set_bit(bv, 0);
907 } else {
908 /* extension information */
909 bitvec_set_bit(bv, 1);
Pau Espin Pedrolc31809f2021-02-09 19:29:28 +0100910 /* R99 extension: */
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200911 if (!gco->ext_info.egprs_supported) {
912 /* 6bit length of extension */
Pau Espin Pedrol5b6f1d72021-01-29 17:51:09 +0100913 bitvec_set_uint(bv, (1 + 5)-1, 6);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200914 /* EGPRS supported in the cell */
915 bitvec_set_bit(bv, 0);
916 } else {
917 /* 6bit length of extension */
Pau Espin Pedrol5b6f1d72021-01-29 17:51:09 +0100918 bitvec_set_uint(bv, (1 + 5 + 5)-1, 6);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200919 /* EGPRS supported in the cell */
920 bitvec_set_bit(bv, 1);
921
Pau Espin Pedrol30bf0e62020-12-14 17:13:47 +0100922 /* 1bit EGPRS PACKET CHANNEL REQUEST (inverted logic) */
923 bitvec_set_bit(bv, !gco->ext_info.use_egprs_p_ch_req);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200924
925 /* 4bit BEP PERIOD */
926 bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
927 }
928 bitvec_set_bit(bv, gco->ext_info.pfc_supported);
929 bitvec_set_bit(bv, gco->ext_info.dtm_supported);
930 bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
Pau Espin Pedrol946bb952020-12-14 17:04:54 +0100931
932 /* REL-4 extension: */
933 bitvec_set_bit(bv, gco->ext_info.ccn_active);
934 bitvec_set_bit(bv, 0); /* NW_EXT_UTBF disabled */
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200935 }
936
937 return 0;
938}
939
940static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
941 const struct osmo_gprs_power_ctrl_pars *pcp)
942{
943 bitvec_set_uint(bv, pcp->alpha, 4);
944 bitvec_set_uint(bv, pcp->t_avg_w, 5);
945 bitvec_set_uint(bv, pcp->t_avg_t, 5);
946 bitvec_set_uint(bv, pcp->pc_meas_chan, 1);
947 bitvec_set_uint(bv, pcp->n_avg_i, 4);
948}
949
950/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
Harald Welte428d03b2019-05-28 18:46:20 +0200951int osmo_gsm48_rest_octets_si13_encode(uint8_t *data, const struct osmo_gsm48_si13_info *si13)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200952{
953 struct bitvec bv;
954
955 memset(&bv, 0, sizeof(bv));
956 bv.data = data;
957 bv.data_len = 20;
958
959 if (0) {
960 /* No rest octets */
961 bitvec_set_bit(&bv, L);
962 } else {
963 bitvec_set_bit(&bv, H);
964 bitvec_set_uint(&bv, si13->bcch_change_mark, 3);
965 bitvec_set_uint(&bv, si13->si_change_field, 4);
966 if (1) {
967 bitvec_set_bit(&bv, 0);
968 } else {
969 bitvec_set_bit(&bv, 1);
970 bitvec_set_uint(&bv, si13->bcch_change_mark, 2);
971 append_gprs_mobile_alloc(&bv);
972 }
973 /* PBCCH not present in cell:
974 it shall never be indicated according to 3GPP TS 44.018 Table 10.5.2.37b.1 */
975 bitvec_set_bit(&bv, 0);
976 bitvec_set_uint(&bv, si13->rac, 8);
977 bitvec_set_bit(&bv, si13->spgc_ccch_sup);
978 bitvec_set_uint(&bv, si13->prio_acc_thr, 3);
979 bitvec_set_uint(&bv, si13->net_ctrl_ord, 2);
980 append_gprs_cell_opt(&bv, &si13->cell_opts);
981 append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);
982
983 /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
984 bitvec_set_bit(&bv, H); /* added Release 99 */
985 /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
986 * was only added in this Release */
987 bitvec_set_bit(&bv, 1);
988 }
989 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
990 return bv.data_len;
991}
Harald Weltef85b33f2019-05-28 17:56:21 +0200992
993
994/***********************************************************************
995 * Decoder
996 ***********************************************************************/
997
998/*! Decode SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72).
999 * \param[out] si3 decoded SI3 rest octets
1000 * \param[in] encoded SI3 rest octets, 4 octets long */
1001void osmo_gsm48_rest_octets_si3_decode(struct osmo_gsm48_si_ro_info *si3, const uint8_t *data)
1002{
1003 struct osmo_gsm48_si_selection_params *sp = &si3->selection_params;
1004 struct osmo_gsm48_si_power_offset *po = &si3->power_offset;
1005 struct osmo_gsm48_si3_gprs_ind *gi = &si3->gprs_ind;
1006 struct bitvec bv;
1007
1008 memset(&bv, 0, sizeof(bv));
1009 bv.data = (uint8_t *) data;
1010 bv.data_len = 4;
1011
1012 memset(si3, 0, sizeof(*si3));
1013
Vadim Yanitskiy74474cf2019-07-17 16:40:11 +07001014 /* Optional Selection Parameters */
Harald Weltef85b33f2019-05-28 17:56:21 +02001015 if (bitvec_get_bit_high(&bv) == H) {
1016 sp->present = 1;
1017 sp->cbq = bitvec_get_uint(&bv, 1);
1018 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
1019 sp->temp_offs = bitvec_get_uint(&bv, 3);
1020 sp->penalty_time = bitvec_get_uint(&bv, 5);
Harald Welte65aabd42020-10-15 08:04:49 +02001021 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001022 sp->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001023 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001024
1025 /* Optional Power Offset */
1026 if (bitvec_get_bit_high(&bv) == H) {
1027 po->present = 1;
1028 po->power_offset = bitvec_get_uint(&bv, 2);
Harald Welte65aabd42020-10-15 08:04:49 +02001029 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001030 po->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001031 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001032
1033 /* System Information 2ter Indicator */
1034 if (bitvec_get_bit_high(&bv) == H)
1035 si3->si2ter_indicator = 1;
1036 else
1037 si3->si2ter_indicator = 0;
1038
1039 /* Early Classmark Sending Control */
1040 if (bitvec_get_bit_high(&bv) == H)
1041 si3->early_cm_ctrl = 1;
1042 else
1043 si3->early_cm_ctrl = 0;
1044
1045 /* Scheduling if and where */
1046 if (bitvec_get_bit_high(&bv) == H) {
1047 si3->scheduling.present = 1;
1048 si3->scheduling.where = bitvec_get_uint(&bv, 3);
Harald Welte65aabd42020-10-15 08:04:49 +02001049 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001050 si3->scheduling.present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001051 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001052
1053 /* GPRS Indicator */
1054 if (bitvec_get_bit_high(&bv) == H) {
1055 gi->present = 1;
1056 gi->ra_colour = bitvec_get_uint(&bv, 3);
1057 gi->si13_position = bitvec_get_uint(&bv, 1);
Harald Welte65aabd42020-10-15 08:04:49 +02001058 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001059 gi->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001060 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001061
1062 /* 3G Early Classmark Sending Restriction. If H, then controlled by
1063 * early_cm_ctrl above */
1064 if (bitvec_get_bit_high(&bv) == H)
Harald Weltef85b33f2019-05-28 17:56:21 +02001065 si3->early_cm_restrict_3g = 0;
Pau Espin Pedrold01163a2020-12-21 13:03:32 +01001066 else
1067 si3->early_cm_restrict_3g = 1;
Harald Weltef85b33f2019-05-28 17:56:21 +02001068
1069 if (bitvec_get_bit_high(&bv) == H)
1070 si3->si2quater_indicator = 1;
1071 else
1072 si3->si2quater_indicator = 0;
1073}
Harald Welte5e1cd5e2020-10-11 20:04:04 +02001074
1075
1076void osmo_gsm48_rest_octets_si4_decode(struct osmo_gsm48_si_ro_info *si4, const uint8_t *data, int len)
1077{
1078 struct osmo_gsm48_si_selection_params *sp = &si4->selection_params;
1079 struct osmo_gsm48_si_power_offset *po = &si4->power_offset;
1080 struct osmo_gsm48_si3_gprs_ind *gi = &si4->gprs_ind;
1081 struct bitvec bv;
1082
1083 memset(&bv, 0, sizeof(bv));
1084 bv.data = (uint8_t *) data;
1085 bv.data_len = len;
1086
1087 memset(si4, 0, sizeof(*si4));
1088
1089 /* Optional Selection Parameters */
1090 if (bitvec_get_bit_high(&bv) == H) {
1091 sp->present = 1;
1092 sp->cbq = bitvec_get_uint(&bv, 1);
1093 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
1094 sp->temp_offs = bitvec_get_uint(&bv, 3);
1095 sp->penalty_time = bitvec_get_uint(&bv, 5);
1096 } else {
1097 sp->present = 0;
1098 }
1099
1100 /* Optional Power Offset */
1101 if (bitvec_get_bit_high(&bv) == H) {
1102 po->present = 1;
1103 po->power_offset = bitvec_get_uint(&bv, 2);
1104 } else {
1105 po->present = 0;
1106 }
1107
1108 /* GPRS Indicator */
1109 if (bitvec_get_bit_high(&bv) == H) {
1110 gi->present = 1;
1111 gi->ra_colour = bitvec_get_uint(&bv, 3);
1112 gi->si13_position = bitvec_get_uint(&bv, 1);
1113 } else {
1114 gi->present = 0;
1115 }
1116}