blob: 7365ab7cece15cea6949570dee715ef9451d8b58 [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>
Max764b0222016-05-11 17:33:17 +020069#include <osmocom/gsm/meas_rep.h>
Max8a5346b2016-04-22 19:28:09 +020070#include <osmocom/gsm/protocol/gsm_04_08.h>
Harald Welteec8b4502010-02-20 20:34:29 +010071
72#include <stdlib.h>
73#include <stdint.h>
74#include <string.h>
Max764b0222016-05-11 17:33:17 +020075#include <stdbool.h>
Harald Welteec8b4502010-02-20 20:34:29 +010076#include <stdio.h>
77#include <errno.h>
Harald Welteaebe08c2010-03-04 10:39:17 +010078#include <ctype.h>
Harald Welteec8b4502010-02-20 20:34:29 +010079
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010080#include "../../config.h"
Harald Welteec8b4502010-02-20 20:34:29 +010081
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +080082/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
83 * Greek symbols at hex positions 0x10 and 0x12-0x1a
84 * left out as they can't be handled with a char and
85 * since most phones don't display or write these
86 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +020087 * more complex.
88 *
89 * Note that this table contains the latin1->7bit mapping _and_ has
90 * been merged with the reverse mapping (7bit->latin1) for the
91 * extended characters at offset 0x7f.
92 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +080093static unsigned char gsm_7bit_alphabet[] = {
94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
95 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
96 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
97 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
98 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
99 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
100 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
101 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
102 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
103 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
104 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
105 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
106 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
107 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
108 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
109 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
110 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
111};
112
Nico Golde28de0532010-07-09 17:19:12 +0200113/* GSM 03.38 6.2.1 Character lookup for decoding */
114static int gsm_septet_lookup(uint8_t ch)
115{
116 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200117 for (; i < sizeof(gsm_7bit_alphabet); i++) {
118 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200119 return i;
120 }
121 return -1;
122}
123
Dennis Wehrle291e6132011-07-24 20:14:13 +0200124/* Compute the number of octets from the number of septets, for instance: 47 septets needs 41,125 = 42 octets */
125uint8_t gsm_get_octet_len(const uint8_t sept_len){
126 int octet_len = (sept_len * 7) / 8;
127 if ((sept_len * 7) % 8 != 0)
128 octet_len++;
129
130 return octet_len;
131}
132
Nico Golde28de0532010-07-09 17:19:12 +0200133/* GSM 03.38 6.2.1 Character unpacking */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200134int 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 +0100135{
Maxcf37c4c2016-01-21 16:52:40 +0100136 unsigned shift = 0;
137 uint8_t c7, c8, next_is_ext = 0, lu, ru;
138 const uint8_t maxlen = gsm_get_octet_len(septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200139 const char *text_buf_begin = text;
140 const char *text_buf_end = text + n;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200141
142 OSMO_ASSERT (n > 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100143
Dennis Wehrle291e6132011-07-24 20:14:13 +0200144 /* skip the user data header */
145 if (ud_hdr_ind) {
146 /* get user data header length + 1 (for the 'user data header length'-field) */
147 shift = ((user_data[0] + 1) * 8) / 7;
148 if ((((user_data[0] + 1) * 8) % 7) != 0)
149 shift++;
150 septet_l = septet_l - shift;
151 }
152
Maxcf37c4c2016-01-21 16:52:40 +0100153 unsigned i, l, r;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200154 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
Maxcf37c4c2016-01-21 16:52:40 +0100155
156 l = ((i + shift) * 7 + 7) >> 3;
157 r = ((i + shift) * 7) >> 3;
158
159 /* the left side index is always >= right side index
160 sometimes it even gets beyond array boundary
161 check for that explicitly and force 0 instead
162 */
163 if (l >= maxlen)
164 lu = 0;
165 else
166 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
167
168 ru = user_data[r] >> (((i + shift) * 7) & 7);
169
170 c7 = (lu | ru) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200171
Harald Weltebe55a8b2012-09-20 10:00:25 +0200172 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200173 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200174 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200175 c8 = gsm_7bit_alphabet[0x7f + c7];
176 } else if (c7 == 0x1b && i + 1 < septet_l) {
177 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200178 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200179 } else {
180 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200181 }
182
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200183 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100184 }
185
Nico Golde28de0532010-07-09 17:19:12 +0200186 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200187
Maxcf37c4c2016-01-21 16:52:40 +0100188 return text - text_buf_begin;
Nico Golde28de0532010-07-09 17:19:12 +0200189}
190
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200191int 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 +0200192{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200193 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200194}
195
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200196int 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 +0200197{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200198 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200199
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200200 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200201 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200202 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
203 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200204
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200205 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200206}
207
Nico Golde28de0532010-07-09 17:19:12 +0200208/* GSM 03.38 6.2.1 Prepare character packing */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200209int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200210{
211 int i, y = 0;
212 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200213 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200214 ch = data[i];
215 switch(ch){
216 /* fall-through for extension characters */
217 case 0x0c:
218 case 0x5e:
219 case 0x7b:
220 case 0x7d:
221 case 0x5c:
222 case 0x5b:
223 case 0x7e:
224 case 0x5d:
225 case 0x7c:
226 result[y++] = 0x1b;
227 default:
228 result[y] = gsm_7bit_alphabet[ch];
229 break;
230 }
231 y++;
232 }
233
234 return y;
235}
236
Dennis Wehrle291e6132011-07-24 20:14:13 +0200237/* 7bit to octet packing */
Harald Welteca693882013-03-13 15:10:55 +0100238int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
239{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200240 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200241 uint8_t cb, nb;
242 int shift = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200243 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
Nico Golde28de0532010-07-09 17:19:12 +0200244
Dennis Wehrle291e6132011-07-24 20:14:13 +0200245 if (padding) {
246 shift = 7 - padding;
247 /* the first zero is needed for padding */
248 memcpy(data + 1, rdata, septet_len);
249 septet_len++;
250 } else
251 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200252
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200253 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200254 if (shift == 7) {
255 /*
256 * special end case with the. This is necessary if the
257 * last septet fits into the previous octet. E.g. 48
258 * non-extension characters:
259 * ....ag ( a = 1100001, g = 1100111)
260 * result[40] = 100001 XX, result[41] = 1100111 1 */
261 if (i + 1 < septet_len) {
262 shift = 0;
263 continue;
264 } else if (i + 1 == septet_len)
265 break;
Nico Golde28de0532010-07-09 17:19:12 +0200266 }
267
Dennis Wehrle291e6132011-07-24 20:14:13 +0200268 cb = (data[i] & 0x7f) >> shift;
269 if (i + 1 < septet_len) {
270 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200271 cb = cb | nb;
272 }
273
274 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200275 shift++;
276 }
277
Dennis Wehrle291e6132011-07-24 20:14:13 +0200278 free(data);
279
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200280 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100281}
282
Dennis Wehrle291e6132011-07-24 20:14:13 +0200283/* GSM 03.38 6.2.1 Character packing */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200284int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200285{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200286 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200287 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100288 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200289
Dennis Wehrle291e6132011-07-24 20:14:13 +0200290 /* prepare for the worst case, every character expanding to two bytes */
291 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
292 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200293
294 if (y > max_septets) {
295 /*
296 * Limit the number of septets to avoid the generation
297 * of more than n octets.
298 */
299 y = max_septets;
300 }
301
302 o = gsm_septets2octets(result, rdata, y, 0);
303
304 if (octets)
305 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200306
307 free(rdata);
308
309 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200310 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200311 * unique. E.g.:
312 * 1.) 46 non-extension characters + 1 extension character
313 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
314 * 2.) 47 non-extension characters
315 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
316 * 3.) 48 non-extension characters
317 * => (48 * 7 bit) / 8 bit = 42 octects
318 */
319 return y;
320}
321
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200322int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
323{
324 int y;
325
326 y = gsm_7bit_encode_n(result, n, data, octets);
327 /* if last octet contains only one bit, add <CR> */
328 if (((y * 7) & 7) == 1)
329 result[(*octets) - 1] |= ('\r' << 1);
330 /* if last character is <CR> and completely fills last octet, add
331 * another <CR>. */
332 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
333 result[(*octets)++] = '\r';
334 y++;
335 }
336
337 return y;
338}
339
Max764b0222016-05-11 17:33:17 +0200340/*! \brief Build the RSL uplink measurement IE (3GPP TS 08.58 § 9.3.25)
341 * \param[in] mru Unidirectional measurement report structure
342 * \param[in] dtxd_used Indicates if DTXd was used during measurement report
343 * period
344 * \param[out] buf Pre-allocated bufer for storing IE
345 * \returns Number of bytes filled in buf
346 */
347size_t gsm0858_rsl_ul_meas_enc(struct gsm_meas_rep_unidir *mru, bool dtxd_used,
348 uint8_t *buf)
349{
350 buf[0] = dtxd_used ? (1 << 6) : 0;
351 buf[0] |= (mru->full.rx_lev & 0x3f);
352 buf[1] = (mru->sub.rx_lev & 0x3f);
353 buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
354
355 return 3;
356}
357
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200358/* convert power class to dBm according to GSM TS 05.05 */
359unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
360{
361 switch (band) {
362 case GSM_BAND_450:
363 case GSM_BAND_480:
364 case GSM_BAND_750:
365 case GSM_BAND_900:
366 case GSM_BAND_810:
367 case GSM_BAND_850:
368 if (class == 1)
369 return 43; /* 20W */
370 if (class == 2)
371 return 39; /* 8W */
372 if (class == 3)
373 return 37; /* 5W */
374 if (class == 4)
375 return 33; /* 2W */
376 if (class == 5)
377 return 29; /* 0.8W */
378 break;
379 case GSM_BAND_1800:
380 if (class == 1)
381 return 30; /* 1W */
382 if (class == 2)
383 return 24; /* 0.25W */
384 if (class == 3)
385 return 36; /* 4W */
386 break;
387 case GSM_BAND_1900:
388 if (class == 1)
389 return 30; /* 1W */
390 if (class == 2)
391 return 24; /* 0.25W */
392 if (class == 3)
393 return 33; /* 2W */
394 break;
395 }
396 return -EINVAL;
397}
398
Harald Welteec8b4502010-02-20 20:34:29 +0100399/* determine power control level for given dBm value, as indicated
400 * by the tables in chapter 4.1.1 of GSM TS 05.05 */
401int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
402{
403 switch (band) {
404 case GSM_BAND_450:
405 case GSM_BAND_480:
406 case GSM_BAND_750:
407 case GSM_BAND_900:
408 case GSM_BAND_810:
409 case GSM_BAND_850:
410 if (dbm >= 39)
411 return 0;
412 else if (dbm < 5)
413 return 19;
414 else {
415 /* we are guaranteed to have (5 <= dbm < 39) */
416 return 2 + ((39 - dbm) / 2);
417 }
418 break;
419 case GSM_BAND_1800:
420 if (dbm >= 36)
421 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200422 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100423 return 30;
424 else if (dbm >= 32)
425 return 31;
426 else if (dbm == 31)
427 return 0;
428 else {
429 /* we are guaranteed to have (0 <= dbm < 31) */
430 return (30 - dbm) / 2;
431 }
432 break;
433 case GSM_BAND_1900:
434 if (dbm >= 33)
435 return 30;
436 else if (dbm >= 32)
437 return 31;
438 else if (dbm == 31)
439 return 0;
440 else {
441 /* we are guaranteed to have (0 <= dbm < 31) */
442 return (30 - dbm) / 2;
443 }
444 break;
445 }
446 return -EINVAL;
447}
448
449int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
450{
451 lvl &= 0x1f;
452
453 switch (band) {
454 case GSM_BAND_450:
455 case GSM_BAND_480:
456 case GSM_BAND_750:
457 case GSM_BAND_900:
458 case GSM_BAND_810:
459 case GSM_BAND_850:
460 if (lvl < 2)
461 return 39;
462 else if (lvl < 20)
463 return 39 - ((lvl - 2) * 2) ;
464 else
465 return 5;
466 break;
467 case GSM_BAND_1800:
468 if (lvl < 16)
469 return 30 - (lvl * 2);
470 else if (lvl < 29)
471 return 0;
472 else
473 return 36 - ((lvl - 29) * 2);
474 break;
475 case GSM_BAND_1900:
476 if (lvl < 16)
477 return 30 - (lvl * 2);
478 else if (lvl < 30)
479 return -EINVAL;
480 else
481 return 33 - (lvl - 30);
482 break;
483 }
484 return -EINVAL;
485}
486
Bhaskar6b30f922013-05-16 17:35:49 +0530487/* According to TS 05.08 Chapter 8.1.4 */
Harald Welteec8b4502010-02-20 20:34:29 +0100488int rxlev2dbm(uint8_t rxlev)
489{
490 if (rxlev > 63)
491 rxlev = 63;
492
493 return -110 + rxlev;
494}
495
Bhaskar6b30f922013-05-16 17:35:49 +0530496/* According to TS 05.08 Chapter 8.1.4 */
Harald Welteec8b4502010-02-20 20:34:29 +0100497uint8_t dbm2rxlev(int dbm)
498{
499 int rxlev = dbm + 110;
500
501 if (rxlev > 63)
502 rxlev = 63;
503 else if (rxlev < 0)
504 rxlev = 0;
505
506 return rxlev;
507}
508
Harald Weltecbc80622010-03-22 08:28:44 +0800509const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100510{
511 switch (band) {
512 case GSM_BAND_450:
513 return "GSM450";
514 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200515 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100516 case GSM_BAND_750:
517 return "GSM750";
518 case GSM_BAND_810:
519 return "GSM810";
520 case GSM_BAND_850:
521 return "GSM850";
522 case GSM_BAND_900:
523 return "GSM900";
524 case GSM_BAND_1800:
525 return "DCS1800";
526 case GSM_BAND_1900:
527 return "PCS1900";
528 }
529 return "invalid";
530}
531
532enum gsm_band gsm_band_parse(const char* mhz)
533{
534 while (*mhz && !isdigit(*mhz))
535 mhz++;
536
537 if (*mhz == '\0')
538 return -EINVAL;
539
Harald Welted3ff15f2010-03-07 18:23:47 +0100540 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100541 case 450:
542 return GSM_BAND_450;
543 case 480:
544 return GSM_BAND_480;
545 case 750:
546 return GSM_BAND_750;
547 case 810:
548 return GSM_BAND_810;
549 case 850:
550 return GSM_BAND_850;
551 case 900:
552 return GSM_BAND_900;
553 case 1800:
554 return GSM_BAND_1800;
555 case 1900:
556 return GSM_BAND_1900;
557 default:
558 return -EINVAL;
559 }
560}
561
Harald Welte622b7182010-03-07 17:50:21 +0100562enum gsm_band gsm_arfcn2band(uint16_t arfcn)
563{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100564 int is_pcs = arfcn & ARFCN_PCS;
565
566 arfcn &= ~ARFCN_FLAG_MASK;
567
568 if (is_pcs)
Harald Welte622b7182010-03-07 17:50:21 +0100569 return GSM_BAND_1900;
570 else if (arfcn <= 124)
571 return GSM_BAND_900;
572 else if (arfcn >= 955 && arfcn <= 1023)
573 return GSM_BAND_900;
574 else if (arfcn >= 128 && arfcn <= 251)
575 return GSM_BAND_850;
576 else if (arfcn >= 512 && arfcn <= 885)
577 return GSM_BAND_1800;
578 else if (arfcn >= 259 && arfcn <= 293)
579 return GSM_BAND_450;
580 else if (arfcn >= 306 && arfcn <= 340)
581 return GSM_BAND_480;
582 else if (arfcn >= 350 && arfcn <= 425)
583 return GSM_BAND_810;
584 else if (arfcn >= 438 && arfcn <= 511)
585 return GSM_BAND_750;
586 else
587 return GSM_BAND_1800;
588}
589
Sylvain Munaut55720312012-12-11 23:44:41 +0100590struct gsm_freq_range {
591 uint16_t arfcn_first;
592 uint16_t arfcn_last;
593 uint16_t freq_ul_first;
594 uint16_t freq_dl_offset;
595 uint16_t flags;
596};
597
598static struct gsm_freq_range gsm_ranges[] = {
599 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
600 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
601 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
602 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
603 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
604 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
605 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
606 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
607 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
608 { /* Guard */ }
609};
610
Harald Welte622b7182010-03-07 17:50:21 +0100611/* Convert an ARFCN to the frequency in MHz * 10 */
612uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
613{
Sylvain Munaut55720312012-12-11 23:44:41 +0100614 struct gsm_freq_range *r;
615 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
616 uint16_t freq10_ul = 0xffff;
617 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100618
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100619 arfcn &= ~ARFCN_FLAG_MASK;
620
Sylvain Munaut55720312012-12-11 23:44:41 +0100621 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
622 if ((flags == r->flags) &&
623 (arfcn >= r->arfcn_first) &&
624 (arfcn <= r->arfcn_last))
625 {
626 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
627 freq10_dl = freq10_ul + r->freq_dl_offset;
628 break;
629 }
630 }
631
632 return uplink ? freq10_ul : freq10_dl;
633}
634
635/* Convert a Frequency in MHz * 10 to ARFCN */
636uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
637{
638 struct gsm_freq_range *r;
639 uint16_t freq10_lo, freq10_hi;
640 uint16_t arfcn = 0xffff;
641
642 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
643 /* Generate frequency limits */
644 freq10_lo = r->freq_ul_first;
645 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
646 if (!uplink) {
647 freq10_lo += r->freq_dl_offset;
648 freq10_hi += r->freq_dl_offset;
649 }
650
651 /* Check if this fits */
652 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
653 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
654 arfcn |= r->flags;
655 break;
656 }
657 }
Harald Welte622b7182010-03-07 17:50:21 +0100658
659 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100660 arfcn |= ARFCN_UPLINK;
661
662 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100663}
664
665void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
666{
667 time->fn = fn;
668 time->t1 = time->fn / (26*51);
669 time->t2 = time->fn % 26;
670 time->t3 = time->fn % 51;
671 time->tc = (time->fn / 51) % 8;
672}
673
674uint32_t gsm_gsmtime2fn(struct gsm_time *time)
675{
676 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
677 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
678}
Harald Weltea1c4f762010-05-01 11:59:42 +0200679
Max8a5346b2016-04-22 19:28:09 +0200680/*! \brief append range1024 encoded data to bit vector */
681void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
682{
683 bitvec_set_uint(bv, r->w1_hi, 2);
684 bitvec_set_uint(bv, r->w1_lo, 8);
685 bitvec_set_uint(bv, r->w2_hi, 8);
686 bitvec_set_uint(bv, r->w2_lo, 1);
687 bitvec_set_uint(bv, r->w3_hi, 7);
688 bitvec_set_uint(bv, r->w3_lo, 2);
689 bitvec_set_uint(bv, r->w4_hi, 6);
690 bitvec_set_uint(bv, r->w4_lo, 2);
691 bitvec_set_uint(bv, r->w5_hi, 6);
692 bitvec_set_uint(bv, r->w5_lo, 2);
693 bitvec_set_uint(bv, r->w6_hi, 6);
694 bitvec_set_uint(bv, r->w6_lo, 2);
695 bitvec_set_uint(bv, r->w7_hi, 6);
696 bitvec_set_uint(bv, r->w7_lo, 2);
697 bitvec_set_uint(bv, r->w8_hi, 6);
698 bitvec_set_uint(bv, r->w8_lo, 1);
699 bitvec_set_uint(bv, r->w9, 7);
700 bitvec_set_uint(bv, r->w10, 7);
701 bitvec_set_uint(bv, r->w11_hi, 1);
702 bitvec_set_uint(bv, r->w11_lo, 6);
703 bitvec_set_uint(bv, r->w12_hi, 2);
704 bitvec_set_uint(bv, r->w12_lo, 5);
705 bitvec_set_uint(bv, r->w13_hi, 3);
706 bitvec_set_uint(bv, r->w13_lo, 4);
707 bitvec_set_uint(bv, r->w14_hi, 4);
708 bitvec_set_uint(bv, r->w14_lo, 3);
709 bitvec_set_uint(bv, r->w15_hi, 5);
710 bitvec_set_uint(bv, r->w15_lo, 2);
711 bitvec_set_uint(bv, r->w16, 6);
712}
713
Harald Welte1f6aad12015-08-15 19:51:45 +0200714/* TS 23.003 Chapter 2.6 */
Harald Weltea1c4f762010-05-01 11:59:42 +0200715int gprs_tlli_type(uint32_t tlli)
716{
717 if ((tlli & 0xc0000000) == 0xc0000000)
718 return TLLI_LOCAL;
719 else if ((tlli & 0xc0000000) == 0x80000000)
720 return TLLI_FOREIGN;
721 else if ((tlli & 0xf8000000) == 0x78000000)
722 return TLLI_RANDOM;
723 else if ((tlli & 0xf8000000) == 0x70000000)
724 return TLLI_AUXILIARY;
Harald Welte1f6aad12015-08-15 19:51:45 +0200725 else if ((tlli & 0xf0000000) == 0x00000000)
726 return TLLI_G_RNTI;
727 else if ((tlli & 0xf0000000) == 0x10000000)
728 return TLLI_RAND_G_RNTI;
Harald Weltea1c4f762010-05-01 11:59:42 +0200729
730 return TLLI_RESERVED;
731}
Harald Weltec2263172010-06-01 10:47:07 +0200732
733uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
734{
735 uint32_t tlli;
736 switch (type) {
737 case TLLI_LOCAL:
738 tlli = p_tmsi | 0xc0000000;
739 break;
740 case TLLI_FOREIGN:
741 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
742 break;
743 default:
744 tlli = 0;
745 break;
746 }
747 return tlli;
748}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200749
750/* Wrappers for deprecated functions: */
751
752int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
753{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100754 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
755 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200756
757 /* Mimic the original behaviour. */
758 return septet_l;
759}
760
761int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
762{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100763 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
764 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200765}
766
767int gsm_7bit_encode(uint8_t *result, const char *data)
768{
769 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100770 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
771 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200772}
773
774int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
775{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100776 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
777 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200778}
779
780int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
781{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100782 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
783 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200784}