blob: aabd7b73491b97f09cda51ba7a5d89adda9754a7 [file] [log] [blame]
Holger Freyther76c95692009-02-17 20:31:30 +00001/*
2 * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
3 * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte7e310b12009-03-30 20:56:32 +00004 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
Holger Freyther76c95692009-02-17 20:31:30 +00005 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
Harald Weltedfe6c7d2010-02-20 16:24:02 +010024//#include <openbsc/gsm_data.h>
25#include <osmocore/utils.h>
26#include <osmocore/gsm_utils.h>
27
Harald Welte12247c62009-05-21 07:23:02 +000028#include <stdlib.h>
Holger Freytherce668962009-02-17 23:42:45 +000029#include <string.h>
Holger Hans Peter Freyther25f30ba2009-10-28 09:12:43 +010030#include <stdio.h>
Harald Welte66b6a8d2009-08-09 14:45:18 +020031#include <errno.h>
Holger Freyther76c95692009-02-17 20:31:30 +000032
Holger Freytherce668962009-02-17 23:42:45 +000033/* GSM 03.38 6.2.1 Charachter packing */
Harald Welte7e310b12009-03-30 20:56:32 +000034int gsm_7bit_decode(char *text, const u_int8_t *user_data, u_int8_t length)
Holger Freyther76c95692009-02-17 20:31:30 +000035{
Daniel Willmann6b1e8222009-08-12 21:17:06 +020036 int i = 0;
37 int l = 0;
Holger Freyther76c95692009-02-17 20:31:30 +000038
Daniel Willmann6b1e8222009-08-12 21:17:06 +020039 /* FIXME: We need to account for user data headers here */
40 i += l;
41 for (; i < length; i ++)
42 *(text ++) =
43 ((user_data[(i * 7 + 7) >> 3] <<
44 (7 - ((i * 7 + 7) & 7))) |
45 (user_data[(i * 7) >> 3] >>
46 ((i * 7) & 7))) & 0x7f;
47 *text = '\0';
48
49 return i - l;
Holger Freyther76c95692009-02-17 20:31:30 +000050}
Holger Freytherce668962009-02-17 23:42:45 +000051
Daniel Willmann6b1e8222009-08-12 21:17:06 +020052
Holger Freytherce668962009-02-17 23:42:45 +000053/* GSM 03.38 6.2.1 Charachter packing */
Harald Welte7e310b12009-03-30 20:56:32 +000054int gsm_7bit_encode(u_int8_t *result, const char *data)
Holger Freytherce668962009-02-17 23:42:45 +000055{
Daniel Willmann6b1e8222009-08-12 21:17:06 +020056 int i,j = 0;
57 unsigned char ch1, ch2;
58 int shift = 0;
Harald Welte93d93032009-03-30 09:11:45 +000059
Daniel Willmann6b1e8222009-08-12 21:17:06 +020060 for ( i=0; i<strlen(data); i++ ) {
Holger Freytherce668962009-02-17 23:42:45 +000061
Daniel Willmann6b1e8222009-08-12 21:17:06 +020062 ch1 = data[i] & 0x7F;
63 ch1 = ch1 >> shift;
64 ch2 = data[(i+1)] & 0x7F;
65 ch2 = ch2 << (7-shift);
Holger Freytherce668962009-02-17 23:42:45 +000066
Daniel Willmann6b1e8222009-08-12 21:17:06 +020067 ch1 = ch1 | ch2;
Holger Freytherce668962009-02-17 23:42:45 +000068
Daniel Willmann6b1e8222009-08-12 21:17:06 +020069 result[j++] = ch1;
70
71 shift++;
72
73 if ((shift == 7) && (i+1<strlen(data))) {
74 shift = 0;
75 i++;
Holger Freytherce668962009-02-17 23:42:45 +000076 }
77 }
78
Daniel Willmann6b1e8222009-08-12 21:17:06 +020079 return i;
Holger Freytherce668962009-02-17 23:42:45 +000080}
Harald Welte66b6a8d2009-08-09 14:45:18 +020081
82/* determine power control level for given dBm value, as indicated
83 * by the tables in chapter 4.1.1 of GSM TS 05.05 */
84int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
85{
86 switch (band) {
Harald Weltedfe6c7d2010-02-20 16:24:02 +010087 case GSM_BAND_450:
88 case GSM_BAND_480:
89 case GSM_BAND_750:
Harald Welte66b6a8d2009-08-09 14:45:18 +020090 case GSM_BAND_900:
Harald Weltedfe6c7d2010-02-20 16:24:02 +010091 case GSM_BAND_810:
Harald Welte66b6a8d2009-08-09 14:45:18 +020092 case GSM_BAND_850:
93 if (dbm >= 39)
94 return 0;
95 else if (dbm < 5)
96 return 19;
Harald Welte854b9b32009-12-12 14:21:16 +010097 else {
98 /* we are guaranteed to have (5 <= dbm < 39) */
Harald Welte66b6a8d2009-08-09 14:45:18 +020099 return 2 + ((39 - dbm) / 2);
Harald Welte854b9b32009-12-12 14:21:16 +0100100 }
Harald Welte66b6a8d2009-08-09 14:45:18 +0200101 break;
102 case GSM_BAND_1800:
103 if (dbm >= 36)
104 return 29;
105 else if (dbm >= 34)
106 return 30;
107 else if (dbm >= 32)
108 return 31;
Harald Welte854b9b32009-12-12 14:21:16 +0100109 else if (dbm == 31)
110 return 0;
111 else {
112 /* we are guaranteed to have (0 <= dbm < 31) */
Harald Welte66b6a8d2009-08-09 14:45:18 +0200113 return (30 - dbm) / 2;
Harald Welte854b9b32009-12-12 14:21:16 +0100114 }
Harald Welte66b6a8d2009-08-09 14:45:18 +0200115 break;
116 case GSM_BAND_1900:
117 if (dbm >= 33)
118 return 30;
119 else if (dbm >= 32)
120 return 31;
Harald Welte854b9b32009-12-12 14:21:16 +0100121 else if (dbm == 31)
122 return 0;
123 else {
124 /* we are guaranteed to have (0 <= dbm < 31) */
Harald Welte66b6a8d2009-08-09 14:45:18 +0200125 return (30 - dbm) / 2;
Harald Welte854b9b32009-12-12 14:21:16 +0100126 }
Harald Welte66b6a8d2009-08-09 14:45:18 +0200127 break;
128 }
129 return -EINVAL;
130}
131
132int ms_pwr_dbm(enum gsm_band band, u_int8_t lvl)
133{
134 lvl &= 0x1f;
135
136 switch (band) {
Harald Weltedfe6c7d2010-02-20 16:24:02 +0100137 case GSM_BAND_450:
138 case GSM_BAND_480:
139 case GSM_BAND_750:
Harald Welte66b6a8d2009-08-09 14:45:18 +0200140 case GSM_BAND_900:
Harald Weltedfe6c7d2010-02-20 16:24:02 +0100141 case GSM_BAND_810:
Harald Welte66b6a8d2009-08-09 14:45:18 +0200142 case GSM_BAND_850:
143 if (lvl < 2)
144 return 39;
145 else if (lvl < 20)
146 return 39 - ((lvl - 2) * 2) ;
147 else
148 return 5;
149 break;
150 case GSM_BAND_1800:
151 if (lvl < 16)
152 return 30 - (lvl * 2);
153 else if (lvl < 29)
154 return 0;
155 else
156 return 36 - ((lvl - 29) * 2);
157 break;
158 case GSM_BAND_1900:
159 if (lvl < 16)
160 return 30 - (lvl * 2);
161 else if (lvl < 30)
162 return -EINVAL;
163 else
164 return 33 - (lvl - 30);
165 break;
166 }
167 return -EINVAL;
168}
169
Harald Welte4bb47382009-12-12 15:37:54 +0100170/* According to TS 08.05 Chapter 8.1.4 */
171int rxlev2dbm(u_int8_t rxlev)
172{
173 if (rxlev > 63)
174 rxlev = 63;
175
176 return -110 + rxlev;
177}
178
179/* According to TS 08.05 Chapter 8.1.4 */
180u_int8_t dbm2rxlev(int dbm)
181{
182 int rxlev = dbm + 110;
183
184 if (rxlev > 63)
185 rxlev = 63;
186 else if (rxlev < 0)
187 rxlev = 0;
188
189 return rxlev;
190}
191
Harald Weltedfe6c7d2010-02-20 16:24:02 +0100192#include <execinfo.h>
Holger Hans Peter Freyther25f30ba2009-10-28 09:12:43 +0100193void generate_backtrace()
194{
195 int i, nptrs;
196 void *buffer[100];
197 char **strings;
Harald Welte66b6a8d2009-08-09 14:45:18 +0200198
Holger Hans Peter Freyther25f30ba2009-10-28 09:12:43 +0100199 nptrs = backtrace(buffer, ARRAY_SIZE(buffer));
200 printf("backtrace() returned %d addresses\n", nptrs);
201
202 strings = backtrace_symbols(buffer, nptrs);
203 if (!strings)
204 return;
205
206 for (i = 1; i < nptrs; i++)
207 printf("%s\n", strings[i]);
208
209 free(strings);
210}