5 A Linux/Unix toolset and driver for Nokia mobile phones.
7 Released under the terms of the GNU GPL, see file COPYING for more details.
16 #include "gsm-common.h"
17 #include "gsm-coding.h"
22 #include "devices/device.h"
25 /* Coding functions */
26 #define NUMBER_OF_7_BIT_ALPHABET_ELEMENTS 128
32 static unsigned char GSM_DefaultAlphabet[NUMBER_OF_7_BIT_ALPHABET_ELEMENTS] = {
34 /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
35 /* Generally table shows chars in Latin 1, but not only - Greek
36 chars are visible correctly in ... */
38 '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec, // 0x08
39 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
41 /* from v13@priest.com codes for Greek chars. Not confirmed and commented */
42 // 0xc4, '_' , 0xd6, 0xc3, 0xcb, 0xd9, 0xd0, 0xd8,
43 // 0xd3, 0xc8, 0xce, 0xcb, 0xc6, 0xe6, 0xdf, 0xc9, // 0x20
45 '?', '_', '?', '?', '?', '?', '?', '?',
46 '?', '?', '?', '?', 0xc6, 0xe6, 0xdf, 0xc9, // 0x20
47 ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
48 '(', ')', '*', '+', ',', '-', '.', '/', // 0x30
49 '0', '1', '2', '3', '4', '5', '6', '7',
50 '8', '9', ':', ';', '<', '=', '>', '?', // 0x40
51 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
52 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
53 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
54 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
55 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
56 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
57 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
58 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
64 /*Simple UNICODE decoding and encoding from/to iso-8859-2
65 First version prepared by Martin Kacer <M.Kacer@sh.cvut.cz>
67 Following table contains triplets:
68 first unicode byte, second unicode byte, iso-8859-2 character*/
69 static unsigned char unicode_table[][3] =
71 /* C< D< E< N< R< S< T< Uo Z< */
72 {0x01, 0x0C, 0xC8}, {0x01, 0x0E, 0xCF}, {0x01, 0x1A, 0xCC},
73 {0x01, 0x47, 0xD2}, {0x01, 0x58, 0xD8}, {0x01, 0x60, 0xA9},
74 {0x01, 0x64, 0xAB}, {0x01, 0x6E, 0xD9}, {0x01, 0x7D, 0xAE},
75 /* c< d< e< n< r< s< t< uo z< */
76 {0x01, 0x0D, 0xE8}, {0x01, 0x0F, 0xEF}, {0x01, 0x1B, 0xEC},
77 {0x01, 0x48, 0xF2}, {0x01, 0x59, 0xF8}, {0x01, 0x61, 0xB9},
78 {0x01, 0x65, 0xBB}, {0x01, 0x6F, 0xF9}, {0x01, 0x7E, 0xBE},
79 /* A< A, C' D/ E, L< L' L/ */
80 {0x01, 0x02, 0xC3}, {0x01, 0x04, 0xA1}, {0x01, 0x06, 0xC6},
81 {0x01, 0x10, 0xD0}, {0x01, 0x18, 0xCA}, {0x01, 0x3D, 0xA5},
82 {0x01, 0x39, 0xC5}, {0x01, 0x41, 0xA3},
83 /* N' O" R' S' S, T, U" Z' Z. */
84 {0x01, 0x43, 0xD1}, {0x01, 0x50, 0xD5}, {0x01, 0x54, 0xC0},
85 {0x01, 0x5A, 0xA6}, {0x01, 0x5E, 0xAA}, {0x01, 0x62, 0xDE},
86 {0x01, 0x70, 0xDB}, {0x01, 0x79, 0xAC}, {0x01, 0x7B, 0xAF},
87 /* a< a, c' d/ e, l< l' l/ */
88 {0x01, 0x03, 0xE3}, {0x01, 0x05, 0xB1}, {0x01, 0x07, 0xE6},
89 {0x01, 0x11, 0xF0}, {0x01, 0x19, 0xEA}, {0x01, 0x3E, 0xB5},
90 {0x01, 0x3A, 0xE5}, {0x01, 0x42, 0xB3},
91 /* n' o" r' s' s, t, u" z' z. */
92 {0x01, 0x44, 0xF1}, {0x01, 0x51, 0xF5}, {0x01, 0x55, 0xE0},
93 {0x01, 0x5B, 0xB6}, {0x01, 0x5F, 0xBA}, {0x01, 0x63, 0xFE},
94 {0x01, 0x71, 0xFB}, {0x01, 0x7A, 0xBC}, {0x01, 0x7C, 0xBF},
99 unsigned char unicode_table[][3] =
109 {0x01, 0x04, 0xA4}, {0x01, 0x06, 0x8F},
115 {0x01, 0x79, 0x8D}, {0x01, 0x7B, 0xBD},
117 {0x01, 0x05, 0xA5}, {0x01, 0x07, 0x86},
123 {0x01, 0x7A, 0xAB}, {0x01, 0x7C, 0xBE},
131 unsigned char EncodeWithDefaultAlphabet(unsigned char value)
135 if (value == '?') return 0x3f;
137 for (i = 0; i < NUMBER_OF_7_BIT_ALPHABET_ELEMENTS; i++)
138 if (GSM_DefaultAlphabet[i] == value)
144 unsigned char DecodeWithDefaultAlphabet(unsigned char value)
146 return GSM_DefaultAlphabet[value];
154 wchar_t EncodeWithUnicodeAlphabet(unsigned char value)
160 /*If character is not found, first unicode byte is set to zero
161 and second one is the same as iso-8859-2 character*/
162 retval = value | (0x00 << 8);
164 for ( j = 0; unicode_table[j][2] != 0x00; ++j )
165 if ( value == unicode_table[j][2] )
167 retval = unicode_table[j][1] | (unicode_table[j][0] << 8);
177 unsigned char DecodeWithUnicodeAlphabet(wchar_t value)
179 unsigned char retval;
183 retval=value & 0xff; /* default is to cut off the first byte */
185 for ( j = 0; unicode_table[j][2] != 0x00; ++j )
186 if (((value >> 8) & 0xff) == unicode_table[j][0] &&
187 (value & 0xff) == unicode_table[j][1] ) {
188 retval = unicode_table[j][2];
199 /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
200 unsigned char GSM_DefaultAlphabetUnicode[NUMBER_OF_7_BIT_ALPHABET_ELEMENTS+1][2] =
202 {0x00,0x40},{0x00,0xa3},{0x00,0x24},{0x00,0xA5},
203 {0x00,0xE8},{0x00,0xE9},{0x00,0xF9},{0x00,0xEC},//0x08
204 {0x00,0xF2},{0x00,0xC7},{0x00,'\n'},{0x00,0xD8},
205 {0x00,0xD9},{0x00,'\r'},{0x00,0xC5},{0x00,0xE5},
206 {0x03,0x94},{0x00,0xb9}/*not exactly, but*/,{0x03,0xA6},{0x03,0x93},
207 {0x03,0x9B},{0x03,0xA9},{0x03,0xA0},{0x03,0xA8},
208 {0x03,0xA3},{0x03,0x98},{0x03,0x9E},{0x00,0xb9},/*not exactly, but*/
209 {0x00,0xC6},{0x00,0xE6},{0x00,0xDF},{0x00,0xC9},//0x20
210 {0x00,' ' },{0x00,'!' },{0x00,'\"'},{0x00,'#' },
211 {0x00,0xA4},{0x00,'%' },{0x00,'&' },{0x00,'\''},
212 {0x00,'(' },{0x00,')' },{0x00,'*' },{0x00,'+' },
213 {0x00,',' },{0x00,'-' },{0x00,'.' },{0x00,'/' }, //0x30
214 {0x00,'0' },{0x00,'1' },{0x00,'2' },{0x00,'3' },
215 {0x00,'4' },{0x00,'5' },{0x00,'6' },{0x00,'7' },
216 {0x00,'8' },{0x00,'9' },{0x00,':' },{0x00,';' },
217 {0x00,'<' },{0x00,'=' },{0x00,'>' },{0x00,'?' }, //0x40
218 {0x00,0xA1},{0x00,'A' },{0x00,'B' },{0x00,'C' },
219 {0x00,'D' },{0x00,'E' },{0x00,'F' },{0x00,'G' },
220 {0x00,'H' },{0x00,'I' },{0x00,'J' },{0x00,'K' },
221 {0x00,'L' },{0x00,'M' },{0x00,'N' },{0x00,'O' },
222 {0x00,'P' },{0x00,'Q' },{0x00,'R' },{0x00,'S' },
223 {0x00,'T' },{0x00,'U' },{0x00,'V' },{0x00,'W' },
224 {0x00,'X' },{0x00,'Y' },{0x00,'Z' },{0x00,0xC4},
225 {0x00,0xD6},{0x00,0xD1},{0x00,0xDC},{0x00,0xA7},
226 {0x00,0xBF},{0x00,'a' },{0x00,'b' },{0x00,'c' },
227 {0x00,'d' },{0x00,'e' },{0x00,'f' },{0x00,'g' },
228 {0x00,'h' },{0x00,'i' },{0x00,'j' },{0x00,'k' },
229 {0x00,'l' },{0x00,'m' },{0x00,'n' },{0x00,'o' },
230 {0x00,'p' },{0x00,'q' },{0x00,'r' },{0x00,'s' },
231 {0x00,'t' },{0x00,'u' },{0x00,'v' },{0x00,'w' },
232 {0x00,'x' },{0x00,'y' },{0x00,'z' },{0x00,0xE4},
233 {0x00,0xF6},{0x00,0xF1},{0x00,0xFC},{0x00,0xE0},
237 unsigned char EncodeWithDefaultAlphabet(unsigned char value)
243 if (value == '?') return 0x3f;
245 for (i = 0; i < NUMBER_OF_7_BIT_ALPHABET_ELEMENTS; i++) {
247 value2 = GSM_DefaultAlphabetUnicode[i][1] | ( GSM_DefaultAlphabetUnicode[i][0] << 8);
249 if (EncodeWithUnicodeAlphabet(value) == value2)
256 unsigned char DecodeWithDefaultAlphabet(unsigned char value)
260 value2 = GSM_DefaultAlphabetUnicode[value][1] | ( GSM_DefaultAlphabetUnicode[value][0] << 8);
262 return DecodeWithUnicodeAlphabet(value2);
265 wchar_t EncodeWithUnicodeAlphabet(unsigned char value)
269 if (mbtowc(&retval, &value, 1) == -1) return '?';
273 unsigned char DecodeWithUnicodeAlphabet(wchar_t value)
275 unsigned char retval;
277 if (wctomb(&retval, value) == -1) return '?';
287 void DecodeDefault (unsigned char* dest, const unsigned char* src, int len)
291 for (i = 0; i < len; i++)
292 dest[i] = DecodeWithDefaultAlphabet(src[i]);
296 void EncodeDefault (unsigned char* dest, const unsigned char* src, int len)
300 for (i = 0; i < len; i++)
301 dest[i] = EncodeWithDefaultAlphabet(src[i]);
307 void DecodeUnicode (unsigned char* dest, const unsigned char* src, int len)
312 for (i = 0; i < len; i++) {
313 wc = src[(2*i)+1] | (src[2*i] << 8);
314 dest[i] = DecodeWithUnicodeAlphabet(wc);
320 void EncodeUnicode (unsigned char* dest, const unsigned char* src, int len)
325 for (i = 0; i < len; i++) {
326 wc = EncodeWithUnicodeAlphabet(src[i]);
327 dest[i*2] = (wc >> 8) &0xff;
328 dest[(i*2)+1] = wc & 0xff;
335 bool EncodeWithUTF8Alphabet(u8 mychar, u8 *ret1, u8 *ret2)
337 u8 mychar1,mychar2,mychar3,mychar4;
340 mychar1=((EncodeWithUnicodeAlphabet(mychar)>>8)&0xff);
341 mychar2=EncodeWithUnicodeAlphabet(mychar)&0xff;
342 if (mychar1>0x00 || mychar2>128) {
346 if (mychar3==mychar1) {
347 if (mychar4+64>=mychar2) {
349 *ret2=0x80+(mychar2-mychar4);
367 void DecodeWithUTF8Alphabet(u8 mychar3, u8 mychar4, u8 *ret)
375 for(j=0;j<mychar3-0xc2;j++) {
383 mychar2=mychar2+(mychar4-0x80);
384 wc = mychar2 | (mychar1 << 8);
385 *ret=DecodeWithUnicodeAlphabet(wc);
391 void EncodeUTF8 (unsigned char* dest, const unsigned char* src, int len)
397 for (i = 0; i < len; i++) {
398 if (EncodeWithUTF8Alphabet(src[i],&mychar1,&mychar2)) {
399 sprintf(buf, "=%02X=%02X",mychar1,mychar2);
400 for (z=0;z<6;z++) dest[j++]=buf[z];
410 void DecodeUTF8 (unsigned char* dest, const unsigned char* src, int len)
413 u8 mychar1, mychar2,ret;
417 /* Need to have correct chars */
418 if (src[i] =='=' && DecodeWithHexBinAlphabet(src[i+1])!=-1
419 && DecodeWithHexBinAlphabet(src[i+2])!=-1 &&
420 src[i+3]=='=' && DecodeWithHexBinAlphabet(src[i+4])!=-1 &&
421 DecodeWithHexBinAlphabet(src[i+5])!=-1) {
422 mychar1=16*DecodeWithHexBinAlphabet(src[i+1])+DecodeWithHexBinAlphabet(src[i+2]);
423 mychar2=16*DecodeWithHexBinAlphabet(src[i+4])+DecodeWithHexBinAlphabet(src[i+5]);
424 DecodeWithUTF8Alphabet(mychar1,mychar2,&ret);
438 int DecodeWithHexBinAlphabet (unsigned char mychar) {
439 if (mychar>='A' && mychar<='F') return mychar-'A'+10;
440 if (mychar>='a' && mychar<='f') return mychar-'a'+10;
441 if (mychar>='0' && mychar<='9') return mychar-'0';
445 unsigned char EncodeWithHexBinAlphabet (int digit) {
446 if (digit >= 0 && digit <= 9) return '0'+(digit);
447 if (digit >=10 && digit <=15) return 'A'+(digit-10);
451 void DecodeHexBin (unsigned char* dest, const unsigned char* src, int len)
455 for (i = 0; i < len/2 ; i++) {
456 dest[current++]=DecodeWithHexBinAlphabet(src[i*2])*16+
457 DecodeWithHexBinAlphabet(src[i*2+1]);
462 void EncodeHexBin (unsigned char* dest, const unsigned char* src, int len)
466 for (i = 0; i < len; i++) {
467 dest[current++]=EncodeWithHexBinAlphabet(src[i] >> 0x04);
468 dest[current++]=EncodeWithHexBinAlphabet(src[i] & 0x0f);
472 void DecodeBCD (unsigned char* dest, const unsigned char* src, int len)
474 int i,current=0,digit;
476 for (i = 0; i < len; i++) {
478 if (digit<10) dest[current++]=digit + '0';
480 if (digit<10) dest[current++]=digit + '0';
485 void EncodeBCD (unsigned char* dest, const unsigned char* src, int len, bool fill)
489 for (i = 0; i < len; i++) {
491 dest[current]=dest[current] | ((src[i]-'0') << 4);
494 dest[current]=src[i]-'0';
498 /* When fill is set: we fill in the most significant bits of the
499 last byte with 0x0f (1111 binary) if the number is represented
500 with odd number of digits. */
501 if (fill && (len & 0x01)) {
502 dest[current]=dest[current] | 0xf0;
506 unsigned char EncodeWithBCDAlphabet(int value)
508 return ((value%10) << 4) | ((value/10) & 0xf);
511 int DecodeWithBCDAlphabet(unsigned char value)
513 return 10*(value & 0x0f)+(value >> 4);