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
33 #define CONNMAN_API_SUBJECT_TO_CHANGE
34 #include <connman/plugin.h>
35 #include <connman/element.h>
36 #include <connman/device.h>
37 #include <connman/network.h>
38 #include <connman/dbus.h>
39 #include <connman/inet.h>
40 #include <connman/technology.h>
41 #include <connman/log.h>
45 #define OFONO_SERVICE "org.ofono"
47 #define OFONO_MANAGER_INTERFACE OFONO_SERVICE ".Manager"
48 #define OFONO_MODEM_INTERFACE OFONO_SERVICE ".Modem"
49 #define OFONO_GPRS_INTERFACE OFONO_SERVICE ".ConnectionManager"
50 #define OFONO_CONTEXT_INTERFACE OFONO_SERVICE ".ConnectionContext"
51 #define OFONO_SIM_INTERFACE OFONO_SERVICE ".SimManager"
52 #define OFONO_REGISTRATION_INTERFACE OFONO_SERVICE ".NetworkRegistration"
54 #define PROPERTY_CHANGED "PropertyChanged"
55 #define GET_PROPERTIES "GetProperties"
56 #define SET_PROPERTY "SetProperty"
57 #define CONTEXT_ADDED "ContextAdded"
58 #define CONTEXT_REMOVED "ContextRemoved"
59 #define ADD_CONTEXT "AddContext"
60 #define GET_MODEMS "GetModems"
61 #define MODEM_ADDED "ModemAdded"
62 #define MODEM_REMOVED "ModemRemoved"
67 static DBusConnection *connection;
69 static GHashTable *modem_hash = NULL;
71 static GHashTable *network_hash;
75 struct connman_device *device;
80 gboolean pending_online;
81 dbus_bool_t requested_online;
84 /* org.ofono.ConnectionManager properties */
87 dbus_bool_t roaming_allowed;
89 uint8_t strength, has_strength;
92 static int modem_probe(struct connman_device *device)
94 DBG("device %p", device);
99 static void modem_remove(struct connman_device *device)
101 DBG("device %p", device);
104 static int call_ofono(const char *path,
105 const char *interface, const char *method,
106 DBusPendingCallNotifyFunction notify, void *user_data,
107 DBusFreeFunction free_function,
110 DBusMessage *message;
111 DBusPendingCall *call;
115 DBG("path %s %s.%s", path, interface, method);
120 message = dbus_message_new_method_call(OFONO_SERVICE, path,
125 dbus_message_set_auto_start(message, FALSE);
128 ok = dbus_message_append_args_valist(message, type, va);
134 if (dbus_connection_send_with_reply(connection, message,
135 &call, TIMEOUT) == FALSE) {
136 connman_error("Failed to call %s.%s", interface, method);
137 dbus_message_unref(message);
142 connman_error("D-Bus connection not available");
143 dbus_message_unref(message);
147 dbus_pending_call_set_notify(call, notify, user_data, free_function);
149 dbus_message_unref(message);
154 static void set_property_reply(DBusPendingCall *call, void *user_data)
158 char const *name = user_data;
162 dbus_error_init(&error);
164 reply = dbus_pending_call_steal_reply(call);
166 if (dbus_set_error_from_message(&error, reply)) {
167 connman_error("SetProperty(%s) %s %s", name,
168 error.name, error.message);
169 dbus_error_free(&error);
172 dbus_message_unref(reply);
174 dbus_pending_call_unref(call);
177 static int set_property(const char *path, const char *interface,
178 const char *property, int type, void *value,
179 DBusPendingCallNotifyFunction notify, void *user_data,
180 DBusFreeFunction free_function)
182 DBusMessage *message;
183 DBusMessageIter iter;
184 DBusPendingCall *call;
186 DBG("path %s %s.%s", path, interface, property);
188 g_assert(notify == NULL ? free_function == NULL : 1);
193 message = dbus_message_new_method_call(OFONO_SERVICE, path,
194 interface, SET_PROPERTY);
198 dbus_message_set_auto_start(message, FALSE);
200 dbus_message_iter_init_append(message, &iter);
201 connman_dbus_property_append_basic(&iter, property, type, value);
203 if (dbus_connection_send_with_reply(connection, message,
204 &call, TIMEOUT) == FALSE) {
205 connman_error("Failed to change \"%s\" property on %s",
206 property, interface);
207 dbus_message_unref(message);
212 connman_error("D-Bus connection not available");
213 dbus_message_unref(message);
217 if (notify == NULL) {
218 notify = set_property_reply;
219 user_data = (void *)property;
220 free_function = NULL;
223 dbus_pending_call_set_notify(call, notify, user_data, free_function);
225 dbus_message_unref(message);
230 static void update_modem_online(struct modem_data *modem,
231 connman_bool_t online)
233 DBG("modem %p path %s online %d", modem, modem->path, online);
235 modem->online = online;
236 modem->requested_online = online;
237 modem->pending_online = FALSE;
240 connman_device_set_powered(modem->device, online);
243 static void set_online_reply(DBusPendingCall *call, void *user_data)
245 struct modem_data *modem;
250 DBG("path %s", (char *)user_data);
252 if (modem_hash == NULL)
255 modem = g_hash_table_lookup(modem_hash, user_data);
259 reply = dbus_pending_call_steal_reply(call);
261 dbus_error_init(&error);
263 if (dbus_set_error_from_message(&error, reply)) {
264 connman_error("SetProperty(Online) %s %s",
265 error.name, error.message);
266 dbus_error_free(&error);
268 result = modem->online;
270 result = modem->requested_online;
272 if (modem->pending_online)
273 update_modem_online(modem, result);
275 dbus_message_unref(reply);
277 dbus_pending_call_unref(call);
280 static int modem_change_online(char const *path, dbus_bool_t online)
282 struct modem_data *modem = g_hash_table_lookup(modem_hash, path);
287 if (modem->online == online)
290 modem->requested_online = online;
292 return set_property(path, OFONO_MODEM_INTERFACE, "Online",
293 DBUS_TYPE_BOOLEAN, &online,
295 (void *)g_strdup(path), g_free);
298 static int modem_enable(struct connman_device *device)
300 const char *path = connman_device_get_string(device, "Path");
302 DBG("device %p, path, %s", device, path);
304 return modem_change_online(path, TRUE);
307 static int modem_disable(struct connman_device *device)
309 const char *path = connman_device_get_string(device, "Path");
311 DBG("device %p path %s", device, path);
313 return modem_change_online(path, FALSE);
316 static struct connman_device_driver modem_driver = {
318 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
319 .probe = modem_probe,
320 .remove = modem_remove,
321 .enable = modem_enable,
322 .disable = modem_disable,
325 static void modem_remove_device(struct modem_data *modem)
327 DBG("modem %p path %s device %p", modem, modem->path, modem->device);
329 if (modem->device == NULL)
332 connman_device_remove_all_networks(modem->device);
333 connman_device_unregister(modem->device);
334 connman_device_unref(modem->device);
336 modem->device = NULL;
339 static void remove_modem(gpointer data)
341 struct modem_data *modem = data;
343 modem_remove_device(modem);
350 static void remove_network(gpointer data)
352 connman_network_unref(data);
355 static char *get_ident(const char *path)
362 pos = strrchr(path, '/');
369 static void create_service(struct connman_network *network)
376 path = connman_network_get_string(network, "Path");
378 group = get_ident(path);
380 connman_network_set_group(network, group);
383 static int network_probe(struct connman_network *network)
388 static gboolean pending_network_is_available(struct connman_network *network)
390 /* Modem or network may be removed */
391 if (network == NULL || connman_network_get_device(network) == NULL) {
392 DBG("Modem or network was removed");
399 static void set_active_reply(DBusPendingCall *call, void *user_data)
401 char const *path = user_data;
404 struct connman_network *network;
406 network = g_hash_table_lookup(network_hash, path);
408 DBG("path %s network %p", path, network);
410 reply = dbus_pending_call_steal_reply(call);
412 if (!pending_network_is_available(network))
415 dbus_error_init(&error);
417 if (dbus_set_error_from_message(&error, reply)) {
418 connman_error("SetProperty(Active) %s %s",
419 error.name, error.message);
421 if (connman_network_get_index(network) < 0)
422 connman_network_set_error(network,
423 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
425 dbus_error_free(&error);
429 dbus_message_unref(reply);
431 dbus_pending_call_unref(call);
434 static int set_network_active(struct connman_network *network,
439 const char *path = connman_network_get_string(network, "Path");
441 DBG("network %p, path %s, active %d", network, path, active);
443 error = set_property(path, OFONO_CONTEXT_INTERFACE,
444 "Active", DBUS_TYPE_BOOLEAN, &active,
445 set_active_reply, g_strdup(path), NULL);
447 if (active == FALSE && error == -EINPROGRESS)
453 static void set_apn(struct connman_network *network)
455 const char *apn, *path;
457 apn = connman_network_get_string(network, "Cellular.APN");
461 path = connman_network_get_string(network, "Path");
465 DBG("path %s, apn %s", path, apn);
467 set_property(path, OFONO_CONTEXT_INTERFACE,
468 "AccessPointName", DBUS_TYPE_STRING, &apn,
472 static int network_connect(struct connman_network *network)
474 struct connman_device *device;
475 struct modem_data *modem;
477 DBG("network %p", network);
479 if (connman_network_get_index(network) >= 0)
482 device = connman_network_get_device(network);
486 modem = connman_device_get_data(device);
490 if (modem->powered == FALSE)
493 return set_network_active(network, TRUE);
496 static int network_disconnect(struct connman_network *network)
498 DBG("network %p", network);
500 if (connman_network_get_index(network) < 0)
503 return set_network_active(network, FALSE);
506 static void network_remove(struct connman_network *network)
508 char const *path = connman_network_get_string(network, "Path");
510 DBG("network %p path %s", network, path);
512 g_hash_table_remove(network_hash, path);
515 static int network_setup(struct connman_network *network, const char *key)
517 if (g_strcmp0(key, "Cellular.APN") == 0)
523 static struct connman_network_driver network_driver = {
525 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
526 .probe = network_probe,
527 .remove = network_remove,
528 .connect = network_connect,
529 .disconnect = network_disconnect,
530 .setup = network_setup,
533 static void update_settings(DBusMessageIter *array,
534 struct connman_network *network);
536 static void set_connected(struct connman_network *network,
537 connman_bool_t connected);
539 static int add_network(struct connman_device *device,
540 const char *path, DBusMessageIter *dict)
542 struct modem_data *modem = connman_device_get_data(device);
543 struct connman_network *network;
545 const char *hash_path;
546 char const *operator;
547 char const *reg_status;
548 dbus_bool_t active = FALSE;
550 DBG("modem %p device %p path %s", modem, device, path);
552 ident = get_ident(path);
554 network = connman_device_get_network(device, ident);
558 network = g_hash_table_lookup(network_hash, path);
559 if (network != NULL) {
560 DBG("path %p already exists with device %p", path,
561 connman_network_get_device(network));
562 if (connman_network_get_device(network))
564 g_hash_table_remove(network_hash, path);
567 network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
571 connman_network_set_string(network, "Path", path);
572 hash_path = connman_network_get_string(network, "Path");
573 if (hash_path == NULL)
576 create_service(network);
578 connman_network_ref(network);
579 g_hash_table_insert(network_hash, (char *)hash_path, network);
581 connman_network_set_available(network, TRUE);
582 connman_network_set_index(network, -1);
584 operator = connman_device_get_string(device, "Operator");
586 connman_network_set_name(network, operator);
588 if (modem->has_strength)
589 connman_network_set_strength(network, modem->strength);
591 reg_status = connman_device_get_string(device, "RegistrationStatus");
593 if (!g_strcmp0(reg_status, "roaming"))
594 connman_network_set_roaming(network, TRUE);
595 else if (!g_strcmp0(reg_status, "registered"))
596 connman_network_set_roaming(network, FALSE);
598 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
599 DBusMessageIter entry, value;
602 dbus_message_iter_recurse(dict, &entry);
603 dbus_message_iter_get_basic(&entry, &key);
605 dbus_message_iter_next(&entry);
606 dbus_message_iter_recurse(&entry, &value);
608 if (g_str_equal(key, "Type")) {
611 dbus_message_iter_get_basic(&value, &type);
612 if (g_strcmp0(type, "internet") != 0) {
613 DBG("path %p type %s", path, type);
616 } else if (g_str_equal(key, "AccessPointName")) {
619 dbus_message_iter_get_basic(&value, &ap);
621 connman_network_set_string(network, "Cellular.APN", ap);
622 } else if (g_str_equal(key, "Settings"))
623 update_settings(&value, network);
624 else if (g_str_equal(key, "Active") == TRUE)
625 dbus_message_iter_get_basic(&value, &active);
627 dbus_message_iter_next(dict);
630 if (connman_device_add_network(device, network) != 0)
634 set_connected(network, active);
639 connman_network_unref(network);
640 g_hash_table_remove(network_hash, hash_path);
644 static void check_networks_reply(DBusPendingCall *call, void *user_data)
646 char *path = user_data;
647 struct modem_data *modem;
649 DBusMessageIter array, entry, value, properties;
651 DBG("path %s", path);
653 modem = g_hash_table_lookup(modem_hash, path);
656 if (modem->device == NULL)
659 reply = dbus_pending_call_steal_reply(call);
661 if (dbus_message_has_signature(reply, "a(oa{sv})") == FALSE)
664 dbus_message_iter_init(reply, &array);
666 dbus_message_iter_recurse(&array, &entry);
668 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRUCT) {
669 char const *network_path;
671 dbus_message_iter_recurse(&entry, &value);
672 dbus_message_iter_get_basic(&value, &network_path);
674 dbus_message_iter_next(&value);
675 dbus_message_iter_recurse(&value, &properties);
677 add_network(modem->device, network_path, &properties);
679 dbus_message_iter_next(&entry);
683 dbus_message_unref(reply);
685 dbus_pending_call_unref(call);
688 static void check_networks(struct modem_data *modem)
690 char const *path = modem->path;
692 DBG("modem %p path %s", modem, path);
694 call_ofono(path, OFONO_GPRS_INTERFACE, "GetContexts",
695 check_networks_reply, g_strdup(path), g_free,
699 static void modem_clear_network_errors(struct modem_data *modem)
701 struct connman_device *device = modem->device;
708 g_hash_table_iter_init(&i, network_hash);
710 while (g_hash_table_iter_next(&i, NULL, &value)) {
711 struct connman_network *network = value;
713 if (connman_network_get_device(network) == device)
714 connman_network_clear_error(network);
718 static void modem_operator_name_changed(struct modem_data *modem,
721 struct connman_device *device = modem->device;
728 connman_device_set_string(device, "Operator", name);
730 for (g_hash_table_iter_init(&i, network_hash);
731 g_hash_table_iter_next(&i, NULL, &value);) {
732 struct connman_network *network = value;
734 if (connman_network_get_device(network) == device) {
735 connman_network_set_name(network, name);
736 connman_network_update(network);
741 static void modem_strength_changed(struct modem_data *modem, uint8_t strength)
743 struct connman_device *device = modem->device;
747 modem->strength = strength;
748 modem->has_strength = TRUE;
753 for (g_hash_table_iter_init(&i, network_hash);
754 g_hash_table_iter_next(&i, NULL, &value);) {
755 struct connman_network *network = value;
757 if (connman_network_get_device(network) == device) {
758 connman_network_set_strength(network, strength);
759 connman_network_update(network);
764 static void modem_roaming_changed(struct modem_data *modem,
767 struct connman_device *device = modem->device;
768 connman_bool_t roaming;
775 connman_device_set_string(device, "RegistrationStatus", status);
777 if (g_str_equal(status, "roaming"))
779 else if (g_str_equal(status, "registered"))
784 for (g_hash_table_iter_init(&i, network_hash);
785 g_hash_table_iter_next(&i, NULL, &value);) {
786 struct connman_network *network = value;
788 if (connman_network_get_device(network) == device) {
789 connman_network_set_roaming(network, roaming);
790 connman_network_update(network);
795 static void modem_registration_changed(struct modem_data *modem,
796 DBusMessageIter *entry)
798 DBusMessageIter iter;
801 connman_uint8_t strength;
802 char const *name, *status, *mcc_s;
804 dbus_message_iter_get_basic(entry, &key);
808 dbus_message_iter_next(entry);
810 dbus_message_iter_recurse(entry, &iter);
812 type = dbus_message_iter_get_arg_type(&iter);
813 if (type != DBUS_TYPE_BYTE && type != DBUS_TYPE_STRING)
816 if (g_str_equal(key, "Name") && type == DBUS_TYPE_STRING) {
817 dbus_message_iter_get_basic(&iter, &name);
818 modem_operator_name_changed(modem, name);
819 } else if (g_str_equal(key, "Strength") && type == DBUS_TYPE_BYTE) {
820 dbus_message_iter_get_basic(&iter, &strength);
821 modem_strength_changed(modem, strength);
822 } else if (g_str_equal(key, "Status") && type == DBUS_TYPE_STRING) {
823 dbus_message_iter_get_basic(&iter, &status);
824 modem_roaming_changed(modem, status);
825 } else if (g_str_equal(key, "MobileCountryCode") &&
826 type == DBUS_TYPE_STRING) {
830 dbus_message_iter_get_basic(&iter, &mcc_s);
836 alpha2 = mcc_country_codes[mcc - 200];
837 connman_technology_set_regdom(alpha2);
842 static gboolean reg_changed(DBusConnection *connection,
843 DBusMessage *message, void *user_data)
845 const char *path = dbus_message_get_path(message);
846 struct modem_data *modem;
847 DBusMessageIter iter;
849 DBG("path %s", path);
851 modem = g_hash_table_lookup(modem_hash, path);
855 if (dbus_message_iter_init(message, &iter))
856 modem_registration_changed(modem, &iter);
861 static void check_registration_reply(DBusPendingCall *call, void *user_data)
863 char const *path = user_data;
864 struct modem_data *modem;
866 DBusMessageIter array, dict, entry;
868 DBG("path %s", path);
870 modem = g_hash_table_lookup(modem_hash, path);
874 reply = dbus_pending_call_steal_reply(call);
876 if (dbus_message_iter_init(reply, &array) == FALSE)
879 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
882 dbus_message_iter_recurse(&array, &dict);
883 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
884 dbus_message_iter_recurse(&dict, &entry);
885 modem_registration_changed(modem, &entry);
886 dbus_message_iter_next(&dict);
890 dbus_message_unref(reply);
892 dbus_pending_call_unref(call);
895 static void check_registration(struct modem_data *modem)
897 char const *path = modem->path;
899 DBG("modem %p path %s", modem, path);
901 call_ofono(path, OFONO_REGISTRATION_INTERFACE, GET_PROPERTIES,
902 check_registration_reply, g_strdup(path), g_free,
906 static void modem_gprs_changed(struct modem_data *modem,
907 DBusMessageIter *entry)
909 DBusMessageIter iter;
914 dbus_message_iter_get_basic(entry, &key);
918 dbus_message_iter_next(entry);
920 dbus_message_iter_recurse(entry, &iter);
922 type = dbus_message_iter_get_arg_type(&iter);
924 if (type != DBUS_TYPE_BOOLEAN)
927 dbus_message_iter_get_basic(&iter, &value);
929 if (g_str_equal(key, "Attached") == TRUE) {
930 DBG("Attached %d", value);
932 modem->attached = value;
935 modem_clear_network_errors(modem);
936 } else if (g_str_equal(key, "Powered") == TRUE) {
937 DBG("Powered %d", value);
939 modem->powered = value;
940 } else if (g_str_equal(key, "RoamingAllowed") == TRUE) {
941 DBG("RoamingAllowed %d", value);
943 modem->roaming_allowed = value;
947 static void check_gprs_reply(DBusPendingCall *call, void *user_data)
949 char const *path = user_data;
950 struct modem_data *modem;
952 DBusMessageIter array, dict, entry;
954 DBG("path %s", path);
956 modem = g_hash_table_lookup(modem_hash, path);
960 reply = dbus_pending_call_steal_reply(call);
962 if (dbus_message_iter_init(reply, &array) == FALSE)
965 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
968 dbus_message_iter_recurse(&array, &dict);
969 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
970 dbus_message_iter_recurse(&dict, &entry);
971 modem_gprs_changed(modem, &entry);
972 dbus_message_iter_next(&dict);
976 dbus_message_unref(reply);
978 dbus_pending_call_unref(call);
980 check_networks(modem);
983 static void check_gprs(struct modem_data *modem)
985 char const *path = modem->path;
987 DBG("modem %p path %s", modem, path);
989 call_ofono(path, OFONO_GPRS_INTERFACE, GET_PROPERTIES,
990 check_gprs_reply, g_strdup(path), g_free,
994 static void add_device(const char *path, const char *imsi)
996 struct modem_data *modem;
997 struct connman_device *device;
999 DBG("path %s imsi %s", path, imsi);
1007 modem = g_hash_table_lookup(modem_hash, path);
1011 if (modem->device) {
1012 if (!g_strcmp0(imsi, connman_device_get_ident(modem->device)))
1015 modem_remove_device(modem);
1018 if (strlen(imsi) == 0)
1021 device = connman_device_create(imsi, CONNMAN_DEVICE_TYPE_CELLULAR);
1025 connman_device_set_ident(device, imsi);
1027 connman_device_set_string(device, "Path", path);
1029 connman_device_set_data(device, modem);
1031 if (connman_device_register(device) < 0) {
1032 connman_device_unref(device);
1036 modem->device = device;
1039 check_registration(modem);
1041 if (modem->has_gprs)
1045 static void sim_properties_reply(DBusPendingCall *call, void *user_data)
1047 const char *path = user_data;
1048 const char *imsi = NULL;
1050 DBusMessageIter array, dict;
1052 DBG("path %s", path);
1054 reply = dbus_pending_call_steal_reply(call);
1056 if (dbus_message_iter_init(reply, &array) == FALSE)
1059 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1062 dbus_message_iter_recurse(&array, &dict);
1064 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1065 DBusMessageIter entry, value;
1068 dbus_message_iter_recurse(&dict, &entry);
1069 dbus_message_iter_get_basic(&entry, &key);
1071 dbus_message_iter_next(&entry);
1072 dbus_message_iter_recurse(&entry, &value);
1074 if (g_str_equal(key, "SubscriberIdentity")) {
1075 dbus_message_iter_get_basic(&value, &imsi);
1076 add_device(path, imsi);
1079 dbus_message_iter_next(&dict);
1083 dbus_message_unref(reply);
1085 dbus_pending_call_unref(call);
1088 static void get_imsi(const char *path)
1090 DBG("path %s", path);
1092 call_ofono(path, OFONO_SIM_INTERFACE, GET_PROPERTIES,
1093 sim_properties_reply, g_strdup(path), g_free,
1097 static int gprs_change_powered(const char *path, dbus_bool_t powered)
1099 DBG("path %s powered %d", path, powered);
1101 return set_property(path, OFONO_GPRS_INTERFACE, "Powered",
1102 DBUS_TYPE_BOOLEAN, &powered,
1106 static int modem_change_powered(const char *path, dbus_bool_t powered)
1108 DBG("path %s powered %d", path, powered);
1110 return set_property(path, OFONO_MODEM_INTERFACE, "Powered",
1111 DBUS_TYPE_BOOLEAN, &powered,
1116 static gboolean modem_has_interface(DBusMessageIter *array,
1117 char const *interface)
1119 DBusMessageIter entry;
1121 dbus_message_iter_recurse(array, &entry);
1123 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1124 const char *element;
1126 dbus_message_iter_get_basic(&entry, &element);
1128 if (g_strcmp0(interface, element) == 0)
1131 dbus_message_iter_next(&entry);
1137 static gboolean modem_has_sim(DBusMessageIter *array)
1139 return modem_has_interface(array, OFONO_SIM_INTERFACE);
1142 static gboolean modem_has_reg(DBusMessageIter *array)
1144 return modem_has_interface(array, OFONO_REGISTRATION_INTERFACE);
1147 static gboolean modem_has_gprs(DBusMessageIter *array)
1149 return modem_has_interface(array, OFONO_GPRS_INTERFACE);
1152 static void add_modem(const char *path, DBusMessageIter *prop)
1154 struct modem_data *modem;
1155 dbus_bool_t powered = FALSE;
1156 dbus_bool_t online = FALSE;
1157 dbus_bool_t has_online = FALSE;
1158 dbus_bool_t locked = FALSE;
1159 gboolean has_sim = FALSE;
1160 gboolean has_reg = FALSE;
1161 gboolean has_gprs = FALSE;
1163 modem = g_hash_table_lookup(modem_hash, path);
1168 modem = g_try_new0(struct modem_data, 1);
1172 modem->path = g_strdup(path);
1173 modem->device = NULL;
1174 modem->available = TRUE;
1176 g_hash_table_insert(modem_hash, g_strdup(path), modem);
1178 while (dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY) {
1179 DBusMessageIter entry, value;
1182 dbus_message_iter_recurse(prop, &entry);
1183 dbus_message_iter_get_basic(&entry, &key);
1185 dbus_message_iter_next(&entry);
1186 dbus_message_iter_recurse(&entry, &value);
1188 if (g_str_equal(key, "Powered") == TRUE)
1189 dbus_message_iter_get_basic(&value, &powered);
1190 else if (g_str_equal(key, "Lockdown") == TRUE)
1191 dbus_message_iter_get_basic(&value, &locked);
1192 else if (g_str_equal(key, "Online") == TRUE) {
1194 dbus_message_iter_get_basic(&value, &online);
1195 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1196 has_sim = modem_has_sim(&value);
1197 has_reg = modem_has_reg(&value);
1198 has_gprs = modem_has_gprs(&value);
1201 dbus_message_iter_next(prop);
1208 modem_change_powered(path, TRUE);
1210 modem->has_sim = has_sim;
1211 modem->has_reg = has_reg;
1212 modem->has_gprs = has_gprs;
1214 update_modem_online(modem, online);
1220 static void manager_modems_reply(DBusPendingCall *call, void *user_data)
1224 DBusMessageIter array, dict;
1228 reply = dbus_pending_call_steal_reply(call);
1230 if (dbus_message_has_signature(reply, "a(oa{sv})") == FALSE)
1233 dbus_error_init(&error);
1235 if (dbus_set_error_from_message(&error, reply)) {
1236 connman_error("ModemManager.GetModems() %s %s",
1237 error.name, error.message);
1238 dbus_error_free(&error);
1242 if (dbus_message_iter_init(reply, &array) == FALSE)
1245 dbus_message_iter_recurse(&array, &dict);
1247 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
1248 DBusMessageIter value, properties;
1249 const char *modem_path;
1251 dbus_message_iter_recurse(&dict, &value);
1252 dbus_message_iter_get_basic(&value, &modem_path);
1254 dbus_message_iter_next(&value);
1255 dbus_message_iter_recurse(&value, &properties);
1258 add_modem(modem_path, &properties);
1260 dbus_message_iter_next(&dict);
1264 dbus_message_unref(reply);
1266 dbus_pending_call_unref(call);
1269 static void ofono_connect(DBusConnection *connection, void *user_data)
1271 DBG("connection %p", connection);
1273 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1274 g_free, remove_modem);
1276 network_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1277 NULL, remove_network);
1279 call_ofono("/", OFONO_MANAGER_INTERFACE, GET_MODEMS,
1280 manager_modems_reply, NULL, NULL,
1284 static void ofono_disconnect(DBusConnection *connection, void *user_data)
1286 DBG("connection %p", connection);
1288 if (modem_hash == NULL)
1291 g_hash_table_destroy(modem_hash);
1296 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1299 const char *path = dbus_message_get_path(message);
1300 struct modem_data *modem;
1301 DBusMessageIter iter, value;
1304 DBG("path %s", path);
1306 modem = g_hash_table_lookup(modem_hash, path);
1310 if (dbus_message_iter_init(message, &iter) == FALSE)
1313 dbus_message_iter_get_basic(&iter, &key);
1315 dbus_message_iter_next(&iter);
1316 dbus_message_iter_recurse(&iter, &value);
1318 if (g_str_equal(key, "Powered") == TRUE) {
1319 dbus_bool_t powered;
1321 dbus_message_iter_get_basic(&value, &powered);
1322 if (powered == TRUE)
1325 modem->has_sim = FALSE;
1326 modem->has_reg = FALSE;
1327 modem->has_gprs = FALSE;
1329 modem_remove_device(modem);
1330 } else if (g_str_equal(key, "Online") == TRUE) {
1333 dbus_message_iter_get_basic(&value, &online);
1335 update_modem_online(modem, online);
1336 } else if (g_str_equal(key, "Lockdown") == TRUE) {
1339 dbus_message_iter_get_basic(&value, &locked);
1342 modem_change_powered(path, TRUE);
1344 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1345 gboolean has_sim = modem_has_sim(&value);
1346 gboolean has_reg = modem_has_reg(&value);
1347 gboolean added_reg = has_reg && !modem->has_reg;
1348 gboolean has_gprs = modem_has_gprs(&value);
1349 gboolean added_gprs = has_gprs && !modem->has_gprs;
1351 modem->has_sim = has_sim;
1352 modem->has_reg = has_reg;
1353 modem->has_gprs = has_gprs;
1355 if (modem->device == NULL) {
1357 get_imsi(modem->path);
1358 } else if (!has_sim) {
1359 modem_remove_device(modem);
1362 check_registration(modem);
1365 gprs_change_powered(modem->path, TRUE);
1374 static gboolean sim_changed(DBusConnection *connection, DBusMessage *message,
1377 const char *path = dbus_message_get_path(message);
1378 struct modem_data *modem;
1379 DBusMessageIter iter, value;
1382 DBG("path %s", path);
1384 modem = g_hash_table_lookup(modem_hash, path);
1388 if (dbus_message_iter_init(message, &iter) == FALSE)
1391 dbus_message_iter_get_basic(&iter, &key);
1393 dbus_message_iter_next(&iter);
1394 dbus_message_iter_recurse(&iter, &value);
1396 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1399 dbus_message_iter_get_basic(&value, &imsi);
1401 add_device(path, imsi);
1402 } else if (g_str_equal(key, "Present") == TRUE) {
1403 dbus_bool_t present;
1405 dbus_message_iter_get_basic(&value, &present);
1410 if (modem->device != NULL)
1411 modem_remove_device(modem);
1413 modem->has_gprs = FALSE;
1414 modem->has_reg = FALSE;
1420 static gboolean gprs_changed(DBusConnection *connection, DBusMessage *message,
1423 const char *path = dbus_message_get_path(message);
1424 struct modem_data *modem;
1425 DBusMessageIter iter;
1427 DBG("path %s", path);
1429 modem = g_hash_table_lookup(modem_hash, path);
1433 if (dbus_message_iter_init(message, &iter))
1434 modem_gprs_changed(modem, &iter);
1439 static gboolean modem_added(DBusConnection *connection,
1440 DBusMessage *message, void *user_data)
1442 DBusMessageIter iter, properties;
1443 const char *modem_path;
1447 if (dbus_message_iter_init(message, &iter) == FALSE)
1450 dbus_message_iter_get_basic(&iter, &modem_path);
1452 dbus_message_iter_next(&iter);
1453 dbus_message_iter_recurse(&iter, &properties);
1455 add_modem(modem_path, &properties);
1460 static gboolean modem_removed(DBusConnection *connection,
1461 DBusMessage *message, void *user_data)
1463 DBusMessageIter iter;
1464 const char *modem_path;
1468 if (dbus_message_iter_init(message, &iter) == FALSE)
1471 dbus_message_iter_get_basic(&iter, &modem_path);
1473 g_hash_table_remove(modem_hash, modem_path);
1479 static void get_dns(DBusMessageIter *array, struct connman_element *parent)
1481 DBusMessageIter entry;
1482 gchar *nameserver = NULL, *nameserver_old = NULL;
1486 dbus_message_iter_recurse(array, &entry);
1488 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1491 dbus_message_iter_get_basic(&entry, &dns);
1495 if (nameserver == NULL) {
1497 nameserver = g_strdup(dns);
1500 nameserver_old = nameserver;
1501 nameserver = g_strdup_printf("%s %s",
1502 nameserver_old, dns);
1503 g_free(nameserver_old);
1506 dbus_message_iter_next(&entry);
1509 parent->ipv4.nameserver = nameserver;
1512 static void update_settings(DBusMessageIter *array,
1513 struct connman_network *network)
1515 struct connman_element *parent = connman_network_get_element(network);
1516 DBusMessageIter dict;
1517 const char *interface = NULL;
1519 DBG("network %p", network);
1521 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
1524 dbus_message_iter_recurse(array, &dict);
1526 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1527 DBusMessageIter entry, value;
1530 dbus_message_iter_recurse(&dict, &entry);
1531 dbus_message_iter_get_basic(&entry, &key);
1535 dbus_message_iter_next(&entry);
1536 dbus_message_iter_recurse(&entry, &value);
1538 if (g_str_equal(key, "Interface") == TRUE) {
1541 dbus_message_iter_get_basic(&value, &interface);
1543 DBG("interface %s", interface);
1545 index = connman_inet_ifindex(interface);
1547 connman_network_set_index(network, index);
1549 connman_error("Can not find interface %s",
1553 } else if (g_str_equal(key, "Method") == TRUE) {
1556 dbus_message_iter_get_basic(&value, &method);
1557 if (g_strcmp0(method, "static") == 0) {
1559 parent->ipv4.method =
1560 CONNMAN_IPCONFIG_METHOD_FIXED;
1561 } else if (g_strcmp0(method, "dhcp") == 0) {
1563 parent->ipv4.method =
1564 CONNMAN_IPCONFIG_METHOD_DHCP;
1567 } else if (g_str_equal(key, "Address") == TRUE) {
1568 const char *address;
1570 dbus_message_iter_get_basic(&value, &address);
1572 DBG("address %s", address);
1574 parent->ipv4.address = g_strdup(address);
1575 } else if (g_str_equal(key, "Netmask") == TRUE) {
1576 const char *netmask;
1578 dbus_message_iter_get_basic(&value, &netmask);
1580 DBG("netmask %s", netmask);
1582 parent->ipv4.netmask = g_strdup(netmask);
1583 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
1585 get_dns(&value, parent);
1586 } else if (g_str_equal(key, "Gateway") == TRUE) {
1587 const char *gateway;
1589 dbus_message_iter_get_basic(&value, &gateway);
1591 DBG("gateway %s", gateway);
1593 parent->ipv4.gateway = g_strdup(gateway);
1596 dbus_message_iter_next(&dict);
1599 /* deactive, oFono send NULL inteface before deactive signal */
1600 if (interface == NULL)
1601 connman_network_set_index(network, -1);
1604 static void cleanup_ipconfig(struct connman_network *network)
1606 struct connman_element *parent = connman_network_get_element(network);
1608 g_free(parent->ipv4.address);
1609 parent->ipv4.address = NULL;
1611 g_free(parent->ipv4.netmask);
1612 parent->ipv4.netmask = NULL;
1614 g_free(parent->ipv4.nameserver);
1615 parent->ipv4.nameserver = NULL;
1617 g_free(parent->ipv4.gateway);
1618 parent->ipv4.gateway = NULL;
1620 parent->ipv4.method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1624 static void set_connected(struct connman_network *network,
1625 connman_bool_t connected)
1627 struct connman_element *parent = connman_network_get_element(network);
1628 enum connman_ipconfig_method method = parent->ipv4.method;
1631 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1632 case CONNMAN_IPCONFIG_METHOD_OFF:
1633 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1634 case CONNMAN_IPCONFIG_METHOD_AUTO:
1637 case CONNMAN_IPCONFIG_METHOD_FIXED:
1638 connman_network_set_ipv4_method(network, method);
1640 connman_network_set_connected(network, connected);
1642 if (connected == FALSE)
1643 cleanup_ipconfig(network);
1647 case CONNMAN_IPCONFIG_METHOD_DHCP:
1648 connman_network_set_ipv4_method(network, method);
1650 connman_network_set_connected(network, connected);
1655 static gboolean context_changed(DBusConnection *connection,
1656 DBusMessage *message, void *user_data)
1658 const char *path = dbus_message_get_path(message);
1659 struct connman_network *network;
1660 DBusMessageIter iter, value;
1663 DBG("path %s", path);
1665 network = g_hash_table_lookup(network_hash, path);
1666 if (network == NULL)
1669 if (!pending_network_is_available(network)) {
1670 remove_network(network);
1674 if (dbus_message_iter_init(message, &iter) == FALSE)
1677 dbus_message_iter_get_basic(&iter, &key);
1679 dbus_message_iter_next(&iter);
1680 dbus_message_iter_recurse(&iter, &value);
1682 if (g_str_equal(key, "Settings") == TRUE)
1683 update_settings(&value, network);
1684 else if (g_str_equal(key, "Active") == TRUE) {
1687 dbus_message_iter_get_basic(&value, &active);
1689 set_connected(network, active);
1696 static guint reg_watch;
1697 static guint sim_watch;
1698 static guint gprs_watch;
1699 static guint modem_watch;
1700 static guint modem_added_watch;
1701 static guint modem_removed_watch;
1702 static guint context_watch;
1704 static int ofono_init(void)
1708 connection = connman_dbus_get_connection();
1709 if (connection == NULL)
1712 watch = g_dbus_add_service_watch(connection, OFONO_SERVICE,
1713 ofono_connect, ofono_disconnect, NULL, NULL);
1715 reg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1716 OFONO_REGISTRATION_INTERFACE,
1721 gprs_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1722 OFONO_GPRS_INTERFACE,
1727 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1728 OFONO_MODEM_INTERFACE,
1733 sim_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1734 OFONO_SIM_INTERFACE,
1739 modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1740 OFONO_MANAGER_INTERFACE,
1745 modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1746 OFONO_MANAGER_INTERFACE,
1751 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1752 OFONO_CONTEXT_INTERFACE,
1757 if (watch == 0 || gprs_watch == 0 || modem_watch == 0 ||
1758 reg_watch == 0 || sim_watch == 0 ||
1759 modem_added_watch == 0 || modem_removed_watch == 0 ||
1760 context_watch == 0) {
1765 err = connman_network_driver_register(&network_driver);
1769 err = connman_device_driver_register(&modem_driver);
1771 connman_network_driver_unregister(&network_driver);
1778 g_dbus_remove_watch(connection, watch);
1779 g_dbus_remove_watch(connection, sim_watch);
1780 g_dbus_remove_watch(connection, reg_watch);
1781 g_dbus_remove_watch(connection, gprs_watch);
1782 g_dbus_remove_watch(connection, modem_watch);
1783 g_dbus_remove_watch(connection, modem_added_watch);
1784 g_dbus_remove_watch(connection, modem_removed_watch);
1785 g_dbus_remove_watch(connection, context_watch);
1787 dbus_connection_unref(connection);
1792 static void ofono_exit(void)
1794 g_dbus_remove_watch(connection, watch);
1795 g_dbus_remove_watch(connection, sim_watch);
1796 g_dbus_remove_watch(connection, reg_watch);
1797 g_dbus_remove_watch(connection, gprs_watch);
1798 g_dbus_remove_watch(connection, modem_watch);
1799 g_dbus_remove_watch(connection, modem_added_watch);
1800 g_dbus_remove_watch(connection, modem_removed_watch);
1801 g_dbus_remove_watch(connection, context_watch);
1803 ofono_disconnect(connection, NULL);
1805 connman_device_driver_unregister(&modem_driver);
1806 connman_network_driver_unregister(&network_driver);
1808 dbus_connection_unref(connection);
1811 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
1812 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)