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 gboolean pending_online;
71 gboolean requested_online;
75 static int modem_probe(struct connman_device *device)
77 DBG("device %p", device);
82 static void modem_remove(struct connman_device *device)
84 DBG("device %p", device);
87 static int call_ofono(const char *path,
88 const char *interface, const char *method,
89 DBusPendingCallNotifyFunction notify, void *user_data,
90 DBusFreeFunction free_function,
94 DBusPendingCall *call;
98 DBG("path %s %s.%s", path, interface, method);
103 message = dbus_message_new_method_call(OFONO_SERVICE, path,
108 dbus_message_set_auto_start(message, FALSE);
111 ok = dbus_message_append_args_valist(message, type, va);
117 if (dbus_connection_send_with_reply(connection, message,
118 &call, TIMEOUT) == FALSE) {
119 connman_error("Failed to call %s.%s", interface, method);
120 dbus_message_unref(message);
125 connman_error("D-Bus connection not available");
126 dbus_message_unref(message);
130 dbus_pending_call_set_notify(call, notify, user_data, free_function);
132 dbus_message_unref(message);
137 static void set_property_reply(DBusPendingCall *call, void *user_data)
141 char const *name = user_data;
145 dbus_error_init(&error);
147 reply = dbus_pending_call_steal_reply(call);
149 if (dbus_set_error_from_message(&error, reply)) {
150 connman_error("SetProperty(%s) %s %s", name,
151 error.name, error.message);
152 dbus_error_free(&error);
155 dbus_message_unref(reply);
157 dbus_pending_call_unref(call);
160 static int set_property(const char *path, const char *interface,
161 const char *property, int type, void *value,
162 DBusPendingCallNotifyFunction notify, void *user_data,
163 DBusFreeFunction free_function)
165 DBusMessage *message;
166 DBusMessageIter iter;
167 DBusPendingCall *call;
169 DBG("path %s %s.%s", path, interface, property);
171 g_assert(notify == NULL ? free_function == NULL : 1);
176 message = dbus_message_new_method_call(OFONO_SERVICE, path,
177 interface, SET_PROPERTY);
181 dbus_message_set_auto_start(message, FALSE);
183 dbus_message_iter_init_append(message, &iter);
184 connman_dbus_property_append_basic(&iter, property, type, value);
186 if (dbus_connection_send_with_reply(connection, message,
187 &call, TIMEOUT) == FALSE) {
188 connman_error("Failed to change \"%s\" property on %s",
189 property, interface);
190 dbus_message_unref(message);
195 connman_error("D-Bus connection not available");
196 dbus_message_unref(message);
200 if (notify == NULL) {
201 notify = set_property_reply;
202 user_data = (void *)property;
203 free_function = NULL;
206 dbus_pending_call_set_notify(call, notify, user_data, free_function);
208 dbus_message_unref(message);
213 static void update_modem_online(struct modem_data *modem,
214 connman_bool_t online)
216 DBG("modem %p path %s online %d", modem, modem->path, online);
218 modem->online = online;
219 modem->requested_online = online;
220 modem->pending_online = FALSE;
223 connman_device_set_powered(modem->device, online);
226 static void set_online_reply(DBusPendingCall *call, void *user_data)
228 struct modem_data *modem;
233 DBG("path %s", (char *)user_data);
235 if (modem_hash == NULL)
238 modem = g_hash_table_lookup(modem_hash, user_data);
242 reply = dbus_pending_call_steal_reply(call);
244 dbus_error_init(&error);
246 if (dbus_set_error_from_message(&error, reply)) {
247 connman_error("SetProperty(Online): %s: %s",
248 error.name, error.message);
249 dbus_error_free(&error);
251 result = modem->online;
253 result = modem->requested_online;
255 if (modem->pending_online)
256 update_modem_online(modem, result);
258 dbus_message_unref(reply);
260 dbus_pending_call_unref(call);
263 static int modem_change_online(char const *path, dbus_bool_t online)
265 return set_property(path, OFONO_MODEM_INTERFACE, "Online",
266 DBUS_TYPE_BOOLEAN, &online,
268 (void *)g_strdup(path), g_free);
271 static int modem_enable(struct connman_device *device)
273 const char *path = connman_device_get_string(device, "Path");
275 DBG("device %p, path, %s", device, path);
277 return modem_change_online(path, TRUE);
280 static int modem_disable(struct connman_device *device)
282 const char *path = connman_device_get_string(device, "Path");
284 DBG("device %p, path, %s", device, path);
286 return modem_change_online(path, FALSE);
289 static struct connman_device_driver modem_driver = {
291 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
292 .probe = modem_probe,
293 .remove = modem_remove,
294 .enable = modem_enable,
295 .disable = modem_disable,
298 static void modem_remove_device(struct modem_data *modem)
300 DBG("modem %p path %s device %p", modem, modem->path, modem->device);
302 if (modem->device == NULL)
305 connman_device_remove_all_networks(modem->device);
306 connman_device_unregister(modem->device);
307 connman_device_unref(modem->device);
309 modem->device = NULL;
312 static void remove_modem(gpointer data)
314 struct modem_data *modem = data;
316 modem_remove_device(modem);
323 static char *get_ident(const char *path)
330 pos = strrchr(path, '/');
337 static void create_service(struct connman_network *network)
344 path = connman_network_get_string(network, "Path");
346 group = get_ident(path);
348 connman_network_set_group(network, group);
351 static void set_network_name_reply(DBusPendingCall *call, void *user_data)
353 struct connman_network *network = user_data;
355 DBusMessageIter array, dict;
357 DBG("network %p", network);
359 reply = dbus_pending_call_steal_reply(call);
361 if (dbus_message_iter_init(reply, &array) == FALSE)
364 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
367 dbus_message_iter_recurse(&array, &dict);
369 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
370 DBusMessageIter entry, value;
373 dbus_message_iter_recurse(&dict, &entry);
374 dbus_message_iter_get_basic(&entry, &key);
376 dbus_message_iter_next(&entry);
377 dbus_message_iter_recurse(&entry, &value);
380 * 'Operator' is deprecated since version 0.20, but
381 * keep it here for backward compatibility reasons.
383 if (g_str_equal(key, "Operator") == TRUE ||
384 g_str_equal(key, "Name") == TRUE) {
387 dbus_message_iter_get_basic(&value, &name);
388 connman_network_set_name(network, name);
389 create_service(network);
390 } else if (g_strcmp0(key, "Status") == 0) {
392 connman_bool_t roaming;
394 dbus_message_iter_get_basic(&value, &status);
395 if (g_strcmp0(status, "roaming") == 0)
397 else if (g_strcmp0(status, "registered") == 0)
400 dbus_message_iter_next(&dict);
404 connman_network_set_roaming(network, roaming);
405 connman_network_update(network);
408 dbus_message_iter_next(&dict);
411 dbus_message_unref(reply);
413 dbus_pending_call_unref(call);
416 static void set_network_name(struct connman_network *network)
418 struct connman_device *device;
421 device = connman_network_get_device(network);
423 path = connman_device_get_string(device, "Path");
427 DBG("path %s", path);
429 call_ofono(path, OFONO_REGISTRATION_INTERFACE, GET_PROPERTIES,
430 set_network_name_reply, network, NULL,
434 static void config_network_reply(DBusPendingCall *call, void *user_data)
436 struct connman_network *network = user_data;
438 DBusMessageIter array, dict;
439 gboolean internet_type = FALSE;
441 DBG("network %p", network);
443 reply = dbus_pending_call_steal_reply(call);
445 if (dbus_message_iter_init(reply, &array) == FALSE)
448 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
451 dbus_message_iter_recurse(&array, &dict);
453 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
454 DBusMessageIter entry, value;
457 dbus_message_iter_recurse(&dict, &entry);
458 dbus_message_iter_get_basic(&entry, &key);
460 dbus_message_iter_next(&entry);
461 dbus_message_iter_recurse(&entry, &value);
463 if (g_str_equal(key, "Type") == TRUE) {
466 dbus_message_iter_get_basic(&value, &type);
467 if (g_strcmp0(type, "internet") == 0) {
468 internet_type = TRUE;
470 connman_network_set_protocol(network,
471 CONNMAN_NETWORK_PROTOCOL_IP);
472 set_network_name(network);
474 internet_type = FALSE;
476 connman_network_set_protocol(network,
477 CONNMAN_NETWORK_PROTOCOL_UNKNOWN);
481 dbus_message_iter_next(&dict);
485 dbus_message_unref(reply);
487 dbus_pending_call_unref(call);
490 static void config_network(struct connman_network *network, const char *path)
492 DBG("path %s", path);
494 call_ofono(path, OFONO_PRI_CONTEXT_INTERFACE, GET_PROPERTIES,
495 config_network_reply, network, NULL,
499 static gboolean registration_changed(DBusConnection *connection,
500 DBusMessage *message, void *user_data)
502 const char *path = dbus_message_get_path(message);
503 struct connman_network *network = user_data;
504 DBusMessageIter iter, value;
507 DBG("path %s", path);
509 if (dbus_message_iter_init(message, &iter) == FALSE)
512 dbus_message_iter_get_basic(&iter, &key);
516 dbus_message_iter_next(&iter);
517 dbus_message_iter_recurse(&iter, &value);
519 if (g_strcmp0(key, "Name") == 0 ||
520 g_strcmp0(key, "Operator") == 0) {
523 dbus_message_iter_get_basic(&value, &name);
524 DBG("name %s", name);
525 connman_network_set_name(network, name);
526 create_service(network);
527 } else if (g_strcmp0(key, "Strength") == 0) {
528 connman_uint8_t strength;
530 dbus_message_iter_get_basic(&value, &strength);
531 connman_network_set_strength(network, strength);
532 connman_network_update(network);
533 } else if (g_strcmp0(key, "Status") == 0) {
535 connman_bool_t roaming;
537 dbus_message_iter_get_basic(&value, &status);
538 if (g_strcmp0(status, "roaming") == 0)
540 else if (g_strcmp0(status, "registered") == 0)
545 connman_network_set_roaming(network, roaming);
546 connman_network_update(network);
552 static int network_probe(struct connman_network *network)
557 reg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
558 OFONO_REGISTRATION_INTERFACE,
560 registration_changed,
565 connman_network_set_data(network, GUINT_TO_POINTER(reg_watch));
567 path = connman_network_get_string(network, "Path");
569 DBG("network %p path %s", network, path);
571 config_network(network, path);
576 static struct connman_network *pending_network;
578 static gboolean pending_network_is_available(struct connman_network *network)
580 /* Modem or network may be removed during waiting for active reply */
581 if (connman_network_get_device(network) == NULL) {
582 DBG("Modem or network was removed");
589 static void set_active_reply(DBusPendingCall *call, void *user_data)
593 struct connman_network *network = user_data;
595 DBG("network %p", network);
597 reply = dbus_pending_call_steal_reply(call);
599 if (pending_network_is_available(network) == FALSE)
602 dbus_error_init(&error);
603 if (dbus_set_error_from_message(&error, reply)) {
604 if (connman_network_get_index(network) < 0)
605 connman_network_set_error(network,
606 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
608 pending_network = NULL;
610 connman_error("SetProperty(Active) %s %s",
611 error.name, error.message);
613 dbus_error_free(&error);
615 pending_network = network;
618 dbus_message_unref(reply);
620 dbus_pending_call_unref(call);
623 static int set_network_active(struct connman_network *network,
628 const char *path = connman_network_get_string(network, "Path");
630 DBG("network %p, path %s, active %d", network, path, active);
632 error = set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
633 "Active", DBUS_TYPE_BOOLEAN, &active,
634 set_active_reply, network, NULL);
635 if (active == FALSE && error == -EINPROGRESS)
641 static void set_apn(struct connman_network *network)
643 const char *apn, *path;
645 apn = connman_network_get_string(network, "Cellular.APN");
649 path = connman_network_get_string(network, "Path");
653 DBG("path %s, apn %s", path, apn);
655 set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
656 "AccessPointName", DBUS_TYPE_STRING, &apn,
660 static int network_connect(struct connman_network *network)
662 if (connman_network_get_index(network) >= 0)
665 return set_network_active(network, TRUE);
668 static int network_disconnect(struct connman_network *network)
670 if (connman_network_get_index(network) < 0)
673 return set_network_active(network, FALSE);
676 static void network_remove(struct connman_network *network)
680 DBG("network %p", network);
682 reg_watch = GPOINTER_TO_UINT(connman_network_get_data(network));
683 g_dbus_remove_watch(connection, reg_watch);
686 static int network_setup(struct connman_network *network, const char *key)
690 if (g_strcmp0(key, "Cellular.APN") == 0)
696 static struct connman_network_driver network_driver = {
698 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
699 .probe = network_probe,
700 .remove = network_remove,
701 .connect = network_connect,
702 .disconnect = network_disconnect,
703 .setup = network_setup,
706 static void add_network(struct connman_device *device, const char *path)
708 struct connman_network *network;
711 DBG("device %p path %s", device, path);
713 ident = get_ident(path);
715 network = connman_device_get_network(device, ident);
719 network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
723 if (connman_network_set_string(network, "Path", path) != 0)
726 connman_network_set_available(network, TRUE);
727 connman_network_set_index(network, -1);
729 if (connman_device_add_network(device, network) == 0)
733 connman_network_unref(network);
736 static void add_networks(struct connman_device *device, DBusMessageIter *array)
738 DBusMessageIter entry;
742 dbus_message_iter_recurse(array, &entry);
744 while (dbus_message_iter_get_arg_type(&entry) ==
745 DBUS_TYPE_OBJECT_PATH) {
748 dbus_message_iter_get_basic(&entry, &path);
750 add_network(device, path);
752 dbus_message_iter_next(&entry);
756 static void create_context_reply(DBusPendingCall *call, void *user_data)
763 dbus_error_init(&error);
765 reply = dbus_pending_call_steal_reply(call);
767 if (dbus_set_error_from_message(&error, reply)) {
768 connman_error("CreateContext() %s %s",
769 error.name, error.message);
770 dbus_error_free(&error);
773 dbus_message_unref(reply);
775 dbus_pending_call_unref(call);
778 static void add_default_context(DBusMessageIter *array,
779 const char *path, const char *name, const char *type)
781 DBusMessageIter entry;
788 dbus_message_iter_recurse(array, &entry);
790 if (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_OBJECT_PATH)
793 DBG("path %s, name %s, type %s", path, name, type);
795 call_ofono(path, OFONO_GPRS_INTERFACE, CREATE_CONTEXT,
796 create_context_reply, NULL, NULL,
797 DBUS_TYPE_STRING, &name,
798 DBUS_TYPE_STRING, &type,
802 static void check_networks_reply(DBusPendingCall *call, void *user_data)
804 char *path = user_data;
805 struct modem_data *modem;
806 struct connman_device *device;
808 DBusMessageIter array, dict, contexts;
809 dbus_bool_t attached;
811 DBG("path %s", path);
813 modem = g_hash_table_lookup(modem_hash, path);
814 if (modem == NULL || modem->device == NULL)
817 device = modem->device;
819 reply = dbus_pending_call_steal_reply(call);
821 if (dbus_message_iter_init(reply, &array) == FALSE)
824 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
827 dbus_message_iter_recurse(&array, &dict);
829 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
830 DBusMessageIter entry, value;
833 dbus_message_iter_recurse(&dict, &entry);
834 dbus_message_iter_get_basic(&entry, &key);
836 dbus_message_iter_next(&entry);
837 dbus_message_iter_recurse(&entry, &value);
841 if (g_str_equal(key, "Attached") == TRUE) {
842 dbus_message_iter_get_basic(&value, &attached);
843 DBG("Attached %d", attached);
844 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
847 path = connman_device_get_string(device, "Path");
849 add_default_context(&contexts, path,
850 CONTEXT_NAME, CONTEXT_TYPE);
853 dbus_message_iter_next(&dict);
856 if (attached == TRUE)
857 add_networks(device, &contexts);
860 dbus_message_unref(reply);
862 dbus_pending_call_unref(call);
865 static void check_networks(struct modem_data *modem)
867 char const *path = modem->path;
869 DBG("modem %p path %s", modem, path);
871 call_ofono(path, OFONO_GPRS_INTERFACE, GET_PROPERTIES,
872 check_networks_reply, g_strdup(path), g_free,
876 static void add_device(const char *path, const char *imsi)
878 struct modem_data *modem;
879 struct connman_device *device;
881 DBG("path %s imsi %s", path, imsi);
889 modem = g_hash_table_lookup(modem_hash, path);
894 if (g_str_equal(imsi, connman_device_get_ident(modem->device)))
897 modem_remove_device(modem);
900 if (strlen(imsi) == 0)
903 device = connman_device_create(imsi, CONNMAN_DEVICE_TYPE_CELLULAR);
907 connman_device_set_ident(device, imsi);
909 connman_device_set_mode(device, CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE);
911 connman_device_set_string(device, "Path", path);
913 if (connman_device_register(device) < 0) {
914 connman_device_unref(device);
918 modem->device = device;
921 check_networks(modem);
924 static void sim_properties_reply(DBusPendingCall *call, void *user_data)
926 const char *path = user_data;
929 DBusMessageIter array, dict;
931 DBG("path %s", path);
933 reply = dbus_pending_call_steal_reply(call);
935 if (dbus_message_iter_init(reply, &array) == FALSE)
938 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
941 dbus_message_iter_recurse(&array, &dict);
943 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
944 DBusMessageIter entry, value;
947 dbus_message_iter_recurse(&dict, &entry);
948 dbus_message_iter_get_basic(&entry, &key);
950 dbus_message_iter_next(&entry);
951 dbus_message_iter_recurse(&entry, &value);
953 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
954 dbus_message_iter_get_basic(&value, &imsi);
955 add_device(path, imsi);
958 dbus_message_iter_next(&dict);
962 dbus_message_unref(reply);
964 dbus_pending_call_unref(call);
967 static void get_imsi(const char *path)
969 DBG("path %s", path);
971 call_ofono(path, OFONO_SIM_INTERFACE, GET_PROPERTIES,
972 sim_properties_reply, g_strdup(path), g_free,
976 static int modem_change_powered(const char *path, dbus_bool_t powered)
978 DBG("path %s powered %d", path, powered);
980 return set_property(path, OFONO_MODEM_INTERFACE, "Powered",
981 DBUS_TYPE_BOOLEAN, &powered,
985 static struct modem_data *add_modem(const char *path)
987 struct modem_data *modem;
989 DBG("path %s", path);
994 modem = g_hash_table_lookup(modem_hash, path);
996 modem->available = TRUE;
1001 modem = g_try_new0(struct modem_data, 1);
1005 modem->path = g_strdup(path);
1006 modem->device = NULL;
1007 modem->available = TRUE;
1009 g_hash_table_insert(modem_hash, g_strdup(path), modem);
1014 static gboolean modem_has_interface(DBusMessageIter *array,
1015 char const *interface)
1017 DBusMessageIter entry;
1019 dbus_message_iter_recurse(array, &entry);
1021 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1022 const char *element;
1024 dbus_message_iter_get_basic(&entry, &element);
1026 if (g_strcmp0(interface, element) == 0)
1029 dbus_message_iter_next(&entry);
1035 static gboolean modem_has_sim(DBusMessageIter *array)
1037 return modem_has_interface(array, OFONO_SIM_INTERFACE);
1040 static gboolean modem_has_gprs(DBusMessageIter *array)
1042 return modem_has_interface(array, OFONO_GPRS_INTERFACE);
1045 static void modem_properties_reply(DBusPendingCall *call, void *user_data)
1049 DBusMessageIter array, dict;
1050 const char *path = user_data;
1051 dbus_bool_t powered = FALSE;
1052 dbus_bool_t online = FALSE;
1053 dbus_bool_t has_online = FALSE;
1054 gboolean has_sim = FALSE;
1055 gboolean has_gprs = FALSE;
1056 struct modem_data *new_modem;
1058 DBG("path %s", path);
1060 reply = dbus_pending_call_steal_reply(call);
1062 if (g_hash_table_lookup(modem_hash, path))
1065 dbus_error_init(&error);
1067 if (dbus_set_error_from_message(&error, reply)) {
1068 connman_error("Modem.GetProperties(%s) %s %s",
1069 path, error.name, error.message);
1070 dbus_error_free(&error);
1074 if (dbus_message_iter_init(reply, &array) == FALSE)
1077 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1080 dbus_message_iter_recurse(&array, &dict);
1082 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1083 DBusMessageIter entry, value;
1086 dbus_message_iter_recurse(&dict, &entry);
1087 dbus_message_iter_get_basic(&entry, &key);
1089 dbus_message_iter_next(&entry);
1090 dbus_message_iter_recurse(&entry, &value);
1092 if (g_str_equal(key, "Powered") == TRUE)
1093 dbus_message_iter_get_basic(&value, &powered);
1094 else if (g_str_equal(key, "Online") == TRUE) {
1096 dbus_message_iter_get_basic(&value, &online);
1097 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1098 has_sim = modem_has_sim(&value);
1099 has_gprs = modem_has_gprs(&value);
1102 dbus_message_iter_next(&dict);
1105 new_modem = add_modem(path);
1106 if (new_modem == NULL)
1110 modem_change_powered(path, TRUE);
1112 new_modem->has_sim = has_sim;
1113 new_modem->has_gprs = has_gprs;
1115 update_modem_online(new_modem, online);
1121 dbus_message_unref(reply);
1123 dbus_pending_call_unref(call);
1126 static void get_modem_properties(const char *path)
1128 DBG("path %s", path);
1130 call_ofono(path, OFONO_MODEM_INTERFACE, GET_PROPERTIES,
1131 modem_properties_reply, g_strdup(path), g_free,
1135 static void mask_unavailable(gpointer key, gpointer value, gpointer user_data)
1137 struct modem_data *modem = value;
1139 modem->available = FALSE;
1142 static void modems_set_unavailable()
1144 g_hash_table_foreach(modem_hash, mask_unavailable, NULL);
1147 static void cleanup_modem(gpointer key, gpointer value, gpointer user_data)
1149 struct modem_data *modem = value;
1151 if (modem->available == FALSE)
1152 g_hash_table_remove(modem_hash, key);
1155 static void cleanup_modems()
1157 g_hash_table_foreach(modem_hash, cleanup_modem, NULL);
1160 static void update_modems(DBusMessageIter *array)
1162 DBusMessageIter entry;
1166 dbus_message_iter_recurse(array, &entry);
1168 modems_set_unavailable();
1170 while (dbus_message_iter_get_arg_type(&entry) ==
1171 DBUS_TYPE_OBJECT_PATH) {
1173 struct modem_data *modem;
1175 dbus_message_iter_get_basic(&entry, &path);
1177 modem = g_hash_table_lookup(modem_hash, path);
1180 modem->available = TRUE;
1182 get_modem_properties(path);
1184 dbus_message_iter_next(&entry);
1190 static void manager_properties_reply(DBusPendingCall *call, void *user_data)
1194 DBusMessageIter array, dict;
1198 reply = dbus_pending_call_steal_reply(call);
1200 dbus_error_init(&error);
1202 if (dbus_set_error_from_message(&error, reply)) {
1203 connman_error("ModemManager.GetProperties() %s %s",
1204 error.name, error.message);
1205 dbus_error_free(&error);
1209 if (dbus_message_iter_init(reply, &array) == FALSE)
1212 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1215 dbus_message_iter_recurse(&array, &dict);
1217 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1218 DBusMessageIter entry, value;
1221 dbus_message_iter_recurse(&dict, &entry);
1222 dbus_message_iter_get_basic(&entry, &key);
1224 dbus_message_iter_next(&entry);
1225 dbus_message_iter_recurse(&entry, &value);
1227 if (g_str_equal(key, "Modems") == TRUE) {
1228 update_modems(&value);
1232 dbus_message_iter_next(&dict);
1236 dbus_message_unref(reply);
1238 dbus_pending_call_unref(call);
1241 static void ofono_connect(DBusConnection *connection, void *user_data)
1243 DBG("connection %p", connection);
1245 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1246 g_free, remove_modem);
1248 call_ofono("/", OFONO_MANAGER_INTERFACE, GET_PROPERTIES,
1249 manager_properties_reply, NULL, NULL,
1253 static void ofono_disconnect(DBusConnection *connection, void *user_data)
1255 DBG("connection %p", connection);
1257 if (modem_hash == NULL)
1260 g_hash_table_destroy(modem_hash);
1265 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1268 const char *path = dbus_message_get_path(message);
1269 struct modem_data *modem;
1270 DBusMessageIter iter, value;
1273 DBG("path %s", path);
1275 modem = g_hash_table_lookup(modem_hash, path);
1279 if (dbus_message_iter_init(message, &iter) == FALSE)
1282 dbus_message_iter_get_basic(&iter, &key);
1284 dbus_message_iter_next(&iter);
1285 dbus_message_iter_recurse(&iter, &value);
1287 if (g_str_equal(key, "Powered") == TRUE) {
1288 dbus_bool_t powered;
1290 dbus_message_iter_get_basic(&value, &powered);
1291 if (powered == TRUE)
1294 modem->has_sim = FALSE;
1295 modem->has_gprs = FALSE;
1297 modem_remove_device(modem);
1298 } else if (g_str_equal(key, "Online") == TRUE) {
1301 dbus_message_iter_get_basic(&value, &online);
1303 update_modem_online(modem, online);
1304 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1305 gboolean has_sim = modem_has_sim(&value);
1306 gboolean has_gprs = modem_has_gprs(&value);
1308 modem->has_sim = has_sim;
1309 modem->has_gprs = has_gprs;
1311 if (modem->device == NULL) {
1313 get_imsi(modem->path);
1314 } else if (!has_sim) {
1315 modem_remove_device(modem);
1322 static gboolean sim_changed(DBusConnection *connection, DBusMessage *message,
1325 const char *path = dbus_message_get_path(message);
1326 struct modem_data *modem;
1327 DBusMessageIter iter, value;
1330 DBG("path %s", path);
1332 modem = g_hash_table_lookup(modem_hash, path);
1336 if (dbus_message_iter_init(message, &iter) == FALSE)
1339 dbus_message_iter_get_basic(&iter, &key);
1341 dbus_message_iter_next(&iter);
1342 dbus_message_iter_recurse(&iter, &value);
1344 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1347 dbus_message_iter_get_basic(&value, &imsi);
1349 add_device(path, imsi);
1350 } else if (g_str_equal(key, "Present") == TRUE) {
1351 dbus_bool_t present;
1353 dbus_message_iter_get_basic(&value, &present);
1358 if (modem->device != NULL)
1359 modem_remove_device(modem);
1361 modem->has_gprs = FALSE;
1367 static gboolean gprs_changed(DBusConnection *connection, DBusMessage *message,
1370 const char *path = dbus_message_get_path(message);
1371 struct modem_data *modem;
1372 DBusMessageIter iter, value;
1375 DBG("path %s", path);
1377 modem = g_hash_table_lookup(modem_hash, path);
1381 if (dbus_message_iter_init(message, &iter) == FALSE)
1384 dbus_message_iter_get_basic(&iter, &key);
1386 dbus_message_iter_next(&iter);
1387 dbus_message_iter_recurse(&iter, &value);
1389 if (g_str_equal(key, "Attached") == TRUE) {
1390 dbus_bool_t attached;
1392 dbus_message_iter_get_basic(&value, &attached);
1394 DBG("Attached %d", attached);
1396 if (attached == TRUE)
1397 check_networks(modem);
1398 else if (modem->device != NULL)
1399 connman_device_remove_all_networks(modem->device);
1401 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
1402 check_networks(modem);
1408 static gboolean manager_changed(DBusConnection *connection,
1409 DBusMessage *message, void *user_data)
1411 const char *path = dbus_message_get_path(message);
1412 DBusMessageIter iter, value;
1415 DBG("path %s", path);
1417 if (dbus_message_iter_init(message, &iter) == FALSE)
1420 dbus_message_iter_get_basic(&iter, &key);
1422 dbus_message_iter_next(&iter);
1423 dbus_message_iter_recurse(&iter, &value);
1425 if (g_str_equal(key, "Modems") == TRUE)
1426 update_modems(&value);
1431 static void get_dns(DBusMessageIter *array, struct connman_element *parent)
1433 DBusMessageIter entry;
1434 gchar *nameserver = NULL, *nameserver_old = NULL;
1438 dbus_message_iter_recurse(array, &entry);
1440 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1443 dbus_message_iter_get_basic(&entry, &dns);
1447 if (nameserver == NULL) {
1449 nameserver = g_strdup(dns);
1452 nameserver_old = nameserver;
1453 nameserver = g_strdup_printf("%s %s",
1454 nameserver_old, dns);
1455 g_free(nameserver_old);
1458 dbus_message_iter_next(&entry);
1461 parent->ipv4.nameserver = nameserver;
1464 static void update_settings(DBusMessageIter *array,
1465 struct connman_network *network)
1467 struct connman_element *parent = connman_network_get_element(network);
1468 DBusMessageIter dict;
1469 const char *interface = NULL;
1471 DBG("network %p", network);
1473 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
1476 dbus_message_iter_recurse(array, &dict);
1478 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1479 DBusMessageIter entry, value;
1482 dbus_message_iter_recurse(&dict, &entry);
1483 dbus_message_iter_get_basic(&entry, &key);
1487 dbus_message_iter_next(&entry);
1488 dbus_message_iter_recurse(&entry, &value);
1490 if (g_str_equal(key, "Interface") == TRUE) {
1493 dbus_message_iter_get_basic(&value, &interface);
1495 DBG("interface %s", interface);
1497 index = connman_inet_ifindex(interface);
1499 connman_network_set_index(network, index);
1501 connman_error("Can not find interface %s",
1505 } else if (g_str_equal(key, "Method") == TRUE) {
1508 dbus_message_iter_get_basic(&value, &method);
1509 if (g_strcmp0(method, "static") == 0) {
1511 parent->ipv4.method =
1512 CONNMAN_IPCONFIG_METHOD_FIXED;
1513 } else if (g_strcmp0(method, "dhcp") == 0) {
1515 parent->ipv4.method =
1516 CONNMAN_IPCONFIG_METHOD_DHCP;
1519 } else if (g_str_equal(key, "Address") == TRUE) {
1520 const char *address;
1522 dbus_message_iter_get_basic(&value, &address);
1524 DBG("address %s", address);
1526 parent->ipv4.address = g_strdup(address);
1527 } else if (g_str_equal(key, "Netmask") == TRUE) {
1528 const char *netmask;
1530 dbus_message_iter_get_basic(&value, &netmask);
1532 DBG("netmask %s", netmask);
1534 parent->ipv4.netmask = g_strdup(netmask);
1535 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
1537 get_dns(&value, parent);
1538 } else if (g_str_equal(key, "Gateway") == TRUE) {
1539 const char *gateway;
1541 dbus_message_iter_get_basic(&value, &gateway);
1543 DBG("gateway %s", gateway);
1545 parent->ipv4.gateway = g_strdup(gateway);
1548 dbus_message_iter_next(&dict);
1551 /* deactive, oFono send NULL inteface before deactive signal */
1552 if (interface == NULL)
1553 connman_network_set_index(network, -1);
1556 static void cleanup_ipconfig(struct connman_network *network)
1558 struct connman_element *parent = connman_network_get_element(network);
1560 g_free(parent->ipv4.address);
1561 parent->ipv4.address = NULL;
1563 g_free(parent->ipv4.netmask);
1564 parent->ipv4.netmask = NULL;
1566 g_free(parent->ipv4.nameserver);
1567 parent->ipv4.nameserver = NULL;
1569 g_free(parent->ipv4.gateway);
1570 parent->ipv4.gateway = NULL;
1572 parent->ipv4.method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1576 static void set_connected(struct connman_network *network,
1577 connman_bool_t connected)
1579 struct connman_element *parent = connman_network_get_element(network);
1580 enum connman_ipconfig_method method = parent->ipv4.method;
1583 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1584 case CONNMAN_IPCONFIG_METHOD_OFF:
1585 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1588 case CONNMAN_IPCONFIG_METHOD_FIXED:
1589 connman_network_set_method(network, method);
1591 if (connected == FALSE)
1592 cleanup_ipconfig(network);
1594 connman_network_set_connected(network, connected);
1597 case CONNMAN_IPCONFIG_METHOD_DHCP:
1598 connman_network_set_method(network, method);
1600 connman_network_set_connected(network, connected);
1605 static gboolean pri_context_changed(DBusConnection *connection,
1606 DBusMessage *message, void *user_data)
1608 const char *path = dbus_message_get_path(message);
1609 const char *pending_path;
1610 DBusMessageIter iter, value;
1613 DBG("pending_network %p, path %s", pending_network, path);
1615 if (pending_network == NULL)
1618 pending_path = connman_network_get_string(pending_network, "Path");
1619 if (g_strcmp0(pending_path, path) != 0)
1622 if (dbus_message_iter_init(message, &iter) == FALSE)
1625 dbus_message_iter_get_basic(&iter, &key);
1627 dbus_message_iter_next(&iter);
1628 dbus_message_iter_recurse(&iter, &value);
1630 if (g_str_equal(key, "Settings") == TRUE)
1631 update_settings(&value, pending_network);
1632 else if (g_str_equal(key, "Active") == TRUE) {
1635 dbus_message_iter_get_basic(&value, &active);
1637 set_connected(pending_network, active);
1639 pending_network = NULL;
1646 static guint sim_watch;
1647 static guint gprs_watch;
1648 static guint modem_watch;
1649 static guint manager_watch;
1650 static guint context_watch;
1652 static int ofono_init(void)
1656 connection = connman_dbus_get_connection();
1657 if (connection == NULL)
1660 watch = g_dbus_add_service_watch(connection, OFONO_SERVICE,
1661 ofono_connect, ofono_disconnect, NULL, NULL);
1663 gprs_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1664 OFONO_GPRS_INTERFACE,
1669 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1670 OFONO_MODEM_INTERFACE,
1675 sim_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1676 OFONO_SIM_INTERFACE,
1681 manager_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1682 OFONO_MANAGER_INTERFACE,
1687 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1688 OFONO_PRI_CONTEXT_INTERFACE,
1690 pri_context_changed,
1693 if (watch == 0 || gprs_watch == 0 || modem_watch == 0 ||
1695 manager_watch == 0 || context_watch == 0) {
1700 err = connman_network_driver_register(&network_driver);
1704 err = connman_device_driver_register(&modem_driver);
1706 connman_network_driver_unregister(&network_driver);
1713 g_dbus_remove_watch(connection, watch);
1714 g_dbus_remove_watch(connection, sim_watch);
1715 g_dbus_remove_watch(connection, gprs_watch);
1716 g_dbus_remove_watch(connection, modem_watch);
1717 g_dbus_remove_watch(connection, manager_watch);
1718 g_dbus_remove_watch(connection, context_watch);
1720 dbus_connection_unref(connection);
1725 static void ofono_exit(void)
1727 g_dbus_remove_watch(connection, watch);
1728 g_dbus_remove_watch(connection, sim_watch);
1729 g_dbus_remove_watch(connection, gprs_watch);
1730 g_dbus_remove_watch(connection, modem_watch);
1731 g_dbus_remove_watch(connection, manager_watch);
1732 g_dbus_remove_watch(connection, context_watch);
1734 ofono_disconnect(connection, NULL);
1736 connman_device_driver_unregister(&modem_driver);
1737 connman_network_driver_unregister(&network_driver);
1739 dbus_connection_unref(connection);
1742 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
1743 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)