fix unapplied build option
[platform/core/telephony/tel-plugin-packetservice.git] / src / ps_tcore_interface.c
1 /*
2  * tel-plugin-packetservice
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: DongHoo Park <donghoo.park@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
22 #include "ps_common.h"
23 #include "ps_context.h"
24 #include "ps_modem.h"
25 #include "ps_service.h"
26 #include "ps_master.h"
27 #include "ps_tcore_interface.h"
28 #include "ps_hook.h"
29
30 #include <server.h>
31 #include <plugin.h>
32 #include <storage.h>
33 #include <co_ps.h>
34 #include <co_context.h>
35 #include <co_modem.h>
36 #include <co_sim.h>
37 #include <type/network.h>
38 #include <co_network.h>
39 #include <user_request.h>
40 #include <vconf.h>
41 #include "ps_log.h"
42
43 enum ps_call_state {
44         PS_CALL_STATE_RESULT_OK = 0x00,
45         PS_CALL_STATE_RESULT_CONNECT = 0x01,
46         PS_CALL_STATE_RESULT_NO_CARRIER = 0x03
47 };
48
49 static void __ps_handle_prop_dnet_connection_status(CoreObject *co_ps, void *user_data)
50 {
51         const char *value = NULL;
52         int context_id;
53         guint index;
54         ps_service_t *service = (ps_service_t *)user_data;
55
56         value = tcore_object_ref_property(co_ps, PROP_DNET_CONNECTION_STATUS);
57         ps_info_ex_svc(service, "Dnet connection status = %s", value);
58
59         if (!value || strlen(value) == 0)
60                 return;
61
62         if (g_strrstr(value, "disconnected")) {
63                 for (index = 0; index < g_slist_length(service->contexts); index++) {
64                         ps_context_t *context = g_slist_nth_data(service->contexts, index);
65                         CoreObject *co_context = _ps_context_ref_co_context(context);
66                         if (tcore_context_get_role(co_context) == CONTEXT_ROLE_INTERNET) {
67                                 context_id = value[0];
68                                 ps_info_ex_svc(service, "TNOTI_PS_CALL_STATUS - CID: [%d] State: [%d]", context_id, PS_CALL_STATE_RESULT_NO_CARRIER);
69                                 _ps_context_set_ps_defined(context, FALSE);
70                                 tcore_ps_set_cid_active(co_ps, context_id, FALSE);
71                                 tcore_ps_set_cid_connected(co_ps, context_id, FALSE);
72                                 _ps_context_set_connected(context, FALSE);
73                                 break;
74                         }
75                 }
76         }
77 }
78
79 static gboolean __ps_on_prop_changed(CoreObject *co_ps, const void *event_info,
80                                      void *user_data)
81 {
82         GSList *key = (GSList *)event_info;
83
84         if (CORE_OBJECT_KEY_FIND(key, PROP_DNET_CONNECTION_STATUS))
85                 __ps_handle_prop_dnet_connection_status(co_ps, user_data);
86         return TRUE;
87 }
88
89 static void __ps_modem_cp_reset_handler(ps_modem_t *modem)
90 {
91         unsigned int index;
92 #ifdef TIZEN_SUPPORT_VOLTE
93         enum co_context_role role = CONTEXT_ROLE_UNKNOWN;
94 #endif
95
96         ps_info_ex_modem(modem, "disconnect all contexts");
97         /* send deactivation request to clear resources. */
98         for (index = 0; index < g_slist_length(modem->contexts); index++) {
99                 ps_context_t *context = g_slist_nth_data(modem->contexts, index);
100                 ps_service_t *service = _ps_context_ref_service(context);
101                 CoreObject *co_context = _ps_context_ref_co_context(context);
102                 if (service == NULL)
103                         continue;
104 #ifdef TIZEN_SUPPORT_VOLTE
105                 role = tcore_context_get_role(co_context);
106                 ps_info_ex_modem(modem, "role(%d)", role);
107                 if (role == CONTEXT_ROLE_IMS && !tcore_network_get_ims_on_deregistering(_ps_service_ref_co_network(service))) {
108                         if (_ps_context_deregister_ims(context) == TCORE_RETURN_SUCCESS)
109                                 tcore_context_set_state(co_context, CONTEXT_STATE_DEACTIVATED);
110                 }
111 #endif
112                 tcore_ps_deactivate_context(_ps_service_ref_co_ps(service), co_context, NULL);
113                 tcore_context_set_state(co_context, CONTEXT_STATE_DEACTIVATED);
114
115                 //due to pendig UR needs to clear AP resources
116                 tcore_ps_clear_context_id(_ps_service_ref_co_ps(service), co_context);
117                 _ps_context_set_connected(context, FALSE);
118
119         }
120 #ifdef TIZEN_SUPPORT_REQUEST_HOOK_PDP_CONTROL
121         /* check for any pending request in modem queue and respond with error */
122         _ps_hook_cp_reset_send_pending_request_response(modem);
123
124         /* reset modem flag */
125         modem->hook_flag &= PS_NO_PENDING_REQUEST;
126 #endif
127 }
128
129 #ifdef PREPAID_SIM_APN_SUPPORT
130 static void __on_call_status_for_prepaid_sim(ps_service_t *service, ps_context_t *def_context, ps_modem_t *modem, struct tnoti_ps_call_status *cstatus, gboolean retry)
131 {
132         unsigned char prepaid_cid = 0;
133         ps_context_t *prepaid_def_context = NULL;
134         unsigned char def_cid = 0;
135
136         if (!service) {
137                 ps_err_ex_svc(service, "service does not exist");
138                 return;
139         }
140
141         if (!modem) {
142                 ps_err_ex_modem(modem, "modem does not exist");
143                 return;
144         }
145
146         if (def_context == NULL) {
147                 def_context = _ps_service_return_default_context(service, CONTEXT_ROLE_INTERNET);
148                 if (def_context) {
149                         CoreObject *co_context = NULL;
150                         co_context = _ps_context_ref_co_context(def_context);
151                         def_cid = tcore_context_get_id(co_context);
152                 }
153         }
154
155         prepaid_def_context = _ps_service_return_default_context(service, CONTEXT_ROLE_PREPAID_INTERNET);
156         ps_dbg_ex_modem(modem, "prepaid_def_context[%p]", prepaid_def_context);
157         if (prepaid_def_context) {
158                 CoreObject *co_context = NULL;
159                 co_context = _ps_context_ref_co_context(prepaid_def_context);
160                 prepaid_cid = tcore_context_get_id(co_context);
161         }
162         ps_dbg_ex_modem(modem, "prepaid_cid[%d]", prepaid_cid);
163
164         /* Has prepaid APN */
165         if (prepaid_def_context) {
166                 ps_master_t * master = NULL;
167                 ps_context_t *context = NULL;
168                 int rv = 0;
169
170                 ps_dbg_ex_modem(modem, "Context id: %d", cstatus->context_id);
171                 ps_dbg_ex_modem(modem, "retry: %s", retry ? "TRUE" : "FALSE");
172
173                 if (cstatus->context_id == def_cid) {
174                         ps_dbg_ex_modem(modem, "Resetting connection time for default context");
175                         _ps_service_reset_connection_timer(def_context);
176
177                         /* Connect to default prepaid internet */
178                         rv = _ps_service_connect_default_prepaid_context(service);
179                         ps_dbg_ex_modem(modem, "prepaid internet connect - rv[%d]", rv);
180                 } else if (cstatus->context_id == prepaid_cid) {
181                         /* Reset connection */
182                         ps_dbg_ex_modem(modem, "Resetting connection time for prepaid internet context");
183                         _ps_service_reset_connection_timer(prepaid_def_context);
184
185                         /* Connect to default internet */
186                         rv =  _ps_service_connect_default_context(service);
187                         ps_dbg_ex_modem(modem, "default internet connect - rv[%d]", rv);
188                 }
189
190                 /* Reset Last connected, Profile ID and Operator vconf keys. */
191                 ps_dbg_ex_modem(modem, "Reset vconf keys...");
192                 master = _ps_modem_ref_master(modem);
193                 _ps_master_set_storage_value_string(master, STORAGE_KEY_TELEPHONY_LAST_CONNECTED_CONTEXT_PLMN, NULL);
194                 /* Get context*/
195                 context = _ps_service_return_context_by_cid(service, cstatus->context_id);
196                 ps_dbg_ex_modem(modem, "context[%p]", context);
197                 if (context) {
198                         /* Set profile ID */
199                         ps_dbg_ex_modem(modem, "Reset profile id");
200                         _ps_master_set_storage_value_int(master, STORAGE_KEY_PDP_LAST_CONNECTED_CONTEXT_PROFILE_ID, -1);
201                         /* set vconf last connected profile */
202                         ps_dbg_ex_modem(modem, "set vconf last connected profile to FALSE");
203                         _ps_master_set_storage_value_bool(master, STORAGE_KEY_PDP_LAST_CONNECTED_CONTEXT_BOOL, FALSE);
204                 }
205         }
206 }
207 #endif
208
209 static void __on_hook_status_NO_carrier(ps_modem_t *modem, ps_service_t *service,
210                 CoreObject *co_ps, struct tnoti_ps_call_status *cstatus)
211 {
212         ps_context_t *def_context = NULL, *ims_context = NULL;
213         unsigned char def_cid = 0, ims_cid = 0;
214         int value = 0;
215         gboolean retry = TRUE;
216
217         if (!modem || !service || !cstatus)
218                 return;
219
220         retry = ps_util_check_permanent_reject_cause(cstatus->result, _ps_modem_get_roaming(modem));
221         /* if retry not permitted by network */
222         if (FALSE == retry) {
223                 ps_dbg_ex_modem(modem, "DO NOT RETRY NETWORK CONNECTION AUTOMATICALLY");
224                 ps_info_ex_modem(modem, "permanent reject cause (%d), roaming(%d)", cstatus->result, _ps_modem_get_roaming(modem));
225
226                 def_context = _ps_service_return_default_context(service, CONTEXT_ROLE_INTERNET);
227                 if (def_context) {
228                         CoreObject *co_context = _ps_context_ref_co_context(def_context);
229                         def_cid = tcore_context_get_id(co_context);
230                 }
231
232                 ims_context = _ps_service_return_default_context(service, CONTEXT_ROLE_IMS);
233                 if (ims_context) {
234                         CoreObject *co_context = _ps_context_ref_co_context(ims_context);
235                         ims_cid = tcore_context_get_id(co_context);
236                 }
237         }
238
239         _ps_service_set_ps_defined(service, FALSE, cstatus->context_id);
240         tcore_ps_set_cid_active(co_ps, cstatus->context_id, FALSE);
241         tcore_ps_set_cid_connected(co_ps, cstatus->context_id, FALSE);
242         _ps_service_set_connected(service, cstatus, FALSE);
243
244         if (FALSE == tcore_ps_any_internet_mms_tethering_context_activating_activated(co_ps, &value)) {
245                 ps_dbg_ex_modem(modem, "No context open connections, publish disconnected signal");
246 #ifdef TIZEN_SUPPORT_REQUEST_HOOK_PDP_CONTROL
247                 /* Handle any pending request if present */
248                 modem = _ps_service_ref_modem(service);
249                 _ps_hook_send_pending_user_request(modem);
250 #endif
251                 /* Ensured that set_reset_profile is always done default thread's context */
252                 if (_ps_modem_get_reset_profile(modem) == TRUE) {
253                         /* Initiate Reset Profile */
254                         ps_info_ex_modem(modem, "Profiles are being reset");
255                         /* Shouldn't invoke set profile directly, as it will remove hooks registered to server while being hook callback*/
256                         if (NULL == _ps_modem_get_profile_reset_gsource(modem)) {
257                                 GSource *gsource = NULL;
258                                 gsource = ps_util_gsource_dispatch(g_main_context_default(), G_PRIORITY_LOW, (GSourceFunc)_ps_modem_initiate_reset_profile, modem);
259                                 _ps_modem_set_profile_reset_gsource(modem, gsource);
260                         }
261                 }
262         }
263
264 #ifdef PREPAID_SIM_APN_SUPPORT
265         __on_call_status_for_prepaid_sim(service, def_context, modem, cstatus, retry);
266 #endif
267
268         ps_info_ex_modem(modem, "Any context activating or activated [%d]", value);
269         if (FALSE == retry) {
270                 if (cstatus->context_id == def_cid) {
271                         _ps_service_reset_connection_timer(def_context);
272                         _ps_context_set_alwayson_enable(def_context, FALSE);
273                 } else if (cstatus->context_id == ims_cid) {
274                         _ps_service_reset_connection_timer(ims_context);
275                         _ps_context_set_alwayson_enable(ims_context, FALSE);
276                 }
277         }
278 }
279
280 static enum tcore_hook_return __on_hook_call_status(Server *s, CoreObject *source,
281                                                     enum tcore_notification_command command, unsigned int data_len, void *data,
282                                                     void *user_data)
283 {
284         ps_modem_t *modem = NULL;
285         ps_service_t *service = user_data;
286         CoreObject *co_ps = NULL;
287         GSList *co_list;
288
289         gboolean b_data_allowed = FALSE;
290         gboolean b_roaming_checker = TRUE;
291         gboolean b_mms_checker = FALSE;
292         gboolean b_ims_checker = FALSE;
293         gboolean b_allowed_on_data_off = FALSE;
294
295         struct tnoti_ps_call_status *cstatus = data;
296
297         g_return_val_if_fail(service != NULL, TCORE_HOOK_RETURN_STOP_PROPAGATION);
298
299         co_ps = _ps_service_ref_co_ps(service);
300         if (co_ps != source) {
301                 ps_warn_ex_svc(service, "Received notification for different Subscription - neglecting the notification!!!");
302                 return TCORE_HOOK_RETURN_CONTINUE;
303         }
304
305         modem = _ps_service_ref_modem(service);
306         if (!modem) {
307                 ps_err_ex_modem(modem, "modem does not exist");
308                 return TCORE_HOOK_RETURN_CONTINUE;
309         }
310
311         b_data_allowed = _ps_modem_get_data_allowed(modem);
312
313         co_list = tcore_ps_ref_context_by_id(co_ps, cstatus->context_id);
314         for (; co_list; co_list = co_list->next) {
315                 CoreObject *co_context = NULL;
316                 enum co_context_role role = CONTEXT_ROLE_UNKNOWN;
317
318                 co_context = co_list->data;
319                 role = tcore_context_get_role(co_context);
320
321                 if (role == CONTEXT_ROLE_MMS || role == CONTEXT_ROLE_PREPAID_MMS) {
322                         b_mms_checker = TRUE;
323                         break;
324                 }
325                 if (role == CONTEXT_ROLE_IMS || role == CONTEXT_ROLE_IMS_EMERGENCY || role == CONTEXT_ROLE_IMS_UT) {
326                         b_ims_checker = TRUE;
327                         break;
328                 }
329                 if (role == CONTEXT_ROLE_BIP || role == CONTEXT_ROLE_FOTA) {
330                         b_allowed_on_data_off = TRUE;
331                         break;
332                 }
333         }
334
335 #if !defined(TIZEN_SUPPORT_MMS_CONNECT_FORCE)
336                 ps_dbg_ex_modem(modem, "csc runtime feature disabled");
337                 b_mms_checker = FALSE;
338 #endif
339
340         if (!b_ims_checker && (_ps_modem_get_roaming(modem)) && !(_ps_modem_get_data_roaming_allowed(modem))) {
341                 ps_info_ex_modem(modem, "roaming network is not allowed");
342                 b_roaming_checker = FALSE;
343         }
344
345         ps_info_ex_modem(modem, "data_allowed(%d) call status event cid(%d) state(%d) reason(%d)",
346                          b_data_allowed, cstatus->context_id, cstatus->state, cstatus->result);
347
348         if (!b_roaming_checker || (!b_data_allowed && !b_mms_checker && !b_ims_checker && !b_allowed_on_data_off)) {
349                 ps_dbg_ex_modem(modem, "mismatched: roaming checker(%d) data_allowed(%d) mms_checker(%d) b_ims_checker(%d)",
350                                 b_roaming_checker, b_data_allowed, b_mms_checker, b_ims_checker);
351
352                 if (cstatus->state == PS_CALL_STATE_RESULT_OK) {
353                         /*
354                          * If attach_apn_complete is FALSE, need to set TRUE.
355                          * In case of boot-up with roaming-SIM and Data Roaming option disabled,
356                          * although define process is triggered, 'attach_apn_complete' flag does not set TRUE.
357                          * So, when Data Roaming option is enabled, pdp activation is not triggered.
358                          */
359                         if (service->attach_apn_complete) {
360                                 _ps_service_set_connected(service, cstatus, FALSE);
361                                 tcore_ps_set_cid_active(co_ps, cstatus->context_id, FALSE);
362                         } else {
363                                 _ps_service_set_ps_defined(service, TRUE, cstatus->context_id);
364                         }
365                         return TCORE_HOOK_RETURN_CONTINUE;
366                 } else if (cstatus->state == PS_CALL_STATE_RESULT_CONNECT) {
367                         _ps_service_set_connected(service, cstatus, TRUE);
368                         _ps_service_disconnect_contexts(service);
369                         return TCORE_HOOK_RETURN_CONTINUE;
370                 }
371         }
372
373         ps_dbg_ex_modem(modem, "service(%p) status(%d)", service, cstatus->state);
374         if (cstatus->state == PS_CALL_STATE_RESULT_OK) {                /* DEFINE */
375                 _ps_service_set_ps_defined(service, TRUE, cstatus->context_id);
376         } else if (cstatus->state == PS_CALL_STATE_RESULT_CONNECT) {    /* CONNECTED */
377                 TReturn rv;
378
379                 if (tcore_ps_get_cid_active(co_ps, cstatus->context_id) == FALSE) {
380                         ps_dbg_ex_modem(modem, "DDS scenario");
381
382                         /* De-activate context */
383                         rv = tcore_ps_deactivate_contexts(co_ps);
384                         if (rv != TCORE_RETURN_SUCCESS) {
385                                 ps_err_ex_modem(modem, "fail to deactivation");
386                                 return TCORE_HOOK_RETURN_CONTINUE;
387                         }
388                 } else {
389                         gboolean ret = TRUE;
390                         gboolean need_deactivate = FALSE;
391
392                         ret = _ps_service_set_connected(service, cstatus, TRUE);
393                         tcore_ps_set_cid_connected(co_ps, cstatus->context_id, TRUE);
394
395                         if (ret == FALSE || (_ps_modem_get_reset_profile(modem) == TRUE))
396                                 need_deactivate = TRUE;
397
398 #ifdef TIZEN_SUPPORT_REQUEST_HOOK_PDP_CONTROL
399                         if (g_queue_get_length(_ps_hook_ref_work_queue(modem)))
400                                 need_deactivate = TRUE;
401 #endif
402
403                         if (need_deactivate) {
404                                 ps_info_ex_modem(modem, "Special request present in queue or pending activation request");
405 #ifdef TIZEN_SUPPORT_REQUEST_HOOK_PDP_CONTROL
406                                 if (ps_util_peek_waiting_job(_ps_hook_ref_work_queue(modem), TREQ_NETWORK_SEARCH) ||
407                                     ps_util_peek_waiting_job(_ps_hook_ref_work_queue(modem), TREQ_NETWORK_SET_CANCEL_MANUAL_SEARCH) ||
408                                     ps_util_peek_waiting_job(_ps_hook_ref_work_queue(modem), TREQ_NETWORK_SET_PLMN_SELECTION_MODE)) {
409                                         GHashTableIter iter;
410                                         gpointer key, tmp_service;
411
412                                         ps_info_ex_modem(modem, "Network search/selection/cancel searchrequest is in queue");
413                                         g_hash_table_iter_init(&iter, modem->services);
414                                         while (g_hash_table_iter_next(&iter, &key, &tmp_service) == TRUE)
415                                                 _ps_service_disconnect_internet_mms_tethering_contexts(tmp_service);
416                                 } else
417 #endif
418                                 {
419                                         rv = tcore_ps_deactivate_contexts(co_ps);
420                                         if (rv != TCORE_RETURN_SUCCESS) {
421                                                 ps_dbg_ex_modem(modem, "fail to deactivation");
422                                                 return TCORE_HOOK_RETURN_CONTINUE;
423                                         }
424                                 }
425                         }
426                 }
427         } else if (cstatus->state == PS_CALL_STATE_RESULT_NO_CARRIER) { /* DISCONNECTED-NO CARRIER */
428                 __on_hook_status_NO_carrier(modem, service, co_ps, cstatus);
429         } /* disconnected case */
430
431         return TCORE_HOOK_RETURN_CONTINUE;
432 }
433
434 static enum tcore_hook_return __on_hook_dedicated_bearerinfo(Server *s, CoreObject *source,
435                                                              enum tcore_notification_command command, unsigned int data_len, void *data,
436                                                              void *user_data)
437 {
438         ps_service_t *service = user_data;
439         CoreObject *co_ps = NULL;
440         struct tnoti_ps_dedicated_bearer_info *bearer_info = data;
441
442         g_return_val_if_fail(service != NULL, TCORE_HOOK_RETURN_CONTINUE);
443
444         co_ps = _ps_service_ref_co_ps(service);
445         if (co_ps != source)
446                 return TCORE_HOOK_RETURN_CONTINUE;
447
448         _ps_service_set_context_bearerinfo(service, bearer_info);
449         ps_info_ex_svc(service, "dedicated bearer information event");
450         return TCORE_HOOK_RETURN_CONTINUE;
451 }
452
453 static enum tcore_hook_return __on_hook_default_data_subscription(Server *s, CoreObject *source,
454                                                                   enum tcore_notification_command command, unsigned int data_len, void *data,
455                                                                   void *user_data)
456 {
457         ps_service_t *service = user_data;
458         const struct tnoti_network_default_data_subs *default_data_subs_info = data;
459
460         if (default_data_subs_info->default_subs != (enum telephony_network_default_data_subs)tcore_object_ref_subscription_type(_ps_service_ref_co_ps(service)))
461                 return TCORE_HOOK_RETURN_CONTINUE;
462
463         ps_info_ex_svc(service, "'default' data subscription information event");
464         _ps_service_connect_default_context(service);
465
466         return TCORE_HOOK_RETURN_CONTINUE;
467 }
468 static enum tcore_hook_return __on_hook_epdg_status(Server *s, CoreObject *source,
469                                                     enum tcore_notification_command command, unsigned int data_len, void *data,
470                                                     void *user_data)
471 {
472         ps_service_t *service = user_data;
473         const struct tnoti_network_epdg_status *noti = (const struct tnoti_network_epdg_status *)data;
474         gboolean available = FALSE;
475
476         g_return_val_if_fail(service != NULL, TCORE_HOOK_RETURN_CONTINUE);
477         g_return_val_if_fail(noti != NULL, TCORE_HOOK_RETURN_CONTINUE);
478
479         if ((noti->status == NETWORK_EPDG_STATUS_AVAILABLE) ||
480                 (noti->status == NETWORK_EPDG_STATUS_CONNECTED) ||
481                 (noti->status == NETWORK_EPDG_STATUS_HO_LTE_TO_IWLAN)) {
482                 available = TRUE;
483         }
484
485         ps_info_ex_svc(service, "ePDG: [%s]", ((available == TRUE) ? "AVAILABLE" : "UNAVAILABLE"));
486         _ps_service_set_epdg_status(service, available);
487
488         if (noti->status == NETWORK_EPDG_STATUS_HO_LTE_TO_IWLAN)
489                 _ps_service_set_epdg_ip_configuration(service, noti->cid, noti->ipv4_address, noti->ipv6_address);
490         return TCORE_HOOK_RETURN_CONTINUE;
491 }
492
493 static enum tcore_hook_return __on_hook_ipconfiguration(Server *s, CoreObject *source,
494                                                         enum tcore_notification_command command, unsigned int data_len, void *data,
495                                                         void *user_data)
496 {
497         ps_service_t *service = user_data;
498         CoreObject *co_ps = NULL;
499         struct tnoti_ps_pdp_ipconfiguration *devinfo = data;
500         char ipv4[16], ipv4_dns_1[16], ipv4_dns_2[16];
501
502         g_return_val_if_fail(service != NULL, TCORE_HOOK_RETURN_STOP_PROPAGATION);
503
504         co_ps = _ps_service_ref_co_ps(service);
505         if (co_ps != source) {
506                 ps_warn_ex_svc(service, "Received notification for different Subscription - neglecting the notification!!!");
507                 return TCORE_HOOK_RETURN_CONTINUE;
508         }
509
510         ps_info_ex_svc(service, "ip configuration event");
511
512         /*
513          * In case IPv4 address is available and DNS address
514          * is NOT available, set -
515          * DNS 1 - Google DNS
516          * DNS 2 - Open DNS
517          */
518         snprintf(ipv4, 16, "%d.%d.%d.%d",
519                  devinfo->ip_address[0], devinfo->ip_address[1],
520                  devinfo->ip_address[2], devinfo->ip_address[3]);
521         if (!g_str_equal(ipv4, "0.0.0.0")) {
522                 snprintf(ipv4_dns_1, 16, "%d.%d.%d.%d",
523                          devinfo->primary_dns[0], devinfo->primary_dns[1],
524                          devinfo->primary_dns[2], devinfo->primary_dns[3]);
525                 if (g_str_equal(ipv4_dns_1, "0.0.0.0")) {
526                         ps_err_ex_svc(service, "[IPV4]primary dns address is 0");
527
528                         /* google dns 1st */
529                         devinfo->primary_dns[0] = 8;
530                         devinfo->primary_dns[1] = 8;
531                         devinfo->primary_dns[2] = 8;
532                         devinfo->primary_dns[3] = 8;
533                 }
534
535                 snprintf(ipv4_dns_2, 16, "%d.%d.%d.%d",
536                          devinfo->secondary_dns[0], devinfo->secondary_dns[1],
537                          devinfo->secondary_dns[2], devinfo->secondary_dns[3]);
538                 if (g_str_equal(ipv4_dns_2, "0.0.0.0")) {
539                         /* open dns 2nd */
540                         ps_err_ex_svc(service, "[IPV4]secondary dns address is 0");
541                         devinfo->secondary_dns[0] = 208;
542                         devinfo->secondary_dns[1] = 67;
543                         devinfo->secondary_dns[2] = 222;
544                         devinfo->secondary_dns[3] = 222;
545                 }
546         }
547
548         /*
549          * In case IPv6 address is available and DNS address
550          * is NOT available, set -
551          * DNS 1 - Google DNS
552          * DNS 2 - Open DNS
553          */
554         if (devinfo->ipv6_address != NULL) {
555                 if (devinfo->ipv6_primary_dns == NULL) {
556                         ps_err_ex_svc(service, "[IPV6]primary dns address is 0");
557                         devinfo->ipv6_primary_dns = g_strdup("2001:4860:4860::8888");
558
559                 }
560                 if (devinfo->ipv6_secondary_dns == NULL) {
561                         ps_err_ex_svc(service, "[IPV6]secondary dns address is 0");
562                         devinfo->ipv6_secondary_dns = g_strdup("2620:0:ccc::2");
563                 }
564         }
565
566         _ps_service_set_context_devinfo(service, devinfo);
567
568         return TCORE_HOOK_RETURN_CONTINUE;
569 }
570
571 static enum tcore_hook_return __on_hook_powered(Server *s, CoreObject *source,
572                                                 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
573 {
574         ps_modem_t *modem = user_data;
575         CoreObject *co_modem;
576         struct tnoti_modem_power *modem_power = data;
577         int power = PS_MODEM_STATE_UNKNOWN;
578
579         CORE_OBJECT_CHECK_RETURN(source, CORE_OBJECT_TYPE_MODEM, TCORE_HOOK_RETURN_CONTINUE);
580
581         g_return_val_if_fail(modem != NULL, TCORE_HOOK_RETURN_CONTINUE);
582         g_return_val_if_fail(modem_power != NULL, TCORE_HOOK_RETURN_CONTINUE);
583
584         co_modem = _ps_modem_ref_co_modem(modem);
585         if (co_modem != source) {
586                 ps_dbg_ex_modem(modem, "Notification for other modem!");
587                 return TCORE_HOOK_RETURN_CONTINUE;
588         }
589
590         ps_info_ex_modem(modem, "powered event called: state [%d]", modem_power->state);
591
592         switch (modem_power->state) {
593         case MODEM_STATE_ONLINE:
594                 power = PS_MODEM_STATE_ONLINE;
595                 break;
596
597         case MODEM_STATE_LOW:
598                 power = PS_MODEM_STATE_LOW;
599                 break;
600
601         case MODEM_STATE_ERROR:
602         case MODEM_STATE_RESET:
603                 /* Reset hook flag in any present */
604                 __ps_modem_cp_reset_handler(modem);
605                 break;
606
607         default:
608                 ps_warn_ex_modem(modem, "Unhandled modem power event.");
609                 break;
610         }
611
612         if (power != PS_MODEM_STATE_UNKNOWN)
613                 _ps_modem_processing_power_enable(modem, power);
614
615         return TCORE_HOOK_RETURN_CONTINUE;
616 }
617
618 static enum tcore_hook_return __on_hook_flight(Server *s, CoreObject *source,
619                                                enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
620 {
621         ps_modem_t *modem = user_data;
622         struct tnoti_modem_flight_mode *modem_flight = data;
623
624         g_return_val_if_fail(modem != NULL, TCORE_HOOK_RETURN_CONTINUE);
625         ps_info_ex_modem(modem, "flight mode event called");
626
627         _ps_modem_processing_flight_mode(modem, modem_flight->enable);
628
629         return TCORE_HOOK_RETURN_CONTINUE;
630 }
631
632 static enum tcore_hook_return __on_hook_net_register(Server *s, CoreObject *source,
633                                                      enum tcore_notification_command command, unsigned int data_len, void *data,
634                                                      void *user_data)
635 {
636         ps_service_t *service = user_data;
637         gboolean ps_attached = FALSE;
638         struct tnoti_network_registration_status *regist_status = data;
639         CoreObject *co_network;
640
641         g_return_val_if_fail(service != NULL, TCORE_HOOK_RETURN_CONTINUE);
642
643         co_network = _ps_service_ref_co_network(service);
644         if (co_network != source)
645                 return TCORE_HOOK_RETURN_CONTINUE;
646
647         if (regist_status->ps_domain_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL)
648                 ps_attached = TRUE;
649
650         _ps_modem_set_roaming(_ps_service_ref_modem(service), regist_status->roaming_status);
651         _ps_service_processing_network_event(service, ps_attached, regist_status->roaming_status);
652
653         return TCORE_HOOK_RETURN_CONTINUE;
654 }
655
656 static enum tcore_hook_return __on_hook_net_change(Server *s, CoreObject *source,
657                                                    enum tcore_notification_command command, unsigned int data_len, void *data,
658                                                    void *user_data)
659 {
660         ps_service_t *service = user_data;
661         struct tnoti_network_change *network_change = data;
662         CoreObject *co_network;
663
664         g_return_val_if_fail(service != NULL, TCORE_HOOK_RETURN_CONTINUE);
665
666         co_network = _ps_service_ref_co_network(service);
667         if (co_network != source)
668                 return TCORE_HOOK_RETURN_CONTINUE;
669
670         ps_dbg_ex_svc(service, "plmn(%s) act(%d)", network_change->plmn, network_change->act);
671         _ps_service_set_access_technology(service, network_change->act);
672
673         return TCORE_HOOK_RETURN_CONTINUE;
674 }
675
676 static enum tcore_hook_return __on_hook_net_restricted_state(Server *s, CoreObject *source,
677                                                              enum tcore_notification_command command, unsigned int data_len, void *data,
678                                                              void *user_data)
679 {
680         ps_service_t *service = user_data;
681         struct tnoti_network_restricted_state *network_restricted = data;
682         CoreObject *co_network;
683
684         g_return_val_if_fail(service != NULL, TCORE_HOOK_RETURN_CONTINUE);
685
686         co_network = _ps_service_ref_co_network(service);
687         if (co_network != source)
688                 return TCORE_HOOK_RETURN_CONTINUE;
689
690         ps_dbg_ex_svc(service, "network restricted state(%d)", network_restricted->restricted_state);
691         _ps_service_set_restricted(service, ((network_restricted->restricted_state & NETWORK_RESTRICTED_STATE_PS_ALL) ? TRUE : FALSE));
692
693         return TCORE_HOOK_RETURN_CONTINUE;
694 }
695
696 static enum tcore_hook_return __on_hook_sim_init(Server *s, CoreObject *source,
697                                                  enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
698 {
699         struct tnoti_sim_status *sim_data = data;
700         ps_modem_t *modem = user_data;
701         const gchar *cp_name, *source_cp_name;
702
703         ps_info_ex_modem(modem, "sim init event called");
704
705         g_return_val_if_fail(modem != NULL, TCORE_HOOK_RETURN_CONTINUE);
706
707         cp_name = _ps_modem_ref_cp_name(modem);
708         source_cp_name = tcore_server_get_cp_name_by_plugin(tcore_object_ref_plugin(source));
709         if (g_strcmp0(cp_name, source_cp_name) != 0) {
710                 ps_dbg_ex_modem(modem, "Received notification for different Subscription - neglecting the notification!!!");
711                 return TCORE_HOOK_RETURN_CONTINUE;
712         }
713
714         ps_info_ex_modem(modem, "sim status is (%d)", sim_data->sim_status);
715
716         switch (sim_data->sim_status) {
717         case SIM_STATUS_INITIALIZING:
718                 break;
719
720         case SIM_STATUS_INIT_COMPLETED: {
721                 struct tel_sim_imsi *sim_imsi = NULL;
722                 enum tel_sim_type sim_type = SIM_TYPE_UNKNOWN;
723                 sim_type = tcore_sim_get_type(source);
724
725                 if (sim_type == SIM_TYPE_NVSIM) {
726                         ps_info_ex_modem(modem, "initial boot from CDMA network.");
727                         _ps_modem_processing_sim_complete(modem, TRUE, PS_CDMA_DUMMY_PROFILE_PLMN);
728                 } else {
729                         sim_imsi = tcore_sim_get_imsi(source);
730                         _ps_modem_processing_sim_complete(modem, TRUE, sim_imsi->plmn);
731                         g_free(sim_imsi);
732                 }
733         }
734         break;
735
736         case SIM_STATUS_CARD_ERROR: /* FALLTHROUGH */
737         case SIM_STATUS_CARD_REMOVED: /* FALLTHROUGH */
738         case SIM_STATUS_CARD_CRASHED: /* FALLTHROUGH */
739         case SIM_STATUS_CARD_POWEROFF:
740                 /* Set SIM complete FALSE, operator is not required */
741                 _ps_modem_processing_sim_complete(modem, FALSE, NULL);
742                 _ps_modem_processing_no_sim(modem);
743                 break;
744
745         case SIM_STATUS_CARD_NOT_PRESENT:
746                 _ps_modem_processing_no_sim(modem);
747                 break;
748
749         default:
750                 ps_dbg_ex_modem(modem, "Unhandled SIM state: [%d]", sim_data->sim_status);
751                 _ps_modem_processing_no_sim(modem);
752                 break;
753         }
754
755         return TCORE_HOOK_RETURN_CONTINUE;
756 }
757
758
759 #ifdef TIZEN_SUPPORT_VOLTE
760 static enum tcore_hook_return __on_hook_sim_refresh(Server *s, CoreObject *source,
761                                                     enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
762 {
763         struct tnoti_sim_refresh_stage *sim_data = data;
764         ps_modem_t *modem = user_data;
765
766         ps_info_ex_modem(modem, "sim stage is (%d)", sim_data->stage);
767
768         if (sim_data->stage == SIM_REFRESH_START)
769                 _ps_modem_processing_sim_refresh(modem);
770         return TCORE_HOOK_RETURN_CONTINUE;
771 }
772 #endif
773
774 enum tcore_hook_return __on_hook_modem_added(Server *s,
775                                              CoreObject *source, enum tcore_notification_command command,
776                                              unsigned int data_len, void *data, void *user_data)
777 {
778         ps_master_t *master = user_data;
779         TcorePlugin *plg = data;
780
781         if (FALSE == _ps_master_create_modems(master, plg))
782                 err("[%s] Failed to create modem", tcore_server_get_cp_name_by_plugin(plg));
783
784         return TCORE_HOOK_RETURN_CONTINUE;
785 }
786
787 enum tcore_hook_return __on_hook_modem_removed(Server *s,
788                                                CoreObject *source, enum tcore_notification_command command,
789                                                unsigned int data_len, void *data, void *user_data)
790 {
791         ps_master_t *master = user_data;
792         TcorePlugin *plg = data;
793
794         if (FALSE == _ps_master_destroy_modem(master, plg))
795                 err("Failed to destroy modem[%s]", tcore_server_get_cp_name_by_plugin(plg));
796
797         return TCORE_HOOK_RETURN_CONTINUE;
798 }
799
800 gboolean _ps_get_co_modem_values(ps_modem_t *modem)
801 {
802         TcorePlugin *plg;
803         CoreObject *co_modem = NULL;
804         CoreObject *co_sim = NULL;
805         ps_modem_t *ps_modem = modem;
806
807         gboolean sim_init = FALSE, flight_mode = FALSE;
808         enum modem_state modem_power_state = MODEM_STATE_UNKNOWN;
809         int sim_status = 0;
810         enum tel_sim_type sim_type = SIM_TYPE_UNKNOWN;
811         struct tel_sim_imsi *sim_imsi = NULL;
812         int power = PS_MODEM_STATE_UNKNOWN;
813
814         g_return_val_if_fail(ps_modem != NULL, FALSE);
815
816         co_modem = _ps_modem_ref_co_modem(ps_modem);
817         if (!co_modem)
818                 return FALSE;
819
820         plg = tcore_object_ref_plugin(co_modem);
821         if (!plg)
822                 return FALSE;
823
824         co_sim = tcore_plugin_ref_core_object(plg, CORE_OBJECT_TYPE_SIM);
825
826         sim_status = tcore_sim_get_status(co_sim);
827         if (sim_status == SIM_STATUS_INIT_COMPLETED)
828                 sim_init = TRUE;
829
830         sim_imsi = tcore_sim_get_imsi(co_sim);
831         flight_mode = tcore_modem_get_flight_mode_state(co_modem);
832         tcore_modem_get_modem_power_state(co_modem, &modem_power_state);
833
834         switch (modem_power_state) {
835         case MODEM_STATE_ONLINE:
836                 power = PS_MODEM_STATE_ONLINE;
837                 break;
838
839         case MODEM_STATE_LOW:
840                 power = PS_MODEM_STATE_LOW;
841                 break;
842
843         case MODEM_STATE_ERROR:
844         case MODEM_STATE_RESET:
845         default:
846                 ps_warn_ex_modem(modem, "Unhandled modem power event.");
847                 break;
848         }
849
850         _ps_modem_processing_flight_mode(ps_modem, flight_mode);
851         if (power != PS_MODEM_STATE_UNKNOWN)
852                 _ps_modem_processing_power_enable(modem, power);
853
854         sim_type = tcore_sim_get_type(co_sim);
855
856         if (sim_type == SIM_TYPE_NVSIM)
857                 _ps_modem_processing_sim_complete(ps_modem, sim_init, PS_CDMA_DUMMY_PROFILE_PLMN);
858         else
859                 _ps_modem_processing_sim_complete(ps_modem, sim_init, sim_imsi->plmn);
860         g_free(sim_imsi);
861         return TRUE;
862 }
863
864 gboolean _ps_get_co_network_values(ps_service_t *service)
865 {
866         CoreObject *co_network = NULL;
867         gboolean ps_attached = FALSE;
868         gint ps_restricted = 0;
869
870         enum telephony_network_service_domain_status ps_status;
871         enum telephony_network_access_technology act;
872
873         g_return_val_if_fail(service != NULL, FALSE);
874
875         co_network = _ps_service_ref_co_network(service);
876         ps_dbg_ex_svc(service, "Entered ");
877
878         tcore_network_get_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, &ps_status);
879         tcore_network_get_access_technology(co_network, &act);
880
881         if (ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL)
882                 ps_attached = TRUE;
883
884         ps_restricted = tcore_network_get_restricted_state(co_network);
885
886         _ps_service_set_restricted(service, ((ps_restricted == NETWORK_RESTRICTED_STATE_PS_ALL) ? TRUE : FALSE));
887         _ps_service_set_roaming(service, tcore_network_get_roaming_state(co_network));
888         _ps_service_set_ps_attached(service, ps_attached);
889         _ps_service_set_access_technology(service, act);
890
891         return TRUE;
892 }
893
894 gboolean _ps_add_co_ps_event(ps_service_t *service)
895 {
896         Server *s;
897         g_return_val_if_fail(service != NULL, FALSE);
898         ps_dbg_ex_svc(service, "Entered ");
899         s = tcore_plugin_ref_server(_ps_service_ref_plugin(service));
900         tcore_server_add_notification_hook(s, TNOTI_PS_CALL_STATUS, __on_hook_call_status, service);
901         tcore_server_add_notification_hook(s, TNOTI_PS_PDP_IPCONFIGURATION, __on_hook_ipconfiguration, service);
902         tcore_server_add_notification_hook(s, TNOTI_PS_DEDICATED_BEARER_INFO, __on_hook_dedicated_bearerinfo, service);
903         tcore_server_add_notification_hook(s, TNOTI_NETWORK_DEFAULT_DATA_SUBSCRIPTION, __on_hook_default_data_subscription, service);
904 //      tcore_server_add_notification_hook(s, TNOTI_PS_GPRS_BACKOFF_TIMER, __on_hook_gprs_backoff_timer, service);
905 //      tcore_server_add_notification_hook(s, TNOTI_PS_GPRS_NAS_TIMER, __on_hook_gprs_nas_timer, service);
906         tcore_server_add_notification_hook(s, TNOTI_NETWORK_EPDG_STATUS, __on_hook_epdg_status, service);
907         tcore_object_add_callback(_ps_service_ref_co_ps(service), CORE_OBJECT_EVENT_PROPERTY_CHANGED, __ps_on_prop_changed, service);
908         return TRUE;
909 }
910
911 gboolean _ps_add_co_network_event(ps_service_t *service)
912 {
913         Server *s;
914
915         g_return_val_if_fail(service != NULL, FALSE);
916
917         s = tcore_plugin_ref_server(_ps_service_ref_plugin(service));
918
919         tcore_server_add_notification_hook(s, TNOTI_NETWORK_REGISTRATION_STATUS, __on_hook_net_register, service);
920         tcore_server_add_notification_hook(s, TNOTI_NETWORK_CHANGE, __on_hook_net_change, service);
921         tcore_server_add_notification_hook(s, TNOTI_NETWORK_RESTRICTED_STATE, __on_hook_net_restricted_state, service);
922
923         return TRUE;
924 }
925
926 gboolean _ps_add_co_modem_event(ps_modem_t *modem)
927 {
928         Server *s = NULL;
929
930         g_return_val_if_fail(modem != NULL, FALSE);
931
932         s = tcore_plugin_ref_server(_ps_modem_ref_plugin(modem));
933
934         tcore_server_add_notification_hook(s, TNOTI_MODEM_POWER, __on_hook_powered, modem);
935         tcore_server_add_notification_hook(s, TNOTI_MODEM_FLIGHT_MODE, __on_hook_flight, modem);
936         tcore_server_add_notification_hook(s, TNOTI_SIM_STATUS, __on_hook_sim_init, modem);
937 //      tcore_server_add_notification_hook(s, TNOTI_SIM_REFRESH_STAGE, __on_hook_sim_refresh, modem);
938 #ifdef TIZEN_SUPPORT_REQUEST_HOOK_PDP_CONTROL
939         _ps_hook_add_modem_hooks(modem);
940 #endif
941         return TRUE;
942 }
943
944 gboolean _ps_free_co_ps_event(ps_service_t *service)
945 {
946         Server *s;
947         g_return_val_if_fail(service != NULL, FALSE);
948         ps_dbg_ex_svc(service, "Entered ");
949         s = tcore_plugin_ref_server(_ps_service_ref_plugin(service));
950         tcore_object_del_callback(_ps_service_ref_co_ps(service), CORE_OBJECT_EVENT_PROPERTY_CHANGED, __ps_on_prop_changed);
951         tcore_server_remove_notification_hook(s, __on_hook_call_status);
952         tcore_server_remove_notification_hook(s, __on_hook_ipconfiguration);
953         tcore_server_remove_notification_hook(s, __on_hook_dedicated_bearerinfo);
954         tcore_server_remove_notification_hook(s, __on_hook_default_data_subscription);
955 //      tcore_server_remove_notification_hook(s, __on_hook_gprs_backoff_timer);
956 //      tcore_server_remove_notification_hook(s, __on_hook_gprs_nas_timer);
957         tcore_server_remove_notification_hook(s, __on_hook_epdg_status);
958         return TRUE;
959 }
960
961 gboolean _ps_free_co_network_event(ps_service_t *service)
962 {
963         Server *s;
964         g_return_val_if_fail(service != NULL, FALSE);
965         ps_dbg_ex_svc(service, "Entered");
966         s = tcore_plugin_ref_server(_ps_service_ref_plugin(service));
967         tcore_server_remove_notification_hook(s, __on_hook_net_register);
968         tcore_server_remove_notification_hook(s, __on_hook_net_change);
969         tcore_server_remove_notification_hook(s, __on_hook_net_restricted_state);
970         return TRUE;
971 }
972
973 gboolean _ps_free_co_modem_event(ps_modem_t *modem)
974 {
975         Server *s;
976         g_return_val_if_fail(modem != NULL, FALSE);
977         s = tcore_plugin_ref_server(_ps_modem_ref_plugin(modem));
978         tcore_server_remove_notification_hook(s, __on_hook_powered);
979         tcore_server_remove_notification_hook(s, __on_hook_flight);
980         tcore_server_remove_notification_hook(s, __on_hook_sim_init);
981 //      tcore_server_remove_notification_hook(s, __on_hook_sim_refresh);
982         return TRUE;
983 }
984
985 gboolean _ps_update_cellular_state_key(ps_service_t *service)
986 {
987         int current_state = 0;
988         int stored_state = 0;
989         ps_modem_t *modem;
990         ps_master_t *master;
991         ps_subs_type subs_type;
992         int selected_sim = -1;
993
994         g_return_val_if_fail(service != NULL, FALSE);
995
996         modem = _ps_service_ref_modem(service);
997         master = _ps_modem_ref_master(modem);
998         subs_type = _ps_modem_get_subs_type(modem);
999
1000         ps_dbg_ex_svc(service, "Update cellular state for [SIM%d]", subs_type + 1);
1001
1002         selected_sim = _ps_master_get_storage_value_int(master, STORAGE_KEY_TELEPHONY_DUALSIM_DEFAULT_DATA_SERVICE_INT);
1003         if ((selected_sim != -1) && (selected_sim != (int)subs_type)) {
1004                 ps_warn_ex_svc(service, "Update for only [SIM%d] selected by Setting", selected_sim + 1);
1005                 return FALSE;
1006         }
1007
1008         current_state = _ps_service_check_cellular_state(service);
1009
1010         if (tcore_modem_get_flight_mode_state(modem->co_modem) == TRUE)
1011                 current_state = TELEPHONY_PS_FLIGHT_MODE;
1012
1013         stored_state = _ps_master_get_storage_value_int(master, STORAGE_KEY_CELLULAR_STATE);
1014         if (current_state != stored_state) {
1015                 ps_info_ex_svc(service, "Cellular state, current: [%d], stored: [%d]", current_state, stored_state);
1016                 _ps_master_set_storage_value_int(master, STORAGE_KEY_CELLULAR_STATE, current_state);
1017         }
1018
1019         return TRUE;
1020 }