blob: fb69377f72f314cc52cd6a8624b6826b98aa1d37 [file] [log] [blame]
Harald Welteec8b4502010-02-20 20:34:29 +01001/*
2 * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
3 * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte622b7182010-03-07 17:50:21 +01004 * (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
Nico Golde28de0532010-07-09 17:19:12 +02005 * (C) 2010 by Nico Golde <nico@ngolde.de>
Harald Welteec8b4502010-02-20 20:34:29 +01006 *
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 <openbsc/gsm_data.h>
26#include <osmocore/utils.h>
27#include <osmocore/gsm_utils.h>
28
29#include <stdlib.h>
30#include <stdint.h>
31#include <string.h>
32#include <stdio.h>
33#include <errno.h>
Harald Welteaebe08c2010-03-04 10:39:17 +010034#include <ctype.h>
Harald Welteec8b4502010-02-20 20:34:29 +010035
36#include "../config.h"
37
Nico Golde28de0532010-07-09 17:19:12 +020038/* GSM 03.38 6.2.1 Character lookup for decoding */
39static int gsm_septet_lookup(uint8_t ch)
40{
41 int i = 0;
42 for(; i < sizeof(gsm_7bit_alphabet); i++){
43 if(gsm_7bit_alphabet[i] == ch)
44 return i;
45 }
46 return -1;
47}
48
49/* GSM 03.38 6.2.1 Character unpacking */
Harald Welteec8b4502010-02-20 20:34:29 +010050int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t length)
51{
52 int i = 0;
53 int l = 0;
Nico Golde28de0532010-07-09 17:19:12 +020054 uint8_t *rtext = calloc(length, sizeof(uint8_t));
55 uint8_t tmp;
Harald Welteec8b4502010-02-20 20:34:29 +010056
Nico Golde28de0532010-07-09 17:19:12 +020057 /* FIXME: We need to account for user data headers here */
Harald Welteec8b4502010-02-20 20:34:29 +010058 i += l;
Nico Golde28de0532010-07-09 17:19:12 +020059 for (; i < length; i ++){
60 rtext[i] =
Harald Welteec8b4502010-02-20 20:34:29 +010061 ((user_data[(i * 7 + 7) >> 3] <<
62 (7 - ((i * 7 + 7) & 7))) |
63 (user_data[(i * 7) >> 3] >>
64 ((i * 7) & 7))) & 0x7f;
Nico Golde28de0532010-07-09 17:19:12 +020065 }
66 for(i = 0; i < length; i++){
67 /* this is an extension character */
68 if(rtext[i] == 0x1b){
69 tmp = rtext[i+1];
70 *(text++) = gsm_7bit_alphabet[0x7f + tmp];
Harald Welteec8b4502010-02-20 20:34:29 +010071 i++;
Nico Golde28de0532010-07-09 17:19:12 +020072 continue;
Harald Welteec8b4502010-02-20 20:34:29 +010073 }
Nico Golde28de0532010-07-09 17:19:12 +020074
75 *(text++) = gsm_septet_lookup(rtext[i]);
Harald Welteec8b4502010-02-20 20:34:29 +010076 }
77
Nico Golde28de0532010-07-09 17:19:12 +020078 *text = '\0';
79 free(rtext);
80
81 return i;
82}
83
84/* GSM 03.38 6.2.1 Prepare character packing */
85static int gsm_septet_encode(uint8_t *result, const char *data)
86{
87 int i, y = 0;
88 uint8_t ch;
89 for(i = 0; i < strlen(data); i++){
90 ch = data[i];
91 switch(ch){
92 /* fall-through for extension characters */
93 case 0x0c:
94 case 0x5e:
95 case 0x7b:
96 case 0x7d:
97 case 0x5c:
98 case 0x5b:
99 case 0x7e:
100 case 0x5d:
101 case 0x7c:
102 result[y++] = 0x1b;
103 default:
104 result[y] = gsm_7bit_alphabet[ch];
105 break;
106 }
107 y++;
108 }
109
110 return y;
111}
112
113/* GSM 03.38 6.2.1 Character packing */
114int gsm_7bit_encode(uint8_t *result, const char *data)
115{
116 int i,y,z = 0;
117 /* prepare for the worst case, every character expanding to two bytes */
118 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
119 uint8_t cb, nb;
120 int shift = 0;
121
122 y = gsm_septet_encode(rdata, data);
123
124 for(i = 0; i < y; i++) {
125 if(shift == 7 && i + 1 < y){
126 shift = 0;
127 continue;
128 }
129
130 cb = (rdata[i] & 0x7f) >> shift;
131 if(i + 1 < y){
132 nb = (rdata[i + 1] & 0x7f) << (7 - shift);
133 cb = cb | nb;
134 }
135
136 result[z++] = cb;
137
138 shift++;
139 }
140
141 free(rdata);
Harald Welteec8b4502010-02-20 20:34:29 +0100142 return i;
143}
144
145/* determine power control level for given dBm value, as indicated
146 * by the tables in chapter 4.1.1 of GSM TS 05.05 */
147int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
148{
149 switch (band) {
150 case GSM_BAND_450:
151 case GSM_BAND_480:
152 case GSM_BAND_750:
153 case GSM_BAND_900:
154 case GSM_BAND_810:
155 case GSM_BAND_850:
156 if (dbm >= 39)
157 return 0;
158 else if (dbm < 5)
159 return 19;
160 else {
161 /* we are guaranteed to have (5 <= dbm < 39) */
162 return 2 + ((39 - dbm) / 2);
163 }
164 break;
165 case GSM_BAND_1800:
166 if (dbm >= 36)
167 return 29;
168 else if (dbm >= 34)
169 return 30;
170 else if (dbm >= 32)
171 return 31;
172 else if (dbm == 31)
173 return 0;
174 else {
175 /* we are guaranteed to have (0 <= dbm < 31) */
176 return (30 - dbm) / 2;
177 }
178 break;
179 case GSM_BAND_1900:
180 if (dbm >= 33)
181 return 30;
182 else if (dbm >= 32)
183 return 31;
184 else if (dbm == 31)
185 return 0;
186 else {
187 /* we are guaranteed to have (0 <= dbm < 31) */
188 return (30 - dbm) / 2;
189 }
190 break;
191 }
192 return -EINVAL;
193}
194
195int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
196{
197 lvl &= 0x1f;
198
199 switch (band) {
200 case GSM_BAND_450:
201 case GSM_BAND_480:
202 case GSM_BAND_750:
203 case GSM_BAND_900:
204 case GSM_BAND_810:
205 case GSM_BAND_850:
206 if (lvl < 2)
207 return 39;
208 else if (lvl < 20)
209 return 39 - ((lvl - 2) * 2) ;
210 else
211 return 5;
212 break;
213 case GSM_BAND_1800:
214 if (lvl < 16)
215 return 30 - (lvl * 2);
216 else if (lvl < 29)
217 return 0;
218 else
219 return 36 - ((lvl - 29) * 2);
220 break;
221 case GSM_BAND_1900:
222 if (lvl < 16)
223 return 30 - (lvl * 2);
224 else if (lvl < 30)
225 return -EINVAL;
226 else
227 return 33 - (lvl - 30);
228 break;
229 }
230 return -EINVAL;
231}
232
233/* According to TS 08.05 Chapter 8.1.4 */
234int rxlev2dbm(uint8_t rxlev)
235{
236 if (rxlev > 63)
237 rxlev = 63;
238
239 return -110 + rxlev;
240}
241
242/* According to TS 08.05 Chapter 8.1.4 */
243uint8_t dbm2rxlev(int dbm)
244{
245 int rxlev = dbm + 110;
246
247 if (rxlev > 63)
248 rxlev = 63;
249 else if (rxlev < 0)
250 rxlev = 0;
251
252 return rxlev;
253}
254
Harald Weltecbc80622010-03-22 08:28:44 +0800255const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100256{
257 switch (band) {
258 case GSM_BAND_450:
259 return "GSM450";
260 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200261 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100262 case GSM_BAND_750:
263 return "GSM750";
264 case GSM_BAND_810:
265 return "GSM810";
266 case GSM_BAND_850:
267 return "GSM850";
268 case GSM_BAND_900:
269 return "GSM900";
270 case GSM_BAND_1800:
271 return "DCS1800";
272 case GSM_BAND_1900:
273 return "PCS1900";
274 }
275 return "invalid";
276}
277
278enum gsm_band gsm_band_parse(const char* mhz)
279{
280 while (*mhz && !isdigit(*mhz))
281 mhz++;
282
283 if (*mhz == '\0')
284 return -EINVAL;
285
Harald Welted3ff15f2010-03-07 18:23:47 +0100286 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100287 case 450:
288 return GSM_BAND_450;
289 case 480:
290 return GSM_BAND_480;
291 case 750:
292 return GSM_BAND_750;
293 case 810:
294 return GSM_BAND_810;
295 case 850:
296 return GSM_BAND_850;
297 case 900:
298 return GSM_BAND_900;
299 case 1800:
300 return GSM_BAND_1800;
301 case 1900:
302 return GSM_BAND_1900;
303 default:
304 return -EINVAL;
305 }
306}
307
308
Harald Welteec8b4502010-02-20 20:34:29 +0100309#ifdef HAVE_EXECINFO_H
310#include <execinfo.h>
311void generate_backtrace()
312{
313 int i, nptrs;
314 void *buffer[100];
315 char **strings;
316
317 nptrs = backtrace(buffer, ARRAY_SIZE(buffer));
318 printf("backtrace() returned %d addresses\n", nptrs);
319
320 strings = backtrace_symbols(buffer, nptrs);
321 if (!strings)
322 return;
323
324 for (i = 1; i < nptrs; i++)
325 printf("%s\n", strings[i]);
326
327 free(strings);
328}
329#endif
Harald Welte622b7182010-03-07 17:50:21 +0100330
331enum gsm_band gsm_arfcn2band(uint16_t arfcn)
332{
333 if (arfcn & ARFCN_PCS)
334 return GSM_BAND_1900;
335 else if (arfcn <= 124)
336 return GSM_BAND_900;
337 else if (arfcn >= 955 && arfcn <= 1023)
338 return GSM_BAND_900;
339 else if (arfcn >= 128 && arfcn <= 251)
340 return GSM_BAND_850;
341 else if (arfcn >= 512 && arfcn <= 885)
342 return GSM_BAND_1800;
343 else if (arfcn >= 259 && arfcn <= 293)
344 return GSM_BAND_450;
345 else if (arfcn >= 306 && arfcn <= 340)
346 return GSM_BAND_480;
347 else if (arfcn >= 350 && arfcn <= 425)
348 return GSM_BAND_810;
349 else if (arfcn >= 438 && arfcn <= 511)
350 return GSM_BAND_750;
351 else
352 return GSM_BAND_1800;
353}
354
355/* Convert an ARFCN to the frequency in MHz * 10 */
356uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
357{
358 uint16_t freq10_ul;
359 uint16_t freq10_dl;
360
361 if (arfcn & ARFCN_PCS) {
362 /* DCS 1900 */
363 arfcn &= ~ARFCN_PCS;
364 freq10_ul = 18502 + 2 * (arfcn-512);
365 freq10_dl = freq10_ul + 800;
366 } else if (arfcn <= 124) {
367 /* Primary GSM + ARFCN 0 of E-GSM */
368 freq10_ul = 8900 + 2 * arfcn;
369 freq10_dl = freq10_ul + 450;
370 } else if (arfcn >= 955 && arfcn <= 1023) {
371 /* E-GSM and R-GSM */
372 freq10_ul = 8900 + 2 * (arfcn - 1024);
373 freq10_dl = freq10_ul + 450;
374 } else if (arfcn >= 128 && arfcn <= 251) {
375 /* GSM 850 */
376 freq10_ul = 8242 + 2 * (arfcn - 128);
377 freq10_dl = freq10_ul + 450;
378 } else if (arfcn >= 512 && arfcn <= 885) {
379 /* DCS 1800 */
380 freq10_ul = 17102 + 2 * (arfcn - 512);
381 freq10_dl = freq10_ul + 950;
382 } else if (arfcn >= 259 && arfcn <= 293) {
383 /* GSM 450 */
384 freq10_ul = 4506 + 2 * (arfcn - 259);
385 freq10_dl = freq10_ul + 100;
386 } else if (arfcn >= 306 && arfcn <= 340) {
387 /* GSM 480 */
388 freq10_ul = 4790 + 2 * (arfcn - 306);
389 freq10_dl = freq10_ul + 100;
390 } else if (arfcn >= 350 && arfcn <= 425) {
391 /* GSM 810 */
392 freq10_ul = 8060 + 2 * (arfcn - 350);
393 freq10_dl = freq10_ul + 450;
394 } else if (arfcn >= 438 && arfcn <= 511) {
395 /* GSM 750 */
396 freq10_ul = 7472 + 2 * (arfcn - 438);
397 freq10_dl = freq10_ul + 300;
398 } else
399 return 0xffff;
400
401 if (uplink)
402 return freq10_ul;
403 else
404 return freq10_dl;
405}
406
407void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
408{
409 time->fn = fn;
410 time->t1 = time->fn / (26*51);
411 time->t2 = time->fn % 26;
412 time->t3 = time->fn % 51;
413 time->tc = (time->fn / 51) % 8;
414}
415
416uint32_t gsm_gsmtime2fn(struct gsm_time *time)
417{
418 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
419 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
420}
Harald Weltea1c4f762010-05-01 11:59:42 +0200421
422/* TS 03.03 Chapter 2.6 */
423int gprs_tlli_type(uint32_t tlli)
424{
425 if ((tlli & 0xc0000000) == 0xc0000000)
426 return TLLI_LOCAL;
427 else if ((tlli & 0xc0000000) == 0x80000000)
428 return TLLI_FOREIGN;
429 else if ((tlli & 0xf8000000) == 0x78000000)
430 return TLLI_RANDOM;
431 else if ((tlli & 0xf8000000) == 0x70000000)
432 return TLLI_AUXILIARY;
433
434 return TLLI_RESERVED;
435}
Harald Weltec2263172010-06-01 10:47:07 +0200436
437uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
438{
439 uint32_t tlli;
440 switch (type) {
441 case TLLI_LOCAL:
442 tlli = p_tmsi | 0xc0000000;
443 break;
444 case TLLI_FOREIGN:
445 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
446 break;
447 default:
448 tlli = 0;
449 break;
450 }
451 return tlli;
452}