Remove IPv4 element registration from the oFono plugin
[platform/upstream/connman.git] / plugins / ofono.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  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
28 #include <gdbus.h>
29 #include <string.h>
30
31 #define CONNMAN_API_SUBJECT_TO_CHANGE
32 #include <connman/plugin.h>
33 #include <connman/element.h>
34 #include <connman/device.h>
35 #include <connman/network.h>
36 #include <connman/dbus.h>
37 #include <connman/inet.h>
38 #include <connman/log.h>
39
40 #define OFONO_SERVICE                   "org.ofono"
41
42 #define OFONO_MANAGER_INTERFACE         OFONO_SERVICE ".Manager"
43 #define OFONO_MODEM_INTERFACE           OFONO_SERVICE ".Modem"
44 #define OFONO_GPRS_INTERFACE            OFONO_SERVICE ".DataConnectionManager"
45 #define OFONO_SIM_INTERFACE             OFONO_SERVICE ".SimManager"
46 #define OFONO_PRI_CONTEXT_INTERFACE     OFONO_SERVICE ".PrimaryDataContext"
47 #define OFONO_REGISTRATION_INTERFACE    OFONO_SERVICE ".NetworkRegistration"
48
49 #define PROPERTY_CHANGED                "PropertyChanged"
50 #define GET_PROPERTIES                  "GetProperties"
51 #define SET_PROPERTY                    "SetProperty"
52 #define CREATE_CONTEXT                  "CreateContext"
53
54 #define TIMEOUT 5000
55
56 #define CONTEXT_NAME "3G Connection"
57 #define CONTEXT_TYPE "internet"
58
59 static DBusConnection *connection;
60
61 static GHashTable *modem_hash = NULL;
62
63 struct modem_data {
64         char *path;
65         struct connman_device *device;
66         gboolean available;
67 };
68
69 static int modem_probe(struct connman_device *device)
70 {
71         DBG("device %p", device);
72
73         return 0;
74 }
75
76 static void modem_remove(struct connman_device *device)
77 {
78         DBG("device %p", device);
79 }
80
81 static void powered_reply(DBusPendingCall *call, void *user_data)
82 {
83         DBusMessage *reply;
84         DBusError error;
85
86         DBG("");
87
88         dbus_error_init(&error);
89
90         reply = dbus_pending_call_steal_reply(call);
91
92         if (dbus_set_error_from_message(&error, reply)) {
93                 connman_error("%s", error.message);
94                 dbus_error_free(&error);
95         }
96
97         dbus_message_unref(reply);
98
99         dbus_pending_call_unref(call);
100 }
101
102 static int gprs_change_powered(const char *path, dbus_bool_t powered)
103 {
104         DBusMessage *message;
105         DBusMessageIter iter;
106         DBusPendingCall *call;
107
108         DBG("path %s powered %d", path, powered);
109
110         if (path == NULL)
111                 return -EINVAL;
112
113         message = dbus_message_new_method_call(OFONO_SERVICE, path,
114                                         OFONO_GPRS_INTERFACE, SET_PROPERTY);
115         if (message == NULL)
116                 return -ENOMEM;
117
118         dbus_message_set_auto_start(message, FALSE);
119
120         dbus_message_iter_init_append(message, &iter);
121         connman_dbus_property_append_basic(&iter, "Powered",
122                                                 DBUS_TYPE_BOOLEAN, &powered);
123
124         if (dbus_connection_send_with_reply(connection, message,
125                                                 &call, TIMEOUT) == FALSE) {
126                 connman_error("Failed to change powered property");
127                 dbus_message_unref(message);
128                 return -EINVAL;
129         }
130
131         if (call == NULL) {
132                 connman_error("D-Bus connection not available");
133                 dbus_message_unref(message);
134                 return -EINVAL;
135         }
136
137         dbus_pending_call_set_notify(call, powered_reply, (void *)path, NULL);
138
139         dbus_message_unref(message);
140
141         return -EINPROGRESS;
142 }
143
144 static int modem_enable(struct connman_device *device)
145 {
146         const char *path = connman_device_get_string(device, "Path");
147
148         DBG("device %p, path, %s", device, path);
149
150         return gprs_change_powered(path, TRUE);
151 }
152
153 static int modem_disable(struct connman_device *device)
154 {
155         const char *path = connman_device_get_string(device, "Path");
156
157         DBG("device %p, path %s", device, path);
158
159         return gprs_change_powered(path, FALSE);
160 }
161
162 static struct connman_device_driver modem_driver = {
163         .name           = "modem",
164         .type           = CONNMAN_DEVICE_TYPE_CELLULAR,
165         .probe          = modem_probe,
166         .remove         = modem_remove,
167         .enable         = modem_enable,
168         .disable        = modem_disable,
169 };
170
171 static char *get_ident(const char *path)
172 {
173         char *pos;
174
175         if (*path != '/')
176                 return NULL;
177
178         pos = strrchr(path, '/');
179         if (pos == NULL)
180                 return NULL;
181
182         return g_strdup(pos + 1);
183 }
184
185 static void create_service(struct connman_network *network)
186 {
187         const char *path;
188         char *group;
189
190         DBG("");
191
192         path = connman_network_get_string(network, "Path");
193
194         group = get_ident(path);
195
196         connman_network_set_group(network, group);
197
198         g_free(group);
199 }
200
201 static void set_network_name_reply(DBusPendingCall *call, void *user_data)
202 {
203         struct connman_network *network = user_data;
204         DBusMessage *reply;
205         DBusMessageIter array, dict;
206
207         DBG("network %p", network);
208
209         reply = dbus_pending_call_steal_reply(call);
210
211         if (dbus_message_iter_init(reply, &array) == FALSE)
212                 goto done;
213
214         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
215                 goto done;
216
217         dbus_message_iter_recurse(&array, &dict);
218
219         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
220                 DBusMessageIter entry, value;
221                 const char *key;
222
223                 dbus_message_iter_recurse(&dict, &entry);
224                 dbus_message_iter_get_basic(&entry, &key);
225
226                 dbus_message_iter_next(&entry);
227                 dbus_message_iter_recurse(&entry, &value);
228
229                 /*
230                  * 'Operator' is deprecated since version 0.20, but
231                  * keep it here for backward compatibility reasons.
232                  */
233                 if (g_str_equal(key, "Operator") == TRUE ||
234                                 g_str_equal(key, "Name") == TRUE) {
235                         const char *name;
236
237                         dbus_message_iter_get_basic(&value, &name);
238                         connman_network_set_name(network, name);
239                         create_service(network);
240                 }
241
242                 dbus_message_iter_next(&dict);
243         }
244 done:
245         dbus_message_unref(reply);
246
247         dbus_pending_call_unref(call);
248 }
249
250 static void set_network_name(struct connman_network *network)
251 {
252         struct connman_device *device;
253         DBusMessage *message;
254         DBusPendingCall *call;
255         const char *path;
256
257         device = connman_network_get_device(network);
258
259         path = connman_device_get_string(device, "Path");
260         if (path == NULL)
261                 return;
262
263         DBG("path %s", path);
264
265         message = dbus_message_new_method_call(OFONO_SERVICE, path,
266                                 OFONO_REGISTRATION_INTERFACE, GET_PROPERTIES);
267         if (message == NULL)
268                 return;
269
270         dbus_message_set_auto_start(message, FALSE);
271
272         if (dbus_connection_send_with_reply(connection, message,
273                                                 &call, TIMEOUT) == FALSE) {
274                 connman_error("Failed to get operator");
275                 goto done;
276         }
277
278         if (call == NULL) {
279                 connman_error("D-Bus connection not available");
280                 goto done;
281         }
282
283         dbus_pending_call_set_notify(call, set_network_name_reply,
284                                                 (void *)network, NULL);
285
286 done:
287         dbus_message_unref(message);
288 }
289
290 static void config_network_reply(DBusPendingCall *call, void *user_data)
291 {
292         struct connman_network *network = user_data;
293         DBusMessage *reply;
294         DBusMessageIter array, dict;
295         gboolean internet_type = FALSE;
296
297         DBG("network %p", network);
298
299         reply = dbus_pending_call_steal_reply(call);
300
301         if (dbus_message_iter_init(reply, &array) == FALSE)
302                 goto done;
303
304         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
305                 goto done;
306
307         dbus_message_iter_recurse(&array, &dict);
308
309         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
310                 DBusMessageIter entry, value;
311                 const char *key;
312
313                 dbus_message_iter_recurse(&dict, &entry);
314                 dbus_message_iter_get_basic(&entry, &key);
315
316                 dbus_message_iter_next(&entry);
317                 dbus_message_iter_recurse(&entry, &value);
318
319                 if (g_str_equal(key, "Type") == TRUE) {
320                         const char *type;
321
322                         dbus_message_iter_get_basic(&value, &type);
323                         if (g_strcmp0(type, "internet") == 0) {
324                                 internet_type = TRUE;
325
326                                 connman_network_set_protocol(network,
327                                                 CONNMAN_NETWORK_PROTOCOL_IP);
328                                 set_network_name(network);
329                         } else {
330                                 internet_type = FALSE;
331
332                                 connman_network_set_protocol(network,
333                                         CONNMAN_NETWORK_PROTOCOL_UNKNOWN);
334                         }
335                 }
336
337                 dbus_message_iter_next(&dict);
338         }
339
340 done:
341         dbus_message_unref(reply);
342
343         dbus_pending_call_unref(call);
344 }
345
346 static void config_network(struct connman_network *network, const char *path)
347 {
348         DBusMessage *message;
349         DBusPendingCall *call;
350
351         DBG("path %s", path);
352
353         message = dbus_message_new_method_call(OFONO_SERVICE, path,
354                                 OFONO_PRI_CONTEXT_INTERFACE, GET_PROPERTIES);
355         if (message == NULL)
356                 return;
357
358         dbus_message_set_auto_start(message, FALSE);
359
360         if (dbus_connection_send_with_reply(connection, message,
361                                                 &call, TIMEOUT) == FALSE) {
362                 connman_error("Failed to get Primary Context");
363                 goto done;
364         }
365
366         if (call == NULL) {
367                 connman_error("D-Bus connection not available");
368                 goto done;
369         }
370
371         dbus_pending_call_set_notify(call, config_network_reply,
372                                                 (void *)network, NULL);
373
374 done:
375         dbus_message_unref(message);
376 }
377
378 static int network_probe(struct connman_network *network)
379 {
380         const char *path;
381
382         path = connman_network_get_string(network, "Path");
383
384         DBG("network %p path %s", network, path);
385
386         config_network(network, path);
387
388         return 0;
389 }
390
391 static struct connman_network *pending_network;
392
393 static gboolean pending_network_is_available(
394                 struct connman_network *pending_network)
395 {
396         struct connman_device *device;
397         struct connman_network *network;
398         const char *identifier;
399         char *ident;
400
401         /* Modem may be removed during waiting for active reply */
402         device  = connman_network_get_device(pending_network);
403         if (device == NULL) {
404                 DBG("Modem is removed");
405                 return FALSE;
406         }
407
408         identifier = connman_network_get_identifier(pending_network);
409
410         ident = g_strdup(identifier);
411
412         connman_network_unref(pending_network);
413
414         /* network may be removed during waiting for active reply */
415         network = connman_device_get_network(device, ident);
416
417         g_free(ident);
418
419         if (network == NULL)
420                 return FALSE;
421
422         return TRUE;
423 }
424
425 static void set_active_reply(DBusPendingCall *call, void *user_data)
426 {
427         DBusMessage *reply;
428         DBusError error;
429         struct connman_network *network = user_data;
430
431         DBG("network %p", network);
432
433         reply = dbus_pending_call_steal_reply(call);
434
435         if (pending_network_is_available(network) == FALSE)
436                 goto done;
437
438         dbus_error_init(&error);
439         if (dbus_set_error_from_message(&error, reply)) {
440                 if (connman_network_get_index(network) < 0)
441                         connman_network_set_error(network,
442                                 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
443
444                 pending_network = NULL;
445
446                 connman_error("%s", error.message);
447
448                 dbus_error_free(&error);
449         } else
450                 pending_network = network;
451
452 done:
453         dbus_message_unref(reply);
454
455         dbus_pending_call_unref(call);
456 }
457
458 static int set_network_active(struct connman_network *network,
459                                                 dbus_bool_t active)
460 {
461         DBusMessage *message;
462         DBusPendingCall *call;
463         DBusMessageIter iter;
464
465         const char *path = connman_network_get_string(network, "Path");
466
467         DBG("network %p, path %s, active %d", network, path, active);
468
469         if (path == NULL)
470                 return -EINVAL;
471
472         message = dbus_message_new_method_call(OFONO_SERVICE, path,
473                                 OFONO_PRI_CONTEXT_INTERFACE, SET_PROPERTY);
474         if (message == NULL)
475                 return -ENOMEM;
476
477         dbus_message_set_auto_start(message, FALSE);
478
479         dbus_message_iter_init_append(message, &iter);
480         connman_dbus_property_append_basic(&iter, "Active",
481                                                 DBUS_TYPE_BOOLEAN, &active);
482
483         if (dbus_connection_send_with_reply(connection, message,
484                                         &call, TIMEOUT * 10) == FALSE) {
485                 connman_error("Failed to connect service");
486                 dbus_message_unref(message);
487                 return -EINVAL;
488         }
489
490         if (call == NULL) {
491                 connman_error("D-Bus connection not available");
492                 dbus_message_unref(message);
493                 return -EINVAL;
494         }
495
496         connman_network_ref(network);
497
498         dbus_pending_call_set_notify(call, set_active_reply, network, NULL);
499
500         dbus_message_unref(message);
501
502         if (active == TRUE)
503                 return -EINPROGRESS;
504
505         return 0;
506 }
507
508 static void set_apn_reply(DBusPendingCall *call, void *user_data)
509 {
510         DBusMessage *reply;
511         DBusError error;
512
513         reply = dbus_pending_call_steal_reply(call);
514
515         dbus_error_init(&error);
516         if (dbus_set_error_from_message(&error, reply)) {
517                 connman_error("%s", error.message);
518
519                 dbus_error_free(&error);
520         }
521
522         dbus_message_unref(reply);
523
524         dbus_pending_call_unref(call);
525 }
526
527 static void set_apn(struct connman_network *network)
528 {
529         DBusMessage *message;
530         DBusPendingCall *call;
531         DBusMessageIter iter;
532         const char *apn, *path;
533
534         apn = connman_network_get_string(network, "Cellular.APN");
535         if (apn == NULL)
536                 return;
537
538         path = connman_network_get_string(network, "Path");
539         if (path == NULL)
540                 return;
541
542         DBG("path %s, apn %s", path, apn);
543
544         message = dbus_message_new_method_call(OFONO_SERVICE, path,
545                                 OFONO_PRI_CONTEXT_INTERFACE, SET_PROPERTY);
546         if (message == NULL)
547                 return;
548
549         dbus_message_set_auto_start(message, FALSE);
550
551         dbus_message_iter_init_append(message, &iter);
552         connman_dbus_property_append_basic(&iter, "AccessPointName",
553                                                 DBUS_TYPE_STRING, &apn);
554
555         if (dbus_connection_send_with_reply(connection, message,
556                                         &call, TIMEOUT) == FALSE) {
557                 dbus_message_unref(message);
558                 return;
559         }
560
561         if (call == NULL) {
562                 connman_error("D-Bus connection not available");
563                 dbus_message_unref(message);
564                 return;
565         }
566
567         dbus_pending_call_set_notify(call, set_apn_reply, NULL, NULL);
568
569         dbus_message_unref(message);
570 }
571
572 static int network_connect(struct connman_network *network)
573 {
574         if (connman_network_get_index(network) >= 0)
575                 return -EISCONN;
576
577         return set_network_active(network, TRUE);
578 }
579
580 static int network_disconnect(struct connman_network *network)
581 {
582         if (connman_network_get_index(network) < 0)
583                 return -ENOTCONN;
584
585         return set_network_active(network, FALSE);
586 }
587
588 static void network_remove(struct connman_network *network)
589 {
590         DBG("network %p", network);
591 }
592
593 static int network_setup(struct connman_network *network, const char *key)
594 {
595         DBG("");
596
597         if (g_strcmp0(key, "Cellular.APN") == 0)
598                 set_apn(network);
599
600         return 0;
601 }
602
603 static struct connman_network_driver network_driver = {
604         .name           = "network",
605         .type           = CONNMAN_NETWORK_TYPE_CELLULAR,
606         .probe          = network_probe,
607         .remove         = network_remove,
608         .connect        = network_connect,
609         .disconnect     = network_disconnect,
610         .setup          = network_setup,
611 };
612
613 static void add_network(struct connman_device *device, const char *path)
614 {
615         struct connman_network *network;
616         char *ident;
617         const char *mcc;
618         const char *mnc;
619
620         DBG("device %p path %s", device, path);
621
622         network = connman_device_get_network(device, path);
623         if (network != NULL)
624                 return;
625
626         ident = get_ident(path);
627
628         network = connman_network_create(ident,
629                                         CONNMAN_NETWORK_TYPE_CELLULAR);
630         if (network == NULL)
631                 return;
632
633         g_free(ident);
634
635         connman_network_set_string(network, "Path", path);
636         connman_network_set_available(network, TRUE);
637         connman_network_set_index(network, -1);
638
639         mcc = connman_device_get_string(device, "MCC");
640         if (mcc != NULL)
641                 connman_network_set_string(network, "Cellular.MCC", mcc);
642
643         mnc = connman_device_get_string(device, "MNC");
644         if (mnc != NULL)
645                 connman_network_set_string(network, "Cellular.MNC", mnc);
646
647         connman_device_add_network(device, network);
648 }
649
650 static void add_networks(struct connman_device *device, DBusMessageIter *array)
651 {
652         DBusMessageIter entry;
653
654         DBG("");
655
656         dbus_message_iter_recurse(array, &entry);
657
658         while (dbus_message_iter_get_arg_type(&entry) ==
659                                         DBUS_TYPE_OBJECT_PATH) {
660                 const char *path;
661
662                 dbus_message_iter_get_basic(&entry, &path);
663
664                 add_network(device, path);
665
666                 dbus_message_iter_next(&entry);
667         }
668 }
669
670 static void create_context_reply(DBusPendingCall *call, void *user_data)
671 {
672         DBusMessage *reply;
673         DBusError error;
674
675         DBG("");
676
677         dbus_error_init(&error);
678
679         reply = dbus_pending_call_steal_reply(call);
680
681         if (dbus_set_error_from_message(&error, reply)) {
682                 connman_error("%s", error.message);
683                 dbus_error_free(&error);
684         }
685
686         dbus_message_unref(reply);
687
688         dbus_pending_call_unref(call);
689 }
690
691 static void add_default_context(DBusMessageIter *array,
692                 const char *path, const char *name, const char *type)
693 {
694         DBusMessageIter entry;
695         DBusMessage *message;
696         DBusPendingCall *call;
697
698         if (path == NULL)
699                 return;
700
701         DBG("");
702
703         dbus_message_iter_recurse(array, &entry);
704
705         if (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_OBJECT_PATH)
706                 return;
707
708         DBG("path %s, name %s, type %s", path, name, type);
709
710         message = dbus_message_new_method_call(OFONO_SERVICE, path,
711                                         OFONO_GPRS_INTERFACE, CREATE_CONTEXT);
712         if (message == NULL)
713                 return;
714
715         dbus_message_set_auto_start(message, FALSE);
716
717         dbus_message_append_args(message, DBUS_TYPE_STRING,
718                                         &name, DBUS_TYPE_STRING,
719                                                 &type, DBUS_TYPE_INVALID);
720
721         if (dbus_connection_send_with_reply(connection, message,
722                                                 &call, TIMEOUT) == FALSE) {
723                 connman_error("Failed to create default context");
724                 dbus_message_unref(message);
725                 return;
726         }
727
728         if (call == NULL) {
729                 connman_error("D-Bus connection not available");
730                 dbus_message_unref(message);
731                 return;
732         }
733
734         dbus_pending_call_set_notify(call, create_context_reply, NULL, NULL);
735
736         dbus_message_unref(message);
737 }
738
739 static void check_networks_reply(DBusPendingCall *call, void *user_data)
740 {
741         struct connman_device *device = user_data;
742         DBusMessage *reply;
743         DBusMessageIter array, dict, contexts;
744         dbus_bool_t attached;
745
746         DBG("device %p", device);
747
748         reply = dbus_pending_call_steal_reply(call);
749
750         if (dbus_message_iter_init(reply, &array) == FALSE)
751                 goto done;
752
753         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
754                 goto done;
755
756         dbus_message_iter_recurse(&array, &dict);
757
758         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
759                 DBusMessageIter entry, value;
760                 const char *key;
761
762                 dbus_message_iter_recurse(&dict, &entry);
763                 dbus_message_iter_get_basic(&entry, &key);
764
765                 dbus_message_iter_next(&entry);
766                 dbus_message_iter_recurse(&entry, &value);
767
768                 DBG("key %s", key);
769
770                 if (g_str_equal(key, "Attached") == TRUE) {
771                         dbus_message_iter_get_basic(&value, &attached);
772                         DBG("Attached %d", attached);
773                 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
774                         const char *path;
775
776                         path = connman_device_get_string(device, "Path");
777                         contexts = value;
778                         add_default_context(&contexts, path,
779                                         CONTEXT_NAME, CONTEXT_TYPE);
780                 } else if (g_str_equal(key, "Powered") == TRUE) {
781                         dbus_bool_t powered;
782
783                         dbus_message_iter_get_basic(&value, &powered);
784
785                         connman_device_set_powered(device, powered);
786                 }
787
788                 dbus_message_iter_next(&dict);
789         }
790
791         if (attached == TRUE)
792                 add_networks(device, &contexts);
793
794 done:
795         dbus_message_unref(reply);
796
797         dbus_pending_call_unref(call);
798 }
799
800 static void check_networks(struct modem_data *modem)
801 {
802         DBusMessage *message;
803         DBusPendingCall *call;
804         struct connman_device *device;
805
806         DBG("modem %p", modem);
807
808         if (modem == NULL)
809                 return;
810
811         device = modem->device;
812         if (device == NULL)
813                 return;
814
815         message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
816                                         OFONO_GPRS_INTERFACE, GET_PROPERTIES);
817         if (message == NULL)
818                 return;
819
820         dbus_message_set_auto_start(message, FALSE);
821
822         if (dbus_connection_send_with_reply(connection, message,
823                                                 &call, TIMEOUT) == FALSE) {
824                 connman_error("Failed to get ofono GPRS");
825                 goto done;
826         }
827
828         if (call == NULL) {
829                 connman_error("D-Bus connection not available");
830                 goto done;
831         }
832
833         dbus_pending_call_set_notify(call, check_networks_reply,
834                                                 (void *)device, NULL);
835
836 done:
837         dbus_message_unref(message);
838 }
839
840 static void add_device(const char *path, const char *imsi,
841                                 const char *mcc, const char *mnc)
842 {
843         struct modem_data *modem;
844         struct connman_device *device;
845
846         DBG("path %s imsi %s", path, imsi);
847
848         if (path == NULL)
849                 return;
850
851         if (imsi == NULL)
852                 return;
853
854         modem = g_hash_table_lookup(modem_hash, path);
855         if (modem == NULL)
856                 return;
857
858         device = connman_device_create(imsi, CONNMAN_DEVICE_TYPE_CELLULAR);
859         if (device == NULL)
860                 return;
861
862         connman_device_set_ident(device, imsi);
863
864         connman_device_set_mode(device, CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE);
865
866         connman_device_set_string(device, "Path", path);
867         if (mcc != NULL)
868                 connman_device_set_string(device, "MCC", mcc);
869         if (mnc != NULL)
870                 connman_device_set_string(device, "MNC", mnc);
871
872         if (connman_device_register(device) < 0) {
873                 connman_device_unref(device);
874                 return;
875         }
876
877         modem->device = device;
878
879         check_networks(modem);
880 }
881
882 static void sim_properties_reply(DBusPendingCall *call, void *user_data)
883 {
884         const char *path = user_data;
885         const char *imsi;
886         char *mcc = NULL;
887         char *mnc = NULL;
888         /* If MobileNetworkCodeLength is not provided, mnc_length is 0 */
889         unsigned char mnc_length = 0;
890         DBusMessage *reply;
891         DBusMessageIter array, dict;
892
893         DBG("path %s", path);
894
895         reply = dbus_pending_call_steal_reply(call);
896
897         if (dbus_message_iter_init(reply, &array) == FALSE)
898                 goto done;
899
900         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
901                 goto done;
902
903         dbus_message_iter_recurse(&array, &dict);
904
905         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
906                 DBusMessageIter entry, value;
907                 const char *key;
908
909                 dbus_message_iter_recurse(&dict, &entry);
910                 dbus_message_iter_get_basic(&entry, &key);
911
912                 dbus_message_iter_next(&entry);
913                 dbus_message_iter_recurse(&entry, &value);
914
915                 if (g_str_equal(key, "SubscriberIdentity") == TRUE)
916                         dbus_message_iter_get_basic(&value, &imsi);
917                 /*
918                  * 'MobileNetworkCodeLength' is deprecated since version 0.20, but
919                  * keep it here for backward compatibility reasons.
920                  */
921                 else if (g_str_equal(key, "MobileNetworkCodeLength") == TRUE)
922                         dbus_message_iter_get_basic(&value,
923                                                 (void *) &mnc_length);
924                 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
925                         dbus_message_iter_get_basic(&value,
926                                                 (void *) &mcc);
927                 else if (g_str_equal(key, "MobileNetworkCode") == TRUE)
928                         dbus_message_iter_get_basic(&value,
929                                                 (void *) &mnc);
930
931                 dbus_message_iter_next(&dict);
932         }
933
934         if (mnc_length == 2 || mnc_length == 3) {
935                 mcc = g_strndup(imsi, 3);
936                 mnc = g_strndup(imsi + 3, mnc_length);
937         }
938
939         add_device(path, imsi, mcc, mnc);
940
941         if (mnc_length == 2 || mnc_length == 3) {
942                 g_free(mcc);
943                 g_free(mnc);
944         }
945
946 done:
947         dbus_message_unref(reply);
948
949         dbus_pending_call_unref(call);
950 }
951
952 static void get_imsi(const char *path)
953 {
954         DBusMessage *message;
955         DBusPendingCall *call;
956
957         DBG("path %s", path);
958
959         message = dbus_message_new_method_call(OFONO_SERVICE, path,
960                                 OFONO_SIM_INTERFACE, GET_PROPERTIES);
961         if (message == NULL)
962                 return;
963
964         dbus_message_set_auto_start(message, FALSE);
965
966         if (dbus_connection_send_with_reply(connection, message,
967                                                 &call, TIMEOUT) == FALSE) {
968                 connman_error("Failed to get ofono modem sim");
969                 goto done;
970         }
971
972         if (call == NULL) {
973                 connman_error("D-Bus connection not available");
974                 goto done;
975         }
976
977         dbus_pending_call_set_notify(call, sim_properties_reply,
978                                                 (void *)path, NULL);
979
980 done:
981         dbus_message_unref(message);
982 }
983
984 static int modem_change_powered(const char *path, dbus_bool_t powered)
985 {
986         DBusMessage *message;
987         DBusMessageIter iter;
988         DBusPendingCall *call;
989
990         DBG("path %s powered %d", path, powered);
991
992         if (path == NULL)
993                 return -EINVAL;
994
995         message = dbus_message_new_method_call(OFONO_SERVICE, path,
996                                         OFONO_MODEM_INTERFACE, SET_PROPERTY);
997         if (message == NULL)
998                 return -ENOMEM;
999
1000         dbus_message_set_auto_start(message, FALSE);
1001
1002         dbus_message_iter_init_append(message, &iter);
1003         connman_dbus_property_append_basic(&iter, "Powered",
1004                                                 DBUS_TYPE_BOOLEAN, &powered);
1005
1006         if (dbus_connection_send_with_reply(connection, message,
1007                                                 &call, TIMEOUT) == FALSE) {
1008                 connman_error("Failed to change powered property");
1009                 dbus_message_unref(message);
1010                 return -EINVAL;
1011         }
1012
1013         if (call == NULL) {
1014                 connman_error("D-Bus connection not available");
1015                 dbus_message_unref(message);
1016                 return -EINVAL;
1017         }
1018
1019         dbus_pending_call_set_notify(call, powered_reply, NULL, NULL);
1020
1021         dbus_message_unref(message);
1022
1023         return -EINPROGRESS;
1024 }
1025
1026 static struct modem_data *add_modem(const char *path)
1027 {
1028         struct modem_data *modem;
1029
1030         if (path == NULL)
1031                 return NULL;
1032
1033         modem = g_hash_table_lookup(modem_hash, path);
1034         if (modem != NULL) {
1035                 modem->available = TRUE;
1036
1037                 return modem;
1038         }
1039
1040         modem = g_try_new0(struct modem_data, 1);
1041         if (modem == NULL)
1042                 return NULL;
1043
1044         modem->path = g_strdup(path);
1045         modem->device = NULL;
1046         modem->available = TRUE;
1047
1048         g_hash_table_insert(modem_hash, g_strdup(path), modem);
1049
1050         return modem;
1051 }
1052
1053 static gboolean modem_has_gprs(DBusMessageIter *array)
1054 {
1055         DBusMessageIter entry;
1056
1057         dbus_message_iter_recurse(array, &entry);
1058
1059         while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1060                 const char *interface;
1061
1062                 dbus_message_iter_get_basic(&entry, &interface);
1063
1064                 if (g_strcmp0(OFONO_GPRS_INTERFACE, interface) == 0)
1065                         return TRUE;
1066
1067                 dbus_message_iter_next(&entry);
1068         }
1069
1070         return FALSE;
1071 }
1072
1073 static void modem_properties_reply(DBusPendingCall *call, void *user_data)
1074 {
1075         DBusMessage *reply;
1076         DBusMessageIter array, dict;
1077         const char *path = user_data;
1078
1079         DBG("path %s", path);
1080
1081         reply = dbus_pending_call_steal_reply(call);
1082
1083         if (dbus_message_iter_init(reply, &array) == FALSE)
1084                 goto done;
1085
1086         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1087                 goto done;
1088
1089         dbus_message_iter_recurse(&array, &dict);
1090
1091         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1092                 DBusMessageIter entry, value;
1093                 const char *key;
1094                 dbus_bool_t powered;
1095
1096                 dbus_message_iter_recurse(&dict, &entry);
1097                 dbus_message_iter_get_basic(&entry, &key);
1098
1099                 dbus_message_iter_next(&entry);
1100                 dbus_message_iter_recurse(&entry, &value);
1101
1102                 if (g_str_equal(key, "Powered") == TRUE) {
1103                         dbus_message_iter_get_basic(&value, &powered);
1104
1105                         if (powered == FALSE) {
1106                                 modem_change_powered(path, TRUE);
1107                                 break;
1108                         }
1109                 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1110                         if (modem_has_gprs(&value) == TRUE)
1111                                 get_imsi(path);
1112                 }
1113
1114                 dbus_message_iter_next(&dict);
1115         }
1116
1117 done:
1118         dbus_message_unref(reply);
1119
1120         dbus_pending_call_unref(call);
1121 }
1122
1123 static void get_modem_properties(struct modem_data *modem)
1124 {
1125         DBusMessage *message;
1126         DBusPendingCall *call;
1127
1128         DBG("path %s", modem->path);
1129
1130         if (modem->path == NULL)
1131                 return;
1132
1133         message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
1134                                 OFONO_MODEM_INTERFACE, GET_PROPERTIES);
1135         if (message == NULL)
1136                 return;
1137
1138         dbus_message_set_auto_start(message, FALSE);
1139
1140         if (dbus_connection_send_with_reply(connection, message,
1141                                                 &call, TIMEOUT) == FALSE) {
1142                 connman_error("Failed to get ofono modem");
1143                 goto done;
1144         }
1145
1146         if (call == NULL) {
1147                 connman_error("D-Bus connection not available");
1148                 goto done;
1149         }
1150
1151         dbus_pending_call_set_notify(call, modem_properties_reply,
1152                                                 (void *)modem->path, NULL);
1153
1154 done:
1155         dbus_message_unref(message);
1156 }
1157
1158 static void mask_unavailable(gpointer key, gpointer value, gpointer user_data)
1159 {
1160         struct modem_data *modem = value;
1161
1162         modem->available = FALSE;
1163 }
1164
1165 static void modems_set_unavailable()
1166 {
1167         g_hash_table_foreach(modem_hash, mask_unavailable, NULL);
1168 }
1169
1170 static void cleanup_modem(gpointer key, gpointer value, gpointer user_data)
1171 {
1172         struct modem_data *modem = value;
1173
1174         if (modem->available == FALSE)
1175                 g_hash_table_remove(modem_hash, key);
1176 }
1177
1178 static void cleanup_modems()
1179 {
1180         g_hash_table_foreach(modem_hash, cleanup_modem, NULL);
1181 }
1182
1183 static void update_modems(DBusMessageIter *array)
1184 {
1185         DBusMessageIter entry;
1186
1187         dbus_message_iter_recurse(array, &entry);
1188
1189         modems_set_unavailable();
1190
1191         while (dbus_message_iter_get_arg_type(&entry) ==
1192                                         DBUS_TYPE_OBJECT_PATH) {
1193                 const char *path;
1194                 struct modem_data *modem;
1195
1196                 dbus_message_iter_get_basic(&entry, &path);
1197
1198                 modem = add_modem(path);
1199                 if (modem != NULL)
1200                         get_modem_properties(modem);
1201
1202                 dbus_message_iter_next(&entry);
1203         }
1204
1205         cleanup_modems();
1206 }
1207
1208 static void manager_properties_reply(DBusPendingCall *call, void *user_data)
1209 {
1210         DBusMessage *reply;
1211         DBusMessageIter array, dict;
1212
1213         DBG("");
1214
1215         reply = dbus_pending_call_steal_reply(call);
1216
1217         if (dbus_message_iter_init(reply, &array) == FALSE)
1218                 goto done;
1219
1220         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1221                 goto done;
1222
1223         dbus_message_iter_recurse(&array, &dict);
1224
1225         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1226                 DBusMessageIter entry, value;
1227                 const char *key;
1228
1229                 dbus_message_iter_recurse(&dict, &entry);
1230                 dbus_message_iter_get_basic(&entry, &key);
1231
1232                 dbus_message_iter_next(&entry);
1233                 dbus_message_iter_recurse(&entry, &value);
1234
1235                 if (g_str_equal(key, "Modems") == TRUE) {
1236                         update_modems(&value);
1237                         break;
1238                 }
1239
1240                 dbus_message_iter_next(&dict);
1241         }
1242
1243 done:
1244         dbus_message_unref(reply);
1245
1246         dbus_pending_call_unref(call);
1247 }
1248
1249 static void modem_remove_device(struct modem_data *modem)
1250 {
1251         if (modem->device == NULL)
1252                 return;
1253
1254         connman_device_unregister(modem->device);
1255         connman_device_unref(modem->device);
1256
1257         modem->device = NULL;
1258 }
1259
1260 static void remove_modem(gpointer data)
1261 {
1262         struct modem_data *modem = data;
1263
1264         g_free(modem->path);
1265
1266         modem_remove_device(modem);
1267
1268         g_free(modem);
1269 }
1270
1271 static void ofono_connect(DBusConnection *connection, void *user_data)
1272 {
1273         DBusMessage *message;
1274         DBusPendingCall *call;
1275
1276         DBG("connection %p", connection);
1277
1278         modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1279                                                 g_free, remove_modem);
1280
1281         message = dbus_message_new_method_call(OFONO_SERVICE, "/",
1282                                 OFONO_MANAGER_INTERFACE, GET_PROPERTIES);
1283         if (message == NULL)
1284                 return;
1285
1286         dbus_message_set_auto_start(message, FALSE);
1287
1288         if (dbus_connection_send_with_reply(connection, message,
1289                                                 &call, TIMEOUT) == FALSE) {
1290                 connman_error("Failed to get ofono modems");
1291                 goto done;
1292         }
1293
1294         if (call == NULL) {
1295                 connman_error("D-Bus connection not available");
1296                 goto done;
1297         }
1298
1299         dbus_pending_call_set_notify(call, manager_properties_reply,
1300                                                                 NULL, NULL);
1301
1302 done:
1303         dbus_message_unref(message);
1304
1305 }
1306
1307 static void ofono_disconnect(DBusConnection *connection, void *user_data)
1308 {
1309         DBG("connection %p", connection);
1310
1311         if (modem_hash == NULL)
1312                 return;
1313
1314         g_hash_table_destroy(modem_hash);
1315
1316         modem_hash = NULL;
1317 }
1318
1319 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1320                                 void *user_data)
1321 {
1322         const char *path = dbus_message_get_path(message);
1323         struct modem_data *modem;
1324         DBusMessageIter iter, value;
1325         const char *key;
1326
1327         DBG("path %s", path);
1328
1329         modem = g_hash_table_lookup(modem_hash, path);
1330         if (modem == NULL)
1331                 return TRUE;
1332
1333         if (dbus_message_iter_init(message, &iter) == FALSE)
1334                 return TRUE;
1335
1336         dbus_message_iter_get_basic(&iter, &key);
1337
1338         dbus_message_iter_next(&iter);
1339         dbus_message_iter_recurse(&iter, &value);
1340
1341         if (g_str_equal(key, "Powered") == TRUE) {
1342                 dbus_bool_t powered;
1343
1344                 dbus_message_iter_get_basic(&value, &powered);
1345                 if (powered == TRUE)
1346                         return TRUE;
1347
1348                 modem_remove_device(modem);
1349         } else if (g_str_equal(key, "Interfaces") == TRUE) {
1350                 if (modem_has_gprs(&value) == TRUE) {
1351                         if (modem->device == NULL)
1352                                 get_imsi(modem->path);
1353                 } else if (modem->device != NULL)
1354                         modem_remove_device(modem);
1355         }
1356
1357         return TRUE;
1358 }
1359
1360 static gboolean gprs_changed(DBusConnection *connection, DBusMessage *message,
1361                                 void *user_data)
1362 {
1363         const char *path = dbus_message_get_path(message);
1364         struct modem_data *modem;
1365         DBusMessageIter iter, value;
1366         const char *key;
1367
1368         DBG("path %s", path);
1369
1370         modem = g_hash_table_lookup(modem_hash, path);
1371         if (modem == NULL)
1372                 return TRUE;
1373
1374         if (dbus_message_iter_init(message, &iter) == FALSE)
1375                 return TRUE;
1376
1377         dbus_message_iter_get_basic(&iter, &key);
1378
1379         dbus_message_iter_next(&iter);
1380         dbus_message_iter_recurse(&iter, &value);
1381
1382         if (g_str_equal(key, "Attached") == TRUE) {
1383                 dbus_bool_t attached;
1384
1385                 dbus_message_iter_get_basic(&value, &attached);
1386
1387                 DBG("Attached %d", attached);
1388
1389                 if (attached == TRUE)
1390                         check_networks(modem);
1391                 else if (modem->device != NULL)
1392                         connman_device_remove_all_networks(modem->device);
1393
1394         } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
1395                 check_networks(modem);
1396         } else if (g_str_equal(key, "Powered") == TRUE) {
1397                 dbus_bool_t powered;
1398
1399                 if (modem->device == NULL)
1400                         return TRUE;
1401
1402                 dbus_message_iter_get_basic(&value, &powered);
1403                 connman_device_set_powered(modem->device, powered);
1404         }
1405
1406         return TRUE;
1407 }
1408
1409 static gboolean manager_changed(DBusConnection *connection,
1410                                 DBusMessage *message, void *user_data)
1411 {
1412         const char *path = dbus_message_get_path(message);
1413         DBusMessageIter iter, value;
1414         const char *key;
1415
1416         DBG("path %s", path);
1417
1418         if (dbus_message_iter_init(message, &iter) == FALSE)
1419                 return TRUE;
1420
1421         dbus_message_iter_get_basic(&iter, &key);
1422
1423         dbus_message_iter_next(&iter);
1424         dbus_message_iter_recurse(&iter, &value);
1425
1426         if (g_str_equal(key, "Modems") == TRUE)
1427                 update_modems(&value);
1428
1429         return TRUE;
1430 }
1431
1432 static void get_dns(DBusMessageIter *array, struct connman_element *parent)
1433 {
1434         DBusMessageIter entry;
1435         gchar *nameserver = NULL, *nameserver_old = NULL;
1436
1437         DBG("");
1438
1439         dbus_message_iter_recurse(array, &entry);
1440
1441         while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1442                 const char *dns;
1443
1444                 dbus_message_iter_get_basic(&entry, &dns);
1445
1446                 DBG("dns %s", dns);
1447
1448                 if (nameserver == NULL) {
1449
1450                         nameserver = g_strdup(dns);
1451                 } else {
1452
1453                         nameserver_old = nameserver;
1454                         nameserver = g_strdup_printf("%s %s",
1455                                                 nameserver_old, dns);
1456                         g_free(nameserver_old);
1457                 }
1458
1459                 dbus_message_iter_next(&entry);
1460         }
1461
1462         parent->ipv4.nameserver = nameserver;
1463 }
1464
1465 static void update_settings(DBusMessageIter *array,
1466                         struct connman_element *parent)
1467 {
1468         DBusMessageIter dict;
1469         const char *interface = NULL;
1470
1471         DBG("");
1472
1473         if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
1474                 return;
1475
1476         dbus_message_iter_recurse(array, &dict);
1477
1478         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1479                 DBusMessageIter entry, value;
1480                 const char *key;
1481
1482                 dbus_message_iter_recurse(&dict, &entry);
1483                 dbus_message_iter_get_basic(&entry, &key);
1484
1485                 dbus_message_iter_next(&entry);
1486                 dbus_message_iter_recurse(&entry, &value);
1487
1488                 if (g_str_equal(key, "Interface") == TRUE) {
1489                         int index;
1490
1491                         dbus_message_iter_get_basic(&value, &interface);
1492
1493                         DBG("interface %s", interface);
1494
1495                         index = connman_inet_ifindex(interface);
1496                         if (index >= 0) {
1497                                 connman_network_set_index(
1498                                         pending_network, index);
1499                         } else {
1500                                 connman_error("Can not find interface %s",
1501                                                                 interface);
1502                                 break;
1503                         }
1504                 } else if (g_str_equal(key, "Method") == TRUE) {
1505                         const char *method;
1506
1507                         dbus_message_iter_get_basic(&value, &method);
1508                         if (g_strcmp0(method, "static") == 0) {
1509
1510                                 parent->ipv4.method =
1511                                         CONNMAN_IPCONFIG_METHOD_FIXED;
1512                         } else if (g_strcmp0(method, "dhcp") == 0) {
1513
1514                                 parent->ipv4.method =
1515                                         CONNMAN_IPCONFIG_METHOD_DHCP;
1516                                 break;
1517                         }
1518                 } else if (g_str_equal(key, "Address") == TRUE) {
1519                         const char *address;
1520
1521                         dbus_message_iter_get_basic(&value, &address);
1522
1523                         DBG("address %s", address);
1524
1525                         parent->ipv4.address = g_strdup(address);
1526                 } else if (g_str_equal(key, "Netmask") == TRUE) {
1527                         const char *netmask;
1528
1529                         dbus_message_iter_get_basic(&value, &netmask);
1530
1531                         DBG("netmask %s", netmask);
1532
1533                         parent->ipv4.netmask = g_strdup(netmask);
1534                 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
1535
1536                         get_dns(&value, parent);
1537                 } else if (g_str_equal(key, "Gateway") == TRUE) {
1538                         const char *gateway;
1539
1540                         dbus_message_iter_get_basic(&value, &gateway);
1541
1542                         DBG("gateway %s", gateway);
1543
1544                         parent->ipv4.gateway = g_strdup(gateway);
1545                 }
1546
1547                 dbus_message_iter_next(&dict);
1548         }
1549
1550         /* deactive, oFono send NULL inteface before deactive signal */
1551         if (interface == NULL)
1552                 connman_network_set_index(pending_network, -1);
1553 }
1554
1555 static void cleanup_ipconfig(struct connman_element *parent)
1556 {
1557         g_free(parent->ipv4.address);
1558         parent->ipv4.address = NULL;
1559
1560         g_free(parent->ipv4.netmask);
1561         parent->ipv4.netmask = NULL;
1562
1563         g_free(parent->ipv4.nameserver);
1564         parent->ipv4.nameserver = NULL;
1565
1566         g_free(parent->ipv4.gateway);
1567         parent->ipv4.gateway = NULL;
1568
1569         parent->ipv4.method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1570 }
1571
1572 static int static_network_set_connected(
1573                 struct connman_network *pending_network,
1574                                 struct connman_element *parent,
1575                                         connman_bool_t connected)
1576 {
1577         if (connected == FALSE)
1578                 cleanup_ipconfig(parent);
1579
1580         connman_network_set_connected(pending_network, connected);
1581
1582         return 0;
1583 }
1584
1585 static gboolean pri_context_changed(DBusConnection *connection,
1586                                         DBusMessage *message, void *user_data)
1587 {
1588         const char *path = dbus_message_get_path(message);
1589         struct connman_element *parent;
1590         const char *pending_path;
1591         DBusMessageIter iter, value;
1592         const char *key;
1593
1594         DBG("pending_network %p, path %s", pending_network, path);
1595
1596         if (pending_network == NULL)
1597                 return TRUE;
1598
1599         pending_path = connman_network_get_string(pending_network, "Path");
1600         if (g_strcmp0(pending_path, path) != 0)
1601                 return TRUE;
1602
1603         parent = connman_network_get_element(pending_network);
1604
1605         if (dbus_message_iter_init(message, &iter) == FALSE)
1606                 return TRUE;
1607
1608         dbus_message_iter_get_basic(&iter, &key);
1609
1610         dbus_message_iter_next(&iter);
1611         dbus_message_iter_recurse(&iter, &value);
1612
1613         if (g_str_equal(key, "Settings") == TRUE) {
1614
1615                 update_settings(&value, parent);
1616         } else if (g_str_equal(key, "Active") == TRUE) {
1617                 dbus_bool_t active;
1618
1619                 dbus_message_iter_get_basic(&value, &active);
1620
1621                 switch (parent->ipv4.method) {
1622                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1623                 case CONNMAN_IPCONFIG_METHOD_OFF:
1624                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1625                         break;
1626                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1627                         connman_network_set_method(pending_network,
1628                                                 CONNMAN_IPCONFIG_METHOD_FIXED);
1629
1630                         if (static_network_set_connected(
1631                                         pending_network, parent, active) < 0)
1632                                 set_network_active(pending_network, FALSE);
1633                         break;
1634                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1635                         connman_network_set_method(pending_network,
1636                                                 CONNMAN_IPCONFIG_METHOD_DHCP);
1637                         connman_network_set_connected(pending_network, active);
1638                         break;
1639                 }
1640
1641                 pending_network = NULL;
1642         }
1643
1644         return TRUE;
1645 }
1646
1647 static guint watch;
1648 static guint gprs_watch;
1649 static guint modem_watch;
1650 static guint manager_watch;
1651 static guint context_watch;
1652
1653 static int ofono_init(void)
1654 {
1655         int err;
1656
1657         connection = connman_dbus_get_connection();
1658         if (connection == NULL)
1659                 return -EIO;
1660
1661         watch = g_dbus_add_service_watch(connection, OFONO_SERVICE,
1662                         ofono_connect, ofono_disconnect, NULL, NULL);
1663
1664         gprs_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1665                                                 OFONO_GPRS_INTERFACE,
1666                                                 PROPERTY_CHANGED,
1667                                                 gprs_changed,
1668                                                 NULL, NULL);
1669
1670         modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1671                                                 OFONO_MODEM_INTERFACE,
1672                                                 PROPERTY_CHANGED,
1673                                                 modem_changed,
1674                                                 NULL, NULL);
1675
1676         manager_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1677                                                 OFONO_MANAGER_INTERFACE,
1678                                                 PROPERTY_CHANGED,
1679                                                 manager_changed,
1680                                                 NULL, NULL);
1681
1682         context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1683                                                 OFONO_PRI_CONTEXT_INTERFACE,
1684                                                 PROPERTY_CHANGED,
1685                                                 pri_context_changed,
1686                                                 NULL, NULL);
1687
1688         if (watch == 0 || gprs_watch == 0 || modem_watch == 0 ||
1689                         manager_watch == 0 || context_watch == 0) {
1690                 err = -EIO;
1691                 goto remove;
1692         }
1693
1694         err = connman_network_driver_register(&network_driver);
1695         if (err < 0)
1696                 goto remove;
1697
1698         err = connman_device_driver_register(&modem_driver);
1699         if (err < 0) {
1700                 connman_network_driver_unregister(&network_driver);
1701                 goto remove;
1702         }
1703
1704         return 0;
1705
1706 remove:
1707         g_dbus_remove_watch(connection, watch);
1708         g_dbus_remove_watch(connection, gprs_watch);
1709         g_dbus_remove_watch(connection, modem_watch);
1710         g_dbus_remove_watch(connection, manager_watch);
1711         g_dbus_remove_watch(connection, context_watch);
1712
1713         dbus_connection_unref(connection);
1714
1715         return err;
1716 }
1717
1718 static void ofono_exit(void)
1719 {
1720         g_dbus_remove_watch(connection, watch);
1721         g_dbus_remove_watch(connection, gprs_watch);
1722         g_dbus_remove_watch(connection, modem_watch);
1723         g_dbus_remove_watch(connection, manager_watch);
1724         g_dbus_remove_watch(connection, context_watch);
1725
1726         ofono_disconnect(connection, NULL);
1727
1728         connman_device_driver_unregister(&modem_driver);
1729         connman_network_driver_unregister(&network_driver);
1730
1731         dbus_connection_unref(connection);
1732 }
1733
1734 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
1735                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)