Merge commit 'f08eabf2341de43993918246e89ce30c3651f378'
[osmocom-bb.git] / src / shared / libosmocore / src / gsm_utils.c
1 /*
2  * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
3  * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
4  * (C) 2009 by Harald Welte <laforge@gnumonks.org>
5  *
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
24 //#include <openbsc/gsm_data.h>
25 #include <osmocore/utils.h>
26 #include <osmocore/gsm_utils.h>
27
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <errno.h>
33
34 #include "../config.h"
35
36 /* GSM 03.38 6.2.1 Charachter packing */
37 int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t length)
38 {
39         int i = 0;
40         int l = 0;
41
42         /* FIXME: We need to account for user data headers here */
43         i += l;
44         for (; i < length; i ++)
45                 *(text ++) =
46                         ((user_data[(i * 7 + 7) >> 3] <<
47                           (7 - ((i * 7 + 7) & 7))) |
48                          (user_data[(i * 7) >> 3] >>
49                           ((i * 7) & 7))) & 0x7f;
50         *text = '\0';
51
52         return i - l;
53 }
54
55
56 /* GSM 03.38 6.2.1 Charachter packing */
57 int gsm_7bit_encode(uint8_t *result, const char *data)
58 {
59         int i,j = 0;
60         unsigned char ch1, ch2;
61         int shift = 0;
62
63         for ( i=0; i<strlen(data); i++ ) {
64
65                 ch1 = data[i] & 0x7F;
66                 ch1 = ch1 >> shift;
67                 ch2 = data[(i+1)] & 0x7F;
68                 ch2 = ch2 << (7-shift);
69
70                 ch1 = ch1 | ch2;
71
72                 result[j++] = ch1;
73
74                 shift++;
75
76                 if ((shift == 7) && (i+1<strlen(data))) {
77                         shift = 0;
78                         i++;
79                 }
80         }
81
82         return i;
83 }
84
85 /* determine power control level for given dBm value, as indicated
86  * by the tables in chapter 4.1.1 of GSM TS 05.05 */
87 int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
88 {
89         switch (band) {
90         case GSM_BAND_450:
91         case GSM_BAND_480:
92         case GSM_BAND_750:
93         case GSM_BAND_900:
94         case GSM_BAND_810:
95         case GSM_BAND_850:
96                 if (dbm >= 39)
97                         return 0;
98                 else if (dbm < 5)
99                         return 19;
100                 else {
101                         /* we are guaranteed to have (5 <= dbm < 39) */
102                         return 2 + ((39 - dbm) / 2);
103                 }
104                 break;
105         case GSM_BAND_1800:
106                 if (dbm >= 36)
107                         return 29;
108                 else if (dbm >= 34)     
109                         return 30;
110                 else if (dbm >= 32)
111                         return 31;
112                 else if (dbm == 31)
113                         return 0;
114                 else {
115                         /* we are guaranteed to have (0 <= dbm < 31) */
116                         return (30 - dbm) / 2;
117                 }
118                 break;
119         case GSM_BAND_1900:
120                 if (dbm >= 33)
121                         return 30;
122                 else if (dbm >= 32)
123                         return 31;
124                 else if (dbm == 31)
125                         return 0;
126                 else {
127                         /* we are guaranteed to have (0 <= dbm < 31) */
128                         return (30 - dbm) / 2;
129                 }
130                 break;
131         }
132         return -EINVAL;
133 }
134
135 int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
136 {
137         lvl &= 0x1f;
138
139         switch (band) {
140         case GSM_BAND_450:
141         case GSM_BAND_480:
142         case GSM_BAND_750:
143         case GSM_BAND_900:
144         case GSM_BAND_810:
145         case GSM_BAND_850:
146                 if (lvl < 2)
147                         return 39;
148                 else if (lvl < 20)
149                         return 39 - ((lvl - 2) * 2) ;
150                 else
151                         return 5;
152                 break;
153         case GSM_BAND_1800:
154                 if (lvl < 16)
155                         return 30 - (lvl * 2);
156                 else if (lvl < 29)
157                         return 0;
158                 else
159                         return 36 - ((lvl - 29) * 2);
160                 break;
161         case GSM_BAND_1900:
162                 if (lvl < 16)
163                         return 30 - (lvl * 2);
164                 else if (lvl < 30)
165                         return -EINVAL;
166                 else
167                         return 33 - (lvl - 30);
168                 break;
169         }
170         return -EINVAL;
171 }
172
173 /* According to TS 08.05 Chapter 8.1.4 */
174 int rxlev2dbm(uint8_t rxlev)
175 {
176         if (rxlev > 63)
177                 rxlev = 63;
178
179         return -110 + rxlev;
180 }
181
182 /* According to TS 08.05 Chapter 8.1.4 */
183 uint8_t dbm2rxlev(int dbm)
184 {
185         int rxlev = dbm + 110;
186
187         if (rxlev > 63)
188                 rxlev = 63;
189         else if (rxlev < 0)
190                 rxlev = 0;
191
192         return rxlev;
193 }
194
195 #ifdef HAVE_EXECINFO_H
196 #include <execinfo.h>
197 void generate_backtrace()
198 {
199         int i, nptrs;
200         void *buffer[100];
201         char **strings;
202
203         nptrs = backtrace(buffer, ARRAY_SIZE(buffer));
204         printf("backtrace() returned %d addresses\n", nptrs);
205
206         strings = backtrace_symbols(buffer, nptrs);
207         if (!strings)
208                 return;
209
210         for (i = 1; i < nptrs; i++)
211                 printf("%s\n", strings[i]);
212
213         free(strings);
214 }
215 #endif