blob: 198ec698506c83717a0ffb004f86041446c0e577 [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>
67#include <osmocom/gsm/gsm_utils.h>
Harald Welteec8b4502010-02-20 20:34:29 +010068
69#include <stdlib.h>
70#include <stdint.h>
71#include <string.h>
72#include <stdio.h>
73#include <errno.h>
Harald Welteaebe08c2010-03-04 10:39:17 +010074#include <ctype.h>
Harald Welteec8b4502010-02-20 20:34:29 +010075
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010076#include "../../config.h"
Harald Welteec8b4502010-02-20 20:34:29 +010077
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +080078/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
79 * Greek symbols at hex positions 0x10 and 0x12-0x1a
80 * left out as they can't be handled with a char and
81 * since most phones don't display or write these
82 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +020083 * more complex.
84 *
85 * Note that this table contains the latin1->7bit mapping _and_ has
86 * been merged with the reverse mapping (7bit->latin1) for the
87 * extended characters at offset 0x7f.
88 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +080089static unsigned char gsm_7bit_alphabet[] = {
90 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
91 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
92 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
93 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
94 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
95 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
96 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
97 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
98 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
99 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
100 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
101 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
102 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
103 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
104 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
105 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
106 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
107};
108
Nico Golde28de0532010-07-09 17:19:12 +0200109/* GSM 03.38 6.2.1 Character lookup for decoding */
110static int gsm_septet_lookup(uint8_t ch)
111{
112 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200113 for (; i < sizeof(gsm_7bit_alphabet); i++) {
114 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200115 return i;
116 }
117 return -1;
118}
119
Dennis Wehrle291e6132011-07-24 20:14:13 +0200120/* Compute the number of octets from the number of septets, for instance: 47 septets needs 41,125 = 42 octets */
121uint8_t gsm_get_octet_len(const uint8_t sept_len){
122 int octet_len = (sept_len * 7) / 8;
123 if ((sept_len * 7) % 8 != 0)
124 octet_len++;
125
126 return octet_len;
127}
128
Nico Golde28de0532010-07-09 17:19:12 +0200129/* GSM 03.38 6.2.1 Character unpacking */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200130int 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 +0100131{
132 int i = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200133 int shift = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200134 uint8_t c7, c8;
Nico Goldec56a56d2012-09-18 14:29:40 +0200135 uint8_t next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200136 const char *text_buf_begin = text;
137 const char *text_buf_end = text + n;
138 int nchars;
139
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
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200151 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
152 c7 =
Dennis Wehrle291e6132011-07-24 20:14:13 +0200153 ((user_data[((i + shift) * 7 + 7) >> 3] <<
154 (7 - (((i + shift) * 7 + 7) & 7))) |
155 (user_data[((i + shift) * 7) >> 3] >>
156 (((i + shift) * 7) & 7))) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200157
Harald Weltebe55a8b2012-09-20 10:00:25 +0200158 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200159 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200160 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200161 c8 = gsm_7bit_alphabet[0x7f + c7];
162 } else if (c7 == 0x1b && i + 1 < septet_l) {
163 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200164 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200165 } else {
166 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200167 }
168
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200169 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100170 }
171
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200172 nchars = text - text_buf_begin;
173
Nico Golde28de0532010-07-09 17:19:12 +0200174 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200175
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200176 return nchars;
Nico Golde28de0532010-07-09 17:19:12 +0200177}
178
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200179int 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 +0200180{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200181 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200182}
183
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200184int 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 +0200185{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200186 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200187
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200188 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200189 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200190 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
191 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200192
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200193 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200194}
195
Nico Golde28de0532010-07-09 17:19:12 +0200196/* GSM 03.38 6.2.1 Prepare character packing */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200197int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200198{
199 int i, y = 0;
200 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200201 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200202 ch = data[i];
203 switch(ch){
204 /* fall-through for extension characters */
205 case 0x0c:
206 case 0x5e:
207 case 0x7b:
208 case 0x7d:
209 case 0x5c:
210 case 0x5b:
211 case 0x7e:
212 case 0x5d:
213 case 0x7c:
214 result[y++] = 0x1b;
215 default:
216 result[y] = gsm_7bit_alphabet[ch];
217 break;
218 }
219 y++;
220 }
221
222 return y;
223}
224
Dennis Wehrle291e6132011-07-24 20:14:13 +0200225/* 7bit to octet packing */
Harald Welteca693882013-03-13 15:10:55 +0100226int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
227{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200228 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200229 uint8_t cb, nb;
230 int shift = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200231 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
Nico Golde28de0532010-07-09 17:19:12 +0200232
Dennis Wehrle291e6132011-07-24 20:14:13 +0200233 if (padding) {
234 shift = 7 - padding;
235 /* the first zero is needed for padding */
236 memcpy(data + 1, rdata, septet_len);
237 septet_len++;
238 } else
239 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200240
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200241 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200242 if (shift == 7) {
243 /*
244 * special end case with the. This is necessary if the
245 * last septet fits into the previous octet. E.g. 48
246 * non-extension characters:
247 * ....ag ( a = 1100001, g = 1100111)
248 * result[40] = 100001 XX, result[41] = 1100111 1 */
249 if (i + 1 < septet_len) {
250 shift = 0;
251 continue;
252 } else if (i + 1 == septet_len)
253 break;
Nico Golde28de0532010-07-09 17:19:12 +0200254 }
255
Dennis Wehrle291e6132011-07-24 20:14:13 +0200256 cb = (data[i] & 0x7f) >> shift;
257 if (i + 1 < septet_len) {
258 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200259 cb = cb | nb;
260 }
261
262 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200263 shift++;
264 }
265
Dennis Wehrle291e6132011-07-24 20:14:13 +0200266 free(data);
267
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200268 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100269}
270
Dennis Wehrle291e6132011-07-24 20:14:13 +0200271/* GSM 03.38 6.2.1 Character packing */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200272int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200273{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200274 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200275 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100276 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200277
Dennis Wehrle291e6132011-07-24 20:14:13 +0200278 /* prepare for the worst case, every character expanding to two bytes */
279 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
280 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200281
282 if (y > max_septets) {
283 /*
284 * Limit the number of septets to avoid the generation
285 * of more than n octets.
286 */
287 y = max_septets;
288 }
289
290 o = gsm_septets2octets(result, rdata, y, 0);
291
292 if (octets)
293 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200294
295 free(rdata);
296
297 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200298 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200299 * unique. E.g.:
300 * 1.) 46 non-extension characters + 1 extension character
301 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
302 * 2.) 47 non-extension characters
303 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
304 * 3.) 48 non-extension characters
305 * => (48 * 7 bit) / 8 bit = 42 octects
306 */
307 return y;
308}
309
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200310int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
311{
312 int y;
313
314 y = gsm_7bit_encode_n(result, n, data, octets);
315 /* if last octet contains only one bit, add <CR> */
316 if (((y * 7) & 7) == 1)
317 result[(*octets) - 1] |= ('\r' << 1);
318 /* if last character is <CR> and completely fills last octet, add
319 * another <CR>. */
320 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
321 result[(*octets)++] = '\r';
322 y++;
323 }
324
325 return y;
326}
327
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200328/* convert power class to dBm according to GSM TS 05.05 */
329unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
330{
331 switch (band) {
332 case GSM_BAND_450:
333 case GSM_BAND_480:
334 case GSM_BAND_750:
335 case GSM_BAND_900:
336 case GSM_BAND_810:
337 case GSM_BAND_850:
338 if (class == 1)
339 return 43; /* 20W */
340 if (class == 2)
341 return 39; /* 8W */
342 if (class == 3)
343 return 37; /* 5W */
344 if (class == 4)
345 return 33; /* 2W */
346 if (class == 5)
347 return 29; /* 0.8W */
348 break;
349 case GSM_BAND_1800:
350 if (class == 1)
351 return 30; /* 1W */
352 if (class == 2)
353 return 24; /* 0.25W */
354 if (class == 3)
355 return 36; /* 4W */
356 break;
357 case GSM_BAND_1900:
358 if (class == 1)
359 return 30; /* 1W */
360 if (class == 2)
361 return 24; /* 0.25W */
362 if (class == 3)
363 return 33; /* 2W */
364 break;
365 }
366 return -EINVAL;
367}
368
Harald Welteec8b4502010-02-20 20:34:29 +0100369/* determine power control level for given dBm value, as indicated
370 * by the tables in chapter 4.1.1 of GSM TS 05.05 */
371int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
372{
373 switch (band) {
374 case GSM_BAND_450:
375 case GSM_BAND_480:
376 case GSM_BAND_750:
377 case GSM_BAND_900:
378 case GSM_BAND_810:
379 case GSM_BAND_850:
380 if (dbm >= 39)
381 return 0;
382 else if (dbm < 5)
383 return 19;
384 else {
385 /* we are guaranteed to have (5 <= dbm < 39) */
386 return 2 + ((39 - dbm) / 2);
387 }
388 break;
389 case GSM_BAND_1800:
390 if (dbm >= 36)
391 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200392 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100393 return 30;
394 else if (dbm >= 32)
395 return 31;
396 else if (dbm == 31)
397 return 0;
398 else {
399 /* we are guaranteed to have (0 <= dbm < 31) */
400 return (30 - dbm) / 2;
401 }
402 break;
403 case GSM_BAND_1900:
404 if (dbm >= 33)
405 return 30;
406 else if (dbm >= 32)
407 return 31;
408 else if (dbm == 31)
409 return 0;
410 else {
411 /* we are guaranteed to have (0 <= dbm < 31) */
412 return (30 - dbm) / 2;
413 }
414 break;
415 }
416 return -EINVAL;
417}
418
419int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
420{
421 lvl &= 0x1f;
422
423 switch (band) {
424 case GSM_BAND_450:
425 case GSM_BAND_480:
426 case GSM_BAND_750:
427 case GSM_BAND_900:
428 case GSM_BAND_810:
429 case GSM_BAND_850:
430 if (lvl < 2)
431 return 39;
432 else if (lvl < 20)
433 return 39 - ((lvl - 2) * 2) ;
434 else
435 return 5;
436 break;
437 case GSM_BAND_1800:
438 if (lvl < 16)
439 return 30 - (lvl * 2);
440 else if (lvl < 29)
441 return 0;
442 else
443 return 36 - ((lvl - 29) * 2);
444 break;
445 case GSM_BAND_1900:
446 if (lvl < 16)
447 return 30 - (lvl * 2);
448 else if (lvl < 30)
449 return -EINVAL;
450 else
451 return 33 - (lvl - 30);
452 break;
453 }
454 return -EINVAL;
455}
456
Bhaskar6b30f922013-05-16 17:35:49 +0530457/* According to TS 05.08 Chapter 8.1.4 */
Harald Welteec8b4502010-02-20 20:34:29 +0100458int rxlev2dbm(uint8_t rxlev)
459{
460 if (rxlev > 63)
461 rxlev = 63;
462
463 return -110 + rxlev;
464}
465
Bhaskar6b30f922013-05-16 17:35:49 +0530466/* According to TS 05.08 Chapter 8.1.4 */
Harald Welteec8b4502010-02-20 20:34:29 +0100467uint8_t dbm2rxlev(int dbm)
468{
469 int rxlev = dbm + 110;
470
471 if (rxlev > 63)
472 rxlev = 63;
473 else if (rxlev < 0)
474 rxlev = 0;
475
476 return rxlev;
477}
478
Harald Weltecbc80622010-03-22 08:28:44 +0800479const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100480{
481 switch (band) {
482 case GSM_BAND_450:
483 return "GSM450";
484 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200485 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100486 case GSM_BAND_750:
487 return "GSM750";
488 case GSM_BAND_810:
489 return "GSM810";
490 case GSM_BAND_850:
491 return "GSM850";
492 case GSM_BAND_900:
493 return "GSM900";
494 case GSM_BAND_1800:
495 return "DCS1800";
496 case GSM_BAND_1900:
497 return "PCS1900";
498 }
499 return "invalid";
500}
501
502enum gsm_band gsm_band_parse(const char* mhz)
503{
504 while (*mhz && !isdigit(*mhz))
505 mhz++;
506
507 if (*mhz == '\0')
508 return -EINVAL;
509
Harald Welted3ff15f2010-03-07 18:23:47 +0100510 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100511 case 450:
512 return GSM_BAND_450;
513 case 480:
514 return GSM_BAND_480;
515 case 750:
516 return GSM_BAND_750;
517 case 810:
518 return GSM_BAND_810;
519 case 850:
520 return GSM_BAND_850;
521 case 900:
522 return GSM_BAND_900;
523 case 1800:
524 return GSM_BAND_1800;
525 case 1900:
526 return GSM_BAND_1900;
527 default:
528 return -EINVAL;
529 }
530}
531
Harald Welte622b7182010-03-07 17:50:21 +0100532enum gsm_band gsm_arfcn2band(uint16_t arfcn)
533{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100534 int is_pcs = arfcn & ARFCN_PCS;
535
536 arfcn &= ~ARFCN_FLAG_MASK;
537
538 if (is_pcs)
Harald Welte622b7182010-03-07 17:50:21 +0100539 return GSM_BAND_1900;
540 else if (arfcn <= 124)
541 return GSM_BAND_900;
542 else if (arfcn >= 955 && arfcn <= 1023)
543 return GSM_BAND_900;
544 else if (arfcn >= 128 && arfcn <= 251)
545 return GSM_BAND_850;
546 else if (arfcn >= 512 && arfcn <= 885)
547 return GSM_BAND_1800;
548 else if (arfcn >= 259 && arfcn <= 293)
549 return GSM_BAND_450;
550 else if (arfcn >= 306 && arfcn <= 340)
551 return GSM_BAND_480;
552 else if (arfcn >= 350 && arfcn <= 425)
553 return GSM_BAND_810;
554 else if (arfcn >= 438 && arfcn <= 511)
555 return GSM_BAND_750;
556 else
557 return GSM_BAND_1800;
558}
559
Sylvain Munaut55720312012-12-11 23:44:41 +0100560struct gsm_freq_range {
561 uint16_t arfcn_first;
562 uint16_t arfcn_last;
563 uint16_t freq_ul_first;
564 uint16_t freq_dl_offset;
565 uint16_t flags;
566};
567
568static struct gsm_freq_range gsm_ranges[] = {
569 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
570 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
571 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
572 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
573 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
574 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
575 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
576 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
577 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
578 { /* Guard */ }
579};
580
Harald Welte622b7182010-03-07 17:50:21 +0100581/* Convert an ARFCN to the frequency in MHz * 10 */
582uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
583{
Sylvain Munaut55720312012-12-11 23:44:41 +0100584 struct gsm_freq_range *r;
585 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
586 uint16_t freq10_ul = 0xffff;
587 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100588
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100589 arfcn &= ~ARFCN_FLAG_MASK;
590
Sylvain Munaut55720312012-12-11 23:44:41 +0100591 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
592 if ((flags == r->flags) &&
593 (arfcn >= r->arfcn_first) &&
594 (arfcn <= r->arfcn_last))
595 {
596 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
597 freq10_dl = freq10_ul + r->freq_dl_offset;
598 break;
599 }
600 }
601
602 return uplink ? freq10_ul : freq10_dl;
603}
604
605/* Convert a Frequency in MHz * 10 to ARFCN */
606uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
607{
608 struct gsm_freq_range *r;
609 uint16_t freq10_lo, freq10_hi;
610 uint16_t arfcn = 0xffff;
611
612 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
613 /* Generate frequency limits */
614 freq10_lo = r->freq_ul_first;
615 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
616 if (!uplink) {
617 freq10_lo += r->freq_dl_offset;
618 freq10_hi += r->freq_dl_offset;
619 }
620
621 /* Check if this fits */
622 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
623 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
624 arfcn |= r->flags;
625 break;
626 }
627 }
Harald Welte622b7182010-03-07 17:50:21 +0100628
629 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100630 arfcn |= ARFCN_UPLINK;
631
632 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100633}
634
635void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
636{
637 time->fn = fn;
638 time->t1 = time->fn / (26*51);
639 time->t2 = time->fn % 26;
640 time->t3 = time->fn % 51;
641 time->tc = (time->fn / 51) % 8;
642}
643
644uint32_t gsm_gsmtime2fn(struct gsm_time *time)
645{
646 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
647 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
648}
Harald Weltea1c4f762010-05-01 11:59:42 +0200649
650/* TS 03.03 Chapter 2.6 */
651int gprs_tlli_type(uint32_t tlli)
652{
653 if ((tlli & 0xc0000000) == 0xc0000000)
654 return TLLI_LOCAL;
655 else if ((tlli & 0xc0000000) == 0x80000000)
656 return TLLI_FOREIGN;
657 else if ((tlli & 0xf8000000) == 0x78000000)
658 return TLLI_RANDOM;
659 else if ((tlli & 0xf8000000) == 0x70000000)
660 return TLLI_AUXILIARY;
661
662 return TLLI_RESERVED;
663}
Harald Weltec2263172010-06-01 10:47:07 +0200664
665uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
666{
667 uint32_t tlli;
668 switch (type) {
669 case TLLI_LOCAL:
670 tlli = p_tmsi | 0xc0000000;
671 break;
672 case TLLI_FOREIGN:
673 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
674 break;
675 default:
676 tlli = 0;
677 break;
678 }
679 return tlli;
680}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200681
682/* Wrappers for deprecated functions: */
683
684int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
685{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100686 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
687 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200688
689 /* Mimic the original behaviour. */
690 return septet_l;
691}
692
693int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
694{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100695 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
696 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200697}
698
699int gsm_7bit_encode(uint8_t *result, const char *data)
700{
701 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100702 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
703 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200704}
705
706int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
707{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100708 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
709 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200710}
711
712int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
713{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100714 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
715 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200716}