5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
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.
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.
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
31 #define CONNMAN_API_SUBJECT_TO_CHANGE
32 #include <connman/plugin.h>
33 #include <connman/device.h>
34 #include <connman/network.h>
35 #include <connman/dbus.h>
36 #include <connman/inet.h>
37 #include <connman/log.h>
39 #define OFONO_SERVICE "org.ofono"
41 #define OFONO_MANAGER_INTERFACE OFONO_SERVICE ".Manager"
42 #define OFONO_MODEM_INTERFACE OFONO_SERVICE ".Modem"
43 #define OFONO_GPRS_INTERFACE OFONO_SERVICE ".DataConnectionManager"
44 #define OFONO_SIM_INTERFACE OFONO_SERVICE ".SimManager"
45 #define OFONO_PRI_CONTEXT_INTERFACE OFONO_SERVICE ".PrimaryDataContext"
47 #define PROPERTY_CHANGED "PropertyChanged"
48 #define GET_PROPERTIES "GetProperties"
49 #define SET_PROPERTY "SetProperty"
53 static DBusConnection *connection;
55 static GHashTable *modem_hash = NULL;
59 struct connman_device *device;
63 static int modem_probe(struct connman_device *device)
65 DBG("device %p", device);
70 static void modem_remove(struct connman_device *device)
72 DBG("device %p", device);
75 static void powered_reply(DBusPendingCall *call, void *user_data)
82 dbus_error_init(&error);
84 reply = dbus_pending_call_steal_reply(call);
86 if (dbus_set_error_from_message(&error, reply)) {
87 connman_error("%s", error.message);
88 dbus_error_free(&error);
91 dbus_message_unref(reply);
94 static int gprs_change_powered(const char *path, dbus_bool_t powered)
98 DBusPendingCall *call;
100 DBG("path %s powered %d", path, powered);
105 message = dbus_message_new_method_call(OFONO_SERVICE, path,
106 OFONO_GPRS_INTERFACE, SET_PROPERTY);
110 dbus_message_set_auto_start(message, FALSE);
112 dbus_message_iter_init_append(message, &iter);
113 connman_dbus_property_append_variant(&iter, "Powered",
114 DBUS_TYPE_BOOLEAN, &powered);
116 if (dbus_connection_send_with_reply(connection, message,
117 &call, TIMEOUT) == FALSE) {
118 connman_error("Failed to change powered property");
119 dbus_message_unref(message);
124 connman_error("D-Bus connection not available");
125 dbus_message_unref(message);
129 dbus_pending_call_set_notify(call, powered_reply, (void *)path, NULL);
131 dbus_message_unref(message);
136 static int modem_enable(struct connman_device *device)
138 const char *path = connman_device_get_string(device, "Path");
140 DBG("device %p, path, %s", device, path);
142 return gprs_change_powered(path, TRUE);
145 static int modem_disable(struct connman_device *device)
147 const char *path = connman_device_get_string(device, "Path");
149 DBG("device %p, path %s", device, path);
151 return gprs_change_powered(path, FALSE);
154 static struct connman_device_driver modem_driver = {
156 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
157 .probe = modem_probe,
158 .remove = modem_remove,
159 .enable = modem_enable,
160 .disable = modem_disable,
163 static char *get_ident(const char *path)
170 ident = g_strdup(path + 1);
174 while ((pos = strchr(pos, '/')) != NULL)
180 static void config_network_reply(DBusPendingCall *call, void *user_data)
182 struct connman_network *network = user_data;
184 DBusMessageIter array, dict;
185 gboolean internet_type = FALSE;
187 DBG("network %p", network);
189 reply = dbus_pending_call_steal_reply(call);
193 if (dbus_message_iter_init(reply, &array) == FALSE)
196 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
199 dbus_message_iter_recurse(&array, &dict);
201 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
202 DBusMessageIter entry, value;
205 dbus_message_iter_recurse(&dict, &entry);
206 dbus_message_iter_get_basic(&entry, &key);
208 dbus_message_iter_next(&entry);
209 dbus_message_iter_recurse(&entry, &value);
211 if (g_str_equal(key, "Name") == TRUE) {
214 dbus_message_iter_get_basic(&value, &name);
215 connman_network_set_name(network, name);
216 } else if (g_str_equal(key, "Type") == TRUE) {
219 dbus_message_iter_get_basic(&value, &type);
220 if (g_strcmp0(type, "internet") == 0) {
221 internet_type = TRUE;
223 connman_network_set_protocol(network,
224 CONNMAN_NETWORK_PROTOCOL_IP);
226 internet_type = FALSE;
228 connman_network_set_protocol(network,
229 CONNMAN_NETWORK_PROTOCOL_UNKNOWN);
233 dbus_message_iter_next(&dict);
236 if (internet_type == TRUE) {
240 path = connman_network_get_string(network, "Path");
242 group = get_ident(path);
244 connman_network_set_group(network, group);
250 dbus_message_unref(reply);
253 static void config_network(struct connman_network *network, const char *path)
255 DBusMessage *message;
256 DBusPendingCall *call;
258 DBG("path %s", path);
260 message = dbus_message_new_method_call(OFONO_SERVICE, path,
261 OFONO_PRI_CONTEXT_INTERFACE, GET_PROPERTIES);
265 dbus_message_set_auto_start(message, FALSE);
267 if (dbus_connection_send_with_reply(connection, message,
268 &call, TIMEOUT) == FALSE) {
269 connman_error("Failed to get Primary Context");
274 connman_error("D-Bus connection not available");
278 dbus_pending_call_set_notify(call, config_network_reply,
279 (void *)network, NULL);
282 dbus_message_unref(message);
285 static int network_probe(struct connman_network *network)
289 path = connman_network_get_string(network, "Path");
291 DBG("network %p path %s", network, path);
293 config_network(network, path);
298 static struct connman_network *pending_network;
300 static gboolean pending_network_is_available(
301 struct connman_network *pending_network)
303 struct connman_device *device;
304 struct connman_network *network;
305 const char *identifier;
308 /* Modem may be removed during waiting for active reply */
309 device = connman_network_get_device(pending_network);
313 identifier = connman_network_get_identifier(pending_network);
315 ident = g_strdup(identifier);
317 connman_network_unref(pending_network);
319 /* network may be removed during waiting for active reply */
320 network = connman_device_get_network(device, ident);
330 static void set_active_reply(DBusPendingCall *call, void *user_data)
334 struct connman_network *network = user_data;
336 DBG("network %p", network);
338 if (pending_network_is_available(network) == FALSE)
341 reply = dbus_pending_call_steal_reply(call);
345 dbus_error_init(&error);
346 if (dbus_set_error_from_message(&error, reply)) {
347 if (connman_network_get_index(network) < 0)
348 connman_network_set_error(network,
349 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
351 pending_network = NULL;
353 connman_error("%s", error.message);
355 dbus_error_free(&error);
357 pending_network = network;
359 dbus_message_unref(reply);
362 static int set_network_active(struct connman_network *network,
365 DBusMessage *message;
366 DBusPendingCall *call;
367 DBusMessageIter iter;
369 const char *path = connman_network_get_string(network, "Path");
371 DBG("network %p, path %s, active %d", network, path, active);
376 message = dbus_message_new_method_call(OFONO_SERVICE, path,
377 OFONO_PRI_CONTEXT_INTERFACE, SET_PROPERTY);
381 dbus_message_set_auto_start(message, FALSE);
383 dbus_message_iter_init_append(message, &iter);
384 connman_dbus_property_append_variant(&iter, "Active",
385 DBUS_TYPE_BOOLEAN, &active);
387 if (dbus_connection_send_with_reply(connection, message,
388 &call, TIMEOUT * 10) == FALSE) {
389 connman_error("Failed to connect service");
390 dbus_message_unref(message);
395 connman_error("D-Bus connection not available");
396 dbus_message_unref(message);
400 connman_network_ref(network);
402 dbus_pending_call_set_notify(call, set_active_reply, network, NULL);
404 dbus_message_unref(message);
412 static int network_connect(struct connman_network *network)
414 if (connman_network_get_index(network) >= 0)
417 return set_network_active(network, TRUE);
420 static int network_disconnect(struct connman_network *network)
422 if (connman_network_get_index(network) < 0)
425 return set_network_active(network, FALSE);
428 static void network_remove(struct connman_network *network)
430 DBG("network %p", network);
433 static struct connman_network_driver network_driver = {
435 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
436 .probe = network_probe,
437 .remove = network_remove,
438 .connect = network_connect,
439 .disconnect = network_disconnect,
442 static void add_network(struct connman_device *device, const char *path)
444 struct connman_network *network;
447 DBG("device %p path %s", device, path);
449 network = connman_device_get_network(device, path);
453 ident = get_ident(path);
455 network = connman_network_create(ident,
456 CONNMAN_NETWORK_TYPE_CELLULAR);
462 connman_network_set_string(network, "Path", path);
463 connman_network_set_available(network, TRUE);
464 connman_network_set_index(network, -1);
465 connman_device_add_network(device, network);
468 static void add_networks(struct connman_device *device, DBusMessageIter *array)
470 DBusMessageIter entry;
474 dbus_message_iter_recurse(array, &entry);
476 while (dbus_message_iter_get_arg_type(&entry) ==
477 DBUS_TYPE_OBJECT_PATH) {
480 dbus_message_iter_get_basic(&entry, &path);
482 add_network(device, path);
484 dbus_message_iter_next(&entry);
488 static void check_networks_reply(DBusPendingCall *call, void *user_data)
490 struct connman_device *device = user_data;
492 DBusMessageIter array, dict, contexts;
493 dbus_bool_t attached;
495 DBG("device %p", device);
497 reply = dbus_pending_call_steal_reply(call);
501 if (dbus_message_iter_init(reply, &array) == FALSE)
504 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
507 dbus_message_iter_recurse(&array, &dict);
509 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
510 DBusMessageIter entry, value;
513 dbus_message_iter_recurse(&dict, &entry);
514 dbus_message_iter_get_basic(&entry, &key);
516 dbus_message_iter_next(&entry);
517 dbus_message_iter_recurse(&entry, &value);
521 if (g_str_equal(key, "Attached") == TRUE) {
522 dbus_message_iter_get_basic(&value, &attached);
523 DBG("Attached %d", attached);
524 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
526 } else if (g_str_equal(key, "Status") == TRUE) {
529 dbus_message_iter_get_basic(&value, &status);
530 /* FIXME: add roaming support */
531 } else if (g_str_equal(key, "Powered") == TRUE) {
534 dbus_message_iter_get_basic(&value, &powered);
536 connman_device_set_powered(device, powered);
539 dbus_message_iter_next(&dict);
542 if (attached == TRUE)
543 add_networks(device, &contexts);
546 dbus_message_unref(reply);
549 static void check_networks(struct modem_data *modem)
551 DBusMessage *message;
552 DBusPendingCall *call;
553 struct connman_device *device;
555 DBG("modem %p", modem);
560 device = modem->device;
564 message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
565 OFONO_GPRS_INTERFACE, GET_PROPERTIES);
569 dbus_message_set_auto_start(message, FALSE);
571 if (dbus_connection_send_with_reply(connection, message,
572 &call, TIMEOUT) == FALSE) {
573 connman_error("Failed to get ofono GPRS");
578 connman_error("D-Bus connection not available");
582 dbus_pending_call_set_notify(call, check_networks_reply,
583 (void *)device, NULL);
586 dbus_message_unref(message);
589 static void add_device(const char *path, const char *imsi)
591 struct modem_data *modem;
592 struct connman_device *device;
594 DBG("path %s imsi %s", path, imsi);
602 modem = g_hash_table_lookup(modem_hash, path);
606 device = connman_device_create(imsi, CONNMAN_DEVICE_TYPE_CELLULAR);
610 connman_device_set_ident(device, imsi);
612 connman_device_set_mode(device, CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE);
614 connman_device_set_string(device, "Path", path);
616 if (connman_device_register(device) < 0) {
617 connman_device_unref(device);
621 modem->device = device;
623 check_networks(modem);
626 static void sim_properties_reply(DBusPendingCall *call, void *user_data)
628 const char *path = user_data;
630 DBusMessageIter array, dict;
632 DBG("path %s", path);
634 reply = dbus_pending_call_steal_reply(call);
638 if (dbus_message_iter_init(reply, &array) == FALSE)
641 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
644 dbus_message_iter_recurse(&array, &dict);
646 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
647 DBusMessageIter entry, value;
648 const char *key, *imsi;
650 dbus_message_iter_recurse(&dict, &entry);
651 dbus_message_iter_get_basic(&entry, &key);
653 dbus_message_iter_next(&entry);
654 dbus_message_iter_recurse(&entry, &value);
656 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
657 dbus_message_iter_get_basic(&value, &imsi);
659 add_device(path, imsi);
662 dbus_message_iter_next(&dict);
666 dbus_message_unref(reply);
669 static void get_imsi(const char *path)
671 DBusMessage *message;
672 DBusPendingCall *call;
674 DBG("path %s", path);
676 message = dbus_message_new_method_call(OFONO_SERVICE, path,
677 OFONO_SIM_INTERFACE, GET_PROPERTIES);
681 dbus_message_set_auto_start(message, FALSE);
683 if (dbus_connection_send_with_reply(connection, message,
684 &call, TIMEOUT) == FALSE) {
685 connman_error("Failed to get ofono modem sim");
690 connman_error("D-Bus connection not available");
694 dbus_pending_call_set_notify(call, sim_properties_reply,
698 dbus_message_unref(message);
701 static int modem_change_powered(const char *path, dbus_bool_t powered)
703 DBusMessage *message;
704 DBusMessageIter iter;
705 DBusPendingCall *call;
707 DBG("path %s powered %d", path, powered);
712 message = dbus_message_new_method_call(OFONO_SERVICE, path,
713 OFONO_MODEM_INTERFACE, SET_PROPERTY);
717 dbus_message_set_auto_start(message, FALSE);
719 dbus_message_iter_init_append(message, &iter);
720 connman_dbus_property_append_variant(&iter, "Powered",
721 DBUS_TYPE_BOOLEAN, &powered);
723 if (dbus_connection_send_with_reply(connection, message,
724 &call, TIMEOUT) == FALSE) {
725 connman_error("Failed to change powered property");
726 dbus_message_unref(message);
731 connman_error("D-Bus connection not available");
732 dbus_message_unref(message);
736 dbus_pending_call_set_notify(call, powered_reply, NULL, NULL);
738 dbus_message_unref(message);
743 static struct modem_data *add_modem(const char *path)
745 struct modem_data *modem;
750 modem = g_hash_table_lookup(modem_hash, path);
752 modem->available = TRUE;
757 modem = g_try_new0(struct modem_data, 1);
761 modem->path = g_strdup(path);
762 modem->device = NULL;
763 modem->available = TRUE;
765 g_hash_table_insert(modem_hash, g_strdup(path), modem);
770 static gboolean modem_has_gprs(DBusMessageIter *array)
772 DBusMessageIter entry;
774 dbus_message_iter_recurse(array, &entry);
776 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
777 const char *interface;
779 dbus_message_iter_get_basic(&entry, &interface);
781 if (g_strcmp0(OFONO_GPRS_INTERFACE, interface) == 0)
784 dbus_message_iter_next(&entry);
790 static void modem_properties_reply(DBusPendingCall *call, void *user_data)
793 DBusMessageIter array, dict;
794 const char *path = user_data;
796 DBG("path %s", path);
798 reply = dbus_pending_call_steal_reply(call);
802 if (dbus_message_iter_init(reply, &array) == FALSE)
805 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
808 dbus_message_iter_recurse(&array, &dict);
810 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
811 DBusMessageIter entry, value;
815 dbus_message_iter_recurse(&dict, &entry);
816 dbus_message_iter_get_basic(&entry, &key);
818 dbus_message_iter_next(&entry);
819 dbus_message_iter_recurse(&entry, &value);
821 if (g_str_equal(key, "Powered") == TRUE) {
822 dbus_message_iter_get_basic(&value, &powered);
824 if (powered == FALSE) {
825 modem_change_powered(path, TRUE);
828 } else if (g_str_equal(key, "Interface") == TRUE) {
829 if (modem_has_gprs(&value) == TRUE)
833 dbus_message_iter_next(&dict);
837 dbus_message_unref(reply);
840 static void get_modem_properties(struct modem_data *modem)
842 DBusMessage *message;
843 DBusPendingCall *call;
845 DBG("path %s", modem->path);
847 if (modem->path == NULL)
850 message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
851 OFONO_MODEM_INTERFACE, GET_PROPERTIES);
855 dbus_message_set_auto_start(message, FALSE);
857 if (dbus_connection_send_with_reply(connection, message,
858 &call, TIMEOUT) == FALSE) {
859 connman_error("Failed to get ofono modem");
864 connman_error("D-Bus connection not available");
868 dbus_pending_call_set_notify(call, modem_properties_reply,
869 (void *)modem->path, NULL);
872 dbus_message_unref(message);
875 static void mask_unavailable(gpointer key, gpointer value, gpointer user_data)
877 struct modem_data *modem = value;
879 modem->available = FALSE;
882 static void modems_set_unavailable()
884 g_hash_table_foreach(modem_hash, mask_unavailable, NULL);
887 static void cleanup_modem(gpointer key, gpointer value, gpointer user_data)
889 struct modem_data *modem = value;
891 if (modem->available == FALSE)
892 g_hash_table_remove(modem_hash, key);
895 static void cleanup_modems()
897 g_hash_table_foreach(modem_hash, cleanup_modem, NULL);
900 static void update_modems(DBusMessageIter *array)
902 DBusMessageIter entry;
904 dbus_message_iter_recurse(array, &entry);
906 modems_set_unavailable();
908 while (dbus_message_iter_get_arg_type(&entry) ==
909 DBUS_TYPE_OBJECT_PATH) {
911 struct modem_data *modem;
913 dbus_message_iter_get_basic(&entry, &path);
915 modem = add_modem(path);
917 get_modem_properties(modem);
919 dbus_message_iter_next(&entry);
925 static void manager_properties_reply(DBusPendingCall *call, void *user_data)
928 DBusMessageIter array, dict;
932 reply = dbus_pending_call_steal_reply(call);
936 if (dbus_message_iter_init(reply, &array) == FALSE)
939 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
942 dbus_message_iter_recurse(&array, &dict);
944 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
945 DBusMessageIter entry, value;
948 dbus_message_iter_recurse(&dict, &entry);
949 dbus_message_iter_get_basic(&entry, &key);
951 dbus_message_iter_next(&entry);
952 dbus_message_iter_recurse(&entry, &value);
954 if (g_str_equal(key, "Modems") == TRUE) {
955 update_modems(&value);
959 dbus_message_iter_next(&dict);
963 dbus_message_unref(reply);
966 static void modem_remove_device(struct modem_data *modem)
968 if (modem->device == NULL)
971 connman_device_unregister(modem->device);
972 connman_device_unref(modem->device);
974 modem->device = NULL;
977 static void remove_modem(gpointer data)
979 struct modem_data *modem = data;
983 modem_remove_device(modem);
988 static void ofono_connect(DBusConnection *connection, void *user_data)
990 DBusMessage *message;
991 DBusPendingCall *call;
993 DBG("connection %p", connection);
995 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
996 g_free, remove_modem);
998 message = dbus_message_new_method_call(OFONO_SERVICE, "/",
999 OFONO_MANAGER_INTERFACE, GET_PROPERTIES);
1000 if (message == NULL)
1003 dbus_message_set_auto_start(message, FALSE);
1005 if (dbus_connection_send_with_reply(connection, message,
1006 &call, TIMEOUT) == FALSE) {
1007 connman_error("Failed to get ofono modems");
1012 connman_error("D-Bus connection not available");
1016 dbus_pending_call_set_notify(call, manager_properties_reply,
1020 dbus_message_unref(message);
1024 static void ofono_disconnect(DBusConnection *connection, void *user_data)
1026 DBG("connection %p", connection);
1028 if (modem_hash == NULL)
1031 g_hash_table_destroy(modem_hash);
1036 static void modem_changed(DBusConnection *connection, DBusMessage *message)
1038 const char *path = dbus_message_get_path(message);
1039 struct modem_data *modem;
1040 DBusMessageIter iter, value;
1043 DBG("path %s", path);
1045 modem = g_hash_table_lookup(modem_hash, path);
1049 if (dbus_message_iter_init(message, &iter) == FALSE)
1052 dbus_message_iter_get_basic(&iter, &key);
1054 dbus_message_iter_next(&iter);
1055 dbus_message_iter_recurse(&iter, &value);
1057 if (g_str_equal(key, "Powered") == TRUE) {
1058 dbus_bool_t powered;
1060 dbus_message_iter_get_basic(&value, &powered);
1061 if (powered == TRUE)
1064 modem_remove_device(modem);
1065 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1066 if (modem_has_gprs(&value) == TRUE) {
1067 if (modem->device == NULL)
1068 get_imsi(modem->path);
1069 } else if (modem->device != NULL)
1070 modem_remove_device(modem);
1074 static void gprs_changed(DBusConnection *connection, DBusMessage *message)
1076 const char *path = dbus_message_get_path(message);
1077 struct modem_data *modem;
1078 DBusMessageIter iter, value;
1081 DBG("path %s", path);
1083 modem = g_hash_table_lookup(modem_hash, path);
1087 if (dbus_message_iter_init(message, &iter) == FALSE)
1090 dbus_message_iter_get_basic(&iter, &key);
1092 dbus_message_iter_next(&iter);
1093 dbus_message_iter_recurse(&iter, &value);
1095 if (g_str_equal(key, "Attached") == TRUE) {
1096 dbus_bool_t attached;
1098 dbus_message_iter_get_basic(&value, &attached);
1100 DBG("Attached %d", attached);
1102 if (attached == TRUE)
1103 check_networks(modem);
1104 else if (modem->device != NULL)
1105 connman_device_remove_all_networks(modem->device);
1107 } else if (g_str_equal(key, "Status") == TRUE) {
1109 dbus_message_iter_get_basic(&value, &status);
1111 DBG("status %s", status);
1113 /* FIXME: add roaming support */
1114 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
1115 check_networks(modem);
1116 } else if (g_str_equal(key, "Powered") == TRUE) {
1117 dbus_bool_t powered;
1119 if (modem->device == NULL)
1122 dbus_message_iter_get_basic(&value, &powered);
1123 connman_device_set_powered(modem->device, powered);
1127 static void manager_changed(DBusConnection *connection, DBusMessage *message)
1129 const char *path = dbus_message_get_path(message);
1130 DBusMessageIter iter, value;
1133 DBG("path %s", path);
1135 if (dbus_message_iter_init(message, &iter) == FALSE)
1138 dbus_message_iter_get_basic(&iter, &key);
1140 dbus_message_iter_next(&iter);
1141 dbus_message_iter_recurse(&iter, &value);
1143 if (g_str_equal(key, "Modems") == TRUE)
1144 update_modems(&value);
1147 static void update_settings(DBusMessageIter *array)
1149 DBusMessageIter dict;
1150 const char *interface = NULL;
1154 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
1157 dbus_message_iter_recurse(array, &dict);
1159 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1160 DBusMessageIter entry, value;
1163 dbus_message_iter_recurse(&dict, &entry);
1164 dbus_message_iter_get_basic(&entry, &key);
1166 dbus_message_iter_next(&entry);
1167 dbus_message_iter_recurse(&entry, &value);
1169 if (g_str_equal(key, "Interface") == TRUE) {
1172 dbus_message_iter_get_basic(&value, &interface);
1174 DBG("interface %s", interface);
1176 index = connman_inet_ifindex(interface);
1178 connman_network_set_index(
1179 pending_network, index);
1181 connman_error("Can not find interface %s",
1185 } else if (g_str_equal(key, "Method") == TRUE) {
1188 dbus_message_iter_get_basic(&value, &method);
1189 if (g_strcmp0(method, "static") == 0) {
1191 } else if (g_strcmp0(method, "dhcp") == 0) {
1195 } else if (g_str_equal(key, "address") == TRUE) {
1196 const char *address;
1198 dbus_message_iter_get_basic(&value, &address);
1200 DBG("address %s", address);
1202 /* FIXME: add static setting */
1203 dbus_message_iter_next(&dict);
1206 /* deactive, oFono send NULL inteface before deactive signal */
1207 if (interface == NULL)
1208 connman_network_set_index(pending_network, -1);
1211 static void pri_context_changed(DBusConnection *connection,
1212 DBusMessage *message)
1214 const char *path = dbus_message_get_path(message);
1215 const char *pending_path;
1216 DBusMessageIter iter, value;
1219 DBG("pending_network %p, path %s", pending_network, path);
1221 if (pending_network == NULL)
1224 pending_path = connman_network_get_string(pending_network, "Path");
1225 if (g_strcmp0(pending_path, path) != 0)
1228 if (dbus_message_iter_init(message, &iter) == FALSE)
1231 dbus_message_iter_get_basic(&iter, &key);
1233 dbus_message_iter_next(&iter);
1234 dbus_message_iter_recurse(&iter, &value);
1236 if (g_str_equal(key, "Settings") == TRUE) {
1237 update_settings(&value);
1238 } else if (g_str_equal(key, "Active") == TRUE) {
1241 dbus_message_iter_get_basic(&value, &active);
1242 connman_network_set_connected(pending_network, active);
1244 pending_network = NULL;
1248 static DBusHandlerResult ofono_signal(DBusConnection *connection,
1249 DBusMessage *message, void *user_data)
1251 if (dbus_message_is_signal(message, OFONO_MODEM_INTERFACE,
1252 PROPERTY_CHANGED) == TRUE) {
1253 modem_changed(connection, message);
1254 } else if (dbus_message_is_signal(message, OFONO_GPRS_INTERFACE,
1255 PROPERTY_CHANGED) == TRUE) {
1256 gprs_changed(connection, message);
1257 } else if (dbus_message_is_signal(message, OFONO_MANAGER_INTERFACE,
1258 PROPERTY_CHANGED) == TRUE) {
1259 manager_changed(connection, message);
1260 } else if (dbus_message_is_signal(message, OFONO_PRI_CONTEXT_INTERFACE,
1261 PROPERTY_CHANGED) == TRUE) {
1262 pri_context_changed(connection, message);
1265 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1268 static const char *gprs_rule = "type=signal, member=" PROPERTY_CHANGED
1269 ",interface=" OFONO_GPRS_INTERFACE;
1270 static const char *modem_rule = "type=signal,member=" PROPERTY_CHANGED
1271 ",interface=" OFONO_MODEM_INTERFACE;
1272 static const char *manager_rule = "type=signal,member=" PROPERTY_CHANGED
1273 ",interface=" OFONO_MANAGER_INTERFACE;
1274 static const char *pri_context_rule = "type=signal,member=" PROPERTY_CHANGED
1275 ", interface=" OFONO_PRI_CONTEXT_INTERFACE;
1279 static int ofono_init(void)
1283 connection = connman_dbus_get_connection();
1284 if (connection == NULL)
1287 if (dbus_connection_add_filter(connection, ofono_signal,
1288 NULL, NULL) == FALSE) {
1293 err = connman_network_driver_register(&network_driver);
1297 err = connman_device_driver_register(&modem_driver);
1299 connman_network_driver_unregister(&network_driver);
1303 watch = g_dbus_add_service_watch(connection, OFONO_SERVICE,
1304 ofono_connect, ofono_disconnect, NULL, NULL);
1310 dbus_bus_add_match(connection, modem_rule, NULL);
1311 dbus_bus_add_match(connection, gprs_rule, NULL);
1312 dbus_bus_add_match(connection, manager_rule, NULL);
1313 dbus_bus_add_match(connection, pri_context_rule, NULL);
1318 dbus_connection_remove_filter(connection, ofono_signal, NULL);
1321 dbus_connection_unref(connection);
1326 static void ofono_exit(void)
1328 dbus_bus_remove_match(connection, modem_rule, NULL);
1329 dbus_bus_remove_match(connection, gprs_rule, NULL);
1330 dbus_bus_remove_match(connection, manager_rule, NULL);
1331 dbus_bus_remove_match(connection, pri_context_rule, NULL);
1333 g_dbus_remove_watch(connection, watch);
1335 ofono_disconnect(connection, NULL);
1337 connman_device_driver_unregister(&modem_driver);
1338 connman_network_driver_unregister(&network_driver);
1340 dbus_connection_remove_filter(connection, ofono_signal, NULL);
1342 dbus_connection_unref(connection);
1345 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
1346 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)