blob: 60a8219b22a96d35ff303baf421c3226beab2c68 [file] [log] [blame]
Harald Weltea54a2bb2009-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>
26#include <sys/types.h>
27#include <netinet/in.h>
28
29#include <openbsc/gsm_04_08.h>
30#include <openbsc/gsm_data.h>
31#include <openbsc/abis_rsl.h>
32#include <openbsc/rest_octets.h>
33
34#define GSM48_CELL_CHAN_DESC_SIZE 16
35#define GSM_MACBLOCK_LEN 23
36#define GSM_MACBLOCK_PADDING 0x2b
37
Harald Weltebc479662009-12-14 20:25:05 +010038/* Frequency Lists as per TS 04.08 10.5.2.13 */
39
40/* 10.5.2.13.2: Bit map 0 format */
Harald Weltea54a2bb2009-12-01 18:04:30 +053041static int cchan_list_bm0_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
42{
43 unsigned int byte, bit;
44
Harald Weltebc479662009-12-14 20:25:05 +010045 if (arfcn > 124 || arfcn < 1)
Harald Weltea54a2bb2009-12-01 18:04:30 +053046 return -EINVAL;
47
Harald Weltebc479662009-12-14 20:25:05 +010048 /* the bitmask is from 1..124, not from 0..123 */
49 arfcn--;
50
Harald Weltea54a2bb2009-12-01 18:04:30 +053051 byte = arfcn / 8;
52 bit = arfcn % 8;
53
Harald Weltebc479662009-12-14 20:25:05 +010054 chan_list[GSM48_CELL_CHAN_DESC_SIZE-1-byte] |= (1 << bit);
Harald Weltea54a2bb2009-12-01 18:04:30 +053055
56 return 0;
57}
58
Harald Weltebc479662009-12-14 20:25:05 +010059/* 10.5.2.13.7: Variable bit map format */
Harald Weltea54a2bb2009-12-01 18:04:30 +053060static int cchan_list_bmrel_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
61{
62 unsigned int byte, bit;
63 unsigned int min_arfcn;
64 unsigned int bitno;
65
66 min_arfcn = (chan_list[0] & 1) << 9;
67 min_arfcn |= chan_list[1] << 1;
68 min_arfcn |= (chan_list[2] >> 7) & 1;
69
70 /* The lower end of our bitmaks is always implicitly included */
71 if (arfcn == min_arfcn)
72 return 0;
73
74 if (arfcn < min_arfcn)
75 return -EINVAL;
76 if (arfcn > min_arfcn + 111)
77 return -EINVAL;
78
79 bitno = (arfcn - min_arfcn);
80 byte = bitno / 8;
81 bit = bitno % 8;
82
83 chan_list[2 + byte] |= 1 << (7 - bit);
84
85 return 0;
86}
87
88/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
89static int generate_cell_chan_list(u_int8_t *chan_list, const struct gsm_bts *bts)
90{
91 struct gsm_bts_trx *trx;
92 int rc, min = 1024, max = 0;
93
94 memset(chan_list, 0, 16);
95
96 /* GSM900-only handsets only support 'bit map 0 format' */
97 if (bts->band == GSM_BAND_900) {
98 chan_list[0] = 0;
99 llist_for_each_entry(trx, &bts->trx_list, list) {
100 rc = cchan_list_bm0_set_arfcn(chan_list, trx->arfcn);
101 if (rc < 0)
102 return rc;
103 }
104 return 0;
105 }
106
107 /* We currently only support the 'Variable bitmap format' */
108 chan_list[0] = 0x8e;
109
110 llist_for_each_entry(trx, &bts->trx_list, list) {
111 if (trx->arfcn < min)
112 min = trx->arfcn;
113 if (trx->arfcn > max)
114 max = trx->arfcn;
115 }
116
117 if ((max - min) > 111)
118 return -EINVAL;
119
120 chan_list[0] |= (min >> 9) & 1;
121 chan_list[1] = (min >> 1);
122 chan_list[2] = (min & 1) << 7;
123
124 llist_for_each_entry(trx, &bts->trx_list, list) {
125 rc = cchan_list_bmrel_set_arfcn(chan_list, trx->arfcn);
126 if (rc < 0)
127 return rc;
128 }
129
130 return 0;
131}
132
133/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
134static int generate_bcch_chan_list(u_int8_t *chan_list, const struct gsm_bts *bts)
135{
136 struct gsm_bts *cur_bts;
137 struct gsm_bts_trx *trx;
138 int rc, min = 1024, max = 0;
139
140 memset(chan_list, 0, 16);
141
142 /* GSM900-only handsets only support 'bit map 0 format' */
143 if (bts->band == GSM_BAND_900) {
144 chan_list[0] = 0;
145 llist_for_each_entry(cur_bts, &bts->list, list) {
Harald Welte5b8d7d32009-12-05 11:58:24 +0530146 if (&cur_bts->list == &bts->network->bts_list)
147 continue;
Harald Weltea54a2bb2009-12-01 18:04:30 +0530148 trx = cur_bts->c0;
149 rc = cchan_list_bm0_set_arfcn(chan_list, trx->arfcn);
150 if (rc < 0)
151 return rc;
152 }
153 return 0;
154 }
155
156 /* We currently only support the 'Variable bitmap format' */
157 chan_list[0] = 0x8e;
158
159 llist_for_each_entry(cur_bts, &bts->list, list) {
160 if (&cur_bts->list == &bts->network->bts_list)
161 continue;
162 trx = cur_bts->c0;
163 if (trx->arfcn < min)
164 min = trx->arfcn;
165 if (trx->arfcn > max)
166 max = trx->arfcn;
167 }
168
169 if ((max - min) > 111)
170 return -EINVAL;
171
172 chan_list[0] |= (min >> 9) & 1;
173 chan_list[1] = (min >> 1);
174 chan_list[2] = (min & 1) << 7;
175
176 llist_for_each_entry(cur_bts, &bts->list, list) {
177 if (&cur_bts->list == &bts->network->bts_list)
178 continue;
179 trx = cur_bts->c0;
180 rc = cchan_list_bmrel_set_arfcn(chan_list, trx->arfcn);
181 if (rc < 0)
182 return rc;
183 }
184
185 return 0;
186}
187
188static int generate_si1(u_int8_t *output, const struct gsm_bts *bts)
189{
190 int rc;
191 struct gsm48_system_information_type_1 *si1 =
192 (struct gsm48_system_information_type_1 *) output;
193
194 memset(si1, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
195
196 si1->header.l2_plen = (21 << 2) | 1;
197 si1->header.rr_protocol_discriminator = GSM48_PDISC_RR;
198 si1->header.skip_indicator = 0;
199 si1->header.system_information = GSM48_MT_RR_SYSINFO_1;
200
201 rc = generate_cell_chan_list(si1->cell_channel_description, bts);
202 if (rc < 0)
203 return rc;
204
205 si1->rach_control = bts->si_common.rach_control;
206
207 /* SI1 Rest Octets (10.5.2.32), contains NCH position */
208 rest_octets_si1(si1->rest_octets, NULL);
209
210 return GSM_MACBLOCK_LEN;
211}
212
213static int generate_si2(u_int8_t *output, const struct gsm_bts *bts)
214{
215 int rc;
216 struct gsm48_system_information_type_2 *si2 =
217 (struct gsm48_system_information_type_2 *) output;
218
219 memset(si2, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
220
221 si2->header.l2_plen = (22 << 2) | 1;
222 si2->header.rr_protocol_discriminator = GSM48_PDISC_RR;
223 si2->header.skip_indicator = 0;
224 si2->header.system_information = GSM48_MT_RR_SYSINFO_2;
225
226 rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts);
227 if (rc < 0)
228 return rc;
229
230 si2->ncc_permitted = bts->si_common.ncc_permitted;
231 si2->rach_control = bts->si_common.rach_control;
232
233 return GSM_MACBLOCK_LEN;
234}
235
236struct gsm48_si_ro_info si_info = {
237 .selection_params = {
238 .present = 0,
239 },
240 .power_offset = {
241 .present = 0,
242 },
243 .si2ter_indicator = 0,
244 .early_cm_ctrl = 1,
245 .scheduling = {
246 .present = 0,
247 },
248 .gprs_ind = {
249 .si13_position = 0,
250 .ra_colour = 0,
251 .present = 0,
252 },
253 .lsa_params = {
254 .present = 0,
255 },
256 .cell_id = 0, /* FIXME: doesn't the bts have this? */
257 .break_ind = 0,
258};
259
260static int generate_si3(u_int8_t *output, const struct gsm_bts *bts)
261{
262 struct gsm48_system_information_type_3 *si3 =
263 (struct gsm48_system_information_type_3 *) output;
264
265 memset(si3, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
266
267 si3->header.l2_plen = (18 << 2) | 1;
268 si3->header.rr_protocol_discriminator = GSM48_PDISC_RR;
269 si3->header.skip_indicator = 0;
270 si3->header.system_information = GSM48_MT_RR_SYSINFO_3;
271
272 si3->cell_identity = htons(bts->cell_identity);
273 gsm0408_generate_lai(&si3->lai, bts->network->country_code,
274 bts->network->network_code,
275 bts->location_area_code);
276 si3->control_channel_desc = bts->si_common.chan_desc;
277 si3->cell_options = bts->si_common.cell_options;
278 si3->cell_sel_par = bts->si_common.cell_sel_par;
279 si3->rach_control = bts->si_common.rach_control;
280
281 /* SI3 Rest Octets (10.5.2.34), containing
282 CBQ, CELL_RESELECT_OFFSET, TEMPORARY_OFFSET, PENALTY_TIME
283 Power Offset, 2ter Indicator, Early Classmark Sending,
284 Scheduling if and WHERE, GPRS Indicator, SI13 position */
285 rest_octets_si3(si3->rest_octets, &si_info);
286
287 return GSM_MACBLOCK_LEN;
288}
289
290static int generate_si4(u_int8_t *output, const struct gsm_bts *bts)
291{
292 struct gsm48_system_information_type_4 *si4 =
293 (struct gsm48_system_information_type_4 *) output;
294
295 /* length of all IEs present except SI4 rest octets and l2_plen */
296 int l2_plen = sizeof(*si4) - 1;
297
298 memset(si4, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
299
300 si4->header.rr_protocol_discriminator = GSM48_PDISC_RR;
301 si4->header.skip_indicator = 0;
302 si4->header.system_information = GSM48_MT_RR_SYSINFO_4;
303
304 gsm0408_generate_lai(&si4->lai, bts->network->country_code,
305 bts->network->network_code,
306 bts->location_area_code);
307 si4->cell_sel_par = bts->si_common.cell_sel_par;
308 si4->rach_control = bts->si_common.rach_control;
309
310 /* Optional: CBCH Channel Description + CBCH Mobile Allocation */
311
312 si4->header.l2_plen = (l2_plen << 2) | 1;
313
314 /* SI4 Rest Octets (10.5.2.35), containing
315 Optional Power offset, GPRS Indicator,
316 Cell Identity, LSA ID, Selection Parameter */
317 rest_octets_si4(si4->data, &si_info);
318
319 return GSM_MACBLOCK_LEN;
320}
321
322static int generate_si5(u_int8_t *output, const struct gsm_bts *bts)
323{
324 struct gsm48_system_information_type_5 *si5 =
325 (struct gsm48_system_information_type_5 *) output;
326 int rc;
327
328 memset(si5, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
329
330 /* l2 pseudo length, not part of msg: 18 */
331 si5->rr_protocol_discriminator = GSM48_PDISC_RR;
332 si5->skip_indicator = 0;
333 si5->system_information = GSM48_MT_RR_SYSINFO_5;
334 rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts);
335 if (rc < 0)
336 return rc;
337
338 /* 04.08 9.1.37: L2 Pseudo Length of 18 */
339 return 18;
340}
341
342static int generate_si6(u_int8_t *output, const struct gsm_bts *bts)
343{
344 struct gsm48_system_information_type_6 *si6 =
345 (struct gsm48_system_information_type_6 *) output;
346
347 memset(si6, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
348
349 /* l2 pseudo length, not part of msg: 11 */
350 si6->rr_protocol_discriminator = GSM48_PDISC_RR;
351 si6->skip_indicator = 0;
352 si6->system_information = GSM48_MT_RR_SYSINFO_6;
353 si6->cell_identity = htons(bts->cell_identity);
354 gsm0408_generate_lai(&si6->lai, bts->network->country_code,
355 bts->network->network_code,
356 bts->location_area_code);
357 si6->cell_options = bts->si_common.cell_options;
358 si6->ncc_permitted = bts->si_common.ncc_permitted;
359
360 /* SI6 Rest Octets: 10.5.2.35a: PCH / NCH info, VBS/VGCS options */
361
362 return 18;
363}
364
365static struct gsm48_si13_info si13_default = {
366 .cell_opts = {
367 .nmo = GPRS_NMO_III,
368 .t3168 = 1000,
369 .t3192 = 1000,
370 .drx_timer_max = 1,
371 .bs_cv_max = 15,
372 },
373 .pwr_ctrl_pars = {
374 .alpha = 10, /* a = 1.0 */
375 .t_avg_w = 25,
376 .t_avg_t = 25,
377 .pc_meas_chan = 0, /* downling measured on CCCH */
378 .n_avg_i = 15,
379 },
380 .bcch_change_mark = 0,
381 .si_change_field = 0,
382 .pbcch_present = 0,
383 {
384 .no_pbcch = {
385 .rac = 0,
386 .spgc_ccch_sup = 0,
387 .net_ctrl_ord = 0,
388 .prio_acc_thr = 0,
389 },
390 },
391};
392
393static int generate_si13(u_int8_t *output, const struct gsm_bts *bts)
394{
395 struct gsm48_system_information_type_13 *si13 =
396 (struct gsm48_system_information_type_13 *) output;
397 int ret;
398
399 memset(si13, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
400
401 si13->header.rr_protocol_discriminator = GSM48_PDISC_RR;
402 si13->header.skip_indicator = 0;
403 si13->header.system_information = GSM48_MT_RR_SYSINFO_13;
404
405 ret = rest_octets_si13(si13->rest_octets, &si13_default);
406 if (ret < 0)
407 return ret;
408
409 si13->header.l2_plen = ret & 0xff;
410
411 return GSM_MACBLOCK_LEN;
412}
413
414int gsm_generate_si(u_int8_t *output, struct gsm_bts *bts, int type)
415{
416 switch (type) {
417 case RSL_SYSTEM_INFO_1:
418 return generate_si1(output, bts);
419 case RSL_SYSTEM_INFO_2:
420 return generate_si2(output, bts);
421 case RSL_SYSTEM_INFO_3:
422 return generate_si3(output, bts);
423 case RSL_SYSTEM_INFO_4:
424 return generate_si4(output, bts);
425 case RSL_SYSTEM_INFO_5:
426 return generate_si5(output, bts);
427 case RSL_SYSTEM_INFO_6:
428 return generate_si6(output, bts);
429 case RSL_SYSTEM_INFO_13:
430 return generate_si13(output, bts);
431 default:
432 return -EINVAL;
433 }
434
435 return 0;
436}