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(
500 struct connman_network *pending_network)
502 struct connman_device *device;
503 struct connman_network *network;
504 const char *identifier;
507 /* Modem may be removed during waiting for active reply */
508 device = connman_network_get_device(pending_network);
509 if (device == NULL) {
510 DBG("Modem is removed");
514 identifier = connman_network_get_identifier(pending_network);
516 ident = g_strdup(identifier);
518 connman_network_unref(pending_network);
520 /* network may be removed during waiting for active reply */
521 network = connman_device_get_network(device, ident);
531 static void set_active_reply(DBusPendingCall *call, void *user_data)
535 struct connman_network *network = user_data;
537 DBG("network %p", network);
539 reply = dbus_pending_call_steal_reply(call);
541 if (pending_network_is_available(network) == FALSE)
544 dbus_error_init(&error);
545 if (dbus_set_error_from_message(&error, reply)) {
546 if (connman_network_get_index(network) < 0)
547 connman_network_set_error(network,
548 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
550 pending_network = NULL;
552 connman_error("SetProperty(Active) %s %s",
553 error.name, error.message);
555 dbus_error_free(&error);
557 pending_network = network;
560 dbus_message_unref(reply);
562 dbus_pending_call_unref(call);
565 static int set_network_active(struct connman_network *network,
570 const char *path = connman_network_get_string(network, "Path");
572 DBG("network %p, path %s, active %d", network, path, active);
574 error = set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
575 "Active", DBUS_TYPE_BOOLEAN, &active,
576 set_active_reply, network, NULL);
577 if (active == FALSE && error == -EINPROGRESS)
583 static void set_apn(struct connman_network *network)
585 const char *apn, *path;
587 apn = connman_network_get_string(network, "Cellular.APN");
591 path = connman_network_get_string(network, "Path");
595 DBG("path %s, apn %s", path, apn);
597 set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
598 "AccessPointName", DBUS_TYPE_STRING, &apn,
602 static int network_connect(struct connman_network *network)
604 if (connman_network_get_index(network) >= 0)
607 return set_network_active(network, TRUE);
610 static int network_disconnect(struct connman_network *network)
612 if (connman_network_get_index(network) < 0)
615 return set_network_active(network, FALSE);
618 static void network_remove(struct connman_network *network)
622 DBG("network %p", network);
624 reg_watch = GPOINTER_TO_UINT(connman_network_get_data(network));
625 g_dbus_remove_watch(connection, reg_watch);
628 static int network_setup(struct connman_network *network, const char *key)
632 if (g_strcmp0(key, "Cellular.APN") == 0)
638 static struct connman_network_driver network_driver = {
640 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
641 .probe = network_probe,
642 .remove = network_remove,
643 .connect = network_connect,
644 .disconnect = network_disconnect,
645 .setup = network_setup,
648 static void add_network(struct connman_device *device, const char *path)
650 struct connman_network *network;
655 DBG("device %p path %s", device, path);
657 ident = get_ident(path);
659 network = connman_device_get_network(device, ident);
663 network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
667 if (connman_network_set_string(network, "Path", path) != 0)
670 connman_network_set_available(network, TRUE);
671 connman_network_set_index(network, -1);
673 mcc = connman_device_get_string(device, "MCC");
675 connman_network_set_string(network, "Cellular.MCC", mcc);
677 mnc = connman_device_get_string(device, "MNC");
679 connman_network_set_string(network, "Cellular.MNC", mnc);
681 if (connman_device_add_network(device, network) == 0)
685 connman_network_unref(network);
688 static void add_networks(struct connman_device *device, DBusMessageIter *array)
690 DBusMessageIter entry;
694 dbus_message_iter_recurse(array, &entry);
696 while (dbus_message_iter_get_arg_type(&entry) ==
697 DBUS_TYPE_OBJECT_PATH) {
700 dbus_message_iter_get_basic(&entry, &path);
702 add_network(device, path);
704 dbus_message_iter_next(&entry);
708 static void create_context_reply(DBusPendingCall *call, void *user_data)
715 dbus_error_init(&error);
717 reply = dbus_pending_call_steal_reply(call);
719 if (dbus_set_error_from_message(&error, reply)) {
720 connman_error("CreateContext() %s %s",
721 error.name, error.message);
722 dbus_error_free(&error);
725 dbus_message_unref(reply);
727 dbus_pending_call_unref(call);
730 static void add_default_context(DBusMessageIter *array,
731 const char *path, const char *name, const char *type)
733 DBusMessageIter entry;
740 dbus_message_iter_recurse(array, &entry);
742 if (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_OBJECT_PATH)
745 DBG("path %s, name %s, type %s", path, name, type);
747 call_ofono(path, OFONO_GPRS_INTERFACE, CREATE_CONTEXT,
748 create_context_reply, NULL, NULL,
749 DBUS_TYPE_STRING, &name,
750 DBUS_TYPE_STRING, &type,
754 static void check_networks_reply(DBusPendingCall *call, void *user_data)
756 char *path = user_data;
757 struct modem_data *modem;
758 struct connman_device *device;
760 DBusMessageIter array, dict, contexts;
761 dbus_bool_t attached;
763 DBG("path %s", path);
765 modem = g_hash_table_lookup(modem_hash, path);
766 if (modem == NULL || modem->device == NULL)
769 device = modem->device;
771 reply = dbus_pending_call_steal_reply(call);
773 if (dbus_message_iter_init(reply, &array) == FALSE)
776 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
779 dbus_message_iter_recurse(&array, &dict);
781 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
782 DBusMessageIter entry, value;
785 dbus_message_iter_recurse(&dict, &entry);
786 dbus_message_iter_get_basic(&entry, &key);
788 dbus_message_iter_next(&entry);
789 dbus_message_iter_recurse(&entry, &value);
793 if (g_str_equal(key, "Attached") == TRUE) {
794 dbus_message_iter_get_basic(&value, &attached);
795 DBG("Attached %d", attached);
796 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
799 path = connman_device_get_string(device, "Path");
801 add_default_context(&contexts, path,
802 CONTEXT_NAME, CONTEXT_TYPE);
803 } else if (g_str_equal(key, "Powered") == TRUE) {
806 dbus_message_iter_get_basic(&value, &powered);
808 connman_device_set_powered(device, powered);
811 dbus_message_iter_next(&dict);
814 if (attached == TRUE)
815 add_networks(device, &contexts);
818 dbus_message_unref(reply);
820 dbus_pending_call_unref(call);
823 static void check_networks(struct modem_data *modem)
825 char const *path = modem->path;
827 DBG("modem %p path %s", modem, path);
829 call_ofono(path, OFONO_GPRS_INTERFACE, GET_PROPERTIES,
830 check_networks_reply, g_strdup(path), g_free,
834 static void add_device(const char *path, const char *imsi,
835 const char *mcc, const char *mnc)
837 struct modem_data *modem;
838 struct connman_device *device;
840 DBG("path %s imsi %s", path, imsi);
848 modem = g_hash_table_lookup(modem_hash, path);
852 device = connman_device_create(imsi, CONNMAN_DEVICE_TYPE_CELLULAR);
856 connman_device_set_ident(device, imsi);
858 connman_device_set_mode(device, CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE);
860 connman_device_set_string(device, "Path", path);
862 connman_device_set_string(device, "MCC", mcc);
864 connman_device_set_string(device, "MNC", mnc);
866 if (connman_device_register(device) < 0) {
867 connman_device_unref(device);
871 modem->device = device;
873 check_networks(modem);
876 static void sim_properties_reply(DBusPendingCall *call, void *user_data)
878 const char *path = user_data;
882 /* If MobileNetworkCodeLength is not provided, mnc_length is 0 */
883 unsigned char mnc_length = 0;
885 DBusMessageIter array, dict;
887 DBG("path %s", path);
889 reply = dbus_pending_call_steal_reply(call);
891 if (dbus_message_iter_init(reply, &array) == FALSE)
894 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
897 dbus_message_iter_recurse(&array, &dict);
899 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
900 DBusMessageIter entry, value;
903 dbus_message_iter_recurse(&dict, &entry);
904 dbus_message_iter_get_basic(&entry, &key);
906 dbus_message_iter_next(&entry);
907 dbus_message_iter_recurse(&entry, &value);
909 if (g_str_equal(key, "SubscriberIdentity") == TRUE)
910 dbus_message_iter_get_basic(&value, &imsi);
912 * 'MobileNetworkCodeLength' is deprecated since version 0.20, but
913 * keep it here for backward compatibility reasons.
915 else if (g_str_equal(key, "MobileNetworkCodeLength") == TRUE)
916 dbus_message_iter_get_basic(&value,
917 (void *) &mnc_length);
918 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
919 dbus_message_iter_get_basic(&value,
921 else if (g_str_equal(key, "MobileNetworkCode") == TRUE)
922 dbus_message_iter_get_basic(&value,
925 dbus_message_iter_next(&dict);
928 if (mnc_length == 2 || mnc_length == 3) {
929 mcc = g_strndup(imsi, 3);
930 mnc = g_strndup(imsi + 3, mnc_length);
933 add_device(path, imsi, mcc, mnc);
935 if (mnc_length == 2 || mnc_length == 3) {
941 dbus_message_unref(reply);
943 dbus_pending_call_unref(call);
946 static void get_imsi(const char *path)
948 DBG("path %s", path);
950 call_ofono(path, OFONO_SIM_INTERFACE, GET_PROPERTIES,
951 sim_properties_reply, g_strdup(path), g_free,
955 static int modem_change_powered(const char *path, dbus_bool_t powered)
957 DBG("path %s powered %d", path, powered);
959 return set_property(path, OFONO_MODEM_INTERFACE, "Powered",
960 DBUS_TYPE_BOOLEAN, &powered,
964 static struct modem_data *add_modem(const char *path)
966 struct modem_data *modem;
968 DBG("path %s", path);
973 modem = g_hash_table_lookup(modem_hash, path);
975 modem->available = TRUE;
980 modem = g_try_new0(struct modem_data, 1);
984 modem->path = g_strdup(path);
985 modem->device = NULL;
986 modem->available = TRUE;
988 g_hash_table_insert(modem_hash, g_strdup(path), modem);
993 static gboolean modem_has_gprs(DBusMessageIter *array)
995 DBusMessageIter entry;
997 dbus_message_iter_recurse(array, &entry);
999 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1000 const char *interface;
1002 dbus_message_iter_get_basic(&entry, &interface);
1004 if (g_strcmp0(OFONO_GPRS_INTERFACE, interface) == 0)
1007 dbus_message_iter_next(&entry);
1013 static void modem_properties_reply(DBusPendingCall *call, void *user_data)
1017 DBusMessageIter array, dict;
1018 const char *path = user_data;
1019 dbus_bool_t powered = FALSE;
1020 gboolean has_gprs = FALSE;
1021 struct modem_data *new_modem;
1023 DBG("path %s", path);
1025 reply = dbus_pending_call_steal_reply(call);
1027 if (g_hash_table_lookup(modem_hash, path))
1030 dbus_error_init(&error);
1032 if (dbus_set_error_from_message(&error, reply)) {
1033 connman_error("Modem.GetProperties(%s) %s %s",
1034 path, error.name, error.message);
1035 dbus_error_free(&error);
1039 if (dbus_message_iter_init(reply, &array) == FALSE)
1042 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1045 dbus_message_iter_recurse(&array, &dict);
1047 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1048 DBusMessageIter entry, value;
1051 dbus_message_iter_recurse(&dict, &entry);
1052 dbus_message_iter_get_basic(&entry, &key);
1054 dbus_message_iter_next(&entry);
1055 dbus_message_iter_recurse(&entry, &value);
1057 if (g_str_equal(key, "Powered") == TRUE)
1058 dbus_message_iter_get_basic(&value, &powered);
1059 else if (g_str_equal(key, "Interfaces") == TRUE)
1060 has_gprs = modem_has_gprs(&value);
1062 dbus_message_iter_next(&dict);
1065 new_modem = add_modem(path);
1066 if (new_modem == NULL)
1070 modem_change_powered(path, TRUE);
1076 dbus_message_unref(reply);
1078 dbus_pending_call_unref(call);
1081 static void get_modem_properties(const char *path)
1083 DBG("path %s", path);
1085 call_ofono(path, OFONO_MODEM_INTERFACE, GET_PROPERTIES,
1086 modem_properties_reply, g_strdup(path), g_free,
1090 static void mask_unavailable(gpointer key, gpointer value, gpointer user_data)
1092 struct modem_data *modem = value;
1094 modem->available = FALSE;
1097 static void modems_set_unavailable()
1099 g_hash_table_foreach(modem_hash, mask_unavailable, NULL);
1102 static void cleanup_modem(gpointer key, gpointer value, gpointer user_data)
1104 struct modem_data *modem = value;
1106 if (modem->available == FALSE)
1107 g_hash_table_remove(modem_hash, key);
1110 static void cleanup_modems()
1112 g_hash_table_foreach(modem_hash, cleanup_modem, NULL);
1115 static void update_modems(DBusMessageIter *array)
1117 DBusMessageIter entry;
1121 dbus_message_iter_recurse(array, &entry);
1123 modems_set_unavailable();
1125 while (dbus_message_iter_get_arg_type(&entry) ==
1126 DBUS_TYPE_OBJECT_PATH) {
1128 struct modem_data *modem;
1130 dbus_message_iter_get_basic(&entry, &path);
1132 modem = g_hash_table_lookup(modem_hash, path);
1135 modem->available = TRUE;
1137 get_modem_properties(path);
1139 dbus_message_iter_next(&entry);
1145 static void manager_properties_reply(DBusPendingCall *call, void *user_data)
1149 DBusMessageIter array, dict;
1153 reply = dbus_pending_call_steal_reply(call);
1155 dbus_error_init(&error);
1157 if (dbus_set_error_from_message(&error, reply)) {
1158 connman_error("ModemManager.GetProperties() %s %s",
1159 error.name, error.message);
1160 dbus_error_free(&error);
1164 if (dbus_message_iter_init(reply, &array) == FALSE)
1167 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1170 dbus_message_iter_recurse(&array, &dict);
1172 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1173 DBusMessageIter entry, value;
1176 dbus_message_iter_recurse(&dict, &entry);
1177 dbus_message_iter_get_basic(&entry, &key);
1179 dbus_message_iter_next(&entry);
1180 dbus_message_iter_recurse(&entry, &value);
1182 if (g_str_equal(key, "Modems") == TRUE) {
1183 update_modems(&value);
1187 dbus_message_iter_next(&dict);
1191 dbus_message_unref(reply);
1193 dbus_pending_call_unref(call);
1196 static void modem_remove_device(struct modem_data *modem)
1198 if (modem->device == NULL)
1201 connman_device_unregister(modem->device);
1202 connman_device_unref(modem->device);
1204 modem->device = NULL;
1207 static void remove_modem(gpointer data)
1209 struct modem_data *modem = data;
1211 g_free(modem->path);
1213 modem_remove_device(modem);
1218 static void ofono_connect(DBusConnection *connection, void *user_data)
1220 DBG("connection %p", connection);
1222 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1223 g_free, remove_modem);
1225 call_ofono("/", OFONO_MANAGER_INTERFACE, GET_PROPERTIES,
1226 manager_properties_reply, NULL, NULL,
1230 static void ofono_disconnect(DBusConnection *connection, void *user_data)
1232 DBG("connection %p", connection);
1234 if (modem_hash == NULL)
1237 g_hash_table_destroy(modem_hash);
1242 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1245 const char *path = dbus_message_get_path(message);
1246 struct modem_data *modem;
1247 DBusMessageIter iter, value;
1250 DBG("path %s", path);
1252 modem = g_hash_table_lookup(modem_hash, path);
1256 if (dbus_message_iter_init(message, &iter) == FALSE)
1259 dbus_message_iter_get_basic(&iter, &key);
1261 dbus_message_iter_next(&iter);
1262 dbus_message_iter_recurse(&iter, &value);
1264 if (g_str_equal(key, "Powered") == TRUE) {
1265 dbus_bool_t powered;
1267 dbus_message_iter_get_basic(&value, &powered);
1268 if (powered == TRUE)
1271 modem_remove_device(modem);
1272 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1273 if (modem_has_gprs(&value) == TRUE) {
1274 if (modem->device == NULL)
1275 get_imsi(modem->path);
1276 } else if (modem->device != NULL)
1277 modem_remove_device(modem);
1283 static gboolean gprs_changed(DBusConnection *connection, DBusMessage *message,
1286 const char *path = dbus_message_get_path(message);
1287 struct modem_data *modem;
1288 DBusMessageIter iter, value;
1291 DBG("path %s", path);
1293 modem = g_hash_table_lookup(modem_hash, path);
1297 if (dbus_message_iter_init(message, &iter) == FALSE)
1300 dbus_message_iter_get_basic(&iter, &key);
1302 dbus_message_iter_next(&iter);
1303 dbus_message_iter_recurse(&iter, &value);
1305 if (g_str_equal(key, "Attached") == TRUE) {
1306 dbus_bool_t attached;
1308 dbus_message_iter_get_basic(&value, &attached);
1310 DBG("Attached %d", attached);
1312 if (attached == TRUE)
1313 check_networks(modem);
1314 else if (modem->device != NULL)
1315 connman_device_remove_all_networks(modem->device);
1317 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
1318 check_networks(modem);
1319 } else if (g_str_equal(key, "Powered") == TRUE) {
1320 dbus_bool_t powered;
1322 if (modem->device == NULL)
1325 dbus_message_iter_get_basic(&value, &powered);
1326 connman_device_set_powered(modem->device, powered);
1332 static gboolean manager_changed(DBusConnection *connection,
1333 DBusMessage *message, void *user_data)
1335 const char *path = dbus_message_get_path(message);
1336 DBusMessageIter iter, value;
1339 DBG("path %s", path);
1341 if (dbus_message_iter_init(message, &iter) == FALSE)
1344 dbus_message_iter_get_basic(&iter, &key);
1346 dbus_message_iter_next(&iter);
1347 dbus_message_iter_recurse(&iter, &value);
1349 if (g_str_equal(key, "Modems") == TRUE)
1350 update_modems(&value);
1355 static void get_dns(DBusMessageIter *array, struct connman_element *parent)
1357 DBusMessageIter entry;
1358 gchar *nameserver = NULL, *nameserver_old = NULL;
1362 dbus_message_iter_recurse(array, &entry);
1364 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1367 dbus_message_iter_get_basic(&entry, &dns);
1371 if (nameserver == NULL) {
1373 nameserver = g_strdup(dns);
1376 nameserver_old = nameserver;
1377 nameserver = g_strdup_printf("%s %s",
1378 nameserver_old, dns);
1379 g_free(nameserver_old);
1382 dbus_message_iter_next(&entry);
1385 parent->ipv4.nameserver = nameserver;
1388 static void update_settings(DBusMessageIter *array,
1389 struct connman_element *parent)
1391 DBusMessageIter dict;
1392 const char *interface = NULL;
1396 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
1399 dbus_message_iter_recurse(array, &dict);
1401 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1402 DBusMessageIter entry, value;
1405 dbus_message_iter_recurse(&dict, &entry);
1406 dbus_message_iter_get_basic(&entry, &key);
1408 dbus_message_iter_next(&entry);
1409 dbus_message_iter_recurse(&entry, &value);
1411 if (g_str_equal(key, "Interface") == TRUE) {
1414 dbus_message_iter_get_basic(&value, &interface);
1416 DBG("interface %s", interface);
1418 index = connman_inet_ifindex(interface);
1420 connman_network_set_index(
1421 pending_network, index);
1423 connman_error("Can not find interface %s",
1427 } else if (g_str_equal(key, "Method") == TRUE) {
1430 dbus_message_iter_get_basic(&value, &method);
1431 if (g_strcmp0(method, "static") == 0) {
1433 parent->ipv4.method =
1434 CONNMAN_IPCONFIG_METHOD_FIXED;
1435 } else if (g_strcmp0(method, "dhcp") == 0) {
1437 parent->ipv4.method =
1438 CONNMAN_IPCONFIG_METHOD_DHCP;
1441 } else if (g_str_equal(key, "Address") == TRUE) {
1442 const char *address;
1444 dbus_message_iter_get_basic(&value, &address);
1446 DBG("address %s", address);
1448 parent->ipv4.address = g_strdup(address);
1449 } else if (g_str_equal(key, "Netmask") == TRUE) {
1450 const char *netmask;
1452 dbus_message_iter_get_basic(&value, &netmask);
1454 DBG("netmask %s", netmask);
1456 parent->ipv4.netmask = g_strdup(netmask);
1457 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
1459 get_dns(&value, parent);
1460 } else if (g_str_equal(key, "Gateway") == TRUE) {
1461 const char *gateway;
1463 dbus_message_iter_get_basic(&value, &gateway);
1465 DBG("gateway %s", gateway);
1467 parent->ipv4.gateway = g_strdup(gateway);
1470 dbus_message_iter_next(&dict);
1473 /* deactive, oFono send NULL inteface before deactive signal */
1474 if (interface == NULL)
1475 connman_network_set_index(pending_network, -1);
1478 static void cleanup_ipconfig(struct connman_element *parent)
1480 g_free(parent->ipv4.address);
1481 parent->ipv4.address = NULL;
1483 g_free(parent->ipv4.netmask);
1484 parent->ipv4.netmask = NULL;
1486 g_free(parent->ipv4.nameserver);
1487 parent->ipv4.nameserver = NULL;
1489 g_free(parent->ipv4.gateway);
1490 parent->ipv4.gateway = NULL;
1492 parent->ipv4.method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1495 static int static_network_set_connected(
1496 struct connman_network *pending_network,
1497 struct connman_element *parent,
1498 connman_bool_t connected)
1500 if (connected == FALSE)
1501 cleanup_ipconfig(parent);
1503 connman_network_set_connected(pending_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 struct connman_element *parent;
1513 const char *pending_path;
1514 DBusMessageIter iter, value;
1517 DBG("pending_network %p, path %s", pending_network, path);
1519 if (pending_network == NULL)
1522 pending_path = connman_network_get_string(pending_network, "Path");
1523 if (g_strcmp0(pending_path, path) != 0)
1526 parent = connman_network_get_element(pending_network);
1528 if (dbus_message_iter_init(message, &iter) == FALSE)
1531 dbus_message_iter_get_basic(&iter, &key);
1533 dbus_message_iter_next(&iter);
1534 dbus_message_iter_recurse(&iter, &value);
1536 if (g_str_equal(key, "Settings") == TRUE) {
1538 update_settings(&value, parent);
1539 } else if (g_str_equal(key, "Active") == TRUE) {
1542 dbus_message_iter_get_basic(&value, &active);
1544 switch (parent->ipv4.method) {
1545 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1546 case CONNMAN_IPCONFIG_METHOD_OFF:
1547 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1549 case CONNMAN_IPCONFIG_METHOD_FIXED:
1550 connman_network_set_method(pending_network,
1551 CONNMAN_IPCONFIG_METHOD_FIXED);
1553 if (static_network_set_connected(
1554 pending_network, parent, active) < 0)
1555 set_network_active(pending_network, FALSE);
1557 case CONNMAN_IPCONFIG_METHOD_DHCP:
1558 connman_network_set_method(pending_network,
1559 CONNMAN_IPCONFIG_METHOD_DHCP);
1560 connman_network_set_connected(pending_network, active);
1564 pending_network = NULL;
1571 static guint gprs_watch;
1572 static guint modem_watch;
1573 static guint manager_watch;
1574 static guint context_watch;
1576 static int ofono_init(void)
1580 connection = connman_dbus_get_connection();
1581 if (connection == NULL)
1584 watch = g_dbus_add_service_watch(connection, OFONO_SERVICE,
1585 ofono_connect, ofono_disconnect, NULL, NULL);
1587 gprs_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1588 OFONO_GPRS_INTERFACE,
1593 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1594 OFONO_MODEM_INTERFACE,
1599 manager_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1600 OFONO_MANAGER_INTERFACE,
1605 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1606 OFONO_PRI_CONTEXT_INTERFACE,
1608 pri_context_changed,
1611 if (watch == 0 || gprs_watch == 0 || modem_watch == 0 ||
1612 manager_watch == 0 || context_watch == 0) {
1617 err = connman_network_driver_register(&network_driver);
1621 err = connman_device_driver_register(&modem_driver);
1623 connman_network_driver_unregister(&network_driver);
1630 g_dbus_remove_watch(connection, watch);
1631 g_dbus_remove_watch(connection, gprs_watch);
1632 g_dbus_remove_watch(connection, modem_watch);
1633 g_dbus_remove_watch(connection, manager_watch);
1634 g_dbus_remove_watch(connection, context_watch);
1636 dbus_connection_unref(connection);
1641 static void ofono_exit(void)
1643 g_dbus_remove_watch(connection, watch);
1644 g_dbus_remove_watch(connection, gprs_watch);
1645 g_dbus_remove_watch(connection, modem_watch);
1646 g_dbus_remove_watch(connection, manager_watch);
1647 g_dbus_remove_watch(connection, context_watch);
1649 ofono_disconnect(connection, NULL);
1651 connman_device_driver_unregister(&modem_driver);
1652 connman_network_driver_unregister(&network_driver);
1654 dbus_connection_unref(connection);
1657 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
1658 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)