blob: 039d2c83ad2b4fae8f1e8674265a0ed5d137693f [file] [log] [blame]
Harald Weltea43f7892009-12-01 18:04:30 +05301/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface,
2 * rest octet handling according to
3 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
4
5/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
6 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25#include <string.h>
26#include <stdlib.h>
27#include <errno.h>
28
29#include <openbsc/gsm_data.h>
Harald Weltedfe6c7d2010-02-20 16:24:02 +010030#include <osmocore/bitvec.h>
Harald Weltea43f7892009-12-01 18:04:30 +053031#include <openbsc/rest_octets.h>
32
33/* generate SI1 rest octets */
34int rest_octets_si1(u_int8_t *data, u_int8_t *nch_pos)
35{
36 struct bitvec bv;
37
38 memset(&bv, 0, sizeof(bv));
39 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +010040 bv.data_len = 1;
Harald Weltea43f7892009-12-01 18:04:30 +053041
42 if (nch_pos) {
43 bitvec_set_bit(&bv, H);
44 bitvec_set_uint(&bv, *nch_pos, 5);
45 } else
46 bitvec_set_bit(&bv, L);
47
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +010048 bitvec_spare_padding(&bv, 7);
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +010049 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +053050}
51
52/* Append selection parameters to bitvec */
53static void append_selection_params(struct bitvec *bv,
54 const struct gsm48_si_selection_params *sp)
55{
56 if (sp->present) {
57 bitvec_set_bit(bv, H);
58 bitvec_set_bit(bv, sp->cbq);
59 bitvec_set_uint(bv, sp->cell_resel_off, 6);
60 bitvec_set_uint(bv, sp->temp_offs, 3);
61 bitvec_set_uint(bv, sp->penalty_time, 5);
62 } else
63 bitvec_set_bit(bv, L);
64}
65
66/* Append power offset to bitvec */
67static void append_power_offset(struct bitvec *bv,
68 const struct gsm48_si_power_offset *po)
69{
70 if (po->present) {
71 bitvec_set_bit(bv, H);
72 bitvec_set_uint(bv, po->power_offset, 2);
73 } else
74 bitvec_set_bit(bv, L);
75}
76
77/* Append GPRS indicator to bitvec */
78static void append_gprs_ind(struct bitvec *bv,
79 const struct gsm48_si3_gprs_ind *gi)
80{
81 if (gi->present) {
82 bitvec_set_bit(bv, H);
83 bitvec_set_uint(bv, gi->ra_colour, 3);
84 /* 0 == SI13 in BCCH Norm, 1 == SI13 sent on BCCH Ext */
85 bitvec_set_bit(bv, gi->si13_position);
86 } else
87 bitvec_set_bit(bv, L);
88}
89
90
91/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
92int rest_octets_si3(u_int8_t *data, const struct gsm48_si_ro_info *si3)
93{
94 struct bitvec bv;
95
96 memset(&bv, 0, sizeof(bv));
97 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +010098 bv.data_len = 4;
Harald Weltea43f7892009-12-01 18:04:30 +053099
100 /* Optional Selection Parameters */
101 append_selection_params(&bv, &si3->selection_params);
102
103 /* Optional Power Offset */
104 append_power_offset(&bv, &si3->power_offset);
105
106 /* Do we have a SI2ter on the BCCH? */
107 if (si3->si2ter_indicator)
108 bitvec_set_bit(&bv, H);
109 else
110 bitvec_set_bit(&bv, L);
111
112 /* Early Classmark Sending Control */
113 if (si3->early_cm_ctrl)
114 bitvec_set_bit(&bv, H);
115 else
116 bitvec_set_bit(&bv, L);
117
118 /* Do we have a SI Type 9 on the BCCH? */
119 if (si3->scheduling.present) {
120 bitvec_set_bit(&bv, H);
121 bitvec_set_uint(&bv, si3->scheduling.where, 3);
122 } else
123 bitvec_set_bit(&bv, L);
124
125 /* GPRS Indicator */
126 append_gprs_ind(&bv, &si3->gprs_ind);
127
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100128 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
129 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530130}
131
132static int append_lsa_params(struct bitvec *bv,
133 const struct gsm48_lsa_params *lsa_params)
134{
135 /* FIXME */
Holger Hans Peter Freytherae80f922010-04-10 00:05:16 +0200136 return -1;
Harald Weltea43f7892009-12-01 18:04:30 +0530137}
138
139/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
140int rest_octets_si4(u_int8_t *data, const struct gsm48_si_ro_info *si4)
141{
142 struct bitvec bv;
143
144 memset(&bv, 0, sizeof(bv));
145 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +0100146 bv.data_len = 10; /* FIXME: up to ? */
Harald Weltea43f7892009-12-01 18:04:30 +0530147
148 /* SI4 Rest Octets O */
149 append_selection_params(&bv, &si4->selection_params);
150 append_power_offset(&bv, &si4->power_offset);
151 append_gprs_ind(&bv, &si4->gprs_ind);
152
153 if (0 /* FIXME */) {
154 /* H and SI4 Rest Octets S */
155 bitvec_set_bit(&bv, H);
156
157 /* LSA Parameters */
158 if (si4->lsa_params.present) {
159 bitvec_set_bit(&bv, H);
160 append_lsa_params(&bv, &si4->lsa_params);
161 } else
162 bitvec_set_bit(&bv, L);
163
164 /* Cell Identity */
165 if (1) {
166 bitvec_set_bit(&bv, H);
167 bitvec_set_uint(&bv, si4->cell_id, 16);
168 } else
169 bitvec_set_bit(&bv, L);
170
171 /* LSA ID Information */
172 if (0) {
173 bitvec_set_bit(&bv, H);
174 /* FIXME */
175 } else
176 bitvec_set_bit(&bv, L);
177 } else {
178 /* L and break indicator */
179 bitvec_set_bit(&bv, L);
180 bitvec_set_bit(&bv, si4->break_ind ? H : L);
181 }
182
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100183 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530184}
185
186/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
187 < GPRS Mobile Allocation IE > ::=
188 < HSN : bit (6) >
189 { 0 | 1 < RFL number list : < RFL number list struct > > }
190 { 0 < MA_LENGTH : bit (6) >
191 < MA_BITMAP: bit (val(MA_LENGTH) + 1) >
192 | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;
193
194 < RFL number list struct > :: =
195 < RFL_NUMBER : bit (4) >
196 { 0 | 1 < RFL number list struct > } ;
197 < ARFCN index list struct > ::=
198 < ARFCN_INDEX : bit(6) >
199 { 0 | 1 < ARFCN index list struct > } ;
200 */
201static int append_gprs_mobile_alloc(struct bitvec *bv)
202{
203 /* Hopping Sequence Number */
204 bitvec_set_uint(bv, 0, 6);
205
206 if (0) {
207 /* We want to use a RFL number list */
208 bitvec_set_bit(bv, 1);
209 /* FIXME: RFL number list */
210 } else
211 bitvec_set_bit(bv, 0);
212
213 if (0) {
214 /* We want to use a MA_BITMAP */
215 bitvec_set_bit(bv, 0);
216 /* FIXME: MA_LENGTH, MA_BITMAP, ... */
217 } else {
218 bitvec_set_bit(bv, 1);
219 if (0) {
220 /* We want to provide an ARFCN index list */
221 bitvec_set_bit(bv, 1);
222 /* FIXME */
223 } else
224 bitvec_set_bit(bv, 0);
225 }
226 return 0;
227}
228
229static int encode_t3192(unsigned int t3192)
230{
231 if (t3192 == 0)
232 return 3;
233 else if (t3192 <= 80)
234 return 4;
235 else if (t3192 <= 120)
236 return 5;
237 else if (t3192 <= 160)
238 return 6;
239 else if (t3192 <= 200)
240 return 7;
241 else if (t3192 <= 500)
242 return 0;
243 else if (t3192 <= 1000)
244 return 1;
245 else if (t3192 <= 1500)
246 return 2;
247 else
248 return -EINVAL;
249}
250
251static int encode_drx_timer(unsigned int drx)
252{
253 if (drx == 0)
254 return 0;
255 else if (drx == 1)
256 return 1;
257 else if (drx == 2)
258 return 2;
259 else if (drx <= 4)
260 return 3;
261 else if (drx <= 8)
262 return 4;
263 else if (drx <= 16)
264 return 5;
265 else if (drx <= 32)
266 return 6;
267 else if (drx <= 64)
268 return 7;
269 else
270 return -EINVAL;
271}
272
273/* GPRS Cell Options as per TS 04.60 Chapter 12.24
274 < GPRS Cell Options IE > ::=
275 < NMO : bit(2) >
276 < T3168 : bit(3) >
277 < T3192 : bit(3) >
278 < DRX_TIMER_MAX: bit(3) >
279 < ACCESS_BURST_TYPE: bit >
280 < CONTROL_ACK_TYPE : bit >
281 < BS_CV_MAX: bit(4) >
282 { 0 | 1 < PAN_DEC : bit(3) >
283 < PAN_INC : bit(3) >
284 < PAN_MAX : bit(3) >
285 { 0 | 1 < Extension Length : bit(6) >
286 < bit (val(Extension Length) + 1
287 & { < Extension Information > ! { bit ** = <no string> } } ;
288 < Extension Information > ::=
289 { 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit >
290 < BEP_PERIOD : bit(4) > }
291 < PFC_FEATURE_MODE : bit >
292 < DTM_SUPPORT : bit >
293 <BSS_PAGING_COORDINATION: bit >
294 <spare bit > ** ;
295 */
Harald Weltea4e2d042009-12-20 17:08:22 +0100296static int append_gprs_cell_opt(struct bitvec *bv,
297 const struct gprs_cell_options *gco)
Harald Weltea43f7892009-12-01 18:04:30 +0530298{
299 int t3192, drx_timer_max;
300
301 t3192 = encode_t3192(gco->t3192);
302 if (t3192 < 0)
303 return t3192;
304
305 drx_timer_max = encode_drx_timer(gco->drx_timer_max);
306 if (drx_timer_max < 0)
307 return drx_timer_max;
308
309 bitvec_set_uint(bv, gco->nmo, 2);
310 bitvec_set_uint(bv, gco->t3168 / 500, 3);
311 bitvec_set_uint(bv, t3192, 3);
312 bitvec_set_uint(bv, drx_timer_max, 3);
313 /* ACCESS_BURST_TYPE: Hard-code 8bit */
314 bitvec_set_bit(bv, 0);
315 /* CONTROL_ACK_TYPE: Hard-code to RLC/MAC control block */
316 bitvec_set_bit(bv, 1);
317 bitvec_set_uint(bv, gco->bs_cv_max, 4);
318
319 /* hard-code no PAN_{DEC,INC,MAX} */
320 bitvec_set_bit(bv, 0);
321
Harald Welteda0586a2010-04-18 14:49:05 +0200322 if (!gco->ext_info_present) {
323 /* no extension information */
324 bitvec_set_bit(bv, 0);
325 } else {
326 /* extension information */
327 bitvec_set_bit(bv, 1);
328 if (!gco->ext_info.egprs_supported) {
329 /* 6bit length of extension */
Harald Welte39608dc2010-04-18 22:47:22 +0200330 bitvec_set_uint(bv, (1 + 3)-1, 6);
Harald Welteda0586a2010-04-18 14:49:05 +0200331 /* EGPRS supported in the cell */
332 bitvec_set_bit(bv, 0);
333 } else {
334 /* 6bit length of extension */
Harald Welte39608dc2010-04-18 22:47:22 +0200335 bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);
Harald Welteda0586a2010-04-18 14:49:05 +0200336 /* EGPRS supported in the cell */
337 bitvec_set_bit(bv, 1);
338 /* 1bit EGPRS PACKET CHANNEL REQUEST */
339 bitvec_set_bit(bv, gco->ext_info.use_egprs_p_ch_req);
340 /* 4bit BEP PERIOD */
341 bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
342 }
343 bitvec_set_bit(bv, gco->ext_info.pfc_supported);
344 bitvec_set_bit(bv, gco->ext_info.dtm_supported);
345 bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
346 }
Harald Weltea43f7892009-12-01 18:04:30 +0530347
348 return 0;
349}
350
351static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
Harald Weltea4e2d042009-12-20 17:08:22 +0100352 const struct gprs_power_ctrl_pars *pcp)
Harald Weltea43f7892009-12-01 18:04:30 +0530353{
354 bitvec_set_uint(bv, pcp->alpha, 4);
355 bitvec_set_uint(bv, pcp->t_avg_w, 5);
356 bitvec_set_uint(bv, pcp->t_avg_t, 5);
357 bitvec_set_uint(bv, pcp->pc_meas_chan, 1);
358 bitvec_set_uint(bv, pcp->n_avg_i, 4);
359}
360
Harald Welte5fda9082010-04-18 22:41:01 +0200361/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
Harald Weltea43f7892009-12-01 18:04:30 +0530362int rest_octets_si13(u_int8_t *data, const struct gsm48_si13_info *si13)
363{
364 struct bitvec bv;
365
366 memset(&bv, 0, sizeof(bv));
367 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +0100368 bv.data_len = 20;
Harald Weltea43f7892009-12-01 18:04:30 +0530369
370 if (0) {
371 /* No rest octets */
372 bitvec_set_bit(&bv, L);
373 } else {
374 bitvec_set_bit(&bv, H);
375 bitvec_set_uint(&bv, si13->bcch_change_mark, 3);
376 bitvec_set_uint(&bv, si13->si_change_field, 4);
Harald Welte97a282b2010-03-14 15:37:43 +0800377 if (1) {
Harald Weltea43f7892009-12-01 18:04:30 +0530378 bitvec_set_bit(&bv, 0);
379 } else {
380 bitvec_set_bit(&bv, 1);
381 bitvec_set_uint(&bv, si13->bcch_change_mark, 2);
382 append_gprs_mobile_alloc(&bv);
383 }
384 if (!si13->pbcch_present) {
385 /* PBCCH not present in cell */
386 bitvec_set_bit(&bv, 0);
387 bitvec_set_uint(&bv, si13->no_pbcch.rac, 8);
388 bitvec_set_bit(&bv, si13->no_pbcch.spgc_ccch_sup);
389 bitvec_set_uint(&bv, si13->no_pbcch.prio_acc_thr, 3);
390 bitvec_set_uint(&bv, si13->no_pbcch.net_ctrl_ord, 2);
391 append_gprs_cell_opt(&bv, &si13->cell_opts);
392 append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);
393 } else {
394 /* PBCCH present in cell */
395 bitvec_set_bit(&bv, 1);
396 bitvec_set_uint(&bv, si13->pbcch.psi1_rep_per, 4);
397 /* PBCCH Descripiton */
398 bitvec_set_uint(&bv, si13->pbcch.pb, 4);
399 bitvec_set_uint(&bv, si13->pbcch.tsc, 3);
400 bitvec_set_uint(&bv, si13->pbcch.tn, 3);
401 switch (si13->pbcch.carrier_type) {
402 case PBCCH_BCCH:
403 bitvec_set_bit(&bv, 0);
404 bitvec_set_bit(&bv, 0);
405 break;
406 case PBCCH_ARFCN:
407 bitvec_set_bit(&bv, 0);
408 bitvec_set_bit(&bv, 1);
409 bitvec_set_uint(&bv, si13->pbcch.arfcn, 10);
410 break;
411 case PBCCH_MAIO:
412 bitvec_set_bit(&bv, 1);
413 bitvec_set_uint(&bv, si13->pbcch.maio, 6);
414 break;
415 }
416 }
Harald Welte5fda9082010-04-18 22:41:01 +0200417 /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
418 bitvec_set_bit(&bv, H); /* added Release 99 */
419 /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
420 * was only added in this Release */
421 bitvec_set_bit(&bv, 1);
Harald Weltea43f7892009-12-01 18:04:30 +0530422 }
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100423 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
424 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530425}