blob: 50029479dee8f24206da6b3b71300bcaacb66f7e [file] [log] [blame]
Harald Welteec8b4502010-02-20 20:34:29 +01001/*
2 * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +02003 * (C) 2009,2013 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 Goldec56a56d2012-09-18 14:29:40 +02005 * (C) 2010-2012 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
Harald Welted38c8b82011-08-30 11:32:56 +020025/*! \mainpage libosmogsm Documentation
26 *
27 * \section sec_intro Introduction
28 * This library is a collection of common code used in various
29 * GSM related sub-projects inside the Osmocom family of projects. It
30 * includes A5/1 and A5/2 ciphers, COMP128v1, a LAPDm implementation,
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +020031 * a GSM TLV parser, SMS utility routines as well as
Harald Welted38c8b82011-08-30 11:32:56 +020032 * protocol definitions for a series of protocols:
33 * * Um L2 (04.06)
34 * * Um L3 (04.08)
35 * * A-bis RSL (08.58)
36 * * A-bis OML (08.59, 12.21)
37 * * A (08.08)
38 * \n\n
39 * Please note that C language projects inside Osmocom are typically
40 * single-threaded event-loop state machine designs. As such,
41 * routines in libosmogsm are not thread-safe. If you must use them in
42 * a multi-threaded context, you have to add your own locking.
43 *
44 * \section sec_copyright Copyright and License
45 * Copyright © 2008-2011 - Harald Welte, Holger Freyther and contributors\n
46 * All rights reserved. \n\n
47 * The source code of libosmogsm is licensed under the terms of the GNU
48 * General Public License as published by the Free Software Foundation;
49 * either version 2 of the License, or (at your option) any later
50 * version.\n
51 * See <http://www.gnu.org/licenses/> or COPYING included in the source
52 * code package istelf.\n
53 * The information detailed here is provided AS IS with NO WARRANTY OF
54 * ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
55 * FITNESS FOR A PARTICULAR PURPOSE.
56 * \n\n
57 *
58 * \section sec_contact Contact and Support
59 * Community-based support is available at the OpenBSC mailing list
60 * <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
61 * Commercial support options available upon request from
62 * <http://sysmocom.de/>
63 */
64
Harald Welteec8b4502010-02-20 20:34:29 +010065//#include <openbsc/gsm_data.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010066#include <osmocom/core/utils.h>
Max8a5346b2016-04-22 19:28:09 +020067#include <osmocom/core/bitvec.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010068#include <osmocom/gsm/gsm_utils.h>
Max8a5346b2016-04-22 19:28:09 +020069#include <osmocom/gsm/protocol/gsm_04_08.h>
Harald Welteec8b4502010-02-20 20:34:29 +010070
71#include <stdlib.h>
72#include <stdint.h>
73#include <string.h>
74#include <stdio.h>
75#include <errno.h>
Harald Welteaebe08c2010-03-04 10:39:17 +010076#include <ctype.h>
Harald Welteec8b4502010-02-20 20:34:29 +010077
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010078#include "../../config.h"
Harald Welteec8b4502010-02-20 20:34:29 +010079
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +080080/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
81 * Greek symbols at hex positions 0x10 and 0x12-0x1a
82 * left out as they can't be handled with a char and
83 * since most phones don't display or write these
84 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +020085 * more complex.
86 *
87 * Note that this table contains the latin1->7bit mapping _and_ has
88 * been merged with the reverse mapping (7bit->latin1) for the
89 * extended characters at offset 0x7f.
90 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +080091static unsigned char gsm_7bit_alphabet[] = {
92 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
94 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
95 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
96 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
97 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
98 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
99 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
100 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
101 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
102 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
103 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
104 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
105 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
106 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
107 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
108 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
109};
110
Nico Golde28de0532010-07-09 17:19:12 +0200111/* GSM 03.38 6.2.1 Character lookup for decoding */
112static int gsm_septet_lookup(uint8_t ch)
113{
114 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200115 for (; i < sizeof(gsm_7bit_alphabet); i++) {
116 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200117 return i;
118 }
119 return -1;
120}
121
Dennis Wehrle291e6132011-07-24 20:14:13 +0200122/* Compute the number of octets from the number of septets, for instance: 47 septets needs 41,125 = 42 octets */
123uint8_t gsm_get_octet_len(const uint8_t sept_len){
124 int octet_len = (sept_len * 7) / 8;
125 if ((sept_len * 7) % 8 != 0)
126 octet_len++;
127
128 return octet_len;
129}
130
Nico Golde28de0532010-07-09 17:19:12 +0200131/* GSM 03.38 6.2.1 Character unpacking */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200132int gsm_7bit_decode_n_hdr(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind)
Harald Welteec8b4502010-02-20 20:34:29 +0100133{
Maxcf37c4c2016-01-21 16:52:40 +0100134 unsigned shift = 0;
135 uint8_t c7, c8, next_is_ext = 0, lu, ru;
136 const uint8_t maxlen = gsm_get_octet_len(septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200137 const char *text_buf_begin = text;
138 const char *text_buf_end = text + n;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200139
140 OSMO_ASSERT (n > 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100141
Dennis Wehrle291e6132011-07-24 20:14:13 +0200142 /* skip the user data header */
143 if (ud_hdr_ind) {
144 /* get user data header length + 1 (for the 'user data header length'-field) */
145 shift = ((user_data[0] + 1) * 8) / 7;
146 if ((((user_data[0] + 1) * 8) % 7) != 0)
147 shift++;
148 septet_l = septet_l - shift;
149 }
150
Maxcf37c4c2016-01-21 16:52:40 +0100151 unsigned i, l, r;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200152 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
Maxcf37c4c2016-01-21 16:52:40 +0100153
154 l = ((i + shift) * 7 + 7) >> 3;
155 r = ((i + shift) * 7) >> 3;
156
157 /* the left side index is always >= right side index
158 sometimes it even gets beyond array boundary
159 check for that explicitly and force 0 instead
160 */
161 if (l >= maxlen)
162 lu = 0;
163 else
164 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
165
166 ru = user_data[r] >> (((i + shift) * 7) & 7);
167
168 c7 = (lu | ru) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200169
Harald Weltebe55a8b2012-09-20 10:00:25 +0200170 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200171 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200172 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200173 c8 = gsm_7bit_alphabet[0x7f + c7];
174 } else if (c7 == 0x1b && i + 1 < septet_l) {
175 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200176 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200177 } else {
178 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200179 }
180
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200181 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100182 }
183
Nico Golde28de0532010-07-09 17:19:12 +0200184 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200185
Maxcf37c4c2016-01-21 16:52:40 +0100186 return text - text_buf_begin;
Nico Golde28de0532010-07-09 17:19:12 +0200187}
188
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200189int gsm_7bit_decode_n(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l)
Dennis Wehrle291e6132011-07-24 20:14:13 +0200190{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200191 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200192}
193
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200194int gsm_7bit_decode_n_ussd(char *text, size_t n, const uint8_t *user_data, uint8_t length)
Andreas Eversberg95975552013-08-08 12:38:53 +0200195{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200196 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200197
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200198 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200199 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200200 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
201 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200202
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200203 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200204}
205
Nico Golde28de0532010-07-09 17:19:12 +0200206/* GSM 03.38 6.2.1 Prepare character packing */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200207int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200208{
209 int i, y = 0;
210 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200211 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200212 ch = data[i];
213 switch(ch){
214 /* fall-through for extension characters */
215 case 0x0c:
216 case 0x5e:
217 case 0x7b:
218 case 0x7d:
219 case 0x5c:
220 case 0x5b:
221 case 0x7e:
222 case 0x5d:
223 case 0x7c:
224 result[y++] = 0x1b;
225 default:
226 result[y] = gsm_7bit_alphabet[ch];
227 break;
228 }
229 y++;
230 }
231
232 return y;
233}
234
Dennis Wehrle291e6132011-07-24 20:14:13 +0200235/* 7bit to octet packing */
Harald Welteca693882013-03-13 15:10:55 +0100236int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
237{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200238 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200239 uint8_t cb, nb;
240 int shift = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200241 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
Nico Golde28de0532010-07-09 17:19:12 +0200242
Dennis Wehrle291e6132011-07-24 20:14:13 +0200243 if (padding) {
244 shift = 7 - padding;
245 /* the first zero is needed for padding */
246 memcpy(data + 1, rdata, septet_len);
247 septet_len++;
248 } else
249 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200250
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200251 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200252 if (shift == 7) {
253 /*
254 * special end case with the. This is necessary if the
255 * last septet fits into the previous octet. E.g. 48
256 * non-extension characters:
257 * ....ag ( a = 1100001, g = 1100111)
258 * result[40] = 100001 XX, result[41] = 1100111 1 */
259 if (i + 1 < septet_len) {
260 shift = 0;
261 continue;
262 } else if (i + 1 == septet_len)
263 break;
Nico Golde28de0532010-07-09 17:19:12 +0200264 }
265
Dennis Wehrle291e6132011-07-24 20:14:13 +0200266 cb = (data[i] & 0x7f) >> shift;
267 if (i + 1 < septet_len) {
268 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200269 cb = cb | nb;
270 }
271
272 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200273 shift++;
274 }
275
Dennis Wehrle291e6132011-07-24 20:14:13 +0200276 free(data);
277
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200278 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100279}
280
Dennis Wehrle291e6132011-07-24 20:14:13 +0200281/* GSM 03.38 6.2.1 Character packing */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200282int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200283{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200284 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200285 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100286 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200287
Dennis Wehrle291e6132011-07-24 20:14:13 +0200288 /* prepare for the worst case, every character expanding to two bytes */
289 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
290 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200291
292 if (y > max_septets) {
293 /*
294 * Limit the number of septets to avoid the generation
295 * of more than n octets.
296 */
297 y = max_septets;
298 }
299
300 o = gsm_septets2octets(result, rdata, y, 0);
301
302 if (octets)
303 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200304
305 free(rdata);
306
307 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200308 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200309 * unique. E.g.:
310 * 1.) 46 non-extension characters + 1 extension character
311 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
312 * 2.) 47 non-extension characters
313 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
314 * 3.) 48 non-extension characters
315 * => (48 * 7 bit) / 8 bit = 42 octects
316 */
317 return y;
318}
319
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200320int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
321{
322 int y;
323
324 y = gsm_7bit_encode_n(result, n, data, octets);
325 /* if last octet contains only one bit, add <CR> */
326 if (((y * 7) & 7) == 1)
327 result[(*octets) - 1] |= ('\r' << 1);
328 /* if last character is <CR> and completely fills last octet, add
329 * another <CR>. */
330 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
331 result[(*octets)++] = '\r';
332 y++;
333 }
334
335 return y;
336}
337
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200338/* convert power class to dBm according to GSM TS 05.05 */
339unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
340{
341 switch (band) {
342 case GSM_BAND_450:
343 case GSM_BAND_480:
344 case GSM_BAND_750:
345 case GSM_BAND_900:
346 case GSM_BAND_810:
347 case GSM_BAND_850:
348 if (class == 1)
349 return 43; /* 20W */
350 if (class == 2)
351 return 39; /* 8W */
352 if (class == 3)
353 return 37; /* 5W */
354 if (class == 4)
355 return 33; /* 2W */
356 if (class == 5)
357 return 29; /* 0.8W */
358 break;
359 case GSM_BAND_1800:
360 if (class == 1)
361 return 30; /* 1W */
362 if (class == 2)
363 return 24; /* 0.25W */
364 if (class == 3)
365 return 36; /* 4W */
366 break;
367 case GSM_BAND_1900:
368 if (class == 1)
369 return 30; /* 1W */
370 if (class == 2)
371 return 24; /* 0.25W */
372 if (class == 3)
373 return 33; /* 2W */
374 break;
375 }
376 return -EINVAL;
377}
378
Harald Welteec8b4502010-02-20 20:34:29 +0100379/* determine power control level for given dBm value, as indicated
380 * by the tables in chapter 4.1.1 of GSM TS 05.05 */
381int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
382{
383 switch (band) {
384 case GSM_BAND_450:
385 case GSM_BAND_480:
386 case GSM_BAND_750:
387 case GSM_BAND_900:
388 case GSM_BAND_810:
389 case GSM_BAND_850:
390 if (dbm >= 39)
391 return 0;
392 else if (dbm < 5)
393 return 19;
394 else {
395 /* we are guaranteed to have (5 <= dbm < 39) */
396 return 2 + ((39 - dbm) / 2);
397 }
398 break;
399 case GSM_BAND_1800:
400 if (dbm >= 36)
401 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200402 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100403 return 30;
404 else if (dbm >= 32)
405 return 31;
406 else if (dbm == 31)
407 return 0;
408 else {
409 /* we are guaranteed to have (0 <= dbm < 31) */
410 return (30 - dbm) / 2;
411 }
412 break;
413 case GSM_BAND_1900:
414 if (dbm >= 33)
415 return 30;
416 else if (dbm >= 32)
417 return 31;
418 else if (dbm == 31)
419 return 0;
420 else {
421 /* we are guaranteed to have (0 <= dbm < 31) */
422 return (30 - dbm) / 2;
423 }
424 break;
425 }
426 return -EINVAL;
427}
428
429int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
430{
431 lvl &= 0x1f;
432
433 switch (band) {
434 case GSM_BAND_450:
435 case GSM_BAND_480:
436 case GSM_BAND_750:
437 case GSM_BAND_900:
438 case GSM_BAND_810:
439 case GSM_BAND_850:
440 if (lvl < 2)
441 return 39;
442 else if (lvl < 20)
443 return 39 - ((lvl - 2) * 2) ;
444 else
445 return 5;
446 break;
447 case GSM_BAND_1800:
448 if (lvl < 16)
449 return 30 - (lvl * 2);
450 else if (lvl < 29)
451 return 0;
452 else
453 return 36 - ((lvl - 29) * 2);
454 break;
455 case GSM_BAND_1900:
456 if (lvl < 16)
457 return 30 - (lvl * 2);
458 else if (lvl < 30)
459 return -EINVAL;
460 else
461 return 33 - (lvl - 30);
462 break;
463 }
464 return -EINVAL;
465}
466
Bhaskar6b30f922013-05-16 17:35:49 +0530467/* According to TS 05.08 Chapter 8.1.4 */
Harald Welteec8b4502010-02-20 20:34:29 +0100468int rxlev2dbm(uint8_t rxlev)
469{
470 if (rxlev > 63)
471 rxlev = 63;
472
473 return -110 + rxlev;
474}
475
Bhaskar6b30f922013-05-16 17:35:49 +0530476/* According to TS 05.08 Chapter 8.1.4 */
Harald Welteec8b4502010-02-20 20:34:29 +0100477uint8_t dbm2rxlev(int dbm)
478{
479 int rxlev = dbm + 110;
480
481 if (rxlev > 63)
482 rxlev = 63;
483 else if (rxlev < 0)
484 rxlev = 0;
485
486 return rxlev;
487}
488
Harald Weltecbc80622010-03-22 08:28:44 +0800489const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100490{
491 switch (band) {
492 case GSM_BAND_450:
493 return "GSM450";
494 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200495 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100496 case GSM_BAND_750:
497 return "GSM750";
498 case GSM_BAND_810:
499 return "GSM810";
500 case GSM_BAND_850:
501 return "GSM850";
502 case GSM_BAND_900:
503 return "GSM900";
504 case GSM_BAND_1800:
505 return "DCS1800";
506 case GSM_BAND_1900:
507 return "PCS1900";
508 }
509 return "invalid";
510}
511
512enum gsm_band gsm_band_parse(const char* mhz)
513{
514 while (*mhz && !isdigit(*mhz))
515 mhz++;
516
517 if (*mhz == '\0')
518 return -EINVAL;
519
Harald Welted3ff15f2010-03-07 18:23:47 +0100520 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100521 case 450:
522 return GSM_BAND_450;
523 case 480:
524 return GSM_BAND_480;
525 case 750:
526 return GSM_BAND_750;
527 case 810:
528 return GSM_BAND_810;
529 case 850:
530 return GSM_BAND_850;
531 case 900:
532 return GSM_BAND_900;
533 case 1800:
534 return GSM_BAND_1800;
535 case 1900:
536 return GSM_BAND_1900;
537 default:
538 return -EINVAL;
539 }
540}
541
Harald Welte622b7182010-03-07 17:50:21 +0100542enum gsm_band gsm_arfcn2band(uint16_t arfcn)
543{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100544 int is_pcs = arfcn & ARFCN_PCS;
545
546 arfcn &= ~ARFCN_FLAG_MASK;
547
548 if (is_pcs)
Harald Welte622b7182010-03-07 17:50:21 +0100549 return GSM_BAND_1900;
550 else if (arfcn <= 124)
551 return GSM_BAND_900;
552 else if (arfcn >= 955 && arfcn <= 1023)
553 return GSM_BAND_900;
554 else if (arfcn >= 128 && arfcn <= 251)
555 return GSM_BAND_850;
556 else if (arfcn >= 512 && arfcn <= 885)
557 return GSM_BAND_1800;
558 else if (arfcn >= 259 && arfcn <= 293)
559 return GSM_BAND_450;
560 else if (arfcn >= 306 && arfcn <= 340)
561 return GSM_BAND_480;
562 else if (arfcn >= 350 && arfcn <= 425)
563 return GSM_BAND_810;
564 else if (arfcn >= 438 && arfcn <= 511)
565 return GSM_BAND_750;
566 else
567 return GSM_BAND_1800;
568}
569
Sylvain Munaut55720312012-12-11 23:44:41 +0100570struct gsm_freq_range {
571 uint16_t arfcn_first;
572 uint16_t arfcn_last;
573 uint16_t freq_ul_first;
574 uint16_t freq_dl_offset;
575 uint16_t flags;
576};
577
578static struct gsm_freq_range gsm_ranges[] = {
579 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
580 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
581 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
582 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
583 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
584 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
585 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
586 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
587 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
588 { /* Guard */ }
589};
590
Harald Welte622b7182010-03-07 17:50:21 +0100591/* Convert an ARFCN to the frequency in MHz * 10 */
592uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
593{
Sylvain Munaut55720312012-12-11 23:44:41 +0100594 struct gsm_freq_range *r;
595 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
596 uint16_t freq10_ul = 0xffff;
597 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100598
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100599 arfcn &= ~ARFCN_FLAG_MASK;
600
Sylvain Munaut55720312012-12-11 23:44:41 +0100601 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
602 if ((flags == r->flags) &&
603 (arfcn >= r->arfcn_first) &&
604 (arfcn <= r->arfcn_last))
605 {
606 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
607 freq10_dl = freq10_ul + r->freq_dl_offset;
608 break;
609 }
610 }
611
612 return uplink ? freq10_ul : freq10_dl;
613}
614
615/* Convert a Frequency in MHz * 10 to ARFCN */
616uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
617{
618 struct gsm_freq_range *r;
619 uint16_t freq10_lo, freq10_hi;
620 uint16_t arfcn = 0xffff;
621
622 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
623 /* Generate frequency limits */
624 freq10_lo = r->freq_ul_first;
625 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
626 if (!uplink) {
627 freq10_lo += r->freq_dl_offset;
628 freq10_hi += r->freq_dl_offset;
629 }
630
631 /* Check if this fits */
632 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
633 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
634 arfcn |= r->flags;
635 break;
636 }
637 }
Harald Welte622b7182010-03-07 17:50:21 +0100638
639 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100640 arfcn |= ARFCN_UPLINK;
641
642 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100643}
644
645void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
646{
647 time->fn = fn;
648 time->t1 = time->fn / (26*51);
649 time->t2 = time->fn % 26;
650 time->t3 = time->fn % 51;
651 time->tc = (time->fn / 51) % 8;
652}
653
654uint32_t gsm_gsmtime2fn(struct gsm_time *time)
655{
656 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
657 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
658}
Harald Weltea1c4f762010-05-01 11:59:42 +0200659
Max8a5346b2016-04-22 19:28:09 +0200660/*! \brief append range1024 encoded data to bit vector */
661void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
662{
663 bitvec_set_uint(bv, r->w1_hi, 2);
664 bitvec_set_uint(bv, r->w1_lo, 8);
665 bitvec_set_uint(bv, r->w2_hi, 8);
666 bitvec_set_uint(bv, r->w2_lo, 1);
667 bitvec_set_uint(bv, r->w3_hi, 7);
668 bitvec_set_uint(bv, r->w3_lo, 2);
669 bitvec_set_uint(bv, r->w4_hi, 6);
670 bitvec_set_uint(bv, r->w4_lo, 2);
671 bitvec_set_uint(bv, r->w5_hi, 6);
672 bitvec_set_uint(bv, r->w5_lo, 2);
673 bitvec_set_uint(bv, r->w6_hi, 6);
674 bitvec_set_uint(bv, r->w6_lo, 2);
675 bitvec_set_uint(bv, r->w7_hi, 6);
676 bitvec_set_uint(bv, r->w7_lo, 2);
677 bitvec_set_uint(bv, r->w8_hi, 6);
678 bitvec_set_uint(bv, r->w8_lo, 1);
679 bitvec_set_uint(bv, r->w9, 7);
680 bitvec_set_uint(bv, r->w10, 7);
681 bitvec_set_uint(bv, r->w11_hi, 1);
682 bitvec_set_uint(bv, r->w11_lo, 6);
683 bitvec_set_uint(bv, r->w12_hi, 2);
684 bitvec_set_uint(bv, r->w12_lo, 5);
685 bitvec_set_uint(bv, r->w13_hi, 3);
686 bitvec_set_uint(bv, r->w13_lo, 4);
687 bitvec_set_uint(bv, r->w14_hi, 4);
688 bitvec_set_uint(bv, r->w14_lo, 3);
689 bitvec_set_uint(bv, r->w15_hi, 5);
690 bitvec_set_uint(bv, r->w15_lo, 2);
691 bitvec_set_uint(bv, r->w16, 6);
692}
693
Harald Welte1f6aad12015-08-15 19:51:45 +0200694/* TS 23.003 Chapter 2.6 */
Harald Weltea1c4f762010-05-01 11:59:42 +0200695int gprs_tlli_type(uint32_t tlli)
696{
697 if ((tlli & 0xc0000000) == 0xc0000000)
698 return TLLI_LOCAL;
699 else if ((tlli & 0xc0000000) == 0x80000000)
700 return TLLI_FOREIGN;
701 else if ((tlli & 0xf8000000) == 0x78000000)
702 return TLLI_RANDOM;
703 else if ((tlli & 0xf8000000) == 0x70000000)
704 return TLLI_AUXILIARY;
Harald Welte1f6aad12015-08-15 19:51:45 +0200705 else if ((tlli & 0xf0000000) == 0x00000000)
706 return TLLI_G_RNTI;
707 else if ((tlli & 0xf0000000) == 0x10000000)
708 return TLLI_RAND_G_RNTI;
Harald Weltea1c4f762010-05-01 11:59:42 +0200709
710 return TLLI_RESERVED;
711}
Harald Weltec2263172010-06-01 10:47:07 +0200712
713uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
714{
715 uint32_t tlli;
716 switch (type) {
717 case TLLI_LOCAL:
718 tlli = p_tmsi | 0xc0000000;
719 break;
720 case TLLI_FOREIGN:
721 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
722 break;
723 default:
724 tlli = 0;
725 break;
726 }
727 return tlli;
728}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200729
730/* Wrappers for deprecated functions: */
731
732int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
733{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100734 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
735 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200736
737 /* Mimic the original behaviour. */
738 return septet_l;
739}
740
741int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
742{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100743 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
744 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200745}
746
747int gsm_7bit_encode(uint8_t *result, const char *data)
748{
749 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100750 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
751 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200752}
753
754int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
755{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100756 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
757 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200758}
759
760int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
761{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100762 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
763 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200764}