5 * Copyright (C) 2007-2012 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
34 static DBusConnection *connection;
36 static GSList *technology_list = NULL;
39 * List of devices with no technology associated with them either because of
40 * no compiled in support or the driver is not yet loaded.
42 static GSList *techless_device_list = NULL;
43 static GHashTable *rfkill_list;
45 static connman_bool_t global_offlinemode;
47 struct connman_rfkill {
49 enum connman_service_type type;
50 connman_bool_t softblock;
51 connman_bool_t hardblock;
54 struct connman_technology {
56 enum connman_service_type type;
59 connman_bool_t enabled;
61 connman_bool_t connected;
63 connman_bool_t tethering;
64 connman_bool_t tethering_persistent; /* Tells the save status, needed
65 * as offline mode might set
68 char *tethering_ident;
69 char *tethering_passphrase;
70 bool tethering_hidden;
72 connman_bool_t enable_persistent; /* Save the tech state */
76 DBusMessage *pending_reply;
77 guint pending_timeout;
81 connman_bool_t rfkill_driven;
82 connman_bool_t softblocked;
83 connman_bool_t hardblocked;
84 connman_bool_t dbus_registered;
87 static GSList *driver_list = NULL;
89 static gint compare_priority(gconstpointer a, gconstpointer b)
91 const struct connman_technology_driver *driver1 = a;
92 const struct connman_technology_driver *driver2 = b;
94 return driver2->priority - driver1->priority;
97 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
99 struct connman_rfkill *rfkill = value;
100 enum connman_service_type type = GPOINTER_TO_INT(user_data);
102 /* Calling _technology_rfkill_add will update the tech. */
103 if (rfkill->type == type)
104 __connman_technology_add_rfkill(rfkill->index, type,
105 rfkill->softblock, rfkill->hardblock);
109 connman_technology_is_tethering_allowed(enum connman_service_type type)
111 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
113 const char *type_str = __connman_service_type2string(type);
117 if (type_str == NULL)
120 allowed = connman_setting_get_string_list("TetheringTechnologies");
122 allowed = allowed_default;
124 for (i = 0; allowed[i] != NULL; i++) {
125 if (g_strcmp0(allowed[i], type_str) == 0)
133 * connman_technology_driver_register:
134 * @driver: Technology driver definition
136 * Register a new technology driver
138 * Returns: %0 on success
140 int connman_technology_driver_register(struct connman_technology_driver *driver)
143 struct connman_device *device;
144 enum connman_service_type type;
146 DBG("Registering %s driver", driver->name);
148 driver_list = g_slist_insert_sorted(driver_list, driver,
152 * Check for technology less devices if this driver
153 * can service any of them.
155 for (list = techless_device_list; list != NULL; list = list->next) {
158 type = __connman_device_get_service_type(device);
159 if (type != driver->type)
162 techless_device_list = g_slist_remove(techless_device_list,
165 __connman_technology_add_device(device);
168 /* Check for orphaned rfkill switches. */
169 g_hash_table_foreach(rfkill_list, rfkill_check,
170 GINT_TO_POINTER(driver->type));
176 * connman_technology_driver_unregister:
177 * @driver: Technology driver definition
179 * Remove a previously registered technology driver
181 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
183 GSList *list, *tech_drivers;
184 struct connman_technology *technology;
185 struct connman_technology_driver *current;
187 DBG("Unregistering driver %p name %s", driver, driver->name);
189 for (list = technology_list; list; list = list->next) {
190 technology = list->data;
192 for (tech_drivers = technology->driver_list;
193 tech_drivers != NULL;
194 tech_drivers = g_slist_next(tech_drivers)) {
196 current = tech_drivers->data;
197 if (driver != current)
200 if (driver->remove != NULL)
201 driver->remove(technology);
203 technology->driver_list =
204 g_slist_remove(technology->driver_list, driver);
210 driver_list = g_slist_remove(driver_list, driver);
213 static const char *get_name(enum connman_service_type type)
216 case CONNMAN_SERVICE_TYPE_UNKNOWN:
217 case CONNMAN_SERVICE_TYPE_SYSTEM:
218 case CONNMAN_SERVICE_TYPE_GPS:
219 case CONNMAN_SERVICE_TYPE_VPN:
220 case CONNMAN_SERVICE_TYPE_GADGET:
222 case CONNMAN_SERVICE_TYPE_ETHERNET:
224 case CONNMAN_SERVICE_TYPE_WIFI:
226 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
228 case CONNMAN_SERVICE_TYPE_CELLULAR:
235 static void technology_save(struct connman_technology *technology)
240 DBG("technology %p", technology);
242 keyfile = __connman_storage_load_global();
244 keyfile = g_key_file_new();
246 identifier = g_strdup_printf("%s", get_name(technology->type));
247 if (identifier == NULL)
250 g_key_file_set_boolean(keyfile, identifier, "Enable",
251 technology->enable_persistent);
253 g_key_file_set_boolean(keyfile, identifier, "Tethering",
254 technology->tethering_persistent);
256 if (technology->tethering_ident != NULL)
257 g_key_file_set_string(keyfile, identifier,
258 "Tethering.Identifier",
259 technology->tethering_ident);
261 if (technology->tethering_passphrase != NULL)
262 g_key_file_set_string(keyfile, identifier,
263 "Tethering.Passphrase",
264 technology->tethering_passphrase);
269 __connman_storage_save_global(keyfile);
271 g_key_file_free(keyfile);
276 static void tethering_changed(struct connman_technology *technology)
278 connman_bool_t tethering = technology->tethering;
280 connman_dbus_property_changed_basic(technology->path,
281 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
282 DBUS_TYPE_BOOLEAN, &tethering);
284 technology_save(technology);
287 void connman_technology_tethering_notify(struct connman_technology *technology,
288 connman_bool_t enabled)
292 DBG("technology %p enabled %u", technology, enabled);
294 if (technology->tethering == enabled)
297 technology->tethering = enabled;
299 tethering_changed(technology);
302 __connman_tethering_set_enabled();
304 for (list = technology_list; list; list = list->next) {
305 struct connman_technology *other_tech = list->data;
306 if (other_tech->tethering == TRUE)
310 __connman_tethering_set_disabled();
314 static int set_tethering(struct connman_technology *technology,
315 connman_bool_t enabled)
317 int result = -EOPNOTSUPP;
319 const char *ident, *passphrase, *bridge;
320 GSList *tech_drivers;
323 ident = technology->tethering_ident;
324 passphrase = technology->tethering_passphrase;
325 hidden = technology->tethering_hidden;
327 __sync_synchronize();
328 if (technology->enabled == FALSE)
331 bridge = __connman_tethering_get_bridge();
335 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && ident == NULL)
338 for (tech_drivers = technology->driver_list; tech_drivers != NULL;
339 tech_drivers = g_slist_next(tech_drivers)) {
340 struct connman_technology_driver *driver = tech_drivers->data;
342 if (driver == NULL || driver->set_tethering == NULL)
345 err = driver->set_tethering(technology, ident, passphrase,
346 bridge, enabled, hidden);
348 if (result == -EINPROGRESS)
351 if (err == -EINPROGRESS || err == 0) {
360 void connman_technology_regdom_notify(struct connman_technology *technology,
366 connman_error("Failed to set regulatory domain");
368 DBG("Regulatory domain set to %s", alpha2);
370 g_free(technology->regdom);
371 technology->regdom = g_strdup(alpha2);
374 static int set_regdom_by_device(struct connman_technology *technology,
379 for (list = technology->device_list; list; list = list->next) {
380 struct connman_device *device = list->data;
382 if (connman_device_set_regdom(device, alpha2) != 0)
389 int connman_technology_set_regdom(const char *alpha2)
391 GSList *list, *tech_drivers;
393 for (list = technology_list; list; list = list->next) {
394 struct connman_technology *technology = list->data;
396 if (set_regdom_by_device(technology, alpha2) != 0) {
398 for (tech_drivers = technology->driver_list;
399 tech_drivers != NULL;
400 tech_drivers = g_slist_next(tech_drivers)) {
402 struct connman_technology_driver *driver =
405 if (driver->set_regdom != NULL)
406 driver->set_regdom(technology, alpha2);
414 static struct connman_technology *technology_find(enum connman_service_type type)
418 DBG("type %d", type);
420 for (list = technology_list; list; list = list->next) {
421 struct connman_technology *technology = list->data;
423 if (technology->type == type)
430 connman_bool_t connman_technology_get_wifi_tethering(const char **ssid,
433 struct connman_technology *technology;
435 if (ssid == NULL || psk == NULL)
440 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
441 if (technology == NULL)
444 if (technology->tethering == FALSE)
447 *ssid = technology->tethering_ident;
448 *psk = technology->tethering_passphrase;
453 static void free_rfkill(gpointer data)
455 struct connman_rfkill *rfkill = data;
460 static void technology_load(struct connman_technology *technology)
464 GError *error = NULL;
465 connman_bool_t enable, need_saving = FALSE;
467 DBG("technology %p", technology);
469 keyfile = __connman_storage_load_global();
470 /* Fallback on disabling technology if file not found. */
471 if (keyfile == NULL) {
472 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
473 /* We enable ethernet by default */
474 technology->enable_persistent = TRUE;
476 technology->enable_persistent = FALSE;
480 identifier = g_strdup_printf("%s", get_name(technology->type));
481 if (identifier == NULL)
484 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
486 technology->enable_persistent = enable;
488 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
489 technology->enable_persistent = TRUE;
491 technology->enable_persistent = FALSE;
494 g_clear_error(&error);
497 enable = g_key_file_get_boolean(keyfile, identifier,
498 "Tethering", &error);
500 technology->tethering_persistent = enable;
503 g_clear_error(&error);
506 if (need_saving == TRUE)
507 technology_save(technology);
509 technology->tethering_ident = g_key_file_get_string(keyfile,
510 identifier, "Tethering.Identifier", NULL);
512 technology->tethering_passphrase = g_key_file_get_string(keyfile,
513 identifier, "Tethering.Passphrase", NULL);
517 g_key_file_free(keyfile);
522 connman_bool_t __connman_technology_get_offlinemode(void)
524 return global_offlinemode;
527 static void connman_technology_save_offlinemode()
531 keyfile = __connman_storage_load_global();
533 keyfile = g_key_file_new();
535 g_key_file_set_boolean(keyfile, "global",
536 "OfflineMode", global_offlinemode);
538 __connman_storage_save_global(keyfile);
540 g_key_file_free(keyfile);
545 static connman_bool_t connman_technology_load_offlinemode()
548 GError *error = NULL;
549 connman_bool_t offlinemode;
551 /* If there is a error, we enable offlinemode */
552 keyfile = __connman_storage_load_global();
556 offlinemode = g_key_file_get_boolean(keyfile, "global",
557 "OfflineMode", &error);
560 g_clear_error(&error);
563 g_key_file_free(keyfile);
568 static void append_properties(DBusMessageIter *iter,
569 struct connman_technology *technology)
571 DBusMessageIter dict;
574 connman_dbus_dict_open(iter, &dict);
576 str = get_name(technology->type);
578 connman_dbus_dict_append_basic(&dict, "Name",
579 DBUS_TYPE_STRING, &str);
581 str = __connman_service_type2string(technology->type);
583 connman_dbus_dict_append_basic(&dict, "Type",
584 DBUS_TYPE_STRING, &str);
586 __sync_synchronize();
587 connman_dbus_dict_append_basic(&dict, "Powered",
589 &technology->enabled);
591 connman_dbus_dict_append_basic(&dict, "Connected",
593 &technology->connected);
595 connman_dbus_dict_append_basic(&dict, "Tethering",
597 &technology->tethering);
599 if (technology->tethering_ident != NULL)
600 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
602 &technology->tethering_ident);
604 if (technology->tethering_passphrase != NULL)
605 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
607 &technology->tethering_passphrase);
609 connman_dbus_dict_append_basic(&dict, "Hidden",
611 &technology->tethering_hidden);
613 connman_dbus_dict_close(iter, &dict);
616 static void technology_added_signal(struct connman_technology *technology)
619 DBusMessageIter iter;
621 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
622 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
626 dbus_message_iter_init_append(signal, &iter);
627 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
629 append_properties(&iter, technology);
631 dbus_connection_send(connection, signal, NULL);
632 dbus_message_unref(signal);
635 static void technology_removed_signal(struct connman_technology *technology)
637 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
638 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
639 DBUS_TYPE_OBJECT_PATH, &technology->path,
643 static DBusMessage *get_properties(DBusConnection *conn,
644 DBusMessage *message, void *user_data)
646 struct connman_technology *technology = user_data;
648 DBusMessageIter iter;
650 reply = dbus_message_new_method_return(message);
654 dbus_message_iter_init_append(reply, &iter);
655 append_properties(&iter, technology);
660 void __connman_technology_list_struct(DBusMessageIter *array)
663 DBusMessageIter entry;
665 for (list = technology_list; list; list = list->next) {
666 struct connman_technology *technology = list->data;
668 if (technology->path == NULL ||
669 (technology->rfkill_driven == TRUE &&
670 technology->hardblocked == TRUE))
673 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
675 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
677 append_properties(&entry, technology);
678 dbus_message_iter_close_container(array, &entry);
682 static gboolean technology_pending_reply(gpointer user_data)
684 struct connman_technology *technology = user_data;
687 /* Power request timedout, send ETIMEDOUT. */
688 if (technology->pending_reply != NULL) {
689 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
691 g_dbus_send_message(connection, reply);
693 dbus_message_unref(technology->pending_reply);
694 technology->pending_reply = NULL;
695 technology->pending_timeout = 0;
701 static int technology_affect_devices(struct connman_technology *technology,
702 connman_bool_t enable_device)
707 for (list = technology->device_list; list; list = list->next) {
708 struct connman_device *device = list->data;
710 if (enable_device == TRUE)
711 err = __connman_device_enable(device);
713 err = __connman_device_disable(device);
719 static int technology_enable(struct connman_technology *technology)
724 DBG("technology %p enable", technology);
726 __sync_synchronize();
727 if (technology->enabled == TRUE)
730 if (technology->pending_reply != NULL)
733 if (connman_setting_get_bool("PersistentTetheringMode") == TRUE &&
734 technology->tethering == TRUE)
735 set_tethering(technology, TRUE);
737 if (technology->rfkill_driven == TRUE)
738 err = __connman_rfkill_block(technology->type, FALSE);
740 err_dev = technology_affect_devices(technology, TRUE);
742 if (technology->rfkill_driven == FALSE)
748 static int technology_disable(struct connman_technology *technology)
752 DBG("technology %p disable", technology);
754 __sync_synchronize();
755 if (technology->enabled == FALSE)
758 if (technology->pending_reply != NULL)
761 if (technology->tethering == TRUE)
762 set_tethering(technology, FALSE);
764 err = technology_affect_devices(technology, FALSE);
766 if (technology->rfkill_driven == TRUE)
767 err = __connman_rfkill_block(technology->type, TRUE);
772 static DBusMessage *set_powered(struct connman_technology *technology,
773 DBusMessage *msg, connman_bool_t powered)
775 DBusMessage *reply = NULL;
778 if (technology->rfkill_driven && technology->hardblocked == TRUE) {
784 err = technology_enable(technology);
786 err = technology_disable(technology);
789 technology->enable_persistent = powered;
790 technology_save(technology);
794 if (err == -EINPROGRESS) {
795 technology->pending_reply = dbus_message_ref(msg);
796 technology->pending_timeout = g_timeout_add_seconds(10,
797 technology_pending_reply, technology);
798 } else if (err == -EALREADY) {
800 reply = __connman_error_already_enabled(msg);
802 reply = __connman_error_already_disabled(msg);
804 reply = __connman_error_failed(msg, -err);
806 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
811 static DBusMessage *set_property(DBusConnection *conn,
812 DBusMessage *msg, void *data)
814 struct connman_technology *technology = data;
815 DBusMessageIter iter, value;
819 DBG("conn %p", conn);
821 if (dbus_message_iter_init(msg, &iter) == FALSE)
822 return __connman_error_invalid_arguments(msg);
824 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
825 return __connman_error_invalid_arguments(msg);
827 dbus_message_iter_get_basic(&iter, &name);
828 dbus_message_iter_next(&iter);
830 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
831 return __connman_error_invalid_arguments(msg);
833 dbus_message_iter_recurse(&iter, &value);
835 type = dbus_message_iter_get_arg_type(&value);
837 DBG("property %s", name);
839 if (g_str_equal(name, "Tethering") == TRUE) {
841 connman_bool_t tethering;
843 if (type != DBUS_TYPE_BOOLEAN)
844 return __connman_error_invalid_arguments(msg);
846 if (connman_technology_is_tethering_allowed(technology->type)
848 DBG("%s tethering not allowed by config file",
849 __connman_service_type2string(technology->type));
850 return __connman_error_not_supported(msg);
853 dbus_message_iter_get_basic(&value, &tethering);
855 if (technology->tethering == tethering) {
856 if (tethering == FALSE)
857 return __connman_error_already_disabled(msg);
859 return __connman_error_already_enabled(msg);
862 err = set_tethering(technology, tethering);
864 return __connman_error_failed(msg, -err);
866 technology->tethering_persistent = tethering;
868 technology_save(technology);
870 } else if (g_str_equal(name, "TetheringIdentifier") == TRUE) {
873 dbus_message_iter_get_basic(&value, &str);
875 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
876 return __connman_error_not_supported(msg);
878 if (strlen(str) < 1 || strlen(str) > 32)
879 return __connman_error_invalid_arguments(msg);
881 if (g_strcmp0(technology->tethering_ident, str) != 0) {
882 g_free(technology->tethering_ident);
883 technology->tethering_ident = g_strdup(str);
884 technology_save(technology);
886 connman_dbus_property_changed_basic(technology->path,
887 CONNMAN_TECHNOLOGY_INTERFACE,
888 "TetheringIdentifier",
890 &technology->tethering_ident);
892 } else if (g_str_equal(name, "TetheringPassphrase") == TRUE) {
895 dbus_message_iter_get_basic(&value, &str);
897 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
898 return __connman_error_not_supported(msg);
900 if (strlen(str) < 8 || strlen(str) > 63) {
901 if (g_str_equal(str, ""))
902 technology->tethering_passphrase = NULL;
904 return __connman_error_passphrase_required(msg);
906 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
907 g_free(technology->tethering_passphrase);
908 technology->tethering_passphrase = g_strdup(str);
909 technology_save(technology);
911 connman_dbus_property_changed_basic(technology->path,
912 CONNMAN_TECHNOLOGY_INTERFACE,
913 "TetheringPassphrase",
915 &technology->tethering_passphrase);
918 } else if (g_str_equal(name, "Hidden") == TRUE) {
921 if (type != DBUS_TYPE_BOOLEAN)
922 return __connman_error_invalid_arguments(msg);
924 dbus_message_iter_get_basic(&value, &hidden);
926 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
927 return __connman_error_not_supported(msg);
929 technology->tethering_hidden = hidden;
930 } else if (g_str_equal(name, "Powered") == TRUE) {
931 connman_bool_t enable;
933 if (type != DBUS_TYPE_BOOLEAN)
934 return __connman_error_invalid_arguments(msg);
936 dbus_message_iter_get_basic(&value, &enable);
938 return set_powered(technology, msg, enable);
940 return __connman_error_invalid_property(msg);
942 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
945 static void reply_scan_pending(struct connman_technology *technology, int err)
949 DBG("technology %p err %d", technology, err);
951 while (technology->scan_pending != NULL) {
952 DBusMessage *msg = technology->scan_pending->data;
954 DBG("reply to %s", dbus_message_get_sender(msg));
957 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
959 reply = __connman_error_failed(msg, -err);
960 g_dbus_send_message(connection, reply);
961 dbus_message_unref(msg);
963 technology->scan_pending =
964 g_slist_delete_link(technology->scan_pending,
965 technology->scan_pending);
969 void __connman_technology_scan_started(struct connman_device *device)
971 DBG("device %p", device);
974 void __connman_technology_scan_stopped(struct connman_device *device)
977 struct connman_technology *technology;
978 enum connman_service_type type;
981 type = __connman_device_get_service_type(device);
982 technology = technology_find(type);
984 DBG("technology %p device %p", technology, device);
986 if (technology == NULL)
989 for (list = technology->device_list; list != NULL; list = list->next) {
990 struct connman_device *other_device = list->data;
992 if (device == other_device)
995 if (__connman_device_get_service_type(other_device) != type)
998 if (connman_device_get_scanning(other_device) == TRUE)
1003 reply_scan_pending(technology, 0);
1006 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1007 int result, const char *alpha2)
1009 connman_bool_t regdom_set = FALSE;
1010 struct connman_technology *technology;
1011 enum connman_service_type type;
1012 GSList *tech_drivers;
1014 type = __connman_device_get_service_type(device);
1015 technology = technology_find(type);
1017 if (technology == NULL)
1022 for (tech_drivers = technology->driver_list;
1023 tech_drivers != NULL;
1024 tech_drivers = g_slist_next(tech_drivers)) {
1025 struct connman_technology_driver *driver =
1028 if (driver->set_regdom != NULL) {
1029 driver->set_regdom(technology, alpha2);
1035 if (regdom_set == FALSE)
1039 connman_technology_regdom_notify(technology, alpha2);
1042 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1044 struct connman_technology *technology = data;
1047 DBG ("technology %p request from %s", technology,
1048 dbus_message_get_sender(msg));
1050 dbus_message_ref(msg);
1051 technology->scan_pending =
1052 g_slist_prepend(technology->scan_pending, msg);
1054 err = __connman_device_request_scan(technology->type);
1056 reply_scan_pending(technology, err);
1061 static const GDBusMethodTable technology_methods[] = {
1062 { GDBUS_DEPRECATED_METHOD("GetProperties",
1063 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1065 { GDBUS_ASYNC_METHOD("SetProperty",
1066 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1067 NULL, set_property) },
1068 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1072 static const GDBusSignalTable technology_signals[] = {
1073 { GDBUS_SIGNAL("PropertyChanged",
1074 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1075 { GDBUS_SIGNAL("DhcpConnected",
1076 GDBUS_ARGS({ "aptype", "s" },
1079 { "hostname", "s" })) },
1080 { GDBUS_SIGNAL("DhcpLeaseDeleted",
1081 GDBUS_ARGS({ "aptype", "s" },
1084 { "hostname", "s" })) },
1088 static gboolean technology_dbus_register(struct connman_technology *technology)
1090 if (technology->dbus_registered == TRUE ||
1091 (technology->rfkill_driven == TRUE &&
1092 technology->hardblocked == TRUE))
1095 if (g_dbus_register_interface(connection, technology->path,
1096 CONNMAN_TECHNOLOGY_INTERFACE,
1097 technology_methods, technology_signals,
1098 NULL, technology, NULL) == FALSE) {
1099 connman_error("Failed to register %s", technology->path);
1103 technology_added_signal(technology);
1104 technology->dbus_registered = TRUE;
1109 static struct connman_technology *technology_get(enum connman_service_type type)
1111 GSList *tech_drivers = NULL;
1112 struct connman_technology_driver *driver;
1113 struct connman_technology *technology;
1117 DBG("type %d", type);
1119 str = __connman_service_type2string(type);
1123 technology = technology_find(type);
1124 if (technology != NULL) {
1125 __sync_fetch_and_add(&technology->refcount, 1);
1129 /* First check if we have a driver for this technology type */
1130 for (list = driver_list; list; list = list->next) {
1131 driver = list->data;
1133 if (driver->type == type) {
1134 DBG("technology %p driver %p", technology, driver);
1135 tech_drivers = g_slist_append(tech_drivers, driver);
1139 if (tech_drivers == NULL) {
1140 DBG("No matching drivers found for %s.",
1141 __connman_service_type2string(type));
1145 technology = g_try_new0(struct connman_technology, 1);
1146 if (technology == NULL)
1149 technology->refcount = 1;
1151 technology->rfkill_driven = FALSE;
1152 technology->softblocked = FALSE;
1153 technology->hardblocked = FALSE;
1154 technology->tethering_hidden = false;
1156 technology->type = type;
1157 technology->path = g_strdup_printf("%s/technology/%s",
1160 technology->device_list = NULL;
1162 technology->pending_reply = NULL;
1164 technology_load(technology);
1166 if (technology_dbus_register(technology) == FALSE) {
1171 technology_list = g_slist_prepend(technology_list, technology);
1173 technology->driver_list = tech_drivers;
1175 for (list = tech_drivers; list != NULL; list = g_slist_next(list)) {
1176 driver = list->data;
1178 if (driver->probe != NULL && driver->probe(technology) < 0)
1179 DBG("Driver probe failed for technology %p",
1183 DBG("technology %p", technology);
1188 static void technology_dbus_unregister(struct connman_technology *technology)
1190 if (technology->dbus_registered == FALSE)
1193 technology_removed_signal(technology);
1194 g_dbus_unregister_interface(connection, technology->path,
1195 CONNMAN_TECHNOLOGY_INTERFACE);
1197 technology->dbus_registered = FALSE;
1200 static void technology_put(struct connman_technology *technology)
1202 DBG("technology %p", technology);
1204 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1207 reply_scan_pending(technology, -EINTR);
1209 while (technology->driver_list != NULL) {
1210 struct connman_technology_driver *driver;
1212 driver = technology->driver_list->data;
1214 if (driver->remove != NULL)
1215 driver->remove(technology);
1217 technology->driver_list =
1218 g_slist_delete_link(technology->driver_list,
1219 technology->driver_list);
1222 technology_list = g_slist_remove(technology_list, technology);
1224 technology_dbus_unregister(technology);
1226 g_slist_free(technology->device_list);
1228 g_free(technology->path);
1229 g_free(technology->regdom);
1230 g_free(technology->tethering_ident);
1231 g_free(technology->tethering_passphrase);
1235 static void enable_tethering(struct connman_technology *technology)
1239 if (connman_setting_get_bool("PersistentTetheringMode") == FALSE)
1242 ret = set_tethering(technology, TRUE);
1243 if (ret < 0 && ret != -EALREADY)
1244 DBG("Cannot enable tethering yet for %s (%d/%s)",
1245 get_name(technology->type),
1246 -ret, strerror(-ret));
1249 void __connman_technology_add_interface(enum connman_service_type type,
1250 int index, const char *name, const char *ident)
1252 struct connman_technology *technology;
1253 GSList *tech_drivers;
1254 struct connman_technology_driver *driver;
1257 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1258 case CONNMAN_SERVICE_TYPE_SYSTEM:
1260 case CONNMAN_SERVICE_TYPE_ETHERNET:
1261 case CONNMAN_SERVICE_TYPE_WIFI:
1262 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1263 case CONNMAN_SERVICE_TYPE_CELLULAR:
1264 case CONNMAN_SERVICE_TYPE_GPS:
1265 case CONNMAN_SERVICE_TYPE_VPN:
1266 case CONNMAN_SERVICE_TYPE_GADGET:
1270 connman_info("Adding interface %s [ %s ]", name,
1271 __connman_service_type2string(type));
1273 technology = technology_find(type);
1275 if (technology == NULL)
1278 for (tech_drivers = technology->driver_list; tech_drivers != NULL;
1279 tech_drivers = g_slist_next(tech_drivers)) {
1280 driver = tech_drivers->data;
1282 if(driver->add_interface != NULL)
1283 driver->add_interface(technology, index, name, ident);
1287 * At this point we can try to enable tethering automatically as
1288 * now the interfaces are set properly.
1290 if (technology->tethering_persistent == TRUE)
1291 enable_tethering(technology);
1294 void __connman_technology_remove_interface(enum connman_service_type type,
1295 int index, const char *name, const char *ident)
1297 struct connman_technology *technology;
1298 GSList *tech_drivers;
1299 struct connman_technology_driver *driver;
1302 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1303 case CONNMAN_SERVICE_TYPE_SYSTEM:
1305 case CONNMAN_SERVICE_TYPE_ETHERNET:
1306 case CONNMAN_SERVICE_TYPE_WIFI:
1307 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1308 case CONNMAN_SERVICE_TYPE_CELLULAR:
1309 case CONNMAN_SERVICE_TYPE_GPS:
1310 case CONNMAN_SERVICE_TYPE_VPN:
1311 case CONNMAN_SERVICE_TYPE_GADGET:
1315 connman_info("Remove interface %s [ %s ]", name,
1316 __connman_service_type2string(type));
1318 technology = technology_find(type);
1320 if (technology == NULL)
1323 for (tech_drivers = technology->driver_list; tech_drivers != NULL;
1324 tech_drivers = g_slist_next(tech_drivers)) {
1325 driver = tech_drivers->data;
1327 if(driver->remove_interface != NULL)
1328 driver->remove_interface(technology, index);
1332 int __connman_technology_add_device(struct connman_device *device)
1334 struct connman_technology *technology;
1335 enum connman_service_type type;
1337 type = __connman_device_get_service_type(device);
1339 DBG("device %p type %s", device, get_name(type));
1341 technology = technology_get(type);
1342 if (technology == NULL) {
1344 * Since no driver can be found for this device at the moment we
1345 * add it to the techless device list.
1347 techless_device_list = g_slist_prepend(techless_device_list,
1353 __sync_synchronize();
1354 if (technology->rfkill_driven == TRUE) {
1355 if (technology->enabled == TRUE)
1356 __connman_device_enable(device);
1358 __connman_device_disable(device);
1363 if (technology->enable_persistent == TRUE &&
1364 global_offlinemode == FALSE) {
1365 int err = __connman_device_enable(device);
1367 * connman_technology_add_device() calls __connman_device_enable()
1368 * but since the device is already enabled, the calls does not
1369 * propagate through to connman_technology_enabled via
1370 * connman_device_set_powered.
1372 if (err == -EALREADY)
1373 __connman_technology_enabled(type);
1375 /* if technology persistent state is offline */
1376 if (technology->enable_persistent == FALSE)
1377 __connman_device_disable(device);
1380 technology->device_list = g_slist_prepend(technology->device_list,
1386 int __connman_technology_remove_device(struct connman_device *device)
1388 struct connman_technology *technology;
1389 enum connman_service_type type;
1391 DBG("device %p", device);
1393 type = __connman_device_get_service_type(device);
1395 technology = technology_find(type);
1396 if (technology == NULL) {
1397 techless_device_list = g_slist_remove(techless_device_list,
1402 technology->device_list = g_slist_remove(technology->device_list,
1405 if (technology->tethering == TRUE)
1406 set_tethering(technology, FALSE);
1408 technology_put(technology);
1413 static void powered_changed(struct connman_technology *technology)
1415 if (technology->dbus_registered == FALSE)
1418 if (technology->pending_reply != NULL) {
1419 g_dbus_send_reply(connection,
1420 technology->pending_reply, DBUS_TYPE_INVALID);
1421 dbus_message_unref(technology->pending_reply);
1422 technology->pending_reply = NULL;
1424 g_source_remove(technology->pending_timeout);
1425 technology->pending_timeout = 0;
1428 __sync_synchronize();
1429 connman_dbus_property_changed_basic(technology->path,
1430 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
1431 DBUS_TYPE_BOOLEAN, &technology->enabled);
1434 static int technology_enabled(struct connman_technology *technology)
1436 __sync_synchronize();
1437 if (technology->enabled == TRUE)
1440 technology->enabled = TRUE;
1442 if (technology->tethering_persistent == TRUE)
1443 enable_tethering(technology);
1445 powered_changed(technology);
1450 int __connman_technology_enabled(enum connman_service_type type)
1452 struct connman_technology *technology;
1454 technology = technology_find(type);
1455 if (technology == NULL)
1458 DBG("technology %p type %s rfkill %d enabled %d", technology,
1459 get_name(type), technology->rfkill_driven,
1460 technology->enabled);
1462 if (technology->rfkill_driven == TRUE) {
1463 if (technology->tethering_persistent == TRUE)
1464 enable_tethering(technology);
1468 return technology_enabled(technology);
1471 static int technology_disabled(struct connman_technology *technology)
1473 __sync_synchronize();
1474 if (technology->enabled == FALSE)
1477 technology->enabled = FALSE;
1479 powered_changed(technology);
1484 int __connman_technology_disabled(enum connman_service_type type)
1486 struct connman_technology *technology;
1489 technology = technology_find(type);
1490 if (technology == NULL)
1493 if (technology->rfkill_driven == TRUE)
1496 for (list = technology->device_list; list != NULL; list = list->next) {
1497 struct connman_device *device = list->data;
1499 if (connman_device_get_powered(device) == TRUE)
1503 return technology_disabled(technology);
1506 int __connman_technology_set_offlinemode(connman_bool_t offlinemode)
1509 int err = -EINVAL, enabled_tech_count = 0;
1511 if (global_offlinemode == offlinemode)
1514 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1517 * This is a bit tricky. When you set offlinemode, there is no
1518 * way to differentiate between attempting offline mode and
1519 * resuming offlinemode from last saved profile. We need that
1520 * information in rfkill_update, otherwise it falls back on the
1521 * technology's persistent state. Hence we set the offline mode here
1522 * but save it & call the notifier only if its successful.
1525 global_offlinemode = offlinemode;
1527 /* Traverse technology list, enable/disable each technology. */
1528 for (list = technology_list; list; list = list->next) {
1529 struct connman_technology *technology = list->data;
1532 err = technology_disable(technology);
1534 if (technology->hardblocked)
1537 if (technology->enable_persistent) {
1538 err = technology_enable(technology);
1539 enabled_tech_count++;
1544 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1545 (err == -EINVAL && enabled_tech_count == 0)) {
1546 connman_technology_save_offlinemode();
1547 __connman_notifier_offlinemode(offlinemode);
1549 global_offlinemode = connman_technology_load_offlinemode();
1554 void __connman_technology_set_connected(enum connman_service_type type,
1555 connman_bool_t connected)
1557 struct connman_technology *technology;
1559 technology = technology_find(type);
1560 if (technology == NULL)
1563 DBG("technology %p connected %d", technology, connected);
1565 technology->connected = connected;
1567 connman_dbus_property_changed_basic(technology->path,
1568 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1569 DBUS_TYPE_BOOLEAN, &connected);
1572 static connman_bool_t technology_apply_rfkill_change(struct connman_technology *technology,
1573 connman_bool_t softblock,
1574 connman_bool_t hardblock,
1575 connman_bool_t new_rfkill)
1577 gboolean hardblock_changed = FALSE;
1578 gboolean apply = TRUE;
1579 GList *start, *list;
1581 DBG("technology %p --> %d/%d vs %d/%d",
1582 technology, softblock, hardblock,
1583 technology->softblocked, technology->hardblocked);
1585 if (technology->hardblocked == hardblock)
1586 goto softblock_change;
1588 if (!(new_rfkill == TRUE && hardblock == FALSE)) {
1589 start = g_hash_table_get_values(rfkill_list);
1591 for (list = start; list != NULL; list = list->next) {
1592 struct connman_rfkill *rfkill = list->data;
1594 if (rfkill->type != technology->type)
1597 if (rfkill->hardblock != hardblock)
1605 goto softblock_change;
1607 technology->hardblocked = hardblock;
1608 hardblock_changed = TRUE;
1611 if (apply == FALSE && technology->softblocked != softblock)
1615 return technology->hardblocked;
1617 technology->softblocked = softblock;
1619 if (technology->hardblocked == TRUE ||
1620 technology->softblocked == TRUE) {
1621 if (technology_disabled(technology) != -EALREADY)
1622 technology_affect_devices(technology, FALSE);
1623 } else if (technology->hardblocked == FALSE &&
1624 technology->softblocked == FALSE) {
1625 if (technology_enabled(technology) != -EALREADY)
1626 technology_affect_devices(technology, TRUE);
1629 if (hardblock_changed == TRUE) {
1630 if (technology->hardblocked == TRUE) {
1631 DBG("%s is switched off.", get_name(technology->type));
1632 technology_dbus_unregister(technology);
1634 DBG("%s is switched on.", get_name(technology->type));
1635 technology_dbus_register(technology);
1637 if (global_offlinemode)
1638 __connman_rfkill_block(technology->type, TRUE);
1642 return technology->hardblocked;
1645 int __connman_technology_add_rfkill(unsigned int index,
1646 enum connman_service_type type,
1647 connman_bool_t softblock,
1648 connman_bool_t hardblock)
1650 struct connman_technology *technology;
1651 struct connman_rfkill *rfkill;
1653 DBG("index %u type %d soft %u hard %u", index, type,
1654 softblock, hardblock);
1656 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1660 rfkill = g_try_new0(struct connman_rfkill, 1);
1664 rfkill->index = index;
1665 rfkill->type = type;
1666 rfkill->softblock = softblock;
1667 rfkill->hardblock = hardblock;
1669 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1672 technology = technology_get(type);
1673 /* If there is no driver for this type, ignore it. */
1674 if (technology == NULL)
1677 technology->rfkill_driven = TRUE;
1679 /* If hardblocked, there is no need to handle softblocked state */
1680 if (technology_apply_rfkill_change(technology,
1681 softblock, hardblock, TRUE) == TRUE)
1684 if (global_offlinemode)
1688 * Depending on softblocked state we unblock/block according to
1689 * offlinemode and persistente state.
1691 if (technology->softblocked == TRUE &&
1692 technology->enable_persistent == TRUE)
1693 return __connman_rfkill_block(type, FALSE);
1694 else if (technology->softblocked == FALSE &&
1695 technology->enable_persistent == FALSE)
1696 return __connman_rfkill_block(type, TRUE);
1701 int __connman_technology_update_rfkill(unsigned int index,
1702 enum connman_service_type type,
1703 connman_bool_t softblock,
1704 connman_bool_t hardblock)
1706 struct connman_technology *technology;
1707 struct connman_rfkill *rfkill;
1709 DBG("index %u soft %u hard %u", index, softblock, hardblock);
1711 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1715 if (rfkill->softblock == softblock &&
1716 rfkill->hardblock == hardblock)
1719 rfkill->softblock = softblock;
1720 rfkill->hardblock = hardblock;
1722 technology = technology_find(type);
1723 /* If there is no driver for this type, ignore it. */
1724 if (technology == NULL)
1727 technology_apply_rfkill_change(technology, softblock, hardblock,
1730 if (technology->hardblocked)
1731 DBG("%s hardblocked", get_name(technology->type));
1733 DBG("%s is%s softblocked", get_name(technology->type),
1734 technology->softblocked ? "" : " not");
1739 int __connman_technology_remove_rfkill(unsigned int index,
1740 enum connman_service_type type)
1742 struct connman_technology *technology;
1743 struct connman_rfkill *rfkill;
1745 DBG("index %u", index);
1747 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1751 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
1753 technology = technology_find(type);
1754 if (technology == NULL)
1757 technology_apply_rfkill_change(technology,
1758 technology->softblocked, !technology->hardblocked, FALSE);
1760 technology_put(technology);
1765 int __connman_technology_init(void)
1769 connection = connman_dbus_get_connection();
1771 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1774 global_offlinemode = connman_technology_load_offlinemode();
1776 /* This will create settings file if it is missing */
1777 connman_technology_save_offlinemode();
1782 void __connman_technology_cleanup(void)
1786 g_hash_table_destroy(rfkill_list);
1788 dbus_connection_unref(connection);