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