blob: 77fd349b09924456f9a963f4d9b76648ffa02a1c [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
Pau Espin Pedrold7a209b2021-02-09 18:28:25 +0100752
753static unsigned int decode_t3192(unsigned int t3192)
754{
755 /* See also 3GPP TS 44.060
756 Table 12.24.2: GPRS Cell Options information element details */
757 static const unsigned int decode_t3192_tbl[8] = {500, 1000, 1500, 0, 80, 120, 160, 200};
758 OSMO_ASSERT(t3192 <= 7);
759 return decode_t3192_tbl[t3192];
760}
761
762static unsigned int decode_drx_timer(unsigned int drx)
763{
764 static const unsigned int decode_drx_timer_tbl[8] = {0, 1, 2, 4, 8, 16, 32, 64};
765 OSMO_ASSERT(drx <= 7);
766 return decode_drx_timer_tbl[drx];
767}
768
769static int decode_gprs_cell_opt(struct osmo_gprs_cell_options *gco, struct bitvec *bv)
770{
771 gco->nmo = bitvec_get_uint(bv, 2);
772 gco->t3168 = (bitvec_get_uint(bv, 3) + 1) * 500;
773 gco->t3192 = decode_t3192(bitvec_get_uint(bv, 3));
774 gco->drx_timer_max = decode_drx_timer(bitvec_get_uint(bv, 3));
775
776 /* ACCESS_BURST_TYPE: */
777 bitvec_get_uint(bv, 1);
778 /* CONTROL_ACK_TYPE: */
779 gco->ctrl_ack_type_use_block = bitvec_get_uint(bv, 1);
780 gco->bs_cv_max = bitvec_get_uint(bv, 4);
781
782 if (bitvec_get_uint(bv, 1)) {
783 bitvec_get_uint(bv, 3); /* DEC */
784 bitvec_get_uint(bv, 3); /* INC */
785 bitvec_get_uint(bv, 3); /* MAX */
786 }
787
788 if (bitvec_get_uint(bv, 1)) {
789 int ext_len = bitvec_get_uint(bv, 6);
790 if (ext_len < 0)
791 return ext_len;
792 unsigned int cur_bit = bv->cur_bit;
793 /* Extension Information */
794 /* R99 extension: */
795 gco->ext_info.egprs_supported = bitvec_get_uint(bv, 1);
796 if (gco->ext_info.egprs_supported) {
797 gco->ext_info.use_egprs_p_ch_req = !bitvec_get_uint(bv, 1);
798 gco->ext_info.bep_period = bitvec_get_uint(bv, 4);
799 }
800 gco->ext_info.pfc_supported = bitvec_get_uint(bv, 1);
801 gco->ext_info.dtm_supported = bitvec_get_uint(bv, 1);
802 gco->ext_info.bss_paging_coordination = bitvec_get_uint(bv, 1);
803 /* REL-4 extension: */
804 gco->ext_info.ccn_active = bitvec_get_uint(bv, 1);
805 bitvec_get_uint(bv, 1); /* NW_EXT_UTBF */
806 bv->cur_bit = cur_bit + ext_len + 1;
807 }
808 return 0;
809}
810
811static void decode_gprs_pwr_ctrl_pars(struct osmo_gprs_power_ctrl_pars *pcp, struct bitvec *bv)
812{
813 pcp->alpha = bitvec_get_uint(bv, 4);
814 pcp->t_avg_w = bitvec_get_uint(bv,5);
815 pcp->t_avg_t = bitvec_get_uint(bv, 5);
816 pcp->pc_meas_chan = bitvec_get_uint(bv, 1);
817 pcp->n_avg_i = bitvec_get_uint(bv, 4);
818}
819
820/*! Decode SI13 Rest Octests (04.08 Chapter 10.5.2.37b).
821 * \param[out] si13 decoded SI13 rest octets
822 * \param[in] encoded SI13 rest octets
823 * \returns parsed bits on success, negative on error */
824int osmo_gsm48_rest_octets_si13_decode(struct osmo_gsm48_si13_info *si13, const uint8_t *data)
825{
826 struct osmo_gprs_cell_options *co = &si13->cell_opts;
827 struct osmo_gprs_power_ctrl_pars *pcp = &si13->pwr_ctrl_pars;
828 struct bitvec bv;
829 int rc;
830
831 memset(&bv, 0, sizeof(bv));
832 bv.data = (uint8_t *) data;
833 bv.data_len = 20;
834
835 memset(si13, 0, sizeof(*si13));
836
837
838 if (bitvec_get_bit_high(&bv) == H) {
839 si13->bcch_change_mark = bitvec_get_uint(&bv, 3);
840 si13->si_change_field = bitvec_get_uint(&bv, 4);
841 if (bitvec_get_uint(&bv, 1)) {
842 si13->bcch_change_mark = bitvec_get_uint(&bv, 2);
843 /* FIXME: implement parsing GPRS Mobile Allocation IE */
844 return -ENOTSUP;
845 }
846 if (bitvec_get_uint(&bv, 1)) {
847 /* PBCCH present in cell */
848 /* FIXME: parse not implemented */
849 return -ENOTSUP;
850 } else {
851 /* PBCCH not present in cell */
852 si13->rac = bitvec_get_uint(&bv, 8);
853 si13->spgc_ccch_sup = bitvec_get_uint(&bv, 1);
854 si13->prio_acc_thr = bitvec_get_uint(&bv, 3);
855 si13->net_ctrl_ord = bitvec_get_uint(&bv, 2);
856 if ((rc = decode_gprs_cell_opt(co, &bv)) < 0)
857 return rc;
858
859 decode_gprs_pwr_ctrl_pars(pcp, &bv);
860 }
861 }
862 return bv.cur_bit;
863}
864
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200865/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
866 < GPRS Mobile Allocation IE > ::=
867 < HSN : bit (6) >
868 { 0 | 1 < RFL number list : < RFL number list struct > > }
869 { 0 < MA_LENGTH : bit (6) >
870 < MA_BITMAP: bit (val(MA_LENGTH) + 1) >
871 | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;
872
873 < RFL number list struct > :: =
874 < RFL_NUMBER : bit (4) >
875 { 0 | 1 < RFL number list struct > } ;
876 < ARFCN index list struct > ::=
877 < ARFCN_INDEX : bit(6) >
878 { 0 | 1 < ARFCN index list struct > } ;
879 */
880static int append_gprs_mobile_alloc(struct bitvec *bv)
881{
882 /* Hopping Sequence Number */
883 bitvec_set_uint(bv, 0, 6);
884
885 if (0) {
886 /* We want to use a RFL number list */
887 bitvec_set_bit(bv, 1);
888 /* FIXME: RFL number list */
Harald Welte65aabd42020-10-15 08:04:49 +0200889 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200890 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200891 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200892
893 if (0) {
894 /* We want to use a MA_BITMAP */
895 bitvec_set_bit(bv, 0);
896 /* FIXME: MA_LENGTH, MA_BITMAP, ... */
897 } else {
898 bitvec_set_bit(bv, 1);
899 if (0) {
900 /* We want to provide an ARFCN index list */
901 bitvec_set_bit(bv, 1);
902 /* FIXME */
Harald Welte65aabd42020-10-15 08:04:49 +0200903 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200904 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200905 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200906 }
907 return 0;
908}
909
910static int encode_t3192(unsigned int t3192)
911{
912 /* See also 3GPP TS 44.060
913 Table 12.24.2: GPRS Cell Options information element details */
914 if (t3192 == 0)
915 return 3;
916 else if (t3192 <= 80)
917 return 4;
918 else if (t3192 <= 120)
919 return 5;
920 else if (t3192 <= 160)
921 return 6;
922 else if (t3192 <= 200)
923 return 7;
924 else if (t3192 <= 500)
925 return 0;
926 else if (t3192 <= 1000)
927 return 1;
928 else if (t3192 <= 1500)
929 return 2;
930 else
931 return -EINVAL;
932}
933
934static int encode_drx_timer(unsigned int drx)
935{
936 if (drx == 0)
937 return 0;
938 else if (drx == 1)
939 return 1;
940 else if (drx == 2)
941 return 2;
942 else if (drx <= 4)
943 return 3;
944 else if (drx <= 8)
945 return 4;
946 else if (drx <= 16)
947 return 5;
948 else if (drx <= 32)
949 return 6;
950 else if (drx <= 64)
951 return 7;
952 else
953 return -EINVAL;
954}
955
956/* GPRS Cell Options as per TS 04.60 Chapter 12.24
957 < GPRS Cell Options IE > ::=
958 < NMO : bit(2) >
959 < T3168 : bit(3) >
960 < T3192 : bit(3) >
961 < DRX_TIMER_MAX: bit(3) >
962 < ACCESS_BURST_TYPE: bit >
963 < CONTROL_ACK_TYPE : bit >
964 < BS_CV_MAX: bit(4) >
965 { 0 | 1 < PAN_DEC : bit(3) >
966 < PAN_INC : bit(3) >
967 < PAN_MAX : bit(3) >
968 { 0 | 1 < Extension Length : bit(6) >
969 < bit (val(Extension Length) + 1
970 & { < Extension Information > ! { bit ** = <no string> } } ;
971 < Extension Information > ::=
972 { 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit >
973 < BEP_PERIOD : bit(4) > }
974 < PFC_FEATURE_MODE : bit >
975 < DTM_SUPPORT : bit >
976 <BSS_PAGING_COORDINATION: bit >
977 <spare bit > ** ;
978 */
979static int append_gprs_cell_opt(struct bitvec *bv,
980 const struct osmo_gprs_cell_options *gco)
981{
982 int t3192, drx_timer_max;
983
984 t3192 = encode_t3192(gco->t3192);
985 if (t3192 < 0)
986 return t3192;
987
988 drx_timer_max = encode_drx_timer(gco->drx_timer_max);
989 if (drx_timer_max < 0)
990 return drx_timer_max;
991
992 bitvec_set_uint(bv, gco->nmo, 2);
993
994 /* See also 3GPP TS 44.060
995 Table 12.24.2: GPRS Cell Options information element details */
996 bitvec_set_uint(bv, gco->t3168 / 500 - 1, 3);
997
998 bitvec_set_uint(bv, t3192, 3);
999 bitvec_set_uint(bv, drx_timer_max, 3);
1000 /* ACCESS_BURST_TYPE: Hard-code 8bit */
1001 bitvec_set_bit(bv, 0);
1002 /* CONTROL_ACK_TYPE: */
1003 bitvec_set_bit(bv, gco->ctrl_ack_type_use_block);
1004 bitvec_set_uint(bv, gco->bs_cv_max, 4);
1005
1006 if (0) {
1007 /* hard-code no PAN_{DEC,INC,MAX} */
1008 bitvec_set_bit(bv, 0);
1009 } else {
1010 /* copied from ip.access BSC protocol trace */
1011 bitvec_set_bit(bv, 1);
1012 bitvec_set_uint(bv, 1, 3); /* DEC */
1013 bitvec_set_uint(bv, 1, 3); /* INC */
1014 bitvec_set_uint(bv, 15, 3); /* MAX */
1015 }
1016
1017 if (!gco->ext_info_present) {
1018 /* no extension information */
1019 bitvec_set_bit(bv, 0);
1020 } else {
1021 /* extension information */
1022 bitvec_set_bit(bv, 1);
Pau Espin Pedrolc31809f2021-02-09 19:29:28 +01001023 /* R99 extension: */
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001024 if (!gco->ext_info.egprs_supported) {
1025 /* 6bit length of extension */
Pau Espin Pedrol5b6f1d72021-01-29 17:51:09 +01001026 bitvec_set_uint(bv, (1 + 5)-1, 6);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001027 /* EGPRS supported in the cell */
1028 bitvec_set_bit(bv, 0);
1029 } else {
1030 /* 6bit length of extension */
Pau Espin Pedrol5b6f1d72021-01-29 17:51:09 +01001031 bitvec_set_uint(bv, (1 + 5 + 5)-1, 6);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001032 /* EGPRS supported in the cell */
1033 bitvec_set_bit(bv, 1);
1034
Pau Espin Pedrol30bf0e62020-12-14 17:13:47 +01001035 /* 1bit EGPRS PACKET CHANNEL REQUEST (inverted logic) */
1036 bitvec_set_bit(bv, !gco->ext_info.use_egprs_p_ch_req);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001037
1038 /* 4bit BEP PERIOD */
1039 bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
1040 }
1041 bitvec_set_bit(bv, gco->ext_info.pfc_supported);
1042 bitvec_set_bit(bv, gco->ext_info.dtm_supported);
1043 bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
Pau Espin Pedrol946bb952020-12-14 17:04:54 +01001044
1045 /* REL-4 extension: */
1046 bitvec_set_bit(bv, gco->ext_info.ccn_active);
1047 bitvec_set_bit(bv, 0); /* NW_EXT_UTBF disabled */
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001048 }
1049
1050 return 0;
1051}
1052
1053static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
1054 const struct osmo_gprs_power_ctrl_pars *pcp)
1055{
1056 bitvec_set_uint(bv, pcp->alpha, 4);
1057 bitvec_set_uint(bv, pcp->t_avg_w, 5);
1058 bitvec_set_uint(bv, pcp->t_avg_t, 5);
1059 bitvec_set_uint(bv, pcp->pc_meas_chan, 1);
1060 bitvec_set_uint(bv, pcp->n_avg_i, 4);
1061}
1062
1063/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
Harald Welte428d03b2019-05-28 18:46:20 +02001064int osmo_gsm48_rest_octets_si13_encode(uint8_t *data, const struct osmo_gsm48_si13_info *si13)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001065{
1066 struct bitvec bv;
1067
1068 memset(&bv, 0, sizeof(bv));
1069 bv.data = data;
1070 bv.data_len = 20;
1071
1072 if (0) {
1073 /* No rest octets */
1074 bitvec_set_bit(&bv, L);
1075 } else {
1076 bitvec_set_bit(&bv, H);
1077 bitvec_set_uint(&bv, si13->bcch_change_mark, 3);
1078 bitvec_set_uint(&bv, si13->si_change_field, 4);
1079 if (1) {
1080 bitvec_set_bit(&bv, 0);
1081 } else {
1082 bitvec_set_bit(&bv, 1);
1083 bitvec_set_uint(&bv, si13->bcch_change_mark, 2);
1084 append_gprs_mobile_alloc(&bv);
1085 }
1086 /* PBCCH not present in cell:
1087 it shall never be indicated according to 3GPP TS 44.018 Table 10.5.2.37b.1 */
1088 bitvec_set_bit(&bv, 0);
1089 bitvec_set_uint(&bv, si13->rac, 8);
1090 bitvec_set_bit(&bv, si13->spgc_ccch_sup);
1091 bitvec_set_uint(&bv, si13->prio_acc_thr, 3);
1092 bitvec_set_uint(&bv, si13->net_ctrl_ord, 2);
1093 append_gprs_cell_opt(&bv, &si13->cell_opts);
1094 append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);
1095
1096 /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
1097 bitvec_set_bit(&bv, H); /* added Release 99 */
1098 /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
1099 * was only added in this Release */
1100 bitvec_set_bit(&bv, 1);
1101 }
1102 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
1103 return bv.data_len;
1104}
Harald Weltef85b33f2019-05-28 17:56:21 +02001105
1106
1107/***********************************************************************
1108 * Decoder
1109 ***********************************************************************/
1110
1111/*! Decode SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72).
1112 * \param[out] si3 decoded SI3 rest octets
1113 * \param[in] encoded SI3 rest octets, 4 octets long */
1114void osmo_gsm48_rest_octets_si3_decode(struct osmo_gsm48_si_ro_info *si3, const uint8_t *data)
1115{
1116 struct osmo_gsm48_si_selection_params *sp = &si3->selection_params;
1117 struct osmo_gsm48_si_power_offset *po = &si3->power_offset;
1118 struct osmo_gsm48_si3_gprs_ind *gi = &si3->gprs_ind;
1119 struct bitvec bv;
1120
1121 memset(&bv, 0, sizeof(bv));
1122 bv.data = (uint8_t *) data;
1123 bv.data_len = 4;
1124
1125 memset(si3, 0, sizeof(*si3));
1126
Vadim Yanitskiy74474cf2019-07-17 16:40:11 +07001127 /* Optional Selection Parameters */
Harald Weltef85b33f2019-05-28 17:56:21 +02001128 if (bitvec_get_bit_high(&bv) == H) {
1129 sp->present = 1;
1130 sp->cbq = bitvec_get_uint(&bv, 1);
1131 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
1132 sp->temp_offs = bitvec_get_uint(&bv, 3);
1133 sp->penalty_time = bitvec_get_uint(&bv, 5);
Harald Welte65aabd42020-10-15 08:04:49 +02001134 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001135 sp->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001136 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001137
1138 /* Optional Power Offset */
1139 if (bitvec_get_bit_high(&bv) == H) {
1140 po->present = 1;
1141 po->power_offset = bitvec_get_uint(&bv, 2);
Harald Welte65aabd42020-10-15 08:04:49 +02001142 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001143 po->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001144 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001145
1146 /* System Information 2ter Indicator */
1147 if (bitvec_get_bit_high(&bv) == H)
1148 si3->si2ter_indicator = 1;
1149 else
1150 si3->si2ter_indicator = 0;
1151
1152 /* Early Classmark Sending Control */
1153 if (bitvec_get_bit_high(&bv) == H)
1154 si3->early_cm_ctrl = 1;
1155 else
1156 si3->early_cm_ctrl = 0;
1157
1158 /* Scheduling if and where */
1159 if (bitvec_get_bit_high(&bv) == H) {
1160 si3->scheduling.present = 1;
1161 si3->scheduling.where = bitvec_get_uint(&bv, 3);
Harald Welte65aabd42020-10-15 08:04:49 +02001162 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001163 si3->scheduling.present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001164 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001165
1166 /* GPRS Indicator */
1167 if (bitvec_get_bit_high(&bv) == H) {
1168 gi->present = 1;
1169 gi->ra_colour = bitvec_get_uint(&bv, 3);
1170 gi->si13_position = bitvec_get_uint(&bv, 1);
Harald Welte65aabd42020-10-15 08:04:49 +02001171 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001172 gi->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001173 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001174
1175 /* 3G Early Classmark Sending Restriction. If H, then controlled by
1176 * early_cm_ctrl above */
1177 if (bitvec_get_bit_high(&bv) == H)
Harald Weltef85b33f2019-05-28 17:56:21 +02001178 si3->early_cm_restrict_3g = 0;
Pau Espin Pedrold01163a2020-12-21 13:03:32 +01001179 else
1180 si3->early_cm_restrict_3g = 1;
Harald Weltef85b33f2019-05-28 17:56:21 +02001181
1182 if (bitvec_get_bit_high(&bv) == H)
1183 si3->si2quater_indicator = 1;
1184 else
1185 si3->si2quater_indicator = 0;
1186}
Harald Welte5e1cd5e2020-10-11 20:04:04 +02001187
1188
1189void osmo_gsm48_rest_octets_si4_decode(struct osmo_gsm48_si_ro_info *si4, const uint8_t *data, int len)
1190{
1191 struct osmo_gsm48_si_selection_params *sp = &si4->selection_params;
1192 struct osmo_gsm48_si_power_offset *po = &si4->power_offset;
1193 struct osmo_gsm48_si3_gprs_ind *gi = &si4->gprs_ind;
1194 struct bitvec bv;
1195
1196 memset(&bv, 0, sizeof(bv));
1197 bv.data = (uint8_t *) data;
1198 bv.data_len = len;
1199
1200 memset(si4, 0, sizeof(*si4));
1201
1202 /* Optional Selection Parameters */
1203 if (bitvec_get_bit_high(&bv) == H) {
1204 sp->present = 1;
1205 sp->cbq = bitvec_get_uint(&bv, 1);
1206 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
1207 sp->temp_offs = bitvec_get_uint(&bv, 3);
1208 sp->penalty_time = bitvec_get_uint(&bv, 5);
1209 } else {
1210 sp->present = 0;
1211 }
1212
1213 /* Optional Power Offset */
1214 if (bitvec_get_bit_high(&bv) == H) {
1215 po->present = 1;
1216 po->power_offset = bitvec_get_uint(&bv, 2);
1217 } else {
1218 po->present = 0;
1219 }
1220
1221 /* GPRS Indicator */
1222 if (bitvec_get_bit_high(&bv) == H) {
1223 gi->present = 1;
1224 gi->ra_colour = bitvec_get_uint(&bv, 3);
1225 gi->si13_position = bitvec_get_uint(&bv, 1);
1226 } else {
1227 gi->present = 0;
1228 }
1229}