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:
221 case CONNMAN_SERVICE_TYPE_GADGET:
223 case CONNMAN_SERVICE_TYPE_ETHERNET:
225 case CONNMAN_SERVICE_TYPE_WIFI:
227 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
229 case CONNMAN_SERVICE_TYPE_CELLULAR:
236 static void technology_save(struct connman_technology *technology)
240 const char *name = get_name(technology->type);
242 DBG("technology %p type %d name %s", technology, technology->type,
247 keyfile = __connman_storage_load_global();
249 keyfile = g_key_file_new();
251 identifier = g_strdup_printf("%s", name);
252 if (identifier == NULL)
255 g_key_file_set_boolean(keyfile, identifier, "Enable",
256 technology->enable_persistent);
258 g_key_file_set_boolean(keyfile, identifier, "Tethering",
259 technology->tethering_persistent);
261 if (technology->tethering_ident != NULL)
262 g_key_file_set_string(keyfile, identifier,
263 "Tethering.Identifier",
264 technology->tethering_ident);
266 if (technology->tethering_passphrase != NULL)
267 g_key_file_set_string(keyfile, identifier,
268 "Tethering.Passphrase",
269 technology->tethering_passphrase);
274 __connman_storage_save_global(keyfile);
276 g_key_file_free(keyfile);
281 static void tethering_changed(struct connman_technology *technology)
283 connman_bool_t tethering = technology->tethering;
285 connman_dbus_property_changed_basic(technology->path,
286 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
287 DBUS_TYPE_BOOLEAN, &tethering);
289 technology_save(technology);
292 void connman_technology_tethering_notify(struct connman_technology *technology,
293 connman_bool_t enabled)
297 DBG("technology %p enabled %u", technology, enabled);
299 if (technology->tethering == enabled)
302 technology->tethering = enabled;
304 tethering_changed(technology);
307 __connman_tethering_set_enabled();
309 for (list = technology_list; list; list = list->next) {
310 struct connman_technology *other_tech = list->data;
311 if (other_tech->tethering == TRUE)
315 __connman_tethering_set_disabled();
319 static int set_tethering(struct connman_technology *technology,
320 connman_bool_t enabled)
322 int result = -EOPNOTSUPP;
324 const char *ident, *passphrase, *bridge;
325 GSList *tech_drivers;
328 ident = technology->tethering_ident;
329 passphrase = technology->tethering_passphrase;
330 hidden = technology->tethering_hidden;
332 __sync_synchronize();
333 if (technology->enabled == FALSE)
336 bridge = __connman_tethering_get_bridge();
340 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && ident == NULL)
343 for (tech_drivers = technology->driver_list; tech_drivers != NULL;
344 tech_drivers = g_slist_next(tech_drivers)) {
345 struct connman_technology_driver *driver = tech_drivers->data;
347 if (driver == NULL || driver->set_tethering == NULL)
350 err = driver->set_tethering(technology, ident, passphrase,
351 bridge, enabled, hidden);
353 if (result == -EINPROGRESS)
356 if (err == -EINPROGRESS || err == 0) {
365 void connman_technology_regdom_notify(struct connman_technology *technology,
371 connman_error("Failed to set regulatory domain");
373 DBG("Regulatory domain set to %s", alpha2);
375 g_free(technology->regdom);
376 technology->regdom = g_strdup(alpha2);
379 static int set_regdom_by_device(struct connman_technology *technology,
384 for (list = technology->device_list; list; list = list->next) {
385 struct connman_device *device = list->data;
387 if (connman_device_set_regdom(device, alpha2) != 0)
394 int connman_technology_set_regdom(const char *alpha2)
396 GSList *list, *tech_drivers;
398 for (list = technology_list; list; list = list->next) {
399 struct connman_technology *technology = list->data;
401 if (set_regdom_by_device(technology, alpha2) != 0) {
403 for (tech_drivers = technology->driver_list;
404 tech_drivers != NULL;
405 tech_drivers = g_slist_next(tech_drivers)) {
407 struct connman_technology_driver *driver =
410 if (driver->set_regdom != NULL)
411 driver->set_regdom(technology, alpha2);
419 static struct connman_technology *technology_find(enum connman_service_type type)
423 DBG("type %d", type);
425 for (list = technology_list; list; list = list->next) {
426 struct connman_technology *technology = list->data;
428 if (technology->type == type)
435 connman_bool_t connman_technology_get_wifi_tethering(const char **ssid,
438 struct connman_technology *technology;
440 if (ssid == NULL || psk == NULL)
445 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
446 if (technology == NULL)
449 if (technology->tethering == FALSE)
452 *ssid = technology->tethering_ident;
453 *psk = technology->tethering_passphrase;
458 static void free_rfkill(gpointer data)
460 struct connman_rfkill *rfkill = data;
465 static void technology_load(struct connman_technology *technology)
469 GError *error = NULL;
470 connman_bool_t enable, need_saving = FALSE;
472 DBG("technology %p", technology);
474 keyfile = __connman_storage_load_global();
475 /* Fallback on disabling technology if file not found. */
476 if (keyfile == NULL) {
477 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
478 /* We enable ethernet by default */
479 technology->enable_persistent = TRUE;
481 technology->enable_persistent = FALSE;
485 identifier = g_strdup_printf("%s", get_name(technology->type));
486 if (identifier == NULL)
489 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
491 technology->enable_persistent = enable;
493 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
494 technology->enable_persistent = TRUE;
496 technology->enable_persistent = FALSE;
499 g_clear_error(&error);
502 enable = g_key_file_get_boolean(keyfile, identifier,
503 "Tethering", &error);
505 technology->tethering_persistent = enable;
508 g_clear_error(&error);
511 if (need_saving == TRUE)
512 technology_save(technology);
514 technology->tethering_ident = g_key_file_get_string(keyfile,
515 identifier, "Tethering.Identifier", NULL);
517 technology->tethering_passphrase = g_key_file_get_string(keyfile,
518 identifier, "Tethering.Passphrase", NULL);
522 g_key_file_free(keyfile);
527 connman_bool_t __connman_technology_get_offlinemode(void)
529 return global_offlinemode;
532 static void connman_technology_save_offlinemode()
536 keyfile = __connman_storage_load_global();
538 keyfile = g_key_file_new();
540 g_key_file_set_boolean(keyfile, "global",
541 "OfflineMode", global_offlinemode);
543 __connman_storage_save_global(keyfile);
545 g_key_file_free(keyfile);
550 static connman_bool_t connman_technology_load_offlinemode()
553 GError *error = NULL;
554 connman_bool_t offlinemode;
556 /* If there is a error, we enable offlinemode */
557 keyfile = __connman_storage_load_global();
561 offlinemode = g_key_file_get_boolean(keyfile, "global",
562 "OfflineMode", &error);
565 g_clear_error(&error);
568 g_key_file_free(keyfile);
573 static void append_properties(DBusMessageIter *iter,
574 struct connman_technology *technology)
576 DBusMessageIter dict;
579 connman_dbus_dict_open(iter, &dict);
581 str = get_name(technology->type);
583 connman_dbus_dict_append_basic(&dict, "Name",
584 DBUS_TYPE_STRING, &str);
586 str = __connman_service_type2string(technology->type);
588 connman_dbus_dict_append_basic(&dict, "Type",
589 DBUS_TYPE_STRING, &str);
591 __sync_synchronize();
592 connman_dbus_dict_append_basic(&dict, "Powered",
594 &technology->enabled);
596 connman_dbus_dict_append_basic(&dict, "Connected",
598 &technology->connected);
600 connman_dbus_dict_append_basic(&dict, "Tethering",
602 &technology->tethering);
604 if (technology->tethering_ident != NULL)
605 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
607 &technology->tethering_ident);
609 if (technology->tethering_passphrase != NULL)
610 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
612 &technology->tethering_passphrase);
614 connman_dbus_dict_append_basic(&dict, "Hidden",
616 &technology->tethering_hidden);
618 connman_dbus_dict_close(iter, &dict);
621 static void technology_added_signal(struct connman_technology *technology)
624 DBusMessageIter iter;
626 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
627 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
631 dbus_message_iter_init_append(signal, &iter);
632 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
634 append_properties(&iter, technology);
636 dbus_connection_send(connection, signal, NULL);
637 dbus_message_unref(signal);
640 static void technology_removed_signal(struct connman_technology *technology)
642 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
643 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
644 DBUS_TYPE_OBJECT_PATH, &technology->path,
648 static DBusMessage *get_properties(DBusConnection *conn,
649 DBusMessage *message, void *user_data)
651 struct connman_technology *technology = user_data;
653 DBusMessageIter iter;
655 reply = dbus_message_new_method_return(message);
659 dbus_message_iter_init_append(reply, &iter);
660 append_properties(&iter, technology);
665 void __connman_technology_list_struct(DBusMessageIter *array)
668 DBusMessageIter entry;
670 for (list = technology_list; list; list = list->next) {
671 struct connman_technology *technology = list->data;
673 if (technology->path == NULL ||
674 (technology->rfkill_driven == TRUE &&
675 technology->hardblocked == TRUE))
678 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
680 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
682 append_properties(&entry, technology);
683 dbus_message_iter_close_container(array, &entry);
687 static gboolean technology_pending_reply(gpointer user_data)
689 struct connman_technology *technology = user_data;
692 /* Power request timedout, send ETIMEDOUT. */
693 if (technology->pending_reply != NULL) {
694 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
696 g_dbus_send_message(connection, reply);
698 dbus_message_unref(technology->pending_reply);
699 technology->pending_reply = NULL;
700 technology->pending_timeout = 0;
706 static int technology_affect_devices(struct connman_technology *technology,
707 connman_bool_t enable_device)
712 for (list = technology->device_list; list; list = list->next) {
713 struct connman_device *device = list->data;
715 if (enable_device == TRUE)
716 err = __connman_device_enable(device);
718 err = __connman_device_disable(device);
724 static int technology_enable(struct connman_technology *technology)
729 DBG("technology %p enable", technology);
731 __sync_synchronize();
732 if (technology->enabled == TRUE)
735 if (technology->pending_reply != NULL)
738 if (connman_setting_get_bool("PersistentTetheringMode") == TRUE &&
739 technology->tethering == TRUE)
740 set_tethering(technology, TRUE);
742 if (technology->rfkill_driven == TRUE)
743 err = __connman_rfkill_block(technology->type, FALSE);
745 err_dev = technology_affect_devices(technology, TRUE);
747 if (technology->rfkill_driven == FALSE)
753 static int technology_disable(struct connman_technology *technology)
757 DBG("technology %p disable", technology);
759 __sync_synchronize();
760 if (technology->enabled == FALSE)
763 if (technology->pending_reply != NULL)
766 if (technology->tethering == TRUE)
767 set_tethering(technology, FALSE);
769 err = technology_affect_devices(technology, FALSE);
771 if (technology->rfkill_driven == TRUE)
772 err = __connman_rfkill_block(technology->type, TRUE);
777 static DBusMessage *set_powered(struct connman_technology *technology,
778 DBusMessage *msg, connman_bool_t powered)
780 DBusMessage *reply = NULL;
783 if (technology->rfkill_driven && technology->hardblocked == TRUE) {
789 err = technology_enable(technology);
791 err = technology_disable(technology);
794 technology->enable_persistent = powered;
795 technology_save(technology);
799 if (err == -EINPROGRESS) {
800 technology->pending_reply = dbus_message_ref(msg);
801 technology->pending_timeout = g_timeout_add_seconds(10,
802 technology_pending_reply, technology);
803 } else if (err == -EALREADY) {
805 reply = __connman_error_already_enabled(msg);
807 reply = __connman_error_already_disabled(msg);
809 reply = __connman_error_failed(msg, -err);
811 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
816 static DBusMessage *set_property(DBusConnection *conn,
817 DBusMessage *msg, void *data)
819 struct connman_technology *technology = data;
820 DBusMessageIter iter, value;
824 DBG("conn %p", conn);
826 if (dbus_message_iter_init(msg, &iter) == FALSE)
827 return __connman_error_invalid_arguments(msg);
829 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
830 return __connman_error_invalid_arguments(msg);
832 dbus_message_iter_get_basic(&iter, &name);
833 dbus_message_iter_next(&iter);
835 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
836 return __connman_error_invalid_arguments(msg);
838 dbus_message_iter_recurse(&iter, &value);
840 type = dbus_message_iter_get_arg_type(&value);
842 DBG("property %s", name);
844 if (g_str_equal(name, "Tethering") == TRUE) {
846 connman_bool_t tethering;
848 if (type != DBUS_TYPE_BOOLEAN)
849 return __connman_error_invalid_arguments(msg);
851 if (connman_technology_is_tethering_allowed(technology->type)
853 DBG("%s tethering not allowed by config file",
854 __connman_service_type2string(technology->type));
855 return __connman_error_not_supported(msg);
858 dbus_message_iter_get_basic(&value, &tethering);
860 if (technology->tethering == tethering) {
861 if (tethering == FALSE)
862 return __connman_error_already_disabled(msg);
864 return __connman_error_already_enabled(msg);
867 err = set_tethering(technology, tethering);
869 return __connman_error_failed(msg, -err);
871 technology->tethering_persistent = tethering;
873 technology_save(technology);
875 } else if (g_str_equal(name, "TetheringIdentifier") == TRUE) {
878 dbus_message_iter_get_basic(&value, &str);
880 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
881 return __connman_error_not_supported(msg);
883 if (strlen(str) < 1 || strlen(str) > 32)
884 return __connman_error_invalid_arguments(msg);
886 if (g_strcmp0(technology->tethering_ident, str) != 0) {
887 g_free(technology->tethering_ident);
888 technology->tethering_ident = g_strdup(str);
889 technology_save(technology);
891 connman_dbus_property_changed_basic(technology->path,
892 CONNMAN_TECHNOLOGY_INTERFACE,
893 "TetheringIdentifier",
895 &technology->tethering_ident);
897 } else if (g_str_equal(name, "TetheringPassphrase") == TRUE) {
900 dbus_message_iter_get_basic(&value, &str);
902 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
903 return __connman_error_not_supported(msg);
905 if (strlen(str) < 8 || strlen(str) > 63) {
906 if (g_str_equal(str, ""))
907 technology->tethering_passphrase = NULL;
909 return __connman_error_passphrase_required(msg);
911 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
912 g_free(technology->tethering_passphrase);
913 technology->tethering_passphrase = g_strdup(str);
914 technology_save(technology);
916 connman_dbus_property_changed_basic(technology->path,
917 CONNMAN_TECHNOLOGY_INTERFACE,
918 "TetheringPassphrase",
920 &technology->tethering_passphrase);
923 } else if (g_str_equal(name, "Hidden") == TRUE) {
926 if (type != DBUS_TYPE_BOOLEAN)
927 return __connman_error_invalid_arguments(msg);
929 dbus_message_iter_get_basic(&value, &hidden);
931 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
932 return __connman_error_not_supported(msg);
934 technology->tethering_hidden = hidden;
935 } else if (g_str_equal(name, "Powered") == TRUE) {
936 connman_bool_t enable;
938 if (type != DBUS_TYPE_BOOLEAN)
939 return __connman_error_invalid_arguments(msg);
941 dbus_message_iter_get_basic(&value, &enable);
943 return set_powered(technology, msg, enable);
945 return __connman_error_invalid_property(msg);
947 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
950 static void reply_scan_pending(struct connman_technology *technology, int err)
954 DBG("technology %p err %d", technology, err);
956 while (technology->scan_pending != NULL) {
957 DBusMessage *msg = technology->scan_pending->data;
959 DBG("reply to %s", dbus_message_get_sender(msg));
962 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
964 reply = __connman_error_failed(msg, -err);
965 g_dbus_send_message(connection, reply);
966 dbus_message_unref(msg);
968 technology->scan_pending =
969 g_slist_delete_link(technology->scan_pending,
970 technology->scan_pending);
974 void __connman_technology_scan_started(struct connman_device *device)
976 DBG("device %p", device);
979 void __connman_technology_scan_stopped(struct connman_device *device)
982 struct connman_technology *technology;
983 enum connman_service_type type;
986 type = __connman_device_get_service_type(device);
987 technology = technology_find(type);
989 DBG("technology %p device %p", technology, device);
991 if (technology == NULL)
994 for (list = technology->device_list; list != NULL; list = list->next) {
995 struct connman_device *other_device = list->data;
997 if (device == other_device)
1000 if (__connman_device_get_service_type(other_device) != type)
1003 if (connman_device_get_scanning(other_device) == TRUE)
1008 reply_scan_pending(technology, 0);
1011 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1012 int result, const char *alpha2)
1014 connman_bool_t regdom_set = FALSE;
1015 struct connman_technology *technology;
1016 enum connman_service_type type;
1017 GSList *tech_drivers;
1019 type = __connman_device_get_service_type(device);
1020 technology = technology_find(type);
1022 if (technology == NULL)
1027 for (tech_drivers = technology->driver_list;
1028 tech_drivers != NULL;
1029 tech_drivers = g_slist_next(tech_drivers)) {
1030 struct connman_technology_driver *driver =
1033 if (driver->set_regdom != NULL) {
1034 driver->set_regdom(technology, alpha2);
1040 if (regdom_set == FALSE)
1044 connman_technology_regdom_notify(technology, alpha2);
1047 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1049 struct connman_technology *technology = data;
1052 DBG ("technology %p request from %s", technology,
1053 dbus_message_get_sender(msg));
1055 dbus_message_ref(msg);
1056 technology->scan_pending =
1057 g_slist_prepend(technology->scan_pending, msg);
1059 err = __connman_device_request_scan(technology->type);
1061 reply_scan_pending(technology, err);
1066 static const GDBusMethodTable technology_methods[] = {
1067 { GDBUS_DEPRECATED_METHOD("GetProperties",
1068 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1070 { GDBUS_ASYNC_METHOD("SetProperty",
1071 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1072 NULL, set_property) },
1073 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1077 static const GDBusSignalTable technology_signals[] = {
1078 { GDBUS_SIGNAL("PropertyChanged",
1079 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1080 { GDBUS_SIGNAL("DhcpConnected",
1081 GDBUS_ARGS({ "aptype", "s" },
1084 { "hostname", "s" })) },
1085 { GDBUS_SIGNAL("DhcpLeaseDeleted",
1086 GDBUS_ARGS({ "aptype", "s" },
1089 { "hostname", "s" })) },
1093 static gboolean technology_dbus_register(struct connman_technology *technology)
1095 if (technology->dbus_registered == TRUE ||
1096 (technology->rfkill_driven == TRUE &&
1097 technology->hardblocked == TRUE))
1100 if (g_dbus_register_interface(connection, technology->path,
1101 CONNMAN_TECHNOLOGY_INTERFACE,
1102 technology_methods, technology_signals,
1103 NULL, technology, NULL) == FALSE) {
1104 connman_error("Failed to register %s", technology->path);
1108 technology_added_signal(technology);
1109 technology->dbus_registered = TRUE;
1114 static struct connman_technology *technology_get(enum connman_service_type type)
1116 GSList *tech_drivers = NULL;
1117 struct connman_technology_driver *driver;
1118 struct connman_technology *technology;
1122 DBG("type %d", type);
1124 str = __connman_service_type2string(type);
1128 technology = technology_find(type);
1129 if (technology != NULL) {
1130 __sync_fetch_and_add(&technology->refcount, 1);
1134 /* First check if we have a driver for this technology type */
1135 for (list = driver_list; list; list = list->next) {
1136 driver = list->data;
1138 if (driver->type == type) {
1139 DBG("technology %p driver %p", technology, driver);
1140 tech_drivers = g_slist_append(tech_drivers, driver);
1144 if (tech_drivers == NULL) {
1145 DBG("No matching drivers found for %s.",
1146 __connman_service_type2string(type));
1150 technology = g_try_new0(struct connman_technology, 1);
1151 if (technology == NULL)
1154 technology->refcount = 1;
1156 technology->rfkill_driven = FALSE;
1157 technology->softblocked = FALSE;
1158 technology->hardblocked = FALSE;
1159 technology->tethering_hidden = false;
1161 technology->type = type;
1162 technology->path = g_strdup_printf("%s/technology/%s",
1165 technology->device_list = NULL;
1167 technology->pending_reply = NULL;
1169 technology_load(technology);
1171 if (technology_dbus_register(technology) == FALSE) {
1176 technology_list = g_slist_prepend(technology_list, technology);
1178 technology->driver_list = tech_drivers;
1180 for (list = tech_drivers; list != NULL; list = g_slist_next(list)) {
1181 driver = list->data;
1183 if (driver->probe != NULL && driver->probe(technology) < 0)
1184 DBG("Driver probe failed for technology %p",
1188 DBG("technology %p", technology);
1193 static void technology_dbus_unregister(struct connman_technology *technology)
1195 if (technology->dbus_registered == FALSE)
1198 technology_removed_signal(technology);
1199 g_dbus_unregister_interface(connection, technology->path,
1200 CONNMAN_TECHNOLOGY_INTERFACE);
1202 technology->dbus_registered = FALSE;
1205 static void technology_put(struct connman_technology *technology)
1207 DBG("technology %p", technology);
1209 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1212 reply_scan_pending(technology, -EINTR);
1214 while (technology->driver_list != NULL) {
1215 struct connman_technology_driver *driver;
1217 driver = technology->driver_list->data;
1219 if (driver->remove != NULL)
1220 driver->remove(technology);
1222 technology->driver_list =
1223 g_slist_delete_link(technology->driver_list,
1224 technology->driver_list);
1227 technology_list = g_slist_remove(technology_list, technology);
1229 technology_dbus_unregister(technology);
1231 g_slist_free(technology->device_list);
1233 g_free(technology->path);
1234 g_free(technology->regdom);
1235 g_free(technology->tethering_ident);
1236 g_free(technology->tethering_passphrase);
1240 static void enable_tethering(struct connman_technology *technology)
1244 if (connman_setting_get_bool("PersistentTetheringMode") == FALSE)
1247 ret = set_tethering(technology, TRUE);
1248 if (ret < 0 && ret != -EALREADY)
1249 DBG("Cannot enable tethering yet for %s (%d/%s)",
1250 get_name(technology->type),
1251 -ret, strerror(-ret));
1254 void __connman_technology_add_interface(enum connman_service_type type,
1255 int index, const char *name, const char *ident)
1257 struct connman_technology *technology;
1258 GSList *tech_drivers;
1259 struct connman_technology_driver *driver;
1262 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1263 case CONNMAN_SERVICE_TYPE_SYSTEM:
1265 case CONNMAN_SERVICE_TYPE_ETHERNET:
1266 case CONNMAN_SERVICE_TYPE_WIFI:
1267 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1268 case CONNMAN_SERVICE_TYPE_CELLULAR:
1269 case CONNMAN_SERVICE_TYPE_GPS:
1270 case CONNMAN_SERVICE_TYPE_VPN:
1271 case CONNMAN_SERVICE_TYPE_GADGET:
1275 connman_info("Adding interface %s [ %s ]", name,
1276 __connman_service_type2string(type));
1278 technology = technology_find(type);
1280 if (technology == NULL)
1283 for (tech_drivers = technology->driver_list; tech_drivers != NULL;
1284 tech_drivers = g_slist_next(tech_drivers)) {
1285 driver = tech_drivers->data;
1287 if(driver->add_interface != NULL)
1288 driver->add_interface(technology, index, name, ident);
1292 * At this point we can try to enable tethering automatically as
1293 * now the interfaces are set properly.
1295 if (technology->tethering_persistent == TRUE)
1296 enable_tethering(technology);
1299 void __connman_technology_remove_interface(enum connman_service_type type,
1300 int index, const char *name, const char *ident)
1302 struct connman_technology *technology;
1303 GSList *tech_drivers;
1304 struct connman_technology_driver *driver;
1307 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1308 case CONNMAN_SERVICE_TYPE_SYSTEM:
1310 case CONNMAN_SERVICE_TYPE_ETHERNET:
1311 case CONNMAN_SERVICE_TYPE_WIFI:
1312 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1313 case CONNMAN_SERVICE_TYPE_CELLULAR:
1314 case CONNMAN_SERVICE_TYPE_GPS:
1315 case CONNMAN_SERVICE_TYPE_VPN:
1316 case CONNMAN_SERVICE_TYPE_GADGET:
1320 connman_info("Remove interface %s [ %s ]", name,
1321 __connman_service_type2string(type));
1323 technology = technology_find(type);
1325 if (technology == NULL)
1328 for (tech_drivers = technology->driver_list; tech_drivers != NULL;
1329 tech_drivers = g_slist_next(tech_drivers)) {
1330 driver = tech_drivers->data;
1332 if(driver->remove_interface != NULL)
1333 driver->remove_interface(technology, index);
1337 int __connman_technology_add_device(struct connman_device *device)
1339 struct connman_technology *technology;
1340 enum connman_service_type type;
1342 type = __connman_device_get_service_type(device);
1344 DBG("device %p type %s", device, get_name(type));
1346 technology = technology_get(type);
1347 if (technology == NULL) {
1349 * Since no driver can be found for this device at the moment we
1350 * add it to the techless device list.
1352 techless_device_list = g_slist_prepend(techless_device_list,
1358 __sync_synchronize();
1359 if (technology->rfkill_driven == TRUE) {
1360 if (technology->enabled == TRUE)
1361 __connman_device_enable(device);
1363 __connman_device_disable(device);
1368 if (technology->enable_persistent == TRUE &&
1369 global_offlinemode == FALSE) {
1370 int err = __connman_device_enable(device);
1372 * connman_technology_add_device() calls __connman_device_enable()
1373 * but since the device is already enabled, the calls does not
1374 * propagate through to connman_technology_enabled via
1375 * connman_device_set_powered.
1377 if (err == -EALREADY)
1378 __connman_technology_enabled(type);
1380 /* if technology persistent state is offline */
1381 if (technology->enable_persistent == FALSE)
1382 __connman_device_disable(device);
1385 technology->device_list = g_slist_prepend(technology->device_list,
1391 int __connman_technology_remove_device(struct connman_device *device)
1393 struct connman_technology *technology;
1394 enum connman_service_type type;
1396 DBG("device %p", device);
1398 type = __connman_device_get_service_type(device);
1400 technology = technology_find(type);
1401 if (technology == NULL) {
1402 techless_device_list = g_slist_remove(techless_device_list,
1407 technology->device_list = g_slist_remove(technology->device_list,
1410 if (technology->tethering == TRUE)
1411 set_tethering(technology, FALSE);
1413 technology_put(technology);
1418 static void powered_changed(struct connman_technology *technology)
1420 if (technology->dbus_registered == FALSE)
1423 if (technology->pending_reply != NULL) {
1424 g_dbus_send_reply(connection,
1425 technology->pending_reply, DBUS_TYPE_INVALID);
1426 dbus_message_unref(technology->pending_reply);
1427 technology->pending_reply = NULL;
1429 g_source_remove(technology->pending_timeout);
1430 technology->pending_timeout = 0;
1433 __sync_synchronize();
1434 connman_dbus_property_changed_basic(technology->path,
1435 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
1436 DBUS_TYPE_BOOLEAN, &technology->enabled);
1439 static int technology_enabled(struct connman_technology *technology)
1441 __sync_synchronize();
1442 if (technology->enabled == TRUE)
1445 technology->enabled = TRUE;
1447 if (technology->tethering_persistent == TRUE)
1448 enable_tethering(technology);
1450 powered_changed(technology);
1455 int __connman_technology_enabled(enum connman_service_type type)
1457 struct connman_technology *technology;
1459 technology = technology_find(type);
1460 if (technology == NULL)
1463 DBG("technology %p type %s rfkill %d enabled %d", technology,
1464 get_name(type), technology->rfkill_driven,
1465 technology->enabled);
1467 if (technology->rfkill_driven == TRUE) {
1468 if (technology->tethering_persistent == TRUE)
1469 enable_tethering(technology);
1473 return technology_enabled(technology);
1476 static int technology_disabled(struct connman_technology *technology)
1478 __sync_synchronize();
1479 if (technology->enabled == FALSE)
1482 technology->enabled = FALSE;
1484 powered_changed(technology);
1489 int __connman_technology_disabled(enum connman_service_type type)
1491 struct connman_technology *technology;
1494 technology = technology_find(type);
1495 if (technology == NULL)
1498 if (technology->rfkill_driven == TRUE)
1501 for (list = technology->device_list; list != NULL; list = list->next) {
1502 struct connman_device *device = list->data;
1504 if (connman_device_get_powered(device) == TRUE)
1508 return technology_disabled(technology);
1511 int __connman_technology_set_offlinemode(connman_bool_t offlinemode)
1514 int err = -EINVAL, enabled_tech_count = 0;
1516 if (global_offlinemode == offlinemode)
1519 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1522 * This is a bit tricky. When you set offlinemode, there is no
1523 * way to differentiate between attempting offline mode and
1524 * resuming offlinemode from last saved profile. We need that
1525 * information in rfkill_update, otherwise it falls back on the
1526 * technology's persistent state. Hence we set the offline mode here
1527 * but save it & call the notifier only if its successful.
1530 global_offlinemode = offlinemode;
1532 /* Traverse technology list, enable/disable each technology. */
1533 for (list = technology_list; list; list = list->next) {
1534 struct connman_technology *technology = list->data;
1537 err = technology_disable(technology);
1539 if (technology->hardblocked)
1542 if (technology->enable_persistent) {
1543 err = technology_enable(technology);
1544 enabled_tech_count++;
1549 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1550 (err == -EINVAL && enabled_tech_count == 0)) {
1551 connman_technology_save_offlinemode();
1552 __connman_notifier_offlinemode(offlinemode);
1554 global_offlinemode = connman_technology_load_offlinemode();
1559 void __connman_technology_set_connected(enum connman_service_type type,
1560 connman_bool_t connected)
1562 struct connman_technology *technology;
1564 technology = technology_find(type);
1565 if (technology == NULL)
1568 DBG("technology %p connected %d", technology, connected);
1570 technology->connected = connected;
1572 connman_dbus_property_changed_basic(technology->path,
1573 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1574 DBUS_TYPE_BOOLEAN, &connected);
1577 static connman_bool_t technology_apply_rfkill_change(struct connman_technology *technology,
1578 connman_bool_t softblock,
1579 connman_bool_t hardblock,
1580 connman_bool_t new_rfkill)
1582 gboolean hardblock_changed = FALSE;
1583 gboolean apply = TRUE;
1584 GList *start, *list;
1586 DBG("technology %p --> %d/%d vs %d/%d",
1587 technology, softblock, hardblock,
1588 technology->softblocked, technology->hardblocked);
1590 if (technology->hardblocked == hardblock)
1591 goto softblock_change;
1593 if (!(new_rfkill == TRUE && hardblock == FALSE)) {
1594 start = g_hash_table_get_values(rfkill_list);
1596 for (list = start; list != NULL; list = list->next) {
1597 struct connman_rfkill *rfkill = list->data;
1599 if (rfkill->type != technology->type)
1602 if (rfkill->hardblock != hardblock)
1610 goto softblock_change;
1612 technology->hardblocked = hardblock;
1613 hardblock_changed = TRUE;
1616 if (apply == FALSE && technology->softblocked != softblock)
1620 return technology->hardblocked;
1622 technology->softblocked = softblock;
1624 if (technology->hardblocked == TRUE ||
1625 technology->softblocked == TRUE) {
1626 if (technology_disabled(technology) != -EALREADY)
1627 technology_affect_devices(technology, FALSE);
1628 } else if (technology->hardblocked == FALSE &&
1629 technology->softblocked == FALSE) {
1630 if (technology_enabled(technology) != -EALREADY)
1631 technology_affect_devices(technology, TRUE);
1634 if (hardblock_changed == TRUE) {
1635 if (technology->hardblocked == TRUE) {
1636 DBG("%s is switched off.", get_name(technology->type));
1637 technology_dbus_unregister(technology);
1639 DBG("%s is switched on.", get_name(technology->type));
1640 technology_dbus_register(technology);
1642 if (global_offlinemode)
1643 __connman_rfkill_block(technology->type, TRUE);
1647 return technology->hardblocked;
1650 int __connman_technology_add_rfkill(unsigned int index,
1651 enum connman_service_type type,
1652 connman_bool_t softblock,
1653 connman_bool_t hardblock)
1655 struct connman_technology *technology;
1656 struct connman_rfkill *rfkill;
1658 DBG("index %u type %d soft %u hard %u", index, type,
1659 softblock, hardblock);
1661 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1665 rfkill = g_try_new0(struct connman_rfkill, 1);
1669 rfkill->index = index;
1670 rfkill->type = type;
1671 rfkill->softblock = softblock;
1672 rfkill->hardblock = hardblock;
1674 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1677 technology = technology_get(type);
1678 /* If there is no driver for this type, ignore it. */
1679 if (technology == NULL)
1682 technology->rfkill_driven = TRUE;
1684 /* If hardblocked, there is no need to handle softblocked state */
1685 if (technology_apply_rfkill_change(technology,
1686 softblock, hardblock, TRUE) == TRUE)
1689 if (global_offlinemode)
1693 * Depending on softblocked state we unblock/block according to
1694 * offlinemode and persistente state.
1696 if (technology->softblocked == TRUE &&
1697 technology->enable_persistent == TRUE)
1698 return __connman_rfkill_block(type, FALSE);
1699 else if (technology->softblocked == FALSE &&
1700 technology->enable_persistent == FALSE)
1701 return __connman_rfkill_block(type, TRUE);
1706 int __connman_technology_update_rfkill(unsigned int index,
1707 enum connman_service_type type,
1708 connman_bool_t softblock,
1709 connman_bool_t hardblock)
1711 struct connman_technology *technology;
1712 struct connman_rfkill *rfkill;
1714 DBG("index %u soft %u hard %u", index, softblock, hardblock);
1716 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1720 if (rfkill->softblock == softblock &&
1721 rfkill->hardblock == hardblock)
1724 rfkill->softblock = softblock;
1725 rfkill->hardblock = hardblock;
1727 technology = technology_find(type);
1728 /* If there is no driver for this type, ignore it. */
1729 if (technology == NULL)
1732 technology_apply_rfkill_change(technology, softblock, hardblock,
1735 if (technology->hardblocked)
1736 DBG("%s hardblocked", get_name(technology->type));
1738 DBG("%s is%s softblocked", get_name(technology->type),
1739 technology->softblocked ? "" : " not");
1744 int __connman_technology_remove_rfkill(unsigned int index,
1745 enum connman_service_type type)
1747 struct connman_technology *technology;
1748 struct connman_rfkill *rfkill;
1750 DBG("index %u", index);
1752 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1756 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
1758 technology = technology_find(type);
1759 if (technology == NULL)
1762 technology_apply_rfkill_change(technology,
1763 technology->softblocked, !technology->hardblocked, FALSE);
1765 technology_put(technology);
1770 int __connman_technology_init(void)
1774 connection = connman_dbus_get_connection();
1776 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1779 global_offlinemode = connman_technology_load_offlinemode();
1781 /* This will create settings file if it is missing */
1782 connman_technology_save_offlinemode();
1787 void __connman_technology_cleanup(void)
1791 g_hash_table_destroy(rfkill_list);
1793 dbus_connection_unref(connection);