Fix VCONFKEY_NETWORK_CELLULAR key to be set when PS connect
[platform/core/telephony/tel-plugin-packetservice.git] / src / service.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-service.h"
23
24 #include "ps.h"
25 #include "ps-error.h"
26
27 #include <core_object.h>
28 #include <co_ps.h>
29
30 #define PROP_DEFAULT    FALSE
31 #define PROP_DEFAULT_STR   NULL
32 #define BOOL2STRING(a)  ((a==TRUE) ? ("TRUE"):("FALSE"))
33
34 #define TIMEOUT_DEFAULT         5
35 #define TIMEOUT_MAX                     1280
36
37 guint connection_timeout;
38 guint timer_src;
39
40 /*Properties*/
41
42 enum {
43         PROP_SERVICE_O,
44
45         PROP_SERVICE_PATH,
46         PROP_SERVICE_PLUGIN,
47         PROP_SERVICE_CONN,
48         PROP_SERVICE_P_MODEM,
49         PROP_SERVICE_CO_NETWORK,
50         PROP_SERVICE_CO_PS
51 };
52
53 enum {
54         SIG_SERVICE_CONTEXT_ADDED,
55         SIG_SERVICE_CONTEXT_REMOVED,
56         SIG_SERVICE_PROPERTY_CHANGED,
57         SIG_SERVICE_LAST
58 };
59
60 static guint32 signals[SIG_SERVICE_LAST] = {0,};
61
62 struct PsServiceClass {
63         GObjectClass parent;
64
65         //method and signals
66         void (*context_added)(PsService *service, gchar *context_path);
67         void (*context_removed)(PsService *service, gchar *context_path);
68         void (*property_changed)(PsService *service, GHashTable *service_property);
69 };
70
71 struct PsService {
72         GObject parent;
73
74         gchar *path;
75         TcorePlugin *plg;
76         DBusGConnection *conn;
77         gpointer p_modem;
78         CoreObject *co_network;
79         CoreObject *co_ps;
80
81         gboolean ps_attached;
82         gboolean roaming;
83         enum telephony_network_access_technology act;
84
85         GHashTable *contexts;
86 };
87
88 G_DEFINE_TYPE(PsService, ps_service, G_TYPE_OBJECT);
89
90 /*Function Declaration*/
91 static void __ps_service_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
92 static void __ps_service_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
93
94 gboolean ps_iface_service_get_properties(PsService *service, DBusGMethodInvocation *context);
95 gboolean ps_iface_service_get_contexts(PsService *service, DBusGMethodInvocation *context);
96
97 static void __ps_service_emit_property_changed_signal(PsService *service);
98 static void __ps_service_emit_context_added_signal(PsService *service, gpointer context);
99 static void __ps_service_emit_context_removed_signal(PsService *service, gpointer context);
100
101 static void __remove_context(gpointer data);
102 static char *__ps_service_act2string(enum telephony_network_access_technology act);
103 static gboolean __ps_service_check_connection_option(gpointer service);
104 static gboolean __ps_service_connetion_timeout_handler(gpointer user_data);
105
106 #include "ps-iface-service-glue.h"
107
108 static void ps_service_init(PsService *service)
109 {
110         dbg("service initialize");
111
112         service->path = PROP_DEFAULT_STR;
113         service->plg = NULL;
114         service->conn = NULL;
115         service->p_modem = NULL;
116         service->co_network = NULL;
117         service->co_ps = NULL;
118
119         service->ps_attached = PROP_DEFAULT;
120         service->roaming = PROP_DEFAULT;
121         service->act = NETWORK_ACT_UNKNOWN;
122
123         service->contexts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, __remove_context);
124         return;
125 }
126
127 static void ps_service_class_init(PsServiceClass *klass)
128 {
129         GObjectClass *object_class = G_OBJECT_CLASS(klass);
130
131         //class init
132         dbg("class init");
133
134         object_class->get_property = __ps_service_get_property;
135         object_class->set_property = __ps_service_set_property;
136
137         //dbus register
138         dbus_g_object_type_install_info(PS_TYPE_SERVICE, &dbus_glib_ps_iface_service_object_info);
139
140         //add properties
141         g_object_class_install_property(
142                         object_class,
143                         PROP_SERVICE_PATH,
144                         g_param_spec_string("path", "PATH", "Technology Path", NULL,
145                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
146
147         g_object_class_install_property(
148                         object_class,
149                         PROP_SERVICE_P_MODEM,
150                         g_param_spec_pointer("p_modem", "MODEM", "Parent Modem Object",
151                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
152
153         g_object_class_install_property(
154                         object_class,
155                         PROP_SERVICE_PLUGIN,
156                         g_param_spec_pointer("plg", "PLUGIN", "Plug in Object",
157                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
158
159         g_object_class_install_property(
160                         object_class,
161                         PROP_SERVICE_CO_NETWORK,
162                         g_param_spec_pointer("co_network", "COREOBJECT NETWORK", "CoreObject of Network",
163                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
164
165         g_object_class_install_property(
166                         object_class,
167                         PROP_SERVICE_CO_PS,
168                         g_param_spec_pointer("co_ps", "COREOBJECTPS", "CoreObject of PS",
169                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
170
171         g_object_class_install_property(
172                         object_class,
173                         PROP_SERVICE_CONN,
174                         g_param_spec_boxed("conn", "CONNECTION", "DBus connection", DBUS_TYPE_G_CONNECTION,
175                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
176
177         //add signal handler
178         signals[SIG_SERVICE_CONTEXT_ADDED] = g_signal_new("context-added", G_OBJECT_CLASS_TYPE(klass),
179                         G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(PsServiceClass, context_added), NULL, NULL,
180                         g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_STRING_STRING_HASHTABLE);
181
182         signals[SIG_SERVICE_CONTEXT_REMOVED] = g_signal_new("context-removed",
183                         G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_LAST,
184                         G_STRUCT_OFFSET(PsServiceClass, context_removed), NULL, NULL,
185                         g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, DBUS_TYPE_G_OBJECT_PATH);
186
187         signals[SIG_SERVICE_PROPERTY_CHANGED] = g_signal_new("property-changed",
188                         G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_LAST,
189                         G_STRUCT_OFFSET(PsServiceClass, property_changed), NULL, NULL,
190                         g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_STRING_STRING_HASHTABLE);
191
192         return;
193 }
194
195 static void __ps_service_get_property(GObject *object, guint prop_id, GValue *value,
196                 GParamSpec *pspec)
197 {
198         return;
199 }
200
201 static void __ps_service_set_property(GObject *object, guint prop_id, const GValue *value,
202                 GParamSpec *pspec)
203 {
204         PsService *service = PS_SERVICE(object);
205
206         switch (prop_id) {
207                 case PROP_SERVICE_PATH: {
208                         if (service->path) g_free(service->path);
209                         service->path = g_value_dup_string(value);
210                         msg("service(%p) set path(%s)", service, service->path);
211                 }
212                         break;
213                 case PROP_SERVICE_P_MODEM: {
214                         service->p_modem = g_value_get_pointer(value);
215                         msg("service(%p) set modem(%p)", service, service->p_modem);
216                 }
217                         break;
218                 case PROP_SERVICE_PLUGIN: {
219                         service->plg = g_value_get_pointer(value);
220                         msg("service(%p) set plg(%p)", service, service->plg);
221                 }
222                         break;
223                 case PROP_SERVICE_CO_NETWORK: {
224                         service->co_network = g_value_get_pointer(value);
225                         msg("service(%p) set co_network(%p)", service, service->co_network);
226                 }
227                         break;
228                 case PROP_SERVICE_CO_PS: {
229                         service->co_ps = g_value_get_pointer(value);
230                         msg("service(%p) set co_ps(%p)", service, service->co_ps);
231                 }
232                         break;
233                 case PROP_SERVICE_CONN: {
234                         service->conn = g_value_get_boxed(value);
235                         msg("service(%p) set conn(%p)", service, service->conn);
236                 }
237                         break;
238                 default:
239                         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
240                         break;
241         } //swtich end
242
243         return;
244 }
245
246 gboolean ps_iface_service_get_properties(PsService *service, DBusGMethodInvocation *context)
247 {
248         GError *error = NULL;
249         gboolean rv = FALSE;
250         GHashTable *properties = NULL;
251
252         dbg("get service properties");
253
254         properties = g_hash_table_new(g_str_hash, g_str_equal);
255         rv = _ps_service_get_properties(service, properties);
256         if (rv != TRUE) {
257                 g_set_error(&error, PS_ERROR, PS_ERR_INTERNAL, "fail to get properties service(%p)",
258                                 service);
259                 dbus_g_method_return_error(context, error);
260                 g_hash_table_destroy(properties);
261                 return FALSE;
262         }
263
264         dbus_g_method_return(context, properties);
265         g_hash_table_destroy(properties);
266         return TRUE;
267 }
268
269 gboolean ps_iface_service_get_contexts(PsService *service, DBusGMethodInvocation *context)
270 {
271         GError *error = NULL;
272         GHashTableIter iter;
273         gpointer key, value;
274         GHashTable *contexts;
275
276         dbg("service get contexts interface");
277
278         if (service->contexts == NULL) {
279                 g_set_error(&error, PS_ERROR, PS_ERR_INTERNAL, "service(%p) does not have contexts",
280                                 service);
281                 dbus_g_method_return_error(context, error);
282                 return FALSE;
283         }
284
285         contexts = g_hash_table_new_full(g_direct_hash, g_str_equal, g_free,
286                         (GDestroyNotify) g_hash_table_destroy);
287
288         g_hash_table_iter_init(&iter, service->contexts);
289         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
290                 gboolean rv = FALSE;
291                 gchar *path = NULL;
292                 GHashTable *properties = NULL;
293
294                 properties = g_hash_table_new(g_str_hash, g_str_equal);
295                 rv = _ps_context_get_properties(value, properties);
296                 if (rv != TRUE) {
297                         g_set_error(&error, PS_ERROR, PS_ERR_INTERNAL, "fail to get properties context(%p)",
298                                         value);
299                         dbus_g_method_return_error(context, error);
300                         g_hash_table_destroy(properties);
301                         g_hash_table_destroy(contexts);
302                         return FALSE;
303                 }
304
305                 path = _ps_context_ref_path(value);
306                 g_hash_table_insert(contexts, g_strdup(path), properties);
307                 dbg("service (%p) inserted into hash", value);
308         }
309
310         dbus_g_method_return(context, contexts);
311         g_hash_table_destroy(contexts);
312
313         return TRUE;
314 }
315
316 static void __ps_service_emit_property_changed_signal(PsService *service)
317 {
318         GHashTable *properties = NULL;
319
320         properties = g_hash_table_new(g_str_hash, g_str_equal);
321         _ps_service_get_properties(service, properties);
322         g_signal_emit(service, signals[SIG_SERVICE_PROPERTY_CHANGED], 0, properties);
323         dbg("service (%p) emit property changed signal", service);
324         g_hash_table_destroy(properties);
325
326         return;
327 }
328
329 static void __ps_service_emit_context_added_signal(PsService *service, gpointer context)
330 {
331         GHashTable *properties = NULL;
332
333         properties = g_hash_table_new(g_str_hash, g_str_equal);
334         _ps_context_get_properties(context, properties);
335         g_signal_emit(service, signals[SIG_SERVICE_CONTEXT_ADDED], 0, properties);
336         dbg("service (%p) emit the context(%p) added signal", service, context);
337         g_hash_table_destroy(properties);
338         return;
339 }
340
341 static void __ps_service_emit_context_removed_signal(PsService *service, gpointer context)
342 {
343         g_signal_emit(service, signals[SIG_SERVICE_CONTEXT_REMOVED], 0, _ps_context_ref_path(context));
344         dbg("service (%p) emit the context(%p) removed signal", service, context);
345         return;
346 }
347
348 static void __remove_context(gpointer data)
349 {
350         return;
351 }
352
353 static char *__ps_service_act2string(enum telephony_network_access_technology act)
354 {
355         switch (act) {
356                 case NETWORK_ACT_GSM:
357                 case NETWORK_ACT_GPRS:
358                 case NETWORK_ACT_EGPRS:
359                 case NETWORK_ACT_UMTS:
360                 case NETWORK_ACT_GSM_UTRAN:
361                         return "GSM";
362                 case NETWORK_ACT_IS95A:
363                 case NETWORK_ACT_IS95B:
364                 case NETWORK_ACT_CDMA_1X:
365                 case NETWORK_ACT_EVDO_REV0:
366                 case NETWORK_ACT_CDMA_1X_EVDO_REV0:
367                 case NETWORK_ACT_EVDO_REVA:
368                 case NETWORK_ACT_CDMA_1X_EVDO_REVA:
369                 case NETWORK_ACT_EVDV:
370                         return "CDMA";
371                 case NETWORK_ACT_LTE:
372                         return "LTE";
373                 case NETWORK_ACT_UNKNOWN:
374                 default:
375                         return "unknown";
376         }
377
378         return NULL;
379 }
380
381 static gboolean __ps_service_check_connection_option(gpointer object)
382 {
383         gboolean b_connect = TRUE;
384         gboolean power, sim, data, flight;
385         PsService *service = object;
386
387         if(service->roaming){
388                 b_connect &=_ps_modem_get_data_roaming_allowed(service->p_modem);
389         }
390
391         power = _ps_modem_get_power(service->p_modem);
392         sim = _ps_modem_get_sim_init(service->p_modem);
393         data = _ps_modem_get_data_allowed(service->p_modem);
394         flight = _ps_modem_get_flght_mode(service->p_modem);
395         b_connect &= power;
396         b_connect &= sim;
397         b_connect &= data;
398         b_connect &= !flight;
399         dbg("power(%d), sim init(%d), data allowed(%d), flight mode(%d)", power, sim, data, flight);
400
401         return b_connect;
402 }
403
404 static gboolean __ps_service_connetion_timeout_handler(gpointer context)
405 {
406         int rv = 0;
407         PsService *service = NULL;
408
409         service = _ps_context_ref_service(context);
410         rv = _ps_service_activate_context(service, context);
411         dbg("return rv(%d)", rv);
412
413         return FALSE;
414 }
415
416 gpointer _ps_service_create_service(DBusGConnection *conn, TcorePlugin *p, gpointer p_modem,
417                 CoreObject *co_network, CoreObject *co_ps, gchar* path)
418 {
419         guint rv = 0;
420         GObject *object;
421         DBusGProxy *proxy;
422         GError *error = NULL;
423
424         dbg("Create SERVICE object - Path: [%s]", path);
425         g_return_val_if_fail(conn != NULL, NULL);
426         g_return_val_if_fail(p_modem != NULL, NULL);
427
428         /* Create new Proxy */
429         proxy = dbus_g_proxy_new_for_name(conn, "org.freedesktop.DBus", "/org/freedesktop/DBus",
430                         "org.freedesktop.DBus");
431
432         if (!dbus_g_proxy_call(proxy, "RequestName", &error, G_TYPE_STRING, PS_DBUS_SERVICE,
433                         G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &rv, G_TYPE_INVALID)) {
434                 err("Failed to acquire context(%s) error(%s)", PS_DBUS_SERVICE, error->message);
435                 return NULL;
436         }
437         dbg("Acquired context: [%s]", PS_DBUS_SERVICE);
438
439         /* Creating new Service object */
440         object = g_object_new(PS_TYPE_SERVICE, "conn", conn, "plg", p, "p_modem", p_modem, "co_network",
441                         co_network, "co_ps", co_ps, "path", path, NULL);
442
443         _ps_hook_co_network_event(object);
444         _ps_get_co_network_values(object);
445         _ps_hook_co_ps_event(object);
446
447         dbus_g_connection_register_g_object(conn, path, object);
448         msg("service(%p) register dbus path(%s)", object, path);
449
450         return object;
451 }
452
453 gboolean _ps_service_ref_context(gpointer object, gpointer context)
454 {
455         gpointer tmp = NULL;
456         gchar *s_path = NULL;
457         PsService *service = object;
458
459         dbg("service refer to context");
460         g_return_val_if_fail(service != NULL, FALSE);
461
462         s_path = _ps_context_ref_path(context);
463         tmp = g_hash_table_lookup(service->contexts, s_path);
464         if (tmp != NULL) {
465                 dbg("context(%p) already existed", tmp);
466                 return FALSE;
467         }
468
469         _ps_context_set_service(context, service);
470         tcore_ps_add_context(service->co_ps, (CoreObject *) _ps_context_ref_co_context(context));
471         g_hash_table_insert(service->contexts, g_strdup(s_path), context);
472
473         dbg("context(%p) insert to hash", context);
474         __ps_service_emit_context_added_signal(service, context);
475
476         //_ps_service_connect_default_context(service);
477         return TRUE;
478 }
479
480 gboolean _ps_service_ref_contexts(gpointer object, GHashTable *contexts, gchar *operator)
481 {
482         GHashTableIter iter;
483         gpointer key, value;
484         PsService *service = object;
485         gboolean ret = TRUE;
486         int rv;
487
488         dbg("Service refer to Contexts");
489
490         g_return_val_if_fail(service != NULL, FALSE);
491
492         g_hash_table_iter_init(&iter, contexts);
493         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
494                 gchar *s_path = NULL;
495                 gpointer tmp = NULL;
496                 gboolean f_awo = FALSE;
497
498                 s_path = _ps_context_ref_path(value);
499                 dbg("Path: [%s]", s_path);
500
501                 /* Hash lookup */
502                 tmp = g_hash_table_lookup(service->contexts, s_path);
503                 if (tmp != NULL) {
504                         dbg("context [0x%x] already existed", tmp);
505                         continue;
506                 }
507
508                 /* Setting service */
509                 _ps_context_set_service(value, service);
510
511                 /* Add Context to PS Core object */
512                 tcore_ps_add_context(service->co_ps, (CoreObject *)_ps_context_ref_co_context(value));
513
514                 /* Insert conetxt to Hash Table */
515                 g_hash_table_insert(service->contexts, g_strdup(s_path), value);
516
517                 dbg("Inserted context to Hash table - context [0x%x]", value);
518
519                 /* Emit Context added signal */
520                 __ps_service_emit_context_added_signal(service, value);
521
522                 f_awo = _ps_context_get_alwayson_enable(value);
523                 dbg("Always ON: [%s]", (f_awo ? "YES" : "NO"));
524                 if(f_awo) {
525                         dbg("Define Context");
526                         rv = _ps_service_define_context(service, value);
527                         dbg("return rv(%d)", rv);
528                 }
529         }
530
531         /* Update cellular state key */
532         _ps_update_cellular_state_key(service);
533         //_ps_service_connect_default_context(service);
534
535         return ret;
536 }
537
538 gboolean _ps_service_unref_context(gpointer object, gpointer context)
539 {
540         PsService *service = object;
541
542         dbg("service unref contexts");
543         g_return_val_if_fail(service != NULL, FALSE);
544         g_return_val_if_fail(context != NULL, FALSE);
545
546         dbg("remove context(%p) from service(%p)", context, service);
547         tcore_ps_remove_context(service->co_ps, (CoreObject *) _ps_context_ref_co_context(context));
548         g_hash_table_remove(service->contexts, _ps_context_ref_path(context));
549         __ps_service_emit_context_removed_signal(service, context);
550
551         return TRUE;
552 }
553
554 gboolean _ps_service_get_properties(gpointer object, GHashTable *properties)
555 {
556         PsService *service = object;
557
558         dbg("get service properties");
559         g_return_val_if_fail(service != NULL, FALSE);
560         g_return_val_if_fail(properties != NULL, FALSE);
561
562         g_hash_table_insert(properties, "path", g_strdup(service->path));
563         g_hash_table_insert(properties, "ps_attached", BOOL2STRING(service->ps_attached));
564         g_hash_table_insert(properties, "roaming", BOOL2STRING(service->roaming));
565         g_hash_table_insert(properties, "act", __ps_service_act2string(service->act));
566
567         return TRUE;
568 }
569
570 gchar* _ps_service_ref_path(gpointer object)
571 {
572         PsService *service = object;
573         g_return_val_if_fail(service != NULL, NULL);
574
575         return service->path;
576 }
577
578 gpointer _ps_service_ref_plugin(gpointer object)
579 {
580         PsService *service = object;
581         g_return_val_if_fail(service != NULL, NULL);
582
583         return service->plg;
584 }
585
586 gpointer _ps_service_ref_co_network(gpointer object)
587 {
588         PsService *service = object;
589         g_return_val_if_fail(service != NULL, NULL);
590
591         return service->co_network;
592 }
593
594 gpointer _ps_service_ref_co_ps(gpointer object)
595 {
596         PsService *service = object;
597         g_return_val_if_fail(service != NULL, NULL);
598
599         return service->co_ps;
600 }
601
602 gboolean _ps_service_set_context_info(gpointer object, struct tnoti_ps_pdp_ipconfiguration *devinfo)
603 {
604         GSList* contexts = NULL;
605         PsService *service = object;
606
607         dbg("Set context information");
608
609         g_return_val_if_fail(service != NULL, FALSE);
610
611         /* Refer context */
612         dbg("Context ID: [%d]", devinfo->context_id);
613         contexts = tcore_ps_ref_context_by_id(service->co_ps, devinfo->context_id);
614         if (NULL == contexts) {
615                 dbg("Failed to refer context");
616                 return FALSE;
617         }
618
619         for (; contexts != NULL; contexts = g_slist_next(contexts)) {
620                 CoreObject *co_context = NULL;
621
622                 co_context = contexts->data;
623                 if (NULL == co_context) {
624                         dbg("Context is NULL");
625                         continue;
626                 }
627
628                 /* Set device information */
629                 tcore_context_set_devinfo(co_context, devinfo);
630         }
631
632         return TRUE;
633 }
634
635 int _ps_service_define_context(gpointer object, gpointer context)
636 {
637         PsService *service = object;
638         CoreObject *co_context = NULL;
639         gboolean b_connect = TRUE;
640
641         dbg("define context(%p)", context);
642         g_return_val_if_fail(service != NULL, FALSE);
643
644         co_context = (CoreObject *)_ps_context_ref_co_context(context);
645
646         b_connect = __ps_service_check_connection_option(service);
647         if(!b_connect)
648                 return TCORE_RETURN_EPERM;
649
650         return tcore_ps_define_context(service->co_ps, co_context, NULL);
651 }
652
653 int _ps_service_activate_context(gpointer object, gpointer context)
654 {
655         PsService *service = object;
656         CoreObject *co_context = NULL;
657         gboolean b_connect = TRUE;
658         gboolean ps_defined;
659         int ret = TCORE_RETURN_FAILURE;
660
661         dbg("Activate context [0x%x]", context);
662         g_return_val_if_fail(service != NULL, TCORE_RETURN_EINVAL);
663
664         co_context = (CoreObject *)_ps_context_ref_co_context(context);
665
666         /* Check for connection option */
667         b_connect = __ps_service_check_connection_option(service);
668         dbg("Service option - PS Attached: [%s]", (service->ps_attached ? "YES" : "NO"));
669
670         b_connect &= service->ps_attached;
671         dbg("Connect: [%s]", (b_connect ? "YES" : "NO"));
672         if(!b_connect)
673                 return TCORE_RETURN_EPERM;
674
675         ps_defined = _ps_context_get_ps_defined(context);
676         if(!ps_defined) {
677                 dbg("PDP profile is NOT defined!!! Need to define it first...");
678                 ret = tcore_ps_define_context(service->co_ps, co_context, NULL);
679         }
680         else {
681                 dbg("PDP profile is defined!!! Activate context...");
682                 ret = tcore_ps_activate_context(service->co_ps, co_context, NULL);
683         }
684
685         return ret;
686 }
687
688 gboolean _ps_service_deactivate_context(gpointer object, gpointer context)
689 {
690         PsService *service = object;
691         CoreObject *co_context = NULL;
692
693         dbg("deactivate context(%p)", context);
694         g_return_val_if_fail(service != NULL, FALSE);
695
696         co_context = (CoreObject *)_ps_context_ref_co_context(context);
697
698         return tcore_ps_deactivate_context(service->co_ps, co_context, NULL);
699 }
700
701 void _ps_service_connection_timer(gpointer object, gpointer context)
702 {
703         gboolean f_awo = FALSE;
704
705         f_awo = _ps_context_get_alwayson_enable(context);
706         if(!f_awo)
707                 return;
708
709         timer_src = g_timeout_add_seconds(connection_timeout, __ps_service_connetion_timeout_handler, context);
710
711         dbg("cellular service timer started timer src(%d), timeout(%d)", timer_src, connection_timeout);
712         connection_timeout = connection_timeout*2;
713         if(connection_timeout > TIMEOUT_MAX)
714                 connection_timeout = TIMEOUT_MAX;
715
716         return;
717 }
718
719 void _ps_service_reset_connection_timer(gpointer context)
720 {
721         gboolean f_awo = FALSE;
722
723         f_awo = _ps_context_get_alwayson_enable(context);
724         dbg("Always ON: [%s]", (f_awo ? "YES" : "NO"));
725         if(f_awo == FALSE)
726                 return;
727
728         connection_timeout = TIMEOUT_DEFAULT;
729
730         if (timer_src != 0) {
731                 dbg("Remove connection Retry timer [%d]", timer_src);
732
733                 g_source_remove(timer_src);
734                 timer_src = 0;
735         }
736 }
737
738 void _ps_service_remove_contexts(gpointer object)
739 {
740         GHashTableIter iter;
741         gpointer key, value;
742         PsService *service = object;
743
744         dbg("service remove all contexts");
745         g_return_if_fail(service != NULL);
746
747         g_hash_table_iter_init(&iter, service->contexts);
748         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
749                 gpointer co_context = NULL;
750
751                 dbg("key(%s), value(%p) context", key, value);
752                 co_context = _ps_context_ref_co_context(value);
753
754                 _ps_service_reset_connection_timer(value);
755                 _ps_context_set_alwayson_enable(value, FALSE);
756                 _ps_service_deactivate_context(service, value);
757                 _ps_context_set_connected(value, FALSE);
758                 tcore_ps_remove_context(service->co_ps, co_context);
759                 tcore_context_free(co_context);
760
761                 __ps_service_emit_context_removed_signal(service, value);
762                 _ps_context_remove_context(value);
763         }
764
765         g_hash_table_remove_all(service->contexts);
766         return;
767 }
768
769 void _ps_service_disconnect_contexts(gpointer object)
770 {
771         GHashTableIter iter;
772         gpointer key, value;
773         PsService *service = object;
774
775         dbg("service disconnect all contexts");
776         g_return_if_fail(service != NULL);
777
778         g_hash_table_iter_init(&iter, service->contexts);
779         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
780                 _ps_service_reset_connection_timer(value);
781                 _ps_service_deactivate_context(service, value);
782         }
783
784         return;
785 }
786
787 void _ps_service_connect_default_context(gpointer object)
788 {
789         GHashTableIter iter;
790         gpointer key, value;
791         PsService *service = object;
792
793         dbg("Connect to 'default' context");
794         g_return_if_fail(service != NULL);
795
796         g_hash_table_iter_init(&iter, service->contexts);
797         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
798                 gboolean f_awo = FALSE;
799
800                 f_awo = _ps_context_get_alwayson_enable(value);
801                 dbg("Always ON: [%s]", (f_awo ? "YES" : "NO"));
802                 if(f_awo){
803                         int rv = 0;
804
805                         _ps_service_reset_connection_timer(value);
806
807                         /* Activate context */
808                         rv = _ps_service_activate_context(service, value);
809                         dbg("return rv(%d)", rv);
810                         break;
811                 }
812         }
813
814         return;
815 }
816
817 gpointer _ps_service_return_default_context(gpointer object)
818 {
819         GHashTableIter iter;
820         gpointer key, value;
821         PsService *service = object;
822
823         g_return_val_if_fail(service != NULL, NULL);
824
825         g_hash_table_iter_init(&iter, service->contexts);
826         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
827                 gboolean b_default = FALSE;
828                 b_default = _ps_context_get_default_internet(value);
829
830                 if(b_default){
831                         return value;
832                 }
833         }
834
835         return NULL;
836 }
837
838 gboolean _ps_service_processing_network_event(gpointer object, gboolean ps_attached, gboolean roaming)
839 {
840         PsService *service = object;
841         g_return_val_if_fail(service != NULL, FALSE);
842
843         if(service->ps_attached == ps_attached && service->roaming == roaming)
844                 return TRUE;
845
846         _ps_service_set_ps_attached(service, ps_attached);
847         _ps_service_set_roaming(service, roaming);
848         _ps_update_cellular_state_key(service);
849
850         if(service->ps_attached)
851                 _ps_service_connect_default_context(service);
852
853         return TRUE;
854 }
855
856 gboolean _ps_service_set_connected(gpointer object, int context_id, gboolean enabled)
857 {
858         GHashTableIter iter;
859         gpointer key, value;
860         PsService *service = NULL;
861
862         dbg("Set service - Context ID: [%d] State: [%s]",
863                         context_id, (enabled ? "CONNECTED" : "NOT CONNECTED"));
864
865         service = (PsService *) object;
866         g_hash_table_iter_init(&iter, service->contexts);
867         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
868                 CoreObject *context = NULL;
869                 int tmp_cid;
870
871                 context = _ps_context_ref_co_context(value);
872                 tmp_cid = tcore_context_get_id(context);
873
874                 if (tmp_cid != context_id) continue;
875
876                 if(!enabled) {
877                         dbg("Clear teh context ID");
878                         tcore_ps_clear_context_id(service->co_ps, context);
879                 }
880
881                 /* Set the state */
882                 _ps_context_set_connected(value, enabled);
883         }
884
885         return TRUE;
886 }
887
888 void _ps_service_set_ps_defined(gpointer *object, gboolean value, int cid)
889 {
890         PsService *service = (PsService*)object;
891         GHashTableIter iter;
892         gpointer key, out;
893
894         dbg("PS Defined - Context ID: [%d] Value: [%d]", cid, value);
895
896         g_return_if_fail(service != NULL);
897
898         g_hash_table_iter_init(&iter, service->contexts);
899         while (g_hash_table_iter_next(&iter, &key, &out) == TRUE) {
900                 gboolean r_activate = 0;
901
902                 /* Set Context */
903                 r_activate = _ps_context_set_ps_defined(out, value, cid);
904                 r_activate &= value;
905
906                 dbg("Activate context: [%s]", (r_activate ? "YES" : "NO"));
907                 if(r_activate) {
908                         int rv;
909
910                         dbg("Activate context - Context ID: [%d]", cid);
911                         rv = _ps_service_activate_context(service, out);
912                         dbg("Activate context request - %s", (rv == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
913                         break;
914                 }
915         }
916
917         return;
918 }
919
920 gboolean _ps_service_set_ps_attached(gpointer object, gboolean value)
921 {
922         PsService *service = object;
923         g_return_val_if_fail(service != NULL, FALSE);
924
925         service->ps_attached = value;
926         dbg("service(%p) ps_attached(%d)", service, service->ps_attached);
927
928         return TRUE;
929 }
930
931 gboolean _ps_service_get_roaming(gpointer object)
932 {
933         PsService *service = object;
934         g_return_val_if_fail(service != NULL, FALSE);
935
936         return service->roaming;
937 }
938
939 gboolean _ps_service_set_roaming(gpointer object, gboolean value)
940 {
941         PsService *service = object;
942         g_return_val_if_fail(service != NULL, FALSE);
943
944         service->roaming = value;
945         dbg("service(%p) roaming(%d)", service, service->roaming);
946         __ps_service_emit_property_changed_signal(service);
947
948         return TRUE;
949 }
950
951 gboolean _ps_service_set_access_technology(gpointer object,
952                 enum telephony_network_access_technology value)
953 {
954         PsService *service = object;
955         g_return_val_if_fail(service != NULL, FALSE);
956
957         service->act = value;
958         dbg("service(%p) Access Technology(%d)", service, service->act);
959
960         if(service->act > NETWORK_ACT_UNKNOWN && service->act < NETWORK_ACT_NOT_SPECIFIED){
961                 _ps_update_cellular_state_key(service);
962                 _ps_service_connect_default_context(service);
963         }
964
965         return TRUE;
966 }
967
968 enum telephony_ps_state _ps_service_check_cellular_state(gpointer object)
969 {
970         gboolean state = FALSE;
971         PsService *service = object;
972         g_return_val_if_fail(service != NULL, TELEPHONY_PS_NO_SERVICE);
973
974         state = _ps_modem_get_power(service->p_modem);
975         if(!state){
976                 return TELEPHONY_PS_NO_SERVICE;
977         }
978
979         state = _ps_modem_get_sim_init(service->p_modem);
980         if(!state){
981                 return TELEPHONY_PS_NO_SERVICE;
982         }
983
984         state = _ps_modem_get_flght_mode(service->p_modem);
985         if(state){
986                 return TELEPHONY_PS_FLIGHT_MODE;
987         }
988
989         if(!service->ps_attached){
990                 return TELEPHONY_PS_NO_SERVICE;
991         }
992
993         state = _ps_modem_get_data_allowed(service->p_modem);
994         if(!state){
995                 return TELEPHONY_PS_3G_OFF;
996         }
997
998         state = _ps_modem_get_data_roaming_allowed(service->p_modem);
999         if(service->roaming && !state){
1000                 return TELEPHONY_PS_ROAMING_OFF;
1001         }
1002
1003         return TELEPHONY_PS_ON;
1004 }