blob: 08c4fd18addcd0ce8992966dcf857d6273c6ea77 [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
Harald Welte7401ae62010-06-15 16:44:12 +02004/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
Harald Weltea43f7892009-12-01 18:04:30 +05305 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01009 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
Harald Weltea43f7892009-12-01 18:04:30 +053011 * (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
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * GNU Affero General Public License for more details.
Harald Weltea43f7892009-12-01 18:04:30 +053017 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010018 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Weltea43f7892009-12-01 18:04:30 +053020 *
21 */
22
23#include <errno.h>
24#include <string.h>
Harald Welte6c40def2009-12-14 22:07:14 +010025#include <stdio.h>
Harald Weltea43f7892009-12-01 18:04:30 +053026#include <netinet/in.h>
27
Harald Welte80cffaf2011-05-24 15:02:20 +020028#include <osmocom/core/bitvec.h>
29#include <osmocom/core/utils.h>
30#include <osmocom/gsm/sysinfo.h>
31
32#include <openbsc/debug.h>
Harald Weltea43f7892009-12-01 18:04:30 +053033#include <openbsc/gsm_04_08.h>
34#include <openbsc/gsm_data.h>
35#include <openbsc/abis_rsl.h>
36#include <openbsc/rest_octets.h>
37
Holger Hans Peter Freytherb91a1062010-01-06 06:38:14 +010038
Harald Welteda760d32009-12-14 20:25:05 +010039/* Frequency Lists as per TS 04.08 10.5.2.13 */
40
41/* 10.5.2.13.2: Bit map 0 format */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020042static int freq_list_bm0_set_arfcn(uint8_t *chan_list, unsigned int arfcn)
Harald Weltea43f7892009-12-01 18:04:30 +053043{
44 unsigned int byte, bit;
45
Harald Welteb1d4c8e2009-12-17 23:10:46 +010046 if (arfcn > 124 || arfcn < 1) {
47 LOGP(DRR, LOGL_ERROR, "Bitmap 0 only supports ARFCN 1...124\n");
Harald Weltea43f7892009-12-01 18:04:30 +053048 return -EINVAL;
Harald Welteb1d4c8e2009-12-17 23:10:46 +010049 }
Harald Weltea43f7892009-12-01 18:04:30 +053050
Harald Welteda760d32009-12-14 20:25:05 +010051 /* the bitmask is from 1..124, not from 0..123 */
52 arfcn--;
53
Harald Weltea43f7892009-12-01 18:04:30 +053054 byte = arfcn / 8;
55 bit = arfcn % 8;
56
Harald Welteda760d32009-12-14 20:25:05 +010057 chan_list[GSM48_CELL_CHAN_DESC_SIZE-1-byte] |= (1 << bit);
Harald Weltea43f7892009-12-01 18:04:30 +053058
59 return 0;
60}
61
Harald Welteda760d32009-12-14 20:25:05 +010062/* 10.5.2.13.7: Variable bit map format */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020063static int freq_list_bmrel_set_arfcn(uint8_t *chan_list, unsigned int arfcn)
Harald Weltea43f7892009-12-01 18:04:30 +053064{
65 unsigned int byte, bit;
66 unsigned int min_arfcn;
67 unsigned int bitno;
68
69 min_arfcn = (chan_list[0] & 1) << 9;
70 min_arfcn |= chan_list[1] << 1;
71 min_arfcn |= (chan_list[2] >> 7) & 1;
72
73 /* The lower end of our bitmaks is always implicitly included */
74 if (arfcn == min_arfcn)
75 return 0;
76
Andreas Eversbergc50543b2012-02-29 09:04:07 +010077 if (((arfcn - min_arfcn) & 1023) > 111) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +010078 LOGP(DRR, LOGL_ERROR, "arfcn(%u) > min(%u) + 111\n", arfcn, min_arfcn);
Harald Weltea43f7892009-12-01 18:04:30 +053079 return -EINVAL;
Harald Welte152b6262009-12-16 11:57:48 +010080 }
Harald Weltea43f7892009-12-01 18:04:30 +053081
Andreas Eversbergc50543b2012-02-29 09:04:07 +010082 bitno = (arfcn - min_arfcn) & 1023;
Harald Weltea43f7892009-12-01 18:04:30 +053083 byte = bitno / 8;
84 bit = bitno % 8;
85
86 chan_list[2 + byte] |= 1 << (7 - bit);
87
88 return 0;
89}
90
91/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020092static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv,
Andreas Eversbergc50543b2012-02-29 09:04:07 +010093 const struct gsm_bts *bts, int bis, int ter)
Harald Weltea43f7892009-12-01 18:04:30 +053094{
Andreas Eversbergc50543b2012-02-29 09:04:07 +010095 int i, rc, min = -1, max = -1, pgsm = 0;
Harald Weltea43f7892009-12-01 18:04:30 +053096
97 memset(chan_list, 0, 16);
98
Harald Welte29350342012-02-17 15:58:23 +010099 if (bts->band == GSM_BAND_900
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100100 && bts->c0->arfcn >= 1 && bts->c0->arfcn <= 124)
101 pgsm = 1;
102 /* P-GSM-only handsets only support 'bit map 0 format' */
103 if (!bis && !ter && pgsm) {
Harald Weltea43f7892009-12-01 18:04:30 +0530104 chan_list[0] = 0;
Harald Welte6c40def2009-12-14 22:07:14 +0100105
106 for (i = 0; i < bv->data_len*8; i++) {
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100107 if (i >= 1 && i <= 124
108 && bitvec_get_bit_pos(bv, i)) {
Harald Welte6c40def2009-12-14 22:07:14 +0100109 rc = freq_list_bm0_set_arfcn(chan_list, i);
110 if (rc < 0)
111 return rc;
112 }
Harald Weltea43f7892009-12-01 18:04:30 +0530113 }
114 return 0;
115 }
116
117 /* We currently only support the 'Variable bitmap format' */
118 chan_list[0] = 0x8e;
119
Harald Welte6c40def2009-12-14 22:07:14 +0100120 for (i = 0; i < bv->data_len*8; i++) {
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100121 /* in case of SI2 or SI5 allow all neighbours in same band
122 * in case of SI*bis, allow neighbours in same band ouside pgsm
123 * in case of SI*ter, allow neighbours in different bands
124 */
125 if (bitvec_get_bit_pos(bv, i)
126 && ((!bis && !ter && gsm_arfcn2band(i) == bts->band)
127 || (bis && pgsm && gsm_arfcn2band(i) == bts->band && (i < 1 || i > 124))
128 || (ter && gsm_arfcn2band(i) != bts->band))) {
129 /* 955..1023 < 0..885 */
130 if (min < 0)
Harald Welte6c40def2009-12-14 22:07:14 +0100131 min = i;
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100132 if (i >= 955 && min < 955)
133 min = i;
134 if (i >= 955 && min >= 955 && i < min)
135 min = i;
136 if (i < 955 && min < 955 && i < min)
137 min = i;
138 if (max < 0)
139 max = i;
140 if (i < 955 && max >= 955)
141 max = i;
142 if (i >= 955 && max >= 955 && i > max)
143 max = i;
144 if (i < 955 && max < 955 && i > max)
Harald Welte6c40def2009-12-14 22:07:14 +0100145 max = i;
146 }
Harald Weltea43f7892009-12-01 18:04:30 +0530147 }
148
Sylvain Munaut42a56522009-12-24 14:20:19 +0100149 if (max == -1) {
150 /* Empty set, use 'bit map 0 format' */
151 chan_list[0] = 0;
152 return 0;
153 }
154
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100155 if (((max - min) & 1023) > 111) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100156 LOGP(DRR, LOGL_ERROR, "min_arfcn=%u, max_arfcn=%u, "
157 "distance > 111\n", min, max);
Harald Weltea43f7892009-12-01 18:04:30 +0530158 return -EINVAL;
Harald Welte152b6262009-12-16 11:57:48 +0100159 }
Harald Weltea43f7892009-12-01 18:04:30 +0530160
161 chan_list[0] |= (min >> 9) & 1;
162 chan_list[1] = (min >> 1);
163 chan_list[2] = (min & 1) << 7;
164
Harald Welte6c40def2009-12-14 22:07:14 +0100165 for (i = 0; i < bv->data_len*8; i++) {
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100166 /* see notes above */
167 if (bitvec_get_bit_pos(bv, i)
168 && ((!bis && !ter && gsm_arfcn2band(i) == bts->band)
169 || (bis && pgsm && gsm_arfcn2band(i) == bts->band && (i < 1 || i > 124))
170 || (ter && gsm_arfcn2band(i) != bts->band))) {
Harald Welte152b6262009-12-16 11:57:48 +0100171 rc = freq_list_bmrel_set_arfcn(chan_list, i);
172 if (rc < 0)
173 return rc;
174 }
Harald Weltea43f7892009-12-01 18:04:30 +0530175 }
176
177 return 0;
178}
179
180/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
Dieter Spaar16646022011-07-28 00:01:50 +0200181/* static*/ int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530182{
Harald Weltea43f7892009-12-01 18:04:30 +0530183 struct gsm_bts_trx *trx;
Harald Welte6c40def2009-12-14 22:07:14 +0100184 struct bitvec *bv = &bts->si_common.cell_alloc;
Harald Weltea43f7892009-12-01 18:04:30 +0530185
Harald Weltea39b0f22010-06-14 22:26:10 +0200186 /* Zero-initialize the bit-vector */
Harald Weltec8794b52010-06-16 11:09:18 +0200187 memset(bv->data, 0, bv->data_len);
Harald Weltea39b0f22010-06-14 22:26:10 +0200188
Harald Welte6c40def2009-12-14 22:07:14 +0100189 /* first we generate a bitvec of all TRX ARFCN's in our BTS */
Harald Weltea39b0f22010-06-14 22:26:10 +0200190 llist_for_each_entry(trx, &bts->trx_list, list) {
191 unsigned int i, j;
192 /* Always add the TRX's ARFCN */
Harald Welte6c40def2009-12-14 22:07:14 +0100193 bitvec_set_bit_pos(bv, trx->arfcn, 1);
Harald Weltea39b0f22010-06-14 22:26:10 +0200194 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
195 struct gsm_bts_trx_ts *ts = &trx->ts[i];
196 /* Add any ARFCNs present in hopping channels */
197 for (j = 0; j < 1024; j++) {
198 if (bitvec_get_bit_pos(&ts->hopping.arfcns, j))
199 bitvec_set_bit_pos(bv, j, 1);
200 }
201 }
202 }
Harald Weltea43f7892009-12-01 18:04:30 +0530203
Harald Welte6c40def2009-12-14 22:07:14 +0100204 /* then we generate a GSM 04.08 frequency list from the bitvec */
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100205 return bitvec2freq_list(chan_list, bv, bts, 0, 0);
Harald Weltea43f7892009-12-01 18:04:30 +0530206}
207
Harald Welte6c40def2009-12-14 22:07:14 +0100208/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100209static int generate_bcch_chan_list(uint8_t *chan_list, struct gsm_bts *bts,
210 int si5, int bis, int ter)
Harald Welte6c40def2009-12-14 22:07:14 +0100211{
212 struct gsm_bts *cur_bts;
Harald Welte64c07d22011-02-15 11:43:27 +0100213 struct bitvec *bv;
214
215 if (si5 && bts->neigh_list_manual_mode == NL_MODE_MANUAL_SI5SEP)
216 bv = &bts->si_common.si5_neigh_list;
217 else
218 bv = &bts->si_common.neigh_list;
Harald Welte6c40def2009-12-14 22:07:14 +0100219
Harald Welte32c09622011-01-11 23:44:56 +0100220 /* Generate list of neighbor cells if we are in automatic mode */
Harald Welte64c07d22011-02-15 11:43:27 +0100221 if (bts->neigh_list_manual_mode == NL_MODE_AUTOMATIC) {
Harald Welte21bbda22011-02-19 20:43:37 +0100222 /* Zero-initialize the bit-vector */
223 memset(bv->data, 0, bv->data_len);
224
Harald Welte32c09622011-01-11 23:44:56 +0100225 /* first we generate a bitvec of the BCCH ARFCN's in our BSC */
226 llist_for_each_entry(cur_bts, &bts->network->bts_list, list) {
227 if (cur_bts == bts)
228 continue;
229 bitvec_set_bit_pos(bv, cur_bts->c0->arfcn, 1);
230 }
Harald Welte6c40def2009-12-14 22:07:14 +0100231 }
232
233 /* then we generate a GSM 04.08 frequency list from the bitvec */
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100234 return bitvec2freq_list(chan_list, bv, bts, bis, ter);
235}
236
237static int list_arfcn(uint8_t *chan_list, uint8_t mask, char *text)
238{
239 int n = 0, i;
240 struct gsm_sysinfo_freq freq[1024];
241
242 memset(freq, 0, sizeof(freq));
243 gsm48_decode_freq_list(freq, chan_list, 16, 0xce, 1);
244 for (i = 0; i < 1024; i++) {
245 if (freq[i].mask) {
246 if (!n)
247 LOGP(DRR, LOGL_INFO, "%s", text);
248 LOGPC(DRR, LOGL_INFO, " %d", i);
249 n++;
250 }
251 }
252 if (n)
253 LOGPC(DRR, LOGL_INFO, "\n");
254
255 return n;
Harald Welte6c40def2009-12-14 22:07:14 +0100256}
257
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200258static int generate_si1(uint8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530259{
260 int rc;
261 struct gsm48_system_information_type_1 *si1 =
262 (struct gsm48_system_information_type_1 *) output;
263
264 memset(si1, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
265
266 si1->header.l2_plen = (21 << 2) | 1;
267 si1->header.rr_protocol_discriminator = GSM48_PDISC_RR;
268 si1->header.skip_indicator = 0;
269 si1->header.system_information = GSM48_MT_RR_SYSINFO_1;
270
271 rc = generate_cell_chan_list(si1->cell_channel_description, bts);
272 if (rc < 0)
273 return rc;
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100274 list_arfcn(si1->cell_channel_description, 0xce, "Serving cell:");
Harald Weltea43f7892009-12-01 18:04:30 +0530275
276 si1->rach_control = bts->si_common.rach_control;
277
278 /* SI1 Rest Octets (10.5.2.32), contains NCH position */
Holger Hans Peter Freyther7ec448d2010-01-06 07:52:31 +0100279 rc = rest_octets_si1(si1->rest_octets, NULL);
Harald Welte7401ae62010-06-15 16:44:12 +0200280
Holger Hans Peter Freyther7ec448d2010-01-06 07:52:31 +0100281 return sizeof(*si1) + rc;
Harald Weltea43f7892009-12-01 18:04:30 +0530282}
283
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200284static int generate_si2(uint8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530285{
286 int rc;
287 struct gsm48_system_information_type_2 *si2 =
288 (struct gsm48_system_information_type_2 *) output;
289
290 memset(si2, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
291
292 si2->header.l2_plen = (22 << 2) | 1;
293 si2->header.rr_protocol_discriminator = GSM48_PDISC_RR;
294 si2->header.skip_indicator = 0;
295 si2->header.system_information = GSM48_MT_RR_SYSINFO_2;
296
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100297 rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts, 0, 0, 0);
Harald Weltea43f7892009-12-01 18:04:30 +0530298 if (rc < 0)
299 return rc;
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100300 list_arfcn(si2->bcch_frequency_list, 0xce,
301 "Neighbour cells in same band:");
Harald Weltea43f7892009-12-01 18:04:30 +0530302
303 si2->ncc_permitted = bts->si_common.ncc_permitted;
304 si2->rach_control = bts->si_common.rach_control;
305
Holger Hans Peter Freyther7ec448d2010-01-06 07:52:31 +0100306 return sizeof(*si2);
Harald Weltea43f7892009-12-01 18:04:30 +0530307}
308
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100309static int generate_si2bis(uint8_t *output, struct gsm_bts *bts)
310{
311 int rc;
312 struct gsm48_system_information_type_2bis *si2b =
313 (struct gsm48_system_information_type_2bis *) output;
314 int n;
315
316 memset(si2b, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
317
318 si2b->header.l2_plen = (22 << 2) | 1;
319 si2b->header.rr_protocol_discriminator = GSM48_PDISC_RR;
320 si2b->header.skip_indicator = 0;
321 si2b->header.system_information = GSM48_MT_RR_SYSINFO_2bis;
322
323 rc = generate_bcch_chan_list(si2b->bcch_frequency_list, bts, 0, 1, 0);
324 if (rc < 0)
325 return rc;
326 n = list_arfcn(si2b->bcch_frequency_list, 0xce,
327 "Neighbour cells in same band, but outside P-GSM:");
328 if (n) {
329 /* indicate in SI2 and SI2bis: there is an extension */
330 struct gsm48_system_information_type_2 *si2 =
331 (struct gsm48_system_information_type_2 *)
332 bts->si_buf[SYSINFO_TYPE_2];
333 si2->bcch_frequency_list[0] |= 0x20;
334 si2b->bcch_frequency_list[0] |= 0x20;
335 } else
336 bts->si_valid &= ~(1 << SYSINFO_TYPE_2bis);
337
338 si2b->rach_control = bts->si_common.rach_control;
339
340 return sizeof(*si2b);
341}
342
343static int generate_si2ter(uint8_t *output, struct gsm_bts *bts)
344{
345 int rc;
346 struct gsm48_system_information_type_2ter *si2t =
347 (struct gsm48_system_information_type_2ter *) output;
348 int n;
349
350 memset(si2t, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
351
352 si2t->header.l2_plen = (22 << 2) | 1;
353 si2t->header.rr_protocol_discriminator = GSM48_PDISC_RR;
354 si2t->header.skip_indicator = 0;
355 si2t->header.system_information = GSM48_MT_RR_SYSINFO_2ter;
356
357 rc = generate_bcch_chan_list(si2t->ext_bcch_frequency_list, bts, 0, 0, 1);
358 if (rc < 0)
359 return rc;
360 n = list_arfcn(si2t->ext_bcch_frequency_list, 0x8e,
361 "Neighbour cells in different band:");
362 if (!n)
363 bts->si_valid &= ~(1 << SYSINFO_TYPE_2ter);
364
365 return sizeof(*si2t);
366}
367
Harald Welte1f893292010-03-14 23:46:48 +0800368static struct gsm48_si_ro_info si_info = {
Harald Weltea43f7892009-12-01 18:04:30 +0530369 .selection_params = {
370 .present = 0,
371 },
372 .power_offset = {
373 .present = 0,
374 },
375 .si2ter_indicator = 0,
376 .early_cm_ctrl = 1,
377 .scheduling = {
378 .present = 0,
379 },
380 .gprs_ind = {
381 .si13_position = 0,
382 .ra_colour = 0,
Harald Welte97a282b2010-03-14 15:37:43 +0800383 .present = 1,
Harald Weltea43f7892009-12-01 18:04:30 +0530384 },
385 .lsa_params = {
386 .present = 0,
387 },
388 .cell_id = 0, /* FIXME: doesn't the bts have this? */
389 .break_ind = 0,
390};
391
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200392static int generate_si3(uint8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530393{
Holger Hans Peter Freyther7ec448d2010-01-06 07:52:31 +0100394 int rc;
Harald Weltea43f7892009-12-01 18:04:30 +0530395 struct gsm48_system_information_type_3 *si3 =
396 (struct gsm48_system_information_type_3 *) output;
397
398 memset(si3, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
399
400 si3->header.l2_plen = (18 << 2) | 1;
401 si3->header.rr_protocol_discriminator = GSM48_PDISC_RR;
402 si3->header.skip_indicator = 0;
403 si3->header.system_information = GSM48_MT_RR_SYSINFO_3;
404
405 si3->cell_identity = htons(bts->cell_identity);
Harald Welteafedeab2010-03-04 10:55:40 +0100406 gsm48_generate_lai(&si3->lai, bts->network->country_code,
407 bts->network->network_code,
408 bts->location_area_code);
Harald Weltea43f7892009-12-01 18:04:30 +0530409 si3->control_channel_desc = bts->si_common.chan_desc;
410 si3->cell_options = bts->si_common.cell_options;
411 si3->cell_sel_par = bts->si_common.cell_sel_par;
412 si3->rach_control = bts->si_common.rach_control;
413
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100414 if ((bts->si_valid & (1 << SYSINFO_TYPE_2ter))) {
415 LOGP(DRR, LOGL_INFO, "SI 2ter is included.\n");
416 si_info.si2ter_indicator = 1;
417 } else {
418 si_info.si2ter_indicator = 0;
419 }
420
Harald Weltea43f7892009-12-01 18:04:30 +0530421 /* SI3 Rest Octets (10.5.2.34), containing
422 CBQ, CELL_RESELECT_OFFSET, TEMPORARY_OFFSET, PENALTY_TIME
423 Power Offset, 2ter Indicator, Early Classmark Sending,
424 Scheduling if and WHERE, GPRS Indicator, SI13 position */
Holger Hans Peter Freyther7ec448d2010-01-06 07:52:31 +0100425 rc = rest_octets_si3(si3->rest_octets, &si_info);
Harald Weltea43f7892009-12-01 18:04:30 +0530426
Holger Hans Peter Freyther7ec448d2010-01-06 07:52:31 +0100427 return sizeof(*si3) + rc;
Harald Weltea43f7892009-12-01 18:04:30 +0530428}
429
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200430static int generate_si4(uint8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530431{
Holger Hans Peter Freyther7ec448d2010-01-06 07:52:31 +0100432 int rc;
Harald Weltea43f7892009-12-01 18:04:30 +0530433 struct gsm48_system_information_type_4 *si4 =
434 (struct gsm48_system_information_type_4 *) output;
435
436 /* length of all IEs present except SI4 rest octets and l2_plen */
437 int l2_plen = sizeof(*si4) - 1;
438
439 memset(si4, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
440
441 si4->header.rr_protocol_discriminator = GSM48_PDISC_RR;
442 si4->header.skip_indicator = 0;
443 si4->header.system_information = GSM48_MT_RR_SYSINFO_4;
444
Harald Welteafedeab2010-03-04 10:55:40 +0100445 gsm48_generate_lai(&si4->lai, bts->network->country_code,
446 bts->network->network_code,
447 bts->location_area_code);
Harald Weltea43f7892009-12-01 18:04:30 +0530448 si4->cell_sel_par = bts->si_common.cell_sel_par;
449 si4->rach_control = bts->si_common.rach_control;
450
451 /* Optional: CBCH Channel Description + CBCH Mobile Allocation */
452
453 si4->header.l2_plen = (l2_plen << 2) | 1;
454
455 /* SI4 Rest Octets (10.5.2.35), containing
456 Optional Power offset, GPRS Indicator,
457 Cell Identity, LSA ID, Selection Parameter */
Holger Hans Peter Freyther7ec448d2010-01-06 07:52:31 +0100458 rc = rest_octets_si4(si4->data, &si_info);
Harald Weltea43f7892009-12-01 18:04:30 +0530459
Holger Hans Peter Freyther7ec448d2010-01-06 07:52:31 +0100460 return sizeof(*si4) + rc;
Harald Weltea43f7892009-12-01 18:04:30 +0530461}
462
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200463static int generate_si5(uint8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530464{
Harald Weltee2d0d5f2009-12-19 21:26:54 +0100465 struct gsm48_system_information_type_5 *si5;
466 int rc, l2_plen = 18;
Harald Weltea43f7892009-12-01 18:04:30 +0530467
Holger Hans Peter Freyther17d81e22010-01-06 07:52:55 +0100468 memset(output, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
469
Harald Weltee2d0d5f2009-12-19 21:26:54 +0100470 /* ip.access nanoBTS needs l2_plen!! */
Harald Weltefd355a32011-03-04 13:41:31 +0100471 switch (bts->type) {
472 case GSM_BTS_TYPE_NANOBTS:
Harald Weltef383aa12012-07-02 19:51:55 +0200473 case GSM_BTS_TYPE_OSMO_SYSMO:
Harald Weltefd355a32011-03-04 13:41:31 +0100474 case GSM_BTS_TYPE_HSL_FEMTO:
Harald Weltee2d0d5f2009-12-19 21:26:54 +0100475 *output++ = (l2_plen << 2) | 1;
476 l2_plen++;
Harald Weltefd355a32011-03-04 13:41:31 +0100477 break;
478 default:
479 break;
Harald Weltee2d0d5f2009-12-19 21:26:54 +0100480 }
481
482 si5 = (struct gsm48_system_information_type_5 *) output;
Harald Weltea43f7892009-12-01 18:04:30 +0530483
484 /* l2 pseudo length, not part of msg: 18 */
485 si5->rr_protocol_discriminator = GSM48_PDISC_RR;
486 si5->skip_indicator = 0;
487 si5->system_information = GSM48_MT_RR_SYSINFO_5;
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100488 rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts, 1, 0, 0);
Harald Weltea43f7892009-12-01 18:04:30 +0530489 if (rc < 0)
490 return rc;
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100491 list_arfcn(si5->bcch_frequency_list, 0xce,
492 "Neighbour cells in same band:");
493
494 /* 04.08 9.1.37: L2 Pseudo Length of 18 */
495 return l2_plen;
496}
497
498static int generate_si5bis(uint8_t *output, struct gsm_bts *bts)
499{
500 struct gsm48_system_information_type_5bis *si5b;
501 int rc, l2_plen = 18;
502 int n;
503
504 memset(output, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
505
506 /* ip.access nanoBTS needs l2_plen!! */
507 switch (bts->type) {
508 case GSM_BTS_TYPE_NANOBTS:
Harald Weltef383aa12012-07-02 19:51:55 +0200509 case GSM_BTS_TYPE_OSMO_SYSMO:
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100510 case GSM_BTS_TYPE_HSL_FEMTO:
511 *output++ = (l2_plen << 2) | 1;
512 l2_plen++;
513 break;
514 default:
515 break;
516 }
517
518 si5b = (struct gsm48_system_information_type_5bis *) output;
519
520 /* l2 pseudo length, not part of msg: 18 */
521 si5b->rr_protocol_discriminator = GSM48_PDISC_RR;
522 si5b->skip_indicator = 0;
523 si5b->system_information = GSM48_MT_RR_SYSINFO_5bis;
524 rc = generate_bcch_chan_list(si5b->bcch_frequency_list, bts, 1, 1, 0);
525 if (rc < 0)
526 return rc;
527 n = list_arfcn(si5b->bcch_frequency_list, 0xce,
528 "Neighbour cells in same band, but outside P-GSM:");
529 if (n) {
530 /* indicate in SI5 and SI5bis: there is an extension */
531 struct gsm48_system_information_type_5 *si5 =
532 (struct gsm48_system_information_type_5 *)
533 bts->si_buf[SYSINFO_TYPE_5];
534 si5->bcch_frequency_list[0] |= 0x20;
535 si5b->bcch_frequency_list[0] |= 0x20;
536 } else
537 bts->si_valid &= ~(1 << SYSINFO_TYPE_5bis);
538
539 /* 04.08 9.1.37: L2 Pseudo Length of 18 */
540 return l2_plen;
541}
542
543static int generate_si5ter(uint8_t *output, struct gsm_bts *bts)
544{
545 struct gsm48_system_information_type_5ter *si5t;
546 int rc, l2_plen = 18;
547 int n;
548
549 memset(output, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
550
551 /* ip.access nanoBTS needs l2_plen!! */
552 switch (bts->type) {
553 case GSM_BTS_TYPE_NANOBTS:
Harald Weltef383aa12012-07-02 19:51:55 +0200554 case GSM_BTS_TYPE_OSMO_SYSMO:
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100555 case GSM_BTS_TYPE_HSL_FEMTO:
556 *output++ = (l2_plen << 2) | 1;
557 l2_plen++;
558 break;
559 default:
560 break;
561 }
562
563 si5t = (struct gsm48_system_information_type_5ter *) output;
564
565 /* l2 pseudo length, not part of msg: 18 */
566 si5t->rr_protocol_discriminator = GSM48_PDISC_RR;
567 si5t->skip_indicator = 0;
568 si5t->system_information = GSM48_MT_RR_SYSINFO_5ter;
569 rc = generate_bcch_chan_list(si5t->bcch_frequency_list, bts, 1, 0, 1);
570 if (rc < 0)
571 return rc;
572 n = list_arfcn(si5t->bcch_frequency_list, 0x8e,
573 "Neighbour cells in different band:");
574 if (!n)
575 bts->si_valid &= ~(1 << SYSINFO_TYPE_5ter);
Harald Weltea43f7892009-12-01 18:04:30 +0530576
577 /* 04.08 9.1.37: L2 Pseudo Length of 18 */
Harald Weltee2d0d5f2009-12-19 21:26:54 +0100578 return l2_plen;
Harald Weltea43f7892009-12-01 18:04:30 +0530579}
580
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200581static int generate_si6(uint8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530582{
Harald Weltee2d0d5f2009-12-19 21:26:54 +0100583 struct gsm48_system_information_type_6 *si6;
584 int l2_plen = 11;
Harald Weltea43f7892009-12-01 18:04:30 +0530585
Holger Hans Peter Freyther17d81e22010-01-06 07:52:55 +0100586 memset(output, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
587
Harald Weltee2d0d5f2009-12-19 21:26:54 +0100588 /* ip.access nanoBTS needs l2_plen!! */
Harald Weltefd355a32011-03-04 13:41:31 +0100589 switch (bts->type) {
590 case GSM_BTS_TYPE_NANOBTS:
Harald Weltef383aa12012-07-02 19:51:55 +0200591 case GSM_BTS_TYPE_OSMO_SYSMO:
Harald Weltefd355a32011-03-04 13:41:31 +0100592 case GSM_BTS_TYPE_HSL_FEMTO:
Harald Weltee2d0d5f2009-12-19 21:26:54 +0100593 *output++ = (l2_plen << 2) | 1;
594 l2_plen++;
Harald Weltefd355a32011-03-04 13:41:31 +0100595 break;
596 default:
597 break;
Harald Weltee2d0d5f2009-12-19 21:26:54 +0100598 }
599
600 si6 = (struct gsm48_system_information_type_6 *) output;
Harald Weltea43f7892009-12-01 18:04:30 +0530601
602 /* l2 pseudo length, not part of msg: 11 */
603 si6->rr_protocol_discriminator = GSM48_PDISC_RR;
604 si6->skip_indicator = 0;
605 si6->system_information = GSM48_MT_RR_SYSINFO_6;
606 si6->cell_identity = htons(bts->cell_identity);
Harald Welteafedeab2010-03-04 10:55:40 +0100607 gsm48_generate_lai(&si6->lai, bts->network->country_code,
608 bts->network->network_code,
609 bts->location_area_code);
Harald Weltea43f7892009-12-01 18:04:30 +0530610 si6->cell_options = bts->si_common.cell_options;
611 si6->ncc_permitted = bts->si_common.ncc_permitted;
612
613 /* SI6 Rest Octets: 10.5.2.35a: PCH / NCH info, VBS/VGCS options */
614
Harald Weltee2d0d5f2009-12-19 21:26:54 +0100615 return l2_plen;
Harald Weltea43f7892009-12-01 18:04:30 +0530616}
617
618static struct gsm48_si13_info si13_default = {
619 .cell_opts = {
Harald Welte85849182010-06-02 12:19:21 +0200620 .nmo = GPRS_NMO_II,
Harald Weltea4b16652010-05-31 12:54:23 +0200621 .t3168 = 2000,
Andreas Eversbergbecc89a2012-09-23 08:14:51 +0200622 .t3192 = 1500,
Harald Welte97a282b2010-03-14 15:37:43 +0800623 .drx_timer_max = 3,
Harald Weltea43f7892009-12-01 18:04:30 +0530624 .bs_cv_max = 15,
Sylvain Munaut851f1202011-10-17 13:56:02 +0200625 .ext_info_present = 0,
Harald Welteda0586a2010-04-18 14:49:05 +0200626 .ext_info = {
627 /* The values below are just guesses ! */
Harald Weltea06fea02010-04-18 15:53:40 +0200628 .egprs_supported = 0,
Harald Welteda0586a2010-04-18 14:49:05 +0200629 .use_egprs_p_ch_req = 1,
Harald Weltea4b16652010-05-31 12:54:23 +0200630 .bep_period = 5,
Harald Welteda0586a2010-04-18 14:49:05 +0200631 .pfc_supported = 0,
632 .dtm_supported = 0,
633 .bss_paging_coordination = 0,
634 },
Harald Weltea43f7892009-12-01 18:04:30 +0530635 },
636 .pwr_ctrl_pars = {
Harald Weltec15d0ac2012-10-08 21:22:08 +0200637 .alpha = 0, /* a = 0.0 */
Harald Weltea4b16652010-05-31 12:54:23 +0200638 .t_avg_w = 16,
639 .t_avg_t = 16,
Harald Weltea43f7892009-12-01 18:04:30 +0530640 .pc_meas_chan = 0, /* downling measured on CCCH */
Harald Weltea4b16652010-05-31 12:54:23 +0200641 .n_avg_i = 8,
Harald Weltea43f7892009-12-01 18:04:30 +0530642 },
Harald Welte97a282b2010-03-14 15:37:43 +0800643 .bcch_change_mark = 1,
Harald Weltea43f7892009-12-01 18:04:30 +0530644 .si_change_field = 0,
645 .pbcch_present = 0,
646 {
647 .no_pbcch = {
Harald Welte97a282b2010-03-14 15:37:43 +0800648 .rac = 0, /* needs to be patched */
Harald Weltea43f7892009-12-01 18:04:30 +0530649 .spgc_ccch_sup = 0,
650 .net_ctrl_ord = 0,
Harald Welte97a282b2010-03-14 15:37:43 +0800651 .prio_acc_thr = 6,
Harald Weltea43f7892009-12-01 18:04:30 +0530652 },
653 },
654};
655
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200656static int generate_si13(uint8_t *output, struct gsm_bts *bts)
Harald Weltea43f7892009-12-01 18:04:30 +0530657{
658 struct gsm48_system_information_type_13 *si13 =
659 (struct gsm48_system_information_type_13 *) output;
660 int ret;
661
662 memset(si13, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
663
664 si13->header.rr_protocol_discriminator = GSM48_PDISC_RR;
665 si13->header.skip_indicator = 0;
666 si13->header.system_information = GSM48_MT_RR_SYSINFO_13;
667
Harald Welte97a282b2010-03-14 15:37:43 +0800668 si13_default.no_pbcch.rac = bts->gprs.rac;
669
Harald Weltea43f7892009-12-01 18:04:30 +0530670 ret = rest_octets_si13(si13->rest_octets, &si13_default);
671 if (ret < 0)
672 return ret;
673
Holger Hans Peter Freyther1c6f3942010-06-16 12:05:56 +0800674 /* length is coded in bit 2 an up */
675 si13->header.l2_plen = 0x01;
Harald Weltea43f7892009-12-01 18:04:30 +0530676
Holger Hans Peter Freyther7ec448d2010-01-06 07:52:31 +0100677 return sizeof (*si13) + ret;
Harald Weltea43f7892009-12-01 18:04:30 +0530678}
679
Harald Welte7401ae62010-06-15 16:44:12 +0200680typedef int (*gen_si_fn_t)(uint8_t *output, struct gsm_bts *bts);
681
682static const gen_si_fn_t gen_si_fn[_MAX_SYSINFO_TYPE] = {
683 [SYSINFO_TYPE_1] = &generate_si1,
684 [SYSINFO_TYPE_2] = &generate_si2,
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100685 [SYSINFO_TYPE_2bis] = &generate_si2bis,
686 [SYSINFO_TYPE_2ter] = &generate_si2ter,
Harald Welte7401ae62010-06-15 16:44:12 +0200687 [SYSINFO_TYPE_3] = &generate_si3,
688 [SYSINFO_TYPE_4] = &generate_si4,
689 [SYSINFO_TYPE_5] = &generate_si5,
Andreas Eversbergc50543b2012-02-29 09:04:07 +0100690 [SYSINFO_TYPE_5bis] = &generate_si5bis,
691 [SYSINFO_TYPE_5ter] = &generate_si5ter,
Harald Welte7401ae62010-06-15 16:44:12 +0200692 [SYSINFO_TYPE_6] = &generate_si6,
693 [SYSINFO_TYPE_13] = &generate_si13,
694};
695
Harald Welte7401ae62010-06-15 16:44:12 +0200696int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type)
697{
698 gen_si_fn_t gen_si;
699
Harald Welte4511d892010-04-18 15:51:20 +0200700 switch (bts->gprs.mode) {
701 case BTS_GPRS_EGPRS:
Harald Weltea06fea02010-04-18 15:53:40 +0200702 si13_default.cell_opts.ext_info_present = 1;
703 si13_default.cell_opts.ext_info.egprs_supported = 1;
704 /* fallthrough */
Harald Welte4511d892010-04-18 15:51:20 +0200705 case BTS_GPRS_GPRS:
706 si_info.gprs_ind.present = 1;
707 break;
708 case BTS_GPRS_NONE:
709 si_info.gprs_ind.present = 0;
710 break;
711 }
Harald Welte1f893292010-03-14 23:46:48 +0800712
Sylvain Munaute0b06b02010-11-28 18:17:28 +0100713 memcpy(&si_info.selection_params,
714 &bts->si_common.cell_ro_sel_par,
715 sizeof(struct gsm48_si_selection_params));
716
Harald Welte7401ae62010-06-15 16:44:12 +0200717 gen_si = gen_si_fn[si_type];
718 if (!gen_si)
Harald Weltea43f7892009-12-01 18:04:30 +0530719 return -EINVAL;
Harald Weltea43f7892009-12-01 18:04:30 +0530720
Harald Welte7401ae62010-06-15 16:44:12 +0200721 return gen_si(bts->si_buf[si_type], bts);
Harald Weltea43f7892009-12-01 18:04:30 +0530722}