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