tizen 2.3.1 release
[framework/api/telephony.git] / src / telephony_common.c
1 /*
2  * Copyright (c) 2014 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 "telephony_common.h"
18 #include "telephony_sim.h"
19 #include "telephony_call.h"
20 #include "telephony_network.h"
21 #include "telephony_private.h"
22 #include <gio/gio.h>
23 #include <dlog.h>
24
25 #include <tapi_common.h>
26 #include <TelSim.h>
27 #include <TelNetwork.h>
28 #include <TapiUtility.h>
29
30 #ifdef LOG_TAG
31 #undef LOG_TAG
32 #endif
33 #define LOG_TAG "CAPI_TELEPHONY"
34
35 #define CALLBACK_CALL(data) \
36         if (evt_cb_data->cb) { \
37                 evt_cb_data->cb(evt_cb_data->handle, \
38                          evt_cb_data->noti_id, data, evt_cb_data->user_data); \
39         }
40
41 #define CHECK_INPUT_PARAMETER(arg) \
42         if (arg == NULL) { \
43                 LOGE("INVALID_PARAMETER"); \
44                 return TELEPHONY_ERROR_INVALID_PARAMETER; \
45         }
46
47 typedef struct {
48         telephony_h handle;
49         telephony_noti_e noti_id;
50         telephony_noti_cb cb;
51         void *user_data;
52 } telephony_evt_cb_data;
53
54 static const char *voice_call_state_tbl[] = {
55         TAPI_NOTI_VOICE_CALL_STATUS_IDLE,
56         TAPI_NOTI_VOICE_CALL_STATUS_ACTIVE,
57         TAPI_NOTI_VOICE_CALL_STATUS_HELD,
58         TAPI_NOTI_VOICE_CALL_STATUS_DIALING,
59         TAPI_NOTI_VOICE_CALL_STATUS_ALERT,
60         TAPI_NOTI_VOICE_CALL_STATUS_INCOMING
61 };
62
63 static const char *video_call_state_tbl[] = {
64         TAPI_NOTI_VIDEO_CALL_STATUS_IDLE,
65         TAPI_NOTI_VIDEO_CALL_STATUS_ACTIVE,
66         TAPI_NOTI_VIDEO_CALL_STATUS_DIALING,
67         TAPI_NOTI_VIDEO_CALL_STATUS_ALERT,
68         TAPI_NOTI_VIDEO_CALL_STATUS_INCOMING
69 };
70
71 static const char *_mapping_noti_id(telephony_noti_e noti_id)
72 {
73         switch (noti_id) {
74         case TELEPHONY_NOTI_SIM_STATUS:
75                 return TAPI_NOTI_SIM_STATUS;
76         case TELEPHONY_NOTI_NETWORK_SERVICE_STATE:
77                 return TAPI_PROP_NETWORK_SERVICE_TYPE;
78         case TELEPHONY_NOTI_NETWORK_CELLID:
79                 return TAPI_PROP_NETWORK_CELLID;
80         case TELEPHONY_NOTI_NETWORK_ROAMING_STATUS:
81                 return TAPI_PROP_NETWORK_ROAMING_STATUS;
82         case TELEPHONY_NOTI_NETWORK_SIGNALSTRENGTH_LEVEL:
83                 return TAPI_PROP_NETWORK_SIGNALSTRENGTH_LEVEL;
84         default:
85                 return NULL;
86         }
87 }
88
89 static int _mapping_sim_status(TelSimCardStatus_t tapi_sim_status)
90 {
91         int sim_status;
92
93         switch (tapi_sim_status) {
94         case TAPI_SIM_STATUS_CARD_ERROR:
95         case TAPI_SIM_STATUS_CARD_NOT_PRESENT:
96         case TAPI_SIM_STATUS_CARD_BLOCKED:
97         case TAPI_SIM_STATUS_CARD_REMOVED:
98         case TAPI_SIM_STATUS_CARD_CRASHED:
99                 sim_status = TELEPHONY_SIM_STATE_UNAVAILABLE;
100                 break;
101         case TAPI_SIM_STATUS_SIM_PIN_REQUIRED:
102         case TAPI_SIM_STATUS_SIM_PUK_REQUIRED:
103         case TAPI_SIM_STATUS_SIM_NCK_REQUIRED:
104         case TAPI_SIM_STATUS_SIM_NSCK_REQUIRED:
105         case TAPI_SIM_STATUS_SIM_SPCK_REQUIRED:
106         case TAPI_SIM_STATUS_SIM_CCK_REQUIRED:
107         case TAPI_SIM_STATUS_SIM_LOCK_REQUIRED:
108                 sim_status = TELEPHONY_SIM_STATE_LOCKED;
109                 break;
110         case TAPI_SIM_STATUS_SIM_INIT_COMPLETED:
111                 sim_status = TELEPHONY_SIM_STATE_AVAILABLE;
112                 break;
113         case TAPI_SIM_STATUS_UNKNOWN:
114         case TAPI_SIM_STATUS_SIM_INITIALIZING:
115         default:
116                 sim_status = TELEPHONY_SIM_STATE_UNKNOWN;
117                 break;
118         }
119
120         return sim_status;
121 }
122
123 static int _mapping_service_state(int tapi_service_type)
124 {
125         int service_state;
126
127         switch (tapi_service_type) {
128         case TAPI_NETWORK_SERVICE_TYPE_UNKNOWN:
129         case TAPI_NETWORK_SERVICE_TYPE_NO_SERVICE:
130         case TAPI_NETWORK_SERVICE_TYPE_SEARCH:
131                 service_state = TELEPHONY_NETWORK_SERVICE_STATE_OUT_OF_SERVICE;
132                 break;
133         case TAPI_NETWORK_SERVICE_TYPE_EMERGENCY:
134                 service_state = TELEPHONY_NETWORK_SERVICE_STATE_EMERGENCY_ONLY;
135                 break;
136         default:
137                 service_state = TELEPHONY_NETWORK_SERVICE_STATE_IN_SERVICE;
138                 break;
139         }
140
141         return service_state;
142 }
143
144 static telephony_error_e __deregister_all_noti(telephony_h handle, telephony_noti_e noti_id)
145 {
146         const char *tapi_noti;
147         int ret, i;
148         TapiHandle *tapi_h;
149
150         CHECK_INPUT_PARAMETER(handle);
151         tapi_h = ((telephony_data *)handle)->tapi_h;
152
153         tapi_noti = _mapping_noti_id(noti_id);
154         if (tapi_noti == NULL && noti_id != TELEPHONY_NOTI_VOICE_CALL_STATE
155                         && noti_id != TELEPHONY_NOTI_VIDEO_CALL_STATE) {
156                 LOGE("Not supported noti_id");
157                 return TELEPHONY_ERROR_INVALID_PARAMETER;
158         }
159
160         /* Deregister all TAPI_NOTI_VOICE/VIDEO_CALL_STATUS_xxx notification */
161         if (noti_id == TELEPHONY_NOTI_VOICE_CALL_STATE) {
162                 int count = sizeof(voice_call_state_tbl) / sizeof(char *);
163                 for (i = 0; i < count; i++) {
164                         ret = tel_deregister_noti_event(tapi_h, voice_call_state_tbl[i]);
165                         if (ret != TAPI_API_SUCCESS) {
166                                 LOGE("Noti [%s] deregistration failed", voice_call_state_tbl[i]);
167                         }
168                 }
169         } else if (noti_id == TELEPHONY_NOTI_VIDEO_CALL_STATE) {
170                 int count = sizeof(video_call_state_tbl) / sizeof(char *);
171                 for (i = 0; i < count; i++) {
172                         ret = tel_deregister_noti_event(tapi_h, video_call_state_tbl[i]);
173                         if (ret != TAPI_API_SUCCESS) {
174                                 LOGE("Noti [%s] deregistration failed", video_call_state_tbl[i]);
175                         }
176                 }
177         } else {
178                 /* Deregister other notifications */
179                 ret = tel_deregister_noti_event(tapi_h, tapi_noti);
180                 if (ret != TAPI_API_SUCCESS) {
181                         LOGE("Noti [%s] deregistration failed", tapi_noti);
182                 }
183         }
184
185         return TELEPHONY_ERROR_NONE;
186 }
187
188 static void _deregister_noti(gpointer data)
189 {
190         telephony_evt_cb_data *evt_cb_data = data;
191
192         if (evt_cb_data != NULL) {
193                 /* Deregister all TAPI_NOTI_VOICE/VIDEO_CALL_STATUS_xxx notification */
194                 if (__deregister_all_noti(evt_cb_data->handle, evt_cb_data->noti_id)
195                                 == TELEPHONY_ERROR_NONE) {
196                         LOGI("De-registered noti_id: [%d]", evt_cb_data->noti_id);
197                 }
198
199                 /* Free evt_cb_data */
200                 g_free(evt_cb_data);
201         }
202 }
203
204 static void on_signal_callback(TapiHandle *tapi_h, const char *evt_id,
205         void *data, void *user_data)
206 {
207         telephony_evt_cb_data *evt_cb_data = user_data;
208
209         if (evt_cb_data == NULL) {
210                 LOGE("evt_cb_data is NULL");
211                 return;
212         }
213
214         if (!g_strcmp0(evt_id, TAPI_NOTI_SIM_STATUS)) {
215                 int sim_status = _mapping_sim_status(*(TelSimCardStatus_t *)data);
216                 CALLBACK_CALL(&sim_status);
217         } else if (!g_strcmp0(evt_id, TAPI_PROP_NETWORK_SERVICE_TYPE)) {
218                 int service_state = _mapping_service_state(*(int *)data);
219                 CALLBACK_CALL(&service_state);
220         } else if (!g_strcmp0(evt_id, TAPI_PROP_NETWORK_CELLID)) {
221                 int cell_id = *(int *)data;
222                 CALLBACK_CALL(&cell_id);
223         } else if (!g_strcmp0(evt_id, TAPI_PROP_NETWORK_ROAMING_STATUS)) {
224                 int roaming_status = *(int *)data;
225                 CALLBACK_CALL(&roaming_status);
226         } else if (!g_strcmp0(evt_id, TAPI_PROP_NETWORK_SIGNALSTRENGTH_LEVEL)) {
227                 int rssi = *(int *)data;
228                 CALLBACK_CALL(&rssi);
229         } else if (!g_strcmp0(evt_id, TAPI_NOTI_VOICE_CALL_STATUS_IDLE)
230                         || !g_strcmp0(evt_id, TAPI_NOTI_VOICE_CALL_STATUS_ACTIVE)
231                         || !g_strcmp0(evt_id, TAPI_NOTI_VOICE_CALL_STATUS_HELD)
232                         || !g_strcmp0(evt_id, TAPI_NOTI_VOICE_CALL_STATUS_DIALING)
233                         || !g_strcmp0(evt_id, TAPI_NOTI_VOICE_CALL_STATUS_ALERT)
234                         || !g_strcmp0(evt_id, TAPI_NOTI_VOICE_CALL_STATUS_INCOMING)) {
235                 telephony_call_state_e call_state;
236                 telephony_call_get_voice_call_state(evt_cb_data->handle, &call_state);
237                 CALLBACK_CALL(&call_state);
238         } else if (!g_strcmp0(evt_id, TAPI_NOTI_VIDEO_CALL_STATUS_IDLE)
239                         || !g_strcmp0(evt_id, TAPI_NOTI_VIDEO_CALL_STATUS_ACTIVE)
240                         || !g_strcmp0(evt_id, TAPI_NOTI_VIDEO_CALL_STATUS_DIALING)
241                         || !g_strcmp0(evt_id, TAPI_NOTI_VIDEO_CALL_STATUS_ALERT)
242                         || !g_strcmp0(evt_id, TAPI_NOTI_VIDEO_CALL_STATUS_INCOMING)) {
243                 telephony_call_state_e call_state;
244                 telephony_call_get_video_call_state(evt_cb_data->handle, &call_state);
245                 CALLBACK_CALL(&call_state);
246         } else {
247                 LOGE("Unhandled noti: [%s]", evt_id);
248         }
249 }
250
251 int telephony_set_noti_cb(telephony_h handle,
252         telephony_noti_e noti_id, telephony_noti_cb cb, void *user_data)
253 {
254         telephony_evt_cb_data *evt_cb_data = NULL;
255         const char *tapi_noti;
256         int ret, i;
257         TapiHandle *tapi_h;
258
259         CHECK_TELEPHONY_SUPPORTED(TELEPHONY_FEATURE);
260         CHECK_INPUT_PARAMETER(handle);
261
262         LOGI("Entry");
263         tapi_h = ((telephony_data *)handle)->tapi_h;
264
265         /* Mapping TAPI notification */
266         tapi_noti = _mapping_noti_id(noti_id);
267         if (tapi_noti == NULL && noti_id != TELEPHONY_NOTI_VOICE_CALL_STATE
268                         && noti_id != TELEPHONY_NOTI_VIDEO_CALL_STATE) {
269                 LOGE("Not supported noti_id");
270                 return TELEPHONY_ERROR_INVALID_PARAMETER;
271         }
272
273         /* Make evt_cb_data */
274         evt_cb_data = g_new0(telephony_evt_cb_data, 1);
275         evt_cb_data->handle = handle;
276         evt_cb_data->noti_id = noti_id;
277         evt_cb_data->cb = cb;
278         evt_cb_data->user_data = user_data;
279
280         /*
281          * In case of register Call State notification,
282          * we should take care of all TAPI_NOTI_VOICE/VIDEO_CALL_STATUS_xxx notification
283          */
284         if (noti_id == TELEPHONY_NOTI_VOICE_CALL_STATE) {
285                 int count = sizeof(voice_call_state_tbl) / sizeof(char *);
286                 for (i = 0; i < count; i++) {
287                         ret = tel_register_noti_event(tapi_h, voice_call_state_tbl[i], on_signal_callback, evt_cb_data);
288                         if (ret != TAPI_API_SUCCESS) {
289                                 LOGE("Noti registration failed");
290                                 g_free(evt_cb_data);
291                                 return TELEPHONY_ERROR_OPERATION_FAILED;
292                         }
293                 }
294         } else if (noti_id == TELEPHONY_NOTI_VIDEO_CALL_STATE) {
295                 int count = sizeof(video_call_state_tbl) / sizeof(char *);
296                 for (i = 0; i < count; i++) {
297                         ret = tel_register_noti_event(tapi_h, video_call_state_tbl[i], on_signal_callback, evt_cb_data);
298                         if (ret != TAPI_API_SUCCESS) {
299                                 LOGE("Noti registration failed");
300                                 g_free(evt_cb_data);
301                                 return TELEPHONY_ERROR_OPERATION_FAILED;
302                         }
303                 }
304         } else { /* Register other notifications */
305                 ret = tel_register_noti_event(tapi_h, tapi_noti, on_signal_callback, evt_cb_data);
306                 if (ret != TAPI_API_SUCCESS) {
307                         LOGE("Noti registration failed");
308                         g_free(evt_cb_data);
309                         return TELEPHONY_ERROR_OPERATION_FAILED;
310                 }
311         }
312
313         /* Append evt_cb_data to free */
314         ((telephony_data *)handle)->evt_list = g_slist_append(((telephony_data *)handle)->evt_list, evt_cb_data);
315
316         return TELEPHONY_ERROR_NONE;
317 }
318
319 int telephony_unset_noti_cb(telephony_h handle, telephony_noti_e noti_id)
320 {
321         telephony_evt_cb_data *evt_cb_data = NULL;
322         GSList *list = NULL;
323
324         CHECK_TELEPHONY_SUPPORTED(TELEPHONY_FEATURE);
325         CHECK_INPUT_PARAMETER(handle);
326
327         LOGI("Entry");
328
329         /* Deregister all TAPI_NOTI_VOICE/VIDEO_CALL_STATUS_xxx notification */
330         if (__deregister_all_noti(handle, noti_id) != TELEPHONY_ERROR_NONE) {
331                 LOGE("De-registration failed");
332                 return TELEPHONY_ERROR_INVALID_PARAMETER;
333         }
334         LOGI("De-registered noti_id: [%d]", noti_id);
335
336         /* Free evt_cb_data */
337         list = g_slist_nth(((telephony_data *)handle)->evt_list, 0);
338         while (list) {
339                 evt_cb_data = list->data;
340                 if (evt_cb_data->noti_id == noti_id) {
341                         ((telephony_data *)handle)->evt_list = g_slist_remove(((telephony_data *)handle)->evt_list, evt_cb_data);
342                         g_free(evt_cb_data);
343                         break;
344                 }
345
346                 list = g_slist_next(list);
347         }
348
349         return TELEPHONY_ERROR_NONE;
350 }
351
352 int telephony_init(telephony_handle_list_s *list)
353 {
354         char **cp_list;
355         int cp_count = 0;
356         int i;
357
358         CHECK_TELEPHONY_SUPPORTED(TELEPHONY_FEATURE);
359         CHECK_INPUT_PARAMETER(list);
360
361 #if !GLIB_CHECK_VERSION(2,35,0)
362         /* Need g_type_init() to use tel_get_cp_name_list() */
363         g_type_init();
364 #endif
365
366         cp_list = tel_get_cp_name_list();
367         if (cp_list == NULL) {
368                 LOGE("cp_list is NULL");
369                 return TELEPHONY_ERROR_OPERATION_FAILED;
370         }
371
372         while (cp_list[cp_count]) {
373                 cp_count++;
374         }
375
376         list->count = cp_count;
377         list->handle = g_malloc(cp_count * sizeof(telephony_h));
378         for (i = 0; i < cp_count; i++) {
379                 telephony_data *tmp = g_malloc(sizeof(telephony_data));
380                 tmp->evt_list = NULL;
381                 tmp->tapi_h = tel_init(cp_list[i]);
382                 if (tmp->tapi_h == NULL) {
383                         int j = 0;
384                         LOGE("handle is NULL");
385                         for (; j < i; j++) {
386                                 /* Need to free already allocated data */
387                                 if (list->handle[j]) {
388                                         tel_deinit(((telephony_data *)list->handle[j])->tapi_h);
389                                         g_free(list->handle[j]);
390                                 }
391                         }
392                         g_free(tmp);
393                         g_free(list->handle);
394                         list->handle = NULL;
395                         list->count = 0;
396                         g_strfreev(cp_list);
397                         return TELEPHONY_ERROR_OPERATION_FAILED;
398                 }
399                 list->handle[i] = (telephony_h)tmp;
400         }
401         g_strfreev(cp_list);
402
403         return TELEPHONY_ERROR_NONE;
404 }
405
406 int telephony_deinit(telephony_handle_list_s *list)
407 {
408         unsigned int i;
409
410         CHECK_TELEPHONY_SUPPORTED(TELEPHONY_FEATURE);
411         CHECK_INPUT_PARAMETER(list);
412
413         for (i = 0; i < list->count; i++) {
414                 telephony_data *tmp = (telephony_data *)list->handle[i];
415
416                 /* De-init all TapiHandle */
417                 tel_deinit(tmp->tapi_h);
418                 tmp->tapi_h = NULL;
419
420                 /* De-register all registered events */
421                 g_slist_free_full(tmp->evt_list, _deregister_noti);
422                 tmp->evt_list = NULL;
423
424                 /* Free handle[i] */
425                 g_free(list->handle[i]);
426         }
427         g_free(list->handle);
428         list->handle = NULL;
429         list->count = 0;
430
431         return TELEPHONY_ERROR_NONE;
432 }