5 * Copyright (C) 2007-2013 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 static DBusConnection *connection;
35 static GSList *technology_list = NULL;
38 * List of devices with no technology associated with them either because of
39 * no compiled in support or the driver is not yet loaded.
41 static GSList *techless_device_list = NULL;
42 static GHashTable *rfkill_list;
44 static bool global_offlinemode;
46 struct connman_rfkill {
48 enum connman_service_type type;
53 struct connman_technology {
55 enum connman_service_type type;
63 bool tethering_persistent; /* Tells the save status, needed
64 * as offline mode might set
67 char *tethering_ident;
68 char *tethering_passphrase;
70 bool enable_persistent; /* Save the tech state */
74 DBusMessage *pending_reply;
75 guint pending_timeout;
85 static GSList *driver_list = NULL;
87 static int technology_enabled(struct connman_technology *technology);
88 static int technology_disabled(struct connman_technology *technology);
90 static gint compare_priority(gconstpointer a, gconstpointer b)
92 const struct connman_technology_driver *driver1 = a;
93 const struct connman_technology_driver *driver2 = b;
95 return driver2->priority - driver1->priority;
98 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
100 struct connman_rfkill *rfkill = value;
101 enum connman_service_type type = GPOINTER_TO_INT(user_data);
103 /* Calling _technology_add_rfkill will update the tech. */
104 if (rfkill->type == type)
105 __connman_technology_add_rfkill(rfkill->index, type,
106 rfkill->softblock, rfkill->hardblock);
110 connman_technology_is_tethering_allowed(enum connman_service_type type)
112 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
114 const char *type_str = __connman_service_type2string(type);
121 allowed = connman_setting_get_string_list("TetheringTechnologies");
123 allowed = allowed_default;
125 for (i = 0; allowed[i]; i++) {
126 if (g_strcmp0(allowed[i], type_str) == 0)
133 static const char *get_name(enum connman_service_type type)
136 case CONNMAN_SERVICE_TYPE_UNKNOWN:
137 case CONNMAN_SERVICE_TYPE_SYSTEM:
138 case CONNMAN_SERVICE_TYPE_GPS:
139 case CONNMAN_SERVICE_TYPE_VPN:
141 case CONNMAN_SERVICE_TYPE_GADGET:
143 case CONNMAN_SERVICE_TYPE_ETHERNET:
145 case CONNMAN_SERVICE_TYPE_WIFI:
147 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
149 case CONNMAN_SERVICE_TYPE_CELLULAR:
151 case CONNMAN_SERVICE_TYPE_P2P:
158 static void technology_save(struct connman_technology *technology)
162 const char *name = get_name(technology->type);
164 DBG("technology %p type %d name %s", technology, technology->type,
169 keyfile = __connman_storage_load_global();
171 keyfile = g_key_file_new();
173 identifier = g_strdup_printf("%s", name);
177 g_key_file_set_boolean(keyfile, identifier, "Enable",
178 technology->enable_persistent);
180 g_key_file_set_boolean(keyfile, identifier, "Tethering",
181 technology->tethering_persistent);
183 if (technology->tethering_ident)
184 g_key_file_set_string(keyfile, identifier,
185 "Tethering.Identifier",
186 technology->tethering_ident);
188 if (technology->tethering_passphrase) {
189 char *enc = g_strescape(technology->tethering_passphrase, NULL);
190 g_key_file_set_string(keyfile, identifier,
191 "Tethering.Passphrase", enc);
198 __connman_storage_save_global(keyfile);
200 g_key_file_free(keyfile);
203 static void tethering_changed(struct connman_technology *technology)
205 dbus_bool_t tethering = technology->tethering;
207 connman_dbus_property_changed_basic(technology->path,
208 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
209 DBUS_TYPE_BOOLEAN, &tethering);
211 technology_save(technology);
214 int connman_technology_tethering_notify(struct connman_technology *technology,
219 DBG("technology %p enabled %u", technology, enabled);
221 if (technology->tethering == enabled)
225 err = __connman_tethering_set_enabled();
229 __connman_tethering_set_disabled();
231 technology->tethering = enabled;
232 tethering_changed(technology);
237 static int set_tethering(struct connman_technology *technology,
240 int result = -EOPNOTSUPP;
242 const char *ident, *passphrase, *bridge;
243 GSList *tech_drivers;
245 ident = technology->tethering_ident;
246 passphrase = technology->tethering_passphrase;
248 __sync_synchronize();
249 if (!technology->enabled)
252 bridge = __connman_tethering_get_bridge();
256 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
257 (!ident || !passphrase))
260 for (tech_drivers = technology->driver_list; tech_drivers;
261 tech_drivers = g_slist_next(tech_drivers)) {
262 struct connman_technology_driver *driver = tech_drivers->data;
264 if (!driver || !driver->set_tethering)
267 err = driver->set_tethering(technology, ident, passphrase,
270 if (result == -EINPROGRESS)
273 if (err == -EINPROGRESS || err == 0)
280 void connman_technology_regdom_notify(struct connman_technology *technology,
286 connman_error("Failed to set regulatory domain");
288 DBG("Regulatory domain set to %s", alpha2);
290 g_free(technology->regdom);
291 technology->regdom = g_strdup(alpha2);
294 static int set_regdom_by_device(struct connman_technology *technology,
299 for (list = technology->device_list; list; list = list->next) {
300 struct connman_device *device = list->data;
302 if (connman_device_set_regdom(device, alpha2) != 0)
309 int connman_technology_set_regdom(const char *alpha2)
311 GSList *list, *tech_drivers;
313 for (list = technology_list; list; list = list->next) {
314 struct connman_technology *technology = list->data;
316 if (set_regdom_by_device(technology, alpha2) != 0) {
318 for (tech_drivers = technology->driver_list;
320 tech_drivers = g_slist_next(tech_drivers)) {
322 struct connman_technology_driver *driver =
325 if (driver->set_regdom)
326 driver->set_regdom(technology, alpha2);
334 static struct connman_technology *technology_find(enum connman_service_type type)
338 DBG("type %d", type);
340 for (list = technology_list; list; list = list->next) {
341 struct connman_technology *technology = list->data;
343 if (technology->type == type)
350 enum connman_service_type connman_technology_get_type
351 (struct connman_technology *technology)
354 return CONNMAN_SERVICE_TYPE_UNKNOWN;
356 return technology->type;
359 bool connman_technology_get_wifi_tethering(const char **ssid,
362 struct connman_technology *technology;
369 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
373 if (!technology->tethering)
376 *ssid = technology->tethering_ident;
377 *psk = technology->tethering_passphrase;
382 static void free_rfkill(gpointer data)
384 struct connman_rfkill *rfkill = data;
389 static void technology_load(struct connman_technology *technology)
393 GError *error = NULL;
394 bool enable, need_saving = false;
397 DBG("technology %p", technology);
399 keyfile = __connman_storage_load_global();
400 /* Fallback on disabling technology if file not found. */
402 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
403 /* We enable ethernet by default */
404 technology->enable_persistent = true;
406 technology->enable_persistent = false;
410 identifier = g_strdup_printf("%s", get_name(technology->type));
414 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
416 technology->enable_persistent = enable;
418 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
419 technology->enable_persistent = true;
421 technology->enable_persistent = false;
424 g_clear_error(&error);
427 enable = g_key_file_get_boolean(keyfile, identifier,
428 "Tethering", &error);
430 technology->tethering_persistent = enable;
433 g_clear_error(&error);
437 technology_save(technology);
439 technology->tethering_ident = g_key_file_get_string(keyfile,
440 identifier, "Tethering.Identifier", NULL);
442 enc = g_key_file_get_string(keyfile,
443 identifier, "Tethering.Passphrase", NULL);
445 technology->tethering_passphrase = g_strcompress(enc);
449 g_key_file_free(keyfile);
452 bool __connman_technology_get_offlinemode(void)
454 return global_offlinemode;
457 static void connman_technology_save_offlinemode(void)
460 GError *error = NULL;
463 keyfile = __connman_storage_load_global();
466 keyfile = g_key_file_new();
467 g_key_file_set_boolean(keyfile, "global",
468 "OfflineMode", global_offlinemode);
470 __connman_storage_save_global(keyfile);
473 offlinemode = g_key_file_get_boolean(keyfile, "global",
474 "OfflineMode", &error);
476 if (error || offlinemode != global_offlinemode) {
477 g_key_file_set_boolean(keyfile, "global",
478 "OfflineMode", global_offlinemode);
480 g_clear_error(&error);
482 __connman_storage_save_global(keyfile);
486 g_key_file_free(keyfile);
489 static bool connman_technology_load_offlinemode(void)
492 GError *error = NULL;
495 /* If there is a error, we enable offlinemode */
496 keyfile = __connman_storage_load_global();
500 offlinemode = g_key_file_get_boolean(keyfile, "global",
501 "OfflineMode", &error);
504 g_clear_error(&error);
507 g_key_file_free(keyfile);
512 static void append_properties(DBusMessageIter *iter,
513 struct connman_technology *technology)
515 DBusMessageIter dict;
519 connman_dbus_dict_open(iter, &dict);
521 str = get_name(technology->type);
523 connman_dbus_dict_append_basic(&dict, "Name",
524 DBUS_TYPE_STRING, &str);
526 str = __connman_service_type2string(technology->type);
528 connman_dbus_dict_append_basic(&dict, "Type",
529 DBUS_TYPE_STRING, &str);
531 __sync_synchronize();
532 val = technology->enabled;
533 connman_dbus_dict_append_basic(&dict, "Powered",
537 val = technology->connected;
538 connman_dbus_dict_append_basic(&dict, "Connected",
542 val = technology->tethering;
543 connman_dbus_dict_append_basic(&dict, "Tethering",
547 if (technology->tethering_ident)
548 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
550 &technology->tethering_ident);
552 if (technology->tethering_passphrase)
553 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
555 &technology->tethering_passphrase);
557 connman_dbus_dict_close(iter, &dict);
560 static void technology_added_signal(struct connman_technology *technology)
563 DBusMessageIter iter;
565 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
566 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
570 dbus_message_iter_init_append(signal, &iter);
571 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
573 append_properties(&iter, technology);
575 dbus_connection_send(connection, signal, NULL);
576 dbus_message_unref(signal);
579 static void technology_removed_signal(struct connman_technology *technology)
581 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
582 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
583 DBUS_TYPE_OBJECT_PATH, &technology->path,
587 static DBusMessage *get_properties(DBusConnection *conn,
588 DBusMessage *message, void *user_data)
590 struct connman_technology *technology = user_data;
592 DBusMessageIter iter;
594 reply = dbus_message_new_method_return(message);
598 dbus_message_iter_init_append(reply, &iter);
599 append_properties(&iter, technology);
604 void __connman_technology_list_struct(DBusMessageIter *array)
607 DBusMessageIter entry;
609 for (list = technology_list; list; list = list->next) {
610 struct connman_technology *technology = list->data;
612 if (!technology->path ||
613 (technology->rfkill_driven &&
614 technology->hardblocked))
617 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
619 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
621 append_properties(&entry, technology);
622 dbus_message_iter_close_container(array, &entry);
626 static gboolean technology_pending_reply(gpointer user_data)
628 struct connman_technology *technology = user_data;
631 /* Power request timed out, send ETIMEDOUT. */
632 if (technology->pending_reply) {
633 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
635 g_dbus_send_message(connection, reply);
637 dbus_message_unref(technology->pending_reply);
638 technology->pending_reply = NULL;
639 technology->pending_timeout = 0;
645 static int technology_affect_devices(struct connman_technology *technology,
648 int err = 0, err_dev;
651 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
653 __connman_technology_enabled(technology->type);
655 __connman_technology_disabled(technology->type);
659 for (list = technology->device_list; list; list = list->next) {
660 struct connman_device *device = list->data;
663 err_dev = __connman_device_enable(device);
665 err_dev = __connman_device_disable(device);
667 if (err_dev < 0 && err_dev != -EALREADY)
674 static void powered_changed(struct connman_technology *technology)
678 if (!technology->dbus_registered)
681 if (technology->pending_reply) {
682 g_dbus_send_reply(connection,
683 technology->pending_reply, DBUS_TYPE_INVALID);
684 dbus_message_unref(technology->pending_reply);
685 technology->pending_reply = NULL;
687 g_source_remove(technology->pending_timeout);
688 technology->pending_timeout = 0;
691 __sync_synchronize();
692 enabled = technology->enabled;
693 connman_dbus_property_changed_basic(technology->path,
694 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
695 DBUS_TYPE_BOOLEAN, &enabled);
698 static void enable_tethering(struct connman_technology *technology)
702 if (!connman_setting_get_bool("PersistentTetheringMode"))
705 ret = set_tethering(technology, true);
706 if (ret < 0 && ret != -EALREADY)
707 DBG("Cannot enable tethering yet for %s (%d/%s)",
708 get_name(technology->type),
709 -ret, strerror(-ret));
712 static int technology_enabled(struct connman_technology *technology)
714 __sync_synchronize();
715 if (technology->enabled)
718 technology->enabled = true;
720 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
721 struct connman_technology *p2p;
723 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
724 if (p2p && !p2p->enabled && p2p->enable_persistent)
725 technology_enabled(p2p);
728 if (technology->tethering_persistent)
729 enable_tethering(technology);
731 powered_changed(technology);
736 static int technology_enable(struct connman_technology *technology)
741 DBG("technology %p enable", technology);
743 __sync_synchronize();
745 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
746 struct connman_technology *wifi;
748 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
749 if (wifi && wifi->enabled)
750 return technology_enabled(technology);
754 if (technology->enabled)
757 if (technology->pending_reply)
760 if (connman_setting_get_bool("PersistentTetheringMode") &&
761 technology->tethering)
762 set_tethering(technology, true);
764 if (technology->rfkill_driven)
765 err = __connman_rfkill_block(technology->type, false);
767 err_dev = technology_affect_devices(technology, true);
769 if (!technology->rfkill_driven)
775 static int technology_disabled(struct connman_technology *technology)
777 __sync_synchronize();
778 if (!technology->enabled)
781 technology->enabled = false;
783 powered_changed(technology);
788 static int technology_disable(struct connman_technology *technology)
792 DBG("technology %p disable", technology);
794 __sync_synchronize();
796 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
797 technology->enable_persistent = false;
798 __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P);
799 __connman_peer_disconnect_all();
800 return technology_disabled(technology);
801 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
802 struct connman_technology *p2p;
804 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
805 if (p2p && p2p->enabled) {
806 p2p->enable_persistent = true;
807 technology_disabled(p2p);
811 if (!technology->enabled)
814 if (technology->pending_reply)
817 if (technology->tethering)
818 set_tethering(technology, false);
820 err = technology_affect_devices(technology, false);
822 if (technology->rfkill_driven)
823 err = __connman_rfkill_block(technology->type, true);
828 static DBusMessage *set_powered(struct connman_technology *technology,
829 DBusMessage *msg, bool powered)
831 DBusMessage *reply = NULL;
834 if (technology->rfkill_driven && technology->hardblocked) {
840 err = technology_enable(technology);
842 err = technology_disable(technology);
845 technology->enable_persistent = powered;
846 technology_save(technology);
850 if (err == -EINPROGRESS) {
851 technology->pending_reply = dbus_message_ref(msg);
852 technology->pending_timeout = g_timeout_add_seconds(10,
853 technology_pending_reply, technology);
854 } else if (err == -EALREADY) {
856 reply = __connman_error_already_enabled(msg);
858 reply = __connman_error_already_disabled(msg);
860 reply = __connman_error_failed(msg, -err);
862 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
867 static DBusMessage *set_property(DBusConnection *conn,
868 DBusMessage *msg, void *data)
870 struct connman_technology *technology = data;
871 DBusMessageIter iter, value;
875 DBG("conn %p", conn);
877 if (!dbus_message_iter_init(msg, &iter))
878 return __connman_error_invalid_arguments(msg);
880 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
881 return __connman_error_invalid_arguments(msg);
883 dbus_message_iter_get_basic(&iter, &name);
884 dbus_message_iter_next(&iter);
886 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
887 return __connman_error_invalid_arguments(msg);
889 dbus_message_iter_recurse(&iter, &value);
891 type = dbus_message_iter_get_arg_type(&value);
893 DBG("property %s", name);
895 if (g_str_equal(name, "Tethering")) {
896 dbus_bool_t tethering;
899 if (type != DBUS_TYPE_BOOLEAN)
900 return __connman_error_invalid_arguments(msg);
902 if (!connman_technology_is_tethering_allowed(technology->type)) {
903 DBG("%s tethering not allowed by config file",
904 __connman_service_type2string(technology->type));
905 return __connman_error_not_supported(msg);
908 dbus_message_iter_get_basic(&value, &tethering);
910 if (technology->tethering == tethering) {
912 return __connman_error_already_disabled(msg);
914 return __connman_error_already_enabled(msg);
917 err = set_tethering(technology, tethering);
919 return __connman_error_failed(msg, -err);
921 technology->tethering_persistent = tethering;
923 technology_save(technology);
925 } else if (g_str_equal(name, "TetheringIdentifier")) {
928 dbus_message_iter_get_basic(&value, &str);
930 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
931 return __connman_error_not_supported(msg);
933 if (strlen(str) < 1 || strlen(str) > 32)
934 return __connman_error_invalid_arguments(msg);
936 if (g_strcmp0(technology->tethering_ident, str) != 0) {
937 g_free(technology->tethering_ident);
938 technology->tethering_ident = g_strdup(str);
939 technology_save(technology);
941 connman_dbus_property_changed_basic(technology->path,
942 CONNMAN_TECHNOLOGY_INTERFACE,
943 "TetheringIdentifier",
945 &technology->tethering_ident);
947 } else if (g_str_equal(name, "TetheringPassphrase")) {
950 dbus_message_iter_get_basic(&value, &str);
952 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
953 return __connman_error_not_supported(msg);
955 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
958 return __connman_error_passphrase_required(msg);
960 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
961 g_free(technology->tethering_passphrase);
962 technology->tethering_passphrase = g_strdup(str);
963 technology_save(technology);
965 connman_dbus_property_changed_basic(technology->path,
966 CONNMAN_TECHNOLOGY_INTERFACE,
967 "TetheringPassphrase",
969 &technology->tethering_passphrase);
971 } else if (g_str_equal(name, "Powered")) {
974 if (type != DBUS_TYPE_BOOLEAN)
975 return __connman_error_invalid_arguments(msg);
977 dbus_message_iter_get_basic(&value, &enable);
979 return set_powered(technology, msg, enable);
981 return __connman_error_invalid_property(msg);
983 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
986 static void reply_scan_pending(struct connman_technology *technology, int err)
990 DBG("technology %p err %d", technology, err);
992 while (technology->scan_pending) {
993 DBusMessage *msg = technology->scan_pending->data;
995 DBG("reply to %s", dbus_message_get_sender(msg));
998 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1000 reply = __connman_error_failed(msg, -err);
1001 g_dbus_send_message(connection, reply);
1002 dbus_message_unref(msg);
1004 technology->scan_pending =
1005 g_slist_delete_link(technology->scan_pending,
1006 technology->scan_pending);
1010 void __connman_technology_scan_started(struct connman_device *device)
1012 DBG("device %p", device);
1015 void __connman_technology_scan_stopped(struct connman_device *device,
1016 enum connman_service_type type)
1019 struct connman_technology *technology;
1022 technology = technology_find(type);
1024 DBG("technology %p device %p", technology, device);
1029 for (list = technology->device_list; list; list = list->next) {
1030 struct connman_device *other_device = list->data;
1032 if (device == other_device)
1035 if (connman_device_get_scanning(other_device, type))
1040 reply_scan_pending(technology, 0);
1043 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1044 int result, const char *alpha2)
1046 bool regdom_set = false;
1047 struct connman_technology *technology;
1048 enum connman_service_type type;
1049 GSList *tech_drivers;
1051 type = __connman_device_get_service_type(device);
1052 technology = technology_find(type);
1059 for (tech_drivers = technology->driver_list;
1061 tech_drivers = g_slist_next(tech_drivers)) {
1062 struct connman_technology_driver *driver =
1065 if (driver->set_regdom) {
1066 driver->set_regdom(technology, alpha2);
1076 connman_technology_regdom_notify(technology, alpha2);
1079 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1081 struct connman_technology *technology = data;
1084 DBG("technology %p request from %s", technology,
1085 dbus_message_get_sender(msg));
1087 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1088 !technology->enabled)
1089 return __connman_error_permission_denied(msg);
1091 dbus_message_ref(msg);
1092 technology->scan_pending =
1093 g_slist_prepend(technology->scan_pending, msg);
1095 err = __connman_device_request_scan_full(technology->type);
1097 reply_scan_pending(technology, err);
1102 static const GDBusMethodTable technology_methods[] = {
1103 { GDBUS_DEPRECATED_METHOD("GetProperties",
1104 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1106 { GDBUS_ASYNC_METHOD("SetProperty",
1107 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1108 NULL, set_property) },
1109 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1113 static const GDBusSignalTable technology_signals[] = {
1114 { GDBUS_SIGNAL("PropertyChanged",
1115 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1119 static bool technology_dbus_register(struct connman_technology *technology)
1121 if (technology->dbus_registered ||
1122 (technology->rfkill_driven &&
1123 technology->hardblocked))
1126 if (!g_dbus_register_interface(connection, technology->path,
1127 CONNMAN_TECHNOLOGY_INTERFACE,
1128 technology_methods, technology_signals,
1129 NULL, technology, NULL)) {
1130 connman_error("Failed to register %s", technology->path);
1134 technology_added_signal(technology);
1135 technology->dbus_registered = true;
1140 static void technology_dbus_unregister(struct connman_technology *technology)
1142 if (!technology->dbus_registered)
1145 technology_removed_signal(technology);
1146 g_dbus_unregister_interface(connection, technology->path,
1147 CONNMAN_TECHNOLOGY_INTERFACE);
1149 technology->dbus_registered = false;
1152 static void technology_put(struct connman_technology *technology)
1154 DBG("technology %p", technology);
1156 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1159 reply_scan_pending(technology, -EINTR);
1161 while (technology->driver_list) {
1162 struct connman_technology_driver *driver;
1164 driver = technology->driver_list->data;
1167 driver->remove(technology);
1169 technology->driver_list =
1170 g_slist_delete_link(technology->driver_list,
1171 technology->driver_list);
1174 technology_list = g_slist_remove(technology_list, technology);
1176 technology_dbus_unregister(technology);
1178 g_slist_free(technology->device_list);
1180 if (technology->pending_reply) {
1181 dbus_message_unref(technology->pending_reply);
1182 technology->pending_reply = NULL;
1183 g_source_remove(technology->pending_timeout);
1184 technology->pending_timeout = 0;
1187 g_free(technology->path);
1188 g_free(technology->regdom);
1189 g_free(technology->tethering_ident);
1190 g_free(technology->tethering_passphrase);
1194 static struct connman_technology *technology_get(enum connman_service_type type)
1196 GSList *tech_drivers = NULL;
1197 struct connman_technology_driver *driver;
1198 struct connman_technology *technology;
1202 DBG("type %d", type);
1204 str = __connman_service_type2string(type);
1208 technology = technology_find(type);
1210 if (type != CONNMAN_SERVICE_TYPE_P2P)
1211 __sync_fetch_and_add(&technology->refcount, 1);
1215 /* First check if we have a driver for this technology type */
1216 for (list = driver_list; list; list = list->next) {
1217 driver = list->data;
1219 if (driver->type == type) {
1220 DBG("technology %p driver %p", technology, driver);
1221 tech_drivers = g_slist_append(tech_drivers, driver);
1225 if (!tech_drivers) {
1226 DBG("No matching drivers found for %s.",
1227 __connman_service_type2string(type));
1231 technology = g_try_new0(struct connman_technology, 1);
1235 technology->refcount = 1;
1236 technology->type = type;
1237 technology->path = g_strdup_printf("%s/technology/%s",
1240 technology_load(technology);
1241 technology_list = g_slist_prepend(technology_list, technology);
1242 technology->driver_list = tech_drivers;
1244 for (list = tech_drivers; list; list = list->next) {
1245 driver = list->data;
1247 if (driver->probe && driver->probe(technology) < 0)
1248 DBG("Driver probe failed for technology %p",
1252 if (!technology_dbus_register(technology)) {
1253 technology_put(technology);
1257 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1258 struct connman_technology *wifi;
1261 enable = technology->enable_persistent;
1263 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
1265 enable = wifi->enabled;
1267 technology_affect_devices(technology, enable);
1270 DBG("technology %p %s", technology, get_name(technology->type));
1275 int connman_technology_driver_register(struct connman_technology_driver *driver)
1278 struct connman_device *device;
1279 enum connman_service_type type;
1281 for (list = driver_list; list; list = list->next) {
1282 if (list->data == driver)
1286 DBG("Registering %s driver", driver->name);
1288 driver_list = g_slist_insert_sorted(driver_list, driver,
1292 * Check for technology less devices if this driver
1293 * can service any of them.
1295 for (list = techless_device_list; list; list = list->next) {
1296 device = list->data;
1298 type = __connman_device_get_service_type(device);
1299 if (type != driver->type)
1302 techless_device_list = g_slist_remove(techless_device_list,
1305 __connman_technology_add_device(device);
1308 /* Check for orphaned rfkill switches. */
1309 g_hash_table_foreach(rfkill_list, rfkill_check,
1310 GINT_TO_POINTER(driver->type));
1313 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1314 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
1321 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
1323 GSList *list, *tech_drivers;
1324 struct connman_technology *technology;
1325 struct connman_technology_driver *current;
1327 DBG("Unregistering driver %p name %s", driver, driver->name);
1329 for (list = technology_list; list; list = list->next) {
1330 technology = list->data;
1332 for (tech_drivers = technology->driver_list; tech_drivers;
1333 tech_drivers = g_slist_next(tech_drivers)) {
1334 current = tech_drivers->data;
1335 if (driver != current)
1339 driver->remove(technology);
1341 technology->driver_list =
1342 g_slist_remove(technology->driver_list,
1348 driver_list = g_slist_remove(driver_list, driver);
1350 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1351 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1353 technology_put(technology);
1357 void __connman_technology_add_interface(enum connman_service_type type,
1358 int index, const char *ident)
1360 struct connman_technology *technology;
1361 GSList *tech_drivers;
1362 struct connman_technology_driver *driver;
1366 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1367 case CONNMAN_SERVICE_TYPE_SYSTEM:
1369 case CONNMAN_SERVICE_TYPE_ETHERNET:
1370 case CONNMAN_SERVICE_TYPE_WIFI:
1371 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1372 case CONNMAN_SERVICE_TYPE_CELLULAR:
1373 case CONNMAN_SERVICE_TYPE_GPS:
1374 case CONNMAN_SERVICE_TYPE_VPN:
1375 case CONNMAN_SERVICE_TYPE_GADGET:
1376 case CONNMAN_SERVICE_TYPE_P2P:
1380 name = connman_inet_ifname(index);
1381 connman_info("Adding interface %s [ %s ]", name,
1382 __connman_service_type2string(type));
1384 technology = technology_find(type);
1389 for (tech_drivers = technology->driver_list; tech_drivers;
1390 tech_drivers = g_slist_next(tech_drivers)) {
1391 driver = tech_drivers->data;
1393 if (driver->add_interface)
1394 driver->add_interface(technology, index, name, ident);
1398 * At this point we can try to enable tethering automatically as
1399 * now the interfaces are set properly.
1401 if (technology->tethering_persistent)
1402 enable_tethering(technology);
1408 void __connman_technology_remove_interface(enum connman_service_type type,
1409 int index, const char *ident)
1411 struct connman_technology *technology;
1412 GSList *tech_drivers;
1413 struct connman_technology_driver *driver;
1417 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1418 case CONNMAN_SERVICE_TYPE_SYSTEM:
1420 case CONNMAN_SERVICE_TYPE_ETHERNET:
1421 case CONNMAN_SERVICE_TYPE_WIFI:
1422 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1423 case CONNMAN_SERVICE_TYPE_CELLULAR:
1424 case CONNMAN_SERVICE_TYPE_GPS:
1425 case CONNMAN_SERVICE_TYPE_VPN:
1426 case CONNMAN_SERVICE_TYPE_GADGET:
1427 case CONNMAN_SERVICE_TYPE_P2P:
1431 name = connman_inet_ifname(index);
1432 connman_info("Remove interface %s [ %s ]", name,
1433 __connman_service_type2string(type));
1436 technology = technology_find(type);
1441 for (tech_drivers = technology->driver_list; tech_drivers;
1442 tech_drivers = g_slist_next(tech_drivers)) {
1443 driver = tech_drivers->data;
1445 if (driver->remove_interface)
1446 driver->remove_interface(technology, index);
1450 int __connman_technology_add_device(struct connman_device *device)
1452 struct connman_technology *technology;
1453 enum connman_service_type type;
1455 type = __connman_device_get_service_type(device);
1457 DBG("device %p type %s", device, get_name(type));
1459 technology = technology_get(type);
1462 * Since no driver can be found for this device at the moment we
1463 * add it to the techless device list.
1465 techless_device_list = g_slist_prepend(techless_device_list,
1471 __sync_synchronize();
1472 if (technology->rfkill_driven) {
1473 if (technology->enabled)
1474 __connman_device_enable(device);
1476 __connman_device_disable(device);
1481 if (technology->enable_persistent &&
1482 !global_offlinemode) {
1483 int err = __connman_device_enable(device);
1485 * connman_technology_add_device() calls __connman_device_enable()
1486 * but since the device is already enabled, the call does not
1487 * propagate through to connman_technology_enabled via
1488 * connman_device_set_powered.
1490 if (err == -EALREADY)
1491 __connman_technology_enabled(type);
1493 /* if technology persistent state is offline */
1494 if (!technology->enable_persistent)
1495 __connman_device_disable(device);
1498 technology->device_list = g_slist_prepend(technology->device_list,
1504 int __connman_technology_remove_device(struct connman_device *device)
1506 struct connman_technology *technology;
1507 enum connman_service_type type;
1509 DBG("device %p", device);
1511 type = __connman_device_get_service_type(device);
1513 technology = technology_find(type);
1515 techless_device_list = g_slist_remove(techless_device_list,
1520 technology->device_list = g_slist_remove(technology->device_list,
1523 if (technology->tethering)
1524 set_tethering(technology, false);
1526 technology_put(technology);
1531 int __connman_technology_enabled(enum connman_service_type type)
1533 struct connman_technology *technology;
1535 technology = technology_find(type);
1539 DBG("technology %p type %s rfkill %d enabled %d", technology,
1540 get_name(type), technology->rfkill_driven,
1541 technology->enabled);
1543 if (technology->rfkill_driven) {
1544 if (technology->tethering_persistent)
1545 enable_tethering(technology);
1549 return technology_enabled(technology);
1552 int __connman_technology_disabled(enum connman_service_type type)
1554 struct connman_technology *technology;
1557 technology = technology_find(type);
1561 if (technology->rfkill_driven)
1564 for (list = technology->device_list; list; list = list->next) {
1565 struct connman_device *device = list->data;
1567 if (connman_device_get_powered(device))
1571 return technology_disabled(technology);
1574 int __connman_technology_set_offlinemode(bool offlinemode)
1577 int err = -EINVAL, enabled_tech_count = 0;
1579 if (global_offlinemode == offlinemode)
1582 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1585 * This is a bit tricky. When you set offlinemode, there is no
1586 * way to differentiate between attempting offline mode and
1587 * resuming offlinemode from last saved profile. We need that
1588 * information in rfkill_update, otherwise it falls back on the
1589 * technology's persistent state. Hence we set the offline mode here
1590 * but save it & call the notifier only if it is successful.
1593 global_offlinemode = offlinemode;
1595 /* Traverse technology list, enable/disable each technology. */
1596 for (list = technology_list; list; list = list->next) {
1597 struct connman_technology *technology = list->data;
1600 err = technology_disable(technology);
1602 if (technology->hardblocked)
1605 if (technology->enable_persistent) {
1606 err = technology_enable(technology);
1607 enabled_tech_count++;
1612 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1613 (err == -EINVAL && enabled_tech_count == 0)) {
1614 connman_technology_save_offlinemode();
1615 __connman_notifier_offlinemode(offlinemode);
1617 global_offlinemode = connman_technology_load_offlinemode();
1622 void __connman_technology_set_connected(enum connman_service_type type,
1625 struct connman_technology *technology;
1628 technology = technology_find(type);
1632 DBG("technology %p connected %d", technology, connected);
1634 technology->connected = connected;
1637 connman_dbus_property_changed_basic(technology->path,
1638 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1639 DBUS_TYPE_BOOLEAN, &val);
1642 static bool technology_apply_rfkill_change(struct connman_technology *technology,
1647 bool hardblock_changed = false;
1649 GList *start, *list;
1651 DBG("technology %p --> %d/%d vs %d/%d",
1652 technology, softblock, hardblock,
1653 technology->softblocked, technology->hardblocked);
1655 if (technology->hardblocked == hardblock)
1656 goto softblock_change;
1658 if (!(new_rfkill && !hardblock)) {
1659 start = g_hash_table_get_values(rfkill_list);
1661 for (list = start; list; list = list->next) {
1662 struct connman_rfkill *rfkill = list->data;
1664 if (rfkill->type != technology->type)
1667 if (rfkill->hardblock != hardblock)
1675 goto softblock_change;
1677 technology->hardblocked = hardblock;
1678 hardblock_changed = true;
1681 if (!apply && technology->softblocked != softblock)
1685 return technology->hardblocked;
1687 technology->softblocked = softblock;
1689 if (technology->hardblocked ||
1690 technology->softblocked) {
1691 if (technology_disabled(technology) != -EALREADY)
1692 technology_affect_devices(technology, false);
1693 } else if (!technology->hardblocked &&
1694 !technology->softblocked) {
1695 if (technology_enabled(technology) != -EALREADY)
1696 technology_affect_devices(technology, true);
1699 if (hardblock_changed) {
1700 if (technology->hardblocked) {
1701 DBG("%s is switched off.", get_name(technology->type));
1702 technology_dbus_unregister(technology);
1704 DBG("%s is switched on.", get_name(technology->type));
1705 technology_dbus_register(technology);
1707 if (global_offlinemode)
1708 __connman_rfkill_block(technology->type, true);
1712 return technology->hardblocked;
1715 int __connman_technology_add_rfkill(unsigned int index,
1716 enum connman_service_type type,
1720 struct connman_technology *technology;
1721 struct connman_rfkill *rfkill;
1723 DBG("index %u type %d soft %u hard %u", index, type,
1724 softblock, hardblock);
1726 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1730 rfkill = g_try_new0(struct connman_rfkill, 1);
1734 rfkill->index = index;
1735 rfkill->type = type;
1736 rfkill->softblock = softblock;
1737 rfkill->hardblock = hardblock;
1739 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1742 technology = technology_get(type);
1743 /* If there is no driver for this type, ignore it. */
1747 technology->rfkill_driven = true;
1749 /* If hardblocked, there is no need to handle softblocked state */
1750 if (technology_apply_rfkill_change(technology,
1751 softblock, hardblock, true))
1754 if (global_offlinemode)
1758 * Depending on softblocked state we unblock/block according to
1759 * offlinemode and persistente state.
1761 if (technology->softblocked &&
1762 technology->enable_persistent)
1763 return __connman_rfkill_block(type, false);
1764 else if (!technology->softblocked &&
1765 !technology->enable_persistent)
1766 return __connman_rfkill_block(type, true);
1771 int __connman_technology_update_rfkill(unsigned int index,
1772 enum connman_service_type type,
1776 struct connman_technology *technology;
1777 struct connman_rfkill *rfkill;
1779 DBG("index %u soft %u hard %u", index, softblock, hardblock);
1781 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1785 if (rfkill->softblock == softblock &&
1786 rfkill->hardblock == hardblock)
1789 rfkill->softblock = softblock;
1790 rfkill->hardblock = hardblock;
1792 technology = technology_find(type);
1793 /* If there is no driver for this type, ignore it. */
1797 technology_apply_rfkill_change(technology, softblock, hardblock,
1800 if (technology->hardblocked)
1801 DBG("%s hardblocked", get_name(technology->type));
1803 DBG("%s is%s softblocked", get_name(technology->type),
1804 technology->softblocked ? "" : " not");
1809 int __connman_technology_remove_rfkill(unsigned int index,
1810 enum connman_service_type type)
1812 struct connman_technology *technology;
1813 struct connman_rfkill *rfkill;
1815 DBG("index %u", index);
1817 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1821 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
1823 technology = technology_find(type);
1827 technology_apply_rfkill_change(technology,
1828 technology->softblocked, !technology->hardblocked, false);
1830 technology_put(technology);
1835 int __connman_technology_init(void)
1839 connection = connman_dbus_get_connection();
1841 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1844 global_offlinemode = connman_technology_load_offlinemode();
1846 /* This will create settings file if it is missing */
1847 connman_technology_save_offlinemode();
1852 void __connman_technology_cleanup(void)
1856 while (technology_list) {
1857 struct connman_technology *technology = technology_list->data;
1858 technology_list = g_slist_remove(technology_list, technology);
1859 technology_put(technology);
1862 g_hash_table_destroy(rfkill_list);
1864 dbus_connection_unref(connection);