blob: fdab70a0c09009c681b20ec28d858fa427beb14a [file] [log] [blame]
Harald Weltea43f7892009-12-01 18:04:30 +05301/* 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 Welte9af6ddf2011-01-01 15:25:50 +010010 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
Harald Weltea43f7892009-12-01 18:04:30 +053012 * (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 Welte9af6ddf2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Harald Weltea43f7892009-12-01 18:04:30 +053018 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010019 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Weltea43f7892009-12-01 18:04:30 +053021 *
22 */
23
24#include <string.h>
25#include <stdlib.h>
26#include <errno.h>
Max59a1bf32016-04-15 16:04:46 +020027#include <stdbool.h>
Harald Weltea43f7892009-12-01 18:04:30 +053028
Max59a1bf32016-04-15 16:04:46 +020029#include <openbsc/debug.h>
Harald Weltea43f7892009-12-01 18:04:30 +053030#include <openbsc/gsm_data.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010031#include <osmocom/core/bitvec.h>
Maxe01f5052016-04-23 18:00:18 +020032#include <osmocom/gsm/bitvec_gsm.h>
Harald Weltea43f7892009-12-01 18:04:30 +053033#include <openbsc/rest_octets.h>
Max59a1bf32016-04-15 16:04:46 +020034#include <openbsc/arfcn_range_encode.h>
Max26679e02016-04-20 15:57:13 +020035#include <openbsc/system_information.h>
Harald Weltea43f7892009-12-01 18:04:30 +053036
37/* generate SI1 rest octets */
Holger Hans Peter Freytherf876c392013-03-06 12:02:33 +010038int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net)
Harald Weltea43f7892009-12-01 18:04:30 +053039{
40 struct bitvec bv;
41
42 memset(&bv, 0, sizeof(bv));
43 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +010044 bv.data_len = 1;
Harald Weltea43f7892009-12-01 18:04:30 +053045
46 if (nch_pos) {
47 bitvec_set_bit(&bv, H);
48 bitvec_set_uint(&bv, *nch_pos, 5);
49 } else
50 bitvec_set_bit(&bv, L);
51
Holger Hans Peter Freytherf876c392013-03-06 12:02:33 +010052 if (is1800_net)
53 bitvec_set_bit(&bv, L);
54 else
55 bitvec_set_bit(&bv, H);
56
57 bitvec_spare_padding(&bv, 6);
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +010058 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +053059}
60
Maxf39d03a2017-05-12 17:00:30 +020061/* Append Repeated E-UTRAN Neighbour Cell to bitvec: see 3GPP TS 44.018 Table 10.5.2.33b.1 */
62static inline void append_eutran_neib_cell(struct bitvec *bv, struct gsm_bts *bts, uint8_t budget)
Max59a1bf32016-04-15 16:04:46 +020063{
Maxf39d03a2017-05-12 17:00:30 +020064 const struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
65 unsigned i, skip = 0;
66 size_t offset = bts->e_offset;
67 uint8_t rem = budget - 6, earfcn_budget; /* account for mandatory stop bit and THRESH_E-UTRAN_high */
Max70fdd242017-06-15 15:10:53 +020068
69 if (budget <= 6)
70 return;
71
72 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
73
Maxf39d03a2017-05-12 17:00:30 +020074 /* first we have to properly adjust budget requirements */
75 if (e->prio_valid) /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
76 rem -= 4;
77 else
78 rem--;
79
80 if (e->thresh_lo_valid) /* THRESH_E-UTRAN_low: */
81 rem -= 6;
82 else
83 rem--;
84
85 if (e->qrxlm_valid) /* E-UTRAN_QRXLEVMIN: */
86 rem -= 6;
87 else
88 rem--;
89
90 /* now we can proceed with actually adding EARFCNs within adjusted budget limit */
Max59a1bf32016-04-15 16:04:46 +020091 for (i = 0; i < e->length; i++) {
92 if (e->arfcn[i] != OSMO_EARFCN_INVALID) {
Maxf39d03a2017-05-12 17:00:30 +020093 if (skip < offset) {
94 skip++; /* ignore EARFCNs added on previous calls */
95 } else {
Max70fdd242017-06-15 15:10:53 +020096 earfcn_budget = 17; /* compute budget per-EARFCN */
Maxf39d03a2017-05-12 17:00:30 +020097 if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
98 earfcn_budget++;
99 else
100 earfcn_budget += 4;
Max59a1bf32016-04-15 16:04:46 +0200101
Max70fdd242017-06-15 15:10:53 +0200102 if (rem - earfcn_budget < 0)
Maxf39d03a2017-05-12 17:00:30 +0200103 break;
Max70fdd242017-06-15 15:10:53 +0200104 else {
Maxf39d03a2017-05-12 17:00:30 +0200105 bts->e_offset++;
Max70fdd242017-06-15 15:10:53 +0200106 rem -= earfcn_budget;
Maxf39d03a2017-05-12 17:00:30 +0200107 bitvec_set_bit(bv, 1); /* EARFCN: */
108 bitvec_set_uint(bv, e->arfcn[i], 16);
109
110 if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
111 bitvec_set_bit(bv, 0);
112 else { /* Measurement Bandwidth: 9.1.54 */
113 bitvec_set_bit(bv, 1);
114 bitvec_set_uint(bv, e->meas_bw[i], 3);
115 }
116 }
Max59a1bf32016-04-15 16:04:46 +0200117 }
118 }
119 }
120
121 /* stop bit - end of EARFCN + Measurement Bandwidth sequence */
122 bitvec_set_bit(bv, 0);
123
Maxf39d03a2017-05-12 17:00:30 +0200124 /* Note: we don't support different EARFCN arrays each with different priority, threshold etc. */
125
Max59a1bf32016-04-15 16:04:46 +0200126 if (e->prio_valid) {
127 /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
128 bitvec_set_bit(bv, 1);
129 bitvec_set_uint(bv, e->prio, 3);
130 } else
131 bitvec_set_bit(bv, 0);
132
133 /* THRESH_E-UTRAN_high */
134 bitvec_set_uint(bv, e->thresh_hi, 5);
135
136 if (e->thresh_lo_valid) {
137 /* THRESH_E-UTRAN_low: */
138 bitvec_set_bit(bv, 1);
139 bitvec_set_uint(bv, e->thresh_lo, 5);
140 } else
141 bitvec_set_bit(bv, 0);
142
143 if (e->qrxlm_valid) {
144 /* E-UTRAN_QRXLEVMIN: */
145 bitvec_set_bit(bv, 1);
146 bitvec_set_uint(bv, e->qrxlm, 5);
147 } else
148 bitvec_set_bit(bv, 0);
149}
150
Maxf39d03a2017-05-12 17:00:30 +0200151static inline void append_earfcn(struct bitvec *bv, struct gsm_bts *bts, uint8_t budget)
Max59a1bf32016-04-15 16:04:46 +0200152{
Max70fdd242017-06-15 15:10:53 +0200153 int rem = budget - 25;
154 if (rem <= 0)
155 return;
156
157 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
158
Max59a1bf32016-04-15 16:04:46 +0200159 /* Additions in Rel-5: */
160 bitvec_set_bit(bv, H);
161 /* No 3G Additional Measurement Param. Descr. */
162 bitvec_set_bit(bv, 0);
163 /* No 3G ADDITIONAL MEASUREMENT Param. Descr. 2 */
164 bitvec_set_bit(bv, 0);
165 /* Additions in Rel-6: */
166 bitvec_set_bit(bv, H);
167 /* 3G_CCN_ACTIVE */
168 bitvec_set_bit(bv, 0);
169 /* Additions in Rel-7: */
170 bitvec_set_bit(bv, H);
171 /* No 700_REPORTING_OFFSET */
172 bitvec_set_bit(bv, 0);
173 /* No 810_REPORTING_OFFSET */
174 bitvec_set_bit(bv, 0);
175 /* Additions in Rel-8: */
176 bitvec_set_bit(bv, H);
177
178 /* Priority and E-UTRAN Parameters Description */
179 bitvec_set_bit(bv, 1);
180
181 /* No Serving Cell Priority Parameters Descr. */
182 bitvec_set_bit(bv, 0);
183 /* No 3G Priority Parameters Description */
184 bitvec_set_bit(bv, 0);
185 /* E-UTRAN Parameters Description */
186 bitvec_set_bit(bv, 1);
187
188 /* E-UTRAN_CCN_ACTIVE */
189 bitvec_set_bit(bv, 0);
190 /* E-UTRAN_Start: 9.1.54 */
191 bitvec_set_bit(bv, 1);
192 /* E-UTRAN_Stop: 9.1.54 */
193 bitvec_set_bit(bv, 1);
194
195 /* No E-UTRAN Measurement Parameters Descr. */
196 bitvec_set_bit(bv, 0);
197 /* No GPRS E-UTRAN Measurement Param. Descr. */
198 bitvec_set_bit(bv, 0);
199
200 /* Note: each of next 3 "repeated" structures might be repeated any
201 (0, 1, 2...) times - we only support 1 and 0 */
202
203 /* Repeated E-UTRAN Neighbour Cells */
204 bitvec_set_bit(bv, 1);
205
Maxf39d03a2017-05-12 17:00:30 +0200206 /* N. B: 25 bits are set in append_earfcn() - keep it in sync with budget adjustment below: */
Max70fdd242017-06-15 15:10:53 +0200207 append_eutran_neib_cell(bv, bts, rem);
Max59a1bf32016-04-15 16:04:46 +0200208
209 /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */
210 bitvec_set_bit(bv, 0);
211
212 /* Note: following 2 repeated structs are not supported ATM */
213 /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */
214 bitvec_set_bit(bv, 0);
215 /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */
216 bitvec_set_bit(bv, 0);
217
218 /* Priority and E-UTRAN Parameters Description ends here */
219 /* No 3G CSG Description */
220 bitvec_set_bit(bv, 0);
221 /* No E-UTRAN CSG Description */
222 bitvec_set_bit(bv, 0);
223 /* No Additions in Rel-9: */
224 bitvec_set_bit(bv, L);
225}
226
Maxf39d03a2017-05-12 17:00:30 +0200227static inline int f0_helper(int *sc, size_t length, uint8_t *chan_list)
Maxe610e702016-12-19 13:41:48 +0100228{
Maxf39d03a2017-05-12 17:00:30 +0200229 int w[RANGE_ENC_MAX_ARFCNS] = { 0 };
230
231 return range_encode(ARFCN_RANGE_1024, sc, length, w, 0, chan_list);
232}
233
234/* Estimate how many bits it'll take to append single FDD UARFCN */
235static inline int append_utran_fdd_length(uint16_t u, int *sc, size_t sc_len, size_t length)
236{
237 uint8_t chan_list[16] = { 0 };
238 int tmp[sc_len], f0;
239
240 memcpy(tmp, sc, sizeof(tmp));
241
242 f0 = f0_helper(tmp, length, chan_list);
243 if (f0 < 0)
244 return f0;
245
246 return 21 + range1024_p(length);
247}
248
249/* Append single FDD UARFCN */
250static inline int append_utran_fdd(struct bitvec *bv, uint16_t u, int *sc, size_t length)
251{
252 uint8_t chan_list[16] = { 0 };
253 int f0 = f0_helper(sc, length, chan_list);
254
255 if (f0 < 0)
256 return f0;
257
Maxe610e702016-12-19 13:41:48 +0100258 /* Repeated UTRAN FDD Neighbour Cells */
259 bitvec_set_bit(bv, 1);
260
261 /* FDD-ARFCN */
262 bitvec_set_bit(bv, 0);
263 bitvec_set_uint(bv, u, 14);
264
Maxe610e702016-12-19 13:41:48 +0100265 /* FDD_Indic0: parameter value '0000000000' is a member of the set? */
266 bitvec_set_bit(bv, f0);
267 /* NR_OF_FDD_CELLS */
268 bitvec_set_uint(bv, length, 5);
269
270 f0 = bv->cur_bit;
271 bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list);
272 bv->cur_bit = f0 + range1024_p(length);
Maxf39d03a2017-05-12 17:00:30 +0200273
274 return 21 + range1024_p(length);
Maxe610e702016-12-19 13:41:48 +0100275}
276
277/* Append multiple FDD UARFCNs */
Maxf39d03a2017-05-12 17:00:30 +0200278static inline int append_uarfcns(struct bitvec *bv, struct gsm_bts *bts, uint8_t budget)
Max26679e02016-04-20 15:57:13 +0200279{
Maxf39d03a2017-05-12 17:00:30 +0200280 const uint16_t *u = bts->si_common.data.uarfcn_list, *sc = bts->si_common.data.scramble_list;
281 int i, j, k, rc, st = 0, a[bts->si_common.uarfcn_length];
282 uint16_t cu = u[bts->u_offset]; /* caller ensures that length is positive */
Max70fdd242017-06-15 15:10:53 +0200283 uint8_t rem = budget - 7, offset_diff; /* account for constant bits right away */
284
285 OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
286
287 if (budget <= 7)
288 return -ENOMEM;
Max26679e02016-04-20 15:57:13 +0200289
290 /* 3G Neighbour Cell Description */
291 bitvec_set_bit(bv, 1);
292 /* No Index_Start_3G */
293 bitvec_set_bit(bv, 0);
294 /* No Absolute_Index_Start_EMR */
295 bitvec_set_bit(bv, 0);
296
297 /* UTRAN FDD Description */
298 bitvec_set_bit(bv, 1);
299 /* No Bandwidth_FDD */
300 bitvec_set_bit(bv, 0);
301
Maxf39d03a2017-05-12 17:00:30 +0200302 for (i = bts->u_offset; i < bts->si_common.uarfcn_length; i++) {
Max70fdd242017-06-15 15:10:53 +0200303 offset_diff = 0;
304 for (j = st, k = 0; j < i; j++) {
Maxe610e702016-12-19 13:41:48 +0100305 a[k++] = sc[j]; /* copy corresponding SCs */
Max70fdd242017-06-15 15:10:53 +0200306 offset_diff++; /* compute proper offset step */
307 }
Maxe610e702016-12-19 13:41:48 +0100308 if (u[i] != cu) { /* we've reached new UARFCN */
Maxf39d03a2017-05-12 17:00:30 +0200309 rc = append_utran_fdd_length(cu, a, bts->si_common.uarfcn_length, k);
310 if (rc < 0) { /* estimate bit length requirements */
Maxe610e702016-12-19 13:41:48 +0100311 return rc;
Maxf39d03a2017-05-12 17:00:30 +0200312 }
313
Max70fdd242017-06-15 15:10:53 +0200314 if (rem - rc <= 0)
Maxf39d03a2017-05-12 17:00:30 +0200315 break; /* we have ran out of budget in current SI2q */
Max70fdd242017-06-15 15:10:53 +0200316 else {
Maxf39d03a2017-05-12 17:00:30 +0200317 rem -= append_utran_fdd(bv, cu, a, k);
Max70fdd242017-06-15 15:10:53 +0200318 bts->u_offset += offset_diff;
Maxf39d03a2017-05-12 17:00:30 +0200319 }
Maxe610e702016-12-19 13:41:48 +0100320 cu = u[i];
321 st = i; /* update start position */
322 }
323 }
Max26679e02016-04-20 15:57:13 +0200324
Maxf39d03a2017-05-12 17:00:30 +0200325 if (rem > 22) { /* add last UARFCN not covered by previous cycle if it could possibly fit into budget */
Max70fdd242017-06-15 15:10:53 +0200326 offset_diff = 0;
327 for (i = st, k = 0; i < bts->si_common.uarfcn_length; i++) {
Maxf39d03a2017-05-12 17:00:30 +0200328 a[k++] = sc[i];
Max70fdd242017-06-15 15:10:53 +0200329 offset_diff++;
330 }
Maxf39d03a2017-05-12 17:00:30 +0200331 rc = append_utran_fdd_length(cu, a, bts->si_common.uarfcn_length, k);
332 if (rc < 0) {
333 return rc;
334 }
335
336 if (rem - rc >= 0) {
337 rem -= append_utran_fdd(bv, cu, a, k);
Max70fdd242017-06-15 15:10:53 +0200338 bts->u_offset += offset_diff;
Maxf39d03a2017-05-12 17:00:30 +0200339 }
340 }
Max26679e02016-04-20 15:57:13 +0200341
342 /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */
343 bitvec_set_bit(bv, 0);
344
345 /* UTRAN TDD Description */
346 bitvec_set_bit(bv, 0);
Max881064e2016-12-14 14:51:40 +0100347
348 return 0;
Max26679e02016-04-20 15:57:13 +0200349}
350
Max59a1bf32016-04-15 16:04:46 +0200351/* generate SI2quater rest octets: 3GPP TS 44.018 § 10.5.2.33b */
Maxf39d03a2017-05-12 17:00:30 +0200352int rest_octets_si2quater(uint8_t *data, struct gsm_bts *bts)
Max59a1bf32016-04-15 16:04:46 +0200353{
Max881064e2016-12-14 14:51:40 +0100354 int rc;
Max59a1bf32016-04-15 16:04:46 +0200355 struct bitvec bv;
Max70fdd242017-06-15 15:10:53 +0200356
357 if (bts->si2q_count < bts->si2q_index)
358 return -EINVAL;
359
Max59a1bf32016-04-15 16:04:46 +0200360 bv.data = data;
361 bv.data_len = 20;
362 bitvec_zero(&bv);
363
364 /* BA_IND */
365 bitvec_set_bit(&bv, 1);
366 /* 3G_BA_IND */
367 bitvec_set_bit(&bv, 1);
368 /* MP_CHANGE_MARK */
369 bitvec_set_bit(&bv, 0);
370
Max59a1bf32016-04-15 16:04:46 +0200371 /* SI2quater_INDEX */
Maxf39d03a2017-05-12 17:00:30 +0200372 bitvec_set_uint(&bv, bts->si2q_index, 4);
Max59a1bf32016-04-15 16:04:46 +0200373 /* SI2quater_COUNT */
Maxf39d03a2017-05-12 17:00:30 +0200374 bitvec_set_uint(&bv, bts->si2q_count, 4);
Max59a1bf32016-04-15 16:04:46 +0200375
376 /* No Measurement_Parameters Description */
377 bitvec_set_bit(&bv, 0);
378 /* No GPRS_Real Time Difference Description */
379 bitvec_set_bit(&bv, 0);
380 /* No GPRS_BSIC Description */
381 bitvec_set_bit(&bv, 0);
382 /* No GPRS_REPORT PRIORITY Description */
383 bitvec_set_bit(&bv, 0);
384 /* No GPRS_MEASUREMENT_Parameters Description */
385 bitvec_set_bit(&bv, 0);
386 /* No NC Measurement Parameters */
387 bitvec_set_bit(&bv, 0);
388 /* No extension (length) */
389 bitvec_set_bit(&bv, 0);
390
Max70fdd242017-06-15 15:10:53 +0200391 rc = SI2Q_MAX_LEN - (bv.cur_bit + 3);
392 if (rc > 0 && bts->si_common.uarfcn_length - bts->u_offset > 0) {
393 rc = append_uarfcns(&bv, bts, rc);
Max881064e2016-12-14 14:51:40 +0100394 if (rc < 0) {
Max70fdd242017-06-15 15:10:53 +0200395 LOGP(DRR, LOGL_ERROR, "SI2quater [%u/%u]: failed to append %zu UARFCNs due to range encoding "
396 "failure: %s\n",
397 bts->si2q_index, bts->si2q_count, bts->si_common.uarfcn_length, strerror(-rc));
Max881064e2016-12-14 14:51:40 +0100398 return rc;
399 }
Max70fdd242017-06-15 15:10:53 +0200400 } else /* No 3G Neighbour Cell Description */
Max59a1bf32016-04-15 16:04:46 +0200401 bitvec_set_bit(&bv, 0);
Max59a1bf32016-04-15 16:04:46 +0200402
403 /* No 3G Measurement Parameters Description */
404 bitvec_set_bit(&bv, 0);
405 /* No GPRS_3G_MEASUREMENT Parameters Descr. */
406 bitvec_set_bit(&bv, 0);
407
Max70fdd242017-06-15 15:10:53 +0200408 rc = SI2Q_MAX_LEN - bv.cur_bit;
409 if (rc > 0 && si2q_earfcn_count(&bts->si_common.si2quater_neigh_list) - bts->e_offset > 0)
410 append_earfcn(&bv, bts, rc);
411 else /* No Additions in Rel-5: */
Max59a1bf32016-04-15 16:04:46 +0200412 bitvec_set_bit(&bv, L);
Max59a1bf32016-04-15 16:04:46 +0200413
414 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
415 return bv.data_len;
416}
417
Harald Weltea43f7892009-12-01 18:04:30 +0530418/* Append selection parameters to bitvec */
419static void append_selection_params(struct bitvec *bv,
420 const struct gsm48_si_selection_params *sp)
421{
422 if (sp->present) {
423 bitvec_set_bit(bv, H);
424 bitvec_set_bit(bv, sp->cbq);
425 bitvec_set_uint(bv, sp->cell_resel_off, 6);
426 bitvec_set_uint(bv, sp->temp_offs, 3);
427 bitvec_set_uint(bv, sp->penalty_time, 5);
428 } else
429 bitvec_set_bit(bv, L);
430}
431
432/* Append power offset to bitvec */
433static void append_power_offset(struct bitvec *bv,
434 const struct gsm48_si_power_offset *po)
435{
436 if (po->present) {
437 bitvec_set_bit(bv, H);
438 bitvec_set_uint(bv, po->power_offset, 2);
439 } else
440 bitvec_set_bit(bv, L);
441}
442
443/* Append GPRS indicator to bitvec */
444static void append_gprs_ind(struct bitvec *bv,
445 const struct gsm48_si3_gprs_ind *gi)
446{
447 if (gi->present) {
448 bitvec_set_bit(bv, H);
449 bitvec_set_uint(bv, gi->ra_colour, 3);
450 /* 0 == SI13 in BCCH Norm, 1 == SI13 sent on BCCH Ext */
451 bitvec_set_bit(bv, gi->si13_position);
452 } else
453 bitvec_set_bit(bv, L);
454}
455
456
457/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200458int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3)
Harald Weltea43f7892009-12-01 18:04:30 +0530459{
460 struct bitvec bv;
461
462 memset(&bv, 0, sizeof(bv));
463 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +0100464 bv.data_len = 4;
Harald Weltea43f7892009-12-01 18:04:30 +0530465
466 /* Optional Selection Parameters */
467 append_selection_params(&bv, &si3->selection_params);
468
469 /* Optional Power Offset */
470 append_power_offset(&bv, &si3->power_offset);
471
472 /* Do we have a SI2ter on the BCCH? */
473 if (si3->si2ter_indicator)
474 bitvec_set_bit(&bv, H);
475 else
476 bitvec_set_bit(&bv, L);
477
478 /* Early Classmark Sending Control */
479 if (si3->early_cm_ctrl)
480 bitvec_set_bit(&bv, H);
481 else
482 bitvec_set_bit(&bv, L);
483
484 /* Do we have a SI Type 9 on the BCCH? */
485 if (si3->scheduling.present) {
486 bitvec_set_bit(&bv, H);
487 bitvec_set_uint(&bv, si3->scheduling.where, 3);
488 } else
489 bitvec_set_bit(&bv, L);
490
491 /* GPRS Indicator */
492 append_gprs_ind(&bv, &si3->gprs_ind);
493
Maxf3f35052016-04-15 16:04:44 +0200494 /* 3G Early Classmark Sending Restriction controlled by
495 * early_cm_ctrl above */
496 bitvec_set_bit(&bv, H);
497
498 if (si3->si2quater_indicator) {
499 bitvec_set_bit(&bv, H); /* indicator struct present */
500 bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */
501 }
502
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100503 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
504 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530505}
506
507static int append_lsa_params(struct bitvec *bv,
508 const struct gsm48_lsa_params *lsa_params)
509{
510 /* FIXME */
Holger Hans Peter Freytherae80f922010-04-10 00:05:16 +0200511 return -1;
Harald Weltea43f7892009-12-01 18:04:30 +0530512}
513
514/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
Holger Hans Peter Freyther7ff77ec2010-12-29 23:06:22 +0100515int rest_octets_si4(uint8_t *data, const struct gsm48_si_ro_info *si4, int len)
Harald Weltea43f7892009-12-01 18:04:30 +0530516{
517 struct bitvec bv;
518
519 memset(&bv, 0, sizeof(bv));
520 bv.data = data;
Holger Hans Peter Freyther7ff77ec2010-12-29 23:06:22 +0100521 bv.data_len = len;
Harald Weltea43f7892009-12-01 18:04:30 +0530522
523 /* SI4 Rest Octets O */
524 append_selection_params(&bv, &si4->selection_params);
525 append_power_offset(&bv, &si4->power_offset);
526 append_gprs_ind(&bv, &si4->gprs_ind);
527
528 if (0 /* FIXME */) {
529 /* H and SI4 Rest Octets S */
530 bitvec_set_bit(&bv, H);
531
532 /* LSA Parameters */
533 if (si4->lsa_params.present) {
534 bitvec_set_bit(&bv, H);
535 append_lsa_params(&bv, &si4->lsa_params);
536 } else
537 bitvec_set_bit(&bv, L);
538
539 /* Cell Identity */
540 if (1) {
541 bitvec_set_bit(&bv, H);
542 bitvec_set_uint(&bv, si4->cell_id, 16);
543 } else
544 bitvec_set_bit(&bv, L);
545
546 /* LSA ID Information */
547 if (0) {
548 bitvec_set_bit(&bv, H);
549 /* FIXME */
550 } else
551 bitvec_set_bit(&bv, L);
552 } else {
553 /* L and break indicator */
554 bitvec_set_bit(&bv, L);
555 bitvec_set_bit(&bv, si4->break_ind ? H : L);
556 }
557
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100558 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530559}
560
Holger Hans Peter Freyther82dd9832016-05-17 23:20:03 +0200561
562/* GSM 04.18 ETSI TS 101 503 V8.27.0 (2006-05)
563
564<SI6 rest octets> ::=
565{L | H <PCH and NCH info>}
566{L | H <VBS/VGCS options : bit(2)>}
567{ < DTM_support : bit == L > I < DTM_support : bit == H >
568< RAC : bit (8) >
569< MAX_LAPDm : bit (3) > }
570< Band indicator >
571{ L | H < GPRS_MS_TXPWR_MAX_CCH : bit (5) > }
572<implicit spare >;
573*/
574int rest_octets_si6(uint8_t *data, bool is1800_net)
575{
576 struct bitvec bv;
577
578 memset(&bv, 0, sizeof(bv));
579 bv.data = data;
580 bv.data_len = 1;
581
582 /* no PCH/NCH info */
583 bitvec_set_bit(&bv, L);
584 /* no VBS/VGCS options */
585 bitvec_set_bit(&bv, L);
586 /* no DTM_support */
587 bitvec_set_bit(&bv, L);
588 /* band indicator */
589 if (is1800_net)
590 bitvec_set_bit(&bv, L);
591 else
592 bitvec_set_bit(&bv, H);
593 /* no GPRS_MS_TXPWR_MAX_CCH */
594 bitvec_set_bit(&bv, L);
595
596 bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
597 return bv.data_len;
598}
599
Harald Weltea43f7892009-12-01 18:04:30 +0530600/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
601 < GPRS Mobile Allocation IE > ::=
602 < HSN : bit (6) >
603 { 0 | 1 < RFL number list : < RFL number list struct > > }
604 { 0 < MA_LENGTH : bit (6) >
605 < MA_BITMAP: bit (val(MA_LENGTH) + 1) >
606 | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;
607
608 < RFL number list struct > :: =
609 < RFL_NUMBER : bit (4) >
610 { 0 | 1 < RFL number list struct > } ;
611 < ARFCN index list struct > ::=
612 < ARFCN_INDEX : bit(6) >
613 { 0 | 1 < ARFCN index list struct > } ;
614 */
615static int append_gprs_mobile_alloc(struct bitvec *bv)
616{
617 /* Hopping Sequence Number */
618 bitvec_set_uint(bv, 0, 6);
619
620 if (0) {
621 /* We want to use a RFL number list */
622 bitvec_set_bit(bv, 1);
623 /* FIXME: RFL number list */
624 } else
625 bitvec_set_bit(bv, 0);
626
627 if (0) {
628 /* We want to use a MA_BITMAP */
629 bitvec_set_bit(bv, 0);
630 /* FIXME: MA_LENGTH, MA_BITMAP, ... */
631 } else {
632 bitvec_set_bit(bv, 1);
633 if (0) {
634 /* We want to provide an ARFCN index list */
635 bitvec_set_bit(bv, 1);
636 /* FIXME */
637 } else
638 bitvec_set_bit(bv, 0);
639 }
640 return 0;
641}
642
643static int encode_t3192(unsigned int t3192)
644{
Philipp Maier3d6cb332016-12-20 14:23:45 +0100645 /* See also 3GPP TS 44.060
646 Table 12.24.2: GPRS Cell Options information element details */
Harald Weltea43f7892009-12-01 18:04:30 +0530647 if (t3192 == 0)
648 return 3;
649 else if (t3192 <= 80)
650 return 4;
651 else if (t3192 <= 120)
652 return 5;
653 else if (t3192 <= 160)
654 return 6;
655 else if (t3192 <= 200)
656 return 7;
657 else if (t3192 <= 500)
658 return 0;
659 else if (t3192 <= 1000)
660 return 1;
661 else if (t3192 <= 1500)
662 return 2;
663 else
664 return -EINVAL;
665}
666
667static int encode_drx_timer(unsigned int drx)
668{
669 if (drx == 0)
670 return 0;
671 else if (drx == 1)
672 return 1;
673 else if (drx == 2)
674 return 2;
675 else if (drx <= 4)
676 return 3;
677 else if (drx <= 8)
678 return 4;
679 else if (drx <= 16)
680 return 5;
681 else if (drx <= 32)
682 return 6;
683 else if (drx <= 64)
684 return 7;
685 else
686 return -EINVAL;
687}
688
689/* GPRS Cell Options as per TS 04.60 Chapter 12.24
690 < GPRS Cell Options IE > ::=
691 < NMO : bit(2) >
692 < T3168 : bit(3) >
693 < T3192 : bit(3) >
694 < DRX_TIMER_MAX: bit(3) >
695 < ACCESS_BURST_TYPE: bit >
696 < CONTROL_ACK_TYPE : bit >
697 < BS_CV_MAX: bit(4) >
698 { 0 | 1 < PAN_DEC : bit(3) >
699 < PAN_INC : bit(3) >
700 < PAN_MAX : bit(3) >
701 { 0 | 1 < Extension Length : bit(6) >
702 < bit (val(Extension Length) + 1
703 & { < Extension Information > ! { bit ** = <no string> } } ;
704 < Extension Information > ::=
705 { 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit >
706 < BEP_PERIOD : bit(4) > }
707 < PFC_FEATURE_MODE : bit >
708 < DTM_SUPPORT : bit >
709 <BSS_PAGING_COORDINATION: bit >
710 <spare bit > ** ;
711 */
Harald Weltea4e2d042009-12-20 17:08:22 +0100712static int append_gprs_cell_opt(struct bitvec *bv,
713 const struct gprs_cell_options *gco)
Harald Weltea43f7892009-12-01 18:04:30 +0530714{
715 int t3192, drx_timer_max;
716
717 t3192 = encode_t3192(gco->t3192);
718 if (t3192 < 0)
719 return t3192;
720
721 drx_timer_max = encode_drx_timer(gco->drx_timer_max);
722 if (drx_timer_max < 0)
723 return drx_timer_max;
724
725 bitvec_set_uint(bv, gco->nmo, 2);
Philipp Maier3d6cb332016-12-20 14:23:45 +0100726
727 /* See also 3GPP TS 44.060
728 Table 12.24.2: GPRS Cell Options information element details */
729 bitvec_set_uint(bv, gco->t3168 / 500 - 1, 3);
730
Harald Weltea43f7892009-12-01 18:04:30 +0530731 bitvec_set_uint(bv, t3192, 3);
732 bitvec_set_uint(bv, drx_timer_max, 3);
733 /* ACCESS_BURST_TYPE: Hard-code 8bit */
734 bitvec_set_bit(bv, 0);
Max292ec582016-07-28 11:55:37 +0200735 /* CONTROL_ACK_TYPE: */
736 bitvec_set_bit(bv, gco->ctrl_ack_type_use_block);
Harald Weltea43f7892009-12-01 18:04:30 +0530737 bitvec_set_uint(bv, gco->bs_cv_max, 4);
738
Harald Weltea4b16652010-05-31 12:54:23 +0200739 if (0) {
740 /* hard-code no PAN_{DEC,INC,MAX} */
741 bitvec_set_bit(bv, 0);
742 } else {
743 /* copied from ip.access BSC protocol trace */
744 bitvec_set_bit(bv, 1);
745 bitvec_set_uint(bv, 1, 3); /* DEC */
746 bitvec_set_uint(bv, 1, 3); /* INC */
747 bitvec_set_uint(bv, 15, 3); /* MAX */
748 }
Harald Weltea43f7892009-12-01 18:04:30 +0530749
Harald Welteda0586a2010-04-18 14:49:05 +0200750 if (!gco->ext_info_present) {
751 /* no extension information */
752 bitvec_set_bit(bv, 0);
753 } else {
754 /* extension information */
755 bitvec_set_bit(bv, 1);
756 if (!gco->ext_info.egprs_supported) {
757 /* 6bit length of extension */
Harald Welte39608dc2010-04-18 22:47:22 +0200758 bitvec_set_uint(bv, (1 + 3)-1, 6);
Harald Welteda0586a2010-04-18 14:49:05 +0200759 /* EGPRS supported in the cell */
760 bitvec_set_bit(bv, 0);
761 } else {
762 /* 6bit length of extension */
Harald Welte39608dc2010-04-18 22:47:22 +0200763 bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);
Harald Welteda0586a2010-04-18 14:49:05 +0200764 /* EGPRS supported in the cell */
765 bitvec_set_bit(bv, 1);
bhargava350533c2016-07-21 11:14:34 +0530766
Harald Welteda0586a2010-04-18 14:49:05 +0200767 /* 1bit EGPRS PACKET CHANNEL REQUEST */
bhargava350533c2016-07-21 11:14:34 +0530768 if (gco->supports_egprs_11bit_rach == 0) {
769 bitvec_set_bit(bv,
770 gco->ext_info.use_egprs_p_ch_req);
771 } else {
772 bitvec_set_bit(bv, 0);
773 }
774
Harald Welteda0586a2010-04-18 14:49:05 +0200775 /* 4bit BEP PERIOD */
776 bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
777 }
778 bitvec_set_bit(bv, gco->ext_info.pfc_supported);
779 bitvec_set_bit(bv, gco->ext_info.dtm_supported);
780 bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
781 }
Harald Weltea43f7892009-12-01 18:04:30 +0530782
783 return 0;
784}
785
786static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
Harald Weltea4e2d042009-12-20 17:08:22 +0100787 const struct gprs_power_ctrl_pars *pcp)
Harald Weltea43f7892009-12-01 18:04:30 +0530788{
789 bitvec_set_uint(bv, pcp->alpha, 4);
790 bitvec_set_uint(bv, pcp->t_avg_w, 5);
791 bitvec_set_uint(bv, pcp->t_avg_t, 5);
792 bitvec_set_uint(bv, pcp->pc_meas_chan, 1);
793 bitvec_set_uint(bv, pcp->n_avg_i, 4);
794}
795
Harald Welte5fda9082010-04-18 22:41:01 +0200796/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200797int rest_octets_si13(uint8_t *data, const struct gsm48_si13_info *si13)
Harald Weltea43f7892009-12-01 18:04:30 +0530798{
799 struct bitvec bv;
800
801 memset(&bv, 0, sizeof(bv));
802 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +0100803 bv.data_len = 20;
Harald Weltea43f7892009-12-01 18:04:30 +0530804
805 if (0) {
806 /* No rest octets */
807 bitvec_set_bit(&bv, L);
808 } else {
809 bitvec_set_bit(&bv, H);
810 bitvec_set_uint(&bv, si13->bcch_change_mark, 3);
811 bitvec_set_uint(&bv, si13->si_change_field, 4);
Harald Welte97a282b2010-03-14 15:37:43 +0800812 if (1) {
Harald Weltea43f7892009-12-01 18:04:30 +0530813 bitvec_set_bit(&bv, 0);
814 } else {
815 bitvec_set_bit(&bv, 1);
816 bitvec_set_uint(&bv, si13->bcch_change_mark, 2);
817 append_gprs_mobile_alloc(&bv);
818 }
819 if (!si13->pbcch_present) {
820 /* PBCCH not present in cell */
821 bitvec_set_bit(&bv, 0);
822 bitvec_set_uint(&bv, si13->no_pbcch.rac, 8);
823 bitvec_set_bit(&bv, si13->no_pbcch.spgc_ccch_sup);
824 bitvec_set_uint(&bv, si13->no_pbcch.prio_acc_thr, 3);
825 bitvec_set_uint(&bv, si13->no_pbcch.net_ctrl_ord, 2);
826 append_gprs_cell_opt(&bv, &si13->cell_opts);
827 append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);
828 } else {
829 /* PBCCH present in cell */
830 bitvec_set_bit(&bv, 1);
831 bitvec_set_uint(&bv, si13->pbcch.psi1_rep_per, 4);
832 /* PBCCH Descripiton */
833 bitvec_set_uint(&bv, si13->pbcch.pb, 4);
834 bitvec_set_uint(&bv, si13->pbcch.tsc, 3);
835 bitvec_set_uint(&bv, si13->pbcch.tn, 3);
836 switch (si13->pbcch.carrier_type) {
837 case PBCCH_BCCH:
838 bitvec_set_bit(&bv, 0);
839 bitvec_set_bit(&bv, 0);
840 break;
841 case PBCCH_ARFCN:
842 bitvec_set_bit(&bv, 0);
843 bitvec_set_bit(&bv, 1);
844 bitvec_set_uint(&bv, si13->pbcch.arfcn, 10);
845 break;
846 case PBCCH_MAIO:
847 bitvec_set_bit(&bv, 1);
848 bitvec_set_uint(&bv, si13->pbcch.maio, 6);
849 break;
850 }
851 }
Harald Welte5fda9082010-04-18 22:41:01 +0200852 /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
853 bitvec_set_bit(&bv, H); /* added Release 99 */
854 /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
855 * was only added in this Release */
856 bitvec_set_bit(&bv, 1);
Harald Weltea43f7892009-12-01 18:04:30 +0530857 }
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100858 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
859 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530860}