5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
6 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 #define CONNMAN_API_SUBJECT_TO_CHANGE
33 #include <connman/plugin.h>
34 #include <connman/element.h>
35 #include <connman/device.h>
36 #include <connman/network.h>
37 #include <connman/dbus.h>
38 #include <connman/inet.h>
39 #include <connman/log.h>
41 #define OFONO_SERVICE "org.ofono"
43 #define OFONO_MANAGER_INTERFACE OFONO_SERVICE ".Manager"
44 #define OFONO_MODEM_INTERFACE OFONO_SERVICE ".Modem"
45 #define OFONO_GPRS_INTERFACE OFONO_SERVICE ".DataConnectionManager"
46 #define OFONO_SIM_INTERFACE OFONO_SERVICE ".SimManager"
47 #define OFONO_PRI_CONTEXT_INTERFACE OFONO_SERVICE ".PrimaryDataContext"
48 #define OFONO_REGISTRATION_INTERFACE OFONO_SERVICE ".NetworkRegistration"
50 #define PROPERTY_CHANGED "PropertyChanged"
51 #define GET_PROPERTIES "GetProperties"
52 #define SET_PROPERTY "SetProperty"
53 #define CREATE_CONTEXT "CreateContext"
57 #define CONTEXT_NAME "3G Connection"
58 #define CONTEXT_TYPE "internet"
60 static DBusConnection *connection;
62 static GHashTable *modem_hash = NULL;
66 struct connman_device *device;
70 static int modem_probe(struct connman_device *device)
72 DBG("device %p", device);
77 static void modem_remove(struct connman_device *device)
79 DBG("device %p", device);
82 static int call_ofono(const char *path,
83 const char *interface, const char *method,
84 DBusPendingCallNotifyFunction notify, void *user_data,
85 DBusFreeFunction free_function,
89 DBusPendingCall *call;
93 DBG("path %s %s.%s", path, interface, method);
98 message = dbus_message_new_method_call(OFONO_SERVICE, path,
103 dbus_message_set_auto_start(message, FALSE);
106 ok = dbus_message_append_args_valist(message, type, va);
112 if (dbus_connection_send_with_reply(connection, message,
113 &call, TIMEOUT) == FALSE) {
114 connman_error("Failed to call %s.%s", interface, method);
115 dbus_message_unref(message);
120 connman_error("D-Bus connection not available");
121 dbus_message_unref(message);
125 dbus_pending_call_set_notify(call, notify, user_data, free_function);
127 dbus_message_unref(message);
132 static void set_property_reply(DBusPendingCall *call, void *user_data)
136 char const *name = user_data;
140 dbus_error_init(&error);
142 reply = dbus_pending_call_steal_reply(call);
144 if (dbus_set_error_from_message(&error, reply)) {
145 connman_error("SetProperty(%s) %s %s", name,
146 error.name, error.message);
147 dbus_error_free(&error);
150 dbus_message_unref(reply);
152 dbus_pending_call_unref(call);
155 static int set_property(const char *path, const char *interface,
156 const char *property, int type, void *value,
157 DBusPendingCallNotifyFunction notify, void *user_data,
158 DBusFreeFunction free_function)
160 DBusMessage *message;
161 DBusMessageIter iter;
162 DBusPendingCall *call;
164 DBG("path %s %s.%s", path, interface, property);
166 g_assert(notify == NULL ? free_function == NULL : 1);
171 message = dbus_message_new_method_call(OFONO_SERVICE, path,
172 interface, SET_PROPERTY);
176 dbus_message_set_auto_start(message, FALSE);
178 dbus_message_iter_init_append(message, &iter);
179 connman_dbus_property_append_basic(&iter, property, type, value);
181 if (dbus_connection_send_with_reply(connection, message,
182 &call, TIMEOUT) == FALSE) {
183 connman_error("Failed to change \"%s\" property on %s",
184 property, interface);
185 dbus_message_unref(message);
190 connman_error("D-Bus connection not available");
191 dbus_message_unref(message);
195 if (notify == NULL) {
196 notify = set_property_reply;
197 user_data = (void *)property;
198 free_function = NULL;
201 dbus_pending_call_set_notify(call, notify, user_data, free_function);
203 dbus_message_unref(message);
208 static int gprs_change_powered(const char *path, dbus_bool_t powered)
210 DBG("path %s powered %d", path, powered);
212 return set_property(path, OFONO_GPRS_INTERFACE, "Powered",
213 DBUS_TYPE_BOOLEAN, &powered,
217 static int modem_enable(struct connman_device *device)
219 const char *path = connman_device_get_string(device, "Path");
221 DBG("device %p, path, %s", device, path);
223 return gprs_change_powered(path, TRUE);
226 static int modem_disable(struct connman_device *device)
228 const char *path = connman_device_get_string(device, "Path");
230 DBG("device %p, path %s", device, path);
232 return gprs_change_powered(path, FALSE);
235 static struct connman_device_driver modem_driver = {
237 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
238 .probe = modem_probe,
239 .remove = modem_remove,
240 .enable = modem_enable,
241 .disable = modem_disable,
244 static char *get_ident(const char *path)
251 pos = strrchr(path, '/');
258 static void create_service(struct connman_network *network)
265 path = connman_network_get_string(network, "Path");
267 group = get_ident(path);
269 connman_network_set_group(network, group);
272 static void set_network_name_reply(DBusPendingCall *call, void *user_data)
274 struct connman_network *network = user_data;
276 DBusMessageIter array, dict;
278 DBG("network %p", network);
280 reply = dbus_pending_call_steal_reply(call);
282 if (dbus_message_iter_init(reply, &array) == FALSE)
285 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
288 dbus_message_iter_recurse(&array, &dict);
290 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
291 DBusMessageIter entry, value;
294 dbus_message_iter_recurse(&dict, &entry);
295 dbus_message_iter_get_basic(&entry, &key);
297 dbus_message_iter_next(&entry);
298 dbus_message_iter_recurse(&entry, &value);
301 * 'Operator' is deprecated since version 0.20, but
302 * keep it here for backward compatibility reasons.
304 if (g_str_equal(key, "Operator") == TRUE ||
305 g_str_equal(key, "Name") == TRUE) {
308 dbus_message_iter_get_basic(&value, &name);
309 connman_network_set_name(network, name);
310 create_service(network);
311 } else if (g_strcmp0(key, "Status") == 0) {
313 connman_bool_t roaming;
315 dbus_message_iter_get_basic(&value, &status);
316 if (g_strcmp0(status, "roaming") == 0)
318 else if (g_strcmp0(status, "registered") == 0)
321 dbus_message_iter_next(&dict);
325 connman_network_set_roaming(network, roaming);
326 connman_network_update(network);
329 dbus_message_iter_next(&dict);
332 dbus_message_unref(reply);
334 dbus_pending_call_unref(call);
337 static void set_network_name(struct connman_network *network)
339 struct connman_device *device;
342 device = connman_network_get_device(network);
344 path = connman_device_get_string(device, "Path");
348 DBG("path %s", path);
350 call_ofono(path, OFONO_REGISTRATION_INTERFACE, GET_PROPERTIES,
351 set_network_name_reply, network, NULL,
355 static void config_network_reply(DBusPendingCall *call, void *user_data)
357 struct connman_network *network = user_data;
359 DBusMessageIter array, dict;
360 gboolean internet_type = FALSE;
362 DBG("network %p", network);
364 reply = dbus_pending_call_steal_reply(call);
366 if (dbus_message_iter_init(reply, &array) == FALSE)
369 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
372 dbus_message_iter_recurse(&array, &dict);
374 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
375 DBusMessageIter entry, value;
378 dbus_message_iter_recurse(&dict, &entry);
379 dbus_message_iter_get_basic(&entry, &key);
381 dbus_message_iter_next(&entry);
382 dbus_message_iter_recurse(&entry, &value);
384 if (g_str_equal(key, "Type") == TRUE) {
387 dbus_message_iter_get_basic(&value, &type);
388 if (g_strcmp0(type, "internet") == 0) {
389 internet_type = TRUE;
391 connman_network_set_protocol(network,
392 CONNMAN_NETWORK_PROTOCOL_IP);
393 set_network_name(network);
395 internet_type = FALSE;
397 connman_network_set_protocol(network,
398 CONNMAN_NETWORK_PROTOCOL_UNKNOWN);
402 dbus_message_iter_next(&dict);
406 dbus_message_unref(reply);
408 dbus_pending_call_unref(call);
411 static void config_network(struct connman_network *network, const char *path)
413 DBG("path %s", path);
415 call_ofono(path, OFONO_PRI_CONTEXT_INTERFACE, GET_PROPERTIES,
416 config_network_reply, network, NULL,
420 static gboolean registration_changed(DBusConnection *connection,
421 DBusMessage *message, void *user_data)
423 const char *path = dbus_message_get_path(message);
424 struct connman_network *network = user_data;
425 DBusMessageIter iter, value;
428 DBG("path %s", path);
430 if (dbus_message_iter_init(message, &iter) == FALSE)
433 dbus_message_iter_get_basic(&iter, &key);
437 dbus_message_iter_next(&iter);
438 dbus_message_iter_recurse(&iter, &value);
440 if (g_strcmp0(key, "Name") == 0 ||
441 g_strcmp0(key, "Operator") == 0) {
444 dbus_message_iter_get_basic(&value, &name);
445 DBG("name %s", name);
446 connman_network_set_name(network, name);
447 create_service(network);
448 } else if (g_strcmp0(key, "Strength") == 0) {
449 connman_uint8_t strength;
451 dbus_message_iter_get_basic(&value, &strength);
452 connman_network_set_strength(network, strength);
453 connman_network_update(network);
454 } else if (g_strcmp0(key, "Status") == 0) {
456 connman_bool_t roaming;
458 dbus_message_iter_get_basic(&value, &status);
459 if (g_strcmp0(status, "roaming") == 0)
461 else if (g_strcmp0(status, "registered") == 0)
466 connman_network_set_roaming(network, roaming);
467 connman_network_update(network);
473 static int network_probe(struct connman_network *network)
478 reg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
479 OFONO_REGISTRATION_INTERFACE,
481 registration_changed,
486 connman_network_set_data(network, GUINT_TO_POINTER(reg_watch));
488 path = connman_network_get_string(network, "Path");
490 DBG("network %p path %s", network, path);
492 config_network(network, path);
497 static struct connman_network *pending_network;
499 static gboolean pending_network_is_available(struct connman_network *network)
501 /* Modem or network may be removed during waiting for active reply */
502 if (connman_network_get_device(network) == NULL) {
503 DBG("Modem or network was removed");
510 static void set_active_reply(DBusPendingCall *call, void *user_data)
514 struct connman_network *network = user_data;
516 DBG("network %p", network);
518 reply = dbus_pending_call_steal_reply(call);
520 if (pending_network_is_available(network) == FALSE)
523 dbus_error_init(&error);
524 if (dbus_set_error_from_message(&error, reply)) {
525 if (connman_network_get_index(network) < 0)
526 connman_network_set_error(network,
527 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
529 pending_network = NULL;
531 connman_error("SetProperty(Active) %s %s",
532 error.name, error.message);
534 dbus_error_free(&error);
536 pending_network = network;
539 dbus_message_unref(reply);
541 dbus_pending_call_unref(call);
544 static int set_network_active(struct connman_network *network,
549 const char *path = connman_network_get_string(network, "Path");
551 DBG("network %p, path %s, active %d", network, path, active);
553 error = set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
554 "Active", DBUS_TYPE_BOOLEAN, &active,
555 set_active_reply, network, NULL);
556 if (active == FALSE && error == -EINPROGRESS)
562 static void set_apn(struct connman_network *network)
564 const char *apn, *path;
566 apn = connman_network_get_string(network, "Cellular.APN");
570 path = connman_network_get_string(network, "Path");
574 DBG("path %s, apn %s", path, apn);
576 set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
577 "AccessPointName", DBUS_TYPE_STRING, &apn,
581 static int network_connect(struct connman_network *network)
583 if (connman_network_get_index(network) >= 0)
586 return set_network_active(network, TRUE);
589 static int network_disconnect(struct connman_network *network)
591 if (connman_network_get_index(network) < 0)
594 return set_network_active(network, FALSE);
597 static void network_remove(struct connman_network *network)
601 DBG("network %p", network);
603 reg_watch = GPOINTER_TO_UINT(connman_network_get_data(network));
604 g_dbus_remove_watch(connection, reg_watch);
607 static int network_setup(struct connman_network *network, const char *key)
611 if (g_strcmp0(key, "Cellular.APN") == 0)
617 static struct connman_network_driver network_driver = {
619 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
620 .probe = network_probe,
621 .remove = network_remove,
622 .connect = network_connect,
623 .disconnect = network_disconnect,
624 .setup = network_setup,
627 static void add_network(struct connman_device *device, const char *path)
629 struct connman_network *network;
632 DBG("device %p path %s", device, path);
634 ident = get_ident(path);
636 network = connman_device_get_network(device, ident);
640 network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
644 if (connman_network_set_string(network, "Path", path) != 0)
647 connman_network_set_available(network, TRUE);
648 connman_network_set_index(network, -1);
650 if (connman_device_add_network(device, network) == 0)
654 connman_network_unref(network);
657 static void add_networks(struct connman_device *device, DBusMessageIter *array)
659 DBusMessageIter entry;
663 dbus_message_iter_recurse(array, &entry);
665 while (dbus_message_iter_get_arg_type(&entry) ==
666 DBUS_TYPE_OBJECT_PATH) {
669 dbus_message_iter_get_basic(&entry, &path);
671 add_network(device, path);
673 dbus_message_iter_next(&entry);
677 static void create_context_reply(DBusPendingCall *call, void *user_data)
684 dbus_error_init(&error);
686 reply = dbus_pending_call_steal_reply(call);
688 if (dbus_set_error_from_message(&error, reply)) {
689 connman_error("CreateContext() %s %s",
690 error.name, error.message);
691 dbus_error_free(&error);
694 dbus_message_unref(reply);
696 dbus_pending_call_unref(call);
699 static void add_default_context(DBusMessageIter *array,
700 const char *path, const char *name, const char *type)
702 DBusMessageIter entry;
709 dbus_message_iter_recurse(array, &entry);
711 if (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_OBJECT_PATH)
714 DBG("path %s, name %s, type %s", path, name, type);
716 call_ofono(path, OFONO_GPRS_INTERFACE, CREATE_CONTEXT,
717 create_context_reply, NULL, NULL,
718 DBUS_TYPE_STRING, &name,
719 DBUS_TYPE_STRING, &type,
723 static void check_networks_reply(DBusPendingCall *call, void *user_data)
725 char *path = user_data;
726 struct modem_data *modem;
727 struct connman_device *device;
729 DBusMessageIter array, dict, contexts;
730 dbus_bool_t attached;
732 DBG("path %s", path);
734 modem = g_hash_table_lookup(modem_hash, path);
735 if (modem == NULL || modem->device == NULL)
738 device = modem->device;
740 reply = dbus_pending_call_steal_reply(call);
742 if (dbus_message_iter_init(reply, &array) == FALSE)
745 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
748 dbus_message_iter_recurse(&array, &dict);
750 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
751 DBusMessageIter entry, value;
754 dbus_message_iter_recurse(&dict, &entry);
755 dbus_message_iter_get_basic(&entry, &key);
757 dbus_message_iter_next(&entry);
758 dbus_message_iter_recurse(&entry, &value);
762 if (g_str_equal(key, "Attached") == TRUE) {
763 dbus_message_iter_get_basic(&value, &attached);
764 DBG("Attached %d", attached);
765 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
768 path = connman_device_get_string(device, "Path");
770 add_default_context(&contexts, path,
771 CONTEXT_NAME, CONTEXT_TYPE);
772 } else if (g_str_equal(key, "Powered") == TRUE) {
775 dbus_message_iter_get_basic(&value, &powered);
777 connman_device_set_powered(device, powered);
780 dbus_message_iter_next(&dict);
783 if (attached == TRUE)
784 add_networks(device, &contexts);
787 dbus_message_unref(reply);
789 dbus_pending_call_unref(call);
792 static void check_networks(struct modem_data *modem)
794 char const *path = modem->path;
796 DBG("modem %p path %s", modem, path);
798 call_ofono(path, OFONO_GPRS_INTERFACE, GET_PROPERTIES,
799 check_networks_reply, g_strdup(path), g_free,
803 static void add_device(const char *path, const char *imsi)
805 struct modem_data *modem;
806 struct connman_device *device;
808 DBG("path %s imsi %s", path, imsi);
816 modem = g_hash_table_lookup(modem_hash, path);
820 device = connman_device_create(imsi, CONNMAN_DEVICE_TYPE_CELLULAR);
824 connman_device_set_ident(device, imsi);
826 connman_device_set_mode(device, CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE);
828 connman_device_set_string(device, "Path", path);
830 if (connman_device_register(device) < 0) {
831 connman_device_unref(device);
835 modem->device = device;
837 check_networks(modem);
840 static void sim_properties_reply(DBusPendingCall *call, void *user_data)
842 const char *path = user_data;
845 DBusMessageIter array, dict;
847 DBG("path %s", path);
849 reply = dbus_pending_call_steal_reply(call);
851 if (dbus_message_iter_init(reply, &array) == FALSE)
854 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
857 dbus_message_iter_recurse(&array, &dict);
859 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
860 DBusMessageIter entry, value;
863 dbus_message_iter_recurse(&dict, &entry);
864 dbus_message_iter_get_basic(&entry, &key);
866 dbus_message_iter_next(&entry);
867 dbus_message_iter_recurse(&entry, &value);
869 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
870 dbus_message_iter_get_basic(&value, &imsi);
871 add_device(path, imsi);
874 dbus_message_iter_next(&dict);
878 dbus_message_unref(reply);
880 dbus_pending_call_unref(call);
883 static void get_imsi(const char *path)
885 DBG("path %s", path);
887 call_ofono(path, OFONO_SIM_INTERFACE, GET_PROPERTIES,
888 sim_properties_reply, g_strdup(path), g_free,
892 static int modem_change_powered(const char *path, dbus_bool_t powered)
894 DBG("path %s powered %d", path, powered);
896 return set_property(path, OFONO_MODEM_INTERFACE, "Powered",
897 DBUS_TYPE_BOOLEAN, &powered,
901 static struct modem_data *add_modem(const char *path)
903 struct modem_data *modem;
905 DBG("path %s", path);
910 modem = g_hash_table_lookup(modem_hash, path);
912 modem->available = TRUE;
917 modem = g_try_new0(struct modem_data, 1);
921 modem->path = g_strdup(path);
922 modem->device = NULL;
923 modem->available = TRUE;
925 g_hash_table_insert(modem_hash, g_strdup(path), modem);
930 static gboolean modem_has_interface(DBusMessageIter *array,
931 char const *interface)
933 DBusMessageIter entry;
935 dbus_message_iter_recurse(array, &entry);
937 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
940 dbus_message_iter_get_basic(&entry, &element);
942 if (g_strcmp0(interface, element) == 0)
945 dbus_message_iter_next(&entry);
951 static gboolean modem_has_gprs(DBusMessageIter *array)
953 return modem_has_interface(array, OFONO_GPRS_INTERFACE);
956 static void modem_properties_reply(DBusPendingCall *call, void *user_data)
960 DBusMessageIter array, dict;
961 const char *path = user_data;
962 dbus_bool_t powered = FALSE;
963 gboolean has_gprs = FALSE;
964 struct modem_data *new_modem;
966 DBG("path %s", path);
968 reply = dbus_pending_call_steal_reply(call);
970 if (g_hash_table_lookup(modem_hash, path))
973 dbus_error_init(&error);
975 if (dbus_set_error_from_message(&error, reply)) {
976 connman_error("Modem.GetProperties(%s) %s %s",
977 path, error.name, error.message);
978 dbus_error_free(&error);
982 if (dbus_message_iter_init(reply, &array) == FALSE)
985 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
988 dbus_message_iter_recurse(&array, &dict);
990 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
991 DBusMessageIter entry, value;
994 dbus_message_iter_recurse(&dict, &entry);
995 dbus_message_iter_get_basic(&entry, &key);
997 dbus_message_iter_next(&entry);
998 dbus_message_iter_recurse(&entry, &value);
1000 if (g_str_equal(key, "Powered") == TRUE)
1001 dbus_message_iter_get_basic(&value, &powered);
1002 else if (g_str_equal(key, "Interfaces") == TRUE)
1003 has_gprs = modem_has_gprs(&value);
1005 dbus_message_iter_next(&dict);
1008 new_modem = add_modem(path);
1009 if (new_modem == NULL)
1013 modem_change_powered(path, TRUE);
1019 dbus_message_unref(reply);
1021 dbus_pending_call_unref(call);
1024 static void get_modem_properties(const char *path)
1026 DBG("path %s", path);
1028 call_ofono(path, OFONO_MODEM_INTERFACE, GET_PROPERTIES,
1029 modem_properties_reply, g_strdup(path), g_free,
1033 static void mask_unavailable(gpointer key, gpointer value, gpointer user_data)
1035 struct modem_data *modem = value;
1037 modem->available = FALSE;
1040 static void modems_set_unavailable()
1042 g_hash_table_foreach(modem_hash, mask_unavailable, NULL);
1045 static void cleanup_modem(gpointer key, gpointer value, gpointer user_data)
1047 struct modem_data *modem = value;
1049 if (modem->available == FALSE)
1050 g_hash_table_remove(modem_hash, key);
1053 static void cleanup_modems()
1055 g_hash_table_foreach(modem_hash, cleanup_modem, NULL);
1058 static void update_modems(DBusMessageIter *array)
1060 DBusMessageIter entry;
1064 dbus_message_iter_recurse(array, &entry);
1066 modems_set_unavailable();
1068 while (dbus_message_iter_get_arg_type(&entry) ==
1069 DBUS_TYPE_OBJECT_PATH) {
1071 struct modem_data *modem;
1073 dbus_message_iter_get_basic(&entry, &path);
1075 modem = g_hash_table_lookup(modem_hash, path);
1078 modem->available = TRUE;
1080 get_modem_properties(path);
1082 dbus_message_iter_next(&entry);
1088 static void manager_properties_reply(DBusPendingCall *call, void *user_data)
1092 DBusMessageIter array, dict;
1096 reply = dbus_pending_call_steal_reply(call);
1098 dbus_error_init(&error);
1100 if (dbus_set_error_from_message(&error, reply)) {
1101 connman_error("ModemManager.GetProperties() %s %s",
1102 error.name, error.message);
1103 dbus_error_free(&error);
1107 if (dbus_message_iter_init(reply, &array) == FALSE)
1110 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1113 dbus_message_iter_recurse(&array, &dict);
1115 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1116 DBusMessageIter entry, value;
1119 dbus_message_iter_recurse(&dict, &entry);
1120 dbus_message_iter_get_basic(&entry, &key);
1122 dbus_message_iter_next(&entry);
1123 dbus_message_iter_recurse(&entry, &value);
1125 if (g_str_equal(key, "Modems") == TRUE) {
1126 update_modems(&value);
1130 dbus_message_iter_next(&dict);
1134 dbus_message_unref(reply);
1136 dbus_pending_call_unref(call);
1139 static void modem_remove_device(struct modem_data *modem)
1141 if (modem->device == NULL)
1144 connman_device_unregister(modem->device);
1145 connman_device_unref(modem->device);
1147 modem->device = NULL;
1150 static void remove_modem(gpointer data)
1152 struct modem_data *modem = data;
1154 g_free(modem->path);
1156 modem_remove_device(modem);
1161 static void ofono_connect(DBusConnection *connection, void *user_data)
1163 DBG("connection %p", connection);
1165 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1166 g_free, remove_modem);
1168 call_ofono("/", OFONO_MANAGER_INTERFACE, GET_PROPERTIES,
1169 manager_properties_reply, NULL, NULL,
1173 static void ofono_disconnect(DBusConnection *connection, void *user_data)
1175 DBG("connection %p", connection);
1177 if (modem_hash == NULL)
1180 g_hash_table_destroy(modem_hash);
1185 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1188 const char *path = dbus_message_get_path(message);
1189 struct modem_data *modem;
1190 DBusMessageIter iter, value;
1193 DBG("path %s", path);
1195 modem = g_hash_table_lookup(modem_hash, path);
1199 if (dbus_message_iter_init(message, &iter) == FALSE)
1202 dbus_message_iter_get_basic(&iter, &key);
1204 dbus_message_iter_next(&iter);
1205 dbus_message_iter_recurse(&iter, &value);
1207 if (g_str_equal(key, "Powered") == TRUE) {
1208 dbus_bool_t powered;
1210 dbus_message_iter_get_basic(&value, &powered);
1211 if (powered == TRUE)
1214 modem_remove_device(modem);
1215 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1216 if (modem_has_gprs(&value) == TRUE) {
1217 if (modem->device == NULL)
1218 get_imsi(modem->path);
1219 } else if (modem->device != NULL)
1220 modem_remove_device(modem);
1226 static gboolean gprs_changed(DBusConnection *connection, DBusMessage *message,
1229 const char *path = dbus_message_get_path(message);
1230 struct modem_data *modem;
1231 DBusMessageIter iter, value;
1234 DBG("path %s", path);
1236 modem = g_hash_table_lookup(modem_hash, path);
1240 if (dbus_message_iter_init(message, &iter) == FALSE)
1243 dbus_message_iter_get_basic(&iter, &key);
1245 dbus_message_iter_next(&iter);
1246 dbus_message_iter_recurse(&iter, &value);
1248 if (g_str_equal(key, "Attached") == TRUE) {
1249 dbus_bool_t attached;
1251 dbus_message_iter_get_basic(&value, &attached);
1253 DBG("Attached %d", attached);
1255 if (attached == TRUE)
1256 check_networks(modem);
1257 else if (modem->device != NULL)
1258 connman_device_remove_all_networks(modem->device);
1260 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
1261 check_networks(modem);
1262 } else if (g_str_equal(key, "Powered") == TRUE) {
1263 dbus_bool_t powered;
1265 if (modem->device == NULL)
1268 dbus_message_iter_get_basic(&value, &powered);
1269 connman_device_set_powered(modem->device, powered);
1275 static gboolean manager_changed(DBusConnection *connection,
1276 DBusMessage *message, void *user_data)
1278 const char *path = dbus_message_get_path(message);
1279 DBusMessageIter iter, value;
1282 DBG("path %s", path);
1284 if (dbus_message_iter_init(message, &iter) == FALSE)
1287 dbus_message_iter_get_basic(&iter, &key);
1289 dbus_message_iter_next(&iter);
1290 dbus_message_iter_recurse(&iter, &value);
1292 if (g_str_equal(key, "Modems") == TRUE)
1293 update_modems(&value);
1298 static void get_dns(DBusMessageIter *array, struct connman_element *parent)
1300 DBusMessageIter entry;
1301 gchar *nameserver = NULL, *nameserver_old = NULL;
1305 dbus_message_iter_recurse(array, &entry);
1307 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1310 dbus_message_iter_get_basic(&entry, &dns);
1314 if (nameserver == NULL) {
1316 nameserver = g_strdup(dns);
1319 nameserver_old = nameserver;
1320 nameserver = g_strdup_printf("%s %s",
1321 nameserver_old, dns);
1322 g_free(nameserver_old);
1325 dbus_message_iter_next(&entry);
1328 parent->ipv4.nameserver = nameserver;
1331 static void update_settings(DBusMessageIter *array,
1332 struct connman_network *network)
1334 struct connman_element *parent = connman_network_get_element(network);
1335 DBusMessageIter dict;
1336 const char *interface = NULL;
1338 DBG("network %p", network);
1340 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
1343 dbus_message_iter_recurse(array, &dict);
1345 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1346 DBusMessageIter entry, value;
1349 dbus_message_iter_recurse(&dict, &entry);
1350 dbus_message_iter_get_basic(&entry, &key);
1354 dbus_message_iter_next(&entry);
1355 dbus_message_iter_recurse(&entry, &value);
1357 if (g_str_equal(key, "Interface") == TRUE) {
1360 dbus_message_iter_get_basic(&value, &interface);
1362 DBG("interface %s", interface);
1364 index = connman_inet_ifindex(interface);
1366 connman_network_set_index(network, index);
1368 connman_error("Can not find interface %s",
1372 } else if (g_str_equal(key, "Method") == TRUE) {
1375 dbus_message_iter_get_basic(&value, &method);
1376 if (g_strcmp0(method, "static") == 0) {
1378 parent->ipv4.method =
1379 CONNMAN_IPCONFIG_METHOD_FIXED;
1380 } else if (g_strcmp0(method, "dhcp") == 0) {
1382 parent->ipv4.method =
1383 CONNMAN_IPCONFIG_METHOD_DHCP;
1386 } else if (g_str_equal(key, "Address") == TRUE) {
1387 const char *address;
1389 dbus_message_iter_get_basic(&value, &address);
1391 DBG("address %s", address);
1393 parent->ipv4.address = g_strdup(address);
1394 } else if (g_str_equal(key, "Netmask") == TRUE) {
1395 const char *netmask;
1397 dbus_message_iter_get_basic(&value, &netmask);
1399 DBG("netmask %s", netmask);
1401 parent->ipv4.netmask = g_strdup(netmask);
1402 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
1404 get_dns(&value, parent);
1405 } else if (g_str_equal(key, "Gateway") == TRUE) {
1406 const char *gateway;
1408 dbus_message_iter_get_basic(&value, &gateway);
1410 DBG("gateway %s", gateway);
1412 parent->ipv4.gateway = g_strdup(gateway);
1415 dbus_message_iter_next(&dict);
1418 /* deactive, oFono send NULL inteface before deactive signal */
1419 if (interface == NULL)
1420 connman_network_set_index(network, -1);
1423 static void cleanup_ipconfig(struct connman_network *network)
1425 struct connman_element *parent = connman_network_get_element(network);
1427 g_free(parent->ipv4.address);
1428 parent->ipv4.address = NULL;
1430 g_free(parent->ipv4.netmask);
1431 parent->ipv4.netmask = NULL;
1433 g_free(parent->ipv4.nameserver);
1434 parent->ipv4.nameserver = NULL;
1436 g_free(parent->ipv4.gateway);
1437 parent->ipv4.gateway = NULL;
1439 parent->ipv4.method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1443 static void set_connected(struct connman_network *network,
1444 connman_bool_t connected)
1446 struct connman_element *parent = connman_network_get_element(network);
1447 enum connman_ipconfig_method method = parent->ipv4.method;
1450 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1451 case CONNMAN_IPCONFIG_METHOD_OFF:
1452 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1455 case CONNMAN_IPCONFIG_METHOD_FIXED:
1456 connman_network_set_method(network, method);
1458 if (connected == FALSE)
1459 cleanup_ipconfig(network);
1461 connman_network_set_connected(network, connected);
1464 case CONNMAN_IPCONFIG_METHOD_DHCP:
1465 connman_network_set_method(network, method);
1467 connman_network_set_connected(network, connected);
1472 static gboolean pri_context_changed(DBusConnection *connection,
1473 DBusMessage *message, void *user_data)
1475 const char *path = dbus_message_get_path(message);
1476 const char *pending_path;
1477 DBusMessageIter iter, value;
1480 DBG("pending_network %p, path %s", pending_network, path);
1482 if (pending_network == NULL)
1485 pending_path = connman_network_get_string(pending_network, "Path");
1486 if (g_strcmp0(pending_path, path) != 0)
1489 if (dbus_message_iter_init(message, &iter) == FALSE)
1492 dbus_message_iter_get_basic(&iter, &key);
1494 dbus_message_iter_next(&iter);
1495 dbus_message_iter_recurse(&iter, &value);
1497 if (g_str_equal(key, "Settings") == TRUE)
1498 update_settings(&value, pending_network);
1499 else if (g_str_equal(key, "Active") == TRUE) {
1502 dbus_message_iter_get_basic(&value, &active);
1504 set_connected(pending_network, active);
1506 pending_network = NULL;
1513 static guint gprs_watch;
1514 static guint modem_watch;
1515 static guint manager_watch;
1516 static guint context_watch;
1518 static int ofono_init(void)
1522 connection = connman_dbus_get_connection();
1523 if (connection == NULL)
1526 watch = g_dbus_add_service_watch(connection, OFONO_SERVICE,
1527 ofono_connect, ofono_disconnect, NULL, NULL);
1529 gprs_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1530 OFONO_GPRS_INTERFACE,
1535 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1536 OFONO_MODEM_INTERFACE,
1541 manager_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1542 OFONO_MANAGER_INTERFACE,
1547 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1548 OFONO_PRI_CONTEXT_INTERFACE,
1550 pri_context_changed,
1553 if (watch == 0 || gprs_watch == 0 || modem_watch == 0 ||
1554 manager_watch == 0 || context_watch == 0) {
1559 err = connman_network_driver_register(&network_driver);
1563 err = connman_device_driver_register(&modem_driver);
1565 connman_network_driver_unregister(&network_driver);
1572 g_dbus_remove_watch(connection, watch);
1573 g_dbus_remove_watch(connection, gprs_watch);
1574 g_dbus_remove_watch(connection, modem_watch);
1575 g_dbus_remove_watch(connection, manager_watch);
1576 g_dbus_remove_watch(connection, context_watch);
1578 dbus_connection_unref(connection);
1583 static void ofono_exit(void)
1585 g_dbus_remove_watch(connection, watch);
1586 g_dbus_remove_watch(connection, gprs_watch);
1587 g_dbus_remove_watch(connection, modem_watch);
1588 g_dbus_remove_watch(connection, manager_watch);
1589 g_dbus_remove_watch(connection, context_watch);
1591 ofono_disconnect(connection, NULL);
1593 connman_device_driver_unregister(&modem_driver);
1594 connman_network_driver_unregister(&network_driver);
1596 dbus_connection_unref(connection);
1599 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
1600 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)