blob: 084f14498c509a691b2e88575527728902c3bb9a [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
Harald Welte9af6ddf2011-01-01 15:25:50 +010010 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
Harald Weltea43f7892009-12-01 18:04:30 +053012 * (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
Harald Welte9af6ddf2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Harald Weltea43f7892009-12-01 18:04:30 +053018 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010019 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Weltea43f7892009-12-01 18:04:30 +053021 *
22 */
23
24#include <string.h>
25#include <stdlib.h>
26#include <errno.h>
27
28#include <openbsc/gsm_data.h>
Harald Weltedfe6c7d2010-02-20 16:24:02 +010029#include <osmocore/bitvec.h>
Harald Weltea43f7892009-12-01 18:04:30 +053030#include <openbsc/rest_octets.h>
31
32/* generate SI1 rest octets */
33int rest_octets_si1(u_int8_t *data, u_int8_t *nch_pos)
34{
35 struct bitvec bv;
36
37 memset(&bv, 0, sizeof(bv));
38 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +010039 bv.data_len = 1;
Harald Weltea43f7892009-12-01 18:04:30 +053040
41 if (nch_pos) {
42 bitvec_set_bit(&bv, H);
43 bitvec_set_uint(&bv, *nch_pos, 5);
44 } else
45 bitvec_set_bit(&bv, L);
46
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +010047 bitvec_spare_padding(&bv, 7);
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +010048 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +053049}
50
51/* Append selection parameters to bitvec */
52static void append_selection_params(struct bitvec *bv,
53 const struct gsm48_si_selection_params *sp)
54{
55 if (sp->present) {
56 bitvec_set_bit(bv, H);
57 bitvec_set_bit(bv, sp->cbq);
58 bitvec_set_uint(bv, sp->cell_resel_off, 6);
59 bitvec_set_uint(bv, sp->temp_offs, 3);
60 bitvec_set_uint(bv, sp->penalty_time, 5);
61 } else
62 bitvec_set_bit(bv, L);
63}
64
65/* Append power offset to bitvec */
66static void append_power_offset(struct bitvec *bv,
67 const struct gsm48_si_power_offset *po)
68{
69 if (po->present) {
70 bitvec_set_bit(bv, H);
71 bitvec_set_uint(bv, po->power_offset, 2);
72 } else
73 bitvec_set_bit(bv, L);
74}
75
76/* Append GPRS indicator to bitvec */
77static void append_gprs_ind(struct bitvec *bv,
78 const struct gsm48_si3_gprs_ind *gi)
79{
80 if (gi->present) {
81 bitvec_set_bit(bv, H);
82 bitvec_set_uint(bv, gi->ra_colour, 3);
83 /* 0 == SI13 in BCCH Norm, 1 == SI13 sent on BCCH Ext */
84 bitvec_set_bit(bv, gi->si13_position);
85 } else
86 bitvec_set_bit(bv, L);
87}
88
89
90/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
91int rest_octets_si3(u_int8_t *data, const struct gsm48_si_ro_info *si3)
92{
93 struct bitvec bv;
94
95 memset(&bv, 0, sizeof(bv));
96 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +010097 bv.data_len = 4;
Harald Weltea43f7892009-12-01 18:04:30 +053098
99 /* Optional Selection Parameters */
100 append_selection_params(&bv, &si3->selection_params);
101
102 /* Optional Power Offset */
103 append_power_offset(&bv, &si3->power_offset);
104
105 /* Do we have a SI2ter on the BCCH? */
106 if (si3->si2ter_indicator)
107 bitvec_set_bit(&bv, H);
108 else
109 bitvec_set_bit(&bv, L);
110
111 /* Early Classmark Sending Control */
112 if (si3->early_cm_ctrl)
113 bitvec_set_bit(&bv, H);
114 else
115 bitvec_set_bit(&bv, L);
116
117 /* Do we have a SI Type 9 on the BCCH? */
118 if (si3->scheduling.present) {
119 bitvec_set_bit(&bv, H);
120 bitvec_set_uint(&bv, si3->scheduling.where, 3);
121 } else
122 bitvec_set_bit(&bv, L);
123
124 /* GPRS Indicator */
125 append_gprs_ind(&bv, &si3->gprs_ind);
126
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100127 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
128 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530129}
130
131static int append_lsa_params(struct bitvec *bv,
132 const struct gsm48_lsa_params *lsa_params)
133{
134 /* FIXME */
Holger Hans Peter Freytherae80f922010-04-10 00:05:16 +0200135 return -1;
Harald Weltea43f7892009-12-01 18:04:30 +0530136}
137
138/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
139int rest_octets_si4(u_int8_t *data, const struct gsm48_si_ro_info *si4)
140{
141 struct bitvec bv;
142
143 memset(&bv, 0, sizeof(bv));
144 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +0100145 bv.data_len = 10; /* FIXME: up to ? */
Harald Weltea43f7892009-12-01 18:04:30 +0530146
147 /* SI4 Rest Octets O */
148 append_selection_params(&bv, &si4->selection_params);
149 append_power_offset(&bv, &si4->power_offset);
150 append_gprs_ind(&bv, &si4->gprs_ind);
151
152 if (0 /* FIXME */) {
153 /* H and SI4 Rest Octets S */
154 bitvec_set_bit(&bv, H);
155
156 /* LSA Parameters */
157 if (si4->lsa_params.present) {
158 bitvec_set_bit(&bv, H);
159 append_lsa_params(&bv, &si4->lsa_params);
160 } else
161 bitvec_set_bit(&bv, L);
162
163 /* Cell Identity */
164 if (1) {
165 bitvec_set_bit(&bv, H);
166 bitvec_set_uint(&bv, si4->cell_id, 16);
167 } else
168 bitvec_set_bit(&bv, L);
169
170 /* LSA ID Information */
171 if (0) {
172 bitvec_set_bit(&bv, H);
173 /* FIXME */
174 } else
175 bitvec_set_bit(&bv, L);
176 } else {
177 /* L and break indicator */
178 bitvec_set_bit(&bv, L);
179 bitvec_set_bit(&bv, si4->break_ind ? H : L);
180 }
181
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100182 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530183}
184
185/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
186 < GPRS Mobile Allocation IE > ::=
187 < HSN : bit (6) >
188 { 0 | 1 < RFL number list : < RFL number list struct > > }
189 { 0 < MA_LENGTH : bit (6) >
190 < MA_BITMAP: bit (val(MA_LENGTH) + 1) >
191 | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;
192
193 < RFL number list struct > :: =
194 < RFL_NUMBER : bit (4) >
195 { 0 | 1 < RFL number list struct > } ;
196 < ARFCN index list struct > ::=
197 < ARFCN_INDEX : bit(6) >
198 { 0 | 1 < ARFCN index list struct > } ;
199 */
200static int append_gprs_mobile_alloc(struct bitvec *bv)
201{
202 /* Hopping Sequence Number */
203 bitvec_set_uint(bv, 0, 6);
204
205 if (0) {
206 /* We want to use a RFL number list */
207 bitvec_set_bit(bv, 1);
208 /* FIXME: RFL number list */
209 } else
210 bitvec_set_bit(bv, 0);
211
212 if (0) {
213 /* We want to use a MA_BITMAP */
214 bitvec_set_bit(bv, 0);
215 /* FIXME: MA_LENGTH, MA_BITMAP, ... */
216 } else {
217 bitvec_set_bit(bv, 1);
218 if (0) {
219 /* We want to provide an ARFCN index list */
220 bitvec_set_bit(bv, 1);
221 /* FIXME */
222 } else
223 bitvec_set_bit(bv, 0);
224 }
225 return 0;
226}
227
228static int encode_t3192(unsigned int t3192)
229{
230 if (t3192 == 0)
231 return 3;
232 else if (t3192 <= 80)
233 return 4;
234 else if (t3192 <= 120)
235 return 5;
236 else if (t3192 <= 160)
237 return 6;
238 else if (t3192 <= 200)
239 return 7;
240 else if (t3192 <= 500)
241 return 0;
242 else if (t3192 <= 1000)
243 return 1;
244 else if (t3192 <= 1500)
245 return 2;
246 else
247 return -EINVAL;
248}
249
250static int encode_drx_timer(unsigned int drx)
251{
252 if (drx == 0)
253 return 0;
254 else if (drx == 1)
255 return 1;
256 else if (drx == 2)
257 return 2;
258 else if (drx <= 4)
259 return 3;
260 else if (drx <= 8)
261 return 4;
262 else if (drx <= 16)
263 return 5;
264 else if (drx <= 32)
265 return 6;
266 else if (drx <= 64)
267 return 7;
268 else
269 return -EINVAL;
270}
271
272/* GPRS Cell Options as per TS 04.60 Chapter 12.24
273 < GPRS Cell Options IE > ::=
274 < NMO : bit(2) >
275 < T3168 : bit(3) >
276 < T3192 : bit(3) >
277 < DRX_TIMER_MAX: bit(3) >
278 < ACCESS_BURST_TYPE: bit >
279 < CONTROL_ACK_TYPE : bit >
280 < BS_CV_MAX: bit(4) >
281 { 0 | 1 < PAN_DEC : bit(3) >
282 < PAN_INC : bit(3) >
283 < PAN_MAX : bit(3) >
284 { 0 | 1 < Extension Length : bit(6) >
285 < bit (val(Extension Length) + 1
286 & { < Extension Information > ! { bit ** = <no string> } } ;
287 < Extension Information > ::=
288 { 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit >
289 < BEP_PERIOD : bit(4) > }
290 < PFC_FEATURE_MODE : bit >
291 < DTM_SUPPORT : bit >
292 <BSS_PAGING_COORDINATION: bit >
293 <spare bit > ** ;
294 */
Harald Weltea4e2d042009-12-20 17:08:22 +0100295static int append_gprs_cell_opt(struct bitvec *bv,
296 const struct gprs_cell_options *gco)
Harald Weltea43f7892009-12-01 18:04:30 +0530297{
298 int t3192, drx_timer_max;
299
300 t3192 = encode_t3192(gco->t3192);
301 if (t3192 < 0)
302 return t3192;
303
304 drx_timer_max = encode_drx_timer(gco->drx_timer_max);
305 if (drx_timer_max < 0)
306 return drx_timer_max;
307
308 bitvec_set_uint(bv, gco->nmo, 2);
309 bitvec_set_uint(bv, gco->t3168 / 500, 3);
310 bitvec_set_uint(bv, t3192, 3);
311 bitvec_set_uint(bv, drx_timer_max, 3);
312 /* ACCESS_BURST_TYPE: Hard-code 8bit */
313 bitvec_set_bit(bv, 0);
314 /* CONTROL_ACK_TYPE: Hard-code to RLC/MAC control block */
315 bitvec_set_bit(bv, 1);
316 bitvec_set_uint(bv, gco->bs_cv_max, 4);
317
Harald Weltea4b16652010-05-31 12:54:23 +0200318 if (0) {
319 /* hard-code no PAN_{DEC,INC,MAX} */
320 bitvec_set_bit(bv, 0);
321 } else {
322 /* copied from ip.access BSC protocol trace */
323 bitvec_set_bit(bv, 1);
324 bitvec_set_uint(bv, 1, 3); /* DEC */
325 bitvec_set_uint(bv, 1, 3); /* INC */
326 bitvec_set_uint(bv, 15, 3); /* MAX */
327 }
Harald Weltea43f7892009-12-01 18:04:30 +0530328
Harald Welteda0586a2010-04-18 14:49:05 +0200329 if (!gco->ext_info_present) {
330 /* no extension information */
331 bitvec_set_bit(bv, 0);
332 } else {
333 /* extension information */
334 bitvec_set_bit(bv, 1);
335 if (!gco->ext_info.egprs_supported) {
336 /* 6bit length of extension */
Harald Welte39608dc2010-04-18 22:47:22 +0200337 bitvec_set_uint(bv, (1 + 3)-1, 6);
Harald Welteda0586a2010-04-18 14:49:05 +0200338 /* EGPRS supported in the cell */
339 bitvec_set_bit(bv, 0);
340 } else {
341 /* 6bit length of extension */
Harald Welte39608dc2010-04-18 22:47:22 +0200342 bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);
Harald Welteda0586a2010-04-18 14:49:05 +0200343 /* EGPRS supported in the cell */
344 bitvec_set_bit(bv, 1);
345 /* 1bit EGPRS PACKET CHANNEL REQUEST */
346 bitvec_set_bit(bv, gco->ext_info.use_egprs_p_ch_req);
347 /* 4bit BEP PERIOD */
348 bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
349 }
350 bitvec_set_bit(bv, gco->ext_info.pfc_supported);
351 bitvec_set_bit(bv, gco->ext_info.dtm_supported);
352 bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
353 }
Harald Weltea43f7892009-12-01 18:04:30 +0530354
355 return 0;
356}
357
358static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
Harald Weltea4e2d042009-12-20 17:08:22 +0100359 const struct gprs_power_ctrl_pars *pcp)
Harald Weltea43f7892009-12-01 18:04:30 +0530360{
361 bitvec_set_uint(bv, pcp->alpha, 4);
362 bitvec_set_uint(bv, pcp->t_avg_w, 5);
363 bitvec_set_uint(bv, pcp->t_avg_t, 5);
364 bitvec_set_uint(bv, pcp->pc_meas_chan, 1);
365 bitvec_set_uint(bv, pcp->n_avg_i, 4);
366}
367
Harald Welte5fda9082010-04-18 22:41:01 +0200368/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
Harald Weltea43f7892009-12-01 18:04:30 +0530369int rest_octets_si13(u_int8_t *data, const struct gsm48_si13_info *si13)
370{
371 struct bitvec bv;
372
373 memset(&bv, 0, sizeof(bv));
374 bv.data = data;
Holger Hans Peter Freyther4cffc452010-01-06 06:44:37 +0100375 bv.data_len = 20;
Harald Weltea43f7892009-12-01 18:04:30 +0530376
377 if (0) {
378 /* No rest octets */
379 bitvec_set_bit(&bv, L);
380 } else {
381 bitvec_set_bit(&bv, H);
382 bitvec_set_uint(&bv, si13->bcch_change_mark, 3);
383 bitvec_set_uint(&bv, si13->si_change_field, 4);
Harald Welte97a282b2010-03-14 15:37:43 +0800384 if (1) {
Harald Weltea43f7892009-12-01 18:04:30 +0530385 bitvec_set_bit(&bv, 0);
386 } else {
387 bitvec_set_bit(&bv, 1);
388 bitvec_set_uint(&bv, si13->bcch_change_mark, 2);
389 append_gprs_mobile_alloc(&bv);
390 }
391 if (!si13->pbcch_present) {
392 /* PBCCH not present in cell */
393 bitvec_set_bit(&bv, 0);
394 bitvec_set_uint(&bv, si13->no_pbcch.rac, 8);
395 bitvec_set_bit(&bv, si13->no_pbcch.spgc_ccch_sup);
396 bitvec_set_uint(&bv, si13->no_pbcch.prio_acc_thr, 3);
397 bitvec_set_uint(&bv, si13->no_pbcch.net_ctrl_ord, 2);
398 append_gprs_cell_opt(&bv, &si13->cell_opts);
399 append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);
400 } else {
401 /* PBCCH present in cell */
402 bitvec_set_bit(&bv, 1);
403 bitvec_set_uint(&bv, si13->pbcch.psi1_rep_per, 4);
404 /* PBCCH Descripiton */
405 bitvec_set_uint(&bv, si13->pbcch.pb, 4);
406 bitvec_set_uint(&bv, si13->pbcch.tsc, 3);
407 bitvec_set_uint(&bv, si13->pbcch.tn, 3);
408 switch (si13->pbcch.carrier_type) {
409 case PBCCH_BCCH:
410 bitvec_set_bit(&bv, 0);
411 bitvec_set_bit(&bv, 0);
412 break;
413 case PBCCH_ARFCN:
414 bitvec_set_bit(&bv, 0);
415 bitvec_set_bit(&bv, 1);
416 bitvec_set_uint(&bv, si13->pbcch.arfcn, 10);
417 break;
418 case PBCCH_MAIO:
419 bitvec_set_bit(&bv, 1);
420 bitvec_set_uint(&bv, si13->pbcch.maio, 6);
421 break;
422 }
423 }
Harald Welte5fda9082010-04-18 22:41:01 +0200424 /* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
425 bitvec_set_bit(&bv, H); /* added Release 99 */
426 /* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
427 * was only added in this Release */
428 bitvec_set_bit(&bv, 1);
Harald Weltea43f7892009-12-01 18:04:30 +0530429 }
Holger Hans Peter Freythercaa14862010-01-06 07:49:58 +0100430 bitvec_spare_padding(&bv, (bv.data_len*8)-1);
431 return bv.data_len;
Harald Weltea43f7892009-12-01 18:04:30 +0530432}