5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
6 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 #define CONNMAN_API_SUBJECT_TO_CHANGE
33 #include <connman/plugin.h>
34 #include <connman/element.h>
35 #include <connman/device.h>
36 #include <connman/network.h>
37 #include <connman/dbus.h>
38 #include <connman/inet.h>
39 #include <connman/log.h>
41 #define OFONO_SERVICE "org.ofono"
43 #define OFONO_MANAGER_INTERFACE OFONO_SERVICE ".Manager"
44 #define OFONO_MODEM_INTERFACE OFONO_SERVICE ".Modem"
45 #define OFONO_GPRS_INTERFACE OFONO_SERVICE ".DataConnectionManager"
46 #define OFONO_SIM_INTERFACE OFONO_SERVICE ".SimManager"
47 #define OFONO_PRI_CONTEXT_INTERFACE OFONO_SERVICE ".PrimaryDataContext"
48 #define OFONO_REGISTRATION_INTERFACE OFONO_SERVICE ".NetworkRegistration"
50 #define PROPERTY_CHANGED "PropertyChanged"
51 #define GET_PROPERTIES "GetProperties"
52 #define SET_PROPERTY "SetProperty"
53 #define CREATE_CONTEXT "CreateContext"
57 #define CONTEXT_NAME "3G Connection"
58 #define CONTEXT_TYPE "internet"
60 static DBusConnection *connection;
62 static GHashTable *modem_hash = NULL;
66 struct connman_device *device;
70 static int modem_probe(struct connman_device *device)
72 DBG("device %p", device);
77 static void modem_remove(struct connman_device *device)
79 DBG("device %p", device);
82 static int call_ofono(const char *path,
83 const char *interface, const char *method,
84 DBusPendingCallNotifyFunction notify, void *user_data,
85 DBusFreeFunction free_function,
89 DBusPendingCall *call;
93 DBG("path %s %s.%s", path, interface, method);
98 message = dbus_message_new_method_call(OFONO_SERVICE, path,
103 dbus_message_set_auto_start(message, FALSE);
106 ok = dbus_message_append_args_valist(message, type, va);
112 if (dbus_connection_send_with_reply(connection, message,
113 &call, TIMEOUT) == FALSE) {
114 connman_error("Failed to call %s.%s", interface, method);
115 dbus_message_unref(message);
120 connman_error("D-Bus connection not available");
121 dbus_message_unref(message);
125 dbus_pending_call_set_notify(call, notify, user_data, free_function);
127 dbus_message_unref(message);
132 static void set_property_reply(DBusPendingCall *call, void *user_data)
136 char const *name = user_data;
140 dbus_error_init(&error);
142 reply = dbus_pending_call_steal_reply(call);
144 if (dbus_set_error_from_message(&error, reply)) {
145 connman_error("SetProperty(%s) %s %s", name,
146 error.name, error.message);
147 dbus_error_free(&error);
150 dbus_message_unref(reply);
152 dbus_pending_call_unref(call);
155 static int set_property(const char *path, const char *interface,
156 const char *property, int type, void *value,
157 DBusPendingCallNotifyFunction notify, void *user_data,
158 DBusFreeFunction free_function)
160 DBusMessage *message;
161 DBusMessageIter iter;
162 DBusPendingCall *call;
164 DBG("path %s %s.%s", path, interface, property);
166 g_assert(notify == NULL ? free_function == NULL : 1);
171 message = dbus_message_new_method_call(OFONO_SERVICE, path,
172 interface, SET_PROPERTY);
176 dbus_message_set_auto_start(message, FALSE);
178 dbus_message_iter_init_append(message, &iter);
179 connman_dbus_property_append_basic(&iter, property, type, value);
181 if (dbus_connection_send_with_reply(connection, message,
182 &call, TIMEOUT) == FALSE) {
183 connman_error("Failed to change \"%s\" property on %s",
184 property, interface);
185 dbus_message_unref(message);
190 connman_error("D-Bus connection not available");
191 dbus_message_unref(message);
195 if (notify == NULL) {
196 notify = set_property_reply;
197 user_data = (void *)property;
198 free_function = NULL;
201 dbus_pending_call_set_notify(call, notify, user_data, free_function);
203 dbus_message_unref(message);
208 static int gprs_change_powered(const char *path, dbus_bool_t powered)
210 DBG("path %s powered %d", path, powered);
212 return set_property(path, OFONO_GPRS_INTERFACE, "Powered",
213 DBUS_TYPE_BOOLEAN, &powered,
217 static int modem_enable(struct connman_device *device)
219 const char *path = connman_device_get_string(device, "Path");
221 DBG("device %p, path, %s", device, path);
223 return gprs_change_powered(path, TRUE);
226 static int modem_disable(struct connman_device *device)
228 const char *path = connman_device_get_string(device, "Path");
230 DBG("device %p, path %s", device, path);
232 return gprs_change_powered(path, FALSE);
235 static struct connman_device_driver modem_driver = {
237 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
238 .probe = modem_probe,
239 .remove = modem_remove,
240 .enable = modem_enable,
241 .disable = modem_disable,
244 static char *get_ident(const char *path)
251 pos = strrchr(path, '/');
258 static void create_service(struct connman_network *network)
265 path = connman_network_get_string(network, "Path");
267 group = get_ident(path);
269 connman_network_set_group(network, group);
272 static void set_network_name_reply(DBusPendingCall *call, void *user_data)
274 struct connman_network *network = user_data;
276 DBusMessageIter array, dict;
278 DBG("network %p", network);
280 reply = dbus_pending_call_steal_reply(call);
282 if (dbus_message_iter_init(reply, &array) == FALSE)
285 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
288 dbus_message_iter_recurse(&array, &dict);
290 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
291 DBusMessageIter entry, value;
294 dbus_message_iter_recurse(&dict, &entry);
295 dbus_message_iter_get_basic(&entry, &key);
297 dbus_message_iter_next(&entry);
298 dbus_message_iter_recurse(&entry, &value);
301 * 'Operator' is deprecated since version 0.20, but
302 * keep it here for backward compatibility reasons.
304 if (g_str_equal(key, "Operator") == TRUE ||
305 g_str_equal(key, "Name") == TRUE) {
308 dbus_message_iter_get_basic(&value, &name);
309 connman_network_set_name(network, name);
310 create_service(network);
311 } else if (g_strcmp0(key, "Status") == 0) {
313 connman_bool_t roaming;
315 dbus_message_iter_get_basic(&value, &status);
316 if (g_strcmp0(status, "roaming") == 0)
318 else if (g_strcmp0(status, "registered") == 0)
321 dbus_message_iter_next(&dict);
325 connman_network_set_roaming(network, roaming);
326 connman_network_update(network);
329 dbus_message_iter_next(&dict);
332 dbus_message_unref(reply);
334 dbus_pending_call_unref(call);
337 static void set_network_name(struct connman_network *network)
339 struct connman_device *device;
342 device = connman_network_get_device(network);
344 path = connman_device_get_string(device, "Path");
348 DBG("path %s", path);
350 call_ofono(path, OFONO_REGISTRATION_INTERFACE, GET_PROPERTIES,
351 set_network_name_reply, network, NULL,
355 static void config_network_reply(DBusPendingCall *call, void *user_data)
357 struct connman_network *network = user_data;
359 DBusMessageIter array, dict;
360 gboolean internet_type = FALSE;
362 DBG("network %p", network);
364 reply = dbus_pending_call_steal_reply(call);
366 if (dbus_message_iter_init(reply, &array) == FALSE)
369 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
372 dbus_message_iter_recurse(&array, &dict);
374 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
375 DBusMessageIter entry, value;
378 dbus_message_iter_recurse(&dict, &entry);
379 dbus_message_iter_get_basic(&entry, &key);
381 dbus_message_iter_next(&entry);
382 dbus_message_iter_recurse(&entry, &value);
384 if (g_str_equal(key, "Type") == TRUE) {
387 dbus_message_iter_get_basic(&value, &type);
388 if (g_strcmp0(type, "internet") == 0) {
389 internet_type = TRUE;
391 connman_network_set_protocol(network,
392 CONNMAN_NETWORK_PROTOCOL_IP);
393 set_network_name(network);
395 internet_type = FALSE;
397 connman_network_set_protocol(network,
398 CONNMAN_NETWORK_PROTOCOL_UNKNOWN);
402 dbus_message_iter_next(&dict);
406 dbus_message_unref(reply);
408 dbus_pending_call_unref(call);
411 static void config_network(struct connman_network *network, const char *path)
413 DBG("path %s", path);
415 call_ofono(path, OFONO_PRI_CONTEXT_INTERFACE, GET_PROPERTIES,
416 config_network_reply, network, NULL,
420 static gboolean registration_changed(DBusConnection *connection,
421 DBusMessage *message, void *user_data)
423 const char *path = dbus_message_get_path(message);
424 struct connman_network *network = user_data;
425 DBusMessageIter iter, value;
428 DBG("path %s", path);
430 if (dbus_message_iter_init(message, &iter) == FALSE)
433 dbus_message_iter_get_basic(&iter, &key);
437 dbus_message_iter_next(&iter);
438 dbus_message_iter_recurse(&iter, &value);
440 if (g_strcmp0(key, "Name") == 0 ||
441 g_strcmp0(key, "Operator") == 0) {
444 dbus_message_iter_get_basic(&value, &name);
445 DBG("name %s", name);
446 connman_network_set_name(network, name);
447 create_service(network);
448 } else if (g_strcmp0(key, "Strength") == 0) {
449 connman_uint8_t strength;
451 dbus_message_iter_get_basic(&value, &strength);
452 connman_network_set_strength(network, strength);
453 connman_network_update(network);
454 } else if (g_strcmp0(key, "Status") == 0) {
456 connman_bool_t roaming;
458 dbus_message_iter_get_basic(&value, &status);
459 if (g_strcmp0(status, "roaming") == 0)
461 else if (g_strcmp0(status, "registered") == 0)
466 connman_network_set_roaming(network, roaming);
467 connman_network_update(network);
473 static int network_probe(struct connman_network *network)
478 reg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
479 OFONO_REGISTRATION_INTERFACE,
481 registration_changed,
486 connman_network_set_data(network, GUINT_TO_POINTER(reg_watch));
488 path = connman_network_get_string(network, "Path");
490 DBG("network %p path %s", network, path);
492 config_network(network, path);
497 static struct connman_network *pending_network;
499 static gboolean pending_network_is_available(struct connman_network *network)
501 /* Modem or network may be removed during waiting for active reply */
502 if (connman_network_get_device(network) == NULL) {
503 DBG("Modem or network was removed");
510 static void set_active_reply(DBusPendingCall *call, void *user_data)
514 struct connman_network *network = user_data;
516 DBG("network %p", network);
518 reply = dbus_pending_call_steal_reply(call);
520 if (pending_network_is_available(network) == FALSE)
523 dbus_error_init(&error);
524 if (dbus_set_error_from_message(&error, reply)) {
525 if (connman_network_get_index(network) < 0)
526 connman_network_set_error(network,
527 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
529 pending_network = NULL;
531 connman_error("SetProperty(Active) %s %s",
532 error.name, error.message);
534 dbus_error_free(&error);
536 pending_network = network;
539 dbus_message_unref(reply);
541 dbus_pending_call_unref(call);
544 static int set_network_active(struct connman_network *network,
549 const char *path = connman_network_get_string(network, "Path");
551 DBG("network %p, path %s, active %d", network, path, active);
553 error = set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
554 "Active", DBUS_TYPE_BOOLEAN, &active,
555 set_active_reply, network, NULL);
556 if (active == FALSE && error == -EINPROGRESS)
562 static void set_apn(struct connman_network *network)
564 const char *apn, *path;
566 apn = connman_network_get_string(network, "Cellular.APN");
570 path = connman_network_get_string(network, "Path");
574 DBG("path %s, apn %s", path, apn);
576 set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
577 "AccessPointName", DBUS_TYPE_STRING, &apn,
581 static int network_connect(struct connman_network *network)
583 if (connman_network_get_index(network) >= 0)
586 return set_network_active(network, TRUE);
589 static int network_disconnect(struct connman_network *network)
591 if (connman_network_get_index(network) < 0)
594 return set_network_active(network, FALSE);
597 static void network_remove(struct connman_network *network)
601 DBG("network %p", network);
603 reg_watch = GPOINTER_TO_UINT(connman_network_get_data(network));
604 g_dbus_remove_watch(connection, reg_watch);
607 static int network_setup(struct connman_network *network, const char *key)
611 if (g_strcmp0(key, "Cellular.APN") == 0)
617 static struct connman_network_driver network_driver = {
619 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
620 .probe = network_probe,
621 .remove = network_remove,
622 .connect = network_connect,
623 .disconnect = network_disconnect,
624 .setup = network_setup,
627 static void add_network(struct connman_device *device, const char *path)
629 struct connman_network *network;
634 DBG("device %p path %s", device, path);
636 ident = get_ident(path);
638 network = connman_device_get_network(device, ident);
642 network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
646 if (connman_network_set_string(network, "Path", path) != 0)
649 connman_network_set_available(network, TRUE);
650 connman_network_set_index(network, -1);
652 mcc = connman_device_get_string(device, "MCC");
654 connman_network_set_string(network, "Cellular.MCC", mcc);
656 mnc = connman_device_get_string(device, "MNC");
658 connman_network_set_string(network, "Cellular.MNC", mnc);
660 if (connman_device_add_network(device, network) == 0)
664 connman_network_unref(network);
667 static void add_networks(struct connman_device *device, DBusMessageIter *array)
669 DBusMessageIter entry;
673 dbus_message_iter_recurse(array, &entry);
675 while (dbus_message_iter_get_arg_type(&entry) ==
676 DBUS_TYPE_OBJECT_PATH) {
679 dbus_message_iter_get_basic(&entry, &path);
681 add_network(device, path);
683 dbus_message_iter_next(&entry);
687 static void create_context_reply(DBusPendingCall *call, void *user_data)
694 dbus_error_init(&error);
696 reply = dbus_pending_call_steal_reply(call);
698 if (dbus_set_error_from_message(&error, reply)) {
699 connman_error("CreateContext() %s %s",
700 error.name, error.message);
701 dbus_error_free(&error);
704 dbus_message_unref(reply);
706 dbus_pending_call_unref(call);
709 static void add_default_context(DBusMessageIter *array,
710 const char *path, const char *name, const char *type)
712 DBusMessageIter entry;
719 dbus_message_iter_recurse(array, &entry);
721 if (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_OBJECT_PATH)
724 DBG("path %s, name %s, type %s", path, name, type);
726 call_ofono(path, OFONO_GPRS_INTERFACE, CREATE_CONTEXT,
727 create_context_reply, NULL, NULL,
728 DBUS_TYPE_STRING, &name,
729 DBUS_TYPE_STRING, &type,
733 static void check_networks_reply(DBusPendingCall *call, void *user_data)
735 char *path = user_data;
736 struct modem_data *modem;
737 struct connman_device *device;
739 DBusMessageIter array, dict, contexts;
740 dbus_bool_t attached;
742 DBG("path %s", path);
744 modem = g_hash_table_lookup(modem_hash, path);
745 if (modem == NULL || modem->device == NULL)
748 device = modem->device;
750 reply = dbus_pending_call_steal_reply(call);
752 if (dbus_message_iter_init(reply, &array) == FALSE)
755 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
758 dbus_message_iter_recurse(&array, &dict);
760 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
761 DBusMessageIter entry, value;
764 dbus_message_iter_recurse(&dict, &entry);
765 dbus_message_iter_get_basic(&entry, &key);
767 dbus_message_iter_next(&entry);
768 dbus_message_iter_recurse(&entry, &value);
772 if (g_str_equal(key, "Attached") == TRUE) {
773 dbus_message_iter_get_basic(&value, &attached);
774 DBG("Attached %d", attached);
775 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
778 path = connman_device_get_string(device, "Path");
780 add_default_context(&contexts, path,
781 CONTEXT_NAME, CONTEXT_TYPE);
782 } else if (g_str_equal(key, "Powered") == TRUE) {
785 dbus_message_iter_get_basic(&value, &powered);
787 connman_device_set_powered(device, powered);
790 dbus_message_iter_next(&dict);
793 if (attached == TRUE)
794 add_networks(device, &contexts);
797 dbus_message_unref(reply);
799 dbus_pending_call_unref(call);
802 static void check_networks(struct modem_data *modem)
804 char const *path = modem->path;
806 DBG("modem %p path %s", modem, path);
808 call_ofono(path, OFONO_GPRS_INTERFACE, GET_PROPERTIES,
809 check_networks_reply, g_strdup(path), g_free,
813 static void add_device(const char *path, const char *imsi,
814 const char *mcc, const char *mnc)
816 struct modem_data *modem;
817 struct connman_device *device;
819 DBG("path %s imsi %s", path, imsi);
827 modem = g_hash_table_lookup(modem_hash, path);
831 device = connman_device_create(imsi, CONNMAN_DEVICE_TYPE_CELLULAR);
835 connman_device_set_ident(device, imsi);
837 connman_device_set_mode(device, CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE);
839 connman_device_set_string(device, "Path", path);
841 connman_device_set_string(device, "MCC", mcc);
843 connman_device_set_string(device, "MNC", mnc);
845 if (connman_device_register(device) < 0) {
846 connman_device_unref(device);
850 modem->device = device;
852 check_networks(modem);
855 static void sim_properties_reply(DBusPendingCall *call, void *user_data)
857 const char *path = user_data;
861 /* If MobileNetworkCodeLength is not provided, mnc_length is 0 */
862 unsigned char mnc_length = 0;
864 DBusMessageIter array, dict;
866 DBG("path %s", path);
868 reply = dbus_pending_call_steal_reply(call);
870 if (dbus_message_iter_init(reply, &array) == FALSE)
873 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
876 dbus_message_iter_recurse(&array, &dict);
878 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
879 DBusMessageIter entry, value;
882 dbus_message_iter_recurse(&dict, &entry);
883 dbus_message_iter_get_basic(&entry, &key);
885 dbus_message_iter_next(&entry);
886 dbus_message_iter_recurse(&entry, &value);
888 if (g_str_equal(key, "SubscriberIdentity") == TRUE)
889 dbus_message_iter_get_basic(&value, &imsi);
891 * 'MobileNetworkCodeLength' is deprecated since version 0.20, but
892 * keep it here for backward compatibility reasons.
894 else if (g_str_equal(key, "MobileNetworkCodeLength") == TRUE)
895 dbus_message_iter_get_basic(&value,
896 (void *) &mnc_length);
897 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
898 dbus_message_iter_get_basic(&value,
900 else if (g_str_equal(key, "MobileNetworkCode") == TRUE)
901 dbus_message_iter_get_basic(&value,
904 dbus_message_iter_next(&dict);
907 if (mnc_length == 2 || mnc_length == 3) {
908 mcc = g_strndup(imsi, 3);
909 mnc = g_strndup(imsi + 3, mnc_length);
912 add_device(path, imsi, mcc, mnc);
914 if (mnc_length == 2 || mnc_length == 3) {
920 dbus_message_unref(reply);
922 dbus_pending_call_unref(call);
925 static void get_imsi(const char *path)
927 DBG("path %s", path);
929 call_ofono(path, OFONO_SIM_INTERFACE, GET_PROPERTIES,
930 sim_properties_reply, g_strdup(path), g_free,
934 static int modem_change_powered(const char *path, dbus_bool_t powered)
936 DBG("path %s powered %d", path, powered);
938 return set_property(path, OFONO_MODEM_INTERFACE, "Powered",
939 DBUS_TYPE_BOOLEAN, &powered,
943 static struct modem_data *add_modem(const char *path)
945 struct modem_data *modem;
947 DBG("path %s", path);
952 modem = g_hash_table_lookup(modem_hash, path);
954 modem->available = TRUE;
959 modem = g_try_new0(struct modem_data, 1);
963 modem->path = g_strdup(path);
964 modem->device = NULL;
965 modem->available = TRUE;
967 g_hash_table_insert(modem_hash, g_strdup(path), modem);
972 static gboolean modem_has_gprs(DBusMessageIter *array)
974 DBusMessageIter entry;
976 dbus_message_iter_recurse(array, &entry);
978 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
979 const char *interface;
981 dbus_message_iter_get_basic(&entry, &interface);
983 if (g_strcmp0(OFONO_GPRS_INTERFACE, interface) == 0)
986 dbus_message_iter_next(&entry);
992 static void modem_properties_reply(DBusPendingCall *call, void *user_data)
996 DBusMessageIter array, dict;
997 const char *path = user_data;
998 dbus_bool_t powered = FALSE;
999 gboolean has_gprs = FALSE;
1000 struct modem_data *new_modem;
1002 DBG("path %s", path);
1004 reply = dbus_pending_call_steal_reply(call);
1006 if (g_hash_table_lookup(modem_hash, path))
1009 dbus_error_init(&error);
1011 if (dbus_set_error_from_message(&error, reply)) {
1012 connman_error("Modem.GetProperties(%s) %s %s",
1013 path, error.name, error.message);
1014 dbus_error_free(&error);
1018 if (dbus_message_iter_init(reply, &array) == FALSE)
1021 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1024 dbus_message_iter_recurse(&array, &dict);
1026 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1027 DBusMessageIter entry, value;
1030 dbus_message_iter_recurse(&dict, &entry);
1031 dbus_message_iter_get_basic(&entry, &key);
1033 dbus_message_iter_next(&entry);
1034 dbus_message_iter_recurse(&entry, &value);
1036 if (g_str_equal(key, "Powered") == TRUE)
1037 dbus_message_iter_get_basic(&value, &powered);
1038 else if (g_str_equal(key, "Interfaces") == TRUE)
1039 has_gprs = modem_has_gprs(&value);
1041 dbus_message_iter_next(&dict);
1044 new_modem = add_modem(path);
1045 if (new_modem == NULL)
1049 modem_change_powered(path, TRUE);
1055 dbus_message_unref(reply);
1057 dbus_pending_call_unref(call);
1060 static void get_modem_properties(const char *path)
1062 DBG("path %s", path);
1064 call_ofono(path, OFONO_MODEM_INTERFACE, GET_PROPERTIES,
1065 modem_properties_reply, g_strdup(path), g_free,
1069 static void mask_unavailable(gpointer key, gpointer value, gpointer user_data)
1071 struct modem_data *modem = value;
1073 modem->available = FALSE;
1076 static void modems_set_unavailable()
1078 g_hash_table_foreach(modem_hash, mask_unavailable, NULL);
1081 static void cleanup_modem(gpointer key, gpointer value, gpointer user_data)
1083 struct modem_data *modem = value;
1085 if (modem->available == FALSE)
1086 g_hash_table_remove(modem_hash, key);
1089 static void cleanup_modems()
1091 g_hash_table_foreach(modem_hash, cleanup_modem, NULL);
1094 static void update_modems(DBusMessageIter *array)
1096 DBusMessageIter entry;
1100 dbus_message_iter_recurse(array, &entry);
1102 modems_set_unavailable();
1104 while (dbus_message_iter_get_arg_type(&entry) ==
1105 DBUS_TYPE_OBJECT_PATH) {
1107 struct modem_data *modem;
1109 dbus_message_iter_get_basic(&entry, &path);
1111 modem = g_hash_table_lookup(modem_hash, path);
1114 modem->available = TRUE;
1116 get_modem_properties(path);
1118 dbus_message_iter_next(&entry);
1124 static void manager_properties_reply(DBusPendingCall *call, void *user_data)
1128 DBusMessageIter array, dict;
1132 reply = dbus_pending_call_steal_reply(call);
1134 dbus_error_init(&error);
1136 if (dbus_set_error_from_message(&error, reply)) {
1137 connman_error("ModemManager.GetProperties() %s %s",
1138 error.name, error.message);
1139 dbus_error_free(&error);
1143 if (dbus_message_iter_init(reply, &array) == FALSE)
1146 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1149 dbus_message_iter_recurse(&array, &dict);
1151 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1152 DBusMessageIter entry, value;
1155 dbus_message_iter_recurse(&dict, &entry);
1156 dbus_message_iter_get_basic(&entry, &key);
1158 dbus_message_iter_next(&entry);
1159 dbus_message_iter_recurse(&entry, &value);
1161 if (g_str_equal(key, "Modems") == TRUE) {
1162 update_modems(&value);
1166 dbus_message_iter_next(&dict);
1170 dbus_message_unref(reply);
1172 dbus_pending_call_unref(call);
1175 static void modem_remove_device(struct modem_data *modem)
1177 if (modem->device == NULL)
1180 connman_device_unregister(modem->device);
1181 connman_device_unref(modem->device);
1183 modem->device = NULL;
1186 static void remove_modem(gpointer data)
1188 struct modem_data *modem = data;
1190 g_free(modem->path);
1192 modem_remove_device(modem);
1197 static void ofono_connect(DBusConnection *connection, void *user_data)
1199 DBG("connection %p", connection);
1201 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1202 g_free, remove_modem);
1204 call_ofono("/", OFONO_MANAGER_INTERFACE, GET_PROPERTIES,
1205 manager_properties_reply, NULL, NULL,
1209 static void ofono_disconnect(DBusConnection *connection, void *user_data)
1211 DBG("connection %p", connection);
1213 if (modem_hash == NULL)
1216 g_hash_table_destroy(modem_hash);
1221 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1224 const char *path = dbus_message_get_path(message);
1225 struct modem_data *modem;
1226 DBusMessageIter iter, value;
1229 DBG("path %s", path);
1231 modem = g_hash_table_lookup(modem_hash, path);
1235 if (dbus_message_iter_init(message, &iter) == FALSE)
1238 dbus_message_iter_get_basic(&iter, &key);
1240 dbus_message_iter_next(&iter);
1241 dbus_message_iter_recurse(&iter, &value);
1243 if (g_str_equal(key, "Powered") == TRUE) {
1244 dbus_bool_t powered;
1246 dbus_message_iter_get_basic(&value, &powered);
1247 if (powered == TRUE)
1250 modem_remove_device(modem);
1251 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1252 if (modem_has_gprs(&value) == TRUE) {
1253 if (modem->device == NULL)
1254 get_imsi(modem->path);
1255 } else if (modem->device != NULL)
1256 modem_remove_device(modem);
1262 static gboolean gprs_changed(DBusConnection *connection, DBusMessage *message,
1265 const char *path = dbus_message_get_path(message);
1266 struct modem_data *modem;
1267 DBusMessageIter iter, value;
1270 DBG("path %s", path);
1272 modem = g_hash_table_lookup(modem_hash, path);
1276 if (dbus_message_iter_init(message, &iter) == FALSE)
1279 dbus_message_iter_get_basic(&iter, &key);
1281 dbus_message_iter_next(&iter);
1282 dbus_message_iter_recurse(&iter, &value);
1284 if (g_str_equal(key, "Attached") == TRUE) {
1285 dbus_bool_t attached;
1287 dbus_message_iter_get_basic(&value, &attached);
1289 DBG("Attached %d", attached);
1291 if (attached == TRUE)
1292 check_networks(modem);
1293 else if (modem->device != NULL)
1294 connman_device_remove_all_networks(modem->device);
1296 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
1297 check_networks(modem);
1298 } else if (g_str_equal(key, "Powered") == TRUE) {
1299 dbus_bool_t powered;
1301 if (modem->device == NULL)
1304 dbus_message_iter_get_basic(&value, &powered);
1305 connman_device_set_powered(modem->device, powered);
1311 static gboolean manager_changed(DBusConnection *connection,
1312 DBusMessage *message, void *user_data)
1314 const char *path = dbus_message_get_path(message);
1315 DBusMessageIter iter, value;
1318 DBG("path %s", path);
1320 if (dbus_message_iter_init(message, &iter) == FALSE)
1323 dbus_message_iter_get_basic(&iter, &key);
1325 dbus_message_iter_next(&iter);
1326 dbus_message_iter_recurse(&iter, &value);
1328 if (g_str_equal(key, "Modems") == TRUE)
1329 update_modems(&value);
1334 static void get_dns(DBusMessageIter *array, struct connman_element *parent)
1336 DBusMessageIter entry;
1337 gchar *nameserver = NULL, *nameserver_old = NULL;
1341 dbus_message_iter_recurse(array, &entry);
1343 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1346 dbus_message_iter_get_basic(&entry, &dns);
1350 if (nameserver == NULL) {
1352 nameserver = g_strdup(dns);
1355 nameserver_old = nameserver;
1356 nameserver = g_strdup_printf("%s %s",
1357 nameserver_old, dns);
1358 g_free(nameserver_old);
1361 dbus_message_iter_next(&entry);
1364 parent->ipv4.nameserver = nameserver;
1367 static void update_settings(DBusMessageIter *array,
1368 struct connman_network *network)
1370 struct connman_element *parent = connman_network_get_element(network);
1371 DBusMessageIter dict;
1372 const char *interface = NULL;
1374 DBG("network %p", network);
1376 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
1379 dbus_message_iter_recurse(array, &dict);
1381 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1382 DBusMessageIter entry, value;
1385 dbus_message_iter_recurse(&dict, &entry);
1386 dbus_message_iter_get_basic(&entry, &key);
1390 dbus_message_iter_next(&entry);
1391 dbus_message_iter_recurse(&entry, &value);
1393 if (g_str_equal(key, "Interface") == TRUE) {
1396 dbus_message_iter_get_basic(&value, &interface);
1398 DBG("interface %s", interface);
1400 index = connman_inet_ifindex(interface);
1402 connman_network_set_index(network, index);
1404 connman_error("Can not find interface %s",
1408 } else if (g_str_equal(key, "Method") == TRUE) {
1411 dbus_message_iter_get_basic(&value, &method);
1412 if (g_strcmp0(method, "static") == 0) {
1414 parent->ipv4.method =
1415 CONNMAN_IPCONFIG_METHOD_FIXED;
1416 } else if (g_strcmp0(method, "dhcp") == 0) {
1418 parent->ipv4.method =
1419 CONNMAN_IPCONFIG_METHOD_DHCP;
1422 } else if (g_str_equal(key, "Address") == TRUE) {
1423 const char *address;
1425 dbus_message_iter_get_basic(&value, &address);
1427 DBG("address %s", address);
1429 parent->ipv4.address = g_strdup(address);
1430 } else if (g_str_equal(key, "Netmask") == TRUE) {
1431 const char *netmask;
1433 dbus_message_iter_get_basic(&value, &netmask);
1435 DBG("netmask %s", netmask);
1437 parent->ipv4.netmask = g_strdup(netmask);
1438 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
1440 get_dns(&value, parent);
1441 } else if (g_str_equal(key, "Gateway") == TRUE) {
1442 const char *gateway;
1444 dbus_message_iter_get_basic(&value, &gateway);
1446 DBG("gateway %s", gateway);
1448 parent->ipv4.gateway = g_strdup(gateway);
1451 dbus_message_iter_next(&dict);
1454 /* deactive, oFono send NULL inteface before deactive signal */
1455 if (interface == NULL)
1456 connman_network_set_index(network, -1);
1459 static void cleanup_ipconfig(struct connman_network *network)
1461 struct connman_element *parent = connman_network_get_element(network);
1463 g_free(parent->ipv4.address);
1464 parent->ipv4.address = NULL;
1466 g_free(parent->ipv4.netmask);
1467 parent->ipv4.netmask = NULL;
1469 g_free(parent->ipv4.nameserver);
1470 parent->ipv4.nameserver = NULL;
1472 g_free(parent->ipv4.gateway);
1473 parent->ipv4.gateway = NULL;
1475 parent->ipv4.method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1479 static void set_connected(struct connman_network *network,
1480 connman_bool_t connected)
1482 struct connman_element *parent = connman_network_get_element(network);
1483 enum connman_ipconfig_method method = parent->ipv4.method;
1486 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1487 case CONNMAN_IPCONFIG_METHOD_OFF:
1488 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1491 case CONNMAN_IPCONFIG_METHOD_FIXED:
1492 connman_network_set_method(network, method);
1494 if (connected == FALSE)
1495 cleanup_ipconfig(network);
1497 connman_network_set_connected(network, connected);
1500 case CONNMAN_IPCONFIG_METHOD_DHCP:
1501 connman_network_set_method(network, method);
1503 connman_network_set_connected(network, connected);
1508 static gboolean pri_context_changed(DBusConnection *connection,
1509 DBusMessage *message, void *user_data)
1511 const char *path = dbus_message_get_path(message);
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 if (dbus_message_iter_init(message, &iter) == FALSE)
1528 dbus_message_iter_get_basic(&iter, &key);
1530 dbus_message_iter_next(&iter);
1531 dbus_message_iter_recurse(&iter, &value);
1533 if (g_str_equal(key, "Settings") == TRUE)
1534 update_settings(&value, pending_network);
1535 else if (g_str_equal(key, "Active") == TRUE) {
1538 dbus_message_iter_get_basic(&value, &active);
1540 set_connected(pending_network, active);
1542 pending_network = NULL;
1549 static guint gprs_watch;
1550 static guint modem_watch;
1551 static guint manager_watch;
1552 static guint context_watch;
1554 static int ofono_init(void)
1558 connection = connman_dbus_get_connection();
1559 if (connection == NULL)
1562 watch = g_dbus_add_service_watch(connection, OFONO_SERVICE,
1563 ofono_connect, ofono_disconnect, NULL, NULL);
1565 gprs_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1566 OFONO_GPRS_INTERFACE,
1571 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1572 OFONO_MODEM_INTERFACE,
1577 manager_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1578 OFONO_MANAGER_INTERFACE,
1583 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1584 OFONO_PRI_CONTEXT_INTERFACE,
1586 pri_context_changed,
1589 if (watch == 0 || gprs_watch == 0 || modem_watch == 0 ||
1590 manager_watch == 0 || context_watch == 0) {
1595 err = connman_network_driver_register(&network_driver);
1599 err = connman_device_driver_register(&modem_driver);
1601 connman_network_driver_unregister(&network_driver);
1608 g_dbus_remove_watch(connection, watch);
1609 g_dbus_remove_watch(connection, gprs_watch);
1610 g_dbus_remove_watch(connection, modem_watch);
1611 g_dbus_remove_watch(connection, manager_watch);
1612 g_dbus_remove_watch(connection, context_watch);
1614 dbus_connection_unref(connection);
1619 static void ofono_exit(void)
1621 g_dbus_remove_watch(connection, watch);
1622 g_dbus_remove_watch(connection, gprs_watch);
1623 g_dbus_remove_watch(connection, modem_watch);
1624 g_dbus_remove_watch(connection, manager_watch);
1625 g_dbus_remove_watch(connection, context_watch);
1627 ofono_disconnect(connection, NULL);
1629 connman_device_driver_unregister(&modem_driver);
1630 connman_network_driver_unregister(&network_driver);
1632 dbus_connection_unref(connection);
1635 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
1636 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)