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 gint compare_priority(gconstpointer a, gconstpointer b)
89 const struct connman_technology_driver *driver1 = a;
90 const struct connman_technology_driver *driver2 = b;
92 return driver2->priority - driver1->priority;
95 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
97 struct connman_rfkill *rfkill = value;
98 enum connman_service_type type = GPOINTER_TO_INT(user_data);
100 /* Calling _technology_rfkill_add will update the tech. */
101 if (rfkill->type == type)
102 __connman_technology_add_rfkill(rfkill->index, type,
103 rfkill->softblock, rfkill->hardblock);
107 connman_technology_is_tethering_allowed(enum connman_service_type type)
109 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
111 const char *type_str = __connman_service_type2string(type);
118 allowed = connman_setting_get_string_list("TetheringTechnologies");
120 allowed = allowed_default;
122 for (i = 0; allowed[i]; i++) {
123 if (g_strcmp0(allowed[i], type_str) == 0)
130 static const char *get_name(enum connman_service_type type)
133 case CONNMAN_SERVICE_TYPE_UNKNOWN:
134 case CONNMAN_SERVICE_TYPE_SYSTEM:
135 case CONNMAN_SERVICE_TYPE_GPS:
136 case CONNMAN_SERVICE_TYPE_VPN:
138 case CONNMAN_SERVICE_TYPE_GADGET:
140 case CONNMAN_SERVICE_TYPE_ETHERNET:
142 case CONNMAN_SERVICE_TYPE_WIFI:
144 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
146 case CONNMAN_SERVICE_TYPE_CELLULAR:
148 case CONNMAN_SERVICE_TYPE_P2P:
155 static void technology_save(struct connman_technology *technology)
159 const char *name = get_name(technology->type);
161 DBG("technology %p type %d name %s", technology, technology->type,
166 keyfile = __connman_storage_load_global();
168 keyfile = g_key_file_new();
170 identifier = g_strdup_printf("%s", name);
174 g_key_file_set_boolean(keyfile, identifier, "Enable",
175 technology->enable_persistent);
177 g_key_file_set_boolean(keyfile, identifier, "Tethering",
178 technology->tethering_persistent);
180 if (technology->tethering_ident)
181 g_key_file_set_string(keyfile, identifier,
182 "Tethering.Identifier",
183 technology->tethering_ident);
185 if (technology->tethering_passphrase)
186 g_key_file_set_string(keyfile, identifier,
187 "Tethering.Passphrase",
188 technology->tethering_passphrase);
193 __connman_storage_save_global(keyfile);
195 g_key_file_free(keyfile);
200 static void tethering_changed(struct connman_technology *technology)
202 dbus_bool_t tethering = technology->tethering;
204 connman_dbus_property_changed_basic(technology->path,
205 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
206 DBUS_TYPE_BOOLEAN, &tethering);
208 technology_save(technology);
211 void connman_technology_tethering_notify(struct connman_technology *technology,
214 DBG("technology %p enabled %u", technology, enabled);
216 if (technology->tethering == enabled)
219 technology->tethering = enabled;
221 tethering_changed(technology);
224 __connman_tethering_set_enabled();
226 __connman_tethering_set_disabled();
229 static int set_tethering(struct connman_technology *technology,
232 int result = -EOPNOTSUPP;
234 const char *ident, *passphrase, *bridge;
235 GSList *tech_drivers;
237 ident = technology->tethering_ident;
238 passphrase = technology->tethering_passphrase;
240 __sync_synchronize();
241 if (!technology->enabled)
244 bridge = __connman_tethering_get_bridge();
248 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
249 (!ident || !passphrase))
252 for (tech_drivers = technology->driver_list; tech_drivers;
253 tech_drivers = g_slist_next(tech_drivers)) {
254 struct connman_technology_driver *driver = tech_drivers->data;
256 if (!driver || !driver->set_tethering)
259 err = driver->set_tethering(technology, ident, passphrase,
262 if (result == -EINPROGRESS)
265 if (err == -EINPROGRESS || err == 0) {
274 void connman_technology_regdom_notify(struct connman_technology *technology,
280 connman_error("Failed to set regulatory domain");
282 DBG("Regulatory domain set to %s", alpha2);
284 g_free(technology->regdom);
285 technology->regdom = g_strdup(alpha2);
288 static int set_regdom_by_device(struct connman_technology *technology,
293 for (list = technology->device_list; list; list = list->next) {
294 struct connman_device *device = list->data;
296 if (connman_device_set_regdom(device, alpha2) != 0)
303 int connman_technology_set_regdom(const char *alpha2)
305 GSList *list, *tech_drivers;
307 for (list = technology_list; list; list = list->next) {
308 struct connman_technology *technology = list->data;
310 if (set_regdom_by_device(technology, alpha2) != 0) {
312 for (tech_drivers = technology->driver_list;
314 tech_drivers = g_slist_next(tech_drivers)) {
316 struct connman_technology_driver *driver =
319 if (driver->set_regdom)
320 driver->set_regdom(technology, alpha2);
328 static struct connman_technology *technology_find(enum connman_service_type type)
332 DBG("type %d", type);
334 for (list = technology_list; list; list = list->next) {
335 struct connman_technology *technology = list->data;
337 if (technology->type == type)
344 bool connman_technology_get_wifi_tethering(const char **ssid,
347 struct connman_technology *technology;
354 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
358 if (!technology->tethering)
361 *ssid = technology->tethering_ident;
362 *psk = technology->tethering_passphrase;
367 static void free_rfkill(gpointer data)
369 struct connman_rfkill *rfkill = data;
374 static void technology_load(struct connman_technology *technology)
378 GError *error = NULL;
379 bool enable, need_saving = false;
381 DBG("technology %p", technology);
383 keyfile = __connman_storage_load_global();
384 /* Fallback on disabling technology if file not found. */
386 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
387 /* We enable ethernet by default */
388 technology->enable_persistent = true;
390 technology->enable_persistent = false;
394 identifier = g_strdup_printf("%s", get_name(technology->type));
398 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
400 technology->enable_persistent = enable;
402 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
403 technology->enable_persistent = true;
405 technology->enable_persistent = false;
408 g_clear_error(&error);
411 enable = g_key_file_get_boolean(keyfile, identifier,
412 "Tethering", &error);
414 technology->tethering_persistent = enable;
417 g_clear_error(&error);
421 technology_save(technology);
423 technology->tethering_ident = g_key_file_get_string(keyfile,
424 identifier, "Tethering.Identifier", NULL);
426 technology->tethering_passphrase = g_key_file_get_string(keyfile,
427 identifier, "Tethering.Passphrase", NULL);
431 g_key_file_free(keyfile);
436 bool __connman_technology_get_offlinemode(void)
438 return global_offlinemode;
441 static void connman_technology_save_offlinemode(void)
445 keyfile = __connman_storage_load_global();
447 keyfile = g_key_file_new();
449 g_key_file_set_boolean(keyfile, "global",
450 "OfflineMode", global_offlinemode);
452 __connman_storage_save_global(keyfile);
454 g_key_file_free(keyfile);
459 static bool connman_technology_load_offlinemode(void)
462 GError *error = NULL;
465 /* If there is a error, we enable offlinemode */
466 keyfile = __connman_storage_load_global();
470 offlinemode = g_key_file_get_boolean(keyfile, "global",
471 "OfflineMode", &error);
474 g_clear_error(&error);
477 g_key_file_free(keyfile);
482 static void append_properties(DBusMessageIter *iter,
483 struct connman_technology *technology)
485 DBusMessageIter dict;
489 connman_dbus_dict_open(iter, &dict);
491 str = get_name(technology->type);
493 connman_dbus_dict_append_basic(&dict, "Name",
494 DBUS_TYPE_STRING, &str);
496 str = __connman_service_type2string(technology->type);
498 connman_dbus_dict_append_basic(&dict, "Type",
499 DBUS_TYPE_STRING, &str);
501 __sync_synchronize();
502 val = technology->enabled;
503 connman_dbus_dict_append_basic(&dict, "Powered",
507 val = technology->connected;
508 connman_dbus_dict_append_basic(&dict, "Connected",
512 val = technology->tethering;
513 connman_dbus_dict_append_basic(&dict, "Tethering",
517 if (technology->tethering_ident)
518 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
520 &technology->tethering_ident);
522 if (technology->tethering_passphrase)
523 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
525 &technology->tethering_passphrase);
527 connman_dbus_dict_close(iter, &dict);
530 static void technology_added_signal(struct connman_technology *technology)
533 DBusMessageIter iter;
535 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
536 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
540 dbus_message_iter_init_append(signal, &iter);
541 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
543 append_properties(&iter, technology);
545 dbus_connection_send(connection, signal, NULL);
546 dbus_message_unref(signal);
549 static void technology_removed_signal(struct connman_technology *technology)
551 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
552 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
553 DBUS_TYPE_OBJECT_PATH, &technology->path,
557 static DBusMessage *get_properties(DBusConnection *conn,
558 DBusMessage *message, void *user_data)
560 struct connman_technology *technology = user_data;
562 DBusMessageIter iter;
564 reply = dbus_message_new_method_return(message);
568 dbus_message_iter_init_append(reply, &iter);
569 append_properties(&iter, technology);
574 void __connman_technology_list_struct(DBusMessageIter *array)
577 DBusMessageIter entry;
579 for (list = technology_list; list; list = list->next) {
580 struct connman_technology *technology = list->data;
582 if (!technology->path ||
583 (technology->rfkill_driven &&
584 technology->hardblocked))
587 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
589 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
591 append_properties(&entry, technology);
592 dbus_message_iter_close_container(array, &entry);
596 static gboolean technology_pending_reply(gpointer user_data)
598 struct connman_technology *technology = user_data;
601 /* Power request timedout, send ETIMEDOUT. */
602 if (technology->pending_reply) {
603 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
605 g_dbus_send_message(connection, reply);
607 dbus_message_unref(technology->pending_reply);
608 technology->pending_reply = NULL;
609 technology->pending_timeout = 0;
615 static int technology_affect_devices(struct connman_technology *technology,
621 if (technology->type == CONNMAN_SERVICE_TYPE_P2P)
624 for (list = technology->device_list; list; list = list->next) {
625 struct connman_device *device = list->data;
628 err = __connman_device_enable(device);
630 err = __connman_device_disable(device);
636 static void powered_changed(struct connman_technology *technology)
640 if (!technology->dbus_registered)
643 if (technology->pending_reply) {
644 g_dbus_send_reply(connection,
645 technology->pending_reply, DBUS_TYPE_INVALID);
646 dbus_message_unref(technology->pending_reply);
647 technology->pending_reply = NULL;
649 g_source_remove(technology->pending_timeout);
650 technology->pending_timeout = 0;
653 __sync_synchronize();
654 enabled = technology->enabled;
655 connman_dbus_property_changed_basic(technology->path,
656 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
657 DBUS_TYPE_BOOLEAN, &enabled);
660 static void enable_tethering(struct connman_technology *technology)
664 if (!connman_setting_get_bool("PersistentTetheringMode"))
667 ret = set_tethering(technology, true);
668 if (ret < 0 && ret != -EALREADY)
669 DBG("Cannot enable tethering yet for %s (%d/%s)",
670 get_name(technology->type),
671 -ret, strerror(-ret));
674 static int technology_enabled(struct connman_technology *technology)
676 __sync_synchronize();
677 if (technology->enabled)
680 technology->enabled = true;
682 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
683 struct connman_technology *p2p;
685 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
686 if (p2p && !p2p->enabled && p2p->enable_persistent)
687 technology_enabled(p2p);
690 if (technology->tethering_persistent)
691 enable_tethering(technology);
693 powered_changed(technology);
698 static int technology_enable(struct connman_technology *technology)
703 DBG("technology %p enable", technology);
705 __sync_synchronize();
707 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
708 struct connman_technology *wifi;
710 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
711 if (wifi && wifi->enabled)
712 return technology_enabled(technology);
716 if (technology->enabled)
719 if (technology->pending_reply)
722 if (connman_setting_get_bool("PersistentTetheringMode") &&
723 technology->tethering)
724 set_tethering(technology, true);
726 if (technology->rfkill_driven)
727 err = __connman_rfkill_block(technology->type, false);
729 err_dev = technology_affect_devices(technology, true);
731 if (!technology->rfkill_driven)
737 static int technology_disabled(struct connman_technology *technology)
739 __sync_synchronize();
740 if (!technology->enabled)
743 technology->enabled = false;
745 powered_changed(technology);
750 static int technology_disable(struct connman_technology *technology)
754 DBG("technology %p disable", technology);
756 __sync_synchronize();
758 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
759 technology->enable_persistent = false;
760 return technology_disabled(technology);
761 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
762 struct connman_technology *p2p;
764 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
765 if (p2p && p2p->enabled) {
766 p2p->enable_persistent = true;
767 technology_disabled(p2p);
771 if (!technology->enabled)
774 if (technology->pending_reply)
777 if (technology->tethering)
778 set_tethering(technology, false);
780 err = technology_affect_devices(technology, false);
782 if (technology->rfkill_driven)
783 err = __connman_rfkill_block(technology->type, true);
788 static DBusMessage *set_powered(struct connman_technology *technology,
789 DBusMessage *msg, bool powered)
791 DBusMessage *reply = NULL;
794 if (technology->rfkill_driven && technology->hardblocked) {
800 err = technology_enable(technology);
802 err = technology_disable(technology);
805 technology->enable_persistent = powered;
806 technology_save(technology);
810 if (err == -EINPROGRESS) {
811 technology->pending_reply = dbus_message_ref(msg);
812 technology->pending_timeout = g_timeout_add_seconds(10,
813 technology_pending_reply, technology);
814 } else if (err == -EALREADY) {
816 reply = __connman_error_already_enabled(msg);
818 reply = __connman_error_already_disabled(msg);
820 reply = __connman_error_failed(msg, -err);
822 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
827 static DBusMessage *set_property(DBusConnection *conn,
828 DBusMessage *msg, void *data)
830 struct connman_technology *technology = data;
831 DBusMessageIter iter, value;
835 DBG("conn %p", conn);
837 if (!dbus_message_iter_init(msg, &iter))
838 return __connman_error_invalid_arguments(msg);
840 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
841 return __connman_error_invalid_arguments(msg);
843 dbus_message_iter_get_basic(&iter, &name);
844 dbus_message_iter_next(&iter);
846 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
847 return __connman_error_invalid_arguments(msg);
849 dbus_message_iter_recurse(&iter, &value);
851 type = dbus_message_iter_get_arg_type(&value);
853 DBG("property %s", name);
855 if (g_str_equal(name, "Tethering")) {
856 dbus_bool_t tethering;
859 if (type != DBUS_TYPE_BOOLEAN)
860 return __connman_error_invalid_arguments(msg);
862 if (!connman_technology_is_tethering_allowed(technology->type)) {
863 DBG("%s tethering not allowed by config file",
864 __connman_service_type2string(technology->type));
865 return __connman_error_not_supported(msg);
868 dbus_message_iter_get_basic(&value, &tethering);
870 if (technology->tethering == tethering) {
872 return __connman_error_already_disabled(msg);
874 return __connman_error_already_enabled(msg);
877 err = set_tethering(technology, tethering);
879 return __connman_error_failed(msg, -err);
881 technology->tethering_persistent = tethering;
883 technology_save(technology);
885 } else if (g_str_equal(name, "TetheringIdentifier")) {
888 dbus_message_iter_get_basic(&value, &str);
890 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
891 return __connman_error_not_supported(msg);
893 if (strlen(str) < 1 || strlen(str) > 32)
894 return __connman_error_invalid_arguments(msg);
896 if (g_strcmp0(technology->tethering_ident, str) != 0) {
897 g_free(technology->tethering_ident);
898 technology->tethering_ident = g_strdup(str);
899 technology_save(technology);
901 connman_dbus_property_changed_basic(technology->path,
902 CONNMAN_TECHNOLOGY_INTERFACE,
903 "TetheringIdentifier",
905 &technology->tethering_ident);
907 } else if (g_str_equal(name, "TetheringPassphrase")) {
910 dbus_message_iter_get_basic(&value, &str);
912 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
913 return __connman_error_not_supported(msg);
915 if (strlen(str) < 8 || strlen(str) > 63)
916 return __connman_error_passphrase_required(msg);
918 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
919 g_free(technology->tethering_passphrase);
920 technology->tethering_passphrase = g_strdup(str);
921 technology_save(technology);
923 connman_dbus_property_changed_basic(technology->path,
924 CONNMAN_TECHNOLOGY_INTERFACE,
925 "TetheringPassphrase",
927 &technology->tethering_passphrase);
929 } else if (g_str_equal(name, "Powered")) {
932 if (type != DBUS_TYPE_BOOLEAN)
933 return __connman_error_invalid_arguments(msg);
935 dbus_message_iter_get_basic(&value, &enable);
937 return set_powered(technology, msg, enable);
939 return __connman_error_invalid_property(msg);
941 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
944 static void reply_scan_pending(struct connman_technology *technology, int err)
948 DBG("technology %p err %d", technology, err);
950 while (technology->scan_pending) {
951 DBusMessage *msg = technology->scan_pending->data;
953 DBG("reply to %s", dbus_message_get_sender(msg));
956 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
958 reply = __connman_error_failed(msg, -err);
959 g_dbus_send_message(connection, reply);
960 dbus_message_unref(msg);
962 technology->scan_pending =
963 g_slist_delete_link(technology->scan_pending,
964 technology->scan_pending);
968 void __connman_technology_scan_started(struct connman_device *device)
970 DBG("device %p", device);
973 void __connman_technology_scan_stopped(struct connman_device *device,
974 enum connman_service_type type)
977 struct connman_technology *technology;
980 technology = technology_find(type);
982 DBG("technology %p device %p", technology, device);
987 for (list = technology->device_list; list; list = list->next) {
988 struct connman_device *other_device = list->data;
990 if (device == other_device)
993 if (__connman_device_get_service_type(other_device) != type)
996 if (connman_device_get_scanning(other_device))
1001 reply_scan_pending(technology, 0);
1004 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1005 int result, const char *alpha2)
1007 bool regdom_set = false;
1008 struct connman_technology *technology;
1009 enum connman_service_type type;
1010 GSList *tech_drivers;
1012 type = __connman_device_get_service_type(device);
1013 technology = technology_find(type);
1020 for (tech_drivers = technology->driver_list;
1022 tech_drivers = g_slist_next(tech_drivers)) {
1023 struct connman_technology_driver *driver =
1026 if (driver->set_regdom) {
1027 driver->set_regdom(technology, alpha2);
1037 connman_technology_regdom_notify(technology, alpha2);
1040 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1042 struct connman_technology *technology = data;
1045 DBG("technology %p request from %s", technology,
1046 dbus_message_get_sender(msg));
1048 dbus_message_ref(msg);
1049 technology->scan_pending =
1050 g_slist_prepend(technology->scan_pending, msg);
1052 err = __connman_device_request_scan(technology->type);
1054 reply_scan_pending(technology, err);
1059 static const GDBusMethodTable technology_methods[] = {
1060 { GDBUS_DEPRECATED_METHOD("GetProperties",
1061 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1063 { GDBUS_ASYNC_METHOD("SetProperty",
1064 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1065 NULL, set_property) },
1066 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1070 static const GDBusSignalTable technology_signals[] = {
1071 { GDBUS_SIGNAL("PropertyChanged",
1072 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1076 static bool technology_dbus_register(struct connman_technology *technology)
1078 if (technology->dbus_registered ||
1079 (technology->rfkill_driven &&
1080 technology->hardblocked))
1083 if (!g_dbus_register_interface(connection, technology->path,
1084 CONNMAN_TECHNOLOGY_INTERFACE,
1085 technology_methods, technology_signals,
1086 NULL, technology, NULL)) {
1087 connman_error("Failed to register %s", technology->path);
1091 technology_added_signal(technology);
1092 technology->dbus_registered = true;
1097 static void technology_dbus_unregister(struct connman_technology *technology)
1099 if (!technology->dbus_registered)
1102 technology_removed_signal(technology);
1103 g_dbus_unregister_interface(connection, technology->path,
1104 CONNMAN_TECHNOLOGY_INTERFACE);
1106 technology->dbus_registered = false;
1109 static void technology_put(struct connman_technology *technology)
1111 DBG("technology %p", technology);
1113 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1116 reply_scan_pending(technology, -EINTR);
1118 while (technology->driver_list) {
1119 struct connman_technology_driver *driver;
1121 driver = technology->driver_list->data;
1124 driver->remove(technology);
1126 technology->driver_list =
1127 g_slist_delete_link(technology->driver_list,
1128 technology->driver_list);
1131 technology_list = g_slist_remove(technology_list, technology);
1133 technology_dbus_unregister(technology);
1135 g_slist_free(technology->device_list);
1137 g_free(technology->path);
1138 g_free(technology->regdom);
1139 g_free(technology->tethering_ident);
1140 g_free(technology->tethering_passphrase);
1144 static struct connman_technology *technology_get(enum connman_service_type type)
1146 GSList *tech_drivers = NULL;
1147 struct connman_technology_driver *driver;
1148 struct connman_technology *technology;
1152 DBG("type %d", type);
1154 str = __connman_service_type2string(type);
1158 technology = technology_find(type);
1160 if (type != CONNMAN_SERVICE_TYPE_P2P)
1161 __sync_fetch_and_add(&technology->refcount, 1);
1165 /* First check if we have a driver for this technology type */
1166 for (list = driver_list; list; list = list->next) {
1167 driver = list->data;
1169 if (driver->type == type) {
1170 DBG("technology %p driver %p", technology, driver);
1171 tech_drivers = g_slist_append(tech_drivers, driver);
1175 if (!tech_drivers) {
1176 DBG("No matching drivers found for %s.",
1177 __connman_service_type2string(type));
1181 technology = g_try_new0(struct connman_technology, 1);
1185 technology->refcount = 1;
1186 technology->type = type;
1187 technology->path = g_strdup_printf("%s/technology/%s",
1189 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1190 struct connman_technology *wifi;
1192 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
1194 technology->enabled = wifi->enabled;
1197 technology_load(technology);
1198 technology_list = g_slist_prepend(technology_list, technology);
1199 technology->driver_list = tech_drivers;
1201 for (list = tech_drivers; list; list = list->next) {
1202 driver = list->data;
1204 if (driver->probe && driver->probe(technology) < 0)
1205 DBG("Driver probe failed for technology %p",
1209 if (!technology_dbus_register(technology)) {
1210 technology_put(technology);
1214 DBG("technology %p", technology);
1219 int connman_technology_driver_register(struct connman_technology_driver *driver)
1222 struct connman_device *device;
1223 enum connman_service_type type;
1225 for (list = driver_list; list; list = list->next) {
1226 if (list->data == driver)
1230 DBG("Registering %s driver", driver->name);
1232 driver_list = g_slist_insert_sorted(driver_list, driver,
1236 * Check for technology less devices if this driver
1237 * can service any of them.
1239 for (list = techless_device_list; list; list = list->next) {
1240 device = list->data;
1242 type = __connman_device_get_service_type(device);
1243 if (type != driver->type)
1246 techless_device_list = g_slist_remove(techless_device_list,
1249 __connman_technology_add_device(device);
1252 /* Check for orphaned rfkill switches. */
1253 g_hash_table_foreach(rfkill_list, rfkill_check,
1254 GINT_TO_POINTER(driver->type));
1257 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1258 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
1265 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
1267 GSList *list, *tech_drivers;
1268 struct connman_technology *technology;
1269 struct connman_technology_driver *current;
1271 DBG("Unregistering driver %p name %s", driver, driver->name);
1273 for (list = technology_list; list; list = list->next) {
1274 technology = list->data;
1276 for (tech_drivers = technology->driver_list; tech_drivers;
1277 tech_drivers = g_slist_next(tech_drivers)) {
1278 current = tech_drivers->data;
1279 if (driver != current)
1283 driver->remove(technology);
1285 technology->driver_list =
1286 g_slist_remove(technology->driver_list,
1292 driver_list = g_slist_remove(driver_list, driver);
1294 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1295 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1297 technology_put(technology);
1301 void __connman_technology_add_interface(enum connman_service_type type,
1302 int index, const char *ident)
1304 struct connman_technology *technology;
1305 GSList *tech_drivers;
1306 struct connman_technology_driver *driver;
1310 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1311 case CONNMAN_SERVICE_TYPE_SYSTEM:
1313 case CONNMAN_SERVICE_TYPE_ETHERNET:
1314 case CONNMAN_SERVICE_TYPE_WIFI:
1315 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1316 case CONNMAN_SERVICE_TYPE_CELLULAR:
1317 case CONNMAN_SERVICE_TYPE_GPS:
1318 case CONNMAN_SERVICE_TYPE_VPN:
1319 case CONNMAN_SERVICE_TYPE_GADGET:
1320 case CONNMAN_SERVICE_TYPE_P2P:
1324 name = connman_inet_ifname(index);
1325 connman_info("Adding interface %s [ %s ]", name,
1326 __connman_service_type2string(type));
1328 technology = technology_find(type);
1333 for (tech_drivers = technology->driver_list; tech_drivers;
1334 tech_drivers = g_slist_next(tech_drivers)) {
1335 driver = tech_drivers->data;
1337 if (driver->add_interface)
1338 driver->add_interface(technology, index, name, ident);
1342 * At this point we can try to enable tethering automatically as
1343 * now the interfaces are set properly.
1345 if (technology->tethering_persistent)
1346 enable_tethering(technology);
1352 void __connman_technology_remove_interface(enum connman_service_type type,
1353 int index, const char *ident)
1355 struct connman_technology *technology;
1356 GSList *tech_drivers;
1357 struct connman_technology_driver *driver;
1361 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1362 case CONNMAN_SERVICE_TYPE_SYSTEM:
1364 case CONNMAN_SERVICE_TYPE_ETHERNET:
1365 case CONNMAN_SERVICE_TYPE_WIFI:
1366 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1367 case CONNMAN_SERVICE_TYPE_CELLULAR:
1368 case CONNMAN_SERVICE_TYPE_GPS:
1369 case CONNMAN_SERVICE_TYPE_VPN:
1370 case CONNMAN_SERVICE_TYPE_GADGET:
1371 case CONNMAN_SERVICE_TYPE_P2P:
1375 name = connman_inet_ifname(index);
1376 connman_info("Remove interface %s [ %s ]", name,
1377 __connman_service_type2string(type));
1380 technology = technology_find(type);
1385 for (tech_drivers = technology->driver_list; tech_drivers;
1386 tech_drivers = g_slist_next(tech_drivers)) {
1387 driver = tech_drivers->data;
1389 if (driver->remove_interface)
1390 driver->remove_interface(technology, index);
1394 int __connman_technology_add_device(struct connman_device *device)
1396 struct connman_technology *technology;
1397 enum connman_service_type type;
1399 type = __connman_device_get_service_type(device);
1401 DBG("device %p type %s", device, get_name(type));
1403 technology = technology_get(type);
1406 * Since no driver can be found for this device at the moment we
1407 * add it to the techless device list.
1409 techless_device_list = g_slist_prepend(techless_device_list,
1415 __sync_synchronize();
1416 if (technology->rfkill_driven) {
1417 if (technology->enabled)
1418 __connman_device_enable(device);
1420 __connman_device_disable(device);
1425 if (technology->enable_persistent &&
1426 !global_offlinemode) {
1427 int err = __connman_device_enable(device);
1429 * connman_technology_add_device() calls __connman_device_enable()
1430 * but since the device is already enabled, the calls does not
1431 * propagate through to connman_technology_enabled via
1432 * connman_device_set_powered.
1434 if (err == -EALREADY)
1435 __connman_technology_enabled(type);
1437 /* if technology persistent state is offline */
1438 if (!technology->enable_persistent)
1439 __connman_device_disable(device);
1442 technology->device_list = g_slist_prepend(technology->device_list,
1448 int __connman_technology_remove_device(struct connman_device *device)
1450 struct connman_technology *technology;
1451 enum connman_service_type type;
1453 DBG("device %p", device);
1455 type = __connman_device_get_service_type(device);
1457 technology = technology_find(type);
1459 techless_device_list = g_slist_remove(techless_device_list,
1464 technology->device_list = g_slist_remove(technology->device_list,
1467 if (technology->tethering)
1468 set_tethering(technology, false);
1470 technology_put(technology);
1475 int __connman_technology_enabled(enum connman_service_type type)
1477 struct connman_technology *technology;
1479 technology = technology_find(type);
1483 DBG("technology %p type %s rfkill %d enabled %d", technology,
1484 get_name(type), technology->rfkill_driven,
1485 technology->enabled);
1487 if (technology->rfkill_driven) {
1488 if (technology->tethering_persistent)
1489 enable_tethering(technology);
1493 return technology_enabled(technology);
1496 int __connman_technology_disabled(enum connman_service_type type)
1498 struct connman_technology *technology;
1501 technology = technology_find(type);
1505 if (technology->rfkill_driven)
1508 for (list = technology->device_list; list; list = list->next) {
1509 struct connman_device *device = list->data;
1511 if (connman_device_get_powered(device))
1515 return technology_disabled(technology);
1518 int __connman_technology_set_offlinemode(bool offlinemode)
1521 int err = -EINVAL, enabled_tech_count = 0;
1523 if (global_offlinemode == offlinemode)
1526 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1529 * This is a bit tricky. When you set offlinemode, there is no
1530 * way to differentiate between attempting offline mode and
1531 * resuming offlinemode from last saved profile. We need that
1532 * information in rfkill_update, otherwise it falls back on the
1533 * technology's persistent state. Hence we set the offline mode here
1534 * but save it & call the notifier only if its successful.
1537 global_offlinemode = offlinemode;
1539 /* Traverse technology list, enable/disable each technology. */
1540 for (list = technology_list; list; list = list->next) {
1541 struct connman_technology *technology = list->data;
1544 err = technology_disable(technology);
1546 if (technology->hardblocked)
1549 if (technology->enable_persistent) {
1550 err = technology_enable(technology);
1551 enabled_tech_count++;
1556 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1557 (err == -EINVAL && enabled_tech_count == 0)) {
1558 connman_technology_save_offlinemode();
1559 __connman_notifier_offlinemode(offlinemode);
1561 global_offlinemode = connman_technology_load_offlinemode();
1566 void __connman_technology_set_connected(enum connman_service_type type,
1569 struct connman_technology *technology;
1572 technology = technology_find(type);
1576 DBG("technology %p connected %d", technology, connected);
1578 technology->connected = connected;
1581 connman_dbus_property_changed_basic(technology->path,
1582 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1583 DBUS_TYPE_BOOLEAN, &val);
1586 static bool technology_apply_rfkill_change(struct connman_technology *technology,
1591 bool hardblock_changed = false;
1593 GList *start, *list;
1595 DBG("technology %p --> %d/%d vs %d/%d",
1596 technology, softblock, hardblock,
1597 technology->softblocked, technology->hardblocked);
1599 if (technology->hardblocked == hardblock)
1600 goto softblock_change;
1602 if (!(new_rfkill && !hardblock)) {
1603 start = g_hash_table_get_values(rfkill_list);
1605 for (list = start; list; list = list->next) {
1606 struct connman_rfkill *rfkill = list->data;
1608 if (rfkill->type != technology->type)
1611 if (rfkill->hardblock != hardblock)
1619 goto softblock_change;
1621 technology->hardblocked = hardblock;
1622 hardblock_changed = true;
1625 if (!apply && technology->softblocked != softblock)
1629 return technology->hardblocked;
1631 technology->softblocked = softblock;
1633 if (technology->hardblocked ||
1634 technology->softblocked) {
1635 if (technology_disabled(technology) != -EALREADY)
1636 technology_affect_devices(technology, false);
1637 } else if (!technology->hardblocked &&
1638 !technology->softblocked) {
1639 if (technology_enabled(technology) != -EALREADY)
1640 technology_affect_devices(technology, true);
1643 if (hardblock_changed) {
1644 if (technology->hardblocked) {
1645 DBG("%s is switched off.", get_name(technology->type));
1646 technology_dbus_unregister(technology);
1648 DBG("%s is switched on.", get_name(technology->type));
1649 technology_dbus_register(technology);
1651 if (global_offlinemode)
1652 __connman_rfkill_block(technology->type, true);
1656 return technology->hardblocked;
1659 int __connman_technology_add_rfkill(unsigned int index,
1660 enum connman_service_type type,
1664 struct connman_technology *technology;
1665 struct connman_rfkill *rfkill;
1667 DBG("index %u type %d soft %u hard %u", index, type,
1668 softblock, hardblock);
1670 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1674 rfkill = g_try_new0(struct connman_rfkill, 1);
1678 rfkill->index = index;
1679 rfkill->type = type;
1680 rfkill->softblock = softblock;
1681 rfkill->hardblock = hardblock;
1683 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1686 technology = technology_get(type);
1687 /* If there is no driver for this type, ignore it. */
1691 technology->rfkill_driven = true;
1693 /* If hardblocked, there is no need to handle softblocked state */
1694 if (technology_apply_rfkill_change(technology,
1695 softblock, hardblock, true))
1698 if (global_offlinemode)
1702 * Depending on softblocked state we unblock/block according to
1703 * offlinemode and persistente state.
1705 if (technology->softblocked &&
1706 technology->enable_persistent)
1707 return __connman_rfkill_block(type, false);
1708 else if (!technology->softblocked &&
1709 !technology->enable_persistent)
1710 return __connman_rfkill_block(type, true);
1715 int __connman_technology_update_rfkill(unsigned int index,
1716 enum connman_service_type type,
1720 struct connman_technology *technology;
1721 struct connman_rfkill *rfkill;
1723 DBG("index %u soft %u hard %u", index, softblock, hardblock);
1725 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1729 if (rfkill->softblock == softblock &&
1730 rfkill->hardblock == hardblock)
1733 rfkill->softblock = softblock;
1734 rfkill->hardblock = hardblock;
1736 technology = technology_find(type);
1737 /* If there is no driver for this type, ignore it. */
1741 technology_apply_rfkill_change(technology, softblock, hardblock,
1744 if (technology->hardblocked)
1745 DBG("%s hardblocked", get_name(technology->type));
1747 DBG("%s is%s softblocked", get_name(technology->type),
1748 technology->softblocked ? "" : " not");
1753 int __connman_technology_remove_rfkill(unsigned int index,
1754 enum connman_service_type type)
1756 struct connman_technology *technology;
1757 struct connman_rfkill *rfkill;
1759 DBG("index %u", index);
1761 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1765 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
1767 technology = technology_find(type);
1771 technology_apply_rfkill_change(technology,
1772 technology->softblocked, !technology->hardblocked, false);
1774 technology_put(technology);
1779 int __connman_technology_init(void)
1783 connection = connman_dbus_get_connection();
1785 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1788 global_offlinemode = connman_technology_load_offlinemode();
1790 /* This will create settings file if it is missing */
1791 connman_technology_save_offlinemode();
1796 void __connman_technology_cleanup(void)
1800 g_hash_table_destroy(rfkill_list);
1802 dbus_connection_unref(connection);