blob: db881998babc8d76f9ed27516779926ba4d9d7ea [file] [log] [blame]
Piotr Krysik4e4a92e2018-05-11 11:39:23 +02001/*! \file gsm_utils.c */
2/*
3 * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
4 * (C) 2009,2013 by Holger Hans Peter Freyther <zecke@selfish.org>
5 * (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
6 * (C) 2010-2012 by Nico Golde <nico@ngolde.de>
7 *
8 * All Rights Reserved
9 *
10 * SPDX-License-Identifier: GPL-2.0+
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 *
26 */
27
28/*! \mainpage libosmogsm Documentation
29 *
30 * \section sec_intro Introduction
31 * This library is a collection of common code used in various
32 * GSM related sub-projects inside the Osmocom family of projects. It
33 * includes A5/1 and A5/2 ciphers, COMP128v1, a LAPDm implementation,
34 * a GSM TLV parser, SMS utility routines as well as
35 * protocol definitions for a series of protocols:
36 * * Um L2 (04.06)
37 * * Um L3 (04.08)
38 * * A-bis RSL (08.58)
39 * * A-bis OML (08.59, 12.21)
40 * * A (08.08)
41 * \n\n
42 * Please note that C language projects inside Osmocom are typically
43 * single-threaded event-loop state machine designs. As such,
44 * routines in libosmogsm are not thread-safe. If you must use them in
45 * a multi-threaded context, you have to add your own locking.
46 *
47 * libosmogsm is developed as part of the Osmocom (Open Source Mobile
48 * Communications) project, a community-based, collaborative development
49 * project to create Free and Open Source implementations of mobile
50 * communications systems. For more information about Osmocom, please
51 * see https://osmocom.org/
52 *
53 * \section sec_copyright Copyright and License
54 * Copyright © 2008-2011 - Harald Welte, Holger Freyther and contributors\n
55 * All rights reserved. \n\n
56 * The source code of libosmogsm is licensed under the terms of the GNU
57 * General Public License as published by the Free Software Foundation;
58 * either version 2 of the License, or (at your option) any later
59 * version.\n
60 * See <http://www.gnu.org/licenses/> or COPYING included in the source
61 * code package istelf.\n
62 * The information detailed here is provided AS IS with NO WARRANTY OF
63 * ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
64 * FITNESS FOR A PARTICULAR PURPOSE.
65 * \n\n
66 *
67 * \section sec_tracker Homepage + Issue Tracker
68 * libosmogsm is distributed as part of libosmocore and shares its
69 * project page at http://osmocom.org/projects/libosmocore
70 *
71 * An Issue Tracker can be found at
72 * https://osmocom.org/projects/libosmocore/issues
73 *
74 * \section sec_contact Contact and Support
75 * Community-based support is available at the OpenBSC mailing list
76 * <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
77 * Commercial support options available upon request from
78 * <http://sysmocom.de/>
79 */
80
81//#include <openbsc/gsm_data.h>
82#include <osmocom/core/utils.h>
83/*#include <osmocom/core/bitvec.h>*/
84#include <osmocom/gsm/gsm_utils.h>
85/*#include <osmocom/gsm/meas_rep.h>*/
86#include <osmocom/gsm/protocol/gsm_04_08.h>
87
88/*#include <stdlib.h>*/
89/*#include <stdint.h>*/
90/*#include <string.h>*/
91/*#include <stdbool.h>*/
92/*#include <stdio.h>*/
93#include <errno.h>
94#include <ctype.h>
95/*#include <inttypes.h>*/
96/*#include <time.h>*/
97/*#include <unistd.h>*/
98
99/*#include "../../config.h"*/
100
101/* FIXME: this can be removed once we bump glibc requirements to 2.25: *
102#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
103#include <sys/random.h>
104#elif HAVE_DECL_SYS_GETRANDOM
105#include <sys/syscall.h>
106#ifndef GRND_NONBLOCK
107#define GRND_NONBLOCK 0x0001
108#endif
109#endif
110
111#if (USE_GNUTLS)
112#pragma message ("including GnuTLS for getrandom fallback.")
113#include <gnutls/gnutls.h>
114#include <gnutls/crypto.h>
115#endif
116*/
117
118/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
119 * Greek symbols at hex positions 0x10 and 0x12-0x1a
120 * left out as they can't be handled with a char and
121 * since most phones don't display or write these
122 * characters this would only needlessly make the code
123 * more complex.
124 *
125 * Note that this table contains the latin1->7bit mapping _and_ has
126 * been merged with the reverse mapping (7bit->latin1) for the
127 * extended characters at offset 0x7f.
128 *
129static unsigned char gsm_7bit_alphabet[] = {
130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
132 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
133 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
134 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
135 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
136 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
137 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
138 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
139 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
140 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
141 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
142 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
143 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
144 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
145 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
146 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
147};
148
149/* GSM 03.38 6.2.1 Character lookup for decoding *
150static int gsm_septet_lookup(uint8_t ch)
151{
152 int i = 0;
153 for (; i < sizeof(gsm_7bit_alphabet); i++) {
154 if (gsm_7bit_alphabet[i] == ch)
155 return i;
156 }
157 return -1;
158}
159
160/*! \brife Compute number of octets from number of septets,
161 * for instance: 47 septets needs 41,125 = 42 octets
162 * \param[in sept_len Number of Septets
163 * \returns Number of octets required *
164uint8_t gsm_get_octet_len(const uint8_t sept_len){
165 int octet_len = (sept_len * 7) / 8;
166 if ((sept_len * 7) % 8 != 0)
167 octet_len++;
168
169 return octet_len;
170}
171
172/*! TS 03.38 7-bit Character unpacking (6.2.1)
173 * \param[out] text Caller-provided output text buffer
174 * \param[in] n Length of \a text
175 * \param[in] user_data Input Data (septets)
176 * \param[in] septet_l Number of septets in \a user_data
177 * \param[in] ud_hdr_ind User Data Header present in data
178 * \returns number of bytes written to \a text *
179int gsm_7bit_decode_n_hdr(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind)
180{
181 unsigned shift = 0;
182 uint8_t c7, c8, next_is_ext = 0, lu, ru;
183 const uint8_t maxlen = gsm_get_octet_len(septet_l);
184 const char *text_buf_begin = text;
185 const char *text_buf_end = text + n;
186
187 OSMO_ASSERT (n > 0);
188
189 /* skip the user data header *
190 if (ud_hdr_ind) {
191 /* get user data header length + 1 (for the 'user data header length'-field) *
192 shift = ((user_data[0] + 1) * 8) / 7;
193 if ((((user_data[0] + 1) * 8) % 7) != 0)
194 shift++;
195 septet_l = septet_l - shift;
196 }
197
198 unsigned i, l, r;
199 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
200
201 l = ((i + shift) * 7 + 7) >> 3;
202 r = ((i + shift) * 7) >> 3;
203
204 /* the left side index is always >= right side index
205 sometimes it even gets beyond array boundary
206 check for that explicitly and force 0 instead
207 *
208 if (l >= maxlen)
209 lu = 0;
210 else
211 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
212
213 ru = user_data[r] >> (((i + shift) * 7) & 7);
214
215 c7 = (lu | ru) & 0x7f;
216
217 if (next_is_ext) {
218 /* this is an extension character *
219 next_is_ext = 0;
220 c8 = gsm_7bit_alphabet[0x7f + c7];
221 } else if (c7 == 0x1b && i + 1 < septet_l) {
222 next_is_ext = 1;
223 continue;
224 } else {
225 c8 = gsm_septet_lookup(c7);
226 }
227
228 *(text++) = c8;
229 }
230
231 *text = '\0';
232
233 return text - text_buf_begin;
234}
235
236/*! Decode 7bit GSM Alphabet *
237int gsm_7bit_decode_n(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l)
238{
239 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
240}
241
242/*! Decode 7bit GSM Alphabet (USSD) *
243int gsm_7bit_decode_n_ussd(char *text, size_t n, const uint8_t *user_data, uint8_t length)
244{
245 int nchars;
246
247 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
248 /* remove last <CR>, if it fits up to the end of last octet *
249 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
250 text[--nchars] = '\0';
251
252 return nchars;
253}
254
255/*! Encode a ASCII characterrs as 7-bit GSM alphabet (TS 03.38)
256 *
257 * This function converts a zero-terminated input string \a data from
258 * ASCII into octet-aligned 7-bit GSM characters. No packing is
259 * performed.
260 *
261 * \param[out] result caller-allocated output buffer
262 * \param[in] data input data, ASCII
263 * \returns number of octets used in \a result *
264int gsm_septet_encode(uint8_t *result, const char *data)
265{
266 int i, y = 0;
267 uint8_t ch;
268 for (i = 0; i < strlen(data); i++) {
269 ch = data[i];
270 switch(ch){
271 /* fall-through for extension characters *
272 case 0x0c:
273 case 0x5e:
274 case 0x7b:
275 case 0x7d:
276 case 0x5c:
277 case 0x5b:
278 case 0x7e:
279 case 0x5d:
280 case 0x7c:
281 result[y++] = 0x1b;
282 default:
283 result[y] = gsm_7bit_alphabet[ch];
284 break;
285 }
286 y++;
287 }
288
289 return y;
290}
291
292/*! GSM Default Alphabet 7bit to octet packing
293 * \param[out] result Caller-provided output buffer
294 * \param[in] rdata Input data septets
295 * \param[in] septet_len Length of \a rdata
296 * \param[in] padding padding bits at start
297 * \returns number of bytes used in \a result *
298int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
299{
300 int i = 0, z = 0;
301 uint8_t cb, nb;
302 int shift = 0;
303 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
304
305 if (padding) {
306 shift = 7 - padding;
307 /* the first zero is needed for padding *
308 memcpy(data + 1, rdata, septet_len);
309 septet_len++;
310 } else
311 memcpy(data, rdata, septet_len);
312
313 for (i = 0; i < septet_len; i++) {
314 if (shift == 7) {
315 /*
316 * special end case with the. This is necessary if the
317 * last septet fits into the previous octet. E.g. 48
318 * non-extension characters:
319 * ....ag ( a = 1100001, g = 1100111)
320 * result[40] = 100001 XX, result[41] = 1100111 1 *
321 if (i + 1 < septet_len) {
322 shift = 0;
323 continue;
324 } else if (i + 1 == septet_len)
325 break;
326 }
327
328 cb = (data[i] & 0x7f) >> shift;
329 if (i + 1 < septet_len) {
330 nb = (data[i + 1] & 0x7f) << (7 - shift);
331 cb = cb | nb;
332 }
333
334 result[z++] = cb;
335 shift++;
336 }
337
338 free(data);
339
340 return z;
341}
342
343/*! GSM 7-bit alphabet TS 03.38 6.2.1 Character packing
344 * \param[out] result Caller-provided output buffer
345 * \param[in] n Maximum length of \a result in bytes
346 * \param[in] data octet-aligned string
347 * \param[out] octets Number of octets encoded
348 * \returns number of septets encoded *
349int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
350{
351 int y = 0;
352 int o;
353 size_t max_septets = n * 8 / 7;
354
355 /* prepare for the worst case, every character expanding to two bytes *
356 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
357 y = gsm_septet_encode(rdata, data);
358
359 if (y > max_septets) {
360 /*
361 * Limit the number of septets to avoid the generation
362 * of more than n octets.
363 *
364 y = max_septets;
365 }
366
367 o = gsm_septets2octets(result, rdata, y, 0);
368
369 if (octets)
370 *octets = o;
371
372 free(rdata);
373
374 /*
375 * We don't care about the number of octets, because they are not
376 * unique. E.g.:
377 * 1.) 46 non-extension characters + 1 extension character
378 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
379 * 2.) 47 non-extension characters
380 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
381 * 3.) 48 non-extension characters
382 * => (48 * 7 bit) / 8 bit = 42 octects
383 *
384 return y;
385}
386
387/*! Encode according to GSM 7-bit alphabet (TS 03.38 6.2.1) for USSD
388 * \param[out] result Caller-provided output buffer
389 * \param[in] n Maximum length of \a result in bytes
390 * \param[in] data octet-aligned string
391 * \param[out] octets Number of octets encoded
392 * \returns number of septets encoded *
393int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
394{
395 int y;
396
397 y = gsm_7bit_encode_n(result, n, data, octets);
398 /* if last octet contains only one bit, add <CR> *
399 if (((y * 7) & 7) == 1)
400 result[(*octets) - 1] |= ('\r' << 1);
401 /* if last character is <CR> and completely fills last octet, add
402 * another <CR>. *
403 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
404 result[(*octets)++] = '\r';
405 y++;
406 }
407
408 return y;
409}
410
411/*! Generate random identifier
412 * We use /dev/urandom (default when GRND_RANDOM flag is not set).
413 * Both /dev/(u)random numbers are coming from the same CSPRNG anyway (at least on GNU/Linux >= 4.8).
414 * See also RFC4086.
415 * \param[out] out Buffer to be filled with random data
416 * \param[in] len Number of random bytes required
417 * \returns 0 on success, or a negative error code on error.
418 *
419int osmo_get_rand_id(uint8_t *out, size_t len)
420{
421 int rc = -ENOTSUP;
422
423 /* this function is intended for generating short identifiers only, not arbitrary-length random data *
424 if (len > OSMO_MAX_RAND_ID_LEN)
425 return -E2BIG;
426
427#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
428 rc = getrandom(out, len, GRND_NONBLOCK);
429#elif HAVE_DECL_SYS_GETRANDOM
430#pragma message ("Using direct syscall access for getrandom(): consider upgrading to glibc >= 2.25")
431 /* FIXME: this can be removed once we bump glibc requirements to 2.25: *
432 rc = syscall(SYS_getrandom, out, len, GRND_NONBLOCK);
433#endif
434
435 /* getrandom() failed entirely: *
436 if (rc < 0) {
437#if (USE_GNUTLS)
438#pragma message ("Secure random failed: using GnuTLS fallback.")
439 return gnutls_rnd(GNUTLS_RND_RANDOM, out, len);
440#endif
441 return -errno;
442 }
443
444 /* getrandom() failed partially due to signal interruption:
445 this should never happen (according to getrandom(2)) as long as OSMO_MAX_RAND_ID_LEN < 256
446 because we do not set GRND_RANDOM but it's better to be paranoid and check anyway *
447 if (rc != len)
448 return -EAGAIN;
449
450 return 0;
451}
452
453/*! Build the RSL uplink measurement IE (3GPP TS 08.58 § 9.3.25)
454 * \param[in] mru Unidirectional measurement report structure
455 * \param[in] dtxd_used Indicates if DTXd was used during measurement report
456 * period
457 * \param[out] buf Pre-allocated bufer for storing IE
458 * \returns Number of bytes filled in buf
459 *
460size_t gsm0858_rsl_ul_meas_enc(struct gsm_meas_rep_unidir *mru, bool dtxd_used,
461 uint8_t *buf)
462{
463 buf[0] = dtxd_used ? (1 << 6) : 0;
464 buf[0] |= (mru->full.rx_lev & 0x3f);
465 buf[1] = (mru->sub.rx_lev & 0x3f);
466 buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
467
468 return 3;
469}
470
471/*! Convert power class to dBm according to GSM TS 05.05
472 * \param[in] band GSM frequency band
473 * \param[in] class GSM power class
474 * \returns maximum transmit power of power class in dBm *
475unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
476{
477 switch (band) {
478 case GSM_BAND_450:
479 case GSM_BAND_480:
480 case GSM_BAND_750:
481 case GSM_BAND_900:
482 case GSM_BAND_810:
483 case GSM_BAND_850:
484 if (class == 1)
485 return 43; /* 20W *
486 if (class == 2)
487 return 39; /* 8W *
488 if (class == 3)
489 return 37; /* 5W *
490 if (class == 4)
491 return 33; /* 2W *
492 if (class == 5)
493 return 29; /* 0.8W *
494 break;
495 case GSM_BAND_1800:
496 if (class == 1)
497 return 30; /* 1W *
498 if (class == 2)
499 return 24; /* 0.25W *
500 if (class == 3)
501 return 36; /* 4W *
502 break;
503 case GSM_BAND_1900:
504 if (class == 1)
505 return 30; /* 1W *
506 if (class == 2)
507 return 24; /* 0.25W *
508 if (class == 3)
509 return 33; /* 2W *
510 break;
511 }
512 return -EINVAL;
513}
514
515/*! determine power control level for given dBm value, as indicated
516 * by the tables in chapter 4.1.1 of GSM TS 05.05
517 * \param[in] GSM frequency band
518 * \param[in] dbm RF power value in dBm
519 * \returns TS 05.05 power control level *
520int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
521{
522 switch (band) {
523 case GSM_BAND_450:
524 case GSM_BAND_480:
525 case GSM_BAND_750:
526 case GSM_BAND_900:
527 case GSM_BAND_810:
528 case GSM_BAND_850:
529 if (dbm >= 39)
530 return 0;
531 else if (dbm < 5)
532 return 19;
533 else {
534 /* we are guaranteed to have (5 <= dbm < 39) *
535 return 2 + ((39 - dbm) / 2);
536 }
537 break;
538 case GSM_BAND_1800:
539 if (dbm >= 36)
540 return 29;
541 else if (dbm >= 34)
542 return 30;
543 else if (dbm >= 32)
544 return 31;
545 else if (dbm == 31)
546 return 0;
547 else {
548 /* we are guaranteed to have (0 <= dbm < 31) *
549 return (30 - dbm) / 2;
550 }
551 break;
552 case GSM_BAND_1900:
553 if (dbm >= 33)
554 return 30;
555 else if (dbm >= 32)
556 return 31;
557 else if (dbm == 31)
558 return 0;
559 else {
560 /* we are guaranteed to have (0 <= dbm < 31) *
561 return (30 - dbm) / 2;
562 }
563 break;
564 }
565 return -EINVAL;
566}
567
568/*! Convert TS 05.05 power level to absolute dBm value
569 * \param[in] band GSM frequency band
570 * \param[in] lvl TS 05.05 power control level
571 * \returns RF power level in dBm *
572int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
573{
574 lvl &= 0x1f;
575
576 switch (band) {
577 case GSM_BAND_450:
578 case GSM_BAND_480:
579 case GSM_BAND_750:
580 case GSM_BAND_900:
581 case GSM_BAND_810:
582 case GSM_BAND_850:
583 if (lvl < 2)
584 return 39;
585 else if (lvl < 20)
586 return 39 - ((lvl - 2) * 2) ;
587 else
588 return 5;
589 break;
590 case GSM_BAND_1800:
591 if (lvl < 16)
592 return 30 - (lvl * 2);
593 else if (lvl < 29)
594 return 0;
595 else
596 return 36 - ((lvl - 29) * 2);
597 break;
598 case GSM_BAND_1900:
599 if (lvl < 16)
600 return 30 - (lvl * 2);
601 else if (lvl < 30)
602 return -EINVAL;
603 else
604 return 33 - (lvl - 30);
605 break;
606 }
607 return -EINVAL;
608}
609
610/*! Convert TS 05.08 RxLev to dBm (TS 05.08 Chapter 8.1.4)
611 * \param[in] rxlev TS 05.08 RxLev value
612 * \returns Received RF power in dBm *
613int rxlev2dbm(uint8_t rxlev)
614{
615 if (rxlev > 63)
616 rxlev = 63;
617
618 return -110 + rxlev;
619}
620
621/*! Convert RF signal level in dBm to TS 05.08 RxLev (TS 05.08 Chapter 8.1.4)
622 * \param[in] dbm RF signal level in dBm
623 * \returns TS 05.08 RxLev value *
624uint8_t dbm2rxlev(int dbm)
625{
626 int rxlev = dbm + 110;
627
628 if (rxlev > 63)
629 rxlev = 63;
630 else if (rxlev < 0)
631 rxlev = 0;
632
633 return rxlev;
634}
635
636/*! Return string name of a given GSM Band */
637const char *gsm_band_name(enum gsm_band band)
638{
639 switch (band) {
640 case GSM_BAND_450:
641 return "GSM450";
642 case GSM_BAND_480:
643 return "GSM480";
644 case GSM_BAND_750:
645 return "GSM750";
646 case GSM_BAND_810:
647 return "GSM810";
648 case GSM_BAND_850:
649 return "GSM850";
650 case GSM_BAND_900:
651 return "GSM900";
652 case GSM_BAND_1800:
653 return "DCS1800";
654 case GSM_BAND_1900:
655 return "PCS1900";
656 }
657 return "invalid";
658}
659
660/*! Parse string name of a GSM band */
661enum gsm_band gsm_band_parse(const char* mhz)
662{
663 while (*mhz && !isdigit((unsigned char)*mhz))
664 mhz++;
665
666 if (*mhz == '\0')
667 return -EINVAL;
668
669 switch (strtol(mhz, NULL, 10)) {
670 case 450:
671 return GSM_BAND_450;
672 case 480:
673 return GSM_BAND_480;
674 case 750:
675 return GSM_BAND_750;
676 case 810:
677 return GSM_BAND_810;
678 case 850:
679 return GSM_BAND_850;
680 case 900:
681 return GSM_BAND_900;
682 case 1800:
683 return GSM_BAND_1800;
684 case 1900:
685 return GSM_BAND_1900;
686 default:
687 return -EINVAL;
688 }
689}
690
691/*! Resolve GSM band from ARFCN
692 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS
693 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
694 * \returns GSM Band */
695enum gsm_band gsm_arfcn2band(uint16_t arfcn)
696{
697 int is_pcs = arfcn & ARFCN_PCS;
698
699 arfcn &= ~ARFCN_FLAG_MASK;
700
701 if (is_pcs)
702 return GSM_BAND_1900;
703 else if (arfcn <= 124)
704 return GSM_BAND_900;
705 else if (arfcn >= 955 && arfcn <= 1023)
706 return GSM_BAND_900;
707 else if (arfcn >= 128 && arfcn <= 251)
708 return GSM_BAND_850;
709 else if (arfcn >= 512 && arfcn <= 885)
710 return GSM_BAND_1800;
711 else if (arfcn >= 259 && arfcn <= 293)
712 return GSM_BAND_450;
713 else if (arfcn >= 306 && arfcn <= 340)
714 return GSM_BAND_480;
715 else if (arfcn >= 350 && arfcn <= 425)
716 return GSM_BAND_810;
717 else if (arfcn >= 438 && arfcn <= 511)
718 return GSM_BAND_750;
719 else
720 return GSM_BAND_1800;
721}
722
723struct gsm_freq_range {
724 uint16_t arfcn_first;
725 uint16_t arfcn_last;
726 uint16_t freq_ul_first;
727 uint16_t freq_dl_offset;
728 uint16_t flags;
729};
730
731static struct gsm_freq_range gsm_ranges[] = {
732 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
733 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
734 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
735 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
736 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
737 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
738 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
739 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
740 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
741 { /* Guard */ }
742};
743
744/*! Convert an ARFCN to the frequency in MHz * 10
745 * \param[in] arfcn GSM ARFCN to convert
746 * \param[in] uplink Uplink (1) or Downlink (0) frequency
747 * \returns Frequency in units of 1/10ths of MHz (100kHz) */
748uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
749{
750 struct gsm_freq_range *r;
751 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
752 uint16_t freq10_ul = 0xffff;
753 uint16_t freq10_dl = 0xffff;
754
755 arfcn &= ~ARFCN_FLAG_MASK;
756
757 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
758 if ((flags == r->flags) &&
759 (arfcn >= r->arfcn_first) &&
760 (arfcn <= r->arfcn_last))
761 {
762 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
763 freq10_dl = freq10_ul + r->freq_dl_offset;
764 break;
765 }
766 }
767
768 return uplink ? freq10_ul : freq10_dl;
769}
770
771/*! Convert a Frequency in MHz * 10 to ARFCN
772 * \param[in] freq10 Frequency in units of 1/10ths of MHz (100kHz)
773 * \param[in] uplink Frequency is Uplink (1) or Downlink (0)
774 * \returns ARFCN in case of success; 0xffff on error */
775uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
776{
777 struct gsm_freq_range *r;
778 uint16_t freq10_lo, freq10_hi;
779 uint16_t arfcn = 0xffff;
780
781 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
782 /* Generate frequency limits */
783 freq10_lo = r->freq_ul_first;
784 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
785 if (!uplink) {
786 freq10_lo += r->freq_dl_offset;
787 freq10_hi += r->freq_dl_offset;
788 }
789
790 /* Check if this fits */
791 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
792 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
793 arfcn |= r->flags;
794 break;
795 }
796 }
797
798 if (uplink)
799 arfcn |= ARFCN_UPLINK;
800
801 return arfcn;
802}
803
804/*! Parse GSM Frame Number into struct \ref gsm_time
805 * \param[out] time Caller-provided memory for \ref gsm_time
806 * \param[in] fn GSM Frame Number *
807void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
808{
809 time->fn = fn;
810 time->t1 = time->fn / (26*51);
811 time->t2 = time->fn % 26;
812 time->t3 = time->fn % 51;
813 time->tc = (time->fn / 51) % 8;
814}
815
816/*! Parse GSM Frame Number into printable string
817 * \param[in] fn GSM Frame Number
818 * \returns pointer to printable string *
819char *gsm_fn_as_gsmtime_str(uint32_t fn)
820{
821 struct gsm_time time;
822
823 gsm_fn2gsmtime(&time, fn);
824 return osmo_dump_gsmtime(&time);
825}
826
827/*! Encode decoded \ref gsm_time to Frame Number
828 * \param[in] time GSM Time in decoded structure
829 * \returns GSM Frame Number *
830uint32_t gsm_gsmtime2fn(struct gsm_time *time)
831{
832 /* TS 05.02 Chapter 4.3.3 TDMA frame number *
833 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
834}
835
836char *osmo_dump_gsmtime(const struct gsm_time *tm)
837{
838 static char buf[64];
839
840 snprintf(buf, sizeof(buf), "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8,
841 tm->fn, tm->t1, tm->t2, tm->t3, (uint8_t)tm->fn%52);
842 buf[sizeof(buf)-1] = '\0';
843 return buf;
844}
845
846/*! append range1024 encoded data to bit vector
847 * \param[out] bv Caller-provided output bit-vector
848 * \param[in] r Input Range1024 sructure *
849void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
850{
851 bitvec_set_uint(bv, r->w1_hi, 2);
852 bitvec_set_uint(bv, r->w1_lo, 8);
853 bitvec_set_uint(bv, r->w2_hi, 8);
854 bitvec_set_uint(bv, r->w2_lo, 1);
855 bitvec_set_uint(bv, r->w3_hi, 7);
856 bitvec_set_uint(bv, r->w3_lo, 2);
857 bitvec_set_uint(bv, r->w4_hi, 6);
858 bitvec_set_uint(bv, r->w4_lo, 2);
859 bitvec_set_uint(bv, r->w5_hi, 6);
860 bitvec_set_uint(bv, r->w5_lo, 2);
861 bitvec_set_uint(bv, r->w6_hi, 6);
862 bitvec_set_uint(bv, r->w6_lo, 2);
863 bitvec_set_uint(bv, r->w7_hi, 6);
864 bitvec_set_uint(bv, r->w7_lo, 2);
865 bitvec_set_uint(bv, r->w8_hi, 6);
866 bitvec_set_uint(bv, r->w8_lo, 1);
867 bitvec_set_uint(bv, r->w9, 7);
868 bitvec_set_uint(bv, r->w10, 7);
869 bitvec_set_uint(bv, r->w11_hi, 1);
870 bitvec_set_uint(bv, r->w11_lo, 6);
871 bitvec_set_uint(bv, r->w12_hi, 2);
872 bitvec_set_uint(bv, r->w12_lo, 5);
873 bitvec_set_uint(bv, r->w13_hi, 3);
874 bitvec_set_uint(bv, r->w13_lo, 4);
875 bitvec_set_uint(bv, r->w14_hi, 4);
876 bitvec_set_uint(bv, r->w14_lo, 3);
877 bitvec_set_uint(bv, r->w15_hi, 5);
878 bitvec_set_uint(bv, r->w15_lo, 2);
879 bitvec_set_uint(bv, r->w16, 6);
880}
881
882/*! Determine GPRS TLLI Type (TS 23.003 Chapter 2.6) *
883int gprs_tlli_type(uint32_t tlli)
884{
885 if ((tlli & 0xc0000000) == 0xc0000000)
886 return TLLI_LOCAL;
887 else if ((tlli & 0xc0000000) == 0x80000000)
888 return TLLI_FOREIGN;
889 else if ((tlli & 0xf8000000) == 0x78000000)
890 return TLLI_RANDOM;
891 else if ((tlli & 0xf8000000) == 0x70000000)
892 return TLLI_AUXILIARY;
893 else if ((tlli & 0xf0000000) == 0x00000000)
894 return TLLI_G_RNTI;
895 else if ((tlli & 0xf0000000) == 0x10000000)
896 return TLLI_RAND_G_RNTI;
897
898 return TLLI_RESERVED;
899}
900
901/*! Determine TLLI from P-TMSI
902 * \param[in] p_tmsi P-TMSI
903 * \param[in] type TLLI Type we want to derive from \a p_tmsi
904 * \returns TLLI of given type *
905uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
906{
907 uint32_t tlli;
908 switch (type) {
909 case TLLI_LOCAL:
910 tlli = p_tmsi | 0xc0000000;
911 break;
912 case TLLI_FOREIGN:
913 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
914 break;
915 default:
916 tlli = 0;
917 break;
918 }
919 return tlli;
920}
921
922/* Wrappers for deprecated functions: *
923
924int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
925{
926 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
927 user_data, septet_l);
928
929 /* Mimic the original behaviour. *
930 return septet_l;
931}
932
933int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
934{
935 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
936 user_data, length);
937}
938
939int gsm_7bit_encode(uint8_t *result, const char *data)
940{
941 int out;
942 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
943 data, &out);
944}
945
946int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
947{
948 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
949 data, octets);
950}
951
952int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
953{
954 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
955 data, octets);
956}*/