8c0b9678e2475c32bd88765e354f955f743c4f16
[framework/telephony/libtcore.git] / src / co_sim.c
1 /*
2  * libtcore
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Ja-young Gu <jygu@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include <glib.h>
26
27 #include "tcore.h"
28 #include "plugin.h"
29 #include "queue.h"
30 #include "user_request.h"
31 #include "core_object.h"
32 #include "co_sim.h"
33
34 struct private_object_data {
35         struct tcore_sim_operations *ops;
36
37         enum tel_sim_type type; /**< Provides the SIM card type*/
38         enum tel_sim_status sim_status; /**< Provides the card status*/
39         struct tel_sim_imsi imsi; /**< Provides IMSI information*/
40         gboolean b_sim_changed; /**< Provides SIM card Identification- 0:no changed, 1:changed*/
41         gboolean b_cphs; /**< Whether current SIM is for CPHS or not*/
42
43         enum tel_sim_file_id language_file; /**<Provides Current cached language EF address */
44         enum tel_sim_file_id cf_file; /**<Provides Current cached call forwarding EF address */
45         enum tel_sim_file_id mw_file; /**<Provides Current cached message waiting EF address */
46         enum tel_sim_file_id mb_file; /**<Provides Current cached mailbox number EF address */
47
48         void *userdata; /**< free use data*/
49 };
50
51
52 static TReturn _dispatcher(CoreObject *o, UserRequest *ur)
53 {
54         enum tcore_request_command command;
55         struct private_object_data *po = NULL;
56
57         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_SIM, TCORE_RETURN_EINVAL);
58
59         po = tcore_object_ref_object(o);
60         if (!po || !po->ops)
61                 return TCORE_RETURN_ENOSYS;
62
63         command = tcore_user_request_get_command(ur);
64
65         switch (command) {
66                 case TREQ_SIM_VERIFY_PINS:
67                         if (!po->ops->verify_pins)
68                                 return TCORE_RETURN_ENOSYS;
69
70                         return po->ops->verify_pins(o, ur);
71                         break;
72
73                 case TREQ_SIM_VERIFY_PUKS:
74                         if (!po->ops->verify_puks)
75                                 return TCORE_RETURN_ENOSYS;
76
77                         return po->ops->verify_puks(o, ur);
78                         break;
79
80                 case TREQ_SIM_CHANGE_PINS:
81                         if (!po->ops->change_pins)
82                                 return TCORE_RETURN_ENOSYS;
83
84                         return po->ops->change_pins(o, ur);
85                         break;
86
87                 case TREQ_SIM_GET_FACILITY_STATUS:
88                         if (!po->ops->get_facility_status)
89                                 return TCORE_RETURN_ENOSYS;
90
91                         return po->ops->get_facility_status(o, ur);
92                         break;
93
94                 case TREQ_SIM_DISABLE_FACILITY:
95                         if (!po->ops->disable_facility)
96                                 return TCORE_RETURN_ENOSYS;
97
98                         return po->ops->disable_facility(o, ur);
99                         break;
100
101                 case TREQ_SIM_ENABLE_FACILITY:
102                         if (!po->ops->enable_facility)
103                                 return TCORE_RETURN_ENOSYS;
104
105                         return po->ops->enable_facility(o, ur);
106                         break;
107
108                 case TREQ_SIM_GET_LOCK_INFO:
109                         if (!po->ops->get_lock_info)
110                                 return TCORE_RETURN_ENOSYS;
111
112                         return po->ops->get_lock_info(o, ur);
113                         break;
114
115                 case TREQ_SIM_TRANSMIT_APDU:
116                         if (!po->ops->transmit_apdu)
117                                 return TCORE_RETURN_ENOSYS;
118
119                         return po->ops->transmit_apdu(o, ur);
120                         break;
121
122                 case TREQ_SIM_GET_ATR:
123                         if (!po->ops->get_atr)
124                                 return TCORE_RETURN_ENOSYS;
125
126                         return po->ops->get_atr(o, ur);
127                         break;
128
129                 case TREQ_SIM_SET_LANGUAGE:
130                 case TREQ_SIM_SET_CALLFORWARDING:
131                         if (!po->ops->update_file)
132                                 return TCORE_RETURN_ENOSYS;
133
134                         return po->ops->update_file(o, ur);
135                         break;
136
137                 case TREQ_SIM_GET_ECC:
138                 case TREQ_SIM_GET_LANGUAGE:
139                 case TREQ_SIM_GET_ICCID:
140                 case TREQ_SIM_GET_MAILBOX:
141                 case TREQ_SIM_GET_CALLFORWARDING:
142                 case TREQ_SIM_GET_MESSAGEWAITING:
143                 case TREQ_SIM_GET_CPHS_INFO:
144                 case TREQ_SIM_GET_MSISDN:
145                 case TREQ_SIM_GET_SPN:
146                 case TREQ_SIM_GET_SPDI:
147                 case TREQ_SIM_GET_OPL:
148                 case TREQ_SIM_GET_PNN:
149                 case TREQ_SIM_GET_CPHS_NETNAME:
150                 case TREQ_SIM_GET_OPLMNWACT:
151                         if (!po->ops->read_file)
152                                 return TCORE_RETURN_ENOSYS;
153
154                         return po->ops->read_file(o, ur);
155                         break;
156
157                 case TREQ_SIM_REQ_AUTHENTICATION:
158                         if (!po->ops->req_authentication)
159                                 return TCORE_RETURN_ENOSYS;
160
161                         return po->ops->req_authentication(o, ur);
162                         break;
163
164                 default:
165                         break;
166         }
167
168         return TCORE_RETURN_SUCCESS;
169 }
170
171 static void _clone_hook(CoreObject *src, CoreObject *dest)
172 {
173         struct private_object_data *src_po = NULL;
174         struct private_object_data *dest_po = NULL;
175
176         if (!src || !dest)
177                 return;
178
179         dest_po = calloc(sizeof(struct private_object_data), 1);
180         if (!dest_po) {
181                 tcore_object_link_object(dest, NULL);
182                 return;
183         }
184
185         src_po = tcore_object_ref_object(src);
186         dest_po->ops = src_po->ops;
187
188         tcore_object_link_object(dest, dest_po);
189 }
190
191 static void _free_hook(CoreObject *o)
192 {
193         struct private_object_data *po = NULL;
194
195         CORE_OBJECT_CHECK(o, CORE_OBJECT_TYPE_SIM);
196
197         po = tcore_object_ref_object(o);
198         if (po) {
199                 free(po);
200                 tcore_object_link_object(o, NULL);
201         }
202 }
203
204 static void _reverse(char* p_in, int length)
205 {
206         int i, j = length - 1;
207         for (i = 0; i < j; i++) {
208                 int t = p_in[i];
209                 p_in[i] = p_in[j];
210                 p_in[j--] = t;
211         }
212 }
213
214 static char* _acitoa(int n, char* str, int b)
215 {
216         int i = 0;
217
218         do {
219                 str[i++] = "0123456789ABCDEF"[n % b];
220         } while ((n /= b) > 0);
221
222         _reverse(str, i);
223
224         str[i] = '\0';
225
226         return str;
227 }
228
229 /*******************************************************************************
230  Convert Digit to BCD (BCD to Digit)
231
232  bcd            <--->   digit
233  0xa                            0x2a '*'
234  0xb                            0x23 '#'
235  0xc                            0x70 'P'
236  0xd                            '?'
237  0xf                            0
238  1032547698             0123456789
239
240  ********************************************************************************/
241 /**
242  * This function is used to Convert Digit to BCD (Digit to BCD)
243  *
244  * @return              None
245  * @param[out]  bcdCode - BCD output
246  * @param[in]           digits - Digit input
247  * @param[in]           digitLen - digit length
248  * @Interface           Synchronous.
249  * @remark
250  * @Refer
251  */
252 static void _digit_to_bcd(char* bcdCode, char* digits, int digitLen)
253 {
254         int i, j, digit;
255         unsigned char higher, lower;
256
257         // 0123456789 -> 1032547698
258         for (i = 0, j = 0; i < digitLen; i = i + 2, j++) {
259                 if (digits[i] == '*')
260                         digit = 0x0A;
261                 else if (digits[i] == '#')
262                         digit = 0x0B;
263                 else if (toupper((int) digits[i]) == 'P')
264                         digit = 0x0C;
265                 else if ((digits[i]) == '?')
266                         digit = 0x0D;
267                 else
268                         digit = (int) digits[i];
269
270                 lower = digit & 0x0F;
271
272                 if (digitLen != i + 1) {
273                         if (digits[i + 1] == '*')
274                                 digit = 0x0A;
275                         else if (digits[i + 1] == '#')
276                                 digit = 0x0B;
277                         else if (toupper((int) digits[i + 1]) == 'P')
278                                 digit = 0x0C;
279                         else if (digits[i + 1] == '?')
280                                 digit = 0x0D;
281                         else
282                                 digit = (int) digits[i + 1];
283                         higher = digit & 0x0F;
284                 } else {
285                         higher = 0xFF;
286                 }
287                 bcdCode[j] = (higher << 4) | lower;
288         }
289 }
290
291 /**
292  * This function is used to Convert BCD to Digit (BCD to Digit)
293  *
294  * @return              None
295  * @param[out]  digit - Digit output output
296  * @param[in]           bcdCode - BCD Input
297  * @param[in]           bcdLen - BCD length
298  * @Interface           Synchronous.
299  * @remark
300  * @Refer
301  */
302 static unsigned long _bcd_to_digit(char* digit, char* bcdCode, int bcdLen)
303 {
304         int i, h, l;
305         char c[2];
306         unsigned char higher, lower;
307         unsigned long digitLen = 0;
308
309         // 0123456789 <- 1032547698
310         memset((void*) digit, 0, bcdLen * 2);
311
312         for (i = 0; i < bcdLen; i++) {
313                 higher = (bcdCode[i] >> 4) & 0x0F; // get high nibble
314
315                 if (higher == 0x0A)
316                         higher = '*'; // =0x2A
317                 else if (higher == 0x0B)
318                         higher = '#'; // =0x23
319                 else if (higher == 0x0C)
320                         higher = 'P'; // =0x70, DTMF Control digit
321                 else if (higher == 0x0D)
322                         higher = '?';
323                 else if (higher == 0x0F)
324                         higher = 0;
325                 else {
326                         h = (int) higher;
327                         _acitoa(h, c, 16);
328                         higher = (char) toupper(*c);
329                 }
330
331                 lower = bcdCode[i] & 0x0F; // get low nibble
332
333                 if (lower == 0x0A)
334                         lower = '*';
335                 else if (lower == 0x0B)
336                         lower = '#';
337                 else if (lower == 0x0C)
338                         lower = 'P'; //DTMF Control digit
339                 else if (lower == 0x0D)
340                         lower = '?';
341                 else if (lower == 0x0F)
342                         lower = 0;
343                 else {
344                         l = (int) lower;
345                         _acitoa(l, c, 16);
346                         lower = (char) toupper(*c);
347                 }
348                 digit[i * 2] = lower;
349                 digit[i * 2 + 1] = higher;
350         }
351
352         digitLen = (unsigned long) strlen(digit);
353         return digitLen;
354 }
355
356 /**
357  * This function is used to get(decode) string name
358  *
359  * @return              length of string
360  * @param[out]  palpha_id - Alpha string
361  * @param[in]           pRecord - Input raw data
362  * @param[in]           alphaIDMaxLen - Max size of alpha id array
363  * @Interface           Synchronous.
364  * @remark
365  * @Refer
366  */
367 static unsigned long _get_string(unsigned char* palpha_id, unsigned char* pRecord,      unsigned long alphaIDMaxLen)
368 {
369         unsigned long i, alphaIDLen = 0;
370         unsigned char *pAlphaID = (unsigned char*) palpha_id;
371
372         memset((void*) pAlphaID, 0, alphaIDMaxLen);
373
374         if (pRecord[0] == 0xFF)
375                 return alphaIDLen;
376
377         for (i = 0; i < alphaIDMaxLen; i++) {
378                 if (pRecord[0] <= 0x7F && pRecord[i] == 0xFF)
379                         break;
380
381                 pAlphaID[i] = pRecord[i];
382                 alphaIDLen++;
383         }
384         return alphaIDLen;
385 }
386
387 /**
388  * This function is used to set(encode) string name
389  *
390  * @return              length of string
391  * @param[in]           palpha_id - Alpha string input
392  * @param[out]  pRecord - output raw data
393  * @param[in]           alphaIDMaxLen - Max size of alpha id array
394  * @Interface           Synchronous.
395  * @remark
396  * @Refer
397  */
398 static void _set_string(unsigned char* pRecord, unsigned char* palpha_id, unsigned long alphaIDMaxLen)
399 {
400         unsigned long i;
401         unsigned char* pAlphaID = (unsigned char*) palpha_id;
402
403         memset((void*) pRecord, 0xFF, alphaIDMaxLen);
404
405         for (i = 0; i < alphaIDMaxLen; i++)
406                 pRecord[i] = pAlphaID[i];
407 }
408
409 static gboolean _is_empty(unsigned char* p_in, int in_length)
410 {
411         int i;
412         for (i = 0; i < in_length; i++) {
413                 if (p_in[i] != 0xFF)
414                         return FALSE;
415         }
416         dbg("current index has empty data");
417         return TRUE;            // this is empty record.
418 }
419
420 /**
421  * This function is used to get BCD length
422  *
423  * @return              length of string
424  * @param[in]           pBcdData - BCD Input data
425  * @param[in]           bcdMaxLen - BCD Max data Length
426  * @Interface           Synchronous.
427  * @remark
428  * @Refer
429  */
430 static int _get_valid_bcd_byte(unsigned char* pBcdData, int bcdMaxLen)
431 {
432         int i, bcd_length = 0;
433
434         for (i = 0; i < bcdMaxLen; i++) {
435                 if (pBcdData[i] == 0xFF)
436                         break;
437
438                 bcd_length++;
439         }
440         return bcd_length;
441 }
442
443 /**
444  * This function is used to get unpacked 8bit Format from GSM 7bit packed string.
445  *
446  * @return          the length of unpacked characters   .
447  * @param[out]  out_string      Specifies the unpacked output string
448  * @param[in]           in_string       Contains the input string to be unpacked
449  * @param[in]           in_string_len   Contains the input string length
450  * @remark
451  */
452 static int _unpack_7bit28bit(unsigned char* pInString, unsigned int inStringLen, unsigned char * pOutString)
453 {
454         int i = 0;
455         unsigned int pos = 0;
456         unsigned short shift = 0;
457         int outlen = 0;
458         outlen = (short int) ((inStringLen * 8) / 7);
459
460         for (i = 0; pos < inStringLen; i++, pos++) {
461                 pOutString[i] = (pInString[pos] << shift) & 0x7F;
462
463                 if (pos != 0) {
464                         /* except the first byte, a character contains some bits from the previous byte.*/
465                         pOutString[i] |= pInString[pos - 1] >> (8 - shift);
466                 }
467
468                 shift++;
469
470                 if (shift == 7) {
471                         shift = 0;
472
473                         /* a possible extra complete character is available */
474                         i++;
475                         pOutString[i] = pInString[pos] >> 1;
476                 }
477         }
478
479         /*If a character is '\r'(13), change it to space(32) */
480         for (i = 0; i < outlen; i++)
481                 if (pOutString[i] == 13) pOutString[i] = 32;
482
483         pOutString[outlen] = '\0';
484
485         dbg( "unpack is done with outlen[%d] and array index[%d], out string[%s]", outlen, i, pOutString);
486         return (unsigned int) (i);
487 }
488
489 static int _ucs2_to_utf8(int in_length, unsigned char *in_data, int *out_length,        unsigned char *out_data)
490 {
491         int i, j;
492         i = j = 0;
493         if (in_length == 0 || in_data == NULL || out_data == NULL) {
494                 dbg( "Unicode Decode Failed as text length is 0");
495                 return FALSE;
496         }
497
498         if (0 != (in_length % 2)) {
499                 dbg( " ##### Unicode decoding failed due to invalid text length [%d]",  in_length);
500                 return FALSE;
501         }
502
503         for (i = 0; i < in_length; i++) {
504                 out_data[i] = in_data[j];
505                 j = j + 2;
506         }
507         *out_length = (in_length / 2);
508         out_data[i] = '\0';
509         return TRUE;
510 }
511
512 /**
513  * According to ETSI 102.221 ( 3GPP specification refers it ), EF-ICCID is coded by BCD, left justified and padded with 'F'.
514  * This EF is mandatory and byte length is fixed with 10 bytes. So actual maximum length of ICCID is 20 digits.
515  */
516 gboolean tcore_sim_decode_iccid(struct tel_sim_iccid *p_out, unsigned char *p_in, int in_length)
517 {
518         int bcd_byte = 0;
519         int char_length = 0;
520
521         if (p_in == NULL || p_out == NULL)
522                 return FALSE;
523
524         if (in_length == 0 || in_length > 10)
525                 return FALSE;
526
527         memset((void*) p_out->iccid, 0, SIM_ICCID_LEN_MAX+1);
528
529         bcd_byte = _get_valid_bcd_byte(p_in, in_length);
530         dbg( "ICCID valid bcd byte is[%d]", bcd_byte);
531
532         char_length = _bcd_to_digit(p_out->iccid, (char*) p_in, bcd_byte);
533         dbg( "ICCID string length is[%d]", char_length);
534
535         *(p_out->iccid+char_length) = '\0';
536
537         return TRUE;
538 }
539
540 /**
541  * This function is used to decode EFLP (2G)
542  */
543 gboolean tcore_sim_decode_lp(struct tel_sim_language *p_out, unsigned char *p_in, int in_length)
544 {
545         int i = 0;
546
547         memset((void*) p_out, 0xFF, sizeof(struct tel_sim_language));
548         p_out->language_count = 0;
549
550         if (in_length == 0)
551                 return FALSE;
552         /*
553          * Description of problem: language decoding was not correctly done if we used 7layers's test SIM
554          * Patch Description : The tested SIM  at 7layers has 3 language codes like [ff][ff][01].
555          In this case we could not decode 3rd language code.
556          So, the below 2 lines checking the UNSPECIFIED language are commented.
557          */
558
559         if (in_length > SIM_LANG_CNT_MAX)
560                 in_length = SIM_LANG_CNT_MAX;
561
562         for (i = 0; i < in_length; i++) {
563                 /*
564                  * Description of problem: Language decoding was not correctly done if we used some test SIM
565                  * Patch Description : Test SIM at some place has 3 language codes like  [ff][ff][01].
566                  * In this case we could not decode 3rd language code.
567                  * So, the below 2 lines checking the UNSPECIFIED language are commented.
568                  */
569                 if (p_in[i] == 0xFF)
570                         continue;
571
572                 p_out->language[p_out->language_count] = (enum tel_sim_language_type) p_in[i];
573                 dbg( "p_out->language[%d]=[%d] ", i, p_out->language[p_out->language_count]);
574                 p_out->language_count++;
575         }
576         dbg( "in_length %d, lang_cnt %d ", in_length, p_out->language_count);
577         return TRUE;
578 }
579
580 /**
581  * This function is used to encode EFLP (2G)
582  */
583 char* tcore_sim_encode_lp( int *out_length, struct tel_sim_language *p_in)
584 {
585     int i = 0;
586     char *tmp_out = NULL;
587
588     if ( out_length == NULL || p_in == NULL ){
589         dbg("out_length or p_in is null");
590         return NULL;
591     }
592
593     tmp_out = (char*)malloc(p_in->language_count);
594     memset((void*) tmp_out, 0xff, p_in->language_count);
595
596     for (i = 0; i < p_in->language_count; i++)
597         tmp_out[i] = p_in->language[i];
598
599     *out_length = i;
600     return tmp_out;
601 }
602
603 /**
604  * This function is used to decode LI (3G)
605  */
606 gboolean tcore_sim_decode_li(enum tel_sim_file_id file_id, struct tel_sim_language *p_out, unsigned char *p_in, int in_length)
607 {
608         int i;
609         unsigned short defaultLi;
610         unsigned char tempLi[3] = { 0, 0, 0 };
611
612         memset((void*) p_out, 0xFF, sizeof(struct tel_sim_language));
613         p_out->language_count  = 0;
614
615         if (in_length == 0)
616                 return FALSE;
617
618         /*
619          * Description of problem: language decoding was not correctly done if we used 7layers's test SIM
620          * Patch Description : TS31.102 If the EFLI has the value 'FFFF' in its highest priority position,
621          then the preferred language selection shall be the language preference in the EFPL
622          */
623         if (/*TODO g_sim.CardType == SIM_TYPE_USIM && */(file_id == SIM_EF_USIM_LI || file_id == SIM_EF_LP)) {
624                 defaultLi = p_in[0];
625                 defaultLi = ((defaultLi << 8) & 0xFF00) + p_in[1];
626
627                 if (defaultLi == 0xFFFF)        // 1st language is default.
628                         return FALSE;
629         }
630
631         if (in_length > SIM_LANG_CNT_MAX)
632                 in_length = SIM_LANG_CNT_MAX;
633
634         for (i = 0; i < in_length; i++) {
635                 tempLi[0] = p_in[i++];
636                 tempLi[1] = p_in[i];
637 /*
638                  Description of problem: language decoding was not correctly done if we used 7layers's test SIM
639                  Patch Description : The tested SIM at specific test lab has 3 language codes like [ff][ff][ff][ff][64][65].
640                  In this case we could not decode 3rd language code.
641                  So, the below 2 lines checking the UNSPECIFIED language are commented.
642 */
643                 if (tempLi[0] == 0xFF || tempLi[1] == 0xFF)  //this is always 2 bytes
644                         continue;
645
646                 p_out->language[p_out->language_count] = SIM_LANG_UNSPECIFIED;
647
648                 if (tempLi[0] == 'e') {
649                         switch (tempLi[1]) {
650                                 case 'n':
651                                         p_out->language[p_out->language_count] = SIM_LANG_ENGLISH;
652                                         break;
653                                 case 's':
654                                         p_out->language[p_out->language_count] = SIM_LANG_SPANISH;
655                                         break;
656                                 case 'l':
657                                         p_out->language[p_out->language_count] = SIM_LANG_GREEK;
658                                         break;
659                         }
660                 } else if (tempLi[0] == 'd') {
661                         switch (tempLi[1]) {
662                                 case 'e':
663                                         p_out->language[p_out->language_count] = SIM_LANG_GERMAN;
664                                         break;
665
666                                 case 'a':
667                                         p_out->language[p_out->language_count] = SIM_LANG_DANISH;
668                                         break;
669                         }
670                 } else if (tempLi[0] == 'i' && tempLi[1] == 't') {
671                         p_out->language[p_out->language_count] = SIM_LANG_ITALIAN;
672                 } else if (tempLi[0] == 'f' && tempLi[1] == 'r') {
673                         p_out->language[p_out->language_count] = SIM_LANG_FRENCH;
674                 } else if (tempLi[0] == 'n' && tempLi[1] == 'l') {
675                         p_out->language[p_out->language_count] = SIM_LANG_DUTCH;
676                 } else if (tempLi[0] == 's' && tempLi[1] == 'v') {
677                         p_out->language[p_out->language_count] = SIM_LANG_SWEDISH;
678                 } else if (tempLi[0] == 'f' && tempLi[1] == 'i') {
679                         p_out->language[p_out->language_count] = SIM_LANG_FINNISH;
680                 } else if (tempLi[0] == 'n' && tempLi[1] == 'o') {
681                         p_out->language[p_out->language_count] = SIM_LANG_NORWEGIAN;
682                 } else if (tempLi[0] == 't' && tempLi[1] == 'r') {
683                         p_out->language[p_out->language_count] = SIM_LANG_TURKISH;
684                 } else if (tempLi[0] == 'h' && tempLi[1] == 'u') {
685                         p_out->language[p_out->language_count] = SIM_LANG_HUNGARIAN;
686                 } else if (tempLi[0] == 'p') {
687                         switch (tempLi[1]) {
688                                 case 'l':
689                                         p_out->language[p_out->language_count] = SIM_LANG_POLISH;
690                                         break;
691                                 case 't':
692                                         p_out->language[p_out->language_count] = SIM_LANG_PORTUGUESE;
693                                         break;
694                         }
695                 } else if (tempLi[0] == 'k' && tempLi[1] == 'o') {
696                         p_out->language[p_out->language_count] = SIM_LANG_KOREAN;
697                 } else if (tempLi[0] == 'z' && tempLi[1] == 'h') {
698                         p_out->language[p_out->language_count] = SIM_LANG_CHINESE;
699                 } else if (tempLi[0] == 'r' && tempLi[1] == 'u') {
700                         p_out->language[p_out->language_count] = SIM_LANG_RUSSIAN;
701                 } else if (tempLi[0] == 'j' && tempLi[1] == 'a') {
702                         p_out->language[p_out->language_count] = SIM_LANG_JAPANESE;
703                 }
704
705                 dbg( "count %d & Codes %d ", p_out->language_count, p_out->language[p_out->language_count]);
706                 p_out->language_count++;
707         }
708
709         if (p_out->language_count == 0) {
710                 dbg( "p_out->language_count = %d ", p_out->language_count);
711                 return FALSE;
712         }
713         else {
714                 return TRUE;
715         }
716 }
717
718 /**
719  * This function is used to encode EFLI (3G)
720  */
721 char* tcore_sim_encode_li( int *out_length, struct tel_sim_language *p_in)
722 {
723         int i = 0;
724     char *tmp_out = NULL;
725         char *LanguageCode[] = { "de", "en", "it", "fr", "es", "nl", "sv", "da", "pt", "fi", "no", "el",
726                                                                                                         "tr", "hu", "pl", "ko", "zh", "ru", "ja" };
727
728     if ( out_length == NULL || p_in == NULL ){
729         dbg("out_length or p_in is null");
730         return NULL;
731     }
732
733     tmp_out = (char*)malloc((p_in->language_count) *2);
734     memset((void*) tmp_out, 0xff, (p_in->language_count)*2);
735
736         for (i = 0; i < p_in->language_count; i++) {
737                 if (p_in->language[i] < SIM_LANG_UNSPECIFIED) {
738                         strncpy((char *) &tmp_out[i * 2], LanguageCode[p_in->language[i]], 2);
739                         dbg( "sim_encode_li: p_out[%s]:[%x][%x]", tmp_out, tmp_out[i*2], tmp_out[(i*2)+1]);
740                 }
741         }
742         *out_length = i*2;
743         return tmp_out;
744 }
745
746 gboolean tcore_sim_decode_imsi(struct tel_sim_imsi *p_out, unsigned char *p_in, int in_length)
747 {
748         int i,j=0;
749         char imsi_raw[16];
750
751         dbg( "Func Entrance");
752
753         if ((NULL == p_out) || (NULL == p_in))
754                 return FALSE;
755
756         /*
757                 According to 3GPP specification, the length of raw IMSI data is 9 bytes.
758                 first byte is length of IMSI
759                 second byte byte has parity nibble, so second byte has one digit of IMSI. other byte has two digit of IMSI
760         */
761         if ((in_length == 0) || (in_length == 0xff) || (4 > in_length) || (9 <in_length)) {
762                 dbg("No valid IMSI present to convert - length:[%x]",   in_length);
763                 return FALSE;
764         }
765         dbg("imsi length[%d], input data length[%d]", p_in[0], in_length);
766
767         /* Decode IMSI value from nibbles */
768         for (i = 1; i < in_length; i++) {
769                 if (i == 1) { /* first byte, ignore lower nibble */
770                         imsi_raw[j++] = ((p_in[i] & 0xF0) >> 4) + '0';
771                 } else if (i == p_in[0]+1) { /* last byte */
772                         imsi_raw[j++] = (p_in[i] & 0x0F)+ '0';
773                         if (p_in[0]%2) /* count the last one if odd digits */
774                                 imsi_raw[j++] = ((p_in[i] & 0xF0) >> 4) + '0';
775                 } else {
776                         imsi_raw[j++] = (p_in[i]  & 0x0F) + '0';
777                         imsi_raw[j++] = ((p_in[i] & 0xF0) >> 4) + '0';
778                 }
779         }
780         /* Terminate string */
781         imsi_raw[j] = '\0';
782         dbg("imsi_raw[%s], size[%d]", imsi_raw, strlen(imsi_raw));
783
784         memcpy(p_out->plmn, imsi_raw, 5);
785         p_out->plmn[5] = '\0';
786         memcpy(p_out->msin, imsi_raw+5, strlen(imsi_raw)-5);
787         p_out->msin[strlen(imsi_raw)-5] = '\0';
788
789         dbg("p_out->plmn[%s], p_out->msin[%s]", p_out->plmn, p_out->msin);
790
791         return TRUE;
792 }
793
794 gboolean tcore_sim_decode_sst(struct tel_sim_sst *p_sst, unsigned char *p_in, int in_length)
795 {
796         unsigned char sstByte, rast, mask = 0;
797         char simServiceID = 1;  // set "CHV1 disable function"
798         int i, svc_count;
799         char *p_index;
800
801         memset((void*)p_sst, 0, sizeof(struct tel_sim_sst));
802
803         if (in_length == 0 || in_length > SIM_SST_LEN_MAX)
804                 return FALSE;
805
806         // get count of SIM service id. one byte has four service status.
807         svc_count = in_length * 4;
808
809         /*3GPP 11.11 SST shows 50 kinds of service types. current sim_ss_s has also 50 elements*/
810         if (svc_count > SIM_SST_SERVICE_CNT_MAX)
811                 svc_count = SIM_SST_SERVICE_CNT_MAX;
812
813         p_index = (char*)p_sst;
814
815         for (i = 0; i < svc_count; i++) {
816                 sstByte = p_in[(simServiceID - 1) / 4];
817                 rast = simServiceID - 4 * (simServiceID / 4);
818
819                 switch (rast) {
820                         case 1:
821                                 mask = 0x02;
822                                 break;
823                         case 2:
824                                 mask = 0x08;
825                                 break;
826                         case 3:
827                                 mask = 0x20;
828                                 break;
829                         case 0:
830                                 mask = 0x80;
831                                 break;
832                 }
833
834                 if (sstByte & mask)
835                         *p_index = 1;
836                 else
837                         *p_index = 0;
838
839                 p_index += sizeof(char);
840                 simServiceID++; // next service id
841         }
842         return TRUE;
843 }
844
845 gboolean tcore_sim_decode_spn(struct tel_sim_spn *p_spn, unsigned char *p_in, int in_length)
846 {
847         int i;
848
849         if (in_length == 0)
850                 return FALSE;
851
852         p_spn->display_condition = p_in[0];
853         dbg( "The display condition is [%d]", p_spn->display_condition);
854
855         for (i = 1; i < SIM_SPN_LEN_MAX + 1; i++) {
856                 if (p_in[i] == 0xFF)
857                         break; /* loop break*/
858
859                 p_spn->spn[i - 1] = p_in[i];
860                 dbg( "EF-SPN name[%d][%c]", i, p_in[i]);
861         }
862         p_spn->spn[i-1] = '\0';
863
864         return TRUE;
865 }
866
867 gboolean tcore_sim_decode_spdi(struct tel_sim_spdi *p_spdi, unsigned char *p_in, int in_length)
868 {
869         int i, Src_plmn_start_len, total_data_len;
870
871         if (in_length == 0)
872                 return FALSE;
873
874         if(p_in[0] == 0xff){
875                 dbg("file is exist but there is no valid records");
876                 p_spdi->plmn_count = 0;
877                 memset(p_spdi->list, 0x00, sizeof(unsigned char)*7*SIM_SPDI_PLMN_MAX);
878                 return TRUE;
879         }
880
881         //Display info tag('A3')
882         if (p_in[0] == 0xA3) {
883                 total_data_len = p_in[1];
884                  //PLMN list tag('80')
885                 if (p_in[2] == 0x80) {
886                         p_spdi->plmn_count = p_in[3] / 3;
887
888                         /*
889                          *  plmn tag 1byte
890                          *  length 1byte
891                          *  each plmn entry 3byte
892                          */
893                         if (p_spdi->plmn_count > SIM_SPDI_PLMN_MAX)
894                                 p_spdi->plmn_count =    SIM_SPDI_PLMN_MAX;
895
896                         Src_plmn_start_len = 4;
897
898                         dbg( "p_spdi->num_of_plmn_entries[%d]", p_spdi->plmn_count);
899
900                         for (i = 0; i < p_spdi->plmn_count; i++) {
901                                 unsigned char packetInDigit[3 * 2 + 1];
902                                 _bcd_to_digit((char*) packetInDigit, (char*) &p_in[Src_plmn_start_len], 3);
903                                 // get MCC (mobile country code)
904                                 memcpy(p_spdi->list[i].plmn, &(packetInDigit[0]), 6);
905                                 p_spdi->list[i].plmn[6] = '\0';
906                                 dbg( "SPDI PLMN[%d][%s]", i, p_spdi->list[i].plmn);
907
908                                 Src_plmn_start_len = Src_plmn_start_len + 3;
909                         }
910                         return TRUE;
911                 }
912                 dbg("Current EF-SPDI has invalid data");
913                 return FALSE;
914         }
915         dbg("Current EF-SPDI has invalid data");
916         return FALSE;
917 }
918
919 gboolean tcore_sim_decode_msisdn(struct tel_sim_msisdn *p_msisdn, unsigned char *p_in, int in_length)
920 {
921         int X;  // alpha id max length
922         int value_length;
923         int bcd_byte;   // dialing number max length
924
925         memset((void*) p_msisdn, 0, sizeof(struct tel_sim_msisdn));
926
927         if (in_length == 0)
928                 return FALSE;
929
930         if (_is_empty(p_in, in_length) == TRUE) {
931                 memset(p_msisdn, 0, sizeof(struct tel_sim_msisdn));
932                 return FALSE;
933         }
934
935         X = in_length - 14;     // get alpha id max length
936
937         if (X != 0) {
938                 value_length =  _get_string((unsigned char *)p_msisdn->name, p_in, X);
939                 p_msisdn->name[value_length] = '\0';
940         }
941
942         // get dialing number length
943         // p_in[X] is BCD length of dialing number length plus TON/NPI 1 bytes.
944         // Convert to digit length and subtract TON/NPI length.
945         if (p_in[X] != 0xFF) {
946                 dbg( "Dialing number Length %d, BCD length 0x%x ",  (p_in[X] - 1) * 2, p_in[X]);
947
948                 // get TON and NPI
949                 p_msisdn->ton = (p_in[X + 1] >> 4) & 0x07;
950
951                 // get actual dialing number length
952                 bcd_byte = _get_valid_bcd_byte(&p_in[X + 2], SIM_XDN_NUMBER_LEN_MAX / 2);
953                 dbg( "bcd_byte[%x]", bcd_byte);
954
955                 // get dialing number/SSC string
956                 value_length = _bcd_to_digit((char*) p_msisdn->num, (char*) &p_in[X + 2], bcd_byte); // actual dialing number length in BCD.
957                 p_msisdn->num[value_length] = '\0';
958                 dbg( "p_msisdn->num[%s]", p_msisdn->num);
959         }
960         return TRUE;
961 }
962
963 gboolean tcore_sim_decode_xdn(struct tel_sim_dialing_number *p_xdn, unsigned char *p_in, int in_length)
964 {
965         int X;  // alpha id max length
966         int bcd_byte;   // dialing number max length
967
968         memset((void*) p_xdn, 0, sizeof(struct tel_sim_dialing_number));
969
970         if (in_length == 0)
971                 return FALSE;
972
973         if (_is_empty(p_in, in_length) == TRUE) {
974                 return FALSE;   // this is empty record
975         }
976
977         X = in_length - 14;     // get alpha id max length
978
979         if (X != 0) {
980                 p_xdn->AlphaIdLength = _get_string((unsigned char *)p_xdn->AlphaId, p_in, X);
981                 p_xdn->AlphaIDMaxLength = X;
982         }
983
984         // get dialing number length
985         // p_in[X] is BCD length of dialing number length plus TON/NPI 1 bytes.
986         // Convert to digit length and subtract TON/NPI length.
987         if (p_in[X] != 0xFF) {
988                 p_xdn->DiallingNumMaxLength = (p_in[X] - 1) * 2;
989                 dbg( "Dialing number Length %d, BCD length 0x%x ",      p_xdn->DiallingNumMaxLength, p_in[X]);
990
991                 if (p_xdn->DiallingNumMaxLength > SIM_XDN_NUMBER_LEN_MAX)       {
992                         /*
993                          this may be broken record.
994                          p_xdn->b_used = FALSE;
995                          memset((void*)p_xdn, 0, sizeof(tapi_sim_dialing_number_info_t));
996                          return FALSE;
997
998                          ADN record cannot have more than 20 digits. Anyway we can restrict this as per 31.102
999                          X+1    Length of BCD number/SSC contents       M       1 byte
1000                          X+2    TON and NPI     M       1 byte
1001                          X+3 to X+12    Dialing Number/SSC String       M       10 bytes
1002                          X+13   Capability/Configuration1 Identifier    M       1 byte
1003                          X+14   Extension1 Record Identifier    M       1 byte
1004
1005                          Anyway we are doing this check @
1006                          bcd_byte = _get_valid_bcd_byte (&p_in[X+2], TAPI_SIM_XDN_DIALING_NUMBER_LEN/2);
1007                          by using the 20/2; so don`t return false.
1008                          */
1009                         if (p_in[X] == 0x00)
1010                                 p_xdn->DiallingNumMaxLength = 0;
1011                         else
1012                                 p_xdn->DiallingNumMaxLength = SIM_XDN_NUMBER_LEN_MAX;
1013                 }
1014
1015                 // get TON and NPI
1016                 p_xdn->TypeOfNumber = (p_in[X + 1] >> 4) & 0x07;
1017                 p_xdn->NumberingPlanIdent = p_in[X + 1] & 0x0F;
1018
1019                 // get actual dialing number length
1020                 bcd_byte = _get_valid_bcd_byte(&p_in[X + 2], SIM_XDN_NUMBER_LEN_MAX / 2);
1021                 dbg( "bcd_byte[%x]", bcd_byte);
1022
1023                 // get dialing number/SSC string
1024                 p_xdn->DiallingnumLength = _bcd_to_digit((char*) p_xdn->DiallingNum, (char*) &p_in[X + 2], bcd_byte); // actual dialing number length in BCD.
1025                 dbg( "p_xdn->DiallingnumLength[%x]", p_xdn->DiallingnumLength);
1026                 dbg( "p_xdn->DiallingNum[%s]", p_xdn->DiallingNum);
1027                 // get Capability/Configuration id
1028                 p_xdn->CapaConfigId = p_in[X + 12];
1029                 // get Extension1 id
1030                 p_xdn->Ext1RecordId = p_in[X + 13];
1031         }
1032         return TRUE;
1033 }
1034
1035 gboolean tcore_sim_encode_xdn(char *p_out, int out_length, struct tel_sim_dialing_number *p_xdn)
1036 {
1037         int X;
1038         char bcdCode[SIM_XDN_NUMBER_LEN_MAX / 2];
1039
1040         memset((void*) p_out, 0xFF, out_length);
1041
1042         X = out_length - 14;            // get alpha id max length
1043
1044         if (X < p_xdn->AlphaIdLength)
1045                 return FALSE;           // alpha id is too big
1046
1047         if (p_xdn->DiallingnumLength > SIM_XDN_NUMBER_LEN_MAX)  // this is digit length
1048                 return FALSE;   // dialing number is too big
1049
1050         _set_string((unsigned char *)p_out, (unsigned char *)p_xdn->AlphaId, p_xdn->AlphaIdLength);
1051
1052         // set length of BCD number/SSC contents
1053         // p_xdn->diallingnumLen is maximum digit length. = 20 bytes.
1054         // convert to BCD length and add 1 byte.
1055         p_out[X] = ((p_xdn->DiallingnumLength + 1) / 2) + 1;
1056
1057         // set TON and NPI
1058         p_out[X + 1] = 0x80;
1059         p_out[X + 1] |= (p_xdn->TypeOfNumber & 0x07) << 4;
1060         p_out[X + 1] |= p_xdn->NumberingPlanIdent & 0x0F;
1061
1062         // set dialing number/SSC string
1063         memset((void*) bcdCode, 0xFF, SIM_XDN_NUMBER_LEN_MAX / 2);
1064
1065         _digit_to_bcd((char*) bcdCode, (char*) p_xdn->DiallingNum, p_xdn->DiallingnumLength);
1066
1067         memcpy((void*) &p_out[X + 2], bcdCode, SIM_XDN_NUMBER_LEN_MAX / 2);
1068
1069         // set Capability/Configuration Identifier
1070         p_out[X + 12] = (unsigned char) p_xdn->CapaConfigId;
1071         // set extension1 record Identifier
1072         p_out[X + 13] = (unsigned char) p_xdn->Ext1RecordId;
1073
1074         return TRUE;
1075 }
1076
1077 gboolean tcore_sim_decode_ecc(struct tel_sim_ecc_list *p_ecc, unsigned char *p_in, int in_length)
1078 {
1079         int bcd_byte;   // dialing number max length
1080         int i;
1081         int valid_ecc_length;
1082         memset((void*)p_ecc, 0x00, sizeof(struct tel_sim_ecc_list));
1083
1084         if(in_length%3 != 0) {
1085                 dbg("error - invalid data length");
1086                 return FALSE;
1087         }
1088
1089         for(i=0; i < in_length/3; i++){
1090                 //get the BCD length of the ECC
1091                 bcd_byte = _get_valid_bcd_byte((unsigned char*) p_in+(i*3), 3);
1092                 if(bcd_byte != 0) {
1093                         valid_ecc_length = _bcd_to_digit(p_ecc->ecc[p_ecc->ecc_count].ecc_num, (char *)p_in+(i*3), bcd_byte);
1094                         p_ecc->ecc[p_ecc->ecc_count].ecc_num[valid_ecc_length] = '\0';
1095                         p_ecc->ecc_count++;
1096                 }
1097         }
1098         return TRUE;
1099 }
1100
1101 gboolean tcore_sim_decode_ust(struct tel_sim_ust *p_ust, unsigned char *p_in, int in_length)
1102 {
1103         int i, j;
1104         char mask;
1105         char *p_index;
1106         memset((void*) p_ust, 0, sizeof(struct tel_sim_ust));
1107         p_index = (char*)p_ust;
1108
1109 /*      UST service is described to 74(1 byte includes 8 service status) in 31.102 r7.
1110         current sim_ust_s has 64 services. so in_length should be under 8 byte. */
1111         if (in_length > SIM_UST_BYTE_LEN_MAX)
1112                 in_length = SIM_UST_BYTE_LEN_MAX;
1113
1114         for (i = 0; i < in_length; i++) {
1115                 mask = 0x01;    // reset mast to check first bit
1116
1117                 for (j = 0; j < 8; j++) {
1118                         if (p_in[i] & mask) {
1119                                 *p_index = 1;
1120                         }
1121                         p_index += sizeof(char);
1122                         mask = mask << 1;
1123                 }
1124         }
1125         return TRUE;
1126 }
1127
1128 gboolean tcore_sim_decode_est(struct tel_sim_est *p_est, unsigned char *p_in, int in_length)
1129 {
1130         memset((void*) p_est, 0, sizeof(struct tel_sim_est));
1131
1132         if (*p_in & 0x01)
1133                 p_est->bFdnEnabled = TRUE;
1134         if (*p_in & 0x02)
1135                 p_est->bBdnEnabled = TRUE;
1136         if (*p_in & 0x04)
1137                 p_est->bAclEnabled = TRUE;
1138
1139         return TRUE;
1140 }
1141
1142 gboolean tcore_sim_decode_uecc(struct tel_sim_ecc *p_ecc, unsigned char* p_in, int in_length)
1143 {
1144         int bcd_byte;   // dialing number max length
1145         unsigned char eccServiceCategory;
1146
1147         if (_is_empty(p_in, in_length) == TRUE) {
1148                 memset(p_ecc, 0, sizeof(struct tel_sim_ecc));
1149                 return FALSE;
1150         }
1151
1152         //get the BCD length of the ECC
1153         bcd_byte = _get_valid_bcd_byte(&p_in[0], SIM_ECC_BYTE_LEN_MAX);
1154
1155         //get the ECC codes in digits and the length as well
1156         _bcd_to_digit((char*) p_ecc->ecc_num, (char*) &p_in[0], bcd_byte);
1157
1158         //get the alpha identifier of ECC (
1159         _get_string((unsigned char*) p_ecc->ecc_string, (unsigned char*) &p_in[3], in_length - 3);
1160
1161         eccServiceCategory = p_in[in_length - 1] & 0x1F;         // Check for the first 5 bits
1162
1163         /*
1164          Assign the service category
1165          3GPP TS24.008 Emergency Service Category Value.
1166          Bit 8,7,6 are spare, 5~1 bit is used.
1167          The meaning of the Emergency Category Value is derived from the following settings
1168          (see 3GPP TS 22.101 clause 10):
1169          Bit 1  Police 0x01
1170          Bit 2  Ambulance 0x02
1171          Bit 3  Fire Brigade 0x04
1172          Bit 4  Marine Guard 0x08
1173          Bit 5  Mountain Rescue 0x10
1174          Bit 6  manually initiated eCall
1175          Bit 7  automatically initiated eCall
1176          Bit 8  is spare and set to "0"
1177          */
1178         switch (eccServiceCategory) {
1179                 case 0x01:
1180                         p_ecc->ecc_category = SIM_ECC_POLICE;
1181                         break;
1182                 case 0x02:
1183                         p_ecc->ecc_category = SIM_ECC_AMBULANCE;
1184                         break;
1185                 case 0x04:
1186                         p_ecc->ecc_category = SIM_ECC_FIREBRIGADE;
1187                         break;
1188                 case 0x08:
1189                         p_ecc->ecc_category = SIM_ECC_MARAINEGUARD;
1190                         break;
1191                 case 0x10:
1192                         p_ecc->ecc_category = SIM_ECC_MOUTAINRESCUE;
1193                         break;
1194                 default:
1195                         p_ecc->ecc_category = SIM_ECC_SPARE;
1196                         break;
1197         }
1198         return TRUE;
1199 }
1200
1201 gboolean tcore_sim_decode_gid( struct tel_sim_gid *p_gid, unsigned char* p_in, int in_length)
1202 {
1203         int i;
1204
1205         memset((void*) p_gid, 0, sizeof(struct tel_sim_gid ));
1206
1207         if (in_length == 0)
1208                 return FALSE;
1209
1210 /*regarding 31.102, EF-GID data byte is not defined. currently 10.*/
1211         if (in_length >= SIM_GROUP_IDENTIFIER_LEN_MAX)
1212                 in_length = SIM_GROUP_IDENTIFIER_LEN_MAX;
1213
1214         for (i = 0; i < in_length; i++) {
1215                 if (p_in[i] == 0xFF)
1216                         break;
1217
1218                 p_gid->szGroupIdentifier[i] = p_in[i];
1219                 p_gid->GroupIdentifierLen++;
1220         }
1221         return TRUE;
1222 }
1223
1224 gboolean tcore_sim_decode_mbi(struct tel_sim_mbi *p_mbi, unsigned char *p_in, int in_length)
1225 {
1226         int i;
1227         for (i = 0; i < in_length; i++) {
1228                 dbg( " \t0x%04X.", p_in[i]);
1229         }
1230
1231         /* EF-MBI is defined 4 mandatory, 1 optional byte in 31.102 */
1232         if (in_length == 0 || in_length > SIM_MAIL_BOX_IDENTIFIER_LEN_MAX)
1233                 return FALSE;
1234
1235         if ( _is_empty(p_in, in_length) == TRUE) {
1236                 return FALSE; // this is empty record
1237         }
1238
1239         p_mbi->VoiceMailBoxIdentifier = p_in[0];
1240         p_mbi->FaxMailBoxIdentifier = p_in[1];
1241         p_mbi->EmailMailBoxIdentifier = p_in[2];
1242         p_mbi->OtherMailBoxIdentifier = p_in[3];
1243
1244         // 5th byte is optional
1245         if (in_length == 5)
1246                 p_mbi->VideoMailBoxIdentifier = p_in[4];
1247
1248         return TRUE;
1249 }
1250
1251 gboolean tcore_sim_encode_mbi(char *p_out, int out_length, struct tel_sim_mbi *p_mbi)
1252 {
1253         p_out[0] = p_mbi->VoiceMailBoxIdentifier;
1254         p_out[1] = p_mbi->FaxMailBoxIdentifier;
1255         p_out[2] = p_mbi->EmailMailBoxIdentifier;
1256         p_out[3] = p_mbi->OtherMailBoxIdentifier;
1257
1258         if (out_length == 5)
1259                 p_out[4] = p_mbi->VideoMailBoxIdentifier;
1260
1261         return TRUE;
1262 }
1263
1264 gboolean tcore_sim_decode_cff(struct tel_sim_callforwarding *cfis, unsigned char *p_in, int in_length)
1265 {
1266         struct tel_sim_cphs_cf  p_cff = {0,};
1267
1268         if (in_length == 0)
1269                 return FALSE;
1270
1271         dbg( "flag(0)=%x, packetlen=%d ", (unsigned int)p_in[0], in_length);
1272         dbg( "flag(1)=%x", p_in[1]);
1273
1274         if ((p_in[0] & 0x0F) == 0x0A) {
1275                 p_cff.bCallForwardUnconditionalLine1 = TRUE;
1276                 cfis->voice1 = TRUE;
1277         }
1278         if ((p_in[0] & 0xF0) == 0xA0) {
1279                 p_cff.bCallForwardUnconditionalLine2 = TRUE;
1280                 cfis->voice2 = TRUE;
1281         }
1282
1283         if (in_length > 1) {
1284                 if ((p_in[1] & 0x0F) == 0x0A) {
1285                         p_cff.bCallForwardUnconditionalFax = TRUE;
1286                         cfis->fax = TRUE;
1287                 }
1288                 if ((p_in[1] & 0xF0) == 0xA0) {
1289                         p_cff.bCallForwardUnconditionalData = TRUE;
1290                         cfis->data = TRUE;
1291                 }
1292         }
1293
1294         dbg("Line1 = %d, line2 = %d, Fax = %d, Data = %d ",
1295                         p_cff.bCallForwardUnconditionalLine1,
1296                         p_cff.bCallForwardUnconditionalLine2,
1297                         p_cff.bCallForwardUnconditionalFax,
1298                         p_cff.bCallForwardUnconditionalData);
1299         return TRUE;
1300 }
1301
1302 char* tcore_sim_encode_cff(const struct tel_sim_callforwarding *cff)
1303 {
1304         int i, j = 0;
1305         char *p_out = NULL;
1306         unsigned char* pTemp = (unsigned char*) cff;
1307         unsigned char present = 0x0A;
1308         unsigned char absent = 0x05;
1309
1310         p_out =  calloc(SIM_CPHS_CALL_FORWARDING_LEN_MAX+1, 1);
1311
1312         for (i = 0; i < SIM_CPHS_CALL_FORWARDING_LEN_MAX; i++) {
1313                 present = 0x0A;
1314                 absent = 0x05;
1315
1316                 for (j = 0; j < 2; j++) {
1317                         if (*pTemp) {
1318                                 p_out[i] = p_out[i] | present;
1319                         } else {
1320                                 p_out[i] = p_out[i] | absent;
1321                         }
1322                         pTemp += sizeof(gboolean);
1323                         present = present << 4;
1324                         absent = absent << 4;
1325                 }
1326         }
1327         p_out[SIM_CPHS_CALL_FORWARDING_LEN_MAX] = '\0';
1328         return p_out;
1329 }
1330
1331 gboolean tcore_sim_decode_csp(struct tel_sim_cphs_csp *p_csp, unsigned char *p_in, int in_length)
1332 {
1333         int i, j, k = 0;
1334         unsigned char byteSignificance = 0x00;
1335         unsigned char mask = 0x80;
1336
1337         if (in_length == 0)
1338                 return FALSE;
1339
1340         memset((void*) p_csp, 0, sizeof(struct tel_sim_cphs_csp));
1341
1342 /* current telephony supports 22 byte cphs-csp data. 18 byte is mandatory, the other is optional. */
1343         for (i = 0, j = 0; i < SIM_CPHS_CSP_LEN_MAX || j < SIM_CPHS_CSP_LEN_MAX; i++, j++) {
1344                 p_csp->ServiceProfileEntry[j].CustomerServiceGroup = (enum tel_sim_cphs_csp_group) p_in[i];
1345                 byteSignificance = p_in[++i];
1346                 mask = 0x80;
1347
1348                 switch (p_csp->ServiceProfileEntry[j].CustomerServiceGroup) {
1349                         case 0x01:
1350                                 for (k = 0; k < 5; k++) {
1351                                         switch (byteSignificance & mask) {
1352                                                 case 0x80:
1353                                                         p_csp->ServiceProfileEntry[j].u.CallOffering.bCallForwardingUnconditional = TRUE;
1354                                                         break;
1355                                                 case 0x40:
1356                                                         p_csp->ServiceProfileEntry[j].u.CallOffering.bCallForwardingOnUserBusy = TRUE;
1357                                                         break;
1358                                                 case 0x20:
1359                                                         p_csp->ServiceProfileEntry[j].u.CallOffering.bCallForwardingOnNoReply = TRUE;
1360                                                         break;
1361                                                 case 0x10:
1362                                                         p_csp->ServiceProfileEntry[j].u.CallOffering.bCallForwardingOnUserNotReachable = TRUE;
1363                                                         break;
1364                                                 case 0x08:
1365                                                         p_csp->ServiceProfileEntry[j].u.CallOffering.bCallTransfer = TRUE;
1366                                                         break;
1367                                                 default:
1368                                                         break;
1369                                         }
1370                                         mask = mask >> 1;
1371                                 }
1372                                 break;
1373
1374                         case 0x02:
1375                                 for (k = 0; k < 5; k++) {
1376                                         switch (byteSignificance & mask) {
1377                                                 case 0x80:
1378                                                         p_csp->ServiceProfileEntry[j].u.CallRestriction.bBarringOfAllOutgoingCalls = TRUE;
1379                                                         break;
1380                                                 case 0x40:
1381                                                         p_csp->ServiceProfileEntry[j].u.CallRestriction.bBarringOfOutgoingInternationalCalls = TRUE;
1382                                                         break;
1383                                                 case 0x20:
1384                                                         p_csp->ServiceProfileEntry[j].u.CallRestriction.bBarringOfOutgoingInternationalCallsExceptHplmn = TRUE;
1385                                                         break;
1386                                                 case 0x10:
1387                                                         p_csp->ServiceProfileEntry[j].u.CallRestriction.bBarringOfAllIncomingCallsRoamingOutsideHplmn = TRUE;
1388                                                         break;
1389                                                 case 0x08:
1390                                                         p_csp->ServiceProfileEntry[j].u.CallRestriction.bBarringOfIncomingCallsWhenRoaming = TRUE;
1391                                                         break;
1392                                                 default:
1393                                                         break;
1394                                         }
1395                                         mask = mask >> 1;
1396                                 }
1397                                 break;
1398
1399                         case 0x03:
1400                                 for (k = 0; k < 5; k++) {
1401                                         switch (byteSignificance & mask) {
1402                                                 case 0x80:
1403                                                         p_csp->ServiceProfileEntry[j].u.OtherSuppServices.bMultiPartyService = TRUE;
1404                                                         break;
1405                                                 case 0x40:
1406                                                         p_csp->ServiceProfileEntry[j].u.OtherSuppServices.bClosedUserGroup = TRUE;
1407                                                         break;
1408                                                 case 0x20:
1409                                                         p_csp->ServiceProfileEntry[j].u.OtherSuppServices.bAdviceOfCharge = TRUE;
1410                                                         break;
1411                                                 case 0x10:
1412                                                         p_csp->ServiceProfileEntry[j].u.OtherSuppServices.bPreferentialClosedUserGroup = TRUE;
1413                                                         break;
1414                                                 case 0x08:
1415                                                         p_csp->ServiceProfileEntry[j].u.OtherSuppServices.bClosedUserGroupOutgoingAccess = TRUE;
1416                                                         break;
1417                                                 default:
1418                                                         break;
1419                                         }
1420                                         mask = mask >> 1;
1421                                 }
1422                                 break;
1423
1424                         case 0x04:
1425                                 for (k = 0; k < 4; k++) {
1426                                         switch (byteSignificance & mask) {
1427                                                 case 0x80:
1428                                                         p_csp->ServiceProfileEntry[j].u.CallComplete.bCallHold = TRUE;
1429                                                         break;
1430                                                 case 0x40:
1431                                                         p_csp->ServiceProfileEntry[j].u.CallComplete.bCallWaiting = TRUE;
1432                                                         break;
1433                                                 case 0x20:
1434                                                         p_csp->ServiceProfileEntry[j].u.CallComplete.bCompletionOfCallToBusySubscriber = TRUE;
1435                                                         break;
1436                                                 case 0x10:
1437                                                         p_csp->ServiceProfileEntry[j].u.CallComplete.bUserUserSignalling = TRUE;
1438                                                         break;
1439                                                 default:
1440                                                         break;
1441                                         }
1442                                         mask = mask >> 1;
1443                                 }
1444                                 break;
1445
1446                         case 0x05:
1447                                 for (k = 0; k < 7; k++) {
1448                                         switch (byteSignificance & mask) {
1449                                                 case 0x80:
1450                                                         p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageMobileTerminated = TRUE;
1451                                                         break;
1452                                                 case 0x40:
1453                                                         p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageMobileOriginated = TRUE;
1454                                                         break;
1455                                                 case 0x20:
1456                                                         p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageCellBroadcast = TRUE;
1457                                                         break;
1458                                                 case 0x10:
1459                                                         p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageReplyPath = TRUE;
1460                                                         break;
1461                                                 case 0x08:
1462                                                         p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageDeliveryConf = TRUE;
1463                                                         break;
1464                                                 case 0x04:
1465                                                         p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageProtocolIdentifier = TRUE;
1466                                                         break;
1467                                                 case 0x02:
1468                                                         p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageValidityPeriod = TRUE;
1469                                                         break;
1470                                                 default:
1471                                                         break;
1472                                         }
1473                                         mask = mask >> 1;
1474                                 }
1475                                 break;
1476
1477                         case 0x06:
1478                                 for (k = 0; k < 1; k++) {
1479                                         switch (byteSignificance & mask) {
1480                                                 case 0x80:
1481                                                         p_csp->ServiceProfileEntry[j].u.CphsTeleservices.bAlternativeLineService =  TRUE;
1482                                                         break;
1483                                                 default:
1484                                                         break;
1485                                         }
1486                                         mask = mask >> 1;
1487                                 }
1488                                 break;
1489
1490                         case 0x07:
1491                                 for (k = 0; k < 1; k++) {
1492                                         switch (byteSignificance & mask) {
1493                                                 case 0x80:
1494                                                         p_csp->ServiceProfileEntry[j].u.CphsFeatures.bStringServiceTable = TRUE;
1495                                                         break;
1496                                                 default:
1497                                                         break;
1498                                         }
1499                                         mask = mask >> 1;
1500                                 }
1501                                 break;
1502
1503                         case 0x08:
1504                                 for (k = 0; k < 8; k++) {
1505                                         switch (byteSignificance & mask) {
1506                                                 case 0x80:
1507                                                         p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bCallingLineIdentificationPresent = TRUE;
1508                                                         break;
1509                                                 case 0x20:
1510                                                         p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bConnectedLineIdentificationRestrict = TRUE;
1511                                                         break;
1512                                                 case 0x10:
1513                                                         p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bConnectedLineIdentificationPresent = TRUE;
1514                                                         break;
1515                                                 case 0x08:
1516                                                         p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bMaliciousCallIdentifier = TRUE;
1517                                                         break;
1518                                                 case 0x02:
1519                                                         p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bCallingLineIdentificationSend = TRUE;
1520                                                         break;
1521                                                 case 0x01:
1522                                                         p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bCallingLineIdentificationBlock = TRUE;
1523                                                         break;
1524                                                 default:
1525                                                         break;
1526                                         }
1527                                         mask = mask >> 1;
1528                                 }
1529                                 break;
1530
1531                         case 0x09:
1532                                 for (k = 0; k < 6; k++) {
1533                                         switch (byteSignificance & mask) {
1534                                                 case 0x80:
1535                                                         p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForGprs = TRUE;
1536                                                         break;
1537                                                 case 0x40:
1538                                                         p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForHighSpeedCsd = TRUE;
1539                                                         break;
1540                                                 case 0x20:
1541                                                         p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForVoiceGroupCall = TRUE;
1542                                                         break;
1543                                                 case 0x10:
1544                                                         p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForVoiceBroadcastService = TRUE;
1545                                                         break;
1546                                                 case 0x08:
1547                                                         p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForMultipleSubscriberProfile = TRUE;
1548                                                         break;
1549                                                 case 0x04:
1550                                                         p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForMultipleBand = TRUE;
1551                                                         break;
1552                                                 default:
1553                                                         break;
1554                                         }
1555                                         mask = mask >> 1;
1556                                 }
1557                                 break;
1558
1559                         case 0xC0:
1560                                 for (k = 0; k < 8; k++) {
1561                                         switch (byteSignificance & mask) {
1562                                                 case 0x80:
1563                                                         p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForManualSelection = TRUE;
1564                                                         break;
1565                                                 case 0x40:
1566                                                         p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForVoiceMail = TRUE;
1567                                                         break;
1568                                                 case 0x20:
1569                                                         p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForMoSmsAndPaging = TRUE;
1570                                                         break;
1571                                                 case 0x10:
1572                                                         p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForMoSmsWithEmialType = TRUE;
1573                                                         break;
1574                                                 case 0x08:
1575                                                         p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForFaxCalls = TRUE;
1576                                                         break;
1577                                                 case 0x04:
1578                                                         p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForDataCalls = TRUE;
1579                                                         break;
1580                                                 case 0x01:
1581                                                         p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForChangeLanguage = TRUE;
1582                                                         break;
1583                                                 default:
1584                                                         break;
1585                                         }
1586                                         mask = mask >> 1;
1587                                 }
1588                                 break;
1589
1590                         case 0xD5:
1591                                 for (k = 0; k < 8; k++) {
1592                                         switch (byteSignificance & mask) {
1593                                                 case 0x80:
1594                                                 case 0x40:
1595                                                 case 0x20:
1596                                                 case 0x10:
1597                                                 case 0x08:
1598                                                 case 0x04:
1599                                                 case 0x02:
1600                                                 case 0x01:
1601                                                         p_csp->ServiceProfileEntry[j].u.InformationNumbers.bInformationNumbers = TRUE;
1602                                                         break;
1603                                                 default:
1604                                                         break;
1605                                         }
1606                                         mask = mask >> 1;
1607                                 }
1608                                 break;
1609
1610                         default:
1611                                 break;
1612                 }
1613         }
1614         return TRUE;
1615 }
1616
1617 gboolean tcore_sim_encode_csp(unsigned char *p_out, int out_length, struct tel_sim_cphs_csp *p_csp)
1618 {
1619         unsigned char i, j = 0;
1620
1621         if (out_length == 0)
1622                 return FALSE;
1623
1624         memset((void*) p_out, 0xFF, out_length);
1625
1626 /* current telephony supports 22 byte cphs-csp data. 18 byte is mandatory, the other is optional.*/
1627         for (i = 0, j = 0; i < 22 || j < 22; i++, j++) {
1628                 p_out[i] = (unsigned char) p_csp->ServiceProfileEntry[j].CustomerServiceGroup;
1629                 switch (p_out[i]) {
1630                         case 0x01:
1631                                 p_out[++i] =    (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallOffering.bCallForwardingUnconditional) << 7)
1632                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallOffering.bCallForwardingOnUserBusy) << 6)
1633                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallOffering.bCallForwardingOnNoReply) << 5)
1634                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallOffering.bCallForwardingOnUserNotReachable) << 4)
1635                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallOffering.bCallTransfer) << 3);
1636                                 break;
1637
1638                         case 0x02:
1639                                 p_out[++i] =    (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallRestriction.bBarringOfAllOutgoingCalls) << 7)
1640                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallRestriction.bBarringOfOutgoingInternationalCalls) << 6)
1641                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallRestriction.bBarringOfOutgoingInternationalCallsExceptHplmn) << 5)
1642                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallRestriction.bBarringOfAllIncomingCallsRoamingOutsideHplmn) << 4)
1643                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallRestriction.bBarringOfIncomingCallsWhenRoaming) << 3);
1644                                 break;
1645
1646                         case 0x03:
1647                                 p_out[++i] =    (((unsigned char) p_csp->ServiceProfileEntry[j].u.OtherSuppServices.bMultiPartyService) << 7)
1648                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.OtherSuppServices.bClosedUserGroup) << 6)
1649                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.OtherSuppServices.bAdviceOfCharge) << 5)
1650                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.OtherSuppServices.bPreferentialClosedUserGroup) << 4)
1651                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.OtherSuppServices.bClosedUserGroupOutgoingAccess) << 3);
1652                                 break;
1653
1654                         case 0x04:
1655                                 p_out[++i] = (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallComplete.bCallHold) << 7)
1656                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallComplete.bCallWaiting) << 6)
1657                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallComplete.bCompletionOfCallToBusySubscriber) << 5)
1658                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.CallComplete.bUserUserSignalling) << 4);
1659                                 break;
1660
1661                         case 0x05:
1662                                 p_out[++i] = (((unsigned char) p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageMobileTerminated) << 7)
1663                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageMobileOriginated) << 6)
1664                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageCellBroadcast) << 5)
1665                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageReplyPath) << 4)
1666                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageDeliveryConf) << 3)
1667                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageProtocolIdentifier) << 2)
1668                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.Teleservices.bShortMessageValidityPeriod) << 1);
1669                                 break;
1670
1671                         case 0x06:
1672                                 p_out[++i] = (((unsigned char) p_csp->ServiceProfileEntry[j].u.CphsTeleservices.bAlternativeLineService) << 7);
1673                                 break;
1674
1675                         case 0x07:
1676                                 p_out[++i] = (((unsigned char) p_csp->ServiceProfileEntry[j].u.CphsFeatures.bStringServiceTable) << 7);
1677                                 break;
1678
1679                         case 0x08:
1680                                 p_out[++i] = (((unsigned char) p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bCallingLineIdentificationPresent) << 7)
1681                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bConnectedLineIdentificationRestrict) << 5)
1682                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bConnectedLineIdentificationPresent) << 4)
1683                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bMaliciousCallIdentifier) << 3)
1684                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bCallingLineIdentificationSend) << 1)
1685                                                                 + ((unsigned char) p_csp->ServiceProfileEntry[j].u.NumberIdentifiers.bCallingLineIdentificationBlock);
1686                                 break;
1687
1688                         case 0x09:
1689                                 p_out[++i] =    (((unsigned char) p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForGprs) << 7)
1690                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForHighSpeedCsd) << 6)
1691                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForVoiceGroupCall) << 5)
1692                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForVoiceBroadcastService) << 4)
1693                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForMultipleSubscriberProfile) << 3)
1694                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.PhaseServices.bMenuForMultipleBand) << 2);
1695                                 break;
1696
1697                         case 0xC0:
1698                                 p_out[++i] =    (((unsigned char) p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForManualSelection) << 7)
1699                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForVoiceMail) << 6)
1700                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForMoSmsAndPaging) << 5)
1701                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForMoSmsWithEmialType) << 4)
1702                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForFaxCalls) << 3)
1703                                                                 + (((unsigned char) p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForDataCalls) << 2)
1704                                                                 + ((unsigned char) p_csp->ServiceProfileEntry[j].u.ValueAddedServices.bRestrictMenuForChangeLanguage);
1705                                 break;
1706
1707                         case 0xD5:
1708                                 if (p_csp->ServiceProfileEntry[j].u.InformationNumbers.bInformationNumbers)
1709                                         p_out[++i] = 0xFF;
1710                                 else
1711                                         p_out[++i] = 0x00;
1712                                 break;
1713
1714                         default:
1715                                 break;
1716                 }
1717         }
1718         return TRUE;
1719 }
1720
1721 gboolean tcore_sim_decode_vmwf(struct tel_sim_cphs_mw *p_vmwf,  unsigned char* p_in, unsigned long in_length)
1722 {
1723         int i, j = 0;
1724         unsigned char* pTemp = (unsigned char*) p_vmwf;
1725         unsigned char mask = 0x0F;
1726         unsigned char voiceMsgFlg = 0;
1727
1728         if (in_length == 0)
1729                 return FALSE;
1730
1731 /*      current telephony supports 2 byte cphs-vmwf data*/
1732         for (i = 0; i < SIM_CPHS_VMWF_LEN_MAX; i++) {
1733                 voiceMsgFlg = p_in[i];
1734                 for (j = 0; j < 2; j++) {
1735                         if ((voiceMsgFlg & mask) == 0x0A) {
1736                                 *pTemp = 1;  //TRUE
1737                         } else if ((voiceMsgFlg & mask) == 0x05) {
1738                                 *pTemp = 0;  // FALSE
1739                         }
1740                         pTemp += sizeof(gboolean);
1741                         voiceMsgFlg = voiceMsgFlg >> 4;
1742                 }
1743         }
1744         return TRUE;
1745 }
1746
1747 gboolean tcore_sim_decode_mwis(struct tel_sim_mw *pMwis, unsigned char *p_in, int in_length)
1748 {
1749         int i;
1750         unsigned char type = 0;
1751         unsigned char mask = 0x01;
1752
1753         if (in_length == 0)
1754                 return FALSE;
1755
1756         memset((void*) pMwis, 0, sizeof(struct tel_sim_mw));
1757
1758         type = p_in[0];  //0x07
1759
1760         if (type) {
1761                 for (i = 0; i < 5; i++) {
1762                         switch (type & mask) {
1763                                 case 0x01:
1764                                         pMwis->IndicatorType = pMwis->IndicatorType | SIM_MWIS_VOICE;
1765                                         break;
1766                                 case 0x02:
1767                                         pMwis->IndicatorType = pMwis->IndicatorType | SIM_MWIS_FAX;
1768                                         break;
1769                                 case 0x04:
1770                                         pMwis->IndicatorType = pMwis->IndicatorType | SIM_MWIS_EMAIL;
1771                                         break;
1772                                 case 0x08:
1773                                         pMwis->IndicatorType = pMwis->IndicatorType | SIM_MWIS_OTHER;
1774                                         break;
1775                                 case 0x10:
1776                                         pMwis->IndicatorType = pMwis->IndicatorType | SIM_MWIS_VIDEO;
1777                                         break;
1778                                 default:
1779                                         pMwis->IndicatorType = pMwis->IndicatorType | SIM_MWIS_NONE;
1780                                         break;
1781                         }
1782                         mask = mask << 1;
1783                 }
1784
1785                 pMwis->voice_count = p_in[1];
1786                 pMwis->fax_count = p_in[2];
1787                 pMwis->email_count = p_in[3];
1788                 pMwis->other_count = p_in[4];
1789
1790                 if (in_length == 6)
1791                         pMwis->video_count = p_in[5];
1792         }
1793         return TRUE;
1794 }
1795
1796 gboolean tcore_sim_encode_mwis( char *p_out, int out_length, struct tel_sim_mw *pMwis)
1797 {
1798         if (out_length == 0)
1799                 return FALSE;
1800
1801         memset((void*) p_out, 0xFF, out_length);
1802         p_out[0] = 0x00;
1803
1804         p_out[0] = (unsigned char) pMwis->IndicatorType;
1805         p_out[1] = pMwis->voice_count;
1806         p_out[2] = pMwis->fax_count;
1807         p_out[3] = pMwis->email_count;
1808         p_out[4] = pMwis->other_count;
1809
1810         if (out_length == 6)
1811                 p_out[5] = pMwis->video_count;
1812
1813         return TRUE;
1814 }
1815
1816 gboolean tcore_sim_encode_vmwf(char *p_out, int out_length, struct tel_sim_cphs_mw *p_vmwf)
1817 {
1818         int i, j = 0;
1819         unsigned char* pTemp = (unsigned char*) p_vmwf;
1820         unsigned char present = 0x0A;
1821         unsigned char absent = 0x05;
1822
1823         if (out_length == 0)
1824                 return FALSE;
1825
1826         for (i = 0; i < 2; i++) {
1827                 present = 0x0A;
1828                 absent = 0x05;
1829
1830                 p_out[i] = 0x00;
1831
1832                 for (j = 0; j < 2; j++) {
1833                         if (*pTemp)
1834                                 p_out[i] = p_out[i] | present;  //TRUE
1835                         else
1836                                 p_out[i] = p_out[i] | absent;  //TRUE
1837
1838                         pTemp += sizeof(gboolean);
1839                         present = present << 4;
1840                         absent = absent << 4;
1841                 }
1842         }
1843         return TRUE;
1844 }
1845
1846 gboolean tcore_sim_decode_ons(unsigned char* p_out,unsigned  char* p_in, int in_length)
1847 {
1848         int length;
1849         memset((void*) p_out, 0, SIM_CPHS_OPERATOR_NAME_LEN_MAX+1);
1850
1851         if (in_length == 0)
1852                 return FALSE;
1853
1854         if (_is_empty(p_in, in_length) == TRUE) {
1855                 return FALSE;
1856         }
1857
1858         /* current telephony supports 25 byte cphs-operator name string.*/
1859         if (in_length >= SIM_CPHS_OPERATOR_NAME_LEN_MAX)
1860                 in_length = SIM_CPHS_OPERATOR_NAME_LEN_MAX;
1861
1862         length = _get_string(p_out, p_in, in_length);
1863         p_out[length] = '\0';
1864         dbg( "Operator Name is (%s) & Length (%d) ",    p_out, length);
1865
1866         return TRUE;
1867 }
1868
1869 gboolean tcore_sim_decode_cfis(struct tel_sim_callforwarding *cfis, unsigned char *p_in, int in_length)
1870 {
1871         int bcd_byte;   // dialing number max length
1872         int i = 0;
1873         struct tel_sim_cfis p_cfis = {0,};
1874
1875         if (in_length == 0)
1876                 return FALSE;
1877
1878         if (_is_empty(p_in, in_length) == TRUE) {
1879                 dbg("empty record. all data is set 0xff");
1880                 return TRUE;    // this is empty record
1881         }
1882
1883         p_cfis.MspNumber = p_in[i++];
1884         p_cfis.Status = p_in[i++];
1885
1886         // get TON and NPI
1887         p_cfis.TypeOfNumber = (p_in[++i] >> 4) & 0x07;
1888         p_cfis.NumberingPlanIdent = p_in[i++] & 0x0F;
1889
1890         // get actual dialing number length
1891         /* current telephony supports 20 byte dialing number format. */
1892         bcd_byte = _get_valid_bcd_byte(&p_in[i], SIM_XDN_NUMBER_LEN_MAX / 2);
1893
1894         // get dialing number/SSC string
1895         p_cfis.DiallingnumLen = _bcd_to_digit((char*) p_cfis.DiallingNum, (char*) &p_in[i], bcd_byte); // actual dialing number length in BCD.
1896         dbg( "Dialing number Length %d \n", p_cfis.DiallingnumLen);
1897
1898         i = i + SIM_XDN_NUMBER_LEN_MAX / 2;
1899
1900         // get Capability/Configuration id
1901         //      p_cfis.CapaConfig2Id = p_in[i++];
1902
1903         // get Extension1 id
1904         //      p_cfis.Ext7RecordId = p_in[i];
1905
1906         dbg( "MspNumber 0x%x", p_cfis.MspNumber);
1907         dbg( "Status 0x%x", p_cfis.Status);
1908         dbg( "DiallingnumLen %d", p_cfis.DiallingnumLen);
1909         dbg( "TypeOfNumber %d", p_cfis.TypeOfNumber);
1910         dbg( "NumberingPlanIdent %d", p_cfis.NumberingPlanIdent);
1911         dbg( "Dialing number[%s]", p_cfis.DiallingNum);
1912
1913         if(p_cfis.Status & 0x01)
1914                 cfis->voice1 = TRUE;
1915         if(p_cfis.Status & 0x02)
1916                 cfis->fax = TRUE;
1917         if(p_cfis.Status & 0x04)
1918                 cfis->data = TRUE;
1919         if(p_cfis.Status & 0x08)
1920                 cfis->sms = TRUE;
1921         if(p_cfis.Status & 0x0a)
1922                 cfis->allbearer = TRUE;
1923         return TRUE;
1924 }
1925
1926 char* tcore_sim_encode_cfis(int *out_length, const struct tel_sim_callforwarding *p_cfis)
1927 {
1928         char *encoded_o = NULL;
1929         encoded_o = calloc(16, 1); // EF-CFIS record length is 16
1930
1931         /*
1932          Bytes  Description                                                     M/O             Length
1933          1              MSP number                                                      M               1 byte
1934          2              CFU indicator status                                    M               1 byte
1935          3              Length of BCD number                                    M               1 byte
1936          4              TON and NPI                                                     M               1 byte
1937          5 to 14        Dialing Number                                          M               10 bytes
1938          15             Capability/Configuration2 Record Identifier     M               1 byte
1939          16             Extension 7 Record Identifier                           M               1 byte
1940          */
1941         encoded_o[0] = 0x01; //default profile
1942
1943         if(p_cfis->voice1 )
1944                 encoded_o[1] = encoded_o[1] | 0x01;
1945         if(p_cfis->fax )
1946                 encoded_o[1] = encoded_o[1] | 0x02;
1947         if(p_cfis->data )
1948                 encoded_o[1] = encoded_o[1] | 0x04;
1949         if(p_cfis->sms )
1950                 encoded_o[1] = encoded_o[1] | 0x08;
1951         if(p_cfis->allbearer )
1952                 encoded_o[1] = encoded_o[1] | 0x0a;
1953
1954         memset(&encoded_o[2], 0xff, 14);
1955
1956         *out_length = 16;
1957         return encoded_o;
1958 }
1959
1960 gboolean tcore_sim_decode_dynamic_flag(struct tel_sim_cphs_dflag *p_df, unsigned char *p_in, int in_length)
1961 {
1962         if (in_length == 0)
1963                 return FALSE;
1964
1965         memset((void*) p_df, 0, sizeof(struct tel_sim_cphs_dflag));
1966
1967         switch (p_in[0] & 0x01) {
1968                 case 0x00:
1969                         p_df->DynamicFlags = SIM_DYNAMIC_FLAGS_LINE2;
1970                         break;
1971
1972                 case 0x01:
1973                         p_df->DynamicFlags = SIM_DYNAMIC_FLAGS_LINE1;
1974                         break;
1975
1976                 default:
1977                         break;
1978         }
1979         return TRUE;
1980 }
1981
1982 gboolean tcore_sim_decode_dynamic2_flag(struct tel_sim_cphs_dflag2 *p_d2f, unsigned char *p_in, int in_length)
1983 {
1984         if (in_length == 0)
1985                 return FALSE;
1986
1987         memset((void*) p_d2f, 0, sizeof(struct tel_sim_cphs_dflag2));
1988
1989         switch (p_in[0] & 0x01) {
1990                 case 0x00:
1991                         p_d2f->Dynamic2Flag = SIM_PIN2_ACCESSIBLE_FLAGS_UNLOCKED;
1992                         break;
1993                 case 0x01:
1994                         p_d2f->Dynamic2Flag = SIM_PIN2_ACCESSIBLE_FLAGS_LOCKED;
1995                         break;
1996                 default:
1997                         break;
1998         }
1999         return TRUE;
2000 }
2001
2002 gboolean tcore_sim_encode_dynamic_flag(char *p_out, int out_length, struct tel_sim_cphs_dflag *p_df)
2003 {
2004         if (out_length == 0 || out_length > 1)
2005                 return FALSE;
2006
2007         memset((void*) p_out, 0xFF, out_length);
2008         p_out[0] = p_df->DynamicFlags;
2009         return TRUE;
2010 }
2011
2012 gboolean tcore_sim_encode_dynamic2_flag(char *p_out, int out_length, struct tel_sim_cphs_dflag2 *p_d2f)
2013 {
2014         if (out_length == 0 || out_length > 1)
2015                 return FALSE;
2016
2017         memset((void*) p_out, 0xFF, out_length);
2018         p_out[0] = p_d2f->Dynamic2Flag;
2019         return TRUE;
2020 }
2021
2022 gboolean tcore_sim_decode_cphs_info(struct tel_sim_cphs_info *pCphsInfo, unsigned char *p_in, int in_length)
2023 {
2024         int i, j = 0;
2025         unsigned char mask = 0x03;
2026         unsigned char* pTemp = (unsigned char*) &pCphsInfo->CphsServiceTable;
2027
2028         memset((void*) pCphsInfo, 0, sizeof(struct tel_sim_cphs_info));
2029
2030         if (in_length == 0)
2031                 return FALSE;
2032
2033          /*CPHS info EF has 3 bytes data.*/
2034         if (in_length >= SIM_CPHS_INFO_LEN_MAX)
2035                 in_length = SIM_CPHS_INFO_LEN_MAX;
2036
2037         switch (p_in[0]) {
2038                 case 0x01:
2039                         pCphsInfo->CphsPhase = SIM_CPHS_PHASE1;
2040                         break;
2041                 case 0x02:
2042                         pCphsInfo->CphsPhase = SIM_CPHS_PHASE2;
2043                         break;
2044                 default:
2045                         pCphsInfo->CphsPhase = SIM_CPHS_PHASE_RFU;
2046                         break;
2047         }
2048
2049         dbg( "Cphs Phase %d \n", pCphsInfo->CphsPhase);
2050
2051         for (i = 1; i < in_length; i++) { //CPHS SST is only 2 bytes
2052                 mask = 0x03;    // reset mast to check first bit
2053                 for (j = 0; j < 4; j++) {
2054                         if (p_in[i] & mask) {
2055                                 *pTemp = 1;
2056                         }
2057                         dbg( "Byte (%d), service (%d) ", i+1, *pTemp);
2058                         pTemp += sizeof(gboolean);
2059                         mask = mask << 2;
2060                 }
2061         }
2062         return TRUE;
2063 }
2064
2065 gboolean tcore_sim_decode_short_ons(unsigned char *p_out, unsigned char *p_in, int in_length)
2066 {
2067         int length;
2068
2069         memset(p_out, 0x00, SIM_CPHS_OPERATOR_NAME_SHORT_FORM_LEN_MAX+1);
2070
2071         if (_is_empty(p_in, in_length) == TRUE){
2072                 return FALSE;   // this is empty record
2073         }
2074
2075         /*CPHS specification shows current EF include 10 bytes */
2076         if (in_length == 0)
2077                 return FALSE;
2078
2079         if(in_length > SIM_CPHS_OPERATOR_NAME_SHORT_FORM_LEN_MAX)
2080                 in_length = SIM_CPHS_OPERATOR_NAME_SHORT_FORM_LEN_MAX;
2081
2082         length = _get_string( p_out, p_in, in_length );
2083         p_out[length] = '\0';
2084         dbg( "Operator short Name is (%s) &  length (%d)", p_out, length);
2085         return TRUE;
2086 }
2087
2088 gboolean tcore_sim_decode_information_number(struct tel_sim_cphs_info_number *p_info, unsigned char* p_in, int in_length)
2089 {
2090         int i;
2091
2092         if (in_length == 0)
2093                 return FALSE;
2094
2095         for (i = 0; i < in_length; i++) {
2096                 dbg( " \t0x%04X.", p_in[i]);
2097         }
2098
2099         if (_is_empty(p_in, in_length) == TRUE) {
2100                 return FALSE;   // this is empty record
2101         }
2102
2103         p_info->AlphaIdLength = p_in[0];
2104
2105         if (p_in[1] & 0x0F)
2106                 p_info->IndexLevelIndicator =   (enum tel_sim_cphs_index_level) (p_in[1] & 0x0F);
2107
2108         if (p_in[1] & 0x10)
2109                 p_info->PremiumServiceIndicator = TRUE;
2110
2111         if (p_in[1] & 0x20)
2112                 p_info->PremiumServiceIndicator = TRUE;
2113
2114         _get_string(p_info->Alpha_id, &p_in[2], p_info->AlphaIdLength);
2115
2116         p_info->DiallingnumLength = p_in[2 + p_info->AlphaIdLength] * 2;
2117         p_info->TypeOfNumber = (p_in[3 + p_info->AlphaIdLength] >> 4) & 0x07;
2118         p_info->NumberingPlanIdentity = p_in[3 + p_info->AlphaIdLength] & 0x0F;
2119
2120         // get dialing number/SSC string
2121         _bcd_to_digit((char*) p_info->DiallingnumLength, (char*) &p_in[4 + p_info->AlphaIdLength],      p_info->DiallingnumLength / 2); // actual dialing number length in BCD.
2122         // get Extension1 id
2123         p_info->Ext1RecordId = p_in[4 + p_info->AlphaIdLength + p_info->DiallingnumLength / 2];
2124
2125         return TRUE;
2126 }
2127
2128 gboolean tcore_sim_decode_opl(struct tel_sim_opl *p_opl, unsigned char *p_in, int in_length)
2129 {
2130         unsigned char packetInDigit[3 * 2 + 1];
2131
2132         if (_is_empty(p_in, in_length) == TRUE) {
2133                 memset(p_opl, 0x00, sizeof(struct tel_sim_opl));
2134                 return FALSE;   // this is empty record
2135         }
2136         _bcd_to_digit((char*) packetInDigit, (char*) &p_in[0], 3);
2137         dbg( "AFTER _bcd_to_digit 4th[0x%x]", packetInDigit[3]);
2138
2139         // get MCC
2140         memcpy(&p_opl->plmn, &(packetInDigit[0]), 3);
2141         // get MNC
2142         if (packetInDigit[3] == 0x00){
2143                 memcpy(&(p_opl->plmn[3]), &(packetInDigit[3 + 1]), 2);
2144                 p_opl->plmn[5] = '\0';
2145         } else{
2146                 memcpy(&(p_opl->plmn[3]), &(packetInDigit[3]), 3);
2147                 p_opl->plmn[6] = '\0';
2148         }
2149
2150         dbg( " PLMN Code[%s]", p_opl->plmn);
2151         p_opl->lac_from = (*(p_in+3) << 8) | (*(p_in+4) & 0x00ff);
2152         dbg( " Start value of the LAC range[%x]",       p_opl->lac_from);
2153         p_opl->lac_to = (*(p_in+5) << 8) | (*(p_in+6) & 0x00ff);
2154         dbg( " End value of the LAC range[%x]", p_opl->lac_to);
2155         p_opl->rec_identifier = p_in[7];
2156         dbg( " PNN Record identifier[%x]", p_opl->rec_identifier);
2157         return TRUE;
2158 }
2159
2160 gboolean tcore_sim_decode_pnn(struct tel_sim_pnn *p_pnn, unsigned char* p_in, int in_length)
2161 {
2162         int f_name_len = 0, s_name_len = 0;
2163         int cvt_leng = 0, s_name_base = 0;
2164
2165         if (_is_empty(p_in, in_length) == TRUE) {
2166                 memset(p_pnn, 0x00, sizeof(struct tel_sim_pnn));
2167                 return FALSE;   // this is empty record
2168         }
2169
2170         /*Full name for network IEI(Information Element Identifier),0x43*/
2171         if (p_in[0] == 0x43) {
2172                 dbg( " Full name of network IEI exist");
2173                 //f_name_part includes information byte.
2174                 f_name_len =  (int)p_in[1] - 1;
2175
2176                 /* 3rd byte information element(according to TS 24.008 for Network Name)
2177                  8 :ext1
2178                  7 6 5 : coding scheme
2179                  4 : Add CI
2180                  3 2 1 : number of spare bits in last octet
2181
2182                  Coding Scheme (octet 3, bits 5-7)
2183                  0      0       0               Cell Broadcast data coding scheme, GSM default alphabet, language unspecified, defined in 3GPP TS 23.038 [8b]
2184                  0      0       1               UCS2 (16 bit) [72]
2185                  0      1       0               to      reserved
2186                  1      1       1               to      reserved
2187                  */
2188                 if ((p_in[2] & 0x01110000) >> 4 == 0) {
2189                         dbg( "DCS:GSM7");
2190                         // In case of GSM7, 35byte packing data will be converted 40 bytes unpacking string.
2191                         if (f_name_len > (SIM_NW_FULL_NAME_LEN_MAX * 7) / 8)
2192                                 f_name_len = (SIM_NW_FULL_NAME_LEN_MAX * 7) / 8;
2193
2194                         _unpack_7bit28bit(p_in + 3, f_name_len, (unsigned char *) (p_pnn->full_name));
2195                 } else if ((p_in[2] & 0x01110000) >> 4 == 1) {
2196                         dbg( "DCS:UCS2");
2197                         /* current telephony supports 40 bytes network name string */
2198                         if (f_name_len > SIM_NW_FULL_NAME_LEN_MAX)
2199                                 f_name_len = SIM_NW_FULL_NAME_LEN_MAX;
2200
2201                         _ucs2_to_utf8(f_name_len, p_in + 3, (int*) &cvt_leng, (unsigned char *) (p_pnn->full_name));
2202                 } else {
2203                         dbg( "DCS:unknown");
2204                         return FALSE;
2205                 }
2206                 dbg( " Full name of network contents[%s]", p_pnn->full_name);
2207
2208                 s_name_base = (int)p_in[1] +2;
2209                 dbg( " short name base byte [0x%02x]", s_name_base);
2210
2211                 /*Short Name for network IEI(Information Element Identifier), 0x45*/
2212                 if (p_in[s_name_base] == 0x45) {
2213                         dbg( " Short name of network IEI exist");
2214                         //s_name_part includes information byte.
2215                         s_name_len = p_in[s_name_base +1] -1;
2216
2217                         if ((p_in[s_name_base + 2] & 0x01110000) >> 4 == 0) {
2218                                 dbg( "DCS:GSM7");
2219                                 // In case of GSM7, 35byte packing data will be converted 40 bytes unpacking string.
2220                                 if (s_name_len > (SIM_NW_FULL_NAME_LEN_MAX * 7) / 8)
2221                                         s_name_len = (SIM_NW_FULL_NAME_LEN_MAX * 7) / 8;
2222
2223                                 _unpack_7bit28bit(p_in + s_name_base + 3, s_name_len, (unsigned char *) (p_pnn->short_name));
2224                         } else if ((p_in[s_name_base +2] & 0x01110000) >> 4 == 1) {
2225                                 dbg( "DCS:UCS2");
2226                                 if (s_name_len > SIM_NW_FULL_NAME_LEN_MAX)
2227                                         s_name_len = SIM_NW_FULL_NAME_LEN_MAX;
2228
2229                                 _ucs2_to_utf8(s_name_len, p_in + s_name_base+ 3, (int*) &cvt_leng, (unsigned char *) (p_pnn->short_name));
2230                         } else {
2231                                 dbg( "DCS:unknown");
2232                                 return FALSE;
2233                         }
2234                         dbg( " Short name of network contents[%s]", p_pnn->short_name);
2235                 }
2236                 return TRUE;
2237         }
2238         return FALSE;
2239 }
2240
2241 gboolean tcore_sim_decode_oplmnwact(struct tel_sim_oplmnwact_list *p_list, unsigned char *p_in, int in_length)
2242 {
2243         unsigned long m = 0;
2244 //unsigned long k, j, m = 0;
2245 //      unsigned char mask = 0x00;
2246
2247         //current raw data can include invalid OPLMN data(ex: ff ff ff 00 00). so we can`t decide the number of OPLMN records directly.
2248         int rawOplmnWactCount = 0;
2249         int i = 0;
2250
2251         memset((void*) p_list, 0, sizeof(struct tel_sim_oplmnwact_list));
2252
2253         rawOplmnWactCount = in_length / 5;
2254
2255         dbg( "rawOplmnWactCount[%d]", rawOplmnWactCount);
2256
2257         for (i = 0; i < rawOplmnWactCount; i++) {
2258                 unsigned char packetInDigit[3 * 2 + 1];
2259
2260                 //Regarding current IPC data, even if there`s no OPLMN value, IPC data is sending with 'ff ff ff 00 00'. so we should check for validation.
2261                 if (p_in[m] == 0xff) {
2262                         p_list->opwa_count = m / 5;
2263                         dbg("OPLMN(MCC+MNC) value is not found at p_in[m]=[%lu].So OPLMN count is [%d]", m, p_list->opwa_count);
2264                         return TRUE;
2265                 }
2266
2267                 _bcd_to_digit((char*) packetInDigit, (char*) &p_in[m], 3);
2268                 dbg( "AFTER _bcd_to_digit 4th[0x%x]", packetInDigit[3]);
2269
2270                 // get MCC
2271                 memcpy(&p_list->opwa[i].plmn, &(packetInDigit[0]), 3);
2272                 // get MNC
2273                 if (packetInDigit[3] == 0x00){
2274                         memcpy(&(p_list->opwa[i].plmn[3]), &(packetInDigit[3 + 1]), 2);
2275                         p_list->opwa[i].plmn[5] = '\0';
2276                 } else{
2277                         memcpy(&(p_list->opwa[i].plmn[3]), &(packetInDigit[3]), 3);
2278                         p_list->opwa[i].plmn[6] = '\0';
2279                 }
2280                 dbg( "[%d] OPLMN PLMN Code[%s]", i, p_list->opwa[i].plmn);
2281
2282                 if(p_in[m+3] & 0x80)
2283                         p_list->opwa[i].b_umts = 1;
2284
2285                 if(p_in[m+4] & 0x80)
2286                         p_list->opwa[i].b_gsm = 1;
2287
2288                 m = m + 5;
2289         }
2290
2291         p_list->opwa_count = rawOplmnWactCount;
2292         dbg( "OPLMN count is p_list->opwa_count[%d]", p_list->opwa_count);
2293
2294         return TRUE;
2295 }
2296
2297 enum tel_sim_status tcore_sim_get_status(CoreObject *o)
2298 {
2299         struct private_object_data *po = NULL;
2300         po = tcore_object_ref_object(o);
2301         if (!po) {
2302                 dbg("po access fail");
2303                 return -1;
2304         }
2305         return po->sim_status;
2306 }
2307
2308 gboolean tcore_sim_set_status(CoreObject *o, enum tel_sim_status status)
2309 {
2310         struct private_object_data *po = NULL;
2311         po = tcore_object_ref_object(o);
2312         if (!po) {
2313                 dbg("po access fail");
2314                 return FALSE;
2315         }
2316         po->sim_status = status;
2317
2318         return TRUE;
2319 }
2320
2321 gboolean tcore_sim_get_identification(CoreObject *o)
2322 {
2323         struct private_object_data *po = NULL;
2324         po = tcore_object_ref_object(o);
2325         if (!po) {
2326                 dbg("po access fail");
2327                 return -1;
2328         }
2329         return po->b_sim_changed;
2330 }
2331
2332 gboolean tcore_sim_set_identification(CoreObject *o, gboolean b_changed)
2333 {
2334         struct private_object_data *po = NULL;
2335         po = tcore_object_ref_object(o);
2336         if (!po) {
2337                 dbg("po access fail");
2338                 return FALSE;
2339         }
2340         po->b_sim_changed = b_changed;
2341
2342         return TRUE;
2343 }
2344
2345 enum tel_sim_type tcore_sim_get_type(CoreObject *o)
2346 {
2347         struct private_object_data *po = NULL;
2348         po = tcore_object_ref_object(o);
2349         if (!po) {
2350                 dbg("po access fail");
2351                 return -1;
2352         }
2353         return po->type;
2354 }
2355
2356 gboolean tcore_sim_set_type(CoreObject *o, enum tel_sim_type type)
2357 {
2358         struct private_object_data *po = NULL;
2359         po = tcore_object_ref_object(o);
2360         if (!po) {
2361                 dbg("po access fail");
2362                 return FALSE;
2363         }
2364         po->type = type;
2365         return TRUE;
2366 }
2367
2368 struct tel_sim_imsi* tcore_sim_get_imsi(CoreObject *o)
2369 {
2370         struct tel_sim_imsi *tmp_imsi;
2371         struct private_object_data *po = NULL;
2372         po = tcore_object_ref_object(o);
2373         if (!po) {
2374                 dbg("po access fail");
2375                 return NULL;
2376         }
2377         tmp_imsi =  calloc(sizeof(struct tel_sim_imsi), 1);
2378         memcpy(tmp_imsi, &po->imsi, sizeof(struct tel_sim_imsi));
2379         return tmp_imsi;
2380 }
2381
2382 gboolean tcore_sim_set_imsi(CoreObject *o, struct tel_sim_imsi *imsi)
2383 {
2384         struct private_object_data *po = NULL;
2385         po = tcore_object_ref_object(o);
2386         if (!po) {
2387                 dbg("po access fail");
2388                 return FALSE;
2389         }
2390         memcpy(&po->imsi, imsi, sizeof(struct tel_sim_imsi));
2391         return TRUE;
2392 }
2393
2394 gboolean tcore_sim_get_cphs_status(CoreObject *o){
2395         struct private_object_data *po = NULL;
2396         po = tcore_object_ref_object(o);
2397         if (!po) {
2398                 dbg("po access fail");
2399                 return FALSE;
2400         }
2401         return po->b_cphs;
2402 }
2403
2404 gboolean tcore_sim_set_cphs_status(CoreObject *o, gboolean b_support){
2405         struct private_object_data *po = NULL;
2406         po = tcore_object_ref_object(o);
2407         if (!po) {
2408                 dbg("po access fail");
2409                 return FALSE;
2410         }
2411         po->b_cphs = b_support;
2412         return TRUE;
2413 }
2414
2415 gboolean tcore_sim_link_userdata(CoreObject *o, void *userdata)
2416 {
2417         struct private_object_data *po = NULL;
2418         po = tcore_object_ref_object(o);
2419         if (!po) {
2420                 dbg("po access fail");
2421                 return FALSE;
2422         }
2423         po->userdata = userdata;
2424         return TRUE;
2425 }
2426
2427 void* tcore_sim_ref_userdata(CoreObject *o)
2428 {
2429         struct private_object_data *po = NULL;
2430         po = tcore_object_ref_object(o);
2431         if (!po || !po->userdata) {
2432                 dbg("po access fail");
2433                 return NULL;
2434         }
2435         return po->userdata;
2436 }
2437
2438 static void tcore_sim_initialize_context(CoreObject *o)
2439 {
2440         struct tcore_sim_operations *tmp_ops = NULL;
2441         struct private_object_data *po = NULL;
2442         po = tcore_object_ref_object(o);
2443         if (!po) {
2444                 dbg("po access fail");
2445                 return;
2446         }
2447
2448         tmp_ops = po->ops;
2449
2450 /*      if(!po->p_cache)
2451                 free(po->p_cache);*/
2452
2453         memset(po, 0x00, sizeof(struct private_object_data));
2454
2455         po->ops = tmp_ops;
2456
2457         po->sim_status = SIM_STATUS_UNKNOWN;
2458         po->language_file = SIM_EF_INVALID;
2459         po->cf_file = SIM_EF_INVALID;
2460         po->mw_file = SIM_EF_INVALID;
2461         po->mb_file = SIM_EF_INVALID;
2462 }
2463
2464 CoreObject *tcore_sim_new(TcorePlugin *p, const char *name,
2465                 struct tcore_sim_operations *ops, TcoreHal *hal)
2466 {
2467         CoreObject *o = NULL;
2468         struct private_object_data *po = NULL;
2469
2470         if (!p)
2471                 return NULL;
2472
2473         o = tcore_object_new(p, name, hal);
2474         if (!o)
2475                 return NULL;
2476
2477         po = calloc(sizeof(struct private_object_data), 1);
2478         if (!po) {
2479                 tcore_object_free(o);
2480                 return NULL;
2481         }
2482
2483         po->ops = ops;
2484
2485         tcore_object_set_type(o, CORE_OBJECT_TYPE_SIM);
2486         tcore_object_link_object(o, po);
2487         tcore_object_set_free_hook(o, _free_hook);
2488         tcore_object_set_clone_hook(o, _clone_hook);
2489         tcore_object_set_dispatcher(o, _dispatcher);
2490
2491         tcore_sim_initialize_context(o);
2492
2493         return o;
2494 }
2495
2496 void tcore_sim_free(CoreObject *o)
2497 {
2498         struct private_object_data *po = NULL;
2499
2500         CORE_OBJECT_CHECK(o, CORE_OBJECT_TYPE_SIM);
2501
2502         po = tcore_object_ref_object(o);
2503         if (!po)
2504                 return;
2505
2506         free(po);
2507         tcore_object_free(o);
2508 }