Fix compilation on jellybean
[samsung-ril.git] / util.c
1 /**
2  * This file is part of samsung-ril.
3  *
4  * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
5  *
6  * samsung-ril is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * samsung-ril is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with samsung-ril.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <stdio.h>
22 #include <string.h>
23
24 #define LOG_TAG "RIL-UTIL"
25 #include <utils/Log.h>
26 #include "util.h"
27
28 #include "samsung-ril.h"
29
30 /**
31  * Converts a hexidecimal string to binary
32  */
33 void hex2bin(const char *data, int length, unsigned char *buf)
34 {
35         int i = 0;
36         char b = 0;
37         unsigned char *p = buf;
38
39         length ^= 0x01;
40
41         while(i < length) {
42                 b = 0;
43
44                 if(data[i] - '0' < 10)
45                         b = data[i] - '0';
46                 else if(data[i] - 'a' < 7)
47                         b = data[i] - 'a' + 10;
48                 else if(data[i] - 'A' < 7)
49                         b = data[i] - 'A' + 10;
50                 i++;
51
52                 b = (b << 4);
53
54                 if(data[i] - '0' < 10)
55                         b |= data[i] - '0';
56                 else if(data[i] - 'a' < 7)
57                         b |= data[i] - 'a' + 10;
58                 else if(data[i] - 'A' < 7)
59                         b |= data[i] - 'A' + 10;
60                 i++;
61
62                 *p++ = b;
63         }
64 }
65
66 /**
67  * Converts binary data to a hexidecimal string
68  */
69 void bin2hex(const unsigned char *data, int length, char *buf)
70 {
71         int i;
72         char b;
73         char *p = buf;
74
75         for(i = 0; i < length; i++) {
76                 b = 0;
77
78                 b = (data[i] >> 4 & 0x0f);
79                 b += (b < 10) ? '0' : ('a' - 10);
80                 *p++ = b;
81
82                 b = (data[i] & 0x0f);
83                 b += (b < 10) ? '0' : ('a' - 10);
84                 *p++ = b;
85         }
86
87         *p = '\0';
88 }
89
90 /**
91  * Converts GSM7 (8 bits) data to ASCII (7 bits)
92  */
93 int gsm72ascii(unsigned char *data, char **data_dec, int length)
94 {
95         int t, u, d, o = 0;
96         int i;
97
98         int dec_length;
99         char *dec;
100
101         dec_length = ((length * 8) - ((length * 8) % 7) ) / 7;
102         dec = malloc(dec_length);
103
104         memset(dec, 0, dec_length);
105
106         for(i=0 ; i < length ; i++)
107         {
108                 d = 7 - i % 7;
109                 if(d == 7 && i != 0)
110                         o++;
111
112                 t = (data[i] - (((data[i] >> d) & 0xff) << d));
113                 u = (data[i] >> d) & 0xff;
114
115                 dec[i+o]+=t << (i + o) % 8;
116
117                 if(u)
118                         dec[i+1+o]+=u;
119         }
120
121         *data_dec = dec;
122         
123         return dec_length;
124 }
125
126 /**
127  * Converts ASCII (7 bits) data to GSM7 (8 bits)
128  */
129 int ascii2gsm7(char *data, unsigned char **data_enc, int length)
130 {
131         int d_off, d_pos, a_off, a_pos = 0;
132         int i;
133
134         int enc_length;
135         unsigned char *enc;
136
137         enc_length = ((length * 7) - (length * 7) % 8) / 8;
138         enc_length += (length * 7) % 8 > 0 ? 1 : 0;
139
140         //FIXME: why does samsung does that?
141         enc_length++;
142
143         enc = malloc(enc_length);
144         memset(enc, 0, enc_length);
145
146         for(i=0 ; i < length ; i++)
147         {
148                 // offset from the right of data to keep
149                 d_off = i % 8;
150
151                 // position of the data we keep
152                 d_pos = ((i * 7) - (i * 7) % 8) / 8;
153                 d_pos += (i * 7) % 8 > 0 ? 1 : 0;
154
155                 // adding the data with correct offset
156                 enc[d_pos] |= data[i] >> d_off;
157
158                 // numbers of bits to omit to get data to add another place
159                 a_off = 8 - d_off;
160                 // position (on the encoded feed) of the data to add
161                 a_pos = d_pos - 1;
162
163                 // adding the data to add at the correct position
164                 enc[a_pos] |= data[i] << a_off;
165         }
166
167         *data_enc = enc;
168
169         //FIXME: what is going on here?
170         enc[enc_length - 2] |= 0x30;
171         enc[enc_length - 1] = 0x02;
172         
173         return enc_length;
174 }
175
176 void hex_dump(void *data, int size)
177 {
178         /* dumps size bytes of *data to stdout. Looks like:
179          * [0000] 75 6E 6B 6E 6F 77 6E 20
180          *                                30 FF 00 00 00 00 39 00 unknown 0.....9.
181          * (in a single line of course)
182          */
183
184         unsigned char *p = data;
185         unsigned char c;
186         int n;
187         char bytestr[4] = {0};
188         char addrstr[10] = {0};
189         char hexstr[ 16*3 + 5] = {0};
190         char charstr[16*1 + 5] = {0};
191         for(n=1;n<=size;n++) {
192                 if (n%16 == 1) {
193                         /* store address for this line */
194                         snprintf(addrstr, sizeof(addrstr), "%.4x",
195                            ((unsigned int)p-(unsigned int)data) );
196                 }
197
198                 c = *p;
199                 if (isalnum(c) == 0) {
200                         c = '.';
201                 }
202
203                 /* store hex str (for left side) */
204                 snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
205                 strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
206
207                 /* store char str (for right side) */
208                 snprintf(bytestr, sizeof(bytestr), "%c", c);
209                 strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
210
211                 if(n%16 == 0) {
212                         /* line completed */
213                         LOGD("[%4.4s]   %-50.50s  %s", addrstr, hexstr, charstr);
214                         hexstr[0] = 0;
215                         charstr[0] = 0;
216                 } else if(n%8 == 0) {
217                         /* half line: add whitespaces */
218                         strncat(hexstr, "  ", sizeof(hexstr)-strlen(hexstr)-1);
219                         strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
220                 }
221                 p++; /* next byte */
222         }
223
224         if (strlen(hexstr) > 0) {
225                 /* print rest of buffer if not empty */
226                 LOGD("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
227         }
228 }
229
230 /* writes the utf8 character encoded in v
231  * to the buffer utf8 at the specified offset
232  */
233 int utf8_write(char *utf8, int offset, int v)
234 {
235
236         int result;
237
238         if (v < 0x80) {
239                 result = 1;
240                 if (utf8)
241                         utf8[offset] = (char)v;
242         } else if (v < 0x800) {
243                 result = 2;
244                 if (utf8) {
245                         utf8[offset + 0] = (char)(0xc0 | (v >> 6));
246                         utf8[offset + 1] = (char)(0x80 | (v & 0x3f));
247                 }
248         } else if (v < 0x10000) {
249                 result = 3;
250                 if (utf8) {
251                         utf8[offset + 0] = (char)(0xe0 | (v >> 12));
252                         utf8[offset + 1] = (char)(0x80 | ((v >> 6) & 0x3f));
253                         utf8[offset + 2] = (char)(0x80 | (v & 0x3f));
254                 }
255         } else {
256                 result = 4;
257                 if (utf8) {
258                         utf8[offset + 0] = (char)(0xf0 | ((v >> 18) & 0x7));
259                         utf8[offset + 1] = (char)(0x80 | ((v >> 12) & 0x3f));
260                         utf8[offset + 2] = (char)(0x80 | ((v >> 6) & 0x3f));
261                         utf8[offset + 3] = (char)(0x80 | (v & 0x3f));
262                 }
263         }
264         return result;
265 }
266
267 SmsCodingScheme sms_get_coding_scheme(int dataCoding)
268 {
269         switch (dataCoding >> 4) {
270         case 0x00:
271         case 0x02:
272         case 0x03:
273                 return SMS_CODING_SCHEME_GSM7;
274         case 0x01:
275                 if (dataCoding == 0x10)
276                         return SMS_CODING_SCHEME_GSM7;
277                 if (dataCoding == 0x11)
278                         return SMS_CODING_SCHEME_UCS2;
279                 break;
280         case 0x04:
281         case 0x05:
282         case 0x06:
283         case 0x07:
284                 if (dataCoding & 0x20)
285                         return SMS_CODING_SCHEME_UNKNOWN;
286                 if (((dataCoding >> 2) & 3) == 0)
287                         return SMS_CODING_SCHEME_GSM7;
288                 if (((dataCoding >> 2) & 3) == 2)
289                         return SMS_CODING_SCHEME_UCS2;
290                 break;
291         case 0xF:
292                 if (!(dataCoding & 4))
293                         return SMS_CODING_SCHEME_GSM7;
294                 break;
295         }
296         return SMS_CODING_SCHEME_UNKNOWN;
297 }
298