5 * Copyright (C) 2007-2013 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 static DBusConnection *connection;
35 static GSList *technology_list = NULL;
38 * List of devices with no technology associated with them either because of
39 * no compiled in support or the driver is not yet loaded.
41 static GSList *techless_device_list = NULL;
42 static GHashTable *rfkill_list;
44 static bool global_offlinemode;
46 struct connman_rfkill {
48 enum connman_service_type type;
53 struct connman_technology {
55 enum connman_service_type type;
63 bool tethering_persistent; /* Tells the save status, needed
64 * as offline mode might set
67 char *tethering_ident;
68 char *tethering_passphrase;
70 bool enable_persistent; /* Save the tech state */
74 DBusMessage *pending_reply;
75 guint pending_timeout;
85 static GSList *driver_list = NULL;
87 static int technology_enabled(struct connman_technology *technology);
88 static int technology_disabled(struct connman_technology *technology);
90 static gint compare_priority(gconstpointer a, gconstpointer b)
92 const struct connman_technology_driver *driver1 = a;
93 const struct connman_technology_driver *driver2 = b;
95 return driver2->priority - driver1->priority;
98 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
100 struct connman_rfkill *rfkill = value;
101 enum connman_service_type type = GPOINTER_TO_INT(user_data);
103 /* Calling _technology_rfkill_add will update the tech. */
104 if (rfkill->type == type)
105 __connman_technology_add_rfkill(rfkill->index, type,
106 rfkill->softblock, rfkill->hardblock);
110 connman_technology_is_tethering_allowed(enum connman_service_type type)
112 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
114 const char *type_str = __connman_service_type2string(type);
121 allowed = connman_setting_get_string_list("TetheringTechnologies");
123 allowed = allowed_default;
125 for (i = 0; allowed[i]; i++) {
126 if (g_strcmp0(allowed[i], type_str) == 0)
133 static const char *get_name(enum connman_service_type type)
136 case CONNMAN_SERVICE_TYPE_UNKNOWN:
137 case CONNMAN_SERVICE_TYPE_SYSTEM:
138 case CONNMAN_SERVICE_TYPE_GPS:
139 case CONNMAN_SERVICE_TYPE_VPN:
141 case CONNMAN_SERVICE_TYPE_GADGET:
143 case CONNMAN_SERVICE_TYPE_ETHERNET:
145 case CONNMAN_SERVICE_TYPE_WIFI:
147 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
149 case CONNMAN_SERVICE_TYPE_CELLULAR:
151 case CONNMAN_SERVICE_TYPE_P2P:
158 static void technology_save(struct connman_technology *technology)
162 const char *name = get_name(technology->type);
164 DBG("technology %p type %d name %s", technology, technology->type,
169 keyfile = __connman_storage_load_global();
171 keyfile = g_key_file_new();
173 identifier = g_strdup_printf("%s", name);
177 g_key_file_set_boolean(keyfile, identifier, "Enable",
178 technology->enable_persistent);
180 g_key_file_set_boolean(keyfile, identifier, "Tethering",
181 technology->tethering_persistent);
183 if (technology->tethering_ident)
184 g_key_file_set_string(keyfile, identifier,
185 "Tethering.Identifier",
186 technology->tethering_ident);
188 if (technology->tethering_passphrase)
189 g_key_file_set_string(keyfile, identifier,
190 "Tethering.Passphrase",
191 technology->tethering_passphrase);
196 __connman_storage_save_global(keyfile);
198 g_key_file_free(keyfile);
203 static void tethering_changed(struct connman_technology *technology)
205 dbus_bool_t tethering = technology->tethering;
207 connman_dbus_property_changed_basic(technology->path,
208 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
209 DBUS_TYPE_BOOLEAN, &tethering);
211 technology_save(technology);
214 void connman_technology_tethering_notify(struct connman_technology *technology,
217 DBG("technology %p enabled %u", technology, enabled);
219 if (technology->tethering == enabled)
222 technology->tethering = enabled;
224 tethering_changed(technology);
227 __connman_tethering_set_enabled();
229 __connman_tethering_set_disabled();
232 static int set_tethering(struct connman_technology *technology,
235 int result = -EOPNOTSUPP;
237 const char *ident, *passphrase, *bridge;
238 GSList *tech_drivers;
240 ident = technology->tethering_ident;
241 passphrase = technology->tethering_passphrase;
243 __sync_synchronize();
244 if (!technology->enabled)
247 bridge = __connman_tethering_get_bridge();
251 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
252 (!ident || !passphrase))
255 for (tech_drivers = technology->driver_list; tech_drivers;
256 tech_drivers = g_slist_next(tech_drivers)) {
257 struct connman_technology_driver *driver = tech_drivers->data;
259 if (!driver || !driver->set_tethering)
262 err = driver->set_tethering(technology, ident, passphrase,
265 if (result == -EINPROGRESS)
268 if (err == -EINPROGRESS || err == 0) {
277 void connman_technology_regdom_notify(struct connman_technology *technology,
283 connman_error("Failed to set regulatory domain");
285 DBG("Regulatory domain set to %s", alpha2);
287 g_free(technology->regdom);
288 technology->regdom = g_strdup(alpha2);
291 static int set_regdom_by_device(struct connman_technology *technology,
296 for (list = technology->device_list; list; list = list->next) {
297 struct connman_device *device = list->data;
299 if (connman_device_set_regdom(device, alpha2) != 0)
306 int connman_technology_set_regdom(const char *alpha2)
308 GSList *list, *tech_drivers;
310 for (list = technology_list; list; list = list->next) {
311 struct connman_technology *technology = list->data;
313 if (set_regdom_by_device(technology, alpha2) != 0) {
315 for (tech_drivers = technology->driver_list;
317 tech_drivers = g_slist_next(tech_drivers)) {
319 struct connman_technology_driver *driver =
322 if (driver->set_regdom)
323 driver->set_regdom(technology, alpha2);
331 static struct connman_technology *technology_find(enum connman_service_type type)
335 DBG("type %d", type);
337 for (list = technology_list; list; list = list->next) {
338 struct connman_technology *technology = list->data;
340 if (technology->type == type)
347 bool connman_technology_get_wifi_tethering(const char **ssid,
350 struct connman_technology *technology;
357 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
361 if (!technology->tethering)
364 *ssid = technology->tethering_ident;
365 *psk = technology->tethering_passphrase;
370 static void free_rfkill(gpointer data)
372 struct connman_rfkill *rfkill = data;
377 static void technology_load(struct connman_technology *technology)
381 GError *error = NULL;
382 bool enable, need_saving = false;
384 DBG("technology %p", technology);
386 keyfile = __connman_storage_load_global();
387 /* Fallback on disabling technology if file not found. */
389 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
390 /* We enable ethernet by default */
391 technology->enable_persistent = true;
393 technology->enable_persistent = false;
397 identifier = g_strdup_printf("%s", get_name(technology->type));
401 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
403 technology->enable_persistent = enable;
405 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
406 technology->enable_persistent = true;
408 technology->enable_persistent = false;
411 g_clear_error(&error);
414 enable = g_key_file_get_boolean(keyfile, identifier,
415 "Tethering", &error);
417 technology->tethering_persistent = enable;
420 g_clear_error(&error);
424 technology_save(technology);
426 technology->tethering_ident = g_key_file_get_string(keyfile,
427 identifier, "Tethering.Identifier", NULL);
429 technology->tethering_passphrase = g_key_file_get_string(keyfile,
430 identifier, "Tethering.Passphrase", NULL);
434 g_key_file_free(keyfile);
439 bool __connman_technology_get_offlinemode(void)
441 return global_offlinemode;
444 static void connman_technology_save_offlinemode(void)
448 keyfile = __connman_storage_load_global();
450 keyfile = g_key_file_new();
452 g_key_file_set_boolean(keyfile, "global",
453 "OfflineMode", global_offlinemode);
455 __connman_storage_save_global(keyfile);
457 g_key_file_free(keyfile);
462 static bool connman_technology_load_offlinemode(void)
465 GError *error = NULL;
468 /* If there is a error, we enable offlinemode */
469 keyfile = __connman_storage_load_global();
473 offlinemode = g_key_file_get_boolean(keyfile, "global",
474 "OfflineMode", &error);
477 g_clear_error(&error);
480 g_key_file_free(keyfile);
485 static void append_properties(DBusMessageIter *iter,
486 struct connman_technology *technology)
488 DBusMessageIter dict;
492 connman_dbus_dict_open(iter, &dict);
494 str = get_name(technology->type);
496 connman_dbus_dict_append_basic(&dict, "Name",
497 DBUS_TYPE_STRING, &str);
499 str = __connman_service_type2string(technology->type);
501 connman_dbus_dict_append_basic(&dict, "Type",
502 DBUS_TYPE_STRING, &str);
504 __sync_synchronize();
505 val = technology->enabled;
506 connman_dbus_dict_append_basic(&dict, "Powered",
510 val = technology->connected;
511 connman_dbus_dict_append_basic(&dict, "Connected",
515 val = technology->tethering;
516 connman_dbus_dict_append_basic(&dict, "Tethering",
520 if (technology->tethering_ident)
521 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
523 &technology->tethering_ident);
525 if (technology->tethering_passphrase)
526 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
528 &technology->tethering_passphrase);
530 connman_dbus_dict_close(iter, &dict);
533 static void technology_added_signal(struct connman_technology *technology)
536 DBusMessageIter iter;
538 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
539 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
543 dbus_message_iter_init_append(signal, &iter);
544 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
546 append_properties(&iter, technology);
548 dbus_connection_send(connection, signal, NULL);
549 dbus_message_unref(signal);
552 static void technology_removed_signal(struct connman_technology *technology)
554 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
555 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
556 DBUS_TYPE_OBJECT_PATH, &technology->path,
560 static DBusMessage *get_properties(DBusConnection *conn,
561 DBusMessage *message, void *user_data)
563 struct connman_technology *technology = user_data;
565 DBusMessageIter iter;
567 reply = dbus_message_new_method_return(message);
571 dbus_message_iter_init_append(reply, &iter);
572 append_properties(&iter, technology);
577 void __connman_technology_list_struct(DBusMessageIter *array)
580 DBusMessageIter entry;
582 for (list = technology_list; list; list = list->next) {
583 struct connman_technology *technology = list->data;
585 if (!technology->path ||
586 (technology->rfkill_driven &&
587 technology->hardblocked))
590 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
592 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
594 append_properties(&entry, technology);
595 dbus_message_iter_close_container(array, &entry);
599 static gboolean technology_pending_reply(gpointer user_data)
601 struct connman_technology *technology = user_data;
604 /* Power request timedout, send ETIMEDOUT. */
605 if (technology->pending_reply) {
606 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
608 g_dbus_send_message(connection, reply);
610 dbus_message_unref(technology->pending_reply);
611 technology->pending_reply = NULL;
612 technology->pending_timeout = 0;
618 static int technology_affect_devices(struct connman_technology *technology,
621 int err = 0, err_dev;
624 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
626 __connman_technology_enabled(technology->type);
628 __connman_technology_disabled(technology->type);
632 for (list = technology->device_list; list; list = list->next) {
633 struct connman_device *device = list->data;
636 err_dev = __connman_device_enable(device);
638 err_dev = __connman_device_disable(device);
640 if (err_dev < 0 && err_dev != -EALREADY)
647 static void powered_changed(struct connman_technology *technology)
651 if (!technology->dbus_registered)
654 if (technology->pending_reply) {
655 g_dbus_send_reply(connection,
656 technology->pending_reply, DBUS_TYPE_INVALID);
657 dbus_message_unref(technology->pending_reply);
658 technology->pending_reply = NULL;
660 g_source_remove(technology->pending_timeout);
661 technology->pending_timeout = 0;
664 __sync_synchronize();
665 enabled = technology->enabled;
666 connman_dbus_property_changed_basic(technology->path,
667 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
668 DBUS_TYPE_BOOLEAN, &enabled);
671 static void enable_tethering(struct connman_technology *technology)
675 if (!connman_setting_get_bool("PersistentTetheringMode"))
678 ret = set_tethering(technology, true);
679 if (ret < 0 && ret != -EALREADY)
680 DBG("Cannot enable tethering yet for %s (%d/%s)",
681 get_name(technology->type),
682 -ret, strerror(-ret));
685 static int technology_enabled(struct connman_technology *technology)
687 __sync_synchronize();
688 if (technology->enabled)
691 technology->enabled = true;
693 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
694 struct connman_technology *p2p;
696 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
697 if (p2p && !p2p->enabled && p2p->enable_persistent)
698 technology_enabled(p2p);
701 if (technology->tethering_persistent)
702 enable_tethering(technology);
704 powered_changed(technology);
709 static int technology_enable(struct connman_technology *technology)
714 DBG("technology %p enable", technology);
716 __sync_synchronize();
718 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
719 struct connman_technology *wifi;
721 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
722 if (wifi && wifi->enabled)
723 return technology_enabled(technology);
727 if (technology->enabled)
730 if (technology->pending_reply)
733 if (connman_setting_get_bool("PersistentTetheringMode") &&
734 technology->tethering)
735 set_tethering(technology, true);
737 if (technology->rfkill_driven)
738 err = __connman_rfkill_block(technology->type, false);
740 err_dev = technology_affect_devices(technology, true);
742 if (!technology->rfkill_driven)
748 static int technology_disabled(struct connman_technology *technology)
750 __sync_synchronize();
751 if (!technology->enabled)
754 technology->enabled = false;
756 powered_changed(technology);
761 static int technology_disable(struct connman_technology *technology)
765 DBG("technology %p disable", technology);
767 __sync_synchronize();
769 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
770 technology->enable_persistent = false;
771 return technology_disabled(technology);
772 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
773 struct connman_technology *p2p;
775 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
776 if (p2p && p2p->enabled) {
777 p2p->enable_persistent = true;
778 technology_disabled(p2p);
782 if (!technology->enabled)
785 if (technology->pending_reply)
788 if (technology->tethering)
789 set_tethering(technology, false);
791 err = technology_affect_devices(technology, false);
793 if (technology->rfkill_driven)
794 err = __connman_rfkill_block(technology->type, true);
799 static DBusMessage *set_powered(struct connman_technology *technology,
800 DBusMessage *msg, bool powered)
802 DBusMessage *reply = NULL;
805 if (technology->rfkill_driven && technology->hardblocked) {
811 err = technology_enable(technology);
813 err = technology_disable(technology);
816 technology->enable_persistent = powered;
817 technology_save(technology);
821 if (err == -EINPROGRESS) {
822 technology->pending_reply = dbus_message_ref(msg);
823 technology->pending_timeout = g_timeout_add_seconds(10,
824 technology_pending_reply, technology);
825 } else if (err == -EALREADY) {
827 reply = __connman_error_already_enabled(msg);
829 reply = __connman_error_already_disabled(msg);
831 reply = __connman_error_failed(msg, -err);
833 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
838 static DBusMessage *set_property(DBusConnection *conn,
839 DBusMessage *msg, void *data)
841 struct connman_technology *technology = data;
842 DBusMessageIter iter, value;
846 DBG("conn %p", conn);
848 if (!dbus_message_iter_init(msg, &iter))
849 return __connman_error_invalid_arguments(msg);
851 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
852 return __connman_error_invalid_arguments(msg);
854 dbus_message_iter_get_basic(&iter, &name);
855 dbus_message_iter_next(&iter);
857 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
858 return __connman_error_invalid_arguments(msg);
860 dbus_message_iter_recurse(&iter, &value);
862 type = dbus_message_iter_get_arg_type(&value);
864 DBG("property %s", name);
866 if (g_str_equal(name, "Tethering")) {
867 dbus_bool_t tethering;
870 if (type != DBUS_TYPE_BOOLEAN)
871 return __connman_error_invalid_arguments(msg);
873 if (!connman_technology_is_tethering_allowed(technology->type)) {
874 DBG("%s tethering not allowed by config file",
875 __connman_service_type2string(technology->type));
876 return __connman_error_not_supported(msg);
879 dbus_message_iter_get_basic(&value, &tethering);
881 if (technology->tethering == tethering) {
883 return __connman_error_already_disabled(msg);
885 return __connman_error_already_enabled(msg);
888 err = set_tethering(technology, tethering);
890 return __connman_error_failed(msg, -err);
892 technology->tethering_persistent = tethering;
894 technology_save(technology);
896 } else if (g_str_equal(name, "TetheringIdentifier")) {
899 dbus_message_iter_get_basic(&value, &str);
901 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
902 return __connman_error_not_supported(msg);
904 if (strlen(str) < 1 || strlen(str) > 32)
905 return __connman_error_invalid_arguments(msg);
907 if (g_strcmp0(technology->tethering_ident, str) != 0) {
908 g_free(technology->tethering_ident);
909 technology->tethering_ident = g_strdup(str);
910 technology_save(technology);
912 connman_dbus_property_changed_basic(technology->path,
913 CONNMAN_TECHNOLOGY_INTERFACE,
914 "TetheringIdentifier",
916 &technology->tethering_ident);
918 } else if (g_str_equal(name, "TetheringPassphrase")) {
921 dbus_message_iter_get_basic(&value, &str);
923 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
924 return __connman_error_not_supported(msg);
926 if (strlen(str) < 8 || strlen(str) > 63)
927 return __connman_error_passphrase_required(msg);
929 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
930 g_free(technology->tethering_passphrase);
931 technology->tethering_passphrase = g_strdup(str);
932 technology_save(technology);
934 connman_dbus_property_changed_basic(technology->path,
935 CONNMAN_TECHNOLOGY_INTERFACE,
936 "TetheringPassphrase",
938 &technology->tethering_passphrase);
940 } else if (g_str_equal(name, "Powered")) {
943 if (type != DBUS_TYPE_BOOLEAN)
944 return __connman_error_invalid_arguments(msg);
946 dbus_message_iter_get_basic(&value, &enable);
948 return set_powered(technology, msg, enable);
950 return __connman_error_invalid_property(msg);
952 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
955 static void reply_scan_pending(struct connman_technology *technology, int err)
959 DBG("technology %p err %d", technology, err);
961 while (technology->scan_pending) {
962 DBusMessage *msg = technology->scan_pending->data;
964 DBG("reply to %s", dbus_message_get_sender(msg));
967 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
969 reply = __connman_error_failed(msg, -err);
970 g_dbus_send_message(connection, reply);
971 dbus_message_unref(msg);
973 technology->scan_pending =
974 g_slist_delete_link(technology->scan_pending,
975 technology->scan_pending);
979 void __connman_technology_scan_started(struct connman_device *device)
981 DBG("device %p", device);
984 void __connman_technology_scan_stopped(struct connman_device *device,
985 enum connman_service_type type)
988 struct connman_technology *technology;
991 technology = technology_find(type);
993 DBG("technology %p device %p", technology, device);
998 for (list = technology->device_list; list; list = list->next) {
999 struct connman_device *other_device = list->data;
1001 if (device == other_device)
1004 if (__connman_device_get_service_type(other_device) != type)
1007 if (connman_device_get_scanning(other_device))
1012 reply_scan_pending(technology, 0);
1015 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1016 int result, const char *alpha2)
1018 bool regdom_set = false;
1019 struct connman_technology *technology;
1020 enum connman_service_type type;
1021 GSList *tech_drivers;
1023 type = __connman_device_get_service_type(device);
1024 technology = technology_find(type);
1031 for (tech_drivers = technology->driver_list;
1033 tech_drivers = g_slist_next(tech_drivers)) {
1034 struct connman_technology_driver *driver =
1037 if (driver->set_regdom) {
1038 driver->set_regdom(technology, alpha2);
1048 connman_technology_regdom_notify(technology, alpha2);
1051 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1053 struct connman_technology *technology = data;
1056 DBG("technology %p request from %s", technology,
1057 dbus_message_get_sender(msg));
1059 dbus_message_ref(msg);
1060 technology->scan_pending =
1061 g_slist_prepend(technology->scan_pending, msg);
1063 err = __connman_device_request_scan(technology->type);
1065 reply_scan_pending(technology, err);
1070 static const GDBusMethodTable technology_methods[] = {
1071 { GDBUS_DEPRECATED_METHOD("GetProperties",
1072 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1074 { GDBUS_ASYNC_METHOD("SetProperty",
1075 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1076 NULL, set_property) },
1077 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1081 static const GDBusSignalTable technology_signals[] = {
1082 { GDBUS_SIGNAL("PropertyChanged",
1083 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1087 static bool technology_dbus_register(struct connman_technology *technology)
1089 if (technology->dbus_registered ||
1090 (technology->rfkill_driven &&
1091 technology->hardblocked))
1094 if (!g_dbus_register_interface(connection, technology->path,
1095 CONNMAN_TECHNOLOGY_INTERFACE,
1096 technology_methods, technology_signals,
1097 NULL, technology, NULL)) {
1098 connman_error("Failed to register %s", technology->path);
1102 technology_added_signal(technology);
1103 technology->dbus_registered = true;
1108 static void technology_dbus_unregister(struct connman_technology *technology)
1110 if (!technology->dbus_registered)
1113 technology_removed_signal(technology);
1114 g_dbus_unregister_interface(connection, technology->path,
1115 CONNMAN_TECHNOLOGY_INTERFACE);
1117 technology->dbus_registered = false;
1120 static void technology_put(struct connman_technology *technology)
1122 DBG("technology %p", technology);
1124 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1127 reply_scan_pending(technology, -EINTR);
1129 while (technology->driver_list) {
1130 struct connman_technology_driver *driver;
1132 driver = technology->driver_list->data;
1135 driver->remove(technology);
1137 technology->driver_list =
1138 g_slist_delete_link(technology->driver_list,
1139 technology->driver_list);
1142 technology_list = g_slist_remove(technology_list, technology);
1144 technology_dbus_unregister(technology);
1146 g_slist_free(technology->device_list);
1148 g_free(technology->path);
1149 g_free(technology->regdom);
1150 g_free(technology->tethering_ident);
1151 g_free(technology->tethering_passphrase);
1155 static struct connman_technology *technology_get(enum connman_service_type type)
1157 GSList *tech_drivers = NULL;
1158 struct connman_technology_driver *driver;
1159 struct connman_technology *technology;
1163 DBG("type %d", type);
1165 str = __connman_service_type2string(type);
1169 technology = technology_find(type);
1171 if (type != CONNMAN_SERVICE_TYPE_P2P)
1172 __sync_fetch_and_add(&technology->refcount, 1);
1176 /* First check if we have a driver for this technology type */
1177 for (list = driver_list; list; list = list->next) {
1178 driver = list->data;
1180 if (driver->type == type) {
1181 DBG("technology %p driver %p", technology, driver);
1182 tech_drivers = g_slist_append(tech_drivers, driver);
1186 if (!tech_drivers) {
1187 DBG("No matching drivers found for %s.",
1188 __connman_service_type2string(type));
1192 technology = g_try_new0(struct connman_technology, 1);
1196 technology->refcount = 1;
1197 technology->type = type;
1198 technology->path = g_strdup_printf("%s/technology/%s",
1201 technology_load(technology);
1202 technology_list = g_slist_prepend(technology_list, technology);
1203 technology->driver_list = tech_drivers;
1205 for (list = tech_drivers; list; list = list->next) {
1206 driver = list->data;
1208 if (driver->probe && driver->probe(technology) < 0)
1209 DBG("Driver probe failed for technology %p",
1213 if (!technology_dbus_register(technology)) {
1214 technology_put(technology);
1218 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1219 struct connman_technology *wifi;
1222 enable = technology->enable_persistent;
1224 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
1226 enable = wifi->enabled;
1228 technology_affect_devices(technology, enable);
1231 DBG("technology %p %s", technology, get_name(technology->type));
1236 int connman_technology_driver_register(struct connman_technology_driver *driver)
1239 struct connman_device *device;
1240 enum connman_service_type type;
1242 for (list = driver_list; list; list = list->next) {
1243 if (list->data == driver)
1247 DBG("Registering %s driver", driver->name);
1249 driver_list = g_slist_insert_sorted(driver_list, driver,
1253 * Check for technology less devices if this driver
1254 * can service any of them.
1256 for (list = techless_device_list; list; list = list->next) {
1257 device = list->data;
1259 type = __connman_device_get_service_type(device);
1260 if (type != driver->type)
1263 techless_device_list = g_slist_remove(techless_device_list,
1266 __connman_technology_add_device(device);
1269 /* Check for orphaned rfkill switches. */
1270 g_hash_table_foreach(rfkill_list, rfkill_check,
1271 GINT_TO_POINTER(driver->type));
1274 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1275 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
1282 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
1284 GSList *list, *tech_drivers;
1285 struct connman_technology *technology;
1286 struct connman_technology_driver *current;
1288 DBG("Unregistering driver %p name %s", driver, driver->name);
1290 for (list = technology_list; list; list = list->next) {
1291 technology = list->data;
1293 for (tech_drivers = technology->driver_list; tech_drivers;
1294 tech_drivers = g_slist_next(tech_drivers)) {
1295 current = tech_drivers->data;
1296 if (driver != current)
1300 driver->remove(technology);
1302 technology->driver_list =
1303 g_slist_remove(technology->driver_list,
1309 driver_list = g_slist_remove(driver_list, driver);
1311 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1312 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1314 technology_put(technology);
1318 void __connman_technology_add_interface(enum connman_service_type type,
1319 int index, const char *ident)
1321 struct connman_technology *technology;
1322 GSList *tech_drivers;
1323 struct connman_technology_driver *driver;
1327 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1328 case CONNMAN_SERVICE_TYPE_SYSTEM:
1330 case CONNMAN_SERVICE_TYPE_ETHERNET:
1331 case CONNMAN_SERVICE_TYPE_WIFI:
1332 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1333 case CONNMAN_SERVICE_TYPE_CELLULAR:
1334 case CONNMAN_SERVICE_TYPE_GPS:
1335 case CONNMAN_SERVICE_TYPE_VPN:
1336 case CONNMAN_SERVICE_TYPE_GADGET:
1337 case CONNMAN_SERVICE_TYPE_P2P:
1341 name = connman_inet_ifname(index);
1342 connman_info("Adding interface %s [ %s ]", name,
1343 __connman_service_type2string(type));
1345 technology = technology_find(type);
1350 for (tech_drivers = technology->driver_list; tech_drivers;
1351 tech_drivers = g_slist_next(tech_drivers)) {
1352 driver = tech_drivers->data;
1354 if (driver->add_interface)
1355 driver->add_interface(technology, index, name, ident);
1359 * At this point we can try to enable tethering automatically as
1360 * now the interfaces are set properly.
1362 if (technology->tethering_persistent)
1363 enable_tethering(technology);
1369 void __connman_technology_remove_interface(enum connman_service_type type,
1370 int index, const char *ident)
1372 struct connman_technology *technology;
1373 GSList *tech_drivers;
1374 struct connman_technology_driver *driver;
1378 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1379 case CONNMAN_SERVICE_TYPE_SYSTEM:
1381 case CONNMAN_SERVICE_TYPE_ETHERNET:
1382 case CONNMAN_SERVICE_TYPE_WIFI:
1383 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1384 case CONNMAN_SERVICE_TYPE_CELLULAR:
1385 case CONNMAN_SERVICE_TYPE_GPS:
1386 case CONNMAN_SERVICE_TYPE_VPN:
1387 case CONNMAN_SERVICE_TYPE_GADGET:
1388 case CONNMAN_SERVICE_TYPE_P2P:
1392 name = connman_inet_ifname(index);
1393 connman_info("Remove interface %s [ %s ]", name,
1394 __connman_service_type2string(type));
1397 technology = technology_find(type);
1402 for (tech_drivers = technology->driver_list; tech_drivers;
1403 tech_drivers = g_slist_next(tech_drivers)) {
1404 driver = tech_drivers->data;
1406 if (driver->remove_interface)
1407 driver->remove_interface(technology, index);
1411 int __connman_technology_add_device(struct connman_device *device)
1413 struct connman_technology *technology;
1414 enum connman_service_type type;
1416 type = __connman_device_get_service_type(device);
1418 DBG("device %p type %s", device, get_name(type));
1420 technology = technology_get(type);
1423 * Since no driver can be found for this device at the moment we
1424 * add it to the techless device list.
1426 techless_device_list = g_slist_prepend(techless_device_list,
1432 __sync_synchronize();
1433 if (technology->rfkill_driven) {
1434 if (technology->enabled)
1435 __connman_device_enable(device);
1437 __connman_device_disable(device);
1442 if (technology->enable_persistent &&
1443 !global_offlinemode) {
1444 int err = __connman_device_enable(device);
1446 * connman_technology_add_device() calls __connman_device_enable()
1447 * but since the device is already enabled, the calls does not
1448 * propagate through to connman_technology_enabled via
1449 * connman_device_set_powered.
1451 if (err == -EALREADY)
1452 __connman_technology_enabled(type);
1454 /* if technology persistent state is offline */
1455 if (!technology->enable_persistent)
1456 __connman_device_disable(device);
1459 technology->device_list = g_slist_prepend(technology->device_list,
1465 int __connman_technology_remove_device(struct connman_device *device)
1467 struct connman_technology *technology;
1468 enum connman_service_type type;
1470 DBG("device %p", device);
1472 type = __connman_device_get_service_type(device);
1474 technology = technology_find(type);
1476 techless_device_list = g_slist_remove(techless_device_list,
1481 technology->device_list = g_slist_remove(technology->device_list,
1484 if (technology->tethering)
1485 set_tethering(technology, false);
1487 technology_put(technology);
1492 int __connman_technology_enabled(enum connman_service_type type)
1494 struct connman_technology *technology;
1496 technology = technology_find(type);
1500 DBG("technology %p type %s rfkill %d enabled %d", technology,
1501 get_name(type), technology->rfkill_driven,
1502 technology->enabled);
1504 if (technology->rfkill_driven) {
1505 if (technology->tethering_persistent)
1506 enable_tethering(technology);
1510 return technology_enabled(technology);
1513 int __connman_technology_disabled(enum connman_service_type type)
1515 struct connman_technology *technology;
1518 technology = technology_find(type);
1522 if (technology->rfkill_driven)
1525 for (list = technology->device_list; list; list = list->next) {
1526 struct connman_device *device = list->data;
1528 if (connman_device_get_powered(device))
1532 return technology_disabled(technology);
1535 int __connman_technology_set_offlinemode(bool offlinemode)
1538 int err = -EINVAL, enabled_tech_count = 0;
1540 if (global_offlinemode == offlinemode)
1543 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1546 * This is a bit tricky. When you set offlinemode, there is no
1547 * way to differentiate between attempting offline mode and
1548 * resuming offlinemode from last saved profile. We need that
1549 * information in rfkill_update, otherwise it falls back on the
1550 * technology's persistent state. Hence we set the offline mode here
1551 * but save it & call the notifier only if its successful.
1554 global_offlinemode = offlinemode;
1556 /* Traverse technology list, enable/disable each technology. */
1557 for (list = technology_list; list; list = list->next) {
1558 struct connman_technology *technology = list->data;
1561 err = technology_disable(technology);
1563 if (technology->hardblocked)
1566 if (technology->enable_persistent) {
1567 err = technology_enable(technology);
1568 enabled_tech_count++;
1573 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1574 (err == -EINVAL && enabled_tech_count == 0)) {
1575 connman_technology_save_offlinemode();
1576 __connman_notifier_offlinemode(offlinemode);
1578 global_offlinemode = connman_technology_load_offlinemode();
1583 void __connman_technology_set_connected(enum connman_service_type type,
1586 struct connman_technology *technology;
1589 technology = technology_find(type);
1593 DBG("technology %p connected %d", technology, connected);
1595 technology->connected = connected;
1598 connman_dbus_property_changed_basic(technology->path,
1599 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1600 DBUS_TYPE_BOOLEAN, &val);
1603 static bool technology_apply_rfkill_change(struct connman_technology *technology,
1608 bool hardblock_changed = false;
1610 GList *start, *list;
1612 DBG("technology %p --> %d/%d vs %d/%d",
1613 technology, softblock, hardblock,
1614 technology->softblocked, technology->hardblocked);
1616 if (technology->hardblocked == hardblock)
1617 goto softblock_change;
1619 if (!(new_rfkill && !hardblock)) {
1620 start = g_hash_table_get_values(rfkill_list);
1622 for (list = start; list; list = list->next) {
1623 struct connman_rfkill *rfkill = list->data;
1625 if (rfkill->type != technology->type)
1628 if (rfkill->hardblock != hardblock)
1636 goto softblock_change;
1638 technology->hardblocked = hardblock;
1639 hardblock_changed = true;
1642 if (!apply && technology->softblocked != softblock)
1646 return technology->hardblocked;
1648 technology->softblocked = softblock;
1650 if (technology->hardblocked ||
1651 technology->softblocked) {
1652 if (technology_disabled(technology) != -EALREADY)
1653 technology_affect_devices(technology, false);
1654 } else if (!technology->hardblocked &&
1655 !technology->softblocked) {
1656 if (technology_enabled(technology) != -EALREADY)
1657 technology_affect_devices(technology, true);
1660 if (hardblock_changed) {
1661 if (technology->hardblocked) {
1662 DBG("%s is switched off.", get_name(technology->type));
1663 technology_dbus_unregister(technology);
1665 DBG("%s is switched on.", get_name(technology->type));
1666 technology_dbus_register(technology);
1668 if (global_offlinemode)
1669 __connman_rfkill_block(technology->type, true);
1673 return technology->hardblocked;
1676 int __connman_technology_add_rfkill(unsigned int index,
1677 enum connman_service_type type,
1681 struct connman_technology *technology;
1682 struct connman_rfkill *rfkill;
1684 DBG("index %u type %d soft %u hard %u", index, type,
1685 softblock, hardblock);
1687 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1691 rfkill = g_try_new0(struct connman_rfkill, 1);
1695 rfkill->index = index;
1696 rfkill->type = type;
1697 rfkill->softblock = softblock;
1698 rfkill->hardblock = hardblock;
1700 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1703 technology = technology_get(type);
1704 /* If there is no driver for this type, ignore it. */
1708 technology->rfkill_driven = true;
1710 /* If hardblocked, there is no need to handle softblocked state */
1711 if (technology_apply_rfkill_change(technology,
1712 softblock, hardblock, true))
1715 if (global_offlinemode)
1719 * Depending on softblocked state we unblock/block according to
1720 * offlinemode and persistente state.
1722 if (technology->softblocked &&
1723 technology->enable_persistent)
1724 return __connman_rfkill_block(type, false);
1725 else if (!technology->softblocked &&
1726 !technology->enable_persistent)
1727 return __connman_rfkill_block(type, true);
1732 int __connman_technology_update_rfkill(unsigned int index,
1733 enum connman_service_type type,
1737 struct connman_technology *technology;
1738 struct connman_rfkill *rfkill;
1740 DBG("index %u soft %u hard %u", index, softblock, hardblock);
1742 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1746 if (rfkill->softblock == softblock &&
1747 rfkill->hardblock == hardblock)
1750 rfkill->softblock = softblock;
1751 rfkill->hardblock = hardblock;
1753 technology = technology_find(type);
1754 /* If there is no driver for this type, ignore it. */
1758 technology_apply_rfkill_change(technology, softblock, hardblock,
1761 if (technology->hardblocked)
1762 DBG("%s hardblocked", get_name(technology->type));
1764 DBG("%s is%s softblocked", get_name(technology->type),
1765 technology->softblocked ? "" : " not");
1770 int __connman_technology_remove_rfkill(unsigned int index,
1771 enum connman_service_type type)
1773 struct connman_technology *technology;
1774 struct connman_rfkill *rfkill;
1776 DBG("index %u", index);
1778 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1782 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
1784 technology = technology_find(type);
1788 technology_apply_rfkill_change(technology,
1789 technology->softblocked, !technology->hardblocked, false);
1791 technology_put(technology);
1796 int __connman_technology_init(void)
1800 connection = connman_dbus_get_connection();
1802 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1805 global_offlinemode = connman_technology_load_offlinemode();
1807 /* This will create settings file if it is missing */
1808 connman_technology_save_offlinemode();
1813 void __connman_technology_cleanup(void)
1817 while (technology_list) {
1818 struct connman_technology *technology = technology_list->data;
1819 technology_list = g_slist_remove(technology_list, technology);
1820 technology_put(technology);
1823 g_hash_table_destroy(rfkill_list);
1825 dbus_connection_unref(connection);