Revert manifest to default one
[framework/telephony/tel-plugin-dbus_tapi.git] / src / sat_util.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <errno.h>
4 #include <string.h>
5 #include <assert.h>
6
7 #include <iconv.h>
8 #include <glib.h>
9
10 #include "sat_manager.h"
11 #include "util.h"
12
13 #define tabGsmUniMax2 9
14 #define tabGsmUniMax 42
15
16 static void _convert_gsm_to_utf8(unsigned char *dest, unsigned short *dest_len, unsigned char *src, unsigned int src_len);
17
18 static gboolean _convert_gsm_to_unicode(unsigned short *dest, int dest_len, unsigned char *src, unsigned int src_len);
19 static gboolean _convert_unicode_to_gsm(unsigned char* dest, int dest_len, unsigned short* src, int src_len);
20
21 static char* _convert_ucs_to_utf8(unsigned char *src, int src_len);
22 static int _convert_utf8_to_unicode(unsigned short* dest, unsigned char* src, unsigned int src_len);
23
24 static unsigned short* _convert_process_unicode(unsigned short *dest, int dest_buf_len, unsigned char *src, unsigned long src_len);
25
26 static int _convert_ucs2_to_gsm(unsigned char* dest, unsigned short* src, unsigned int src_len);
27 static int _convert_gsm_to_ucs2(unsigned short* dest, unsigned char* src, unsigned int src_len);
28
29 static gboolean _find_gsm_code_exception_table(unsigned short src);
30 static int _get_gsm_code_size(unsigned short* src, int src_len);
31 static unsigned short* _swap_byte_order(unsigned short *dest, unsigned short *src, int len);
32
33 typedef struct {
34         char gsm;
35         unsigned short unicode;
36 } GsmUniTable;
37
38 const GsmUniTable gsm_unicode2_table[] = {
39                 { 0x14, 0x005E }, { 0x28, 0x007B }, { 0x29, 0x007D }, { 0x2F, 0x005C },
40                 { 0x3C, 0x005B }, { 0x3D, 0x007E }, { 0x3E, 0x005D }, { 0x40, 0x007C },
41                 { 0x65, 0x20AC } };
42
43 const GsmUniTable gsm_unicode_table[] = {
44                 { 0x00, 0x0040 }, { 0x01, 0x00A3 }, { 0x02, 0x0024 }, { 0x03, 0x00A5 },
45                 { 0x04, 0x00E8 }, { 0x05, 0x00E9 }, { 0x06, 0x00F9 }, { 0x07, 0x00EC }, { 0x08, 0x00F2 },
46                 { 0x09, 0x00E7 }, { 0x0B, 0x00D8 }, { 0x0C, 0x00F8 }, { 0x0E, 0x00C5 }, { 0x0F, 0x00E5 },
47                 { 0x10, 0x0394 }, { 0x11, 0x005F }, { 0x12, 0x03A6 }, { 0x13, 0x0393 }, { 0x14, 0x039B },
48                 { 0x15, 0x03A9 }, { 0x16, 0x03A0 }, { 0x17, 0x03A8 }, { 0x18, 0x03A3 }, { 0x19, 0x0398 },
49                 { 0x1A, 0x039E }, { 0x1C, 0x00C6 }, { 0x1D, 0x00E6 }, { 0x1E, 0x00DF }, { 0x1F, 0x00C9 },
50                 { 0x24, 0x00A4 }, { 0x40, 0x00A1 }, { 0x5B, 0x00C4 }, { 0x5C, 0x00D6 }, { 0x5D, 0x00D1 },
51                 { 0x5E, 0x00DC }, { 0x5F, 0x00A7 }, { 0x60, 0x00BF }, { 0x7B, 0x00E4 }, { 0x7C, 0x00F6 },
52                 { 0x7D, 0x00F1 }, { 0x7E, 0x00FC }, { 0x7F, 0x00E0 }, };
53
54 static int _convert_utf8_to_unicode(unsigned short* dest, unsigned char* src, unsigned int src_len)
55 {
56         unsigned short* org = NULL;
57         unsigned char hi = 0;
58         unsigned char mid = 0;
59         unsigned char low = 0;
60
61         if ((NULL == dest) || (NULL == src)) {
62                 dbg( "[SAT] INPUT PARAM NULL");
63                 return -1;
64         }
65
66         org = dest;
67
68         while (src_len > 0 && (*src != '\0')) {
69                 if (*src < 0x80) {
70                         *dest = (*src & 0x7F);
71                         dest++;
72                         src++;
73                         src_len--;
74                 } else if (((0xC0 <= *src) && (*src < 0xE0)) && (*(src + 1) >= 0x80)) {
75                         hi = *src & 0x1F;
76                         low = *(src+1) & 0x3F;
77                         *dest = (hi << 6) | low;
78                         dest++;
79                         src += 2;
80                         src_len -= 2;
81                 } else if ((*src >= 0xE0) && (*(src + 1) >= 0x80) && (*(src + 2) >= 0x80)) {
82                         hi = *src & 0x0F;
83                         mid = *(src+1) & 0x3F;
84                         low = *(src+2) & 0x3F;
85                         *dest = (hi << 12) | (mid << 6) | low;
86                         dest++;
87                         src += 3;
88                         src_len -= 3;
89                 } else {
90                         *dest = (*src & 0x7F);
91                         dest++;
92                         src++;
93                         src_len--;
94                         dbg( "[SAT] utf8 incorrect range");
95                 }
96         }
97         *dest = 0;
98         return (dest - org);
99 }
100
101 static gboolean _find_gsm_code_exception_table(unsigned short src)
102 {
103         if ((src >= 0x0020 && src <= 0x0023)
104                         || (src >= 0x0025 && src <= 0x003F)
105                         || (src >= 0x0041 && src <= 0x005A)
106                         || (src >= 0x0061 && src <= 0x007A)
107                         || src == 0x000A || src == 0x000D)
108                 return TRUE;
109         return FALSE;
110 }
111
112 static int _get_gsm_code_size(unsigned short* src, int src_len)
113 {
114         gboolean in_table = FALSE;
115         gboolean in_sec_table = FALSE;
116         int i, gsm_len = 0;
117
118         if (NULL == src) {
119                 dbg( "INPUT PARAM was NULL");
120                 return -1;
121         }
122
123         for (; src_len > 0 && src; src_len--) {
124                 if (_find_gsm_code_exception_table(*src) == TRUE) {
125                         src++;
126                         gsm_len++;
127                         continue;
128                 }
129                 in_table = FALSE;
130                 for (i = 0; i < tabGsmUniMax; i++) {
131                         if (*src == gsm_unicode_table[i].unicode) {
132                                 src++;
133                                 in_table = TRUE;
134                                 gsm_len++;
135                                 break;
136                         }
137                 }
138                 if (in_table == FALSE) {
139                         in_sec_table = FALSE;
140                         for (i = 0; i < tabGsmUniMax2; i++) {/* second table */
141                                 if (*src == gsm_unicode2_table[i].unicode) {
142                                         src++;
143                                         in_table = TRUE;
144                                         in_sec_table = TRUE;
145                                         gsm_len += 2;
146                                         break;
147                                 }
148                         }
149                         if (in_sec_table == FALSE) {/* second*/
150                                 if (_find_gsm_code_exception_table(*src) == FALSE) {
151                                         dbg( "GSM Char[%d], gsm_len[%d]", *src, gsm_len);
152                                         return -1;
153                                 }
154                                 src++;
155                                 gsm_len++;
156                         }
157                 }
158         }
159         return gsm_len;
160 }
161
162 static int _convert_ucs2_to_gsm(unsigned char* dest, unsigned short* src, unsigned int src_len)
163 {
164         unsigned char* rear = NULL;
165         unsigned short* p;
166         unsigned char temp;
167         gboolean in_table = FALSE;
168         gboolean in_sec_table = FALSE;
169         int i, gc_len = 0;
170
171         if ((!dest) || (!src) || (0x00 == src_len)) {
172                 dbg( "Warning: Wrong Input");
173                 return -1;
174         }
175
176         rear = dest;
177         p = src;
178
179         for (; src_len > 0 && p; src_len--) {
180                 in_table = FALSE;
181                 for (i = 0; i < tabGsmUniMax; i++) { /* is in table  */
182                         if (*p == gsm_unicode_table[i].unicode) {
183                                 temp = (unsigned char) (gsm_unicode_table[i].gsm);
184                                 *rear = temp;
185                                 rear++;
186                                 p++;
187                                 in_table = TRUE;
188                                 gc_len++;
189                                 break;
190                         }
191                 }
192                 if (in_table == FALSE) {
193                         in_sec_table = FALSE;
194                         for (i = 0; i < tabGsmUniMax2; i++) { /* second table*/
195                                 if (*p == gsm_unicode2_table[i].unicode) {
196                                         *rear = 0x1B;
197                                         rear++;
198                                         temp = (unsigned char) (gsm_unicode2_table[i].gsm);
199                                         *rear = temp;
200                                         rear++;
201                                         p++;
202                                         in_table = TRUE;
203                                         in_sec_table = TRUE;
204                                         gc_len += 2;
205                                         break;
206                                 }
207                         }
208                         if (in_sec_table == FALSE) { /* second */
209                                 if (_find_gsm_code_exception_table(*p) == FALSE)
210                                         return -1;
211                                 temp = (unsigned char) (*p); /* isn't in table */
212                                 *rear = temp;
213                                 rear++;
214                                 p++;
215                                 gc_len++;
216                         }
217                 }
218         }
219         src = p;
220         return gc_len;
221 }
222
223 static gboolean _convert_unicode_to_gsm(unsigned char* dest, int dest_len, unsigned short* src, int src_len)
224 {
225         char* tmp_str;
226         int gc_len = 0;
227
228         if ((NULL == dest) || (NULL == src)) {
229                 dbg( "INPUT PARAM was NULL");
230                 return FALSE;
231         }
232
233         if (src_len == 0)
234                 return FALSE;
235
236         gc_len = _get_gsm_code_size(src, src_len);
237         if (0 >= gc_len) {
238                 dbg( "Warning: Error[%d] while finding the GSM Code Size", gc_len);
239                 return FALSE;
240         }
241
242         if (dest_len < gc_len) {
243                 if (dest_len == sizeof(void*)) {
244                         dbg( "Out buffer size seems to be small (%s)", dest);
245                 } else {
246                         dbg("Buffer size is too small (%s): dest_len(%d), gc_len(%d)", dest, dest_len, gc_len);
247                 }
248                 return FALSE;
249         }
250
251         tmp_str = calloc(1, (unsigned short) gc_len);
252         if (tmp_str == NULL) {
253                 dbg( "Memory Allocation Failed!");
254                 return FALSE;
255         }
256
257         gc_len = _convert_ucs2_to_gsm((unsigned char*) tmp_str, src, src_len);
258         if (gc_len != -1) {
259                 memcpy((char*) dest, (char*) tmp_str, gc_len);
260                 free(tmp_str);
261                 return TRUE;
262         }
263
264         free(tmp_str);
265         return FALSE;
266 }
267
268 void sat_mgr_convert_utf8_to_gsm(unsigned char *dest, int *dest_len, unsigned char* src, unsigned int src_len)
269 {
270         unsigned short *uc = NULL;
271         int gc_len = 0;
272         int uc_len = 0;
273         gboolean ret = FALSE;
274
275         if (src == NULL || src_len == 0) {
276                 dbg( "WARNING: Invalid Parameter");
277                 return;
278         }
279
280         uc = (unsigned short*) calloc(src_len + 1, sizeof(unsigned short));
281         if (!uc) {
282                 dbg( "WARNING: calloc Failed");
283                 return;
284         }
285
286         /*Converting from UTF8 => UNICODE*/
287         uc_len = _convert_utf8_to_unicode(uc, src, src_len);
288         dbg( "uc_len:[%d]", uc_len);
289         if(uc_len == -1) {
290                 dbg( "_convert_utf8_to_unicode returns false!");
291                 free(uc);
292                 return;
293         }
294
295         /*Finding the GSMCode Size*/
296         gc_len = _get_gsm_code_size(uc, uc_len);
297         dbg( "gc_len:[%d]", gc_len);
298         if ( gc_len == -1) {
299                 dbg( "SM- DATA is not in GSM7BIT Character Set & Error:[%d]",   gc_len);
300                 free(uc);
301                 return;
302         }
303
304         *dest_len = gc_len;
305         /*Converting from UNICODE ==> GSM CODE */
306         ret = _convert_unicode_to_gsm((unsigned char*) dest, *dest_len, uc, uc_len);
307         if (ret == FALSE) {
308                 dbg( "_convert_unicode_to_gsm Failed");
309                 *dest_len = 0x00;
310                 free(uc);
311                 return;
312         }
313
314         if(uc)
315                 free(uc);
316 }
317
318 void sat_mgr_convert_utf8_to_ucs2(unsigned char* dest, int* dest_len,   unsigned char* src, int src_len)
319 {
320         gsize byte_converted = 0;
321         gsize byte_read = 0;
322         gchar* str_converted = NULL;
323         GError *error = NULL;
324         int i;
325         char tmp_char;
326
327         if (dest == NULL || dest_len == NULL || src == NULL) {
328                 dbg( "Invalid Input Parameter");
329                 return;
330         }
331
332         /*Converting from UTF8 => UCS-2 using the g_convert*/
333         str_converted = (gchar*) g_convert((gchar*) src, (gsize) src_len,
334                                                                                                                                                 (gchar*) "UCS-2", (gchar*) "UTF8",
335                                                                                                                                                 (gsize*) &byte_read, (gsize*) &byte_converted,
336                                                                                                                                                 &error);
337         if (str_converted == NULL) {
338                 dbg( "str_converted is NULL");
339                 if (error != NULL) {
340                         dbg( "Problem while conversion UTF8 => UCS2, ErrorCode[%d]", error->code);
341                 }
342                 return;
343         }
344
345         dbg( "src_len[%u], byte_read[%u], byte_converted[%u]", src_len, byte_read, byte_converted);
346         *dest_len = (int) byte_converted;
347
348         if (byte_converted % 2 != 0) {
349                 dbg( "string length is wrong!");
350         } else {
351                 for (i = 0; i < (int)byte_converted; i++) {
352                         if (i % 2 == 0) {
353                                 tmp_char = str_converted[i];
354                                 str_converted[i] = str_converted[i + 1];
355                                 str_converted[i + 1] = tmp_char;
356                         }
357                 }
358         }
359         memcpy((unsigned char*) dest, (unsigned char*) str_converted, byte_converted);
360         g_free(str_converted);
361         return;
362 }
363
364 static int _convert_ucs2_to_utf8(char *out, unsigned short *out_len, char *in, unsigned short in_len)
365 {
366         char *p_o = NULL;
367         size_t src_len = in_len;
368         size_t dest_len = in_len*3;
369         short *dest = NULL;
370         short *src = NULL;
371         int i = 0;
372
373         iconv_t cd = iconv_open("UTF-8", "UCS2");
374         if (cd == (iconv_t) (-1)) {
375                 perror("iconv_open");
376                 return 0;
377         }
378 //For byte swap - start
379         src = (short*)malloc(in_len);
380         memcpy(src, in, in_len);
381         dest = (short*)malloc(in_len);
382     memset(dest, 0, in_len);
383     for(i=0; i<in_len/2; i++){
384         dest[i] = ((src[i] << 8) + (src[i] >> 8));
385     }
386     memcpy(in, dest, in_len);
387     free(dest);
388     free(src);
389  //For byte swap - end
390
391         p_o = out;
392
393         dbg("expected input bytes:%d dest_len:%d\n", src_len, dest_len);
394
395         if (iconv(cd, &in, &src_len, &p_o, &dest_len) == (size_t)(-1)) {
396                 dbg("failed to iconv errno:%d", errno);
397         } else {
398                 dbg("remained input bytes:%d processed bytes:%d", src_len, in_len*3-dest_len);
399                 out[in_len*3-dest_len] = '\0';
400         }
401         *out_len = in_len*3-dest_len;
402         dbg("out_len[%d], output[%s]", *out_len, out);
403         iconv_close(cd);
404         return 0;
405 }
406
407 void sat_mgr_convert_string(unsigned char *dest, unsigned short *dest_len,
408                 enum alphabet_format dcs, unsigned char *src, unsigned short src_len)
409 {
410         int tmp_str_len = 0;
411         unsigned char* tmp_dest_str = dest;
412         unsigned short* in_buf = NULL;
413
414         /*get string length*/
415         /* 0xFF is the end of string */
416         while (src[tmp_str_len] != 0xFF && tmp_str_len < src_len) {
417                 tmp_str_len++;
418         }
419         /* last space character must be deleted */
420         while (src[tmp_str_len - 1] == 0x20 && tmp_str_len > 0) {
421                 tmp_str_len--;
422         }
423
424         dbg( "[SAT] alphabetFormat : [0x%x]", dcs);
425         dbg( "[SAT] tmp_str_len[%d] src_len[%d]", tmp_str_len, src_len);
426
427         switch (dcs) {
428                 case ALPHABET_FROMAT_SMS_DEFAULT:
429                         tmp_dest_str = (unsigned char*)tcore_util_unpack_gsm7bit((const unsigned char *)src, src_len);
430                         _convert_gsm_to_utf8(dest, dest_len, tmp_dest_str, strlen((const char*)tmp_dest_str));
431                         break;
432
433                 case ALPHABET_FROMAT_8BIT_DATA:
434                         _convert_gsm_to_utf8(dest, dest_len, src, tmp_str_len);
435                         break;
436
437                 case ALPHABET_FROMAT_UCS2:{
438                         if (src[0] == 0x80) {
439                                 dbg("UCS2:[0x%2x] prefix case", src[0]);
440                                 _convert_ucs2_to_utf8((char*) dest, dest_len, (char*) (src + 1), src_len - 1);
441                         } else if (src[0] == 0x81 || src[0] == 0x82) {
442                                 dbg("UCS2:[0x%2x] prefix case", src[0]);
443                                 *dest_len = tmp_str_len;
444                                 in_buf = (unsigned short*) malloc(tmp_str_len * sizeof(unsigned short) + 1);
445                                 if (!in_buf) {
446                                         dbg( "[SAT] Error:malloc failed");
447                                         return;
448                                 }
449                                 _convert_process_unicode(in_buf, (tmp_str_len * sizeof(unsigned short) + 1), src,
450                                                 tmp_str_len);
451                                 dest = (unsigned char*) _convert_ucs_to_utf8((unsigned char *) in_buf, tmp_str_len);
452                                 if (in_buf) free(in_buf);
453
454                                 if (!dest) {
455                                         dbg( "[SAT] WARNING: dest str is NULL");
456                                         return;
457                                 }
458                                 memcpy(tmp_dest_str, dest, SAT_TEXT_STRING_LEN_MAX);
459
460                                 if (tmp_dest_str != dest) {
461                                         dbg( "[SAT] destination string address changed hence freeing");
462                                         free(dest);
463                                         dest = NULL;
464                                 }
465                                 dbg( "[SAT] string[%s]", dest);
466                                 dbg( "[SAT] out put string[%s]", tmp_dest_str);
467                                 dbg( "[SAT] string pointer after parsing dcs[0x%x]", dest);
468                                 dbg( "[SAT] string length[%d]", *dest_len);
469                         } else {
470                                 dbg("UCS2: no prefix case");
471                                 _convert_ucs2_to_utf8((char*) dest, dest_len, (char*) src, src_len);
472                         }
473                 }
474                         break;
475
476                 default:
477                         dbg("not handled alpha format[%d]", dcs);
478                         break;
479         }
480
481 }
482
483 static int _convert_gsm_to_ucs2(unsigned short* dest, unsigned char* src, unsigned int src_len)
484 {
485         int index;
486         unsigned short* org;
487
488         org = dest;
489
490         for(index=0; index < (int)src_len; index++){
491                 int table_index=0;
492                 gboolean b_tabled = FALSE;
493
494                 /*
495                  * if the first byte is 0x1B, it is the escape character.
496                  * The byte value shoulbe be changed to unicode.
497                  */
498                 if(*src == 0x1B){
499                         src++; index++;//move to next byte
500                         for(table_index=0; table_index < tabGsmUniMax2; table_index++){
501                                 if(*src == gsm_unicode2_table[table_index].gsm){
502                                         *dest = gsm_unicode2_table[table_index].unicode;
503                                         b_tabled = TRUE;
504                                         break;
505                                 }
506                         }
507
508                         //if matched data is not in table, it should be changed to NULL;
509                         if(!b_tabled){
510                                 *dest = 0x0020;
511                         }
512                 }
513                 else{
514                         for(table_index=0; table_index < tabGsmUniMax; table_index++){
515                                 if(*src == gsm_unicode_table[table_index].gsm){
516                                         *dest = gsm_unicode_table[table_index].unicode;
517                                         b_tabled = TRUE;
518                                         break;
519                                 }
520                         }
521
522                         //if matched data is not in table, it is using original value;
523                         if(!b_tabled){
524                                 *dest = *src;
525                         }
526                 }
527
528                 //move to next position
529                 src++; dest++;
530         }
531
532         dbg("[SAT] cvt sr(%s), the size of data (%d) ", org, dest - org);
533         return (dest - org);
534 }
535
536 static gboolean _convert_gsm_to_unicode(unsigned short *dest, int dest_len, unsigned char *src, unsigned int src_len)
537 {
538         int index, tmp_len;
539
540         if(!dest || !src) {
541                 dbg( "[SAT] dest(%p) or src(%p) is null",dest, src);
542                 return FALSE;
543         }
544
545         if(!src_len){
546                 dest[0] = '\0';
547                 return TRUE;
548         }
549
550         dbg("[SAT] source string (%s) len(%d)", src, src_len);
551
552         for(index = 0; index < (int)src_len; index++){
553                 if(src[index] == 0x1B)
554                         src_len--;
555         }
556         dbg("[SAT] strlen excluding escape character (%d)", src_len);
557
558         tmp_len = _convert_gsm_to_ucs2(dest, src, src_len);
559         dest[tmp_len] = '\0';
560
561         return TRUE;
562 }
563
564 static char* _convert_ucs_to_utf8(unsigned char* src, int src_len)
565 {
566         char* utf_str = NULL;
567         iconv_t cd = NULL;
568         size_t ileft = 0;
569         size_t oleft = 0;
570         int err = 0;
571
572         char* pIn = NULL;
573         char* in_buf = NULL;
574         char* out_buf = NULL;
575
576         if (!src) {
577                 dbg("src is null");
578                 return NULL;
579         }
580
581         ileft = src_len * 2;//over allocate as utf-8 may occupy 3 bytes
582         oleft = src_len * 3;//over allocate as utf-8 may occupy 3 bytes
583         pIn = in_buf = (char*) malloc(ileft + 2);
584         utf_str = out_buf = (char *) malloc(oleft + 1);
585
586         memset(in_buf, 0x00, ileft + 2);
587         memset(out_buf, 0x00, oleft + 1);
588         memcpy(in_buf, src, ileft);
589
590         in_buf[ileft] = '\0';
591
592         cd = iconv_open("UTF-8", "UCS-2");
593         err = iconv(cd, (char**) &in_buf, &ileft, &out_buf, &oleft);
594
595         utf_str[src_len * 2 - ileft] = '\0';
596         iconv_close(cd);
597         free(pIn);
598         return utf_str;
599 }
600
601 static void _convert_gsm_to_utf8(unsigned char* dest, unsigned short* dest_len, unsigned char* src, unsigned int src_len)
602 {
603         int tmp_len = 0;
604         char *target_tmp = NULL;
605         unsigned char *raw_unicode = NULL;
606         unsigned short tmp_dest[SAT_TEXT_STRING_LEN_MAX];
607
608         memset(tmp_dest, 0 , SAT_TEXT_STRING_LEN_MAX);
609
610         _convert_gsm_to_unicode(tmp_dest, SAT_TEXT_STRING_LEN_MAX, src, src_len);
611         while(tmp_dest[tmp_len] != '\0')
612                 tmp_len++;
613         tmp_len++; // add null character
614
615         tmp_len = tmp_len*2; //for byte align
616         raw_unicode = (unsigned char*)malloc(tmp_len);
617         memset(raw_unicode, 0, tmp_len);
618
619         memcpy(raw_unicode, (unsigned char*)tmp_dest, tmp_len);
620
621         *dest_len = tmp_len;
622         target_tmp = _convert_ucs_to_utf8(raw_unicode, tmp_len);
623         if(!target_tmp){
624                 dbg( "str is NULL");
625                 return;
626         }
627
628         memcpy(dest, target_tmp, strlen((const char*)target_tmp));
629         dbg("final utf8 str (%s), length (%d)", dest, tmp_len);
630         return;
631 }
632
633 /*
634  * UCS2 character decoding for SIM alpha identifier as defined ETSI 102 221.
635  */
636 static unsigned short* _convert_process_unicode(unsigned short* dest, int dest_buf_len, unsigned char* src, unsigned long src_len)
637 {
638         int i, j, base = 0, str_len = 0, shift =0;
639         unsigned short tmp_str[255 + 1];
640
641         switch (src[0]) {
642                 case 0x80: {
643                         str_len = (src_len - 1) / 2;
644                         memcpy(tmp_str, &src[1], src_len - 1);
645                         tmp_str[str_len] = '\0';
646                         _swap_byte_order(dest, tmp_str, str_len);
647                         dest[str_len] = '\0';
648                         return dest;
649                 }
650
651                 case 0x81: {
652                         str_len = (int) src[1];
653                         base = (int) src[2];
654                         j = 3;
655                         shift = 7;
656                 }
657                         break;
658
659                 case 0x82: {
660                         str_len = (int) src[1];
661                         base = (int) (src[2] << 8 | src[3]);
662                         j = 4;
663                         shift = 0;
664                 }
665                         break;
666
667                 default: {
668                         for (i = 0; i < (int) src_len; i++) {
669                                 if (src[i] == 0xFF) {
670                                         src_len = i;
671                                         break;
672                                 }
673                         }
674                         str_len = (src_len) / 2;
675                         memcpy(tmp_str, &src[0], src_len);
676                         tmp_str[str_len] = '\0';
677                         _swap_byte_order(dest, tmp_str, str_len);
678                         dest[str_len] = '\0';
679                         return dest;
680                         break;
681                 }
682         }
683
684         dbg( "[SAT] str_len[%d], dest_buf_len[%d]", str_len, dest_buf_len);
685
686         for (i = 0; i < str_len && i < dest_buf_len; i++, j++) {
687                 if (src[j] <= 0x7F) {/* GSM Code */
688                         if (src[j] == 0x1B) {/* 2Byte GSM Code */
689                                 _convert_gsm_to_unicode(&dest[i], 2, &src[j], 2);
690                                 j++;
691                         } else {
692                                 _convert_gsm_to_unicode(&dest[i], 2, &src[j], 1);
693                         }
694                 } else {
695                         dest[i] = (unsigned short) ((base << shift)     + (src[j] & 0x7F));
696                         dbg( "[SAT] converted0x%x\n", src[j]);
697                         dbg( "[SAT] converted0x%x\n", dest[i]);
698                 }
699         }
700         dest[i] = '\0';
701         return dest;
702 }
703
704 static unsigned short* _swap_byte_order(unsigned short* dest, unsigned short* src, int src_len)
705 {
706         int i;
707         for (i = 0; i < src_len; i++) {
708                 if (src[i] == '\0')
709                         break;
710                 dest[i] = ((src[i] << 8) + (src[i] >> 8));
711         }
712         dest[i] = '\0';
713         return dest;
714 }