blob: 9cb5df62ddeb3be67e62ff4d6abe1ec817f08169 [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 *
Harald Welte71658802017-06-12 15:40:52 +020044 * libosmogsm is developed as part of the Osmocom (Open Source Mobile
45 * Communications) project, a community-based, collaborative development
46 * project to create Free and Open Source implementations of mobile
47 * communications systems. For more information about Osmocom, please
48 * see https://osmocom.org/
49 *
Harald Welted38c8b82011-08-30 11:32:56 +020050 * \section sec_copyright Copyright and License
51 * Copyright © 2008-2011 - Harald Welte, Holger Freyther and contributors\n
52 * All rights reserved. \n\n
53 * The source code of libosmogsm is licensed under the terms of the GNU
54 * General Public License as published by the Free Software Foundation;
55 * either version 2 of the License, or (at your option) any later
56 * version.\n
57 * See <http://www.gnu.org/licenses/> or COPYING included in the source
58 * code package istelf.\n
59 * The information detailed here is provided AS IS with NO WARRANTY OF
60 * ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
61 * FITNESS FOR A PARTICULAR PURPOSE.
62 * \n\n
63 *
Harald Welte71658802017-06-12 15:40:52 +020064 * \section sec_tracker Homepage + Issue Tracker
65 * libosmogsm is distributed as part of libosmocore and shares its
66 * project page at http://osmocom.org/projects/libosmocore
67 *
68 * An Issue Tracker can be found at
69 * https://osmocom.org/projects/libosmocore/issues
70 *
Harald Welted38c8b82011-08-30 11:32:56 +020071 * \section sec_contact Contact and Support
72 * Community-based support is available at the OpenBSC mailing list
73 * <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
74 * Commercial support options available upon request from
75 * <http://sysmocom.de/>
76 */
77
Harald Welteec8b4502010-02-20 20:34:29 +010078//#include <openbsc/gsm_data.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010079#include <osmocom/core/utils.h>
Max8a5346b2016-04-22 19:28:09 +020080#include <osmocom/core/bitvec.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010081#include <osmocom/gsm/gsm_utils.h>
Max764b0222016-05-11 17:33:17 +020082#include <osmocom/gsm/meas_rep.h>
Max8a5346b2016-04-22 19:28:09 +020083#include <osmocom/gsm/protocol/gsm_04_08.h>
Harald Welteec8b4502010-02-20 20:34:29 +010084
85#include <stdlib.h>
86#include <stdint.h>
87#include <string.h>
Max764b0222016-05-11 17:33:17 +020088#include <stdbool.h>
Harald Welteec8b4502010-02-20 20:34:29 +010089#include <stdio.h>
90#include <errno.h>
Harald Welteaebe08c2010-03-04 10:39:17 +010091#include <ctype.h>
Harald Welteec8b4502010-02-20 20:34:29 +010092
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010093#include "../../config.h"
Harald Welteec8b4502010-02-20 20:34:29 +010094
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +080095/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
96 * Greek symbols at hex positions 0x10 and 0x12-0x1a
97 * left out as they can't be handled with a char and
98 * since most phones don't display or write these
99 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +0200100 * more complex.
101 *
102 * Note that this table contains the latin1->7bit mapping _and_ has
103 * been merged with the reverse mapping (7bit->latin1) for the
104 * extended characters at offset 0x7f.
105 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800106static unsigned char gsm_7bit_alphabet[] = {
107 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
109 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
110 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
111 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
112 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
113 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
114 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
115 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
116 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
117 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
118 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
119 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
120 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
121 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
122 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
123 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
124};
125
Nico Golde28de0532010-07-09 17:19:12 +0200126/* GSM 03.38 6.2.1 Character lookup for decoding */
127static int gsm_septet_lookup(uint8_t ch)
128{
129 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200130 for (; i < sizeof(gsm_7bit_alphabet); i++) {
131 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200132 return i;
133 }
134 return -1;
135}
136
Harald Welte96e2a002017-06-12 21:44:18 +0200137/*! \brife Compute number of octets from number of septets,
138 * for instance: 47 septets needs 41,125 = 42 octets
139 * \param[in sept_len Number of Septets
140 * \returns Number of octets required */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200141uint8_t gsm_get_octet_len(const uint8_t sept_len){
142 int octet_len = (sept_len * 7) / 8;
143 if ((sept_len * 7) % 8 != 0)
144 octet_len++;
145
146 return octet_len;
147}
148
Harald Welte96e2a002017-06-12 21:44:18 +0200149/*! \brief TS 03.38 7-bit Character unpacking (6.2.1)
150 * \param[out] text Caller-provided output text buffer
151 * \param[in] n Length of \a text
152 * \param[in] user_data Input Data (septets)
153 * \param[in] septet_l Number of septets in \a user_data
154 * \param[in] ud_hdr_ind User Data Header present in data
155 * \returns number of bytes written to \a text */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200156int 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 +0100157{
Maxcf37c4c2016-01-21 16:52:40 +0100158 unsigned shift = 0;
159 uint8_t c7, c8, next_is_ext = 0, lu, ru;
160 const uint8_t maxlen = gsm_get_octet_len(septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200161 const char *text_buf_begin = text;
162 const char *text_buf_end = text + n;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200163
164 OSMO_ASSERT (n > 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100165
Dennis Wehrle291e6132011-07-24 20:14:13 +0200166 /* skip the user data header */
167 if (ud_hdr_ind) {
168 /* get user data header length + 1 (for the 'user data header length'-field) */
169 shift = ((user_data[0] + 1) * 8) / 7;
170 if ((((user_data[0] + 1) * 8) % 7) != 0)
171 shift++;
172 septet_l = septet_l - shift;
173 }
174
Maxcf37c4c2016-01-21 16:52:40 +0100175 unsigned i, l, r;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200176 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
Maxcf37c4c2016-01-21 16:52:40 +0100177
178 l = ((i + shift) * 7 + 7) >> 3;
179 r = ((i + shift) * 7) >> 3;
180
181 /* the left side index is always >= right side index
182 sometimes it even gets beyond array boundary
183 check for that explicitly and force 0 instead
184 */
185 if (l >= maxlen)
186 lu = 0;
187 else
188 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
189
190 ru = user_data[r] >> (((i + shift) * 7) & 7);
191
192 c7 = (lu | ru) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200193
Harald Weltebe55a8b2012-09-20 10:00:25 +0200194 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200195 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200196 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200197 c8 = gsm_7bit_alphabet[0x7f + c7];
198 } else if (c7 == 0x1b && i + 1 < septet_l) {
199 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200200 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200201 } else {
202 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200203 }
204
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200205 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100206 }
207
Nico Golde28de0532010-07-09 17:19:12 +0200208 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200209
Maxcf37c4c2016-01-21 16:52:40 +0100210 return text - text_buf_begin;
Nico Golde28de0532010-07-09 17:19:12 +0200211}
212
Harald Welte96e2a002017-06-12 21:44:18 +0200213/*! \brief Decode 7bit GSM Alphabet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200214int 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 +0200215{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200216 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200217}
218
Harald Welte96e2a002017-06-12 21:44:18 +0200219/*! \brief Decode 7bit GSM Alphabet (USSD) */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200220int 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 +0200221{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200222 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200223
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200224 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200225 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200226 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
227 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200228
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200229 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200230}
231
Harald Welte96e2a002017-06-12 21:44:18 +0200232/*! \brief Encode a ASCII characterrs as 7-bit GSM alphabet (TS 03.38)
233 *
234 * This function converts a zero-terminated input string \a data from
235 * ASCII into octet-aligned 7-bit GSM characters. No packing is
236 * performed.
237 *
238 * \param[out] result caller-allocated output buffer
239 * \param[in] data input data, ASCII
240 * \returns number of octets used in \a result */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200241int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200242{
243 int i, y = 0;
244 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200245 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200246 ch = data[i];
247 switch(ch){
248 /* fall-through for extension characters */
249 case 0x0c:
250 case 0x5e:
251 case 0x7b:
252 case 0x7d:
253 case 0x5c:
254 case 0x5b:
255 case 0x7e:
256 case 0x5d:
257 case 0x7c:
258 result[y++] = 0x1b;
259 default:
260 result[y] = gsm_7bit_alphabet[ch];
261 break;
262 }
263 y++;
264 }
265
266 return y;
267}
268
Harald Welte96e2a002017-06-12 21:44:18 +0200269/*! \brief GSM Default Alphabet 7bit to octet packing
270 * \param[out] result Caller-provided output buffer
271 * \param[in] rdata Input data septets
272 * \param[in] septet_len Length of \a rdata
273 * \param[in] padding padding bits at start
274 * \returns number of bytes used in \a result */
Harald Welteca693882013-03-13 15:10:55 +0100275int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
276{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200277 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200278 uint8_t cb, nb;
279 int shift = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200280 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
Nico Golde28de0532010-07-09 17:19:12 +0200281
Dennis Wehrle291e6132011-07-24 20:14:13 +0200282 if (padding) {
283 shift = 7 - padding;
284 /* the first zero is needed for padding */
285 memcpy(data + 1, rdata, septet_len);
286 septet_len++;
287 } else
288 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200289
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200290 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200291 if (shift == 7) {
292 /*
293 * special end case with the. This is necessary if the
294 * last septet fits into the previous octet. E.g. 48
295 * non-extension characters:
296 * ....ag ( a = 1100001, g = 1100111)
297 * result[40] = 100001 XX, result[41] = 1100111 1 */
298 if (i + 1 < septet_len) {
299 shift = 0;
300 continue;
301 } else if (i + 1 == septet_len)
302 break;
Nico Golde28de0532010-07-09 17:19:12 +0200303 }
304
Dennis Wehrle291e6132011-07-24 20:14:13 +0200305 cb = (data[i] & 0x7f) >> shift;
306 if (i + 1 < septet_len) {
307 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200308 cb = cb | nb;
309 }
310
311 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200312 shift++;
313 }
314
Dennis Wehrle291e6132011-07-24 20:14:13 +0200315 free(data);
316
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200317 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100318}
319
Harald Welte96e2a002017-06-12 21:44:18 +0200320/*! \brief GSM 7-bit alphabet TS 03.38 6.2.1 Character packing
321 * \param[out] result Caller-provided output buffer
322 * \param[in] n Maximum length of \a result in bytes
323 * \param[in] data octet-aligned string
324 * \param[out] octets Number of octets encoded
325 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200326int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200327{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200328 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200329 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100330 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200331
Dennis Wehrle291e6132011-07-24 20:14:13 +0200332 /* prepare for the worst case, every character expanding to two bytes */
333 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
334 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200335
336 if (y > max_septets) {
337 /*
338 * Limit the number of septets to avoid the generation
339 * of more than n octets.
340 */
341 y = max_septets;
342 }
343
344 o = gsm_septets2octets(result, rdata, y, 0);
345
346 if (octets)
347 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200348
349 free(rdata);
350
351 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200352 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200353 * unique. E.g.:
354 * 1.) 46 non-extension characters + 1 extension character
355 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
356 * 2.) 47 non-extension characters
357 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
358 * 3.) 48 non-extension characters
359 * => (48 * 7 bit) / 8 bit = 42 octects
360 */
361 return y;
362}
363
Harald Welte96e2a002017-06-12 21:44:18 +0200364/*! \brief Encode according to GSM 7-bit alphabet (TS 03.38 6.2.1) for USSD
365 * \param[out] result Caller-provided output buffer
366 * \param[in] n Maximum length of \a result in bytes
367 * \param[in] data octet-aligned string
368 * \param[out] octets Number of octets encoded
369 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200370int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
371{
372 int y;
373
374 y = gsm_7bit_encode_n(result, n, data, octets);
375 /* if last octet contains only one bit, add <CR> */
376 if (((y * 7) & 7) == 1)
377 result[(*octets) - 1] |= ('\r' << 1);
378 /* if last character is <CR> and completely fills last octet, add
379 * another <CR>. */
380 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
381 result[(*octets)++] = '\r';
382 y++;
383 }
384
385 return y;
386}
387
Max764b0222016-05-11 17:33:17 +0200388/*! \brief Build the RSL uplink measurement IE (3GPP TS 08.58 § 9.3.25)
389 * \param[in] mru Unidirectional measurement report structure
390 * \param[in] dtxd_used Indicates if DTXd was used during measurement report
391 * period
392 * \param[out] buf Pre-allocated bufer for storing IE
393 * \returns Number of bytes filled in buf
394 */
395size_t gsm0858_rsl_ul_meas_enc(struct gsm_meas_rep_unidir *mru, bool dtxd_used,
396 uint8_t *buf)
397{
398 buf[0] = dtxd_used ? (1 << 6) : 0;
399 buf[0] |= (mru->full.rx_lev & 0x3f);
400 buf[1] = (mru->sub.rx_lev & 0x3f);
401 buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
402
403 return 3;
404}
405
Harald Welte96e2a002017-06-12 21:44:18 +0200406/*! \brief Convert power class to dBm according to GSM TS 05.05
407 * \param[in] band GSM frequency band
408 * \param[in] class GSM power class
409 * \returns maximum transmit power of power class in dBm */
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200410unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
411{
412 switch (band) {
413 case GSM_BAND_450:
414 case GSM_BAND_480:
415 case GSM_BAND_750:
416 case GSM_BAND_900:
417 case GSM_BAND_810:
418 case GSM_BAND_850:
419 if (class == 1)
420 return 43; /* 20W */
421 if (class == 2)
422 return 39; /* 8W */
423 if (class == 3)
424 return 37; /* 5W */
425 if (class == 4)
426 return 33; /* 2W */
427 if (class == 5)
428 return 29; /* 0.8W */
429 break;
430 case GSM_BAND_1800:
431 if (class == 1)
432 return 30; /* 1W */
433 if (class == 2)
434 return 24; /* 0.25W */
435 if (class == 3)
436 return 36; /* 4W */
437 break;
438 case GSM_BAND_1900:
439 if (class == 1)
440 return 30; /* 1W */
441 if (class == 2)
442 return 24; /* 0.25W */
443 if (class == 3)
444 return 33; /* 2W */
445 break;
446 }
447 return -EINVAL;
448}
449
Harald Welte96e2a002017-06-12 21:44:18 +0200450/*! \brief determine power control level for given dBm value, as indicated
451 * by the tables in chapter 4.1.1 of GSM TS 05.05
452 * \param[in] GSM frequency band
453 * \param[in] dbm RF power value in dBm
454 * \returns TS 05.05 power control level */
Harald Welteec8b4502010-02-20 20:34:29 +0100455int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
456{
457 switch (band) {
458 case GSM_BAND_450:
459 case GSM_BAND_480:
460 case GSM_BAND_750:
461 case GSM_BAND_900:
462 case GSM_BAND_810:
463 case GSM_BAND_850:
464 if (dbm >= 39)
465 return 0;
466 else if (dbm < 5)
467 return 19;
468 else {
469 /* we are guaranteed to have (5 <= dbm < 39) */
470 return 2 + ((39 - dbm) / 2);
471 }
472 break;
473 case GSM_BAND_1800:
474 if (dbm >= 36)
475 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200476 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100477 return 30;
478 else if (dbm >= 32)
479 return 31;
480 else if (dbm == 31)
481 return 0;
482 else {
483 /* we are guaranteed to have (0 <= dbm < 31) */
484 return (30 - dbm) / 2;
485 }
486 break;
487 case GSM_BAND_1900:
488 if (dbm >= 33)
489 return 30;
490 else if (dbm >= 32)
491 return 31;
492 else if (dbm == 31)
493 return 0;
494 else {
495 /* we are guaranteed to have (0 <= dbm < 31) */
496 return (30 - dbm) / 2;
497 }
498 break;
499 }
500 return -EINVAL;
501}
502
Harald Welte96e2a002017-06-12 21:44:18 +0200503/*! \brief Convert TS 05.05 power level to absolute dBm value
504 * \param[in] band GSM frequency band
505 * \param[in] lvl TS 05.05 power control level
506 * \returns RF power level in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100507int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
508{
509 lvl &= 0x1f;
510
511 switch (band) {
512 case GSM_BAND_450:
513 case GSM_BAND_480:
514 case GSM_BAND_750:
515 case GSM_BAND_900:
516 case GSM_BAND_810:
517 case GSM_BAND_850:
518 if (lvl < 2)
519 return 39;
520 else if (lvl < 20)
521 return 39 - ((lvl - 2) * 2) ;
522 else
523 return 5;
524 break;
525 case GSM_BAND_1800:
526 if (lvl < 16)
527 return 30 - (lvl * 2);
528 else if (lvl < 29)
529 return 0;
530 else
531 return 36 - ((lvl - 29) * 2);
532 break;
533 case GSM_BAND_1900:
534 if (lvl < 16)
535 return 30 - (lvl * 2);
536 else if (lvl < 30)
537 return -EINVAL;
538 else
539 return 33 - (lvl - 30);
540 break;
541 }
542 return -EINVAL;
543}
544
Harald Welte96e2a002017-06-12 21:44:18 +0200545/*! \brief Convert TS 05.08 RxLev to dBm (TS 05.08 Chapter 8.1.4)
546 * \param[in] rxlev TS 05.08 RxLev value
547 * \returns Received RF power in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100548int rxlev2dbm(uint8_t rxlev)
549{
550 if (rxlev > 63)
551 rxlev = 63;
552
553 return -110 + rxlev;
554}
555
Harald Welte96e2a002017-06-12 21:44:18 +0200556/*! \brief Convert RF signal level in dBm to TS 05.08 RxLev (TS 05.08 Chapter 8.1.4)
557 * \param[in] dbm RF signal level in dBm
558 * \returns TS 05.08 RxLev value */
Harald Welteec8b4502010-02-20 20:34:29 +0100559uint8_t dbm2rxlev(int dbm)
560{
561 int rxlev = dbm + 110;
562
563 if (rxlev > 63)
564 rxlev = 63;
565 else if (rxlev < 0)
566 rxlev = 0;
567
568 return rxlev;
569}
570
Harald Welte96e2a002017-06-12 21:44:18 +0200571/*! \brief Return string name of a given GSM Band */
Harald Weltecbc80622010-03-22 08:28:44 +0800572const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100573{
574 switch (band) {
575 case GSM_BAND_450:
576 return "GSM450";
577 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200578 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100579 case GSM_BAND_750:
580 return "GSM750";
581 case GSM_BAND_810:
582 return "GSM810";
583 case GSM_BAND_850:
584 return "GSM850";
585 case GSM_BAND_900:
586 return "GSM900";
587 case GSM_BAND_1800:
588 return "DCS1800";
589 case GSM_BAND_1900:
590 return "PCS1900";
591 }
592 return "invalid";
593}
594
Harald Welte96e2a002017-06-12 21:44:18 +0200595/*! \brief Parse string name of a GSM band */
Harald Welteaebe08c2010-03-04 10:39:17 +0100596enum gsm_band gsm_band_parse(const char* mhz)
597{
598 while (*mhz && !isdigit(*mhz))
599 mhz++;
600
601 if (*mhz == '\0')
602 return -EINVAL;
603
Harald Welted3ff15f2010-03-07 18:23:47 +0100604 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100605 case 450:
606 return GSM_BAND_450;
607 case 480:
608 return GSM_BAND_480;
609 case 750:
610 return GSM_BAND_750;
611 case 810:
612 return GSM_BAND_810;
613 case 850:
614 return GSM_BAND_850;
615 case 900:
616 return GSM_BAND_900;
617 case 1800:
618 return GSM_BAND_1800;
619 case 1900:
620 return GSM_BAND_1900;
621 default:
622 return -EINVAL;
623 }
624}
625
Harald Welte96e2a002017-06-12 21:44:18 +0200626/*! \brief Resolve GSM band from ARFCN
627 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS
628 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
629 * \returns GSM Band */
Harald Welte622b7182010-03-07 17:50:21 +0100630enum gsm_band gsm_arfcn2band(uint16_t arfcn)
631{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100632 int is_pcs = arfcn & ARFCN_PCS;
633
634 arfcn &= ~ARFCN_FLAG_MASK;
635
636 if (is_pcs)
Harald Welte622b7182010-03-07 17:50:21 +0100637 return GSM_BAND_1900;
638 else if (arfcn <= 124)
639 return GSM_BAND_900;
640 else if (arfcn >= 955 && arfcn <= 1023)
641 return GSM_BAND_900;
642 else if (arfcn >= 128 && arfcn <= 251)
643 return GSM_BAND_850;
644 else if (arfcn >= 512 && arfcn <= 885)
645 return GSM_BAND_1800;
646 else if (arfcn >= 259 && arfcn <= 293)
647 return GSM_BAND_450;
648 else if (arfcn >= 306 && arfcn <= 340)
649 return GSM_BAND_480;
650 else if (arfcn >= 350 && arfcn <= 425)
651 return GSM_BAND_810;
652 else if (arfcn >= 438 && arfcn <= 511)
653 return GSM_BAND_750;
654 else
655 return GSM_BAND_1800;
656}
657
Sylvain Munaut55720312012-12-11 23:44:41 +0100658struct gsm_freq_range {
659 uint16_t arfcn_first;
660 uint16_t arfcn_last;
661 uint16_t freq_ul_first;
662 uint16_t freq_dl_offset;
663 uint16_t flags;
664};
665
666static struct gsm_freq_range gsm_ranges[] = {
667 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
668 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
669 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
670 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
671 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
672 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
673 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
674 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
675 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
676 { /* Guard */ }
677};
678
Harald Welte96e2a002017-06-12 21:44:18 +0200679/*! \brief Convert an ARFCN to the frequency in MHz * 10
680 * \param[in] arfcn GSM ARFCN to convert
681 * \param[in] uplink Uplink (1) or Downlink (0) frequency
682 * \returns Frequency in units of 1/10ths of MHz (100kHz) */
Harald Welte622b7182010-03-07 17:50:21 +0100683uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
684{
Sylvain Munaut55720312012-12-11 23:44:41 +0100685 struct gsm_freq_range *r;
686 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
687 uint16_t freq10_ul = 0xffff;
688 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100689
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100690 arfcn &= ~ARFCN_FLAG_MASK;
691
Sylvain Munaut55720312012-12-11 23:44:41 +0100692 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
693 if ((flags == r->flags) &&
694 (arfcn >= r->arfcn_first) &&
695 (arfcn <= r->arfcn_last))
696 {
697 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
698 freq10_dl = freq10_ul + r->freq_dl_offset;
699 break;
700 }
701 }
702
703 return uplink ? freq10_ul : freq10_dl;
704}
705
Harald Welte96e2a002017-06-12 21:44:18 +0200706/*! \brief Convert a Frequency in MHz * 10 to ARFCN
707 * \param[in] freq10 Frequency in units of 1/10ths of MHz (100kHz)
708 * \param[in] uplink Frequency is Uplink (1) or Downlink (0)
709 * \returns ARFCN in case of success; 0xffff on error */
Sylvain Munaut55720312012-12-11 23:44:41 +0100710uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
711{
712 struct gsm_freq_range *r;
713 uint16_t freq10_lo, freq10_hi;
714 uint16_t arfcn = 0xffff;
715
716 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
717 /* Generate frequency limits */
718 freq10_lo = r->freq_ul_first;
719 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
720 if (!uplink) {
721 freq10_lo += r->freq_dl_offset;
722 freq10_hi += r->freq_dl_offset;
723 }
724
725 /* Check if this fits */
726 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
727 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
728 arfcn |= r->flags;
729 break;
730 }
731 }
Harald Welte622b7182010-03-07 17:50:21 +0100732
733 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100734 arfcn |= ARFCN_UPLINK;
735
736 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100737}
738
Harald Welte96e2a002017-06-12 21:44:18 +0200739/*! \brief Parse GSM Frame Number into struct \ref gsm_time
740 * \param[out] time Caller-provided memory for \ref gsm_time
741 * \param[in] fn GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100742void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
743{
744 time->fn = fn;
745 time->t1 = time->fn / (26*51);
746 time->t2 = time->fn % 26;
747 time->t3 = time->fn % 51;
748 time->tc = (time->fn / 51) % 8;
749}
750
Harald Welte96e2a002017-06-12 21:44:18 +0200751/*! \brief Encode decoded \ref gsm_time to Frame Number
752 * \param[in] time GSM Time in decoded structure
753 * \returns GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100754uint32_t gsm_gsmtime2fn(struct gsm_time *time)
755{
756 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
757 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
758}
Harald Weltea1c4f762010-05-01 11:59:42 +0200759
Harald Welte96e2a002017-06-12 21:44:18 +0200760/*! \brief append range1024 encoded data to bit vector
761 * \param[out] bv Caller-provided output bit-vector
762 * \param[in] r Input Range1024 sructure */
Max8a5346b2016-04-22 19:28:09 +0200763void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
764{
765 bitvec_set_uint(bv, r->w1_hi, 2);
766 bitvec_set_uint(bv, r->w1_lo, 8);
767 bitvec_set_uint(bv, r->w2_hi, 8);
768 bitvec_set_uint(bv, r->w2_lo, 1);
769 bitvec_set_uint(bv, r->w3_hi, 7);
770 bitvec_set_uint(bv, r->w3_lo, 2);
771 bitvec_set_uint(bv, r->w4_hi, 6);
772 bitvec_set_uint(bv, r->w4_lo, 2);
773 bitvec_set_uint(bv, r->w5_hi, 6);
774 bitvec_set_uint(bv, r->w5_lo, 2);
775 bitvec_set_uint(bv, r->w6_hi, 6);
776 bitvec_set_uint(bv, r->w6_lo, 2);
777 bitvec_set_uint(bv, r->w7_hi, 6);
778 bitvec_set_uint(bv, r->w7_lo, 2);
779 bitvec_set_uint(bv, r->w8_hi, 6);
780 bitvec_set_uint(bv, r->w8_lo, 1);
781 bitvec_set_uint(bv, r->w9, 7);
782 bitvec_set_uint(bv, r->w10, 7);
783 bitvec_set_uint(bv, r->w11_hi, 1);
784 bitvec_set_uint(bv, r->w11_lo, 6);
785 bitvec_set_uint(bv, r->w12_hi, 2);
786 bitvec_set_uint(bv, r->w12_lo, 5);
787 bitvec_set_uint(bv, r->w13_hi, 3);
788 bitvec_set_uint(bv, r->w13_lo, 4);
789 bitvec_set_uint(bv, r->w14_hi, 4);
790 bitvec_set_uint(bv, r->w14_lo, 3);
791 bitvec_set_uint(bv, r->w15_hi, 5);
792 bitvec_set_uint(bv, r->w15_lo, 2);
793 bitvec_set_uint(bv, r->w16, 6);
794}
795
Harald Welte96e2a002017-06-12 21:44:18 +0200796/*! \brief Determine GPRS TLLI Type (TS 23.003 Chapter 2.6) */
Harald Weltea1c4f762010-05-01 11:59:42 +0200797int gprs_tlli_type(uint32_t tlli)
798{
799 if ((tlli & 0xc0000000) == 0xc0000000)
800 return TLLI_LOCAL;
801 else if ((tlli & 0xc0000000) == 0x80000000)
802 return TLLI_FOREIGN;
803 else if ((tlli & 0xf8000000) == 0x78000000)
804 return TLLI_RANDOM;
805 else if ((tlli & 0xf8000000) == 0x70000000)
806 return TLLI_AUXILIARY;
Harald Welte1f6aad12015-08-15 19:51:45 +0200807 else if ((tlli & 0xf0000000) == 0x00000000)
808 return TLLI_G_RNTI;
809 else if ((tlli & 0xf0000000) == 0x10000000)
810 return TLLI_RAND_G_RNTI;
Harald Weltea1c4f762010-05-01 11:59:42 +0200811
812 return TLLI_RESERVED;
813}
Harald Weltec2263172010-06-01 10:47:07 +0200814
Harald Welte96e2a002017-06-12 21:44:18 +0200815/*! \brief Determine TLLI from P-TMSI
816 * \param[in] p_tmsi P-TMSI
817 * \param[in] type TLLI Type we want to derive from \a p_tmsi
818 * \returns TLLI of given type */
Harald Weltec2263172010-06-01 10:47:07 +0200819uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
820{
821 uint32_t tlli;
822 switch (type) {
823 case TLLI_LOCAL:
824 tlli = p_tmsi | 0xc0000000;
825 break;
826 case TLLI_FOREIGN:
827 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
828 break;
829 default:
830 tlli = 0;
831 break;
832 }
833 return tlli;
834}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200835
836/* Wrappers for deprecated functions: */
837
838int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
839{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100840 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
841 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200842
843 /* Mimic the original behaviour. */
844 return septet_l;
845}
846
847int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
848{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100849 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
850 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200851}
852
853int gsm_7bit_encode(uint8_t *result, const char *data)
854{
855 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100856 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
857 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200858}
859
860int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
861{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100862 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
863 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200864}
865
866int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
867{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100868 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
869 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200870}