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" })) },
1073 { GDBUS_SIGNAL("DhcpConnected",
1074 GDBUS_ARGS({ "aptype", "s" },
1077 { "hostname", "s" })) },
1078 { GDBUS_SIGNAL("DhcpLeaseDeleted",
1079 GDBUS_ARGS({ "aptype", "s" },
1082 { "hostname", "s" })) },
1086 static bool technology_dbus_register(struct connman_technology *technology)
1088 if (technology->dbus_registered ||
1089 (technology->rfkill_driven &&
1090 technology->hardblocked))
1093 if (!g_dbus_register_interface(connection, technology->path,
1094 CONNMAN_TECHNOLOGY_INTERFACE,
1095 technology_methods, technology_signals,
1096 NULL, technology, NULL)) {
1097 connman_error("Failed to register %s", technology->path);
1101 technology_added_signal(technology);
1102 technology->dbus_registered = true;
1107 static void technology_dbus_unregister(struct connman_technology *technology)
1109 if (!technology->dbus_registered)
1112 technology_removed_signal(technology);
1113 g_dbus_unregister_interface(connection, technology->path,
1114 CONNMAN_TECHNOLOGY_INTERFACE);
1116 technology->dbus_registered = false;
1119 static void technology_put(struct connman_technology *technology)
1121 DBG("technology %p", technology);
1123 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1126 reply_scan_pending(technology, -EINTR);
1128 while (technology->driver_list) {
1129 struct connman_technology_driver *driver;
1131 driver = technology->driver_list->data;
1134 driver->remove(technology);
1136 technology->driver_list =
1137 g_slist_delete_link(technology->driver_list,
1138 technology->driver_list);
1141 technology_list = g_slist_remove(technology_list, technology);
1143 technology_dbus_unregister(technology);
1145 g_slist_free(technology->device_list);
1147 g_free(technology->path);
1148 g_free(technology->regdom);
1149 g_free(technology->tethering_ident);
1150 g_free(technology->tethering_passphrase);
1154 static struct connman_technology *technology_get(enum connman_service_type type)
1156 GSList *tech_drivers = NULL;
1157 struct connman_technology_driver *driver;
1158 struct connman_technology *technology;
1162 DBG("type %d", type);
1164 str = __connman_service_type2string(type);
1168 technology = technology_find(type);
1170 if (type != CONNMAN_SERVICE_TYPE_P2P)
1171 __sync_fetch_and_add(&technology->refcount, 1);
1175 /* First check if we have a driver for this technology type */
1176 for (list = driver_list; list; list = list->next) {
1177 driver = list->data;
1179 if (driver->type == type) {
1180 DBG("technology %p driver %p", technology, driver);
1181 tech_drivers = g_slist_append(tech_drivers, driver);
1185 if (!tech_drivers) {
1186 DBG("No matching drivers found for %s.",
1187 __connman_service_type2string(type));
1191 technology = g_try_new0(struct connman_technology, 1);
1195 technology->refcount = 1;
1196 technology->type = type;
1197 technology->path = g_strdup_printf("%s/technology/%s",
1199 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1200 struct connman_technology *wifi;
1202 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
1204 technology->enabled = wifi->enabled;
1207 technology_load(technology);
1208 technology_list = g_slist_prepend(technology_list, technology);
1209 technology->driver_list = tech_drivers;
1211 for (list = tech_drivers; list; list = list->next) {
1212 driver = list->data;
1214 if (driver->probe && driver->probe(technology) < 0)
1215 DBG("Driver probe failed for technology %p",
1219 if (!technology_dbus_register(technology)) {
1220 technology_put(technology);
1224 DBG("technology %p", technology);
1229 int connman_technology_driver_register(struct connman_technology_driver *driver)
1232 struct connman_device *device;
1233 enum connman_service_type type;
1235 for (list = driver_list; list; list = list->next) {
1236 if (list->data == driver)
1240 DBG("Registering %s driver", driver->name);
1242 driver_list = g_slist_insert_sorted(driver_list, driver,
1246 * Check for technology less devices if this driver
1247 * can service any of them.
1249 for (list = techless_device_list; list; list = list->next) {
1250 device = list->data;
1252 type = __connman_device_get_service_type(device);
1253 if (type != driver->type)
1256 techless_device_list = g_slist_remove(techless_device_list,
1259 __connman_technology_add_device(device);
1262 /* Check for orphaned rfkill switches. */
1263 g_hash_table_foreach(rfkill_list, rfkill_check,
1264 GINT_TO_POINTER(driver->type));
1267 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1268 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
1275 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
1277 GSList *list, *tech_drivers;
1278 struct connman_technology *technology;
1279 struct connman_technology_driver *current;
1281 DBG("Unregistering driver %p name %s", driver, driver->name);
1283 for (list = technology_list; list; list = list->next) {
1284 technology = list->data;
1286 for (tech_drivers = technology->driver_list; tech_drivers;
1287 tech_drivers = g_slist_next(tech_drivers)) {
1288 current = tech_drivers->data;
1289 if (driver != current)
1293 driver->remove(technology);
1295 technology->driver_list =
1296 g_slist_remove(technology->driver_list,
1302 driver_list = g_slist_remove(driver_list, driver);
1304 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1305 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1307 technology_put(technology);
1311 void __connman_technology_add_interface(enum connman_service_type type,
1312 int index, const char *ident)
1314 struct connman_technology *technology;
1315 GSList *tech_drivers;
1316 struct connman_technology_driver *driver;
1320 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1321 case CONNMAN_SERVICE_TYPE_SYSTEM:
1323 case CONNMAN_SERVICE_TYPE_ETHERNET:
1324 case CONNMAN_SERVICE_TYPE_WIFI:
1325 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1326 case CONNMAN_SERVICE_TYPE_CELLULAR:
1327 case CONNMAN_SERVICE_TYPE_GPS:
1328 case CONNMAN_SERVICE_TYPE_VPN:
1329 case CONNMAN_SERVICE_TYPE_GADGET:
1330 case CONNMAN_SERVICE_TYPE_P2P:
1334 name = connman_inet_ifname(index);
1335 connman_info("Adding interface %s [ %s ]", name,
1336 __connman_service_type2string(type));
1338 technology = technology_find(type);
1343 for (tech_drivers = technology->driver_list; tech_drivers;
1344 tech_drivers = g_slist_next(tech_drivers)) {
1345 driver = tech_drivers->data;
1347 if (driver->add_interface)
1348 driver->add_interface(technology, index, name, ident);
1352 * At this point we can try to enable tethering automatically as
1353 * now the interfaces are set properly.
1355 if (technology->tethering_persistent)
1356 enable_tethering(technology);
1362 void __connman_technology_remove_interface(enum connman_service_type type,
1363 int index, const char *ident)
1365 struct connman_technology *technology;
1366 GSList *tech_drivers;
1367 struct connman_technology_driver *driver;
1371 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1372 case CONNMAN_SERVICE_TYPE_SYSTEM:
1374 case CONNMAN_SERVICE_TYPE_ETHERNET:
1375 case CONNMAN_SERVICE_TYPE_WIFI:
1376 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1377 case CONNMAN_SERVICE_TYPE_CELLULAR:
1378 case CONNMAN_SERVICE_TYPE_GPS:
1379 case CONNMAN_SERVICE_TYPE_VPN:
1380 case CONNMAN_SERVICE_TYPE_GADGET:
1381 case CONNMAN_SERVICE_TYPE_P2P:
1385 name = connman_inet_ifname(index);
1386 connman_info("Remove interface %s [ %s ]", name,
1387 __connman_service_type2string(type));
1390 technology = technology_find(type);
1395 for (tech_drivers = technology->driver_list; tech_drivers;
1396 tech_drivers = g_slist_next(tech_drivers)) {
1397 driver = tech_drivers->data;
1399 if (driver->remove_interface)
1400 driver->remove_interface(technology, index);
1404 int __connman_technology_add_device(struct connman_device *device)
1406 struct connman_technology *technology;
1407 enum connman_service_type type;
1409 type = __connman_device_get_service_type(device);
1411 DBG("device %p type %s", device, get_name(type));
1413 technology = technology_get(type);
1416 * Since no driver can be found for this device at the moment we
1417 * add it to the techless device list.
1419 techless_device_list = g_slist_prepend(techless_device_list,
1425 __sync_synchronize();
1426 if (technology->rfkill_driven) {
1427 if (technology->enabled)
1428 __connman_device_enable(device);
1430 __connman_device_disable(device);
1435 if (technology->enable_persistent &&
1436 !global_offlinemode) {
1437 int err = __connman_device_enable(device);
1439 * connman_technology_add_device() calls __connman_device_enable()
1440 * but since the device is already enabled, the calls does not
1441 * propagate through to connman_technology_enabled via
1442 * connman_device_set_powered.
1444 if (err == -EALREADY)
1445 __connman_technology_enabled(type);
1447 /* if technology persistent state is offline */
1448 if (!technology->enable_persistent)
1449 __connman_device_disable(device);
1452 technology->device_list = g_slist_prepend(technology->device_list,
1458 int __connman_technology_remove_device(struct connman_device *device)
1460 struct connman_technology *technology;
1461 enum connman_service_type type;
1463 DBG("device %p", device);
1465 type = __connman_device_get_service_type(device);
1467 technology = technology_find(type);
1469 techless_device_list = g_slist_remove(techless_device_list,
1474 technology->device_list = g_slist_remove(technology->device_list,
1477 if (technology->tethering)
1478 set_tethering(technology, false);
1480 technology_put(technology);
1485 int __connman_technology_enabled(enum connman_service_type type)
1487 struct connman_technology *technology;
1489 technology = technology_find(type);
1493 DBG("technology %p type %s rfkill %d enabled %d", technology,
1494 get_name(type), technology->rfkill_driven,
1495 technology->enabled);
1497 if (technology->rfkill_driven) {
1498 if (technology->tethering_persistent)
1499 enable_tethering(technology);
1503 return technology_enabled(technology);
1506 int __connman_technology_disabled(enum connman_service_type type)
1508 struct connman_technology *technology;
1511 technology = technology_find(type);
1515 if (technology->rfkill_driven)
1518 for (list = technology->device_list; list; list = list->next) {
1519 struct connman_device *device = list->data;
1521 if (connman_device_get_powered(device))
1525 return technology_disabled(technology);
1528 int __connman_technology_set_offlinemode(bool offlinemode)
1531 int err = -EINVAL, enabled_tech_count = 0;
1533 if (global_offlinemode == offlinemode)
1536 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1539 * This is a bit tricky. When you set offlinemode, there is no
1540 * way to differentiate between attempting offline mode and
1541 * resuming offlinemode from last saved profile. We need that
1542 * information in rfkill_update, otherwise it falls back on the
1543 * technology's persistent state. Hence we set the offline mode here
1544 * but save it & call the notifier only if its successful.
1547 global_offlinemode = offlinemode;
1549 /* Traverse technology list, enable/disable each technology. */
1550 for (list = technology_list; list; list = list->next) {
1551 struct connman_technology *technology = list->data;
1554 err = technology_disable(technology);
1556 if (technology->hardblocked)
1559 if (technology->enable_persistent) {
1560 err = technology_enable(technology);
1561 enabled_tech_count++;
1566 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1567 (err == -EINVAL && enabled_tech_count == 0)) {
1568 connman_technology_save_offlinemode();
1569 __connman_notifier_offlinemode(offlinemode);
1571 global_offlinemode = connman_technology_load_offlinemode();
1576 void __connman_technology_set_connected(enum connman_service_type type,
1579 struct connman_technology *technology;
1582 technology = technology_find(type);
1586 DBG("technology %p connected %d", technology, connected);
1588 technology->connected = connected;
1591 connman_dbus_property_changed_basic(technology->path,
1592 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1593 DBUS_TYPE_BOOLEAN, &val);
1596 static bool technology_apply_rfkill_change(struct connman_technology *technology,
1601 bool hardblock_changed = false;
1603 GList *start, *list;
1605 DBG("technology %p --> %d/%d vs %d/%d",
1606 technology, softblock, hardblock,
1607 technology->softblocked, technology->hardblocked);
1609 if (technology->hardblocked == hardblock)
1610 goto softblock_change;
1612 if (!(new_rfkill && !hardblock)) {
1613 start = g_hash_table_get_values(rfkill_list);
1615 for (list = start; list; list = list->next) {
1616 struct connman_rfkill *rfkill = list->data;
1618 if (rfkill->type != technology->type)
1621 if (rfkill->hardblock != hardblock)
1629 goto softblock_change;
1631 technology->hardblocked = hardblock;
1632 hardblock_changed = true;
1635 if (!apply && technology->softblocked != softblock)
1639 return technology->hardblocked;
1641 technology->softblocked = softblock;
1643 if (technology->hardblocked ||
1644 technology->softblocked) {
1645 if (technology_disabled(technology) != -EALREADY)
1646 technology_affect_devices(technology, false);
1647 } else if (!technology->hardblocked &&
1648 !technology->softblocked) {
1649 if (technology_enabled(technology) != -EALREADY)
1650 technology_affect_devices(technology, true);
1653 if (hardblock_changed) {
1654 if (technology->hardblocked) {
1655 DBG("%s is switched off.", get_name(technology->type));
1656 technology_dbus_unregister(technology);
1658 DBG("%s is switched on.", get_name(technology->type));
1659 technology_dbus_register(technology);
1661 if (global_offlinemode)
1662 __connman_rfkill_block(technology->type, true);
1666 return technology->hardblocked;
1669 int __connman_technology_add_rfkill(unsigned int index,
1670 enum connman_service_type type,
1674 struct connman_technology *technology;
1675 struct connman_rfkill *rfkill;
1677 DBG("index %u type %d soft %u hard %u", index, type,
1678 softblock, hardblock);
1680 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1684 rfkill = g_try_new0(struct connman_rfkill, 1);
1688 rfkill->index = index;
1689 rfkill->type = type;
1690 rfkill->softblock = softblock;
1691 rfkill->hardblock = hardblock;
1693 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1696 technology = technology_get(type);
1697 /* If there is no driver for this type, ignore it. */
1701 technology->rfkill_driven = true;
1703 /* If hardblocked, there is no need to handle softblocked state */
1704 if (technology_apply_rfkill_change(technology,
1705 softblock, hardblock, true))
1708 if (global_offlinemode)
1712 * Depending on softblocked state we unblock/block according to
1713 * offlinemode and persistente state.
1715 if (technology->softblocked &&
1716 technology->enable_persistent)
1717 return __connman_rfkill_block(type, false);
1718 else if (!technology->softblocked &&
1719 !technology->enable_persistent)
1720 return __connman_rfkill_block(type, true);
1725 int __connman_technology_update_rfkill(unsigned int index,
1726 enum connman_service_type type,
1730 struct connman_technology *technology;
1731 struct connman_rfkill *rfkill;
1733 DBG("index %u soft %u hard %u", index, softblock, hardblock);
1735 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1739 if (rfkill->softblock == softblock &&
1740 rfkill->hardblock == hardblock)
1743 rfkill->softblock = softblock;
1744 rfkill->hardblock = hardblock;
1746 technology = technology_find(type);
1747 /* If there is no driver for this type, ignore it. */
1751 technology_apply_rfkill_change(technology, softblock, hardblock,
1754 if (technology->hardblocked)
1755 DBG("%s hardblocked", get_name(technology->type));
1757 DBG("%s is%s softblocked", get_name(technology->type),
1758 technology->softblocked ? "" : " not");
1763 int __connman_technology_remove_rfkill(unsigned int index,
1764 enum connman_service_type type)
1766 struct connman_technology *technology;
1767 struct connman_rfkill *rfkill;
1769 DBG("index %u", index);
1771 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1775 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
1777 technology = technology_find(type);
1781 technology_apply_rfkill_change(technology,
1782 technology->softblocked, !technology->hardblocked, false);
1784 technology_put(technology);
1789 int __connman_technology_init(void)
1793 connection = connman_dbus_get_connection();
1795 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1798 global_offlinemode = connman_technology_load_offlinemode();
1800 /* This will create settings file if it is missing */
1801 connman_technology_save_offlinemode();
1806 void __connman_technology_cleanup(void)
1810 g_hash_table_destroy(rfkill_list);
1812 dbus_connection_unref(connection);