DA: Add exception check for time logic
[platform/upstream/connman.git] / plugins / telephony.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <gdbus.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #define CONNMAN_API_SUBJECT_TO_CHANGE
32 #include <connman/dbus.h>
33 #include <connman/inet.h>
34 #include <connman/plugin.h>
35 #include <connman/network.h>
36 #include <connman/setting.h>
37 #include <connman/technology.h>
38
39 #include <connman.h>
40
41 #define PS_DBUS_SERVICE                         "com.tcore.ps"
42 #define TELEPHONY_DBUS_SERVICE                  "org.tizen.telephony"
43
44 #define PS_MASTER_INTERFACE                     PS_DBUS_SERVICE ".master"
45 #define PS_MODEM_INTERFACE                      PS_DBUS_SERVICE ".modem"
46 #define PS_SERVICE_INTERFACE            PS_DBUS_SERVICE ".service"
47 #define PS_CONTEXT_INTERFACE            PS_DBUS_SERVICE ".context"
48
49 /* methods */
50 #define GET_MODEMS                              "GetModems"
51 #define GET_SERVICES                    "GetServices"
52 #define GET_CONTEXTS                    "GetContexts"
53 #define ACTIVATE_CONTEXT                "Activate"
54 #define DEACTIVATE_CONTEXT              "Deactivate"
55 #define GET_PROPERTIES                  "GetProperties"
56 #define SET_PROPERTY                    "SetProperties"
57
58 /* signals */
59 #define MODEM_ADDED                             "ModemAdded"
60 #define MODEM_REMOVED                   "ModemRemoved"
61 #define SERVICE_ADDED                   "ServiceAdded"
62 #define SERVICE_REMOVED                 "ServiceRemoved"
63 #define CONTEXT_ADDED                   "ContextAdded"
64 #define CONTEXT_REMOVED                 "ContextRemoved"
65 #define PROPERTY_CHANGED                "PropertyChanged"
66
67 #define TIMEOUT 130000
68
69 #define STRING2BOOL(a)  (!(g_strcmp0(a, "TRUE")) ? (TRUE):(FALSE))
70
71 static DBusConnection *connection;
72 static GHashTable       *modem_hash;
73 static GHashTable       *service_hash;
74 static GHashTable       *network_hash;
75
76 struct telephony_service {
77         char *path;
78
79         gpointer p_modem;
80         char *act;
81         gboolean roaming; /* global roaming state */
82         gboolean ps_attached; /* packet service is available */
83 };
84
85 struct telephony_modem {
86         char *path;
87
88         char *operator;
89         gboolean powered;
90         gboolean sim_init;
91         gboolean flight_mode;
92         gboolean data_allowed;
93         gboolean roaming_allowed;
94
95         struct connman_device *device;
96         struct telephony_service *s_service;
97 };
98
99 struct telephony_network {
100         char *path;
101         int if_index;
102         gboolean routing_only;
103         gboolean ipv6_link_only;
104
105         struct connman_network *network;
106
107         enum connman_ipconfig_method ipv4_method;
108         struct connman_ipaddress *ipv4_address;
109
110         enum connman_ipconfig_method ipv6_method;
111         struct connman_ipaddress *ipv6_address;
112 };
113
114 static int telephony_default_subscription_id = 0;
115
116 /* function prototype */
117 static void telephony_connect(DBusConnection *connection, void *user_data);
118 static void telephony_disconnect(DBusConnection *connection, void *user_data);
119 static void __remove_modem(gpointer data);
120 static void __remove_service(gpointer data);
121 static void __remove_network(gpointer data);
122
123 static int __modem_probe(struct connman_device *device);
124 static void __modem_remove(struct connman_device *device);
125 static int __modem_enable(struct connman_device *device);
126 static int __modem_disable(struct connman_device *device);
127
128 static int __network_probe(struct connman_network *network);
129 static void __network_remove(struct connman_network *network);
130 static int __network_connect(struct connman_network *network);
131 static int __network_disconnect(struct connman_network *network);
132
133
134 /* dbus request and reply */
135 static int __dbus_request(const char *service, const char *path, const char *interface,
136                         const char *method,
137                         DBusPendingCallNotifyFunction notify, void *user_data,
138                         DBusFreeFunction free_function, int type, ...);
139
140 static int __request_get_modems(void);
141 static void __response_get_modems(DBusPendingCall *call, void *user_data);
142 static int __request_get_services(const char *path);
143 static void __response_get_services(DBusPendingCall *call, void *user_data);
144 static int __request_get_contexts(struct telephony_modem *modem);
145 static void __response_get_contexts(DBusPendingCall *call, void *user_data);
146 static int __request_network_activate(struct connman_network *network);
147 static void __response_network_activate(DBusPendingCall *call, void *user_data);
148 static int __request_network_deactivate(struct connman_network *network);
149
150 /* telephony internal function */
151 static void __add_modem(const char *path, DBusMessageIter *prop);
152 static void __add_service(struct telephony_modem *modem,
153                         const char *service_path, DBusMessageIter *prop);
154 static void __add_connman_device(const char *modem_path, const char *operator);
155 static void __remove_connman_device(struct telephony_modem *modem);
156 static void __remove_connman_networks(struct connman_device *device);
157 static int __add_context(struct connman_device *device, const char *path,
158                                                         DBusMessageIter *prop);
159
160 /* signal handler */
161 static gboolean __changed_modem(DBusConnection *connection,
162                                 DBusMessage *message, void *user_data);
163 static gboolean __added_modem(DBusConnection *connection,
164                                 DBusMessage *message, void *user_data);
165 static gboolean __removed_modem(DBusConnection *connection,
166                                 DBusMessage *message, void *user_data);
167 static gboolean __changed_service(DBusConnection *connection,
168                                 DBusMessage *message, void *user_data);
169 static gboolean __added_service(DBusConnection *connection,
170                                 DBusMessage *message, void *user_data);
171 static gboolean __removed_service(DBusConnection *connection,
172                                 DBusMessage *message, void *user_data);
173 static gboolean __changed_context(DBusConnection *connection,
174                                 DBusMessage *message, void *user_data);
175 static gboolean __added_context(DBusConnection *connection,
176                                 DBusMessage *message, void *user_data);
177 static gboolean __removed_context(DBusConnection *connection,
178                                 DBusMessage *message, void *user_data);
179
180 /* device driver */
181 static struct connman_device_driver modem_driver = {
182         .name           = "device",
183         .type           = CONNMAN_DEVICE_TYPE_CELLULAR,
184         .probe          = __modem_probe,
185         .remove         = __modem_remove,
186         .enable         = __modem_enable,
187         .disable        = __modem_disable,
188 };
189
190 /* network driver */
191 static struct connman_network_driver network_driver = {
192         .name           = "network",
193         .type           = CONNMAN_NETWORK_TYPE_CELLULAR,
194         .probe          = __network_probe,
195         .remove         = __network_remove,
196         .connect        = __network_connect,
197         .disconnect     = __network_disconnect,
198 };
199
200 static int tech_probe(struct connman_technology *technology)
201 {
202         return 0;
203 }
204
205 static void tech_remove(struct connman_technology *technology)
206 {
207         return;
208 }
209
210 static struct connman_technology_driver tech_driver = {
211         .name           = "cellular",
212         .type           = CONNMAN_SERVICE_TYPE_CELLULAR,
213         .probe          = tech_probe,
214         .remove         = tech_remove,
215 };
216
217 /* local function */
218 static void telephony_connect(DBusConnection *connection, void *user_data)
219 {
220         DBG("connection %p", connection);
221         modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
222                                                 g_free, __remove_modem);
223         service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
224                                                 g_free, __remove_service);
225         network_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
226                                                 g_free, __remove_network);
227
228         __request_get_modems();
229 }
230
231 static void telephony_disconnect(DBusConnection *connection, void *user_data)
232 {
233         DBG("connection %p", connection);
234
235         if (modem_hash != NULL) {
236                 g_hash_table_destroy(modem_hash);
237                 modem_hash = NULL;
238         }
239
240         if (network_hash != NULL) {
241                 g_hash_table_destroy(network_hash);
242                 network_hash = NULL;
243         }
244 }
245
246 static void __remove_modem(gpointer data)
247 {
248         struct telephony_modem *modem = data;
249
250         __remove_connman_device(modem);
251
252         g_free(modem->path);
253         g_free(modem->operator);
254         g_free(modem);
255 }
256
257 static void __remove_service(gpointer data)
258 {
259         struct telephony_service *service = data;
260
261         g_free(service->path);
262         g_free(service->act);
263         g_free(service);
264 }
265
266 static void __remove_network(gpointer data)
267 {
268         struct telephony_network *info = data;
269         struct connman_device *device;
270
271         device = connman_network_get_device(info->network);
272         if (device != NULL)
273                 connman_device_remove_network(device, info->network);
274
275         connman_network_unref(info->network);
276
277         g_free(info->path);
278
279         connman_ipaddress_free(info->ipv4_address);
280         connman_ipaddress_free(info->ipv6_address);
281
282         g_free(info);
283 }
284
285 static void __set_device_powered(struct telephony_modem *modem,
286                                         gboolean powered)
287 {
288         DBG("set modem(%s) powered(%d)", modem->path, powered);
289
290         if (modem->device)
291                 connman_device_set_powered(modem->device, powered);
292 }
293
294 static int __check_device_powered(const char *path, gboolean powered)
295 {
296         struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path);
297
298         if (modem == NULL)
299                 return -ENODEV;
300
301         DBG("check modem (%s) powered (%d)", modem->path, modem->powered);
302
303         if (modem->powered == powered)
304                 return -EALREADY;
305
306         return 0;
307 }
308
309 static int __modem_probe(struct connman_device *device)
310 {
311         DBG("device %p", device);
312         return 0;
313 }
314
315 static void __modem_remove(struct connman_device *device)
316 {
317         DBG("device %p", device);
318 }
319
320 static int __modem_enable(struct connman_device *device)
321 {
322         const char *path = connman_device_get_string(device, "Path");
323         DBG("device %p, path, %s", device, path);
324
325         return __check_device_powered(path, TRUE);
326 }
327
328 static int __modem_disable(struct connman_device *device)
329 {
330         const char *path = connman_device_get_string(device, "Path");
331         DBG("device %p, path, %s", device, path);
332
333         return __check_device_powered(path, FALSE);
334 }
335
336 static int __network_probe(struct connman_network *network)
337 {
338         DBG("network_prove network(%p)", network);
339         return 0;
340 }
341
342 static int __network_connect(struct connman_network *network)
343 {
344         DBG("network %p", network);
345
346         return __request_network_activate(network);
347 }
348
349 static int __network_disconnect(struct connman_network *network)
350 {
351         DBG("network %p", network);
352
353         if (connman_network_get_associating(network) == TRUE)
354                 connman_network_clear_associating(network);
355
356         connman_network_set_associating(network, FALSE);
357
358         return __request_network_deactivate(network);
359 }
360
361 static void __network_remove(struct connman_network *network)
362 {
363         char const *path = connman_network_get_string(network, "Path");
364         DBG("network %p path %s", network, path);
365
366         g_hash_table_remove(network_hash, path);
367 }
368
369 static int __dbus_request(const char *service, const char *path, const char *interface,
370                 const char *method,
371                 DBusPendingCallNotifyFunction notify, void *user_data,
372                 DBusFreeFunction free_function, int type, ...)
373 {
374         DBusMessage *message;
375         DBusPendingCall *call;
376         dbus_bool_t ok;
377         va_list va;
378
379         DBG("path %s %s.%s", path, interface, method);
380
381         if (path == NULL)
382                 return -EINVAL;
383
384         message = dbus_message_new_method_call(service, path, interface, method);
385         if (message == NULL)
386                 return -ENOMEM;
387
388         dbus_message_set_auto_start(message, FALSE);
389
390         va_start(va, type);
391         ok = dbus_message_append_args_valist(message, type, va);
392         va_end(va);
393
394         if (!ok) {
395                 dbus_message_unref(message);
396                 return -ENOMEM;
397         }
398
399         if (dbus_connection_send_with_reply(connection, message,
400                                                 &call, TIMEOUT) == FALSE) {
401                 connman_error("Failed to call %s.%s", interface, method);
402                 dbus_message_unref(message);
403                 return -EINVAL;
404         }
405
406         if (call == NULL) {
407                 connman_error("D-Bus connection not available");
408                 dbus_message_unref(message);
409                 return -EINVAL;
410         }
411
412         dbus_pending_call_set_notify(call, notify, user_data, free_function);
413
414         dbus_message_unref(message);
415
416         return -EINPROGRESS;
417 }
418
419 static int __request_get_modems(void)
420 {
421         DBG("request get modem");
422         /* call connect master */
423         return __dbus_request(PS_DBUS_SERVICE, "/", PS_MASTER_INTERFACE, GET_MODEMS,
424                         __response_get_modems, NULL, NULL, DBUS_TYPE_INVALID);
425 }
426
427 static void __response_get_modems(DBusPendingCall *call, void *user_data)
428 {
429         DBusMessage *reply;
430         DBusError error;
431         DBusMessageIter args, dict;
432
433         DBG("");
434
435         reply = dbus_pending_call_steal_reply(call);
436
437         dbus_error_init(&error);
438
439         if (dbus_set_error_from_message(&error, reply)) {
440                 connman_error("GetModems() %s %s", error.name, error.message);
441                 dbus_error_free(&error);
442                 goto done;
443         }
444
445         DBG("message signature (%s)", dbus_message_get_signature(reply));
446
447         if (dbus_message_iter_init(reply, &args) == FALSE)
448                 goto done;
449
450         dbus_message_iter_recurse(&args, &dict);
451
452         /* DBG("message type (%d) dic(%d)",
453          *      dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY);
454          */
455
456         while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
457                 DBusMessageIter entry, property;
458                 const char *modem_path;
459
460                 dbus_message_iter_recurse(&dict, &entry);
461                 dbus_message_iter_get_basic(&entry, &modem_path);
462                 DBG("modem path (%s)", modem_path);
463
464                 dbus_message_iter_next(&entry);
465                 dbus_message_iter_recurse(&entry, &property);
466
467                 __add_modem(modem_path, &property);
468
469                 dbus_message_iter_next(&dict);
470         }
471
472 done:
473         dbus_message_unref(reply);
474         dbus_pending_call_unref(call);
475 }
476
477 static int __request_get_services(const char *path)
478 {
479         DBG("request get service");
480         return __dbus_request(PS_DBUS_SERVICE, path, PS_MODEM_INTERFACE, GET_SERVICES,
481                         __response_get_services, g_strdup(path),
482                         g_free, DBUS_TYPE_INVALID);
483 }
484
485 static void __response_get_services(DBusPendingCall *call, void *user_data)
486 {
487         DBusMessage *reply;
488         DBusError error;
489         DBusMessageIter args, dict;
490
491         const char *path = user_data;
492         struct telephony_modem *modem;
493
494         modem = g_hash_table_lookup(modem_hash, path);
495
496         DBG("");
497
498         reply = dbus_pending_call_steal_reply(call);
499
500         dbus_error_init(&error);
501
502         if (dbus_set_error_from_message(&error, reply)) {
503                 connman_error("GetServices() %s %s", error.name, error.message);
504                 dbus_error_free(&error);
505                 goto done;
506         }
507
508         if (modem == NULL || modem->device == NULL)
509                 goto done;
510
511         DBG("message signature (%s)", dbus_message_get_signature(reply));
512
513         if (dbus_message_iter_init(reply, &args) == FALSE)
514                 goto done;
515
516         dbus_message_iter_recurse(&args, &dict);
517
518         /* DBG("message type (%d) dic(%d)",
519          *       dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY);
520          */
521
522         while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
523                 DBusMessageIter entry, property;
524                 const char *service_path;
525
526                 dbus_message_iter_recurse(&dict, &entry);
527                 dbus_message_iter_get_basic(&entry, &service_path);
528                 DBG("service path (%s)", service_path);
529
530                 dbus_message_iter_next(&entry);
531                 dbus_message_iter_recurse(&entry, &property);
532
533                 __add_service(modem, service_path, &property);
534
535                 dbus_message_iter_next(&dict);
536         }
537
538 done:
539         dbus_message_unref(reply);
540         dbus_pending_call_unref(call);
541 }
542
543 static int __request_get_contexts(struct telephony_modem *modem)
544 {
545         DBG("request get contexts");
546         return __dbus_request(PS_DBUS_SERVICE, modem->s_service->path,
547                         PS_SERVICE_INTERFACE, GET_CONTEXTS,
548                         __response_get_contexts, g_strdup(modem->path),
549                         g_free, DBUS_TYPE_INVALID);
550 }
551
552 static void __response_get_contexts(DBusPendingCall *call, void *user_data)
553 {
554         DBusError error;
555         DBusMessage *reply;
556         DBusMessageIter args, dict;
557
558         const char *path = user_data;
559         struct telephony_modem *modem;
560
561         DBG("");
562
563         modem = g_hash_table_lookup(modem_hash, path);
564         if (modem == NULL)
565                 return;
566         if (modem->s_service == NULL)
567                         return;
568         if (modem->device == NULL)
569                 return;
570
571         reply = dbus_pending_call_steal_reply(call);
572
573         dbus_error_init(&error);
574
575         if (dbus_set_error_from_message(&error, reply)) {
576                 connman_error("GetContexts() %s %s", error.name, error.message);
577                 dbus_error_free(&error);
578                 goto done;
579         }
580
581         DBG("message signature (%s)", dbus_message_get_signature(reply));
582
583         if (dbus_message_iter_init(reply, &args) == FALSE)
584                 goto done;
585
586         dbus_message_iter_recurse(&args, &dict);
587
588         while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
589                 DBusMessageIter entry, property;
590                 const char *context_path;
591
592                 dbus_message_iter_recurse(&dict, &entry);
593                 dbus_message_iter_get_basic(&entry, &context_path);
594                 DBG("context path (%s)", context_path);
595
596                 dbus_message_iter_next(&entry);
597                 dbus_message_iter_recurse(&entry, &property);
598
599                 __add_context(modem->device, context_path, &property);
600
601                 dbus_message_iter_next(&dict);
602         }
603
604 done:
605         dbus_message_unref(reply);
606         dbus_pending_call_unref(call);
607 }
608
609 static int __request_network_activate(struct connman_network *network)
610 {
611         int n_modems;
612         const char *path = NULL;
613         struct telephony_modem *modem = NULL;
614
615         n_modems = g_hash_table_size(modem_hash);
616         path = connman_network_get_string(network, "Path");
617         modem = connman_device_get_data(connman_network_get_device(network));
618         DBG("network %p, path %s, modem %s[%d]", network, path, modem->path,
619                         telephony_default_subscription_id);
620
621         if (modem && n_modems > 1 && g_str_has_suffix(path, "_1") == TRUE) {
622                 char *subscribe_id = g_strdup_printf("%d", telephony_default_subscription_id);
623
624                 if (g_str_has_suffix(modem->path, subscribe_id) != TRUE) {
625                         g_free(subscribe_id);
626                         return -ENOLINK;
627                 }
628                 g_free(subscribe_id);
629         }
630
631         return __dbus_request(PS_DBUS_SERVICE, path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT,
632                         __response_network_activate,
633                         g_strdup(path), NULL, DBUS_TYPE_INVALID);
634 }
635
636 static gboolean __check_network_available(struct connman_network *network)
637 {
638         if (network == NULL || connman_network_get_device(network) == NULL)
639                 return FALSE;
640
641         return TRUE;
642 }
643
644 static void __response_network_activate(DBusPendingCall *call, void *user_data)
645 {
646         DBG("network activation response");
647
648         DBusError error;
649         DBusMessage *reply;
650
651         struct telephony_network *info;
652         const char *path = user_data;
653
654         info = g_hash_table_lookup(network_hash, path);
655         reply = dbus_pending_call_steal_reply(call);
656
657         if (info == NULL)
658                 goto done;
659
660         if (__check_network_available(info->network) == FALSE) {
661                 g_hash_table_remove(network_hash, path);
662                 goto done;
663         }
664
665         dbus_error_init(&error);
666         if (dbus_set_error_from_message(&error, reply)) {
667                 connman_error("connection activate() %s %s",
668                                         error.name, error.message);
669
670                 if (connman_network_get_associating(info->network) == TRUE)
671                         connman_network_set_error(info->network,
672                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
673
674                 if (connman_network_get_connecting(info->network) == TRUE)
675                         connman_network_set_error(info->network,
676                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
677
678                 if (connman_network_get_index(info->network) < 0)
679                         connman_network_set_error(info->network,
680                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
681
682                 dbus_error_free(&error);
683                 goto done;
684         }
685
686 done:
687         dbus_message_unref(reply);
688         dbus_pending_call_unref(call);
689 }
690
691 static int __request_network_deactivate(struct connman_network *network)
692 {
693         const char *path = connman_network_get_string(network, "Path");
694         DBG("network %p, path %s", network, path);
695
696         return __dbus_request(PS_DBUS_SERVICE, path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT,
697                         NULL, NULL, NULL, DBUS_TYPE_INVALID);
698 }
699
700 static void __response_get_default_subscription_id(DBusPendingCall *call,
701                 void *user_data)
702 {
703         DBusMessage *reply;
704         DBusError error;
705         DBusMessageIter args;
706
707         DBG("");
708
709         reply = dbus_pending_call_steal_reply(call);
710
711         dbus_error_init(&error);
712         if (dbus_set_error_from_message(&error, reply)) {
713                 connman_error("GetDefaultDataSubscription() %s %s", error.name, error.message);
714                 dbus_error_free(&error);
715                 goto done;
716         }
717
718         DBG("message signature (%s)", dbus_message_get_signature(reply));
719
720         if (dbus_message_iter_init(reply, &args) == FALSE)
721                 goto done;
722
723         dbus_message_iter_get_basic(&args, &telephony_default_subscription_id);
724         DBG("default subscription: %d", telephony_default_subscription_id);
725
726 done:
727         dbus_message_unref(reply);
728         dbus_pending_call_unref(call);
729 }
730
731 static int __request_get_default_subscription_id(const char *path)
732 {
733         int ret;
734         char *telephony_modem_path = NULL;
735
736         telephony_modem_path = g_strdup_printf("/org/tizen/telephony%s", path);
737         DBG("request get default subscription id %s", telephony_modem_path);
738
739         ret = __dbus_request(TELEPHONY_DBUS_SERVICE, telephony_modem_path,
740                         "org.tizen.telephony.Network", "GetDefaultDataSubscription",
741                         __response_get_default_subscription_id, NULL, NULL, DBUS_TYPE_INVALID);
742
743         g_free(telephony_modem_path);
744         return ret;
745 }
746
747 static void __add_modem(const char *path, DBusMessageIter *prop)
748 {
749         struct telephony_modem *modem;
750
751         modem = g_hash_table_lookup(modem_hash, path);
752         if (modem != NULL)
753                 return;
754
755         modem = g_try_new0(struct telephony_modem, 1);
756         if (modem == NULL)
757                 return;
758
759         modem->path = g_strdup(path);
760         modem->device = NULL;
761         modem->s_service = NULL;
762
763         g_hash_table_insert(modem_hash, g_strdup(path), modem);
764
765         while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
766                 DBusMessageIter entry;
767                 const char *key, *tmp;
768
769                 dbus_message_iter_recurse(prop, &entry);
770                 dbus_message_iter_get_basic(&entry, &key);
771
772                 dbus_message_iter_next(&entry);
773                 dbus_message_iter_get_basic(&entry, &tmp);
774
775                 DBG("key (%s) value(%s)", key, tmp);
776
777                 if (g_strcmp0(key, "powered") == 0) {
778                         modem->powered = STRING2BOOL(tmp);
779                 } else if (g_strcmp0(key, "operator") == 0) {
780                         modem->operator = g_strdup(tmp);
781                 } else if (g_strcmp0(key, "sim_init") == 0) {
782                         modem->sim_init = STRING2BOOL(tmp);
783                 } else if (g_strcmp0(key, "flight_mode") == 0) {
784                         modem->flight_mode = STRING2BOOL(tmp);
785                 } else if (g_strcmp0(key, "roaming_allowed") == 0) {
786                         modem->roaming_allowed = STRING2BOOL(tmp);
787                 } else if (g_strcmp0(key, "data_allowed") == 0) {
788                         modem->data_allowed = STRING2BOOL(tmp);
789                 }
790                 dbus_message_iter_next(prop);
791         }
792
793         __add_connman_device(path, modem->operator);
794         __set_device_powered(modem, modem->powered);
795
796         if (g_hash_table_size(modem_hash) > 1)
797                 __request_get_default_subscription_id(modem->path);
798
799         if (modem->powered != TRUE) {
800                 DBG("modem is not powered");
801                 return;
802         }
803
804         __request_get_services(modem->path);
805 }
806
807 static void __add_service(struct telephony_modem *modem,
808                                 const char *service_path, DBusMessageIter *prop)
809 {
810         struct telephony_service *service;
811
812         if (modem->s_service != NULL)
813                 return;
814
815         service = g_try_new0(struct telephony_service, 1);
816         if (service == NULL)
817                 return;
818
819         service->path = g_strdup(service_path);
820         service->p_modem = modem;
821         g_hash_table_insert(service_hash, g_strdup(service_path), service);
822
823         while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
824                 DBusMessageIter entry;
825                 const char *key, *tmp;
826
827                 dbus_message_iter_recurse(prop, &entry);
828                 dbus_message_iter_get_basic(&entry, &key);
829
830                 dbus_message_iter_next(&entry);
831                 dbus_message_iter_get_basic(&entry, &tmp);
832
833                 DBG("key (%s) value(%s)", key, tmp);
834
835                 if (g_strcmp0(key, "roaming") == 0) {
836                         service->roaming = STRING2BOOL(tmp);
837                 } else if (g_strcmp0(key, "act") == 0) {
838                         service->act = g_strdup(tmp);
839                 } else if (g_strcmp0(key, "ps_attached") == 0) {
840                         service->ps_attached = STRING2BOOL(tmp);
841                 }
842
843                 dbus_message_iter_next(prop);
844         }
845
846         modem->s_service = service;
847         __request_get_contexts(modem);
848 }
849
850 static char *__get_ident(const char *path)
851 {
852         char *pos;
853
854         if (*path != '/')
855                 return NULL;
856
857         pos = strrchr(path, '/');
858         if (pos == NULL)
859                 return NULL;
860
861         return pos + 1;
862 }
863
864 static void __add_connman_device(const char *modem_path, const char *operator)
865 {
866         char* ident = NULL;
867         struct telephony_modem *modem;
868         struct connman_device *device;
869
870         DBG("path %s operator %s", modem_path, operator);
871
872         if (modem_path == NULL)
873                 return;
874
875         if (operator == NULL)
876                 return;
877
878         modem = g_hash_table_lookup(modem_hash, modem_path);
879         if (modem == NULL)
880                 return;
881
882         if (modem->device) {
883                 if (!g_strcmp0(operator,
884                                 connman_device_get_ident(modem->device)))
885                         return;
886
887                 __remove_connman_device(modem);
888         }
889
890         if (strlen(operator) == 0)
891                 return;
892
893         device = connman_device_create(operator, CONNMAN_DEVICE_TYPE_CELLULAR);
894         if (device == NULL)
895                 return;
896
897         ident = g_strdup_printf("%s_%s", __get_ident(modem_path), operator);
898         connman_device_set_ident(device, ident);
899         g_free(ident);
900
901         connman_device_set_string(device, "Path", modem_path);
902         connman_device_set_data(device, modem);
903
904         if (connman_device_register(device) < 0) {
905                 connman_error("Failed to register cellular device");
906                 connman_device_unref(device);
907                 return;
908         }
909
910         modem->device = device;
911 }
912
913 static void __remove_connman_device(struct telephony_modem *modem)
914 {
915         DBG("modem %p path %s device %p", modem, modem->path, modem->device);
916
917         if (modem->device == NULL)
918                 return;
919
920         __remove_connman_networks(modem->device);
921
922         connman_device_unregister(modem->device);
923         connman_device_unref(modem->device);
924
925         modem->device = NULL;
926 }
927
928 static void __remove_connman_networks(struct connman_device *device)
929 {
930         GHashTableIter iter;
931         gpointer key, value;
932         GSList *info_list = NULL;
933         GSList *list;
934
935         if (network_hash == NULL)
936                 return;
937
938         g_hash_table_iter_init(&iter, network_hash);
939
940         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
941                 struct telephony_network *info = value;
942
943                 if (connman_network_get_device(info->network) != device)
944                         continue;
945
946                 info_list = g_slist_append(info_list, info);
947         }
948
949         for (list = info_list; list != NULL; list = list->next) {
950                 struct telephony_network *info = list->data;
951                 connman_device_remove_network(device, info->network);
952         }
953
954         g_slist_free(info_list);
955 }
956
957 static gboolean connman_ipaddress_updated(struct connman_ipaddress *ipaddress,
958                                         const char *address, const char *gateway)
959 {
960         if (ipaddress == NULL || address == NULL)
961                 return FALSE;
962
963         if (g_strcmp0(ipaddress->local, address) != 0)
964                 return TRUE;
965
966         if (g_strcmp0(ipaddress->gateway, gateway) != 0)
967                 return TRUE;
968
969         return FALSE;
970 }
971
972 static void __set_network_connected(struct telephony_network *network,
973                                         gboolean connected)
974 {
975         gboolean setip = FALSE;
976
977         DBG("network %p connected %d", network, connected);
978
979         connman_network_set_index(network->network, network->if_index);
980         if (connman_network_get_connected(network->network) == connected)
981                 return;
982
983         switch (network->ipv4_method) {
984         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
985         case CONNMAN_IPCONFIG_METHOD_DHCP:
986         case CONNMAN_IPCONFIG_METHOD_AUTO:
987         case CONNMAN_IPCONFIG_METHOD_OFF:
988                 connman_network_set_ipv4_method(network->network,
989                                                         network->ipv4_method);
990                 break;
991         case CONNMAN_IPCONFIG_METHOD_MANUAL:
992         case CONNMAN_IPCONFIG_METHOD_FIXED:
993                 connman_network_set_ipv4_method(network->network,
994                                                         network->ipv4_method);
995                 connman_network_set_ipaddress(network->network,
996                                                         network->ipv4_address);
997                 setip = TRUE;
998                 break;
999         }
1000
1001         switch (network->ipv6_method) {
1002         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1003         case CONNMAN_IPCONFIG_METHOD_OFF:
1004         case CONNMAN_IPCONFIG_METHOD_DHCP:
1005                 break;
1006         case CONNMAN_IPCONFIG_METHOD_AUTO:
1007                 connman_network_set_ipv6_method(network->network,
1008                                                         network->ipv6_method);
1009                 setip = TRUE;
1010                 break;
1011         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1012         case CONNMAN_IPCONFIG_METHOD_FIXED:
1013                 connman_network_set_ipv6_method(network->network,
1014                                                         network->ipv6_method);
1015                 connman_network_set_ipaddress(network->network,
1016                                                         network->ipv6_address);
1017                 setip = TRUE;
1018                 break;
1019         }
1020
1021         if (setip == TRUE)
1022                 connman_network_set_connected(network->network, connected);
1023 }
1024
1025 static gboolean __set_network_context(
1026                                                         struct telephony_network *network,
1027                                                         DBusMessageIter *dict)
1028 {
1029         int index = 0;
1030         gboolean active = FALSE;
1031         gboolean routing_only = FALSE;
1032         gboolean ipv4_updated = FALSE;
1033         gboolean ipv6_updated = FALSE;
1034         gboolean ipv6_link_only = FALSE;
1035         gboolean default_internet = FALSE;
1036         gboolean active_proxy = FALSE;
1037         char **proxies = NULL;
1038         const char *dev_name = NULL;
1039         const char *proxy_addr = NULL;
1040         char *ipv4_addr = NULL, *ipv4_gw = NULL, *ipv4_netmask = NULL,
1041                                         *ipv4_dns1 = NULL, *ipv4_dns2 = NULL;
1042         char *ipv6_addr = NULL, *ipv6_gw = NULL, *ipv6_netmask = NULL,
1043                                         *ipv6_dns1 = NULL, *ipv6_dns2 = NULL;
1044         struct connman_service *service;
1045
1046         while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) {
1047                 DBusMessageIter entry;
1048                 const char *key, *value;
1049
1050                 dbus_message_iter_recurse(dict, &entry);
1051                 dbus_message_iter_get_basic(&entry, &key);
1052
1053                 dbus_message_iter_next(&entry);
1054
1055                 if (g_strcmp0(key, "dev_name") == 0) {
1056                         dbus_message_iter_get_basic(&entry, &dev_name);
1057                         DBG("dev_name (%s)", dev_name);
1058                 } else if (g_strcmp0(key, "proxy") == 0) {
1059                         dbus_message_iter_get_basic(&entry, &proxy_addr);
1060                         DBG("proxy_addr (%s)", proxy_addr);
1061                 } else if (g_strcmp0(key, "ipv4_address") == 0) {
1062                         dbus_message_iter_get_basic(&entry, &ipv4_addr);
1063                         DBG("ipv4_addr (%s)", ipv4_addr);
1064                 } else if (g_strcmp0(key, "ipv4_gateway") == 0) {
1065                         dbus_message_iter_get_basic(&entry, &ipv4_gw);
1066                         DBG("ipv4_gw (%s)", ipv4_gw);
1067                 } else if (g_strcmp0(key, "ipv4_netmask") == 0) {
1068                         dbus_message_iter_get_basic(&entry, &ipv4_netmask);
1069                         DBG("ipv4_netmask (%s)", ipv4_netmask);
1070                 } else if (g_strcmp0(key, "ipv4_dns1") == 0) {
1071                         dbus_message_iter_get_basic(&entry, &ipv4_dns1);
1072                         DBG("ipv4_dns1 (%s)", ipv4_dns1);
1073                 } else if (g_strcmp0(key, "ipv4_dns2") == 0) {
1074                         dbus_message_iter_get_basic(&entry, &ipv4_dns2);
1075                         DBG("ipv4_dns2 (%s)", ipv4_dns2);
1076                 } else if (g_strcmp0(key, "ipv6_address") == 0) {
1077                         dbus_message_iter_get_basic(&entry, &ipv6_addr);
1078                         DBG("ipv6 address (%s)", ipv6_addr);
1079                 } else if (g_strcmp0(key, "ipv6_gateway") == 0) {
1080                         dbus_message_iter_get_basic(&entry, &ipv6_gw);
1081                         DBG("ipv6_gw (%s)", ipv6_gw);
1082                 } else if (g_strcmp0(key, "ipv6_netmask") == 0) {
1083                         dbus_message_iter_get_basic(&entry, &ipv6_netmask);
1084                         DBG("ipv6_netmask (%s)", ipv6_netmask);
1085                 } else if (g_strcmp0(key, "ipv6_dns1") == 0) {
1086                         dbus_message_iter_get_basic(&entry, &ipv6_dns1);
1087                         DBG("ipv6_dns1 (%s)", ipv6_dns1);
1088                 } else if (g_strcmp0(key, "ipv6_dns2") == 0) {
1089                         dbus_message_iter_get_basic(&entry, &ipv6_dns2);
1090                         DBG("ipv6_dns2 (%s)", ipv6_dns2);
1091                 } else if (g_strcmp0(key, "active") == 0) {
1092                         dbus_message_iter_get_basic(&entry, &value);
1093                         DBG("active (%s)", value);
1094                         active = STRING2BOOL(value);
1095                 } else if (g_strcmp0(key, "routing_only") == 0) {
1096                         dbus_message_iter_get_basic(&entry, &value);
1097                         DBG("routing_only (%s)", value);
1098                         routing_only = STRING2BOOL(value);
1099                         network->routing_only = routing_only;
1100                 } else if (g_strcmp0(key, "ipv6_link_only") == 0) {
1101                         dbus_message_iter_get_basic(&entry, &value);
1102                         DBG("ipv6_link_only (%s)", value);
1103                         ipv6_link_only = STRING2BOOL(value);
1104                         network->ipv6_link_only = ipv6_link_only;
1105                 }
1106                 else if (g_strcmp0(key, "default_internet_conn") == 0) {
1107                         dbus_message_iter_get_basic(&entry, &value);
1108                         DBG("default_internet (%s)", value);
1109                         default_internet = STRING2BOOL(value);
1110                 }
1111
1112                 dbus_message_iter_next(dict);
1113         }
1114
1115         if(routing_only){
1116                 //context active does not effect the connman service status.
1117                 //it only for setting the routing path.
1118                 DBG("routing_only(%d), active(%d)", routing_only, active);
1119                 return active;
1120         }
1121
1122         if (g_strcmp0(proxy_addr, ":") == 0)
1123                 proxy_addr = NULL;
1124         if (g_strcmp0(ipv4_addr, "0.0.0.0") == 0)
1125                 ipv4_addr = NULL;
1126         if (g_strcmp0(ipv4_gw, "0.0.0.0") == 0)
1127                 ipv4_gw = NULL;
1128         if (g_strcmp0(ipv4_netmask, "0.0.0.0") == 0)
1129                 ipv4_netmask = NULL;
1130         if (g_strcmp0(ipv4_dns1, "0.0.0.0") == 0)
1131                 ipv4_dns1 = NULL;
1132         if (g_strcmp0(ipv4_dns2, "0.0.0.0") == 0)
1133                 ipv4_dns2 = NULL;
1134         if (g_strcmp0(ipv6_addr, "::") == 0)
1135                 ipv6_addr = NULL;
1136         if (g_strcmp0(ipv6_gw, "::") == 0)
1137                 ipv6_gw = NULL;
1138         if (g_strcmp0(ipv6_netmask, "::") == 0)
1139                 ipv6_netmask = NULL;
1140         if (g_strcmp0(ipv6_dns1, "::") == 0)
1141                 ipv6_dns1 = NULL;
1142         if (g_strcmp0(ipv6_dns2, "::") == 0)
1143                 ipv6_dns2 = NULL;
1144
1145         connman_network_set_bool(network->network, "DefaultInternet",
1146                                                                 (bool)default_internet);
1147
1148         service = connman_service_lookup_from_network(network->network);
1149         if (service == NULL)
1150                 return FALSE;
1151
1152         if (connman_setting_get_bool("SingleConnectedTechnology") == TRUE) {
1153                 /* Wi-Fi technology is always a top priority */
1154                 if (active == TRUE &&
1155                                 connman_service_is_no_ref_user_pdn_connection(service) == TRUE &&
1156                                 connman_service_get_type(connman_service_get_default_connection())
1157                                         == CONNMAN_SERVICE_TYPE_WIFI) {
1158                         __request_network_deactivate(network->network);
1159
1160                         return FALSE;
1161                 }
1162         }
1163
1164         /* interface index set */
1165         if (dev_name != NULL) {
1166                 index = connman_inet_ifindex(dev_name);
1167                 network->if_index = index;
1168                 DBG("interface index %d", index);
1169         }
1170
1171         /* proxy set */
1172         if (active == TRUE &&
1173                         connman_network_get_connected(network->network) == TRUE)
1174                 active_proxy = TRUE;
1175
1176         proxies = connman_service_get_proxy_servers(service);
1177         if (proxies != NULL) {
1178                 if (proxy_addr == NULL)
1179                         connman_service_set_proxy(service, proxy_addr, active_proxy);
1180                 else if (g_strcmp0(proxy_addr, proxies[0]) != 0)
1181                         connman_service_set_proxy(service, proxy_addr, active_proxy);
1182         } else if (proxy_addr != NULL)
1183                 connman_service_set_proxy(service, proxy_addr, active_proxy);
1184
1185         if (proxies != NULL)
1186                 g_strfreev(proxies);
1187
1188         __connman_service_nameserver_clear(service);
1189
1190         /* ipv4 set */
1191         if (network->ipv4_address == NULL)
1192                 network->ipv4_address =
1193                                 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
1194
1195         if (network->ipv4_address == NULL)
1196                 return FALSE;
1197
1198         if (ipv4_addr == NULL && active == TRUE)
1199                 network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF;
1200         else
1201                 network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
1202
1203         connman_network_set_ipv4_method(network->network, network->ipv4_method);
1204
1205         ipv4_updated = connman_ipaddress_updated(network->ipv4_address,
1206                                                 ipv4_addr, ipv4_gw);
1207         if (ipv4_updated == TRUE)
1208                 connman_ipaddress_set_ipv4(network->ipv4_address, ipv4_addr,
1209                                                 ipv4_netmask, ipv4_gw);
1210
1211         if (ipv4_dns1)
1212 #if defined TIZEN_EXT
1213                 __connman_service_nameserver_append(service, ipv4_dns1, FALSE,
1214                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1215 #else
1216                 __connman_service_nameserver_append(service, ipv4_dns1, FALSE);
1217 #endif
1218         //if (ipv4_dns2)
1219         if (ipv4_dns2 && !ipv4_dns1)
1220 #if defined TIZEN_EXT
1221                 __connman_service_nameserver_append(service, ipv4_dns2, FALSE,
1222                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1223 #else
1224                 __connman_service_nameserver_append(service, ipv4_dns2, FALSE);
1225 #endif
1226         /* ipv6 set */
1227         if (network->ipv6_address == NULL)
1228                 network->ipv6_address =
1229                                 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
1230
1231         if (network->ipv6_address == NULL)
1232                 return FALSE;
1233
1234         if(ipv6_link_only)
1235                 network->ipv6_method = CONNMAN_IPCONFIG_METHOD_AUTO;
1236         else
1237                 network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
1238
1239         if (ipv6_addr == NULL)
1240                 network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
1241
1242         connman_network_set_ipv6_method(network->network, network->ipv6_method);
1243
1244         ipv6_updated = connman_ipaddress_updated(network->ipv6_address,
1245                                                 ipv6_addr, ipv6_gw);
1246         if (ipv6_updated == TRUE)
1247                 connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr,
1248                                                 64, ipv6_gw);
1249
1250         if (ipv6_dns1)
1251 #if defined TIZEN_EXT
1252                 __connman_service_nameserver_append(service, ipv6_dns1, FALSE,
1253                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1254 #else
1255                 __connman_service_nameserver_append(service, ipv6_dns1, FALSE);
1256 #endif
1257         //if (ipv6_dns2)
1258         if (ipv6_dns2 && !ipv6_dns1)
1259 #if defined TIZEN_EXT
1260                 __connman_service_nameserver_append(service, ipv6_dns2, FALSE,
1261                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1262 #else
1263                 __connman_service_nameserver_append(service, ipv6_dns2, FALSE);
1264 #endif
1265
1266         if (active == TRUE &&
1267                         connman_network_get_connected(network->network) == TRUE) {
1268                 if (ipv4_updated == TRUE || ipv6_updated == TRUE) {
1269                         DBG("IPv4 updated %d, IPv6 updated %d", ipv4_updated, ipv6_updated);
1270
1271                         __set_network_connected(network, FALSE);
1272                 } else {
1273                         DBG("Already connected");
1274
1275                         return active;
1276                 }
1277         }
1278
1279         if (active == TRUE)
1280                 connman_network_set_associating(network->network, TRUE);
1281
1282         return active;
1283 }
1284
1285 static int __add_context(struct connman_device *device, const char *path,
1286                                 DBusMessageIter *prop)
1287 {
1288         char *ident;
1289         gboolean active = FALSE;
1290
1291         struct telephony_modem *modem = connman_device_get_data(device);
1292         struct connman_network *network;
1293         struct telephony_network *info;
1294
1295         DBG("modem %p device %p path %s", modem, device, path);
1296
1297         ident = __get_ident(path);
1298
1299         network = connman_device_get_network(device, ident);
1300         if (network != NULL)
1301                 return -EALREADY;
1302
1303         info = g_hash_table_lookup(network_hash, path);
1304         if (info != NULL) {
1305                 DBG("path %p already exists with device %p", path,
1306                         connman_network_get_device(info->network));
1307
1308                 if (connman_network_get_device(info->network))
1309                         return -EALREADY;
1310
1311                 g_hash_table_remove(network_hash, path);
1312         }
1313
1314         network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
1315         if (network == NULL)
1316                 return -ENOMEM;
1317
1318         info = g_try_new0(struct telephony_network, 1);
1319         if (info == NULL) {
1320                 connman_network_unref(network);
1321                 return -ENOMEM;
1322         }
1323
1324         info->path = g_strdup(path);
1325
1326         connman_ipaddress_clear(info->ipv4_address);
1327         connman_ipaddress_clear(info->ipv6_address);
1328
1329         info->network = network;
1330
1331         connman_network_set_string(network, "Path", path);
1332         connman_network_set_name(network, path);
1333
1334         connman_network_set_group(network, ident);
1335
1336         g_hash_table_insert(network_hash, g_strdup(path), info);
1337
1338         connman_network_set_available(network, TRUE);
1339         connman_network_set_bool(network, "Roaming", (bool)modem->s_service->roaming);
1340
1341         if (connman_device_add_network(device, network) != 0) {
1342                 g_hash_table_remove(network_hash, path);
1343                 return -EIO;
1344         }
1345
1346         active = __set_network_context(info, prop);
1347         if(info->routing_only){
1348                 int err = 0;
1349                 struct connman_service *routing_service;
1350                 struct connman_ipconfig *routing_ipconfig;
1351
1352                 if(!active)
1353                         return TRUE;
1354
1355                 routing_service = connman_service_lookup_from_network(info->network);
1356                 routing_ipconfig = __connman_service_get_ip4config(routing_service);
1357                 err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service);
1358
1359                 DBG("set gateway rv(%d)", err);
1360                 return TRUE;
1361         }
1362
1363         if (active == TRUE && (connman_network_get_associating(network) == TRUE ||
1364                         connman_network_get_connecting(network) == TRUE))
1365                 __set_network_connected(info, active);
1366
1367         return 0;
1368 }
1369
1370 static gboolean __changed_modem(DBusConnection *connection,
1371                                 DBusMessage *message, void *user_data)
1372 {
1373         gboolean old_powered;
1374         DBusMessageIter args, dict;
1375         struct telephony_modem *modem;
1376         const char *path = dbus_message_get_path(message);
1377
1378         DBG("modem changed signal %s", path);
1379
1380         modem = g_hash_table_lookup(modem_hash, path);
1381         if (modem == NULL) {
1382                 DBG("modem object does not exists");
1383                 return TRUE;
1384         }
1385
1386         old_powered = modem->powered;
1387
1388         DBG("message signature (%s)", dbus_message_get_signature(message));
1389
1390         if (dbus_message_iter_init(message, &args) == FALSE) {
1391                 DBG("error to read message");
1392                 return TRUE;
1393         }
1394
1395         dbus_message_iter_recurse(&args, &dict);
1396
1397         while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
1398                 DBusMessageIter entry;
1399                 const char *key, *tmp;
1400
1401                 dbus_message_iter_recurse(&dict, &entry);
1402                 dbus_message_iter_get_basic(&entry, &key);
1403
1404                 dbus_message_iter_next(&entry);
1405                 dbus_message_iter_get_basic(&entry, &tmp);
1406
1407                 DBG("key(%s), value(%s)", key, tmp);
1408
1409                 if (g_strcmp0(key, "powered") == 0) {
1410                         modem->powered = STRING2BOOL(tmp);
1411                 } else if (g_strcmp0(key, "operator") == 0) {
1412                         modem->operator = g_strdup(tmp);
1413                 } else if (g_strcmp0(key, "sim_init") == 0) {
1414                         modem->sim_init = STRING2BOOL(tmp);
1415                 } else if (g_strcmp0(key, "flight_mode") == 0) {
1416                         modem->flight_mode = STRING2BOOL(tmp);
1417                 } else if (g_strcmp0(key, "roaming_allowed") == 0) {
1418                         modem->roaming_allowed = STRING2BOOL(tmp);
1419                 } else if (g_strcmp0(key, "data_allowed") == 0) {
1420                         modem->data_allowed = STRING2BOOL(tmp);
1421                 }
1422
1423                 dbus_message_iter_next(&dict);
1424         }
1425
1426         if (modem->device == NULL)
1427                 __add_connman_device(path, modem->operator);
1428
1429         if (old_powered != modem->powered)
1430                 __set_device_powered(modem, modem->powered);
1431
1432         if (modem->powered != TRUE) {
1433                 DBG("modem is not powered");
1434                 return TRUE;
1435         }
1436
1437         if (modem->s_service == NULL) {
1438                 __request_get_services(modem->path);
1439                 return TRUE;
1440         }
1441
1442         DBG("modem(%s) flight mode(%d) data allowed(%d)",
1443                         modem->path, modem->flight_mode, modem->data_allowed);
1444
1445         return TRUE;
1446 }
1447
1448 static gboolean __added_modem(DBusConnection *connection,
1449                                 DBusMessage *message, void *user_data)
1450 {
1451         const char *modem_path = NULL;
1452         DBusMessageIter args, dict, tmp;
1453
1454         DBG("modem added signal (%s)", dbus_message_get_signature(message));
1455
1456         if (dbus_message_iter_init(message, &args) == FALSE) {
1457                 DBG("error to read message");
1458                 return TRUE;
1459         }
1460
1461         dbus_message_iter_recurse(&args, &dict);
1462         memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1463
1464         while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1465                 DBusMessageIter entry;
1466                 const char *key, *value;
1467
1468                 dbus_message_iter_recurse(&tmp, &entry);
1469                 dbus_message_iter_get_basic(&entry, &key);
1470
1471                 dbus_message_iter_next(&entry);
1472                 dbus_message_iter_get_basic(&entry, &value);
1473
1474                 DBG("key (%s) value(%s)", key, value);
1475
1476                 if (g_strcmp0(key, "path") == 0)
1477                         modem_path = g_strdup(value);
1478
1479                 dbus_message_iter_next(&tmp);
1480         }
1481
1482         if (modem_path != NULL)
1483                 __add_modem(modem_path, &dict);
1484
1485         return TRUE;
1486 }
1487
1488 static gboolean __removed_modem(DBusConnection *connection,
1489                                         DBusMessage *message, void *user_data)
1490 {
1491         DBusMessageIter iter;
1492         const char *modem_path;
1493
1494         DBG("modem removed signal");
1495
1496         if (dbus_message_iter_init(message, &iter) == FALSE) {
1497                 DBG("error to read message");
1498                 return TRUE;
1499         }
1500
1501         dbus_message_iter_get_basic(&iter, &modem_path);
1502         g_hash_table_remove(modem_hash, modem_path);
1503
1504         return TRUE;
1505 }
1506
1507 static gboolean __changed_service(DBusConnection *connection,
1508                                         DBusMessage *message, void *user_data)
1509 {
1510         DBusMessageIter args, dict;
1511         struct telephony_modem *modem;
1512         gboolean roaming_option = TRUE;
1513         struct telephony_service *s_service;
1514         const char *service_path = dbus_message_get_path(message);
1515
1516         DBG("service changed signal %s", service_path);
1517
1518         s_service = g_hash_table_lookup(service_hash, service_path);
1519         if (s_service == NULL) {
1520                 DBG("service object does not exists");
1521                 return TRUE;
1522         }
1523
1524         modem = s_service->p_modem;
1525         if (modem == NULL) {
1526                 DBG("modem object does not exists");
1527                 return TRUE;
1528         }
1529
1530         DBG("message signature (%s)", dbus_message_get_signature(message));
1531
1532         if (dbus_message_iter_init(message, &args) == FALSE) {
1533                 DBG("error to read message");
1534                 return TRUE;
1535         }
1536
1537         dbus_message_iter_recurse(&args, &dict);
1538
1539         while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
1540                 DBusMessageIter entry;
1541                 const char *key, *tmp;
1542
1543                 dbus_message_iter_recurse(&dict, &entry);
1544                 dbus_message_iter_get_basic(&entry, &key);
1545
1546                 dbus_message_iter_next(&entry);
1547                 dbus_message_iter_get_basic(&entry, &tmp);
1548
1549                 DBG("key(%s), value(%s)", key, tmp);
1550
1551                 if (g_strcmp0(key, "roaming") == 0) {
1552                         s_service->roaming = STRING2BOOL(tmp);
1553                 } else if (g_strcmp0(key, "act") == 0) {
1554                         s_service->act = g_strdup(tmp);
1555                 } else if (g_strcmp0(key, "ps_attached") == 0) {
1556                         s_service->ps_attached = STRING2BOOL(tmp);
1557                 }
1558
1559                 dbus_message_iter_next(&dict);
1560         }
1561
1562         roaming_option &= (!s_service->roaming && !modem->roaming_allowed)
1563                                 || modem->roaming_allowed;
1564
1565         return TRUE;
1566 }
1567
1568 static gboolean __added_service(DBusConnection *connection,
1569                                 DBusMessage *message, void *user_data)
1570 {
1571         struct telephony_modem *modem;
1572         const char *service_path = NULL;
1573         DBusMessageIter args, dict, tmp;
1574         const char *path = dbus_message_get_path(message);
1575
1576         DBG("service added signal %s", path);
1577
1578         modem = g_hash_table_lookup(modem_hash, path);
1579         if (modem == NULL || modem->device == NULL)
1580                 return TRUE;
1581
1582         DBG("message signature (%s)", dbus_message_get_signature(message));
1583         if (dbus_message_iter_init(message, &args) == FALSE) {
1584                 DBG("error to read message");
1585                 return TRUE;
1586         }
1587
1588         dbus_message_iter_recurse(&args, &dict);
1589         memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1590
1591         while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1592                 DBusMessageIter entry;
1593                 const char *key, *value;
1594
1595                 dbus_message_iter_recurse(&tmp, &entry);
1596                 dbus_message_iter_get_basic(&entry, &key);
1597
1598                 dbus_message_iter_next(&entry);
1599                 dbus_message_iter_get_basic(&entry, &value);
1600
1601                 DBG("key (%s) value(%s)", key, value);
1602
1603                 if (g_strcmp0(key, "path") == 0)
1604                         service_path = value;
1605
1606                 dbus_message_iter_next(&tmp);
1607         }
1608
1609         if (service_path != NULL)
1610                 __add_service(modem, service_path, &dict);
1611
1612         return TRUE;
1613 }
1614
1615 static gboolean __removed_service(DBusConnection *connection,
1616                                         DBusMessage *message, void *user_data)
1617 {
1618         DBusMessageIter iter;
1619         const char *service_path;
1620
1621         DBG("service removed signal");
1622
1623         if (dbus_message_iter_init(message, &iter) == FALSE) {
1624                 DBG("error to read message");
1625                 return TRUE;
1626         }
1627
1628         dbus_message_iter_get_basic(&iter, &service_path);
1629         g_hash_table_remove(service_hash, service_path);
1630
1631         return TRUE;
1632 }
1633
1634 static gboolean __changed_context(DBusConnection *connection,
1635                                         DBusMessage *message, void *user_data)
1636 {
1637         gboolean active = FALSE;
1638         DBusMessageIter args, dict;
1639         struct telephony_network *info;
1640         const char *path = dbus_message_get_path(message);
1641
1642         DBG("network changed signal %s", path);
1643
1644         info = g_hash_table_lookup(network_hash, path);
1645         if (info == NULL)
1646                 return TRUE;
1647
1648         if (__check_network_available(info->network) == FALSE) {
1649                 g_hash_table_remove(network_hash, path);
1650                 return TRUE;
1651         }
1652
1653         if (dbus_message_iter_init(message, &args) == FALSE) {
1654                 DBG("error to read message");
1655                 return TRUE;
1656         }
1657
1658         dbus_message_iter_recurse(&args, &dict);
1659
1660         active = __set_network_context(info, &dict);
1661         if(info->routing_only){
1662                 int err = 0;
1663                 struct connman_service *routing_service;
1664                 struct connman_ipconfig *routing_ipconfig;
1665
1666                 if(!active)
1667                         return TRUE;
1668
1669                 routing_service = connman_service_lookup_from_network(info->network);
1670                 routing_ipconfig = __connman_service_get_ip4config(routing_service);
1671                 err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service);
1672
1673                 DBG("set gateway rv(%d)", err);
1674                 return TRUE;
1675         }
1676
1677         __set_network_connected(info, active);
1678
1679         if (active == FALSE &&
1680                         connman_network_get_connecting(info->network) == TRUE)
1681                 connman_network_set_connected(info->network, FALSE);
1682
1683         return TRUE;
1684 }
1685
1686 static gboolean __added_context(DBusConnection *connection,
1687                                         DBusMessage *message, void *user_data)
1688 {
1689         const char *network_path = NULL;
1690         DBusMessageIter args, dict, tmp;
1691         struct telephony_modem *modem = NULL;
1692         struct telephony_service *service = NULL;
1693         const char *path = dbus_message_get_path(message);
1694
1695         DBG("network added signal %s", path);
1696
1697         service = g_hash_table_lookup(service_hash, path);
1698         if (service == NULL || service->p_modem == NULL)
1699                 return TRUE;
1700
1701         modem = service->p_modem;
1702         if (modem == NULL || modem->device == NULL)
1703                 return TRUE;
1704
1705         DBG("message signature (%s)", dbus_message_get_signature(message));
1706         if (dbus_message_iter_init(message, &args) == FALSE) {
1707                 DBG("error to read message");
1708                 return TRUE;
1709         }
1710
1711         dbus_message_iter_recurse(&args, &dict);
1712         memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1713
1714         while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1715                 DBusMessageIter entry;
1716                 const char *key, *value;
1717
1718                 dbus_message_iter_recurse(&tmp, &entry);
1719                 dbus_message_iter_get_basic(&entry, &key);
1720
1721                 dbus_message_iter_next(&entry);
1722                 dbus_message_iter_get_basic(&entry, &value);
1723
1724                 DBG("key (%s) value(%s)", key, value);
1725
1726                 if (g_strcmp0(key, "path") == 0)
1727                         network_path = g_strdup(value);
1728
1729                 dbus_message_iter_next(&tmp);
1730         }
1731
1732         if (network_path != NULL)
1733                 __add_context(modem->device, network_path, &dict);
1734
1735         return TRUE;
1736 }
1737
1738 static gboolean __removed_context(DBusConnection *connection,
1739                                         DBusMessage *message, void *user_data)
1740 {
1741         DBusMessageIter iter;
1742         const char *network_path = NULL;
1743         struct telephony_service *service = NULL;
1744         const char *path = dbus_message_get_path(message);
1745
1746         DBG("network removed signal %s", path);
1747
1748         service = g_hash_table_lookup(service_hash, path);
1749         if (service == NULL || service->p_modem == NULL)
1750                 return TRUE;
1751
1752         if (dbus_message_iter_init(message, &iter) == FALSE) {
1753                 DBG("error to read message");
1754                 return TRUE;
1755         }
1756
1757         dbus_message_iter_get_basic(&iter, &network_path);
1758         g_hash_table_remove(network_hash, network_path);
1759
1760         return TRUE;
1761 }
1762
1763 static gboolean __changed_default_subscription(DBusConnection *connection,
1764                 DBusMessage *message, void *user_data)
1765 {
1766         DBusMessageIter args;
1767
1768         DBG("message signature (%s)", dbus_message_get_signature(message));
1769         if (dbus_message_iter_init(message, &args) == FALSE)
1770                 return TRUE;
1771
1772         dbus_message_iter_get_basic(&args, &telephony_default_subscription_id);
1773         DBG("default subscription: %d", telephony_default_subscription_id);
1774
1775         return TRUE;
1776 }
1777
1778 /* telephony initialization */
1779 static guint watch = 0;
1780 static guint modem_watch = 0;
1781 static guint modem_added_watch = 0;
1782 static guint modem_removed_watch = 0;
1783 static guint service_watch = 0;
1784 static guint service_added_watch = 0;
1785 static guint service_removed_watch = 0;
1786 static guint context_watch = 0;
1787 static guint context_added_watch = 0;
1788 static guint context_removed_watch = 0;
1789 static guint default_subscription_watch = 0;
1790
1791 static int telephony_init(void)
1792 {
1793         int err;
1794
1795         DBG("telephony plugin");
1796
1797         connection = connman_dbus_get_connection();
1798         if (connection == NULL)
1799                 return -EIO;
1800
1801         /* telephony watch */
1802         watch = g_dbus_add_service_watch(connection, PS_DBUS_SERVICE,
1803                                         telephony_connect, telephony_disconnect,
1804                                         NULL, NULL);
1805
1806         modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1807                                                 PS_MODEM_INTERFACE,
1808                                                 PROPERTY_CHANGED,
1809                                                 __changed_modem,
1810                                                 NULL, NULL);
1811
1812         modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1813                                                 PS_MASTER_INTERFACE,
1814                                                 MODEM_ADDED,
1815                                                 __added_modem,
1816                                                 NULL, NULL);
1817
1818         modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1819                                                 PS_MASTER_INTERFACE,
1820                                                 MODEM_REMOVED,
1821                                                 __removed_modem,
1822                                                 NULL, NULL);
1823
1824         service_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1825                                                 PS_SERVICE_INTERFACE,
1826                                                 PROPERTY_CHANGED,
1827                                                 __changed_service,
1828                                                 NULL, NULL);
1829
1830         service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1831                                                 PS_MODEM_INTERFACE,
1832                                                 SERVICE_ADDED,
1833                                                 __added_service,
1834                                                 NULL, NULL);
1835
1836         service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1837                                                 PS_MODEM_INTERFACE,
1838                                                 SERVICE_REMOVED,
1839                                                 __removed_service,
1840                                                 NULL, NULL);
1841
1842         context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1843                                                 PS_CONTEXT_INTERFACE,
1844                                                 PROPERTY_CHANGED,
1845                                                 __changed_context,
1846                                                 NULL, NULL);
1847
1848         context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1849                                                 PS_SERVICE_INTERFACE,
1850                                                 CONTEXT_ADDED,
1851                                                 __added_context,
1852                                                 NULL, NULL);
1853
1854         context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1855                                                 PS_SERVICE_INTERFACE,
1856                                                 CONTEXT_REMOVED,
1857                                                 __removed_context,
1858                                                 NULL, NULL);
1859
1860         default_subscription_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1861                                                 "org.tizen.telephony.Network",
1862                                                 "DefaultDataSubscription",
1863                                                 __changed_default_subscription,
1864                                                 NULL, NULL);
1865
1866         if (watch == 0 || modem_watch == 0 || modem_added_watch == 0
1867                         || modem_removed_watch == 0 || service_watch == 0
1868                         || service_added_watch == 0 || context_watch == 0
1869                         || service_removed_watch == 0
1870                         || context_added_watch == 0
1871                         || context_removed_watch == 0
1872                         || default_subscription_watch == 0) {
1873                 err = -EIO;
1874                 goto remove;
1875         }
1876
1877         err = connman_network_driver_register(&network_driver);
1878         if (err < 0)
1879                 goto remove;
1880
1881         err = connman_device_driver_register(&modem_driver);
1882         if (err < 0) {
1883                 connman_network_driver_unregister(&network_driver);
1884                 goto remove;
1885         }
1886
1887         err = connman_technology_driver_register(&tech_driver);
1888         if (err < 0) {
1889                 connman_device_driver_unregister(&modem_driver);
1890                 connman_network_driver_unregister(&network_driver);
1891                 goto remove;
1892         }
1893
1894         return 0;
1895
1896 remove:
1897         g_dbus_remove_watch(connection, watch);
1898         g_dbus_remove_watch(connection, modem_watch);
1899         g_dbus_remove_watch(connection, modem_added_watch);
1900         g_dbus_remove_watch(connection, modem_removed_watch);
1901         g_dbus_remove_watch(connection, service_watch);
1902         g_dbus_remove_watch(connection, service_added_watch);
1903         g_dbus_remove_watch(connection, service_removed_watch);
1904         g_dbus_remove_watch(connection, context_watch);
1905         g_dbus_remove_watch(connection, context_added_watch);
1906         g_dbus_remove_watch(connection, context_removed_watch);
1907         g_dbus_remove_watch(connection, default_subscription_watch);
1908
1909         dbus_connection_unref(connection);
1910         return err;
1911 }
1912
1913 static void telephony_exit(void)
1914 {
1915         g_dbus_remove_watch(connection, watch);
1916         g_dbus_remove_watch(connection, modem_watch);
1917         g_dbus_remove_watch(connection, modem_added_watch);
1918         g_dbus_remove_watch(connection, modem_removed_watch);
1919         g_dbus_remove_watch(connection, service_watch);
1920         g_dbus_remove_watch(connection, service_added_watch);
1921         g_dbus_remove_watch(connection, service_removed_watch);
1922         g_dbus_remove_watch(connection, context_watch);
1923         g_dbus_remove_watch(connection, context_added_watch);
1924         g_dbus_remove_watch(connection, context_removed_watch);
1925         g_dbus_remove_watch(connection, default_subscription_watch);
1926
1927         telephony_disconnect(connection, NULL);
1928
1929         connman_device_driver_unregister(&modem_driver);
1930         connman_network_driver_unregister(&network_driver);
1931
1932         dbus_connection_unref(connection);
1933 }
1934
1935 CONNMAN_PLUGIN_DEFINE(telephony, "Samsung Telephony Framework plug-in", VERSION,
1936                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, telephony_init, telephony_exit)