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, '/');
255 return g_strdup(pos + 1);
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);
274 static void set_network_name_reply(DBusPendingCall *call, void *user_data)
276 struct connman_network *network = user_data;
278 DBusMessageIter array, dict;
280 DBG("network %p", network);
282 reply = dbus_pending_call_steal_reply(call);
284 if (dbus_message_iter_init(reply, &array) == FALSE)
287 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
290 dbus_message_iter_recurse(&array, &dict);
292 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
293 DBusMessageIter entry, value;
296 dbus_message_iter_recurse(&dict, &entry);
297 dbus_message_iter_get_basic(&entry, &key);
299 dbus_message_iter_next(&entry);
300 dbus_message_iter_recurse(&entry, &value);
303 * 'Operator' is deprecated since version 0.20, but
304 * keep it here for backward compatibility reasons.
306 if (g_str_equal(key, "Operator") == TRUE ||
307 g_str_equal(key, "Name") == TRUE) {
310 dbus_message_iter_get_basic(&value, &name);
311 connman_network_set_name(network, name);
312 create_service(network);
313 } else if (g_strcmp0(key, "Status") == 0) {
315 connman_bool_t roaming;
317 dbus_message_iter_get_basic(&value, &status);
318 if (g_strcmp0(status, "roaming") == 0)
320 else if (g_strcmp0(status, "registered") == 0)
323 dbus_message_iter_next(&dict);
327 connman_network_set_roaming(network, roaming);
328 connman_network_update(network);
331 dbus_message_iter_next(&dict);
334 dbus_message_unref(reply);
336 dbus_pending_call_unref(call);
339 static void set_network_name(struct connman_network *network)
341 struct connman_device *device;
344 device = connman_network_get_device(network);
346 path = connman_device_get_string(device, "Path");
350 DBG("path %s", path);
352 call_ofono(path, OFONO_REGISTRATION_INTERFACE, GET_PROPERTIES,
353 set_network_name_reply, network, NULL,
357 static void config_network_reply(DBusPendingCall *call, void *user_data)
359 struct connman_network *network = user_data;
361 DBusMessageIter array, dict;
362 gboolean internet_type = FALSE;
364 DBG("network %p", network);
366 reply = dbus_pending_call_steal_reply(call);
368 if (dbus_message_iter_init(reply, &array) == FALSE)
371 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
374 dbus_message_iter_recurse(&array, &dict);
376 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
377 DBusMessageIter entry, value;
380 dbus_message_iter_recurse(&dict, &entry);
381 dbus_message_iter_get_basic(&entry, &key);
383 dbus_message_iter_next(&entry);
384 dbus_message_iter_recurse(&entry, &value);
386 if (g_str_equal(key, "Type") == TRUE) {
389 dbus_message_iter_get_basic(&value, &type);
390 if (g_strcmp0(type, "internet") == 0) {
391 internet_type = TRUE;
393 connman_network_set_protocol(network,
394 CONNMAN_NETWORK_PROTOCOL_IP);
395 set_network_name(network);
397 internet_type = FALSE;
399 connman_network_set_protocol(network,
400 CONNMAN_NETWORK_PROTOCOL_UNKNOWN);
404 dbus_message_iter_next(&dict);
408 dbus_message_unref(reply);
410 dbus_pending_call_unref(call);
413 static void config_network(struct connman_network *network, const char *path)
415 DBG("path %s", path);
417 call_ofono(path, OFONO_PRI_CONTEXT_INTERFACE, GET_PROPERTIES,
418 config_network_reply, network, NULL,
422 static gboolean registration_changed(DBusConnection *connection,
423 DBusMessage *message, void *user_data)
425 const char *path = dbus_message_get_path(message);
426 struct connman_network *network = user_data;
427 DBusMessageIter iter, value;
430 DBG("path %s", path);
432 if (dbus_message_iter_init(message, &iter) == FALSE)
435 dbus_message_iter_get_basic(&iter, &key);
439 dbus_message_iter_next(&iter);
440 dbus_message_iter_recurse(&iter, &value);
442 if (g_strcmp0(key, "Name") == 0 ||
443 g_strcmp0(key, "Operator") == 0) {
446 dbus_message_iter_get_basic(&value, &name);
447 DBG("name %s", name);
448 connman_network_set_name(network, name);
449 create_service(network);
450 } else if (g_strcmp0(key, "Strength") == 0) {
451 connman_uint8_t strength;
453 dbus_message_iter_get_basic(&value, &strength);
454 connman_network_set_strength(network, strength);
455 connman_network_update(network);
456 } else if (g_strcmp0(key, "Status") == 0) {
458 connman_bool_t roaming;
460 dbus_message_iter_get_basic(&value, &status);
461 if (g_strcmp0(status, "roaming") == 0)
463 else if (g_strcmp0(status, "registered") == 0)
468 connman_network_set_roaming(network, roaming);
469 connman_network_update(network);
475 static int network_probe(struct connman_network *network)
480 reg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
481 OFONO_REGISTRATION_INTERFACE,
483 registration_changed,
488 connman_network_set_data(network, GUINT_TO_POINTER(reg_watch));
490 path = connman_network_get_string(network, "Path");
492 DBG("network %p path %s", network, path);
494 config_network(network, path);
499 static struct connman_network *pending_network;
501 static gboolean pending_network_is_available(
502 struct connman_network *pending_network)
504 struct connman_device *device;
505 struct connman_network *network;
506 const char *identifier;
509 /* Modem may be removed during waiting for active reply */
510 device = connman_network_get_device(pending_network);
511 if (device == NULL) {
512 DBG("Modem is removed");
516 identifier = connman_network_get_identifier(pending_network);
518 ident = g_strdup(identifier);
520 connman_network_unref(pending_network);
522 /* network may be removed during waiting for active reply */
523 network = connman_device_get_network(device, ident);
533 static void set_active_reply(DBusPendingCall *call, void *user_data)
537 struct connman_network *network = user_data;
539 DBG("network %p", network);
541 reply = dbus_pending_call_steal_reply(call);
543 if (pending_network_is_available(network) == FALSE)
546 dbus_error_init(&error);
547 if (dbus_set_error_from_message(&error, reply)) {
548 if (connman_network_get_index(network) < 0)
549 connman_network_set_error(network,
550 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
552 pending_network = NULL;
554 connman_error("SetProperty(Active) %s %s",
555 error.name, error.message);
557 dbus_error_free(&error);
559 pending_network = network;
562 dbus_message_unref(reply);
564 dbus_pending_call_unref(call);
567 static int set_network_active(struct connman_network *network,
572 const char *path = connman_network_get_string(network, "Path");
574 DBG("network %p, path %s, active %d", network, path, active);
576 error = set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
577 "Active", DBUS_TYPE_BOOLEAN, &active,
578 set_active_reply, network, NULL);
579 if (active == FALSE && error == -EINPROGRESS)
585 static void set_apn(struct connman_network *network)
587 const char *apn, *path;
589 apn = connman_network_get_string(network, "Cellular.APN");
593 path = connman_network_get_string(network, "Path");
597 DBG("path %s, apn %s", path, apn);
599 set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
600 "AccessPointName", DBUS_TYPE_STRING, &apn,
604 static int network_connect(struct connman_network *network)
606 if (connman_network_get_index(network) >= 0)
609 return set_network_active(network, TRUE);
612 static int network_disconnect(struct connman_network *network)
614 if (connman_network_get_index(network) < 0)
617 return set_network_active(network, FALSE);
620 static void network_remove(struct connman_network *network)
624 DBG("network %p", network);
626 reg_watch = GPOINTER_TO_UINT(connman_network_get_data(network));
627 g_dbus_remove_watch(connection, reg_watch);
630 static int network_setup(struct connman_network *network, const char *key)
634 if (g_strcmp0(key, "Cellular.APN") == 0)
640 static struct connman_network_driver network_driver = {
642 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
643 .probe = network_probe,
644 .remove = network_remove,
645 .connect = network_connect,
646 .disconnect = network_disconnect,
647 .setup = network_setup,
650 static void add_network(struct connman_device *device, const char *path)
652 struct connman_network *network;
657 DBG("device %p path %s", device, path);
659 network = connman_device_get_network(device, path);
663 ident = get_ident(path);
665 network = connman_network_create(ident,
666 CONNMAN_NETWORK_TYPE_CELLULAR);
672 connman_network_set_string(network, "Path", path);
673 connman_network_set_available(network, TRUE);
674 connman_network_set_index(network, -1);
676 mcc = connman_device_get_string(device, "MCC");
678 connman_network_set_string(network, "Cellular.MCC", mcc);
680 mnc = connman_device_get_string(device, "MNC");
682 connman_network_set_string(network, "Cellular.MNC", mnc);
684 connman_device_add_network(device, network);
687 static void add_networks(struct connman_device *device, DBusMessageIter *array)
689 DBusMessageIter entry;
693 dbus_message_iter_recurse(array, &entry);
695 while (dbus_message_iter_get_arg_type(&entry) ==
696 DBUS_TYPE_OBJECT_PATH) {
699 dbus_message_iter_get_basic(&entry, &path);
701 add_network(device, path);
703 dbus_message_iter_next(&entry);
707 static void create_context_reply(DBusPendingCall *call, void *user_data)
714 dbus_error_init(&error);
716 reply = dbus_pending_call_steal_reply(call);
718 if (dbus_set_error_from_message(&error, reply)) {
719 connman_error("CreateContext() %s %s",
720 error.name, error.message);
721 dbus_error_free(&error);
724 dbus_message_unref(reply);
726 dbus_pending_call_unref(call);
729 static void add_default_context(DBusMessageIter *array,
730 const char *path, const char *name, const char *type)
732 DBusMessageIter entry;
739 dbus_message_iter_recurse(array, &entry);
741 if (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_OBJECT_PATH)
744 DBG("path %s, name %s, type %s", path, name, type);
746 call_ofono(path, OFONO_GPRS_INTERFACE, CREATE_CONTEXT,
747 create_context_reply, NULL, NULL,
748 DBUS_TYPE_STRING, &name,
749 DBUS_TYPE_STRING, &type,
753 static void check_networks_reply(DBusPendingCall *call, void *user_data)
755 char *path = user_data;
756 struct modem_data *modem;
757 struct connman_device *device;
759 DBusMessageIter array, dict, contexts;
760 dbus_bool_t attached;
762 DBG("path %s", path);
764 modem = g_hash_table_lookup(modem_hash, path);
765 if (modem == NULL || modem->device == NULL)
768 device = modem->device;
770 reply = dbus_pending_call_steal_reply(call);
772 if (dbus_message_iter_init(reply, &array) == FALSE)
775 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
778 dbus_message_iter_recurse(&array, &dict);
780 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
781 DBusMessageIter entry, value;
784 dbus_message_iter_recurse(&dict, &entry);
785 dbus_message_iter_get_basic(&entry, &key);
787 dbus_message_iter_next(&entry);
788 dbus_message_iter_recurse(&entry, &value);
792 if (g_str_equal(key, "Attached") == TRUE) {
793 dbus_message_iter_get_basic(&value, &attached);
794 DBG("Attached %d", attached);
795 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
798 path = connman_device_get_string(device, "Path");
800 add_default_context(&contexts, path,
801 CONTEXT_NAME, CONTEXT_TYPE);
802 } else if (g_str_equal(key, "Powered") == TRUE) {
805 dbus_message_iter_get_basic(&value, &powered);
807 connman_device_set_powered(device, powered);
810 dbus_message_iter_next(&dict);
813 if (attached == TRUE)
814 add_networks(device, &contexts);
817 dbus_message_unref(reply);
819 dbus_pending_call_unref(call);
822 static void check_networks(struct modem_data *modem)
824 char const *path = modem->path;
826 DBG("modem %p path %s", modem, path);
828 call_ofono(path, OFONO_GPRS_INTERFACE, GET_PROPERTIES,
829 check_networks_reply, g_strdup(path), g_free,
833 static void add_device(const char *path, const char *imsi,
834 const char *mcc, const char *mnc)
836 struct modem_data *modem;
837 struct connman_device *device;
839 DBG("path %s imsi %s", path, imsi);
847 modem = g_hash_table_lookup(modem_hash, path);
851 device = connman_device_create(imsi, CONNMAN_DEVICE_TYPE_CELLULAR);
855 connman_device_set_ident(device, imsi);
857 connman_device_set_mode(device, CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE);
859 connman_device_set_string(device, "Path", path);
861 connman_device_set_string(device, "MCC", mcc);
863 connman_device_set_string(device, "MNC", mnc);
865 if (connman_device_register(device) < 0) {
866 connman_device_unref(device);
870 modem->device = device;
872 check_networks(modem);
875 static void sim_properties_reply(DBusPendingCall *call, void *user_data)
877 const char *path = user_data;
881 /* If MobileNetworkCodeLength is not provided, mnc_length is 0 */
882 unsigned char mnc_length = 0;
884 DBusMessageIter array, dict;
886 DBG("path %s", path);
888 reply = dbus_pending_call_steal_reply(call);
890 if (dbus_message_iter_init(reply, &array) == FALSE)
893 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
896 dbus_message_iter_recurse(&array, &dict);
898 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
899 DBusMessageIter entry, value;
902 dbus_message_iter_recurse(&dict, &entry);
903 dbus_message_iter_get_basic(&entry, &key);
905 dbus_message_iter_next(&entry);
906 dbus_message_iter_recurse(&entry, &value);
908 if (g_str_equal(key, "SubscriberIdentity") == TRUE)
909 dbus_message_iter_get_basic(&value, &imsi);
911 * 'MobileNetworkCodeLength' is deprecated since version 0.20, but
912 * keep it here for backward compatibility reasons.
914 else if (g_str_equal(key, "MobileNetworkCodeLength") == TRUE)
915 dbus_message_iter_get_basic(&value,
916 (void *) &mnc_length);
917 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
918 dbus_message_iter_get_basic(&value,
920 else if (g_str_equal(key, "MobileNetworkCode") == TRUE)
921 dbus_message_iter_get_basic(&value,
924 dbus_message_iter_next(&dict);
927 if (mnc_length == 2 || mnc_length == 3) {
928 mcc = g_strndup(imsi, 3);
929 mnc = g_strndup(imsi + 3, mnc_length);
932 add_device(path, imsi, mcc, mnc);
934 if (mnc_length == 2 || mnc_length == 3) {
940 dbus_message_unref(reply);
942 dbus_pending_call_unref(call);
945 static void get_imsi(const char *path)
947 DBG("path %s", path);
949 call_ofono(path, OFONO_SIM_INTERFACE, GET_PROPERTIES,
950 sim_properties_reply, g_strdup(path), g_free,
954 static int modem_change_powered(const char *path, dbus_bool_t powered)
956 DBG("path %s powered %d", path, powered);
958 return set_property(path, OFONO_MODEM_INTERFACE, "Powered",
959 DBUS_TYPE_BOOLEAN, &powered,
963 static struct modem_data *add_modem(const char *path)
965 struct modem_data *modem;
967 DBG("path %s", path);
972 modem = g_hash_table_lookup(modem_hash, path);
974 modem->available = TRUE;
979 modem = g_try_new0(struct modem_data, 1);
983 modem->path = g_strdup(path);
984 modem->device = NULL;
985 modem->available = TRUE;
987 g_hash_table_insert(modem_hash, g_strdup(path), modem);
992 static gboolean modem_has_gprs(DBusMessageIter *array)
994 DBusMessageIter entry;
996 dbus_message_iter_recurse(array, &entry);
998 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
999 const char *interface;
1001 dbus_message_iter_get_basic(&entry, &interface);
1003 if (g_strcmp0(OFONO_GPRS_INTERFACE, interface) == 0)
1006 dbus_message_iter_next(&entry);
1012 static void modem_properties_reply(DBusPendingCall *call, void *user_data)
1016 DBusMessageIter array, dict;
1017 const char *path = user_data;
1018 dbus_bool_t powered = FALSE;
1019 gboolean has_gprs = FALSE;
1020 struct modem_data *new_modem;
1022 DBG("path %s", path);
1024 reply = dbus_pending_call_steal_reply(call);
1026 if (g_hash_table_lookup(modem_hash, path))
1029 dbus_error_init(&error);
1031 if (dbus_set_error_from_message(&error, reply)) {
1032 connman_error("Modem.GetProperties(%s) %s %s",
1033 path, error.name, error.message);
1034 dbus_error_free(&error);
1038 if (dbus_message_iter_init(reply, &array) == FALSE)
1041 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1044 dbus_message_iter_recurse(&array, &dict);
1046 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1047 DBusMessageIter entry, value;
1050 dbus_message_iter_recurse(&dict, &entry);
1051 dbus_message_iter_get_basic(&entry, &key);
1053 dbus_message_iter_next(&entry);
1054 dbus_message_iter_recurse(&entry, &value);
1056 if (g_str_equal(key, "Powered") == TRUE)
1057 dbus_message_iter_get_basic(&value, &powered);
1058 else if (g_str_equal(key, "Interfaces") == TRUE)
1059 has_gprs = modem_has_gprs(&value);
1061 dbus_message_iter_next(&dict);
1064 new_modem = add_modem(path);
1065 if (new_modem == NULL)
1069 modem_change_powered(path, TRUE);
1075 dbus_message_unref(reply);
1077 dbus_pending_call_unref(call);
1080 static void get_modem_properties(const char *path)
1082 DBG("path %s", path);
1084 call_ofono(path, OFONO_MODEM_INTERFACE, GET_PROPERTIES,
1085 modem_properties_reply, g_strdup(path), g_free,
1089 static void mask_unavailable(gpointer key, gpointer value, gpointer user_data)
1091 struct modem_data *modem = value;
1093 modem->available = FALSE;
1096 static void modems_set_unavailable()
1098 g_hash_table_foreach(modem_hash, mask_unavailable, NULL);
1101 static void cleanup_modem(gpointer key, gpointer value, gpointer user_data)
1103 struct modem_data *modem = value;
1105 if (modem->available == FALSE)
1106 g_hash_table_remove(modem_hash, key);
1109 static void cleanup_modems()
1111 g_hash_table_foreach(modem_hash, cleanup_modem, NULL);
1114 static void update_modems(DBusMessageIter *array)
1116 DBusMessageIter entry;
1120 dbus_message_iter_recurse(array, &entry);
1122 modems_set_unavailable();
1124 while (dbus_message_iter_get_arg_type(&entry) ==
1125 DBUS_TYPE_OBJECT_PATH) {
1127 struct modem_data *modem;
1129 dbus_message_iter_get_basic(&entry, &path);
1131 modem = g_hash_table_lookup(modem_hash, path);
1134 modem->available = TRUE;
1136 get_modem_properties(path);
1138 dbus_message_iter_next(&entry);
1144 static void manager_properties_reply(DBusPendingCall *call, void *user_data)
1148 DBusMessageIter array, dict;
1152 reply = dbus_pending_call_steal_reply(call);
1154 dbus_error_init(&error);
1156 if (dbus_set_error_from_message(&error, reply)) {
1157 connman_error("ModemManager.GetProperties() %s %s",
1158 error.name, error.message);
1159 dbus_error_free(&error);
1163 if (dbus_message_iter_init(reply, &array) == FALSE)
1166 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1169 dbus_message_iter_recurse(&array, &dict);
1171 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1172 DBusMessageIter entry, value;
1175 dbus_message_iter_recurse(&dict, &entry);
1176 dbus_message_iter_get_basic(&entry, &key);
1178 dbus_message_iter_next(&entry);
1179 dbus_message_iter_recurse(&entry, &value);
1181 if (g_str_equal(key, "Modems") == TRUE) {
1182 update_modems(&value);
1186 dbus_message_iter_next(&dict);
1190 dbus_message_unref(reply);
1192 dbus_pending_call_unref(call);
1195 static void modem_remove_device(struct modem_data *modem)
1197 if (modem->device == NULL)
1200 connman_device_unregister(modem->device);
1201 connman_device_unref(modem->device);
1203 modem->device = NULL;
1206 static void remove_modem(gpointer data)
1208 struct modem_data *modem = data;
1210 g_free(modem->path);
1212 modem_remove_device(modem);
1217 static void ofono_connect(DBusConnection *connection, void *user_data)
1219 DBG("connection %p", connection);
1221 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1222 g_free, remove_modem);
1224 call_ofono("/", OFONO_MANAGER_INTERFACE, GET_PROPERTIES,
1225 manager_properties_reply, NULL, NULL,
1229 static void ofono_disconnect(DBusConnection *connection, void *user_data)
1231 DBG("connection %p", connection);
1233 if (modem_hash == NULL)
1236 g_hash_table_destroy(modem_hash);
1241 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1244 const char *path = dbus_message_get_path(message);
1245 struct modem_data *modem;
1246 DBusMessageIter iter, value;
1249 DBG("path %s", path);
1251 modem = g_hash_table_lookup(modem_hash, path);
1255 if (dbus_message_iter_init(message, &iter) == FALSE)
1258 dbus_message_iter_get_basic(&iter, &key);
1260 dbus_message_iter_next(&iter);
1261 dbus_message_iter_recurse(&iter, &value);
1263 if (g_str_equal(key, "Powered") == TRUE) {
1264 dbus_bool_t powered;
1266 dbus_message_iter_get_basic(&value, &powered);
1267 if (powered == TRUE)
1270 modem_remove_device(modem);
1271 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1272 if (modem_has_gprs(&value) == TRUE) {
1273 if (modem->device == NULL)
1274 get_imsi(modem->path);
1275 } else if (modem->device != NULL)
1276 modem_remove_device(modem);
1282 static gboolean gprs_changed(DBusConnection *connection, DBusMessage *message,
1285 const char *path = dbus_message_get_path(message);
1286 struct modem_data *modem;
1287 DBusMessageIter iter, value;
1290 DBG("path %s", path);
1292 modem = g_hash_table_lookup(modem_hash, path);
1296 if (dbus_message_iter_init(message, &iter) == FALSE)
1299 dbus_message_iter_get_basic(&iter, &key);
1301 dbus_message_iter_next(&iter);
1302 dbus_message_iter_recurse(&iter, &value);
1304 if (g_str_equal(key, "Attached") == TRUE) {
1305 dbus_bool_t attached;
1307 dbus_message_iter_get_basic(&value, &attached);
1309 DBG("Attached %d", attached);
1311 if (attached == TRUE)
1312 check_networks(modem);
1313 else if (modem->device != NULL)
1314 connman_device_remove_all_networks(modem->device);
1316 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
1317 check_networks(modem);
1318 } else if (g_str_equal(key, "Powered") == TRUE) {
1319 dbus_bool_t powered;
1321 if (modem->device == NULL)
1324 dbus_message_iter_get_basic(&value, &powered);
1325 connman_device_set_powered(modem->device, powered);
1331 static gboolean manager_changed(DBusConnection *connection,
1332 DBusMessage *message, void *user_data)
1334 const char *path = dbus_message_get_path(message);
1335 DBusMessageIter iter, value;
1338 DBG("path %s", path);
1340 if (dbus_message_iter_init(message, &iter) == FALSE)
1343 dbus_message_iter_get_basic(&iter, &key);
1345 dbus_message_iter_next(&iter);
1346 dbus_message_iter_recurse(&iter, &value);
1348 if (g_str_equal(key, "Modems") == TRUE)
1349 update_modems(&value);
1354 static void get_dns(DBusMessageIter *array, struct connman_element *parent)
1356 DBusMessageIter entry;
1357 gchar *nameserver = NULL, *nameserver_old = NULL;
1361 dbus_message_iter_recurse(array, &entry);
1363 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1366 dbus_message_iter_get_basic(&entry, &dns);
1370 if (nameserver == NULL) {
1372 nameserver = g_strdup(dns);
1375 nameserver_old = nameserver;
1376 nameserver = g_strdup_printf("%s %s",
1377 nameserver_old, dns);
1378 g_free(nameserver_old);
1381 dbus_message_iter_next(&entry);
1384 parent->ipv4.nameserver = nameserver;
1387 static void update_settings(DBusMessageIter *array,
1388 struct connman_element *parent)
1390 DBusMessageIter dict;
1391 const char *interface = NULL;
1395 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
1398 dbus_message_iter_recurse(array, &dict);
1400 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1401 DBusMessageIter entry, value;
1404 dbus_message_iter_recurse(&dict, &entry);
1405 dbus_message_iter_get_basic(&entry, &key);
1407 dbus_message_iter_next(&entry);
1408 dbus_message_iter_recurse(&entry, &value);
1410 if (g_str_equal(key, "Interface") == TRUE) {
1413 dbus_message_iter_get_basic(&value, &interface);
1415 DBG("interface %s", interface);
1417 index = connman_inet_ifindex(interface);
1419 connman_network_set_index(
1420 pending_network, index);
1422 connman_error("Can not find interface %s",
1426 } else if (g_str_equal(key, "Method") == TRUE) {
1429 dbus_message_iter_get_basic(&value, &method);
1430 if (g_strcmp0(method, "static") == 0) {
1432 parent->ipv4.method =
1433 CONNMAN_IPCONFIG_METHOD_FIXED;
1434 } else if (g_strcmp0(method, "dhcp") == 0) {
1436 parent->ipv4.method =
1437 CONNMAN_IPCONFIG_METHOD_DHCP;
1440 } else if (g_str_equal(key, "Address") == TRUE) {
1441 const char *address;
1443 dbus_message_iter_get_basic(&value, &address);
1445 DBG("address %s", address);
1447 parent->ipv4.address = g_strdup(address);
1448 } else if (g_str_equal(key, "Netmask") == TRUE) {
1449 const char *netmask;
1451 dbus_message_iter_get_basic(&value, &netmask);
1453 DBG("netmask %s", netmask);
1455 parent->ipv4.netmask = g_strdup(netmask);
1456 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
1458 get_dns(&value, parent);
1459 } else if (g_str_equal(key, "Gateway") == TRUE) {
1460 const char *gateway;
1462 dbus_message_iter_get_basic(&value, &gateway);
1464 DBG("gateway %s", gateway);
1466 parent->ipv4.gateway = g_strdup(gateway);
1469 dbus_message_iter_next(&dict);
1472 /* deactive, oFono send NULL inteface before deactive signal */
1473 if (interface == NULL)
1474 connman_network_set_index(pending_network, -1);
1477 static void cleanup_ipconfig(struct connman_element *parent)
1479 g_free(parent->ipv4.address);
1480 parent->ipv4.address = NULL;
1482 g_free(parent->ipv4.netmask);
1483 parent->ipv4.netmask = NULL;
1485 g_free(parent->ipv4.nameserver);
1486 parent->ipv4.nameserver = NULL;
1488 g_free(parent->ipv4.gateway);
1489 parent->ipv4.gateway = NULL;
1491 parent->ipv4.method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1494 static int static_network_set_connected(
1495 struct connman_network *pending_network,
1496 struct connman_element *parent,
1497 connman_bool_t connected)
1499 if (connected == FALSE)
1500 cleanup_ipconfig(parent);
1502 connman_network_set_connected(pending_network, connected);
1507 static gboolean pri_context_changed(DBusConnection *connection,
1508 DBusMessage *message, void *user_data)
1510 const char *path = dbus_message_get_path(message);
1511 struct connman_element *parent;
1512 const char *pending_path;
1513 DBusMessageIter iter, value;
1516 DBG("pending_network %p, path %s", pending_network, path);
1518 if (pending_network == NULL)
1521 pending_path = connman_network_get_string(pending_network, "Path");
1522 if (g_strcmp0(pending_path, path) != 0)
1525 parent = connman_network_get_element(pending_network);
1527 if (dbus_message_iter_init(message, &iter) == FALSE)
1530 dbus_message_iter_get_basic(&iter, &key);
1532 dbus_message_iter_next(&iter);
1533 dbus_message_iter_recurse(&iter, &value);
1535 if (g_str_equal(key, "Settings") == TRUE) {
1537 update_settings(&value, parent);
1538 } else if (g_str_equal(key, "Active") == TRUE) {
1541 dbus_message_iter_get_basic(&value, &active);
1543 switch (parent->ipv4.method) {
1544 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1545 case CONNMAN_IPCONFIG_METHOD_OFF:
1546 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1548 case CONNMAN_IPCONFIG_METHOD_FIXED:
1549 connman_network_set_method(pending_network,
1550 CONNMAN_IPCONFIG_METHOD_FIXED);
1552 if (static_network_set_connected(
1553 pending_network, parent, active) < 0)
1554 set_network_active(pending_network, FALSE);
1556 case CONNMAN_IPCONFIG_METHOD_DHCP:
1557 connman_network_set_method(pending_network,
1558 CONNMAN_IPCONFIG_METHOD_DHCP);
1559 connman_network_set_connected(pending_network, active);
1563 pending_network = NULL;
1570 static guint gprs_watch;
1571 static guint modem_watch;
1572 static guint manager_watch;
1573 static guint context_watch;
1575 static int ofono_init(void)
1579 connection = connman_dbus_get_connection();
1580 if (connection == NULL)
1583 watch = g_dbus_add_service_watch(connection, OFONO_SERVICE,
1584 ofono_connect, ofono_disconnect, NULL, NULL);
1586 gprs_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1587 OFONO_GPRS_INTERFACE,
1592 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1593 OFONO_MODEM_INTERFACE,
1598 manager_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1599 OFONO_MANAGER_INTERFACE,
1604 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1605 OFONO_PRI_CONTEXT_INTERFACE,
1607 pri_context_changed,
1610 if (watch == 0 || gprs_watch == 0 || modem_watch == 0 ||
1611 manager_watch == 0 || context_watch == 0) {
1616 err = connman_network_driver_register(&network_driver);
1620 err = connman_device_driver_register(&modem_driver);
1622 connman_network_driver_unregister(&network_driver);
1629 g_dbus_remove_watch(connection, watch);
1630 g_dbus_remove_watch(connection, gprs_watch);
1631 g_dbus_remove_watch(connection, modem_watch);
1632 g_dbus_remove_watch(connection, manager_watch);
1633 g_dbus_remove_watch(connection, context_watch);
1635 dbus_connection_unref(connection);
1640 static void ofono_exit(void)
1642 g_dbus_remove_watch(connection, watch);
1643 g_dbus_remove_watch(connection, gprs_watch);
1644 g_dbus_remove_watch(connection, modem_watch);
1645 g_dbus_remove_watch(connection, manager_watch);
1646 g_dbus_remove_watch(connection, context_watch);
1648 ofono_disconnect(connection, NULL);
1650 connman_device_driver_unregister(&modem_driver);
1651 connman_network_driver_unregister(&network_driver);
1653 dbus_connection_unref(connection);
1656 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
1657 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)