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