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_rfkill_add 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 g_key_file_set_string(keyfile, identifier,
190 "Tethering.Passphrase",
191 technology->tethering_passphrase);
196 __connman_storage_save_global(keyfile);
198 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 bool connman_technology_get_wifi_tethering(const char **ssid,
353 struct connman_technology *technology;
360 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
364 if (!technology->tethering)
367 *ssid = technology->tethering_ident;
368 *psk = technology->tethering_passphrase;
373 static void free_rfkill(gpointer data)
375 struct connman_rfkill *rfkill = data;
380 static void technology_load(struct connman_technology *technology)
384 GError *error = NULL;
385 bool enable, need_saving = false;
387 DBG("technology %p", technology);
389 keyfile = __connman_storage_load_global();
390 /* Fallback on disabling technology if file not found. */
392 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
393 /* We enable ethernet by default */
394 technology->enable_persistent = true;
396 technology->enable_persistent = false;
400 identifier = g_strdup_printf("%s", get_name(technology->type));
404 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
406 technology->enable_persistent = enable;
408 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
409 technology->enable_persistent = true;
411 technology->enable_persistent = false;
414 g_clear_error(&error);
417 enable = g_key_file_get_boolean(keyfile, identifier,
418 "Tethering", &error);
420 technology->tethering_persistent = enable;
423 g_clear_error(&error);
427 technology_save(technology);
429 technology->tethering_ident = g_key_file_get_string(keyfile,
430 identifier, "Tethering.Identifier", NULL);
432 technology->tethering_passphrase = g_key_file_get_string(keyfile,
433 identifier, "Tethering.Passphrase", NULL);
437 g_key_file_free(keyfile);
442 bool __connman_technology_get_offlinemode(void)
444 return global_offlinemode;
447 static void connman_technology_save_offlinemode(void)
450 GError *error = NULL;
453 keyfile = __connman_storage_load_global();
456 keyfile = g_key_file_new();
457 g_key_file_set_boolean(keyfile, "global",
458 "OfflineMode", global_offlinemode);
460 __connman_storage_save_global(keyfile);
463 offlinemode = g_key_file_get_boolean(keyfile, "global",
464 "OfflineMode", &error);
466 if (error || offlinemode != global_offlinemode) {
467 g_key_file_set_boolean(keyfile, "global",
468 "OfflineMode", global_offlinemode);
470 g_clear_error(&error);
472 __connman_storage_save_global(keyfile);
476 g_key_file_free(keyfile);
481 static bool connman_technology_load_offlinemode(void)
484 GError *error = NULL;
487 /* If there is a error, we enable offlinemode */
488 keyfile = __connman_storage_load_global();
492 offlinemode = g_key_file_get_boolean(keyfile, "global",
493 "OfflineMode", &error);
496 g_clear_error(&error);
499 g_key_file_free(keyfile);
504 static void append_properties(DBusMessageIter *iter,
505 struct connman_technology *technology)
507 DBusMessageIter dict;
511 connman_dbus_dict_open(iter, &dict);
513 str = get_name(technology->type);
515 connman_dbus_dict_append_basic(&dict, "Name",
516 DBUS_TYPE_STRING, &str);
518 str = __connman_service_type2string(technology->type);
520 connman_dbus_dict_append_basic(&dict, "Type",
521 DBUS_TYPE_STRING, &str);
523 __sync_synchronize();
524 val = technology->enabled;
525 connman_dbus_dict_append_basic(&dict, "Powered",
529 val = technology->connected;
530 connman_dbus_dict_append_basic(&dict, "Connected",
534 val = technology->tethering;
535 connman_dbus_dict_append_basic(&dict, "Tethering",
539 if (technology->tethering_ident)
540 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
542 &technology->tethering_ident);
544 if (technology->tethering_passphrase)
545 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
547 &technology->tethering_passphrase);
549 connman_dbus_dict_close(iter, &dict);
552 static void technology_added_signal(struct connman_technology *technology)
555 DBusMessageIter iter;
557 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
558 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
562 dbus_message_iter_init_append(signal, &iter);
563 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
565 append_properties(&iter, technology);
567 dbus_connection_send(connection, signal, NULL);
568 dbus_message_unref(signal);
571 static void technology_removed_signal(struct connman_technology *technology)
573 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
574 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
575 DBUS_TYPE_OBJECT_PATH, &technology->path,
579 static DBusMessage *get_properties(DBusConnection *conn,
580 DBusMessage *message, void *user_data)
582 struct connman_technology *technology = user_data;
584 DBusMessageIter iter;
586 reply = dbus_message_new_method_return(message);
590 dbus_message_iter_init_append(reply, &iter);
591 append_properties(&iter, technology);
596 void __connman_technology_list_struct(DBusMessageIter *array)
599 DBusMessageIter entry;
601 for (list = technology_list; list; list = list->next) {
602 struct connman_technology *technology = list->data;
604 if (!technology->path ||
605 (technology->rfkill_driven &&
606 technology->hardblocked))
609 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
611 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
613 append_properties(&entry, technology);
614 dbus_message_iter_close_container(array, &entry);
618 static gboolean technology_pending_reply(gpointer user_data)
620 struct connman_technology *technology = user_data;
623 /* Power request timedout, send ETIMEDOUT. */
624 if (technology->pending_reply) {
625 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
627 g_dbus_send_message(connection, reply);
629 dbus_message_unref(technology->pending_reply);
630 technology->pending_reply = NULL;
631 technology->pending_timeout = 0;
637 static int technology_affect_devices(struct connman_technology *technology,
640 int err = 0, err_dev;
643 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
645 __connman_technology_enabled(technology->type);
647 __connman_technology_disabled(technology->type);
651 for (list = technology->device_list; list; list = list->next) {
652 struct connman_device *device = list->data;
655 err_dev = __connman_device_enable(device);
657 err_dev = __connman_device_disable(device);
659 if (err_dev < 0 && err_dev != -EALREADY)
666 static void powered_changed(struct connman_technology *technology)
670 if (!technology->dbus_registered)
673 if (technology->pending_reply) {
674 g_dbus_send_reply(connection,
675 technology->pending_reply, DBUS_TYPE_INVALID);
676 dbus_message_unref(technology->pending_reply);
677 technology->pending_reply = NULL;
679 g_source_remove(technology->pending_timeout);
680 technology->pending_timeout = 0;
683 __sync_synchronize();
684 enabled = technology->enabled;
685 connman_dbus_property_changed_basic(technology->path,
686 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
687 DBUS_TYPE_BOOLEAN, &enabled);
690 static void enable_tethering(struct connman_technology *technology)
694 if (!connman_setting_get_bool("PersistentTetheringMode"))
697 ret = set_tethering(technology, true);
698 if (ret < 0 && ret != -EALREADY)
699 DBG("Cannot enable tethering yet for %s (%d/%s)",
700 get_name(technology->type),
701 -ret, strerror(-ret));
704 static int technology_enabled(struct connman_technology *technology)
706 __sync_synchronize();
707 if (technology->enabled)
710 technology->enabled = true;
712 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
713 struct connman_technology *p2p;
715 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
716 if (p2p && !p2p->enabled && p2p->enable_persistent)
717 technology_enabled(p2p);
720 if (technology->tethering_persistent)
721 enable_tethering(technology);
723 powered_changed(technology);
728 static int technology_enable(struct connman_technology *technology)
733 DBG("technology %p enable", technology);
735 __sync_synchronize();
737 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
738 struct connman_technology *wifi;
740 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
741 if (wifi && wifi->enabled)
742 return technology_enabled(technology);
746 if (technology->enabled)
749 if (technology->pending_reply)
752 if (connman_setting_get_bool("PersistentTetheringMode") &&
753 technology->tethering)
754 set_tethering(technology, true);
756 if (technology->rfkill_driven)
757 err = __connman_rfkill_block(technology->type, false);
759 err_dev = technology_affect_devices(technology, true);
761 if (!technology->rfkill_driven)
767 static int technology_disabled(struct connman_technology *technology)
769 __sync_synchronize();
770 if (!technology->enabled)
773 technology->enabled = false;
775 powered_changed(technology);
780 static int technology_disable(struct connman_technology *technology)
784 DBG("technology %p disable", technology);
786 __sync_synchronize();
788 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
789 technology->enable_persistent = false;
790 return technology_disabled(technology);
791 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
792 struct connman_technology *p2p;
794 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
795 if (p2p && p2p->enabled) {
796 p2p->enable_persistent = true;
797 technology_disabled(p2p);
801 if (!technology->enabled)
804 if (technology->pending_reply)
807 if (technology->tethering)
808 set_tethering(technology, false);
810 err = technology_affect_devices(technology, false);
812 if (technology->rfkill_driven)
813 err = __connman_rfkill_block(technology->type, true);
818 static DBusMessage *set_powered(struct connman_technology *technology,
819 DBusMessage *msg, bool powered)
821 DBusMessage *reply = NULL;
824 if (technology->rfkill_driven && technology->hardblocked) {
830 err = technology_enable(technology);
832 err = technology_disable(technology);
835 technology->enable_persistent = powered;
836 technology_save(technology);
840 if (err == -EINPROGRESS) {
841 technology->pending_reply = dbus_message_ref(msg);
842 technology->pending_timeout = g_timeout_add_seconds(10,
843 technology_pending_reply, technology);
844 } else if (err == -EALREADY) {
846 reply = __connman_error_already_enabled(msg);
848 reply = __connman_error_already_disabled(msg);
850 reply = __connman_error_failed(msg, -err);
852 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
857 static DBusMessage *set_property(DBusConnection *conn,
858 DBusMessage *msg, void *data)
860 struct connman_technology *technology = data;
861 DBusMessageIter iter, value;
865 DBG("conn %p", conn);
867 if (!dbus_message_iter_init(msg, &iter))
868 return __connman_error_invalid_arguments(msg);
870 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
871 return __connman_error_invalid_arguments(msg);
873 dbus_message_iter_get_basic(&iter, &name);
874 dbus_message_iter_next(&iter);
876 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
877 return __connman_error_invalid_arguments(msg);
879 dbus_message_iter_recurse(&iter, &value);
881 type = dbus_message_iter_get_arg_type(&value);
883 DBG("property %s", name);
885 if (g_str_equal(name, "Tethering")) {
886 dbus_bool_t tethering;
889 if (type != DBUS_TYPE_BOOLEAN)
890 return __connman_error_invalid_arguments(msg);
892 if (!connman_technology_is_tethering_allowed(technology->type)) {
893 DBG("%s tethering not allowed by config file",
894 __connman_service_type2string(technology->type));
895 return __connman_error_not_supported(msg);
898 dbus_message_iter_get_basic(&value, &tethering);
900 if (technology->tethering == tethering) {
902 return __connman_error_already_disabled(msg);
904 return __connman_error_already_enabled(msg);
907 err = set_tethering(technology, tethering);
909 return __connman_error_failed(msg, -err);
911 technology->tethering_persistent = tethering;
913 technology_save(technology);
915 } else if (g_str_equal(name, "TetheringIdentifier")) {
918 dbus_message_iter_get_basic(&value, &str);
920 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
921 return __connman_error_not_supported(msg);
923 if (strlen(str) < 1 || strlen(str) > 32)
924 return __connman_error_invalid_arguments(msg);
926 if (g_strcmp0(technology->tethering_ident, str) != 0) {
927 g_free(technology->tethering_ident);
928 technology->tethering_ident = g_strdup(str);
929 technology_save(technology);
931 connman_dbus_property_changed_basic(technology->path,
932 CONNMAN_TECHNOLOGY_INTERFACE,
933 "TetheringIdentifier",
935 &technology->tethering_ident);
937 } else if (g_str_equal(name, "TetheringPassphrase")) {
940 dbus_message_iter_get_basic(&value, &str);
942 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
943 return __connman_error_not_supported(msg);
945 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
948 return __connman_error_passphrase_required(msg);
950 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
951 g_free(technology->tethering_passphrase);
952 technology->tethering_passphrase = g_strdup(str);
953 technology_save(technology);
955 connman_dbus_property_changed_basic(technology->path,
956 CONNMAN_TECHNOLOGY_INTERFACE,
957 "TetheringPassphrase",
959 &technology->tethering_passphrase);
961 } else if (g_str_equal(name, "Powered")) {
964 if (type != DBUS_TYPE_BOOLEAN)
965 return __connman_error_invalid_arguments(msg);
967 dbus_message_iter_get_basic(&value, &enable);
969 return set_powered(technology, msg, enable);
971 return __connman_error_invalid_property(msg);
973 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
976 static void reply_scan_pending(struct connman_technology *technology, int err)
980 DBG("technology %p err %d", technology, err);
982 while (technology->scan_pending) {
983 DBusMessage *msg = technology->scan_pending->data;
985 DBG("reply to %s", dbus_message_get_sender(msg));
988 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
990 reply = __connman_error_failed(msg, -err);
991 g_dbus_send_message(connection, reply);
992 dbus_message_unref(msg);
994 technology->scan_pending =
995 g_slist_delete_link(technology->scan_pending,
996 technology->scan_pending);
1000 void __connman_technology_scan_started(struct connman_device *device)
1002 DBG("device %p", device);
1005 void __connman_technology_scan_stopped(struct connman_device *device,
1006 enum connman_service_type type)
1009 struct connman_technology *technology;
1012 technology = technology_find(type);
1014 DBG("technology %p device %p", technology, device);
1019 for (list = technology->device_list; list; list = list->next) {
1020 struct connman_device *other_device = list->data;
1022 if (device == other_device)
1025 if (__connman_device_get_service_type(other_device) != type)
1028 if (connman_device_get_scanning(other_device))
1033 reply_scan_pending(technology, 0);
1036 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1037 int result, const char *alpha2)
1039 bool regdom_set = false;
1040 struct connman_technology *technology;
1041 enum connman_service_type type;
1042 GSList *tech_drivers;
1044 type = __connman_device_get_service_type(device);
1045 technology = technology_find(type);
1052 for (tech_drivers = technology->driver_list;
1054 tech_drivers = g_slist_next(tech_drivers)) {
1055 struct connman_technology_driver *driver =
1058 if (driver->set_regdom) {
1059 driver->set_regdom(technology, alpha2);
1069 connman_technology_regdom_notify(technology, alpha2);
1072 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1074 struct connman_technology *technology = data;
1077 DBG("technology %p request from %s", technology,
1078 dbus_message_get_sender(msg));
1080 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1081 !technology->enabled)
1082 return __connman_error_permission_denied(msg);
1084 dbus_message_ref(msg);
1085 technology->scan_pending =
1086 g_slist_prepend(technology->scan_pending, msg);
1088 err = __connman_device_request_scan(technology->type);
1090 reply_scan_pending(technology, err);
1095 static const GDBusMethodTable technology_methods[] = {
1096 { GDBUS_DEPRECATED_METHOD("GetProperties",
1097 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1099 { GDBUS_ASYNC_METHOD("SetProperty",
1100 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1101 NULL, set_property) },
1102 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1106 static const GDBusSignalTable technology_signals[] = {
1107 { GDBUS_SIGNAL("PropertyChanged",
1108 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1112 static bool technology_dbus_register(struct connman_technology *technology)
1114 if (technology->dbus_registered ||
1115 (technology->rfkill_driven &&
1116 technology->hardblocked))
1119 if (!g_dbus_register_interface(connection, technology->path,
1120 CONNMAN_TECHNOLOGY_INTERFACE,
1121 technology_methods, technology_signals,
1122 NULL, technology, NULL)) {
1123 connman_error("Failed to register %s", technology->path);
1127 technology_added_signal(technology);
1128 technology->dbus_registered = true;
1133 static void technology_dbus_unregister(struct connman_technology *technology)
1135 if (!technology->dbus_registered)
1138 technology_removed_signal(technology);
1139 g_dbus_unregister_interface(connection, technology->path,
1140 CONNMAN_TECHNOLOGY_INTERFACE);
1142 technology->dbus_registered = false;
1145 static void technology_put(struct connman_technology *technology)
1147 DBG("technology %p", technology);
1149 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1152 reply_scan_pending(technology, -EINTR);
1154 while (technology->driver_list) {
1155 struct connman_technology_driver *driver;
1157 driver = technology->driver_list->data;
1160 driver->remove(technology);
1162 technology->driver_list =
1163 g_slist_delete_link(technology->driver_list,
1164 technology->driver_list);
1167 technology_list = g_slist_remove(technology_list, technology);
1169 technology_dbus_unregister(technology);
1171 g_slist_free(technology->device_list);
1173 if (technology->pending_reply) {
1174 dbus_message_unref(technology->pending_reply);
1175 technology->pending_reply = NULL;
1176 g_source_remove(technology->pending_timeout);
1177 technology->pending_timeout = 0;
1180 g_free(technology->path);
1181 g_free(technology->regdom);
1182 g_free(technology->tethering_ident);
1183 g_free(technology->tethering_passphrase);
1187 static struct connman_technology *technology_get(enum connman_service_type type)
1189 GSList *tech_drivers = NULL;
1190 struct connman_technology_driver *driver;
1191 struct connman_technology *technology;
1195 DBG("type %d", type);
1197 str = __connman_service_type2string(type);
1201 technology = technology_find(type);
1203 if (type != CONNMAN_SERVICE_TYPE_P2P)
1204 __sync_fetch_and_add(&technology->refcount, 1);
1208 /* First check if we have a driver for this technology type */
1209 for (list = driver_list; list; list = list->next) {
1210 driver = list->data;
1212 if (driver->type == type) {
1213 DBG("technology %p driver %p", technology, driver);
1214 tech_drivers = g_slist_append(tech_drivers, driver);
1218 if (!tech_drivers) {
1219 DBG("No matching drivers found for %s.",
1220 __connman_service_type2string(type));
1224 technology = g_try_new0(struct connman_technology, 1);
1228 technology->refcount = 1;
1229 technology->type = type;
1230 technology->path = g_strdup_printf("%s/technology/%s",
1233 technology_load(technology);
1234 technology_list = g_slist_prepend(technology_list, technology);
1235 technology->driver_list = tech_drivers;
1237 for (list = tech_drivers; list; list = list->next) {
1238 driver = list->data;
1240 if (driver->probe && driver->probe(technology) < 0)
1241 DBG("Driver probe failed for technology %p",
1245 if (!technology_dbus_register(technology)) {
1246 technology_put(technology);
1250 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1251 struct connman_technology *wifi;
1254 enable = technology->enable_persistent;
1256 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
1258 enable = wifi->enabled;
1260 technology_affect_devices(technology, enable);
1263 DBG("technology %p %s", technology, get_name(technology->type));
1268 int connman_technology_driver_register(struct connman_technology_driver *driver)
1271 struct connman_device *device;
1272 enum connman_service_type type;
1274 for (list = driver_list; list; list = list->next) {
1275 if (list->data == driver)
1279 DBG("Registering %s driver", driver->name);
1281 driver_list = g_slist_insert_sorted(driver_list, driver,
1285 * Check for technology less devices if this driver
1286 * can service any of them.
1288 for (list = techless_device_list; list; list = list->next) {
1289 device = list->data;
1291 type = __connman_device_get_service_type(device);
1292 if (type != driver->type)
1295 techless_device_list = g_slist_remove(techless_device_list,
1298 __connman_technology_add_device(device);
1301 /* Check for orphaned rfkill switches. */
1302 g_hash_table_foreach(rfkill_list, rfkill_check,
1303 GINT_TO_POINTER(driver->type));
1306 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1307 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
1314 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
1316 GSList *list, *tech_drivers;
1317 struct connman_technology *technology;
1318 struct connman_technology_driver *current;
1320 DBG("Unregistering driver %p name %s", driver, driver->name);
1322 for (list = technology_list; list; list = list->next) {
1323 technology = list->data;
1325 for (tech_drivers = technology->driver_list; tech_drivers;
1326 tech_drivers = g_slist_next(tech_drivers)) {
1327 current = tech_drivers->data;
1328 if (driver != current)
1332 driver->remove(technology);
1334 technology->driver_list =
1335 g_slist_remove(technology->driver_list,
1341 driver_list = g_slist_remove(driver_list, driver);
1343 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1344 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1346 technology_put(technology);
1350 void __connman_technology_add_interface(enum connman_service_type type,
1351 int index, const char *ident)
1353 struct connman_technology *technology;
1354 GSList *tech_drivers;
1355 struct connman_technology_driver *driver;
1359 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1360 case CONNMAN_SERVICE_TYPE_SYSTEM:
1362 case CONNMAN_SERVICE_TYPE_ETHERNET:
1363 case CONNMAN_SERVICE_TYPE_WIFI:
1364 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1365 case CONNMAN_SERVICE_TYPE_CELLULAR:
1366 case CONNMAN_SERVICE_TYPE_GPS:
1367 case CONNMAN_SERVICE_TYPE_VPN:
1368 case CONNMAN_SERVICE_TYPE_GADGET:
1369 case CONNMAN_SERVICE_TYPE_P2P:
1373 name = connman_inet_ifname(index);
1374 connman_info("Adding interface %s [ %s ]", name,
1375 __connman_service_type2string(type));
1377 technology = technology_find(type);
1382 for (tech_drivers = technology->driver_list; tech_drivers;
1383 tech_drivers = g_slist_next(tech_drivers)) {
1384 driver = tech_drivers->data;
1386 if (driver->add_interface)
1387 driver->add_interface(technology, index, name, ident);
1391 * At this point we can try to enable tethering automatically as
1392 * now the interfaces are set properly.
1394 if (technology->tethering_persistent)
1395 enable_tethering(technology);
1401 void __connman_technology_remove_interface(enum connman_service_type type,
1402 int index, const char *ident)
1404 struct connman_technology *technology;
1405 GSList *tech_drivers;
1406 struct connman_technology_driver *driver;
1410 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1411 case CONNMAN_SERVICE_TYPE_SYSTEM:
1413 case CONNMAN_SERVICE_TYPE_ETHERNET:
1414 case CONNMAN_SERVICE_TYPE_WIFI:
1415 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1416 case CONNMAN_SERVICE_TYPE_CELLULAR:
1417 case CONNMAN_SERVICE_TYPE_GPS:
1418 case CONNMAN_SERVICE_TYPE_VPN:
1419 case CONNMAN_SERVICE_TYPE_GADGET:
1420 case CONNMAN_SERVICE_TYPE_P2P:
1424 name = connman_inet_ifname(index);
1425 connman_info("Remove interface %s [ %s ]", name,
1426 __connman_service_type2string(type));
1429 technology = technology_find(type);
1434 for (tech_drivers = technology->driver_list; tech_drivers;
1435 tech_drivers = g_slist_next(tech_drivers)) {
1436 driver = tech_drivers->data;
1438 if (driver->remove_interface)
1439 driver->remove_interface(technology, index);
1443 int __connman_technology_add_device(struct connman_device *device)
1445 struct connman_technology *technology;
1446 enum connman_service_type type;
1448 type = __connman_device_get_service_type(device);
1450 DBG("device %p type %s", device, get_name(type));
1452 technology = technology_get(type);
1455 * Since no driver can be found for this device at the moment we
1456 * add it to the techless device list.
1458 techless_device_list = g_slist_prepend(techless_device_list,
1464 __sync_synchronize();
1465 if (technology->rfkill_driven) {
1466 if (technology->enabled)
1467 __connman_device_enable(device);
1469 __connman_device_disable(device);
1474 if (technology->enable_persistent &&
1475 !global_offlinemode) {
1476 int err = __connman_device_enable(device);
1478 * connman_technology_add_device() calls __connman_device_enable()
1479 * but since the device is already enabled, the calls does not
1480 * propagate through to connman_technology_enabled via
1481 * connman_device_set_powered.
1483 if (err == -EALREADY)
1484 __connman_technology_enabled(type);
1486 /* if technology persistent state is offline */
1487 if (!technology->enable_persistent)
1488 __connman_device_disable(device);
1491 technology->device_list = g_slist_prepend(technology->device_list,
1497 int __connman_technology_remove_device(struct connman_device *device)
1499 struct connman_technology *technology;
1500 enum connman_service_type type;
1502 DBG("device %p", device);
1504 type = __connman_device_get_service_type(device);
1506 technology = technology_find(type);
1508 techless_device_list = g_slist_remove(techless_device_list,
1513 technology->device_list = g_slist_remove(technology->device_list,
1516 if (technology->tethering)
1517 set_tethering(technology, false);
1519 technology_put(technology);
1524 int __connman_technology_enabled(enum connman_service_type type)
1526 struct connman_technology *technology;
1528 technology = technology_find(type);
1532 DBG("technology %p type %s rfkill %d enabled %d", technology,
1533 get_name(type), technology->rfkill_driven,
1534 technology->enabled);
1536 if (technology->rfkill_driven) {
1537 if (technology->tethering_persistent)
1538 enable_tethering(technology);
1542 return technology_enabled(technology);
1545 int __connman_technology_disabled(enum connman_service_type type)
1547 struct connman_technology *technology;
1550 technology = technology_find(type);
1554 if (technology->rfkill_driven)
1557 for (list = technology->device_list; list; list = list->next) {
1558 struct connman_device *device = list->data;
1560 if (connman_device_get_powered(device))
1564 return technology_disabled(technology);
1567 int __connman_technology_set_offlinemode(bool offlinemode)
1570 int err = -EINVAL, enabled_tech_count = 0;
1572 if (global_offlinemode == offlinemode)
1575 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1578 * This is a bit tricky. When you set offlinemode, there is no
1579 * way to differentiate between attempting offline mode and
1580 * resuming offlinemode from last saved profile. We need that
1581 * information in rfkill_update, otherwise it falls back on the
1582 * technology's persistent state. Hence we set the offline mode here
1583 * but save it & call the notifier only if its successful.
1586 global_offlinemode = offlinemode;
1588 /* Traverse technology list, enable/disable each technology. */
1589 for (list = technology_list; list; list = list->next) {
1590 struct connman_technology *technology = list->data;
1593 err = technology_disable(technology);
1595 if (technology->hardblocked)
1598 if (technology->enable_persistent) {
1599 err = technology_enable(technology);
1600 enabled_tech_count++;
1605 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1606 (err == -EINVAL && enabled_tech_count == 0)) {
1607 connman_technology_save_offlinemode();
1608 __connman_notifier_offlinemode(offlinemode);
1610 global_offlinemode = connman_technology_load_offlinemode();
1615 void __connman_technology_set_connected(enum connman_service_type type,
1618 struct connman_technology *technology;
1621 technology = technology_find(type);
1625 DBG("technology %p connected %d", technology, connected);
1627 technology->connected = connected;
1630 connman_dbus_property_changed_basic(technology->path,
1631 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1632 DBUS_TYPE_BOOLEAN, &val);
1635 static bool technology_apply_rfkill_change(struct connman_technology *technology,
1640 bool hardblock_changed = false;
1642 GList *start, *list;
1644 DBG("technology %p --> %d/%d vs %d/%d",
1645 technology, softblock, hardblock,
1646 technology->softblocked, technology->hardblocked);
1648 if (technology->hardblocked == hardblock)
1649 goto softblock_change;
1651 if (!(new_rfkill && !hardblock)) {
1652 start = g_hash_table_get_values(rfkill_list);
1654 for (list = start; list; list = list->next) {
1655 struct connman_rfkill *rfkill = list->data;
1657 if (rfkill->type != technology->type)
1660 if (rfkill->hardblock != hardblock)
1668 goto softblock_change;
1670 technology->hardblocked = hardblock;
1671 hardblock_changed = true;
1674 if (!apply && technology->softblocked != softblock)
1678 return technology->hardblocked;
1680 technology->softblocked = softblock;
1682 if (technology->hardblocked ||
1683 technology->softblocked) {
1684 if (technology_disabled(technology) != -EALREADY)
1685 technology_affect_devices(technology, false);
1686 } else if (!technology->hardblocked &&
1687 !technology->softblocked) {
1688 if (technology_enabled(technology) != -EALREADY)
1689 technology_affect_devices(technology, true);
1692 if (hardblock_changed) {
1693 if (technology->hardblocked) {
1694 DBG("%s is switched off.", get_name(technology->type));
1695 technology_dbus_unregister(technology);
1697 DBG("%s is switched on.", get_name(technology->type));
1698 technology_dbus_register(technology);
1700 if (global_offlinemode)
1701 __connman_rfkill_block(technology->type, true);
1705 return technology->hardblocked;
1708 int __connman_technology_add_rfkill(unsigned int index,
1709 enum connman_service_type type,
1713 struct connman_technology *technology;
1714 struct connman_rfkill *rfkill;
1716 DBG("index %u type %d soft %u hard %u", index, type,
1717 softblock, hardblock);
1719 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1723 rfkill = g_try_new0(struct connman_rfkill, 1);
1727 rfkill->index = index;
1728 rfkill->type = type;
1729 rfkill->softblock = softblock;
1730 rfkill->hardblock = hardblock;
1732 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1735 technology = technology_get(type);
1736 /* If there is no driver for this type, ignore it. */
1740 technology->rfkill_driven = true;
1742 /* If hardblocked, there is no need to handle softblocked state */
1743 if (technology_apply_rfkill_change(technology,
1744 softblock, hardblock, true))
1747 if (global_offlinemode)
1751 * Depending on softblocked state we unblock/block according to
1752 * offlinemode and persistente state.
1754 if (technology->softblocked &&
1755 technology->enable_persistent)
1756 return __connman_rfkill_block(type, false);
1757 else if (!technology->softblocked &&
1758 !technology->enable_persistent)
1759 return __connman_rfkill_block(type, true);
1764 int __connman_technology_update_rfkill(unsigned int index,
1765 enum connman_service_type type,
1769 struct connman_technology *technology;
1770 struct connman_rfkill *rfkill;
1772 DBG("index %u soft %u hard %u", index, softblock, hardblock);
1774 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1778 if (rfkill->softblock == softblock &&
1779 rfkill->hardblock == hardblock)
1782 rfkill->softblock = softblock;
1783 rfkill->hardblock = hardblock;
1785 technology = technology_find(type);
1786 /* If there is no driver for this type, ignore it. */
1790 technology_apply_rfkill_change(technology, softblock, hardblock,
1793 if (technology->hardblocked)
1794 DBG("%s hardblocked", get_name(technology->type));
1796 DBG("%s is%s softblocked", get_name(technology->type),
1797 technology->softblocked ? "" : " not");
1802 int __connman_technology_remove_rfkill(unsigned int index,
1803 enum connman_service_type type)
1805 struct connman_technology *technology;
1806 struct connman_rfkill *rfkill;
1808 DBG("index %u", index);
1810 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1814 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
1816 technology = technology_find(type);
1820 technology_apply_rfkill_change(technology,
1821 technology->softblocked, !technology->hardblocked, false);
1823 technology_put(technology);
1828 int __connman_technology_init(void)
1832 connection = connman_dbus_get_connection();
1834 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1837 global_offlinemode = connman_technology_load_offlinemode();
1839 /* This will create settings file if it is missing */
1840 connman_technology_save_offlinemode();
1845 void __connman_technology_cleanup(void)
1849 while (technology_list) {
1850 struct connman_technology *technology = technology_list->data;
1851 technology_list = g_slist_remove(technology_list, technology);
1852 technology_put(technology);
1855 g_hash_table_destroy(rfkill_list);
1857 dbus_connection_unref(connection);