blob: 57c2c99afe5e704f64a676aa892b4197b9419bff [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
Harald Welte11926872023-05-08 06:22:21 +020062struct nch_pos {
63 uint8_t num_blocks;
64 uint8_t first_block;
65};
66
67/* 3GPP TS 44.010 Table 10.5.2.32.1b */
68static const struct nch_pos si1ro_nch_positions[] = {
69 [0x00] = {1, 0},
70 [0x01] = {1, 1},
71 [0x02] = {1, 2},
72 [0x03] = {1, 3},
73 [0x04] = {1, 4},
74 [0x05] = {1, 5},
75 [0x06] = {1, 6},
76
77 [0x07] = {2, 0},
78 [0x08] = {2, 1},
Eric9864efc2023-06-03 16:28:37 +020079 [0x09] = {2, 2},
Harald Welte11926872023-05-08 06:22:21 +020080 [0x0a] = {2, 3},
81 [0x0b] = {2, 4},
82 [0x0c] = {2, 5},
83
84 [0x0d] = {3, 0},
85 [0x0e] = {3, 1},
86 [0x0f] = {3, 2},
87 [0x10] = {3, 3},
88 [0x11] = {3, 4},
89
90 [0x12] = {4, 0},
91 [0x13] = {4, 1},
92 [0x14] = {4, 2},
93 [0x15] = {4, 3},
94
95 [0x16] = {5, 0},
96 [0x17] = {5, 1},
97 [0x18] = {5, 2},
98
99 [0x19] = {6, 0},
100 [0x1a] = {6, 1},
101
102 [0x1b] = {7, 0},
103};
104
105/*! Decode the 5-bit 'NCH position' field within SI1 Rest Octets.
106 * \param[in] value 5-bit value from SI1 rest octets
107 * \param[out] num_blocks Number of CCCH used for NCH
108 * \param[out] first_block First CCCH block used for NCH
109 * \returns 0 on success; negative in case of error */
110int osmo_gsm48_si1ro_nch_pos_decode(uint8_t value, uint8_t *num_blocks, uint8_t *first_block)
111{
112 if (value >= ARRAY_SIZE(si1ro_nch_positions))
113 return -EINVAL;
114
115 *num_blocks = si1ro_nch_positions[value].num_blocks;
116 *first_block = si1ro_nch_positions[value].first_block;
117
118 return 0;
119}
120
121/*! Encode the 5-bit 'NCH position' field within SI1 Rest Octets.
122 * \param[in] num_blocks Number of CCCH used for NCH
123 * \param[in] first_block First CCCH block used for NCH
124 * \returns 5-bit value for SI1 rest octets on success; negative in case of error */
125int osmo_gsm48_si1ro_nch_pos_encode(uint8_t num_blocks, uint8_t first_block)
126{
127 unsigned int i;
128
129 for (i = 0; i < ARRAY_SIZE(si1ro_nch_positions); i++) {
130 if (si1ro_nch_positions[i].num_blocks == num_blocks &&
131 si1ro_nch_positions[i].first_block == first_block) {
132 return i;
133 }
134 }
135 return -EINVAL;
136}
137
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200138/* Append Repeated E-UTRAN Neighbour Cell to bitvec: see 3GPP TS 44.018 Table 10.5.2.33b.1 */
139static inline bool append_eutran_neib_cell(struct bitvec *bv, const struct osmo_earfcn_si2q *e, size_t *e_offset,
140 uint8_t budget)
141{
142 unsigned i, skip = 0;
Pau Espin Pedrol0f619de2020-12-14 17:58:00 +0100143 size_t offset = *e_offset;
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200144 int16_t rem = budget - 6; /* account for mandatory stop bit and THRESH_E-UTRAN_high */
145 uint8_t earfcn_budget;
146
147 if (budget <= 6)
148 return false;
149
150 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
151
152 /* first we have to properly adjust budget requirements */
153 if (e->prio_valid) /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
154 rem -= 4;
155 else
156 rem--;
157
158 if (e->thresh_lo_valid) /* THRESH_E-UTRAN_low: */
159 rem -= 6;
160 else
161 rem--;
162
163 if (e->qrxlm_valid) /* E-UTRAN_QRXLEVMIN: */
164 rem -= 6;
165 else
166 rem--;
167
168 if (rem < 0)
169 return false;
170
171 /* now we can proceed with actually adding EARFCNs within adjusted budget limit */
172 for (i = 0; i < e->length; i++) {
173 if (e->arfcn[i] != OSMO_EARFCN_INVALID) {
Pau Espin Pedrol0f619de2020-12-14 17:58:00 +0100174 if (skip < offset) {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200175 skip++; /* ignore EARFCNs added on previous calls */
176 } else {
177 earfcn_budget = 17; /* compute budget per-EARFCN */
178 if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
179 earfcn_budget++;
180 else
181 earfcn_budget += 4;
182
183 if (rem - earfcn_budget < 0)
184 break;
185 else {
186 (*e_offset)++;
187 rem -= earfcn_budget;
188
189 if (rem < 0)
190 return false;
191
192 bitvec_set_bit(bv, 1); /* EARFCN: */
193 bitvec_set_uint(bv, e->arfcn[i], 16);
194
195 if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
196 bitvec_set_bit(bv, 0);
197 else { /* Measurement Bandwidth: 9.1.54 */
198 bitvec_set_bit(bv, 1);
199 bitvec_set_uint(bv, e->meas_bw[i], 3);
200 }
201 }
202 }
203 }
204 }
205
206 /* stop bit - end of EARFCN + Measurement Bandwidth sequence */
207 bitvec_set_bit(bv, 0);
208
209 /* Note: we don't support different EARFCN arrays each with different priority, threshold etc. */
210
211 if (e->prio_valid) {
212 /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
213 bitvec_set_bit(bv, 1);
214 bitvec_set_uint(bv, e->prio, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200215 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200216 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200217 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200218
219 /* THRESH_E-UTRAN_high */
220 bitvec_set_uint(bv, e->thresh_hi, 5);
221
222 if (e->thresh_lo_valid) {
223 /* THRESH_E-UTRAN_low: */
224 bitvec_set_bit(bv, 1);
225 bitvec_set_uint(bv, e->thresh_lo, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200226 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200227 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200228 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200229
230 if (e->qrxlm_valid) {
231 /* E-UTRAN_QRXLEVMIN: */
232 bitvec_set_bit(bv, 1);
233 bitvec_set_uint(bv, e->qrxlm, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200234 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200235 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200236 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200237
238 return true;
239}
240
241static inline void append_earfcn(struct bitvec *bv, const struct osmo_earfcn_si2q *e, size_t *e_offset, uint8_t budget)
242{
243 bool appended;
244 unsigned int old = bv->cur_bit; /* save current position to make rollback possible */
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100245 int rem = ((int)budget) - 40;
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200246 if (rem <= 0)
247 return;
248
249 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
250
251 /* Additions in Rel-5: */
252 bitvec_set_bit(bv, H);
253 /* No 3G Additional Measurement Param. Descr. */
254 bitvec_set_bit(bv, 0);
255 /* No 3G ADDITIONAL MEASUREMENT Param. Descr. 2 */
256 bitvec_set_bit(bv, 0);
257 /* Additions in Rel-6: */
258 bitvec_set_bit(bv, H);
259 /* 3G_CCN_ACTIVE */
260 bitvec_set_bit(bv, 0);
261 /* Additions in Rel-7: */
262 bitvec_set_bit(bv, H);
263 /* No 700_REPORTING_OFFSET */
264 bitvec_set_bit(bv, 0);
265 /* No 810_REPORTING_OFFSET */
266 bitvec_set_bit(bv, 0);
267 /* Additions in Rel-8: */
268 bitvec_set_bit(bv, H);
269
270 /* Priority and E-UTRAN Parameters Description */
271 bitvec_set_bit(bv, 1);
272
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100273 /* budget: 10 bits used above */
274
Pau Espin Pedrol908224c2020-12-14 17:11:19 +0100275 /* Serving Cell Priority Parameters Descr. is Present,
276 * see also: 3GPP TS 44.018, Table 10.5.2.33b.1 */
277 bitvec_set_bit(bv, 1);
278
279 /* GERAN_PRIORITY */
280 bitvec_set_uint(bv, 0, 3);
281
282 /* THRESH_Priority_Search */
283 bitvec_set_uint(bv, 0, 4);
284
285 /* THRESH_GSM_low */
286 bitvec_set_uint(bv, 0, 4);
287
288 /* H_PRIO */
289 bitvec_set_uint(bv, 0, 2);
290
291 /* T_Reselection */
292 bitvec_set_uint(bv, 0, 2);
293
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100294 /* budget: 26 bits used above */
295
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200296 /* No 3G Priority Parameters Description */
297 bitvec_set_bit(bv, 0);
298 /* E-UTRAN Parameters Description */
299 bitvec_set_bit(bv, 1);
300
301 /* E-UTRAN_CCN_ACTIVE */
302 bitvec_set_bit(bv, 0);
303 /* E-UTRAN_Start: 9.1.54 */
304 bitvec_set_bit(bv, 1);
305 /* E-UTRAN_Stop: 9.1.54 */
306 bitvec_set_bit(bv, 1);
307
308 /* No E-UTRAN Measurement Parameters Descr. */
309 bitvec_set_bit(bv, 0);
310 /* No GPRS E-UTRAN Measurement Param. Descr. */
311 bitvec_set_bit(bv, 0);
312
313 /* Note: each of next 3 "repeated" structures might be repeated any
314 (0, 1, 2...) times - we only support 1 and 0 */
315
316 /* Repeated E-UTRAN Neighbour Cells */
317 bitvec_set_bit(bv, 1);
318
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100319 /* budget: 34 bits used above */
320
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200321 appended = append_eutran_neib_cell(bv, e, e_offset, rem);
322 if (!appended) { /* appending is impossible within current budget: rollback */
323 bv->cur_bit = old;
324 return;
325 }
326
Pau Espin Pedrolc4286ad2020-12-14 17:19:30 +0100327 /* budget: further 6 bits used below, totalling 40 bits */
328
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200329 /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */
330 bitvec_set_bit(bv, 0);
331
332 /* Note: following 2 repeated structs are not supported ATM */
333 /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */
334 bitvec_set_bit(bv, 0);
335 /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */
336 bitvec_set_bit(bv, 0);
337
338 /* Priority and E-UTRAN Parameters Description ends here */
339 /* No 3G CSG Description */
340 bitvec_set_bit(bv, 0);
341 /* No E-UTRAN CSG Description */
342 bitvec_set_bit(bv, 0);
343 /* No Additions in Rel-9: */
344 bitvec_set_bit(bv, L);
345}
346
347static int range_encode(enum osmo_gsm48_range r, int *arfcns, int arfcns_used, int *w,
348 int f0, uint8_t *chan_list)
349{
350 /*
351 * Manipulate the ARFCN list according to the rules in J4 depending
352 * on the selected range.
353 */
354 int rc, f0_included;
355
356 osmo_gsm48_range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
357
358 rc = osmo_gsm48_range_enc_arfcns(r, arfcns, arfcns_used, w, 0);
359 if (rc < 0)
360 return rc;
361
362 /* Select the range and the amount of bits needed */
363 switch (r) {
364 case OSMO_GSM48_ARFCN_RANGE_128:
Harald Welte1276c172019-05-28 18:38:35 +0200365 return osmo_gsm48_range_enc_128(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200366 case OSMO_GSM48_ARFCN_RANGE_256:
Harald Welte1276c172019-05-28 18:38:35 +0200367 return osmo_gsm48_range_enc_256(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200368 case OSMO_GSM48_ARFCN_RANGE_512:
Harald Welte1276c172019-05-28 18:38:35 +0200369 return osmo_gsm48_range_enc_512(chan_list, f0, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200370 case OSMO_GSM48_ARFCN_RANGE_1024:
Harald Welte1276c172019-05-28 18:38:35 +0200371 return osmo_gsm48_range_enc_1024(chan_list, f0, f0_included, w);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200372 default:
373 return -ERANGE;
374 };
375
376 return f0_included;
377}
378
379static inline int f0_helper(int *sc, size_t length, uint8_t *chan_list)
380{
381 int w[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS] = { 0 };
382
383 return range_encode(OSMO_GSM48_ARFCN_RANGE_1024, sc, length, w, 0, chan_list);
384}
385
386/* Return p(n) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */
387static unsigned range1024_p(unsigned n)
388{
389 switch (n) {
390 case 0: return 0;
391 case 1: return 10;
392 case 2: return 19;
393 case 3: return 28;
394 case 4: return 36;
395 case 5: return 44;
396 case 6: return 52;
397 case 7: return 60;
398 case 8: return 67;
399 case 9: return 74;
400 case 10: return 81;
401 case 11: return 88;
402 case 12: return 95;
403 case 13: return 102;
404 case 14: return 109;
405 case 15: return 116;
406 case 16: return 122;
407 default: return 0;
408 }
409}
410
411/* Estimate how many bits it'll take to append single FDD UARFCN */
412static inline int append_utran_fdd_length(uint16_t u, const int *sc, size_t sc_len, size_t length)
413{
414 uint8_t chan_list[16] = { 0 };
415 int tmp[sc_len], f0;
416
417 memcpy(tmp, sc, sizeof(tmp));
418
419 f0 = f0_helper(tmp, length, chan_list);
420 if (f0 < 0)
421 return f0;
422
423 return 21 + range1024_p(length);
424}
425
426/* Append single FDD UARFCN */
427static inline int append_utran_fdd(struct bitvec *bv, uint16_t u, int *sc, size_t length)
428{
429 uint8_t chan_list[16] = { 0 };
430 int f0 = f0_helper(sc, length, chan_list);
431
432 if (f0 < 0)
433 return f0;
434
435 /* Repeated UTRAN FDD Neighbour Cells */
436 bitvec_set_bit(bv, 1);
437
438 /* FDD-ARFCN */
439 bitvec_set_bit(bv, 0);
440 bitvec_set_uint(bv, u, 14);
441
442 /* FDD_Indic0: parameter value '0000000000' is a member of the set? */
443 bitvec_set_bit(bv, f0);
444 /* NR_OF_FDD_CELLS */
445 bitvec_set_uint(bv, length, 5);
446
447 f0 = bv->cur_bit;
448 bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list);
449 bv->cur_bit = f0 + range1024_p(length);
450
451 return 21 + range1024_p(length);
452}
453
454static inline int try_adding_uarfcn(struct bitvec *bv, uint16_t *scramble_list,
455 size_t uarfcn_length, size_t *u_offset,
456 uint16_t uarfcn, uint8_t num_sc, uint8_t start_pos, uint8_t budget)
457{
458 int i, k, rc, a[uarfcn_length];
459
460 if (budget < 23)
461 return -ENOMEM;
462
463 /* copy corresponding Scrambling Codes: range encoder make in-place modifications */
464 for (i = start_pos, k = 0; i < num_sc; a[k++] = scramble_list[i++]);
465
466 /* estimate bit length requirements */
467 rc = append_utran_fdd_length(uarfcn, a, uarfcn_length, k);
468 if (rc < 0)
469 return rc; /* range encoder failure */
470
471 if (budget - rc <= 0)
472 return -ENOMEM; /* we have ran out of budget in current SI2q */
473
474 /* compute next offset */
475 *u_offset += k;
476
477 return budget - append_utran_fdd(bv, uarfcn, a, k);
478}
479
480/* Append multiple FDD UARFCNs */
481static inline void append_uarfcns(struct bitvec *bv, const uint16_t *uarfcn_list, size_t *u_offset,
482 size_t uarfcn_length, uint16_t *scramble_list, uint8_t budget)
483{
484 int i, rem = budget - 7, st = *u_offset; /* account for constant bits right away */
485 uint16_t cu = uarfcn_list[*u_offset]; /* caller ensures that length is positive */
486
487 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
488
489 if (budget <= 7)
490 return;
491
492 /* 3G Neighbour Cell Description */
493 bitvec_set_bit(bv, 1);
494 /* No Index_Start_3G */
495 bitvec_set_bit(bv, 0);
496 /* No Absolute_Index_Start_EMR */
497 bitvec_set_bit(bv, 0);
498
499 /* UTRAN FDD Description */
500 bitvec_set_bit(bv, 1);
501 /* No Bandwidth_FDD */
502 bitvec_set_bit(bv, 0);
503
504 for (i = *u_offset; i <= uarfcn_length; i++)
505 if (uarfcn_list[i] != cu) { /* we've reached new UARFCN */
506 rem = try_adding_uarfcn(bv, scramble_list, uarfcn_length, u_offset, cu, i, st, rem);
507 if (rem < 0)
508 break;
509
510 if (i < uarfcn_length) {
511 cu = uarfcn_list[i];
512 st = i;
Harald Welte65aabd42020-10-15 08:04:49 +0200513 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200514 break;
Harald Welte65aabd42020-10-15 08:04:49 +0200515 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200516 }
517
518 /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */
519 bitvec_set_bit(bv, 0);
520
521 /* UTRAN TDD Description */
522 bitvec_set_bit(bv, 0);
523}
524
525static size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e)
526{
527 unsigned i, ret = 0;
528
529 if (!e)
530 return 0;
531
532 for (i = 0; i < e->length; i++)
533 if (e->arfcn[i] != OSMO_EARFCN_INVALID)
534 ret++;
535
536 return ret;
537}
538
539/* generate SI2quater rest octets: 3GPP TS 44.018 § 10.5.2.33b */
Harald Welte428d03b2019-05-28 18:46:20 +0200540int osmo_gsm48_rest_octets_si2quater_encode(uint8_t *data, uint8_t si2q_index, uint8_t si2q_count,
541 const uint16_t *uarfcn_list, size_t *u_offset,
542 size_t uarfcn_length, uint16_t *scramble_list,
543 struct osmo_earfcn_si2q *si2quater_neigh_list,
544 size_t *e_offset)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200545{
546 int rc;
547 struct bitvec bv;
548
549 if (si2q_count < si2q_index)
550 return -EINVAL;
551
552 bv.data = data;
553 bv.data_len = 20;
554 bitvec_zero(&bv);
555
556 /* BA_IND: Set to '0' as that's what we use for SI2xxx type,
557 * whereas '1' is used for SI5xxx type messages. The point here
558 * is to be able to correlate whether a given MS measurement
559 * report was using the neighbor cells advertised in SI2 or in
560 * SI5, as those two could very well be different */
561 bitvec_set_bit(&bv, 0);
562 /* 3G_BA_IND */
563 bitvec_set_bit(&bv, 1);
564 /* MP_CHANGE_MARK */
565 bitvec_set_bit(&bv, 0);
566
567 /* SI2quater_INDEX */
568 bitvec_set_uint(&bv, si2q_index, 4);
569 /* SI2quater_COUNT */
570 bitvec_set_uint(&bv, si2q_count, 4);
571
572 /* No Measurement_Parameters Description */
573 bitvec_set_bit(&bv, 0);
574 /* No GPRS_Real Time Difference Description */
575 bitvec_set_bit(&bv, 0);
576 /* No GPRS_BSIC Description */
577 bitvec_set_bit(&bv, 0);
578 /* No GPRS_REPORT PRIORITY Description */
579 bitvec_set_bit(&bv, 0);
580 /* No GPRS_MEASUREMENT_Parameters Description */
581 bitvec_set_bit(&bv, 0);
582 /* No NC Measurement Parameters */
583 bitvec_set_bit(&bv, 0);
584 /* No extension (length) */
585 bitvec_set_bit(&bv, 0);
586
587 rc = SI2Q_MAX_LEN - (bv.cur_bit + 3);
588 if (rc > 0 && uarfcn_length - *u_offset > 0)
589 append_uarfcns(&bv, uarfcn_list, u_offset, uarfcn_length, scramble_list, rc);
590 else /* No 3G Neighbour Cell Description */
591 bitvec_set_bit(&bv, 0);
592
593 /* No 3G Measurement Parameters Description */
594 bitvec_set_bit(&bv, 0);
595 /* No GPRS_3G_MEASUREMENT Parameters Descr. */
596 bitvec_set_bit(&bv, 0);
597
598 rc = SI2Q_MAX_LEN - bv.cur_bit;
599 if (rc > 0 && si2q_earfcn_count(si2quater_neigh_list) - *e_offset > 0)
600 append_earfcn(&bv, si2quater_neigh_list, e_offset, rc);
601 else /* No Additions in Rel-5: */
602 bitvec_set_bit(&bv, L);
603
604 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
605 return bv.data_len;
606}
607
608/* Append selection parameters to bitvec */
609static void append_selection_params(struct bitvec *bv,
610 const struct osmo_gsm48_si_selection_params *sp)
611{
612 if (sp->present) {
613 bitvec_set_bit(bv, H);
614 bitvec_set_bit(bv, sp->cbq);
615 bitvec_set_uint(bv, sp->cell_resel_off, 6);
616 bitvec_set_uint(bv, sp->temp_offs, 3);
617 bitvec_set_uint(bv, sp->penalty_time, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200618 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200619 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200620 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200621}
622
623/* Append power offset to bitvec */
624static void append_power_offset(struct bitvec *bv,
625 const struct osmo_gsm48_si_power_offset *po)
626{
627 if (po->present) {
628 bitvec_set_bit(bv, H);
629 bitvec_set_uint(bv, po->power_offset, 2);
Harald Welte65aabd42020-10-15 08:04:49 +0200630 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200631 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200632 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200633}
634
635/* Append GPRS indicator to bitvec */
636static void append_gprs_ind(struct bitvec *bv,
637 const struct osmo_gsm48_si3_gprs_ind *gi)
638{
639 if (gi->present) {
640 bitvec_set_bit(bv, H);
641 bitvec_set_uint(bv, gi->ra_colour, 3);
642 /* 0 == SI13 in BCCH Norm, 1 == SI13 sent on BCCH Ext */
643 bitvec_set_bit(bv, gi->si13_position);
Harald Welte65aabd42020-10-15 08:04:49 +0200644 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200645 bitvec_set_bit(bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200646 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200647}
648
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200649/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
Harald Welte428d03b2019-05-28 18:46:20 +0200650int osmo_gsm48_rest_octets_si3_encode(uint8_t *data, const struct osmo_gsm48_si_ro_info *si3)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200651{
652 struct bitvec bv;
653
654 memset(&bv, 0, sizeof(bv));
655 bv.data = data;
656 bv.data_len = 4;
657
658 /* Optional Selection Parameters */
659 append_selection_params(&bv, &si3->selection_params);
660
661 /* Optional Power Offset */
662 append_power_offset(&bv, &si3->power_offset);
663
664 /* Do we have a SI2ter on the BCCH? */
665 if (si3->si2ter_indicator)
666 bitvec_set_bit(&bv, H);
667 else
668 bitvec_set_bit(&bv, L);
669
670 /* Early Classmark Sending Control */
671 if (si3->early_cm_ctrl)
672 bitvec_set_bit(&bv, H);
673 else
674 bitvec_set_bit(&bv, L);
675
676 /* Do we have a SI Type 9 on the BCCH? */
677 if (si3->scheduling.present) {
678 bitvec_set_bit(&bv, H);
679 bitvec_set_uint(&bv, si3->scheduling.where, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200680 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200681 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200682 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200683
684 /* GPRS Indicator */
685 append_gprs_ind(&bv, &si3->gprs_ind);
686
687 /* 3G Early Classmark Sending Restriction. If H, then controlled by
688 * early_cm_ctrl above */
689 if (si3->early_cm_restrict_3g)
Vadim Yanitskiyc9eab822020-05-05 02:03:29 +0700690 bitvec_set_bit(&bv, L);
Pau Espin Pedrol3f6a2822020-12-18 17:19:29 +0100691 else
692 bitvec_set_bit(&bv, H);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200693
694 if (si3->si2quater_indicator) {
695 bitvec_set_bit(&bv, H); /* indicator struct present */
696 bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */
697 }
698
699 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
700 return bv.data_len;
701}
702
703static int append_lsa_params(struct bitvec *bv,
704 const struct osmo_gsm48_lsa_params *lsa_params)
705{
706 /* FIXME */
707 return -1;
708}
709
710/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
Harald Welte428d03b2019-05-28 18:46:20 +0200711int 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 +0200712{
713 struct bitvec bv;
714
715 memset(&bv, 0, sizeof(bv));
716 bv.data = data;
717 bv.data_len = len;
718
719 /* SI4 Rest Octets O */
720 append_selection_params(&bv, &si4->selection_params);
721 append_power_offset(&bv, &si4->power_offset);
722 append_gprs_ind(&bv, &si4->gprs_ind);
723
724 if (0 /* FIXME */) {
725 /* H and SI4 Rest Octets S */
726 bitvec_set_bit(&bv, H);
727
728 /* LSA Parameters */
729 if (si4->lsa_params.present) {
730 bitvec_set_bit(&bv, H);
731 append_lsa_params(&bv, &si4->lsa_params);
Harald Welte65aabd42020-10-15 08:04:49 +0200732 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200733 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200734 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200735
736 /* Cell Identity */
737 if (1) {
738 bitvec_set_bit(&bv, H);
739 bitvec_set_uint(&bv, si4->cell_id, 16);
Harald Welte65aabd42020-10-15 08:04:49 +0200740 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200741 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200742 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200743
744 /* LSA ID Information */
745 if (0) {
746 bitvec_set_bit(&bv, H);
747 /* FIXME */
Harald Welte65aabd42020-10-15 08:04:49 +0200748 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200749 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200750 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200751 } else {
752 /* L and break indicator */
753 bitvec_set_bit(&bv, L);
754 bitvec_set_bit(&bv, si4->break_ind ? H : L);
755 }
756
757 return bv.data_len;
758}
759
760
761/* GSM 04.18 ETSI TS 101 503 V8.27.0 (2006-05)
762
763<SI6 rest octets> ::=
764{L | H <PCH and NCH info>}
765{L | H <VBS/VGCS options : bit(2)>}
766{ < DTM_support : bit == L > I < DTM_support : bit == H >
767< RAC : bit (8) >
768< MAX_LAPDm : bit (3) > }
769< Band indicator >
770{ L | H < GPRS_MS_TXPWR_MAX_CCH : bit (5) > }
771<implicit spare >;
772*/
Harald Welte86156de2019-05-28 19:49:47 +0200773int osmo_gsm48_rest_octets_si6_encode(uint8_t *data, const struct osmo_gsm48_si6_ro_info *in)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200774{
775 struct bitvec bv;
776
777 memset(&bv, 0, sizeof(bv));
778 bv.data = data;
779 bv.data_len = 1;
780
Harald Welte86156de2019-05-28 19:49:47 +0200781 if (in->pch_nch_info.present) {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200782 bitvec_set_bit(&bv, H);
Harald Welte86156de2019-05-28 19:49:47 +0200783 bitvec_set_bit(&bv, !!in->pch_nch_info.paging_channel_restructuring);
784 bitvec_set_uint(&bv, in->pch_nch_info.nln_sacch, 2);
785 if (in->pch_nch_info.call_priority_present) {
786 bitvec_set_bit(&bv, 1);
787 bitvec_set_uint(&bv, in->pch_nch_info.call_priority, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200788 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200789 bitvec_set_bit(&bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200790 }
Harald Welte86156de2019-05-28 19:49:47 +0200791 bitvec_set_bit(&bv, !!in->pch_nch_info.nln_status_sacch);
Harald Welte65aabd42020-10-15 08:04:49 +0200792 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200793 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200794 }
Harald Welte86156de2019-05-28 19:49:47 +0200795
796 if (in->vbs_vgcs_options.present) {
797 bitvec_set_bit(&bv, H);
798 bitvec_set_bit(&bv, !!in->vbs_vgcs_options.inband_notifications);
799 bitvec_set_bit(&bv, !!in->vbs_vgcs_options.inband_pagings);
Harald Welte65aabd42020-10-15 08:04:49 +0200800 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200801 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200802 }
Harald Welte86156de2019-05-28 19:49:47 +0200803
804 if (in->dtm_support.present) {
805 bitvec_set_bit(&bv, H);
806 bitvec_set_uint(&bv, in->dtm_support.rac, 8);
807 bitvec_set_uint(&bv, in->dtm_support.max_lapdm, 3);
Harald Welte65aabd42020-10-15 08:04:49 +0200808 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200809 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200810 }
Harald Welte86156de2019-05-28 19:49:47 +0200811
812 if (in->band_indicator_1900)
813 bitvec_set_bit(&bv, H);
814 else
815 bitvec_set_bit(&bv, L);
816
817 if (in->gprs_ms_txpwr_max_ccch.present) {
818 bitvec_set_bit(&bv, H);
819 bitvec_set_uint(&bv, in->gprs_ms_txpwr_max_ccch.max_txpwr, 5);
Harald Welte65aabd42020-10-15 08:04:49 +0200820 } else {
Harald Welte86156de2019-05-28 19:49:47 +0200821 bitvec_set_bit(&bv, L);
Harald Welte65aabd42020-10-15 08:04:49 +0200822 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200823
824 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
825 return bv.data_len;
826}
827
Pau Espin Pedrold7a209b2021-02-09 18:28:25 +0100828
829static unsigned int decode_t3192(unsigned int t3192)
830{
831 /* See also 3GPP TS 44.060
832 Table 12.24.2: GPRS Cell Options information element details */
833 static const unsigned int decode_t3192_tbl[8] = {500, 1000, 1500, 0, 80, 120, 160, 200};
834 OSMO_ASSERT(t3192 <= 7);
835 return decode_t3192_tbl[t3192];
836}
837
838static unsigned int decode_drx_timer(unsigned int drx)
839{
840 static const unsigned int decode_drx_timer_tbl[8] = {0, 1, 2, 4, 8, 16, 32, 64};
841 OSMO_ASSERT(drx <= 7);
842 return decode_drx_timer_tbl[drx];
843}
844
845static int decode_gprs_cell_opt(struct osmo_gprs_cell_options *gco, struct bitvec *bv)
846{
847 gco->nmo = bitvec_get_uint(bv, 2);
848 gco->t3168 = (bitvec_get_uint(bv, 3) + 1) * 500;
849 gco->t3192 = decode_t3192(bitvec_get_uint(bv, 3));
850 gco->drx_timer_max = decode_drx_timer(bitvec_get_uint(bv, 3));
851
852 /* ACCESS_BURST_TYPE: */
853 bitvec_get_uint(bv, 1);
854 /* CONTROL_ACK_TYPE: */
855 gco->ctrl_ack_type_use_block = bitvec_get_uint(bv, 1);
856 gco->bs_cv_max = bitvec_get_uint(bv, 4);
857
858 if (bitvec_get_uint(bv, 1)) {
859 bitvec_get_uint(bv, 3); /* DEC */
860 bitvec_get_uint(bv, 3); /* INC */
861 bitvec_get_uint(bv, 3); /* MAX */
862 }
863
864 if (bitvec_get_uint(bv, 1)) {
865 int ext_len = bitvec_get_uint(bv, 6);
866 if (ext_len < 0)
867 return ext_len;
868 unsigned int cur_bit = bv->cur_bit;
869 /* Extension Information */
870 /* R99 extension: */
871 gco->ext_info.egprs_supported = bitvec_get_uint(bv, 1);
872 if (gco->ext_info.egprs_supported) {
873 gco->ext_info.use_egprs_p_ch_req = !bitvec_get_uint(bv, 1);
874 gco->ext_info.bep_period = bitvec_get_uint(bv, 4);
875 }
876 gco->ext_info.pfc_supported = bitvec_get_uint(bv, 1);
877 gco->ext_info.dtm_supported = bitvec_get_uint(bv, 1);
878 gco->ext_info.bss_paging_coordination = bitvec_get_uint(bv, 1);
879 /* REL-4 extension: */
880 gco->ext_info.ccn_active = bitvec_get_uint(bv, 1);
881 bitvec_get_uint(bv, 1); /* NW_EXT_UTBF */
882 bv->cur_bit = cur_bit + ext_len + 1;
883 }
884 return 0;
885}
886
887static void decode_gprs_pwr_ctrl_pars(struct osmo_gprs_power_ctrl_pars *pcp, struct bitvec *bv)
888{
889 pcp->alpha = bitvec_get_uint(bv, 4);
890 pcp->t_avg_w = bitvec_get_uint(bv,5);
891 pcp->t_avg_t = bitvec_get_uint(bv, 5);
892 pcp->pc_meas_chan = bitvec_get_uint(bv, 1);
893 pcp->n_avg_i = bitvec_get_uint(bv, 4);
894}
895
896/*! Decode SI13 Rest Octests (04.08 Chapter 10.5.2.37b).
897 * \param[out] si13 decoded SI13 rest octets
898 * \param[in] encoded SI13 rest octets
899 * \returns parsed bits on success, negative on error */
900int osmo_gsm48_rest_octets_si13_decode(struct osmo_gsm48_si13_info *si13, const uint8_t *data)
901{
902 struct osmo_gprs_cell_options *co = &si13->cell_opts;
903 struct osmo_gprs_power_ctrl_pars *pcp = &si13->pwr_ctrl_pars;
904 struct bitvec bv;
905 int rc;
906
907 memset(&bv, 0, sizeof(bv));
908 bv.data = (uint8_t *) data;
909 bv.data_len = 20;
910
911 memset(si13, 0, sizeof(*si13));
912
913
914 if (bitvec_get_bit_high(&bv) == H) {
915 si13->bcch_change_mark = bitvec_get_uint(&bv, 3);
916 si13->si_change_field = bitvec_get_uint(&bv, 4);
917 if (bitvec_get_uint(&bv, 1)) {
918 si13->bcch_change_mark = bitvec_get_uint(&bv, 2);
919 /* FIXME: implement parsing GPRS Mobile Allocation IE */
920 return -ENOTSUP;
921 }
922 if (bitvec_get_uint(&bv, 1)) {
923 /* PBCCH present in cell */
924 /* FIXME: parse not implemented */
925 return -ENOTSUP;
926 } else {
927 /* PBCCH not present in cell */
928 si13->rac = bitvec_get_uint(&bv, 8);
929 si13->spgc_ccch_sup = bitvec_get_uint(&bv, 1);
930 si13->prio_acc_thr = bitvec_get_uint(&bv, 3);
931 si13->net_ctrl_ord = bitvec_get_uint(&bv, 2);
932 if ((rc = decode_gprs_cell_opt(co, &bv)) < 0)
933 return rc;
934
935 decode_gprs_pwr_ctrl_pars(pcp, &bv);
936 }
937 }
938 return bv.cur_bit;
939}
940
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200941/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
942 < GPRS Mobile Allocation IE > ::=
943 < HSN : bit (6) >
944 { 0 | 1 < RFL number list : < RFL number list struct > > }
945 { 0 < MA_LENGTH : bit (6) >
946 < MA_BITMAP: bit (val(MA_LENGTH) + 1) >
947 | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;
948
949 < RFL number list struct > :: =
950 < RFL_NUMBER : bit (4) >
951 { 0 | 1 < RFL number list struct > } ;
952 < ARFCN index list struct > ::=
953 < ARFCN_INDEX : bit(6) >
954 { 0 | 1 < ARFCN index list struct > } ;
955 */
956static int append_gprs_mobile_alloc(struct bitvec *bv)
957{
958 /* Hopping Sequence Number */
959 bitvec_set_uint(bv, 0, 6);
960
961 if (0) {
962 /* We want to use a RFL number list */
963 bitvec_set_bit(bv, 1);
964 /* FIXME: RFL number list */
Harald Welte65aabd42020-10-15 08:04:49 +0200965 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200966 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200967 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200968
969 if (0) {
970 /* We want to use a MA_BITMAP */
971 bitvec_set_bit(bv, 0);
972 /* FIXME: MA_LENGTH, MA_BITMAP, ... */
973 } else {
974 bitvec_set_bit(bv, 1);
975 if (0) {
976 /* We want to provide an ARFCN index list */
977 bitvec_set_bit(bv, 1);
978 /* FIXME */
Harald Welte65aabd42020-10-15 08:04:49 +0200979 } else {
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200980 bitvec_set_bit(bv, 0);
Harald Welte65aabd42020-10-15 08:04:49 +0200981 }
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +0200982 }
983 return 0;
984}
985
986static int encode_t3192(unsigned int t3192)
987{
988 /* See also 3GPP TS 44.060
989 Table 12.24.2: GPRS Cell Options information element details */
990 if (t3192 == 0)
991 return 3;
992 else if (t3192 <= 80)
993 return 4;
994 else if (t3192 <= 120)
995 return 5;
996 else if (t3192 <= 160)
997 return 6;
998 else if (t3192 <= 200)
999 return 7;
1000 else if (t3192 <= 500)
1001 return 0;
1002 else if (t3192 <= 1000)
1003 return 1;
1004 else if (t3192 <= 1500)
1005 return 2;
1006 else
1007 return -EINVAL;
1008}
1009
1010static int encode_drx_timer(unsigned int drx)
1011{
1012 if (drx == 0)
1013 return 0;
1014 else if (drx == 1)
1015 return 1;
1016 else if (drx == 2)
1017 return 2;
1018 else if (drx <= 4)
1019 return 3;
1020 else if (drx <= 8)
1021 return 4;
1022 else if (drx <= 16)
1023 return 5;
1024 else if (drx <= 32)
1025 return 6;
1026 else if (drx <= 64)
1027 return 7;
1028 else
1029 return -EINVAL;
1030}
1031
1032/* GPRS Cell Options as per TS 04.60 Chapter 12.24
1033 < GPRS Cell Options IE > ::=
1034 < NMO : bit(2) >
1035 < T3168 : bit(3) >
1036 < T3192 : bit(3) >
1037 < DRX_TIMER_MAX: bit(3) >
1038 < ACCESS_BURST_TYPE: bit >
1039 < CONTROL_ACK_TYPE : bit >
1040 < BS_CV_MAX: bit(4) >
1041 { 0 | 1 < PAN_DEC : bit(3) >
1042 < PAN_INC : bit(3) >
1043 < PAN_MAX : bit(3) >
1044 { 0 | 1 < Extension Length : bit(6) >
1045 < bit (val(Extension Length) + 1
1046 & { < Extension Information > ! { bit ** = <no string> } } ;
1047 < Extension Information > ::=
1048 { 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit >
1049 < BEP_PERIOD : bit(4) > }
1050 < PFC_FEATURE_MODE : bit >
1051 < DTM_SUPPORT : bit >
1052 <BSS_PAGING_COORDINATION: bit >
1053 <spare bit > ** ;
1054 */
1055static int append_gprs_cell_opt(struct bitvec *bv,
1056 const struct osmo_gprs_cell_options *gco)
1057{
1058 int t3192, drx_timer_max;
1059
1060 t3192 = encode_t3192(gco->t3192);
1061 if (t3192 < 0)
1062 return t3192;
1063
1064 drx_timer_max = encode_drx_timer(gco->drx_timer_max);
1065 if (drx_timer_max < 0)
1066 return drx_timer_max;
1067
1068 bitvec_set_uint(bv, gco->nmo, 2);
1069
1070 /* See also 3GPP TS 44.060
1071 Table 12.24.2: GPRS Cell Options information element details */
1072 bitvec_set_uint(bv, gco->t3168 / 500 - 1, 3);
1073
1074 bitvec_set_uint(bv, t3192, 3);
1075 bitvec_set_uint(bv, drx_timer_max, 3);
1076 /* ACCESS_BURST_TYPE: Hard-code 8bit */
1077 bitvec_set_bit(bv, 0);
1078 /* CONTROL_ACK_TYPE: */
1079 bitvec_set_bit(bv, gco->ctrl_ack_type_use_block);
1080 bitvec_set_uint(bv, gco->bs_cv_max, 4);
1081
1082 if (0) {
1083 /* hard-code no PAN_{DEC,INC,MAX} */
1084 bitvec_set_bit(bv, 0);
1085 } else {
1086 /* copied from ip.access BSC protocol trace */
1087 bitvec_set_bit(bv, 1);
1088 bitvec_set_uint(bv, 1, 3); /* DEC */
1089 bitvec_set_uint(bv, 1, 3); /* INC */
1090 bitvec_set_uint(bv, 15, 3); /* MAX */
1091 }
1092
1093 if (!gco->ext_info_present) {
1094 /* no extension information */
1095 bitvec_set_bit(bv, 0);
1096 } else {
1097 /* extension information */
1098 bitvec_set_bit(bv, 1);
Pau Espin Pedrolc31809f2021-02-09 19:29:28 +01001099 /* R99 extension: */
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001100 if (!gco->ext_info.egprs_supported) {
1101 /* 6bit length of extension */
Pau Espin Pedrol5b6f1d72021-01-29 17:51:09 +01001102 bitvec_set_uint(bv, (1 + 5)-1, 6);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001103 /* EGPRS supported in the cell */
1104 bitvec_set_bit(bv, 0);
1105 } else {
1106 /* 6bit length of extension */
Pau Espin Pedrol5b6f1d72021-01-29 17:51:09 +01001107 bitvec_set_uint(bv, (1 + 5 + 5)-1, 6);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001108 /* EGPRS supported in the cell */
1109 bitvec_set_bit(bv, 1);
1110
Pau Espin Pedrol30bf0e62020-12-14 17:13:47 +01001111 /* 1bit EGPRS PACKET CHANNEL REQUEST (inverted logic) */
1112 bitvec_set_bit(bv, !gco->ext_info.use_egprs_p_ch_req);
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001113
1114 /* 4bit BEP PERIOD */
1115 bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
1116 }
1117 bitvec_set_bit(bv, gco->ext_info.pfc_supported);
1118 bitvec_set_bit(bv, gco->ext_info.dtm_supported);
1119 bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
Pau Espin Pedrol946bb952020-12-14 17:04:54 +01001120
1121 /* REL-4 extension: */
1122 bitvec_set_bit(bv, gco->ext_info.ccn_active);
1123 bitvec_set_bit(bv, 0); /* NW_EXT_UTBF disabled */
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001124 }
1125
1126 return 0;
1127}
1128
1129static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
1130 const struct osmo_gprs_power_ctrl_pars *pcp)
1131{
1132 bitvec_set_uint(bv, pcp->alpha, 4);
1133 bitvec_set_uint(bv, pcp->t_avg_w, 5);
1134 bitvec_set_uint(bv, pcp->t_avg_t, 5);
1135 bitvec_set_uint(bv, pcp->pc_meas_chan, 1);
1136 bitvec_set_uint(bv, pcp->n_avg_i, 4);
1137}
1138
1139/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
Harald Welte428d03b2019-05-28 18:46:20 +02001140int osmo_gsm48_rest_octets_si13_encode(uint8_t *data, const struct osmo_gsm48_si13_info *si13)
Stefan Sperlingbd6e7a92018-07-27 15:17:09 +02001141{
1142 struct bitvec bv;
1143
1144 memset(&bv, 0, sizeof(bv));
1145 bv.data = data;
1146 bv.data_len = 20;
1147
1148 if (0) {
1149 /* No rest octets */
1150 bitvec_set_bit(&bv, L);
1151 } else {
1152 bitvec_set_bit(&bv, H);
1153 bitvec_set_uint(&bv, si13->bcch_change_mark, 3);
1154 bitvec_set_uint(&bv, si13->si_change_field, 4);
1155 if (1) {
1156 bitvec_set_bit(&bv, 0);
1157 } else {
1158 bitvec_set_bit(&bv, 1);
1159 bitvec_set_uint(&bv, si13->bcch_change_mark, 2);
1160 append_gprs_mobile_alloc(&bv);
1161 }
1162 /* PBCCH not present in cell:
1163 it shall never be indicated according to 3GPP TS 44.018 Table 10.5.2.37b.1 */
1164 bitvec_set_bit(&bv, 0);
1165 bitvec_set_uint(&bv, si13->rac, 8);
1166 bitvec_set_bit(&bv, si13->spgc_ccch_sup);
1167 bitvec_set_uint(&bv, si13->prio_acc_thr, 3);
1168 bitvec_set_uint(&bv, si13->net_ctrl_ord, 2);
1169 append_gprs_cell_opt(&bv, &si13->cell_opts);
1170 append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);
1171
1172 /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
1173 bitvec_set_bit(&bv, H); /* added Release 99 */
1174 /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
1175 * was only added in this Release */
1176 bitvec_set_bit(&bv, 1);
1177 }
1178 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
1179 return bv.data_len;
1180}
Harald Weltef85b33f2019-05-28 17:56:21 +02001181
1182
1183/***********************************************************************
1184 * Decoder
1185 ***********************************************************************/
1186
1187/*! Decode SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72).
1188 * \param[out] si3 decoded SI3 rest octets
1189 * \param[in] encoded SI3 rest octets, 4 octets long */
1190void osmo_gsm48_rest_octets_si3_decode(struct osmo_gsm48_si_ro_info *si3, const uint8_t *data)
1191{
1192 struct osmo_gsm48_si_selection_params *sp = &si3->selection_params;
1193 struct osmo_gsm48_si_power_offset *po = &si3->power_offset;
1194 struct osmo_gsm48_si3_gprs_ind *gi = &si3->gprs_ind;
1195 struct bitvec bv;
1196
1197 memset(&bv, 0, sizeof(bv));
1198 bv.data = (uint8_t *) data;
1199 bv.data_len = 4;
1200
1201 memset(si3, 0, sizeof(*si3));
1202
Vadim Yanitskiy74474cf2019-07-17 16:40:11 +07001203 /* Optional Selection Parameters */
Harald Weltef85b33f2019-05-28 17:56:21 +02001204 if (bitvec_get_bit_high(&bv) == H) {
1205 sp->present = 1;
1206 sp->cbq = bitvec_get_uint(&bv, 1);
1207 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
1208 sp->temp_offs = bitvec_get_uint(&bv, 3);
1209 sp->penalty_time = bitvec_get_uint(&bv, 5);
Harald Welte65aabd42020-10-15 08:04:49 +02001210 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001211 sp->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001212 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001213
1214 /* Optional Power Offset */
1215 if (bitvec_get_bit_high(&bv) == H) {
1216 po->present = 1;
1217 po->power_offset = bitvec_get_uint(&bv, 2);
Harald Welte65aabd42020-10-15 08:04:49 +02001218 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001219 po->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001220 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001221
1222 /* System Information 2ter Indicator */
1223 if (bitvec_get_bit_high(&bv) == H)
1224 si3->si2ter_indicator = 1;
1225 else
1226 si3->si2ter_indicator = 0;
1227
1228 /* Early Classmark Sending Control */
1229 if (bitvec_get_bit_high(&bv) == H)
1230 si3->early_cm_ctrl = 1;
1231 else
1232 si3->early_cm_ctrl = 0;
1233
1234 /* Scheduling if and where */
1235 if (bitvec_get_bit_high(&bv) == H) {
1236 si3->scheduling.present = 1;
1237 si3->scheduling.where = bitvec_get_uint(&bv, 3);
Harald Welte65aabd42020-10-15 08:04:49 +02001238 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001239 si3->scheduling.present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001240 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001241
1242 /* GPRS Indicator */
1243 if (bitvec_get_bit_high(&bv) == H) {
1244 gi->present = 1;
1245 gi->ra_colour = bitvec_get_uint(&bv, 3);
1246 gi->si13_position = bitvec_get_uint(&bv, 1);
Harald Welte65aabd42020-10-15 08:04:49 +02001247 } else {
Harald Weltef85b33f2019-05-28 17:56:21 +02001248 gi->present = 0;
Harald Welte65aabd42020-10-15 08:04:49 +02001249 }
Harald Weltef85b33f2019-05-28 17:56:21 +02001250
1251 /* 3G Early Classmark Sending Restriction. If H, then controlled by
1252 * early_cm_ctrl above */
1253 if (bitvec_get_bit_high(&bv) == H)
Harald Weltef85b33f2019-05-28 17:56:21 +02001254 si3->early_cm_restrict_3g = 0;
Pau Espin Pedrold01163a2020-12-21 13:03:32 +01001255 else
1256 si3->early_cm_restrict_3g = 1;
Harald Weltef85b33f2019-05-28 17:56:21 +02001257
1258 if (bitvec_get_bit_high(&bv) == H)
1259 si3->si2quater_indicator = 1;
1260 else
1261 si3->si2quater_indicator = 0;
1262}
Harald Welte5e1cd5e2020-10-11 20:04:04 +02001263
1264
1265void osmo_gsm48_rest_octets_si4_decode(struct osmo_gsm48_si_ro_info *si4, const uint8_t *data, int len)
1266{
1267 struct osmo_gsm48_si_selection_params *sp = &si4->selection_params;
1268 struct osmo_gsm48_si_power_offset *po = &si4->power_offset;
1269 struct osmo_gsm48_si3_gprs_ind *gi = &si4->gprs_ind;
1270 struct bitvec bv;
1271
1272 memset(&bv, 0, sizeof(bv));
1273 bv.data = (uint8_t *) data;
1274 bv.data_len = len;
1275
1276 memset(si4, 0, sizeof(*si4));
1277
1278 /* Optional Selection Parameters */
1279 if (bitvec_get_bit_high(&bv) == H) {
1280 sp->present = 1;
1281 sp->cbq = bitvec_get_uint(&bv, 1);
1282 sp->cell_resel_off = bitvec_get_uint(&bv, 6);
1283 sp->temp_offs = bitvec_get_uint(&bv, 3);
1284 sp->penalty_time = bitvec_get_uint(&bv, 5);
1285 } else {
1286 sp->present = 0;
1287 }
1288
1289 /* Optional Power Offset */
1290 if (bitvec_get_bit_high(&bv) == H) {
1291 po->present = 1;
1292 po->power_offset = bitvec_get_uint(&bv, 2);
1293 } else {
1294 po->present = 0;
1295 }
1296
1297 /* GPRS Indicator */
1298 if (bitvec_get_bit_high(&bv) == H) {
1299 gi->present = 1;
1300 gi->ra_colour = bitvec_get_uint(&bv, 3);
1301 gi->si13_position = bitvec_get_uint(&bv, 1);
1302 } else {
1303 gi->present = 0;
1304 }
1305}