Initial refactoring merge
[platform/core/api/sim.git] / src / sim.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <sim.h>
18
19 #include <string.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <dlog.h>
23
24 #include <glib.h>
25 #include <glib-object.h>
26 #include <gio/gio.h>
27
28 #include <tapi.h>
29 #include <tel_sim.h>
30 #include <tapi_sim.h>
31 #include <tapi_events.h>
32
33 #ifdef LOG_TAG
34 #undef LOG_TAG
35 #endif
36 #define LOG_TAG "CAPI_TELEPHONY_SIM"
37
38 typedef struct {
39         sim_state_e previous_state;
40         TelHandle *th;
41         void *cb;
42         void *user_data;
43 } sim_cb_data;
44
45 static TelHandle *handle = NULL;
46 static sim_cb_data *ccb = NULL;
47
48 // Internal Macros
49 #define SIM_CHECK_INPUT_PARAMETER(arg) \
50         if (arg == NULL) { \
51                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, SIM_ERROR_INVALID_PARAMETER); \
52                 return SIM_ERROR_INVALID_PARAMETER; \
53         }
54
55 #define SIM_INIT(th) \
56         th = tapi_init(NULL); \
57         if (!th) { \
58                 LOGE("[%s] OPERATION_FAILED(0x%08x)", __FUNCTION__, SIM_ERROR_OPERATION_FAILED); \
59                 return SIM_ERROR_OPERATION_FAILED; \
60         }
61
62 #define SIM_DEINIT(th) tapi_deinit(th)
63
64 static sim_error_e _convert_access_rt_to_sim_error(TelSimResult access_rt)
65 {
66         sim_error_e error = SIM_ERROR_NONE;
67
68         switch (access_rt) {
69         case TEL_SIM_RESULT_SUCCESS:
70                 error = SIM_ERROR_NONE;
71                 break;
72         case TEL_SIM_RESULT_ACCESS_CONDITION_NOT_SATISFIED:
73         case TEL_SIM_RESULT_CARD_ERROR:
74                 error = SIM_ERROR_NOT_AVAILABLE;
75                 break;
76         case TEL_SIM_RESULT_FAILURE:
77         default:
78                 error = SIM_ERROR_OPERATION_FAILED;
79                 break;
80         }
81
82         return error;
83 }
84
85 static int __sim_check_init_status(TelHandle *handle)
86 {
87         TelSimCardStatusInfo sim_status_info = {0,};
88         int error_code = SIM_ERROR_NONE;
89
90         if (tapi_sim_get_init_info(handle, &sim_status_info) != TEL_RETURN_SUCCESS
91                         || sim_status_info.status != TEL_SIM_STATUS_SIM_INIT_COMPLETED) {
92                 error_code = SIM_ERROR_NOT_AVAILABLE;
93                 LOGE("[%s] NOT_AVAILABLE(0x%08x)", __FUNCTION__, error_code);
94         }
95
96         return error_code;
97 }
98
99 static GVariant *__sim_get_info(const char *method)
100 {
101         GVariant *sync_gv = NULL;
102         char **cp_list = NULL;
103         GDBusConnection *dbus_connection;
104         GError *error = NULL;
105
106         tapi_get_cp_name_list(&cp_list);
107         if (cp_list == NULL) {
108                 LOGE("CP List is NULL");
109                 return NULL;
110         }
111
112         dbus_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
113         if (error) {
114                 LOGE("Error Creating DBus Connection: [%s]", error->message);
115                 g_error_free(error);
116         } else {
117                 sync_gv = g_dbus_connection_call_sync(dbus_connection,
118                                 TELEPHONY_SERVICE, cp_list[0],
119                                 TELEPHONY_SIM_INTERFACE, method,
120                                 NULL, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
121
122                 if (error) {
123                         LOGE("g_dbus_conn failed. error (%s)", error->message);
124                         g_error_free(error);
125                 }
126         }
127
128         /* Free cp_list */
129         g_object_unref(dbus_connection);
130         g_strfreev(cp_list);
131         return sync_gv;
132 }
133
134 int sim_get_icc_id(char **icc_id)
135 {
136         TelHandle *handle = NULL;
137         int error_code;
138         GVariant *sync_gv = NULL;
139
140         SIM_CHECK_INPUT_PARAMETER(icc_id);
141         *icc_id = NULL;
142         SIM_INIT(handle);
143
144         error_code = __sim_check_init_status(handle);
145         if (error_code != SIM_ERROR_NONE) {
146                 LOGE("[%s] SIM NOT Initialized (0x%08x)", __FUNCTION__, error_code);
147                 return error_code;
148         }
149
150         sync_gv = __sim_get_info("GetIccid");
151         if (sync_gv) {
152                 gint result;
153                 gchar *iccid = NULL;
154
155                 g_variant_get(sync_gv, "(is)", &result, &iccid);
156                 if (result == TEL_SIM_RESULT_SUCCESS) {
157                         if (iccid != NULL) {
158                                 *icc_id = g_strdup(iccid);
159                                 g_free(iccid);
160                                 LOGI("ICCID: [%s]", *icc_id);
161                         } else {
162                                 LOGE("ICCID is NULL");
163                         }
164                 } else {
165                         error_code = _convert_access_rt_to_sim_error(result);
166                         LOGE("[%s] Operation Failed!!! (0x%08x)", __FUNCTION__, error_code);
167                 }
168                 g_variant_unref(sync_gv);
169         } else {
170                 error_code = SIM_ERROR_OPERATION_FAILED;
171                 LOGE("[%s] Operation Failed!!! (0x%08x)", __FUNCTION__, error_code);
172         }
173
174         SIM_DEINIT(handle);
175         return error_code;
176 }
177
178 static int __sim_get_imsi(TelHandle *handle, TelSimImsiInfo *sim_imsi_info)
179 {
180         int error_code = SIM_ERROR_NONE;
181
182         error_code = __sim_check_init_status(handle);
183         if (error_code != SIM_ERROR_NONE) {
184                 LOGE("[%s] SIM NOT Initialized (0x%08x)", __FUNCTION__, error_code);
185                 return error_code;
186         }
187
188         error_code = tapi_sim_get_imsi(handle, sim_imsi_info);
189         return error_code;
190 }
191
192 int sim_get_mcc(char **mcc)
193 {
194         TelHandle *handle = NULL;
195         TelSimImsiInfo sim_imsi_info = {"",};
196         int error_code;
197
198         SIM_CHECK_INPUT_PARAMETER(mcc);
199         SIM_INIT(handle);
200
201         error_code = __sim_get_imsi(handle, &sim_imsi_info);
202         if (error_code != TEL_RETURN_SUCCESS) {
203                 LOGE("[%s] OPERATION_FAILED(0x%08x)", __FUNCTION__, error_code);
204                 *mcc = NULL;
205         } else {
206                 *mcc = g_strdup(sim_imsi_info.mcc);
207                 LOGI("MCC: [%s]", *mcc);
208         }
209
210         SIM_DEINIT(handle);
211         return error_code;
212 }
213
214 int sim_get_mnc(char **mnc)
215 {
216         TelHandle *handle = NULL;
217         TelSimImsiInfo sim_imsi_info = {"",};
218         int error_code;
219
220         SIM_CHECK_INPUT_PARAMETER(mnc);
221         SIM_INIT(handle);
222
223         error_code = __sim_get_imsi(handle, &sim_imsi_info);
224         if (error_code != TEL_RETURN_SUCCESS) {
225                 LOGE("[%s] OPERATION_FAILED(0x%08x)", __FUNCTION__, error_code);
226                 *mnc = NULL;
227         } else {
228                 *mnc = g_strdup(sim_imsi_info.mnc);
229                 LOGI("MNC: [%s]", *mnc);
230         }
231
232         SIM_DEINIT(handle);
233         return error_code;
234 }
235
236 int sim_get_msin(char **msin)
237 {
238         TelHandle *handle = NULL;
239         TelSimImsiInfo sim_imsi_info = {"",};
240         int error_code;
241
242         SIM_CHECK_INPUT_PARAMETER(msin);
243         SIM_INIT(handle);
244
245         error_code = __sim_get_imsi(handle, &sim_imsi_info);
246         if (error_code != TEL_RETURN_SUCCESS) {
247                 LOGE("[%s] OPERATION_FAILED(0x%08x)", __FUNCTION__, error_code);
248                 *msin = NULL;
249         } else {
250                 *msin = g_strdup(sim_imsi_info.msin);
251                 LOGI("MSIN: [%s]", *msin);
252         }
253
254         SIM_DEINIT(handle);
255         return error_code;
256 }
257
258 int sim_get_spn(char **spn)
259 {
260         TelHandle *handle = NULL;
261         int error_code;
262         GVariant *sync_gv = NULL;
263
264         SIM_CHECK_INPUT_PARAMETER(spn);
265         *spn = NULL;
266         SIM_INIT(handle);
267
268         error_code = __sim_check_init_status(handle);
269         if (error_code != SIM_ERROR_NONE) {
270                 LOGE("[%s] SIM NOT initialized (0x%08x)", __FUNCTION__, error_code);
271                 return error_code;
272         }
273
274         sync_gv = __sim_get_info("GetSpn");
275         if (sync_gv) {
276                 gint result;
277                 gint display_condition;
278                 gchar *spn_str = NULL;
279
280                 g_variant_get(sync_gv, "(iis)", &result, &display_condition, &spn_str);
281                 if (result == TEL_SIM_RESULT_SUCCESS) {
282                         if (spn_str != NULL) {
283                                 *spn = g_strdup(spn_str);
284                                 g_free(spn_str);
285                                 LOGI("SPN: [%s]", *spn);
286                         } else {
287                                 LOGE("SPN is NULL");
288                         }
289                 } else {
290                         error_code = _convert_access_rt_to_sim_error(result);
291                         LOGE("[%s] Operation Failed!!! (0x%08x)", __FUNCTION__, error_code);
292                 }
293                 g_variant_unref(sync_gv);
294         } else {
295                 error_code = SIM_ERROR_OPERATION_FAILED;
296                 LOGE("[%s] Operation Failed!!! (0x%08x)", __FUNCTION__, error_code);
297         }
298
299         SIM_DEINIT(handle);
300         return error_code;
301 }
302
303 int sim_get_cphs_operator_name(char **full_name, char **short_name)
304 {
305         TelHandle *handle = NULL;
306         int error_code;
307         GVariant *sync_gv = NULL;
308
309         SIM_CHECK_INPUT_PARAMETER(full_name);
310         SIM_CHECK_INPUT_PARAMETER(short_name);
311         *full_name = NULL;
312         *short_name = NULL;
313         SIM_INIT(handle);
314
315         error_code = __sim_check_init_status(handle);
316         if (error_code != SIM_ERROR_NONE) {
317                 LOGE("[%s] SIM NOT initialized (0x%08x)", __FUNCTION__, error_code);
318                 return error_code;
319         }
320
321         sync_gv = __sim_get_info("GetCphsNetName");
322         if (sync_gv) {
323                 gint result;
324                 gchar *full_str = NULL;
325                 gchar *short_str = NULL;
326
327                 g_variant_get(sync_gv, "(iss)", &result, &full_str, &short_str);
328                 if (result == TEL_SIM_RESULT_SUCCESS) {
329                         if (full_str != NULL) {
330                                 *full_name = g_strdup(full_str);
331                                 g_free(full_str);
332                                 LOGI("Full name: [%s]", *full_name);
333                         } else {
334                                 LOGE("full_name is NULL");
335                         }
336
337                         if (short_str != NULL) {
338                                 *short_name = g_strdup(short_str);
339                                 g_free(short_str);
340                                 LOGI("Short name: [%s]", *short_name);
341                         } else {
342                                 LOGE("short_name is NULL");
343                         }
344                 } else {
345                         error_code = _convert_access_rt_to_sim_error(result);
346                         LOGE("[%s] Operation Failed!!! (0x%08x)", __FUNCTION__, error_code);
347                 }
348                 g_variant_unref(sync_gv);
349         } else {
350                 error_code = SIM_ERROR_OPERATION_FAILED;
351                 LOGE("[%s] Operation Failed!!! (0x%08x)", __FUNCTION__, error_code);
352         }
353
354         SIM_DEINIT(handle);
355         return error_code;
356 }
357
358 int sim_get_state(sim_state_e *sim_state)
359 {
360         TelSimCardStatusInfo sim_status_info = {0,};
361         int error_code = SIM_ERROR_NONE;
362         TelHandle *handle = NULL;
363
364         SIM_CHECK_INPUT_PARAMETER(sim_state);
365         SIM_INIT(handle);
366
367         if (tapi_sim_get_init_info(handle, &sim_status_info) != TEL_RETURN_SUCCESS) {
368                 LOGE("[%s] OPERATION_FAILED(0x%08x)", __FUNCTION__, SIM_ERROR_OPERATION_FAILED);
369                 *sim_state = SIM_STATE_UNKNOWN;
370                 SIM_DEINIT(handle);
371                 return SIM_ERROR_OPERATION_FAILED;
372         }
373
374         switch (sim_status_info.status) {
375         case TEL_SIM_STATUS_CARD_ERROR:
376         case TEL_SIM_STATUS_SIM_CARD_POWEROFF:
377         case TEL_SIM_STATUS_CARD_NOT_PRESENT:
378         case TEL_SIM_STATUS_CARD_BLOCKED:
379         case TEL_SIM_STATUS_CARD_REMOVED:
380                 *sim_state = SIM_STATE_UNAVAILABLE;
381                 break;
382         case TEL_SIM_STATUS_UNKNOWN:
383         case TEL_SIM_STATUS_SIM_INITIALIZING:
384                 *sim_state = SIM_STATE_UNKNOWN;
385                 break;
386         case TEL_SIM_STATUS_SIM_INIT_COMPLETED:
387                 *sim_state = SIM_STATE_AVAILABLE;
388                 break;
389         case TEL_SIM_STATUS_SIM_PIN_REQUIRED:
390         case TEL_SIM_STATUS_SIM_PUK_REQUIRED:
391         case TEL_SIM_STATUS_SIM_NCK_REQUIRED:
392         case TEL_SIM_STATUS_SIM_NSCK_REQUIRED:
393         case TEL_SIM_STATUS_SIM_SPCK_REQUIRED:
394         case TEL_SIM_STATUS_SIM_CCK_REQUIRED:
395         case TEL_SIM_STATUS_SIM_LOCK_REQUIRED:
396                 *sim_state = SIM_STATE_LOCKED;
397                 break;
398         }
399
400         LOGI("SIM state: [%d]", *sim_state);
401
402         SIM_DEINIT(handle);
403         return error_code;
404 }
405
406 int sim_get_subscriber_number(char **subscriber_number)
407 {
408         TelHandle *handle = NULL;
409         int error_code;
410         GVariant *sync_gv = NULL;
411
412         SIM_CHECK_INPUT_PARAMETER(subscriber_number);
413         *subscriber_number = NULL;
414         SIM_INIT(handle);
415
416         error_code = __sim_check_init_status(handle);
417         if (error_code != SIM_ERROR_NONE) {
418                 LOGE("[%s] SIM NOT initialized (0x%08x)", __FUNCTION__, error_code);
419                 return error_code;
420         }
421
422         sync_gv = __sim_get_info("GetMsisdn");
423         if (sync_gv) {
424                 gint result;
425                 GVariant *var = NULL;
426                 TelSimMsisdnList msisdn_list = {0,};
427
428                 g_variant_get(sync_gv, "(iu@aa{sv})", &result, &msisdn_list.count, &var);
429                 if (result == TEL_SIM_RESULT_SUCCESS && msisdn_list.count) {
430                         int i = 0;
431                         GVariantIter *iter = NULL;
432                         GVariantIter *iter_row = NULL;
433
434                         LOGI("MSISDN list count: [%d]", msisdn_list.count);
435                         msisdn_list.list = g_malloc0(msisdn_list.count * sizeof(TelSimMsisdnList));
436                         g_variant_get(var, "aa{sv}", &iter);
437                         while (g_variant_iter_next(iter, "a{sv}", &iter_row)) {
438                                 const gchar *key;
439                                 GVariant *key_value;
440                                 while (g_variant_iter_loop(iter_row, "{sv}", &key, &key_value)) {
441                                         if (g_strcmp0(key, "alpha_id") == 0) {
442                                                 msisdn_list.list[i].alpha_id =
443                                                         g_strdup(g_variant_get_string(key_value, NULL));
444                                         }
445
446                                         if (g_strcmp0(key, "num") == 0) {
447                                                 msisdn_list.list[i].num =
448                                                         g_strdup(g_variant_get_string(key_value, NULL));
449                                         }
450                                 }
451                                 i++;
452                                 g_variant_iter_free(iter_row);
453                         }
454                         g_variant_iter_free(iter);
455
456                         /* Only set first number */
457                         if (msisdn_list.count) {
458                                 *subscriber_number = g_strdup(msisdn_list.list[0].num);
459                                 LOGI("Subscribe Number: [%s]", *subscriber_number);
460                         }
461
462                         /* Free resources */
463                         for (i = 0; i < msisdn_list.count; i++) {
464                                 g_free(msisdn_list.list[i].alpha_id);
465                                 g_free(msisdn_list.list[i].num);
466                         }
467                         g_free(msisdn_list.list);
468                 } else {
469                         error_code = _convert_access_rt_to_sim_error(result);
470                         LOGE("[%s] Operation Failed!!! (0x%08x)", __FUNCTION__, error_code);
471                 }
472                 g_variant_unref(sync_gv);
473         } else {
474                 error_code = SIM_ERROR_OPERATION_FAILED;
475                 LOGE("[%s] Operation Failed!!! (0x%08x)", __FUNCTION__, error_code);
476         }
477
478         SIM_DEINIT(handle);
479         return error_code;
480 }
481
482 static void on_noti_sim_status(TelHandle *handle, const char *noti_id,
483                 void *data, void *user_data)
484 {
485         TelSimCardStatus *status = data;
486         sim_state_e state = SIM_STATE_UNKNOWN;
487         sim_state_changed_cb cb;
488
489         LOGE("event(%s) receive with status[%d]", TEL_NOTI_SIM_STATUS, *status);
490
491         switch (*status) {
492         case TEL_SIM_STATUS_CARD_ERROR:
493         case TEL_SIM_STATUS_SIM_CARD_POWEROFF:
494         case TEL_SIM_STATUS_CARD_NOT_PRESENT:
495         case TEL_SIM_STATUS_CARD_BLOCKED:
496         case TEL_SIM_STATUS_CARD_REMOVED:
497                 state = SIM_STATE_UNAVAILABLE;
498                 break;
499         case TEL_SIM_STATUS_UNKNOWN:
500         case TEL_SIM_STATUS_SIM_INITIALIZING:
501                 state = SIM_STATE_UNKNOWN;
502                 break;
503         case TEL_SIM_STATUS_SIM_INIT_COMPLETED:
504                 state = SIM_STATE_AVAILABLE;
505                 break;
506         case TEL_SIM_STATUS_SIM_PIN_REQUIRED:
507         case TEL_SIM_STATUS_SIM_PUK_REQUIRED:
508         case TEL_SIM_STATUS_SIM_NCK_REQUIRED:
509         case TEL_SIM_STATUS_SIM_NSCK_REQUIRED:
510         case TEL_SIM_STATUS_SIM_SPCK_REQUIRED:
511         case TEL_SIM_STATUS_SIM_CCK_REQUIRED:
512         case TEL_SIM_STATUS_SIM_LOCK_REQUIRED:
513                 state = SIM_STATE_LOCKED;
514                 break;
515         }
516
517         if (!ccb->cb) {
518                 LOGE("[%s] callback is null", __FUNCTION__);
519                 return;
520         }
521
522         cb = ccb->cb;
523         cb(state, ccb->user_data);
524 }
525
526 int sim_set_state_changed_cb(sim_state_changed_cb sim_cb, void *user_data)
527 {
528         int error_code = SIM_ERROR_NONE;
529
530         SIM_CHECK_INPUT_PARAMETER(sim_cb);
531
532         if (handle == NULL)
533                 SIM_INIT(handle);
534
535         if (ccb == NULL)
536                 ccb = g_malloc0(sizeof(sim_cb_data));
537
538         ccb->th = handle;
539         ccb->cb = (void *)sim_cb;
540         ccb->user_data = user_data;
541
542         error_code = tapi_register_event_id(handle, TEL_NOTI_SIM_STATUS, on_noti_sim_status, NULL);
543         if (error_code != TEL_RETURN_SUCCESS) {
544                 error_code = SIM_ERROR_OPERATION_FAILED;
545                 SIM_DEINIT(handle);
546                 handle = NULL;
547                 g_free(ccb);
548                 ccb = NULL;
549         }
550
551         return error_code;
552 }
553
554 int sim_unset_state_changed_cb()
555 {
556         int error_code = SIM_ERROR_NONE;
557
558         if (handle == NULL)
559                 return SIM_ERROR_NONE;
560
561         error_code = tapi_deregister_event_id(handle, TEL_NOTI_SIM_STATUS);
562         if (error_code != TEL_RETURN_SUCCESS)
563                 error_code = SIM_ERROR_OPERATION_FAILED;
564
565         SIM_DEINIT(handle);
566         handle = NULL;
567         g_free(ccb);
568         ccb = NULL;
569         return error_code;
570 }