blob: 2d4ba20a4e35772be0324d2484c61227fa378fcc [file] [log] [blame]
Harald Weltea43f7892009-12-01 18:04:30 +05301/* GSM 04.08 System Information (SI) encoding and decoding
2 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
3
4/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
5 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24#include <errno.h>
25#include <string.h>
Harald Welte6c40def2009-12-14 22:07:14 +010026#include <stdio.h>
Harald Weltea43f7892009-12-01 18:04:30 +053027#include <sys/types.h>
28#include <netinet/in.h>
29
30#include <openbsc/gsm_04_08.h>
31#include <openbsc/gsm_data.h>
32#include <openbsc/abis_rsl.h>
33#include <openbsc/rest_octets.h>
Harald Welte6c40def2009-12-14 22:07:14 +010034#include <openbsc/bitvec.h>
Harald Weltea43f7892009-12-01 18:04:30 +053035
36#define GSM48_CELL_CHAN_DESC_SIZE 16
37#define GSM_MACBLOCK_LEN 23
38#define GSM_MACBLOCK_PADDING 0x2b
39
Harald Welteda760d32009-12-14 20:25:05 +010040/* Frequency Lists as per TS 04.08 10.5.2.13 */
41
42/* 10.5.2.13.2: Bit map 0 format */
Harald Welte6c40def2009-12-14 22:07:14 +010043static int freq_list_bm0_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
Harald Weltea43f7892009-12-01 18:04:30 +053044{
45 unsigned int byte, bit;
46
Harald Welteda760d32009-12-14 20:25:05 +010047 if (arfcn > 124 || arfcn < 1)
Harald Weltea43f7892009-12-01 18:04:30 +053048 return -EINVAL;
49
Harald Welteda760d32009-12-14 20:25:05 +010050 /* the bitmask is from 1..124, not from 0..123 */
51 arfcn--;
52
Harald Weltea43f7892009-12-01 18:04:30 +053053 byte = arfcn / 8;
54 bit = arfcn % 8;
55
Harald Welteda760d32009-12-14 20:25:05 +010056 chan_list[GSM48_CELL_CHAN_DESC_SIZE-1-byte] |= (1 << bit);
Harald Weltea43f7892009-12-01 18:04:30 +053057
58 return 0;
59}
60
Harald Welteda760d32009-12-14 20:25:05 +010061/* 10.5.2.13.7: Variable bit map format */
Harald Welte6c40def2009-12-14 22:07:14 +010062static int freq_list_bmrel_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
Harald Weltea43f7892009-12-01 18:04:30 +053063{
64 unsigned int byte, bit;
65 unsigned int min_arfcn;
66 unsigned int bitno;
67
68 min_arfcn = (chan_list[0] & 1) << 9;
69 min_arfcn |= chan_list[1] << 1;
70 min_arfcn |= (chan_list[2] >> 7) & 1;
71
72 /* The lower end of our bitmaks is always implicitly included */
73 if (arfcn == min_arfcn)
74 return 0;
75
76 if (arfcn < min_arfcn)
77 return -EINVAL;
78 if (arfcn > min_arfcn + 111)
79 return -EINVAL;
80
81 bitno = (arfcn - min_arfcn);
82 byte = bitno / 8;
83 bit = bitno % 8;
84
85 chan_list[2 + byte] |= 1 << (7 - bit);
86
87 return 0;
88}
89
90/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
Harald Welte6c40def2009-12-14 22:07:14 +010091static int bitvec2freq_list(u_int8_t *chan_list, struct bitvec *bv,
92 const struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +053093{
Harald Welte6c40def2009-12-14 22:07:14 +010094 int i, rc, min = 1024, max = 0;
Harald Weltea43f7892009-12-01 18:04:30 +053095
96 memset(chan_list, 0, 16);
97
98 /* GSM900-only handsets only support 'bit map 0 format' */
99 if (bts->band == GSM_BAND_900) {
100 chan_list[0] = 0;
Harald Welte6c40def2009-12-14 22:07:14 +0100101
102 for (i = 0; i < bv->data_len*8; i++) {
103 if (bitvec_get_bit_pos(bv, i)) {
104 rc = freq_list_bm0_set_arfcn(chan_list, i);
105 if (rc < 0)
106 return rc;
107 }
Harald Weltea43f7892009-12-01 18:04:30 +0530108 }
109 return 0;
110 }
111
112 /* We currently only support the 'Variable bitmap format' */
113 chan_list[0] = 0x8e;
114
Harald Welte6c40def2009-12-14 22:07:14 +0100115 for (i = 0; i < bv->data_len*8; i++) {
116 if (bitvec_get_bit_pos(bv, i)) {
117 if (i < min)
118 min = i;
119 if (i > max)
120 max = i;
121 }
Harald Weltea43f7892009-12-01 18:04:30 +0530122 }
123
124 if ((max - min) > 111)
125 return -EINVAL;
126
127 chan_list[0] |= (min >> 9) & 1;
128 chan_list[1] = (min >> 1);
129 chan_list[2] = (min & 1) << 7;
130
Harald Welte6c40def2009-12-14 22:07:14 +0100131 for (i = 0; i < bv->data_len*8; i++) {
132 rc = freq_list_bmrel_set_arfcn(chan_list, i);
Harald Weltea43f7892009-12-01 18:04:30 +0530133 if (rc < 0)
134 return rc;
135 }
136
137 return 0;
138}
139
140/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
Harald Welte6c40def2009-12-14 22:07:14 +0100141static int generate_cell_chan_list(u_int8_t *chan_list, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530142{
Harald Weltea43f7892009-12-01 18:04:30 +0530143 struct gsm_bts_trx *trx;
Harald Welte6c40def2009-12-14 22:07:14 +0100144 struct bitvec *bv = &bts->si_common.cell_alloc;
Harald Weltea43f7892009-12-01 18:04:30 +0530145
Harald Welte6c40def2009-12-14 22:07:14 +0100146 /* first we generate a bitvec of all TRX ARFCN's in our BTS */
147 llist_for_each_entry(trx, &bts->trx_list, list)
148 bitvec_set_bit_pos(bv, trx->arfcn, 1);
Harald Weltea43f7892009-12-01 18:04:30 +0530149
Harald Welte6c40def2009-12-14 22:07:14 +0100150 /* then we generate a GSM 04.08 frequency list from the bitvec */
151 return bitvec2freq_list(chan_list, bv, bts);
Harald Weltea43f7892009-12-01 18:04:30 +0530152}
153
Harald Welte6c40def2009-12-14 22:07:14 +0100154/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
155static int generate_bcch_chan_list(u_int8_t *chan_list, struct gsm_bts *bts)
156{
157 struct gsm_bts *cur_bts;
158 struct bitvec *bv = &bts->si_common.neigh_list;
159
160 /* first we generate a bitvec of the BCCH ARFCN's in our BSC */
161 llist_for_each_entry(cur_bts, &bts->network->bts_list, list) {
162 if (cur_bts == bts)
163 continue;
164 bitvec_set_bit_pos(bv, cur_bts->c0->arfcn, 1);
165 }
166
167 /* then we generate a GSM 04.08 frequency list from the bitvec */
168 return bitvec2freq_list(chan_list, bv, bts);
169}
170
171static int generate_si1(u_int8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530172{
173 int rc;
174 struct gsm48_system_information_type_1 *si1 =
175 (struct gsm48_system_information_type_1 *) output;
176
177 memset(si1, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
178
179 si1->header.l2_plen = (21 << 2) | 1;
180 si1->header.rr_protocol_discriminator = GSM48_PDISC_RR;
181 si1->header.skip_indicator = 0;
182 si1->header.system_information = GSM48_MT_RR_SYSINFO_1;
183
184 rc = generate_cell_chan_list(si1->cell_channel_description, bts);
185 if (rc < 0)
186 return rc;
187
188 si1->rach_control = bts->si_common.rach_control;
189
190 /* SI1 Rest Octets (10.5.2.32), contains NCH position */
191 rest_octets_si1(si1->rest_octets, NULL);
192
193 return GSM_MACBLOCK_LEN;
194}
195
Harald Welte6c40def2009-12-14 22:07:14 +0100196static int generate_si2(u_int8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530197{
198 int rc;
199 struct gsm48_system_information_type_2 *si2 =
200 (struct gsm48_system_information_type_2 *) output;
201
202 memset(si2, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
203
204 si2->header.l2_plen = (22 << 2) | 1;
205 si2->header.rr_protocol_discriminator = GSM48_PDISC_RR;
206 si2->header.skip_indicator = 0;
207 si2->header.system_information = GSM48_MT_RR_SYSINFO_2;
208
209 rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts);
210 if (rc < 0)
211 return rc;
212
213 si2->ncc_permitted = bts->si_common.ncc_permitted;
214 si2->rach_control = bts->si_common.rach_control;
215
216 return GSM_MACBLOCK_LEN;
217}
218
219struct gsm48_si_ro_info si_info = {
220 .selection_params = {
221 .present = 0,
222 },
223 .power_offset = {
224 .present = 0,
225 },
226 .si2ter_indicator = 0,
227 .early_cm_ctrl = 1,
228 .scheduling = {
229 .present = 0,
230 },
231 .gprs_ind = {
232 .si13_position = 0,
233 .ra_colour = 0,
234 .present = 0,
235 },
236 .lsa_params = {
237 .present = 0,
238 },
239 .cell_id = 0, /* FIXME: doesn't the bts have this? */
240 .break_ind = 0,
241};
242
Harald Welte6c40def2009-12-14 22:07:14 +0100243static int generate_si3(u_int8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530244{
245 struct gsm48_system_information_type_3 *si3 =
246 (struct gsm48_system_information_type_3 *) output;
247
248 memset(si3, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
249
250 si3->header.l2_plen = (18 << 2) | 1;
251 si3->header.rr_protocol_discriminator = GSM48_PDISC_RR;
252 si3->header.skip_indicator = 0;
253 si3->header.system_information = GSM48_MT_RR_SYSINFO_3;
254
255 si3->cell_identity = htons(bts->cell_identity);
256 gsm0408_generate_lai(&si3->lai, bts->network->country_code,
257 bts->network->network_code,
258 bts->location_area_code);
259 si3->control_channel_desc = bts->si_common.chan_desc;
260 si3->cell_options = bts->si_common.cell_options;
261 si3->cell_sel_par = bts->si_common.cell_sel_par;
262 si3->rach_control = bts->si_common.rach_control;
263
264 /* SI3 Rest Octets (10.5.2.34), containing
265 CBQ, CELL_RESELECT_OFFSET, TEMPORARY_OFFSET, PENALTY_TIME
266 Power Offset, 2ter Indicator, Early Classmark Sending,
267 Scheduling if and WHERE, GPRS Indicator, SI13 position */
268 rest_octets_si3(si3->rest_octets, &si_info);
269
270 return GSM_MACBLOCK_LEN;
271}
272
Harald Welte6c40def2009-12-14 22:07:14 +0100273static int generate_si4(u_int8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530274{
275 struct gsm48_system_information_type_4 *si4 =
276 (struct gsm48_system_information_type_4 *) output;
277
278 /* length of all IEs present except SI4 rest octets and l2_plen */
279 int l2_plen = sizeof(*si4) - 1;
280
281 memset(si4, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
282
283 si4->header.rr_protocol_discriminator = GSM48_PDISC_RR;
284 si4->header.skip_indicator = 0;
285 si4->header.system_information = GSM48_MT_RR_SYSINFO_4;
286
287 gsm0408_generate_lai(&si4->lai, bts->network->country_code,
288 bts->network->network_code,
289 bts->location_area_code);
290 si4->cell_sel_par = bts->si_common.cell_sel_par;
291 si4->rach_control = bts->si_common.rach_control;
292
293 /* Optional: CBCH Channel Description + CBCH Mobile Allocation */
294
295 si4->header.l2_plen = (l2_plen << 2) | 1;
296
297 /* SI4 Rest Octets (10.5.2.35), containing
298 Optional Power offset, GPRS Indicator,
299 Cell Identity, LSA ID, Selection Parameter */
300 rest_octets_si4(si4->data, &si_info);
301
302 return GSM_MACBLOCK_LEN;
303}
304
Harald Welte6c40def2009-12-14 22:07:14 +0100305static int generate_si5(u_int8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530306{
307 struct gsm48_system_information_type_5 *si5 =
308 (struct gsm48_system_information_type_5 *) output;
309 int rc;
310
311 memset(si5, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
312
313 /* l2 pseudo length, not part of msg: 18 */
314 si5->rr_protocol_discriminator = GSM48_PDISC_RR;
315 si5->skip_indicator = 0;
316 si5->system_information = GSM48_MT_RR_SYSINFO_5;
317 rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts);
318 if (rc < 0)
319 return rc;
320
321 /* 04.08 9.1.37: L2 Pseudo Length of 18 */
322 return 18;
323}
324
Harald Welte6c40def2009-12-14 22:07:14 +0100325static int generate_si6(u_int8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530326{
327 struct gsm48_system_information_type_6 *si6 =
328 (struct gsm48_system_information_type_6 *) output;
329
330 memset(si6, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
331
332 /* l2 pseudo length, not part of msg: 11 */
333 si6->rr_protocol_discriminator = GSM48_PDISC_RR;
334 si6->skip_indicator = 0;
335 si6->system_information = GSM48_MT_RR_SYSINFO_6;
336 si6->cell_identity = htons(bts->cell_identity);
337 gsm0408_generate_lai(&si6->lai, bts->network->country_code,
338 bts->network->network_code,
339 bts->location_area_code);
340 si6->cell_options = bts->si_common.cell_options;
341 si6->ncc_permitted = bts->si_common.ncc_permitted;
342
343 /* SI6 Rest Octets: 10.5.2.35a: PCH / NCH info, VBS/VGCS options */
344
345 return 18;
346}
347
348static struct gsm48_si13_info si13_default = {
349 .cell_opts = {
350 .nmo = GPRS_NMO_III,
351 .t3168 = 1000,
352 .t3192 = 1000,
353 .drx_timer_max = 1,
354 .bs_cv_max = 15,
355 },
356 .pwr_ctrl_pars = {
357 .alpha = 10, /* a = 1.0 */
358 .t_avg_w = 25,
359 .t_avg_t = 25,
360 .pc_meas_chan = 0, /* downling measured on CCCH */
361 .n_avg_i = 15,
362 },
363 .bcch_change_mark = 0,
364 .si_change_field = 0,
365 .pbcch_present = 0,
366 {
367 .no_pbcch = {
368 .rac = 0,
369 .spgc_ccch_sup = 0,
370 .net_ctrl_ord = 0,
371 .prio_acc_thr = 0,
372 },
373 },
374};
375
Harald Welte6c40def2009-12-14 22:07:14 +0100376static int generate_si13(u_int8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530377{
378 struct gsm48_system_information_type_13 *si13 =
379 (struct gsm48_system_information_type_13 *) output;
380 int ret;
381
382 memset(si13, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
383
384 si13->header.rr_protocol_discriminator = GSM48_PDISC_RR;
385 si13->header.skip_indicator = 0;
386 si13->header.system_information = GSM48_MT_RR_SYSINFO_13;
387
388 ret = rest_octets_si13(si13->rest_octets, &si13_default);
389 if (ret < 0)
390 return ret;
391
392 si13->header.l2_plen = ret & 0xff;
393
394 return GSM_MACBLOCK_LEN;
395}
396
397int gsm_generate_si(u_int8_t *output, struct gsm_bts *bts, int type)
398{
399 switch (type) {
400 case RSL_SYSTEM_INFO_1:
401 return generate_si1(output, bts);
402 case RSL_SYSTEM_INFO_2:
403 return generate_si2(output, bts);
404 case RSL_SYSTEM_INFO_3:
405 return generate_si3(output, bts);
406 case RSL_SYSTEM_INFO_4:
407 return generate_si4(output, bts);
408 case RSL_SYSTEM_INFO_5:
409 return generate_si5(output, bts);
410 case RSL_SYSTEM_INFO_6:
411 return generate_si6(output, bts);
412 case RSL_SYSTEM_INFO_13:
413 return generate_si13(output, bts);
414 default:
415 return -EINVAL;
416 }
417
418 return 0;
419}