blob: d6d166c79133f8a0fa194a74ac5984fbee5ec6a1 [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
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) {
139 trx = cur_bts->c0;
140 rc = cchan_list_bm0_set_arfcn(chan_list, trx->arfcn);
141 if (rc < 0)
142 return rc;
143 }
144 return 0;
145 }
146
147 /* We currently only support the 'Variable bitmap format' */
148 chan_list[0] = 0x8e;
149
150 llist_for_each_entry(cur_bts, &bts->list, list) {
151 if (&cur_bts->list == &bts->network->bts_list)
152 continue;
153 trx = cur_bts->c0;
154 if (trx->arfcn < min)
155 min = trx->arfcn;
156 if (trx->arfcn > max)
157 max = trx->arfcn;
158 }
159
160 if ((max - min) > 111)
161 return -EINVAL;
162
163 chan_list[0] |= (min >> 9) & 1;
164 chan_list[1] = (min >> 1);
165 chan_list[2] = (min & 1) << 7;
166
167 llist_for_each_entry(cur_bts, &bts->list, list) {
168 if (&cur_bts->list == &bts->network->bts_list)
169 continue;
170 trx = cur_bts->c0;
171 rc = cchan_list_bmrel_set_arfcn(chan_list, trx->arfcn);
172 if (rc < 0)
173 return rc;
174 }
175
176 return 0;
177}
178
179static int generate_si1(u_int8_t *output, const struct gsm_bts *bts)
180{
181 int rc;
182 struct gsm48_system_information_type_1 *si1 =
183 (struct gsm48_system_information_type_1 *) output;
184
185 memset(si1, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
186
187 si1->header.l2_plen = (21 << 2) | 1;
188 si1->header.rr_protocol_discriminator = GSM48_PDISC_RR;
189 si1->header.skip_indicator = 0;
190 si1->header.system_information = GSM48_MT_RR_SYSINFO_1;
191
192 rc = generate_cell_chan_list(si1->cell_channel_description, bts);
193 if (rc < 0)
194 return rc;
195
196 si1->rach_control = bts->si_common.rach_control;
197
198 /* SI1 Rest Octets (10.5.2.32), contains NCH position */
199 rest_octets_si1(si1->rest_octets, NULL);
200
201 return GSM_MACBLOCK_LEN;
202}
203
204static int generate_si2(u_int8_t *output, const struct gsm_bts *bts)
205{
206 int rc;
207 struct gsm48_system_information_type_2 *si2 =
208 (struct gsm48_system_information_type_2 *) output;
209
210 memset(si2, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
211
212 si2->header.l2_plen = (22 << 2) | 1;
213 si2->header.rr_protocol_discriminator = GSM48_PDISC_RR;
214 si2->header.skip_indicator = 0;
215 si2->header.system_information = GSM48_MT_RR_SYSINFO_2;
216
217 rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts);
218 if (rc < 0)
219 return rc;
220
221 si2->ncc_permitted = bts->si_common.ncc_permitted;
222 si2->rach_control = bts->si_common.rach_control;
223
224 return GSM_MACBLOCK_LEN;
225}
226
227struct gsm48_si_ro_info si_info = {
228 .selection_params = {
229 .present = 0,
230 },
231 .power_offset = {
232 .present = 0,
233 },
234 .si2ter_indicator = 0,
235 .early_cm_ctrl = 1,
236 .scheduling = {
237 .present = 0,
238 },
239 .gprs_ind = {
240 .si13_position = 0,
241 .ra_colour = 0,
242 .present = 0,
243 },
244 .lsa_params = {
245 .present = 0,
246 },
247 .cell_id = 0, /* FIXME: doesn't the bts have this? */
248 .break_ind = 0,
249};
250
251static int generate_si3(u_int8_t *output, const struct gsm_bts *bts)
252{
253 struct gsm48_system_information_type_3 *si3 =
254 (struct gsm48_system_information_type_3 *) output;
255
256 memset(si3, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
257
258 si3->header.l2_plen = (18 << 2) | 1;
259 si3->header.rr_protocol_discriminator = GSM48_PDISC_RR;
260 si3->header.skip_indicator = 0;
261 si3->header.system_information = GSM48_MT_RR_SYSINFO_3;
262
263 si3->cell_identity = htons(bts->cell_identity);
264 gsm0408_generate_lai(&si3->lai, bts->network->country_code,
265 bts->network->network_code,
266 bts->location_area_code);
267 si3->control_channel_desc = bts->si_common.chan_desc;
268 si3->cell_options = bts->si_common.cell_options;
269 si3->cell_sel_par = bts->si_common.cell_sel_par;
270 si3->rach_control = bts->si_common.rach_control;
271
272 /* SI3 Rest Octets (10.5.2.34), containing
273 CBQ, CELL_RESELECT_OFFSET, TEMPORARY_OFFSET, PENALTY_TIME
274 Power Offset, 2ter Indicator, Early Classmark Sending,
275 Scheduling if and WHERE, GPRS Indicator, SI13 position */
276 rest_octets_si3(si3->rest_octets, &si_info);
277
278 return GSM_MACBLOCK_LEN;
279}
280
281static int generate_si4(u_int8_t *output, const struct gsm_bts *bts)
282{
283 struct gsm48_system_information_type_4 *si4 =
284 (struct gsm48_system_information_type_4 *) output;
285
286 /* length of all IEs present except SI4 rest octets and l2_plen */
287 int l2_plen = sizeof(*si4) - 1;
288
289 memset(si4, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
290
291 si4->header.rr_protocol_discriminator = GSM48_PDISC_RR;
292 si4->header.skip_indicator = 0;
293 si4->header.system_information = GSM48_MT_RR_SYSINFO_4;
294
295 gsm0408_generate_lai(&si4->lai, bts->network->country_code,
296 bts->network->network_code,
297 bts->location_area_code);
298 si4->cell_sel_par = bts->si_common.cell_sel_par;
299 si4->rach_control = bts->si_common.rach_control;
300
301 /* Optional: CBCH Channel Description + CBCH Mobile Allocation */
302
303 si4->header.l2_plen = (l2_plen << 2) | 1;
304
305 /* SI4 Rest Octets (10.5.2.35), containing
306 Optional Power offset, GPRS Indicator,
307 Cell Identity, LSA ID, Selection Parameter */
308 rest_octets_si4(si4->data, &si_info);
309
310 return GSM_MACBLOCK_LEN;
311}
312
313static int generate_si5(u_int8_t *output, const struct gsm_bts *bts)
314{
315 struct gsm48_system_information_type_5 *si5 =
316 (struct gsm48_system_information_type_5 *) output;
317 int rc;
318
319 memset(si5, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
320
321 /* l2 pseudo length, not part of msg: 18 */
322 si5->rr_protocol_discriminator = GSM48_PDISC_RR;
323 si5->skip_indicator = 0;
324 si5->system_information = GSM48_MT_RR_SYSINFO_5;
325 rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts);
326 if (rc < 0)
327 return rc;
328
329 /* 04.08 9.1.37: L2 Pseudo Length of 18 */
330 return 18;
331}
332
333static int generate_si6(u_int8_t *output, const struct gsm_bts *bts)
334{
335 struct gsm48_system_information_type_6 *si6 =
336 (struct gsm48_system_information_type_6 *) output;
337
338 memset(si6, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
339
340 /* l2 pseudo length, not part of msg: 11 */
341 si6->rr_protocol_discriminator = GSM48_PDISC_RR;
342 si6->skip_indicator = 0;
343 si6->system_information = GSM48_MT_RR_SYSINFO_6;
344 si6->cell_identity = htons(bts->cell_identity);
345 gsm0408_generate_lai(&si6->lai, bts->network->country_code,
346 bts->network->network_code,
347 bts->location_area_code);
348 si6->cell_options = bts->si_common.cell_options;
349 si6->ncc_permitted = bts->si_common.ncc_permitted;
350
351 /* SI6 Rest Octets: 10.5.2.35a: PCH / NCH info, VBS/VGCS options */
352
353 return 18;
354}
355
356static struct gsm48_si13_info si13_default = {
357 .cell_opts = {
358 .nmo = GPRS_NMO_III,
359 .t3168 = 1000,
360 .t3192 = 1000,
361 .drx_timer_max = 1,
362 .bs_cv_max = 15,
363 },
364 .pwr_ctrl_pars = {
365 .alpha = 10, /* a = 1.0 */
366 .t_avg_w = 25,
367 .t_avg_t = 25,
368 .pc_meas_chan = 0, /* downling measured on CCCH */
369 .n_avg_i = 15,
370 },
371 .bcch_change_mark = 0,
372 .si_change_field = 0,
373 .pbcch_present = 0,
374 {
375 .no_pbcch = {
376 .rac = 0,
377 .spgc_ccch_sup = 0,
378 .net_ctrl_ord = 0,
379 .prio_acc_thr = 0,
380 },
381 },
382};
383
384static int generate_si13(u_int8_t *output, const struct gsm_bts *bts)
385{
386 struct gsm48_system_information_type_13 *si13 =
387 (struct gsm48_system_information_type_13 *) output;
388 int ret;
389
390 memset(si13, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
391
392 si13->header.rr_protocol_discriminator = GSM48_PDISC_RR;
393 si13->header.skip_indicator = 0;
394 si13->header.system_information = GSM48_MT_RR_SYSINFO_13;
395
396 ret = rest_octets_si13(si13->rest_octets, &si13_default);
397 if (ret < 0)
398 return ret;
399
400 si13->header.l2_plen = ret & 0xff;
401
402 return GSM_MACBLOCK_LEN;
403}
404
405int gsm_generate_si(u_int8_t *output, struct gsm_bts *bts, int type)
406{
407 switch (type) {
408 case RSL_SYSTEM_INFO_1:
409 return generate_si1(output, bts);
410 case RSL_SYSTEM_INFO_2:
411 return generate_si2(output, bts);
412 case RSL_SYSTEM_INFO_3:
413 return generate_si3(output, bts);
414 case RSL_SYSTEM_INFO_4:
415 return generate_si4(output, bts);
416 case RSL_SYSTEM_INFO_5:
417 return generate_si5(output, bts);
418 case RSL_SYSTEM_INFO_6:
419 return generate_si6(output, bts);
420 case RSL_SYSTEM_INFO_13:
421 return generate_si13(output, bts);
422 default:
423 return -EINVAL;
424 }
425
426 return 0;
427}