5 * Copyright (C) 2007-2013 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 static DBusConnection *connection;
35 static GSList *technology_list = NULL;
38 * List of devices with no technology associated with them either because of
39 * no compiled in support or the driver is not yet loaded.
41 static GSList *techless_device_list = NULL;
42 static GHashTable *rfkill_list;
44 static bool global_offlinemode;
46 struct connman_rfkill {
48 enum connman_service_type type;
53 struct connman_technology {
55 enum connman_service_type type;
63 bool tethering_persistent; /* Tells the save status, needed
64 * as offline mode might set
67 char *tethering_ident;
68 char *tethering_passphrase;
70 bool enable_persistent; /* Save the tech state */
74 DBusMessage *pending_reply;
75 guint pending_timeout;
85 static GSList *driver_list = NULL;
87 static gint compare_priority(gconstpointer a, gconstpointer b)
89 const struct connman_technology_driver *driver1 = a;
90 const struct connman_technology_driver *driver2 = b;
92 return driver2->priority - driver1->priority;
95 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
97 struct connman_rfkill *rfkill = value;
98 enum connman_service_type type = GPOINTER_TO_INT(user_data);
100 /* Calling _technology_rfkill_add will update the tech. */
101 if (rfkill->type == type)
102 __connman_technology_add_rfkill(rfkill->index, type,
103 rfkill->softblock, rfkill->hardblock);
107 connman_technology_is_tethering_allowed(enum connman_service_type type)
109 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
111 const char *type_str = __connman_service_type2string(type);
118 allowed = connman_setting_get_string_list("TetheringTechnologies");
120 allowed = allowed_default;
122 for (i = 0; allowed[i]; i++) {
123 if (g_strcmp0(allowed[i], type_str) == 0)
130 static const char *get_name(enum connman_service_type type)
133 case CONNMAN_SERVICE_TYPE_UNKNOWN:
134 case CONNMAN_SERVICE_TYPE_SYSTEM:
135 case CONNMAN_SERVICE_TYPE_GPS:
136 case CONNMAN_SERVICE_TYPE_VPN:
138 case CONNMAN_SERVICE_TYPE_GADGET:
140 case CONNMAN_SERVICE_TYPE_ETHERNET:
142 case CONNMAN_SERVICE_TYPE_WIFI:
144 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
146 case CONNMAN_SERVICE_TYPE_CELLULAR:
148 case CONNMAN_SERVICE_TYPE_P2P:
155 static void technology_save(struct connman_technology *technology)
159 const char *name = get_name(technology->type);
161 DBG("technology %p type %d name %s", technology, technology->type,
166 keyfile = __connman_storage_load_global();
168 keyfile = g_key_file_new();
170 identifier = g_strdup_printf("%s", name);
174 g_key_file_set_boolean(keyfile, identifier, "Enable",
175 technology->enable_persistent);
177 g_key_file_set_boolean(keyfile, identifier, "Tethering",
178 technology->tethering_persistent);
180 if (technology->tethering_ident)
181 g_key_file_set_string(keyfile, identifier,
182 "Tethering.Identifier",
183 technology->tethering_ident);
185 if (technology->tethering_passphrase)
186 g_key_file_set_string(keyfile, identifier,
187 "Tethering.Passphrase",
188 technology->tethering_passphrase);
193 __connman_storage_save_global(keyfile);
195 g_key_file_free(keyfile);
200 static void tethering_changed(struct connman_technology *technology)
202 dbus_bool_t tethering = technology->tethering;
204 connman_dbus_property_changed_basic(technology->path,
205 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
206 DBUS_TYPE_BOOLEAN, &tethering);
208 technology_save(technology);
211 void connman_technology_tethering_notify(struct connman_technology *technology,
214 DBG("technology %p enabled %u", technology, enabled);
216 if (technology->tethering == enabled)
219 technology->tethering = enabled;
221 tethering_changed(technology);
224 __connman_tethering_set_enabled();
226 __connman_tethering_set_disabled();
229 static int set_tethering(struct connman_technology *technology,
232 int result = -EOPNOTSUPP;
234 const char *ident, *passphrase, *bridge;
235 GSList *tech_drivers;
237 ident = technology->tethering_ident;
238 passphrase = technology->tethering_passphrase;
240 __sync_synchronize();
241 if (!technology->enabled)
244 bridge = __connman_tethering_get_bridge();
248 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && (!ident))
251 for (tech_drivers = technology->driver_list; tech_drivers;
252 tech_drivers = g_slist_next(tech_drivers)) {
253 struct connman_technology_driver *driver = tech_drivers->data;
255 if (!driver || !driver->set_tethering)
258 err = driver->set_tethering(technology, ident, passphrase,
261 if (result == -EINPROGRESS)
264 if (err == -EINPROGRESS || err == 0) {
273 void connman_technology_regdom_notify(struct connman_technology *technology,
279 connman_error("Failed to set regulatory domain");
281 DBG("Regulatory domain set to %s", alpha2);
283 g_free(technology->regdom);
284 technology->regdom = g_strdup(alpha2);
287 static int set_regdom_by_device(struct connman_technology *technology,
292 for (list = technology->device_list; list; list = list->next) {
293 struct connman_device *device = list->data;
295 if (connman_device_set_regdom(device, alpha2) != 0)
302 int connman_technology_set_regdom(const char *alpha2)
304 GSList *list, *tech_drivers;
306 for (list = technology_list; list; list = list->next) {
307 struct connman_technology *technology = list->data;
309 if (set_regdom_by_device(technology, alpha2) != 0) {
311 for (tech_drivers = technology->driver_list;
313 tech_drivers = g_slist_next(tech_drivers)) {
315 struct connman_technology_driver *driver =
318 if (driver->set_regdom)
319 driver->set_regdom(technology, alpha2);
327 static struct connman_technology *technology_find(enum connman_service_type type)
331 DBG("type %d", type);
333 for (list = technology_list; list; list = list->next) {
334 struct connman_technology *technology = list->data;
336 if (technology->type == type)
343 bool connman_technology_get_wifi_tethering(const char **ssid,
346 struct connman_technology *technology;
353 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
357 if (!technology->tethering)
360 *ssid = technology->tethering_ident;
361 *psk = technology->tethering_passphrase;
366 static void free_rfkill(gpointer data)
368 struct connman_rfkill *rfkill = data;
373 static void technology_load(struct connman_technology *technology)
377 GError *error = NULL;
378 bool enable, need_saving = false;
380 DBG("technology %p", technology);
382 keyfile = __connman_storage_load_global();
383 /* Fallback on disabling technology if file not found. */
385 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
386 /* We enable ethernet by default */
387 technology->enable_persistent = true;
389 technology->enable_persistent = false;
393 identifier = g_strdup_printf("%s", get_name(technology->type));
397 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
399 technology->enable_persistent = enable;
401 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
402 technology->enable_persistent = true;
404 technology->enable_persistent = false;
407 g_clear_error(&error);
410 enable = g_key_file_get_boolean(keyfile, identifier,
411 "Tethering", &error);
413 technology->tethering_persistent = enable;
416 g_clear_error(&error);
420 technology_save(technology);
422 technology->tethering_ident = g_key_file_get_string(keyfile,
423 identifier, "Tethering.Identifier", NULL);
425 technology->tethering_passphrase = g_key_file_get_string(keyfile,
426 identifier, "Tethering.Passphrase", NULL);
430 g_key_file_free(keyfile);
435 bool __connman_technology_get_offlinemode(void)
437 return global_offlinemode;
440 static void connman_technology_save_offlinemode(void)
444 keyfile = __connman_storage_load_global();
446 keyfile = g_key_file_new();
448 g_key_file_set_boolean(keyfile, "global",
449 "OfflineMode", global_offlinemode);
451 __connman_storage_save_global(keyfile);
453 g_key_file_free(keyfile);
458 static bool connman_technology_load_offlinemode(void)
461 GError *error = NULL;
464 /* If there is a error, we enable offlinemode */
465 keyfile = __connman_storage_load_global();
469 offlinemode = g_key_file_get_boolean(keyfile, "global",
470 "OfflineMode", &error);
473 g_clear_error(&error);
476 g_key_file_free(keyfile);
481 static void append_properties(DBusMessageIter *iter,
482 struct connman_technology *technology)
484 DBusMessageIter dict;
488 connman_dbus_dict_open(iter, &dict);
490 str = get_name(technology->type);
492 connman_dbus_dict_append_basic(&dict, "Name",
493 DBUS_TYPE_STRING, &str);
495 str = __connman_service_type2string(technology->type);
497 connman_dbus_dict_append_basic(&dict, "Type",
498 DBUS_TYPE_STRING, &str);
500 __sync_synchronize();
501 val = technology->enabled;
502 connman_dbus_dict_append_basic(&dict, "Powered",
506 val = technology->connected;
507 connman_dbus_dict_append_basic(&dict, "Connected",
511 val = technology->tethering;
512 connman_dbus_dict_append_basic(&dict, "Tethering",
516 if (technology->tethering_ident)
517 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
519 &technology->tethering_ident);
521 if (technology->tethering_passphrase)
522 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
524 &technology->tethering_passphrase);
526 connman_dbus_dict_close(iter, &dict);
529 static void technology_added_signal(struct connman_technology *technology)
532 DBusMessageIter iter;
534 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
535 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
539 dbus_message_iter_init_append(signal, &iter);
540 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
542 append_properties(&iter, technology);
544 dbus_connection_send(connection, signal, NULL);
545 dbus_message_unref(signal);
548 static void technology_removed_signal(struct connman_technology *technology)
550 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
551 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
552 DBUS_TYPE_OBJECT_PATH, &technology->path,
556 static DBusMessage *get_properties(DBusConnection *conn,
557 DBusMessage *message, void *user_data)
559 struct connman_technology *technology = user_data;
561 DBusMessageIter iter;
563 reply = dbus_message_new_method_return(message);
567 dbus_message_iter_init_append(reply, &iter);
568 append_properties(&iter, technology);
573 void __connman_technology_list_struct(DBusMessageIter *array)
576 DBusMessageIter entry;
578 for (list = technology_list; list; list = list->next) {
579 struct connman_technology *technology = list->data;
581 if (!technology->path ||
582 (technology->rfkill_driven &&
583 technology->hardblocked))
586 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
588 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
590 append_properties(&entry, technology);
591 dbus_message_iter_close_container(array, &entry);
595 static gboolean technology_pending_reply(gpointer user_data)
597 struct connman_technology *technology = user_data;
600 /* Power request timedout, send ETIMEDOUT. */
601 if (technology->pending_reply) {
602 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
604 g_dbus_send_message(connection, reply);
606 dbus_message_unref(technology->pending_reply);
607 technology->pending_reply = NULL;
608 technology->pending_timeout = 0;
614 static int technology_affect_devices(struct connman_technology *technology,
620 if (technology->type == CONNMAN_SERVICE_TYPE_P2P)
623 for (list = technology->device_list; list; list = list->next) {
624 struct connman_device *device = list->data;
627 err = __connman_device_enable(device);
629 err = __connman_device_disable(device);
635 static void powered_changed(struct connman_technology *technology)
639 if (!technology->dbus_registered)
642 if (technology->pending_reply) {
643 g_dbus_send_reply(connection,
644 technology->pending_reply, DBUS_TYPE_INVALID);
645 dbus_message_unref(technology->pending_reply);
646 technology->pending_reply = NULL;
648 g_source_remove(technology->pending_timeout);
649 technology->pending_timeout = 0;
652 __sync_synchronize();
653 enabled = technology->enabled;
654 connman_dbus_property_changed_basic(technology->path,
655 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
656 DBUS_TYPE_BOOLEAN, &enabled);
659 static void enable_tethering(struct connman_technology *technology)
663 if (!connman_setting_get_bool("PersistentTetheringMode"))
666 ret = set_tethering(technology, true);
667 if (ret < 0 && ret != -EALREADY)
668 DBG("Cannot enable tethering yet for %s (%d/%s)",
669 get_name(technology->type),
670 -ret, strerror(-ret));
673 static int technology_enabled(struct connman_technology *technology)
675 __sync_synchronize();
676 if (technology->enabled)
679 technology->enabled = true;
681 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
682 struct connman_technology *p2p;
684 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
685 if (p2p && !p2p->enabled && p2p->enable_persistent)
686 technology_enabled(p2p);
689 if (technology->tethering_persistent)
690 enable_tethering(technology);
692 powered_changed(technology);
697 static int technology_enable(struct connman_technology *technology)
702 DBG("technology %p enable", technology);
704 __sync_synchronize();
706 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
707 struct connman_technology *wifi;
709 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
710 if (wifi && wifi->enabled)
711 return technology_enabled(technology);
715 if (technology->enabled)
718 if (technology->pending_reply)
721 if (connman_setting_get_bool("PersistentTetheringMode") &&
722 technology->tethering)
723 set_tethering(technology, true);
725 if (technology->rfkill_driven)
726 err = __connman_rfkill_block(technology->type, false);
728 err_dev = technology_affect_devices(technology, true);
730 if (!technology->rfkill_driven)
736 static int technology_disabled(struct connman_technology *technology)
738 __sync_synchronize();
739 if (!technology->enabled)
742 technology->enabled = false;
744 powered_changed(technology);
749 static int technology_disable(struct connman_technology *technology)
753 DBG("technology %p disable", technology);
755 __sync_synchronize();
757 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
758 technology->enable_persistent = false;
759 return technology_disabled(technology);
760 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
761 struct connman_technology *p2p;
763 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
764 if (p2p && p2p->enabled) {
765 p2p->enable_persistent = true;
766 technology_disabled(p2p);
770 if (!technology->enabled)
773 if (technology->pending_reply)
776 if (technology->tethering)
777 set_tethering(technology, false);
779 err = technology_affect_devices(technology, false);
781 if (technology->rfkill_driven)
782 err = __connman_rfkill_block(technology->type, true);
787 static DBusMessage *set_powered(struct connman_technology *technology,
788 DBusMessage *msg, bool powered)
790 DBusMessage *reply = NULL;
793 if (technology->rfkill_driven && technology->hardblocked) {
799 err = technology_enable(technology);
801 err = technology_disable(technology);
804 technology->enable_persistent = powered;
805 technology_save(technology);
809 if (err == -EINPROGRESS) {
810 technology->pending_reply = dbus_message_ref(msg);
811 technology->pending_timeout = g_timeout_add_seconds(10,
812 technology_pending_reply, technology);
813 } else if (err == -EALREADY) {
815 reply = __connman_error_already_enabled(msg);
817 reply = __connman_error_already_disabled(msg);
819 reply = __connman_error_failed(msg, -err);
821 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
826 static DBusMessage *set_property(DBusConnection *conn,
827 DBusMessage *msg, void *data)
829 struct connman_technology *technology = data;
830 DBusMessageIter iter, value;
834 DBG("conn %p", conn);
836 if (!dbus_message_iter_init(msg, &iter))
837 return __connman_error_invalid_arguments(msg);
839 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
840 return __connman_error_invalid_arguments(msg);
842 dbus_message_iter_get_basic(&iter, &name);
843 dbus_message_iter_next(&iter);
845 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
846 return __connman_error_invalid_arguments(msg);
848 dbus_message_iter_recurse(&iter, &value);
850 type = dbus_message_iter_get_arg_type(&value);
852 DBG("property %s", name);
854 if (g_str_equal(name, "Tethering")) {
855 dbus_bool_t tethering;
858 if (type != DBUS_TYPE_BOOLEAN)
859 return __connman_error_invalid_arguments(msg);
861 if (!connman_technology_is_tethering_allowed(technology->type)) {
862 DBG("%s tethering not allowed by config file",
863 __connman_service_type2string(technology->type));
864 return __connman_error_not_supported(msg);
867 dbus_message_iter_get_basic(&value, &tethering);
869 if (technology->tethering == tethering) {
871 return __connman_error_already_disabled(msg);
873 return __connman_error_already_enabled(msg);
876 err = set_tethering(technology, tethering);
878 return __connman_error_failed(msg, -err);
880 technology->tethering_persistent = tethering;
882 technology_save(technology);
884 } else if (g_str_equal(name, "TetheringIdentifier")) {
887 dbus_message_iter_get_basic(&value, &str);
889 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
890 return __connman_error_not_supported(msg);
892 if (strlen(str) < 1 || strlen(str) > 32)
893 return __connman_error_invalid_arguments(msg);
895 if (g_strcmp0(technology->tethering_ident, str) != 0) {
896 g_free(technology->tethering_ident);
897 technology->tethering_ident = g_strdup(str);
898 technology_save(technology);
900 connman_dbus_property_changed_basic(technology->path,
901 CONNMAN_TECHNOLOGY_INTERFACE,
902 "TetheringIdentifier",
904 &technology->tethering_ident);
906 } else if (g_str_equal(name, "TetheringPassphrase")) {
909 dbus_message_iter_get_basic(&value, &str);
911 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
912 return __connman_error_not_supported(msg);
914 if (strlen(str) < 8 || strlen(str) > 63) {
915 if (g_str_equal(str, "")) {
916 technology->tethering_passphrase = NULL;
918 connman_dbus_property_changed_basic(technology->path,
919 CONNMAN_TECHNOLOGY_INTERFACE,
920 "TetheringPassphrase",
925 return __connman_error_passphrase_required(msg);
927 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
928 g_free(technology->tethering_passphrase);
929 technology->tethering_passphrase = g_strdup(str);
930 technology_save(technology);
932 connman_dbus_property_changed_basic(technology->path,
933 CONNMAN_TECHNOLOGY_INTERFACE,
934 "TetheringPassphrase",
936 &technology->tethering_passphrase);
939 } else if (g_str_equal(name, "Powered")) {
942 if (type != DBUS_TYPE_BOOLEAN)
943 return __connman_error_invalid_arguments(msg);
945 dbus_message_iter_get_basic(&value, &enable);
947 return set_powered(technology, msg, enable);
949 return __connman_error_invalid_property(msg);
951 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
954 static void reply_scan_pending(struct connman_technology *technology, int err)
958 DBG("technology %p err %d", technology, err);
960 while (technology->scan_pending) {
961 DBusMessage *msg = technology->scan_pending->data;
963 DBG("reply to %s", dbus_message_get_sender(msg));
966 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
968 reply = __connman_error_failed(msg, -err);
969 g_dbus_send_message(connection, reply);
970 dbus_message_unref(msg);
972 technology->scan_pending =
973 g_slist_delete_link(technology->scan_pending,
974 technology->scan_pending);
978 void __connman_technology_scan_started(struct connman_device *device)
980 DBG("device %p", device);
983 void __connman_technology_scan_stopped(struct connman_device *device,
984 enum connman_service_type type)
987 struct connman_technology *technology;
990 technology = technology_find(type);
992 DBG("technology %p device %p", technology, device);
997 for (list = technology->device_list; list; list = list->next) {
998 struct connman_device *other_device = list->data;
1000 if (device == other_device)
1003 if (__connman_device_get_service_type(other_device) != type)
1006 if (connman_device_get_scanning(other_device))
1011 reply_scan_pending(technology, 0);
1014 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1015 int result, const char *alpha2)
1017 bool regdom_set = false;
1018 struct connman_technology *technology;
1019 enum connman_service_type type;
1020 GSList *tech_drivers;
1022 type = __connman_device_get_service_type(device);
1023 technology = technology_find(type);
1030 for (tech_drivers = technology->driver_list;
1032 tech_drivers = g_slist_next(tech_drivers)) {
1033 struct connman_technology_driver *driver =
1036 if (driver->set_regdom) {
1037 driver->set_regdom(technology, alpha2);
1047 connman_technology_regdom_notify(technology, alpha2);
1050 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1052 struct connman_technology *technology = data;
1055 DBG("technology %p request from %s", technology,
1056 dbus_message_get_sender(msg));
1058 dbus_message_ref(msg);
1059 technology->scan_pending =
1060 g_slist_prepend(technology->scan_pending, msg);
1062 err = __connman_device_request_scan(technology->type);
1064 reply_scan_pending(technology, err);
1069 static const GDBusMethodTable technology_methods[] = {
1070 { GDBUS_DEPRECATED_METHOD("GetProperties",
1071 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1073 { GDBUS_ASYNC_METHOD("SetProperty",
1074 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1075 NULL, set_property) },
1076 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1080 static const GDBusSignalTable technology_signals[] = {
1081 { GDBUS_SIGNAL("PropertyChanged",
1082 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1083 { GDBUS_SIGNAL("DhcpConnected",
1084 GDBUS_ARGS({ "aptype", "s" },
1087 { "hostname", "s" })) },
1088 { GDBUS_SIGNAL("DhcpLeaseDeleted",
1089 GDBUS_ARGS({ "aptype", "s" },
1092 { "hostname", "s" })) },
1096 static bool technology_dbus_register(struct connman_technology *technology)
1098 if (technology->dbus_registered ||
1099 (technology->rfkill_driven &&
1100 technology->hardblocked))
1103 if (!g_dbus_register_interface(connection, technology->path,
1104 CONNMAN_TECHNOLOGY_INTERFACE,
1105 technology_methods, technology_signals,
1106 NULL, technology, NULL)) {
1107 connman_error("Failed to register %s", technology->path);
1111 technology_added_signal(technology);
1112 technology->dbus_registered = true;
1117 static void technology_dbus_unregister(struct connman_technology *technology)
1119 if (!technology->dbus_registered)
1122 technology_removed_signal(technology);
1123 g_dbus_unregister_interface(connection, technology->path,
1124 CONNMAN_TECHNOLOGY_INTERFACE);
1126 technology->dbus_registered = false;
1129 static void technology_put(struct connman_technology *technology)
1131 DBG("technology %p", technology);
1133 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1136 reply_scan_pending(technology, -EINTR);
1138 while (technology->driver_list) {
1139 struct connman_technology_driver *driver;
1141 driver = technology->driver_list->data;
1144 driver->remove(technology);
1146 technology->driver_list =
1147 g_slist_delete_link(technology->driver_list,
1148 technology->driver_list);
1151 technology_list = g_slist_remove(technology_list, technology);
1153 technology_dbus_unregister(technology);
1155 g_slist_free(technology->device_list);
1157 g_free(technology->path);
1158 g_free(technology->regdom);
1159 g_free(technology->tethering_ident);
1160 g_free(technology->tethering_passphrase);
1164 static struct connman_technology *technology_get(enum connman_service_type type)
1166 GSList *tech_drivers = NULL;
1167 struct connman_technology_driver *driver;
1168 struct connman_technology *technology;
1172 DBG("type %d", type);
1174 str = __connman_service_type2string(type);
1178 technology = technology_find(type);
1180 if (type != CONNMAN_SERVICE_TYPE_P2P)
1181 __sync_fetch_and_add(&technology->refcount, 1);
1185 /* First check if we have a driver for this technology type */
1186 for (list = driver_list; list; list = list->next) {
1187 driver = list->data;
1189 if (driver->type == type) {
1190 DBG("technology %p driver %p", technology, driver);
1191 tech_drivers = g_slist_append(tech_drivers, driver);
1195 if (!tech_drivers) {
1196 DBG("No matching drivers found for %s.",
1197 __connman_service_type2string(type));
1201 technology = g_try_new0(struct connman_technology, 1);
1205 technology->refcount = 1;
1206 technology->type = type;
1207 technology->path = g_strdup_printf("%s/technology/%s",
1209 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1210 struct connman_technology *wifi;
1212 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
1214 technology->enabled = wifi->enabled;
1217 technology_load(technology);
1218 technology_list = g_slist_prepend(technology_list, technology);
1219 technology->driver_list = tech_drivers;
1221 for (list = tech_drivers; list; list = list->next) {
1222 driver = list->data;
1224 if (driver->probe && driver->probe(technology) < 0)
1225 DBG("Driver probe failed for technology %p",
1229 if (!technology_dbus_register(technology)) {
1230 technology_put(technology);
1234 DBG("technology %p", technology);
1239 int connman_technology_driver_register(struct connman_technology_driver *driver)
1242 struct connman_device *device;
1243 enum connman_service_type type;
1245 for (list = driver_list; list; list = list->next) {
1246 if (list->data == driver)
1250 DBG("Registering %s driver", driver->name);
1252 driver_list = g_slist_insert_sorted(driver_list, driver,
1256 * Check for technology less devices if this driver
1257 * can service any of them.
1259 for (list = techless_device_list; list; list = list->next) {
1260 device = list->data;
1262 type = __connman_device_get_service_type(device);
1263 if (type != driver->type)
1266 techless_device_list = g_slist_remove(techless_device_list,
1269 __connman_technology_add_device(device);
1272 /* Check for orphaned rfkill switches. */
1273 g_hash_table_foreach(rfkill_list, rfkill_check,
1274 GINT_TO_POINTER(driver->type));
1277 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1278 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
1285 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
1287 GSList *list, *tech_drivers;
1288 struct connman_technology *technology;
1289 struct connman_technology_driver *current;
1291 DBG("Unregistering driver %p name %s", driver, driver->name);
1293 for (list = technology_list; list; list = list->next) {
1294 technology = list->data;
1296 for (tech_drivers = technology->driver_list; tech_drivers;
1297 tech_drivers = g_slist_next(tech_drivers)) {
1298 current = tech_drivers->data;
1299 if (driver != current)
1303 driver->remove(technology);
1305 technology->driver_list =
1306 g_slist_remove(technology->driver_list,
1312 driver_list = g_slist_remove(driver_list, driver);
1314 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1315 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1317 technology_put(technology);
1321 void __connman_technology_add_interface(enum connman_service_type type,
1322 int index, const char *ident)
1324 struct connman_technology *technology;
1325 GSList *tech_drivers;
1326 struct connman_technology_driver *driver;
1330 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1331 case CONNMAN_SERVICE_TYPE_SYSTEM:
1333 case CONNMAN_SERVICE_TYPE_ETHERNET:
1334 case CONNMAN_SERVICE_TYPE_WIFI:
1335 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1336 case CONNMAN_SERVICE_TYPE_CELLULAR:
1337 case CONNMAN_SERVICE_TYPE_GPS:
1338 case CONNMAN_SERVICE_TYPE_VPN:
1339 case CONNMAN_SERVICE_TYPE_GADGET:
1340 case CONNMAN_SERVICE_TYPE_P2P:
1344 name = connman_inet_ifname(index);
1345 connman_info("Adding interface %s [ %s ]", name,
1346 __connman_service_type2string(type));
1348 technology = technology_find(type);
1353 for (tech_drivers = technology->driver_list; tech_drivers;
1354 tech_drivers = g_slist_next(tech_drivers)) {
1355 driver = tech_drivers->data;
1357 if (driver->add_interface)
1358 driver->add_interface(technology, index, name, ident);
1362 * At this point we can try to enable tethering automatically as
1363 * now the interfaces are set properly.
1365 if (technology->tethering_persistent)
1366 enable_tethering(technology);
1372 void __connman_technology_remove_interface(enum connman_service_type type,
1373 int index, const char *ident)
1375 struct connman_technology *technology;
1376 GSList *tech_drivers;
1377 struct connman_technology_driver *driver;
1381 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1382 case CONNMAN_SERVICE_TYPE_SYSTEM:
1384 case CONNMAN_SERVICE_TYPE_ETHERNET:
1385 case CONNMAN_SERVICE_TYPE_WIFI:
1386 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1387 case CONNMAN_SERVICE_TYPE_CELLULAR:
1388 case CONNMAN_SERVICE_TYPE_GPS:
1389 case CONNMAN_SERVICE_TYPE_VPN:
1390 case CONNMAN_SERVICE_TYPE_GADGET:
1391 case CONNMAN_SERVICE_TYPE_P2P:
1395 name = connman_inet_ifname(index);
1396 connman_info("Remove interface %s [ %s ]", name,
1397 __connman_service_type2string(type));
1400 technology = technology_find(type);
1405 for (tech_drivers = technology->driver_list; tech_drivers;
1406 tech_drivers = g_slist_next(tech_drivers)) {
1407 driver = tech_drivers->data;
1409 if (driver->remove_interface)
1410 driver->remove_interface(technology, index);
1414 int __connman_technology_add_device(struct connman_device *device)
1416 struct connman_technology *technology;
1417 enum connman_service_type type;
1419 type = __connman_device_get_service_type(device);
1421 DBG("device %p type %s", device, get_name(type));
1423 technology = technology_get(type);
1426 * Since no driver can be found for this device at the moment we
1427 * add it to the techless device list.
1429 techless_device_list = g_slist_prepend(techless_device_list,
1435 __sync_synchronize();
1436 if (technology->rfkill_driven) {
1437 if (technology->enabled)
1438 __connman_device_enable(device);
1440 __connman_device_disable(device);
1445 if (technology->enable_persistent &&
1446 !global_offlinemode) {
1447 int err = __connman_device_enable(device);
1449 * connman_technology_add_device() calls __connman_device_enable()
1450 * but since the device is already enabled, the calls does not
1451 * propagate through to connman_technology_enabled via
1452 * connman_device_set_powered.
1454 if (err == -EALREADY)
1455 __connman_technology_enabled(type);
1457 /* if technology persistent state is offline */
1458 if (!technology->enable_persistent)
1459 __connman_device_disable(device);
1462 technology->device_list = g_slist_prepend(technology->device_list,
1468 int __connman_technology_remove_device(struct connman_device *device)
1470 struct connman_technology *technology;
1471 enum connman_service_type type;
1473 DBG("device %p", device);
1475 type = __connman_device_get_service_type(device);
1477 technology = technology_find(type);
1479 techless_device_list = g_slist_remove(techless_device_list,
1484 technology->device_list = g_slist_remove(technology->device_list,
1487 if (technology->tethering)
1488 set_tethering(technology, false);
1490 technology_put(technology);
1495 int __connman_technology_enabled(enum connman_service_type type)
1497 struct connman_technology *technology;
1499 technology = technology_find(type);
1503 DBG("technology %p type %s rfkill %d enabled %d", technology,
1504 get_name(type), technology->rfkill_driven,
1505 technology->enabled);
1507 if (technology->rfkill_driven) {
1508 if (technology->tethering_persistent)
1509 enable_tethering(technology);
1513 return technology_enabled(technology);
1516 int __connman_technology_disabled(enum connman_service_type type)
1518 struct connman_technology *technology;
1521 technology = technology_find(type);
1525 if (technology->rfkill_driven)
1528 for (list = technology->device_list; list; list = list->next) {
1529 struct connman_device *device = list->data;
1531 if (connman_device_get_powered(device))
1535 return technology_disabled(technology);
1538 int __connman_technology_set_offlinemode(bool offlinemode)
1541 int err = -EINVAL, enabled_tech_count = 0;
1543 if (global_offlinemode == offlinemode)
1546 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1549 * This is a bit tricky. When you set offlinemode, there is no
1550 * way to differentiate between attempting offline mode and
1551 * resuming offlinemode from last saved profile. We need that
1552 * information in rfkill_update, otherwise it falls back on the
1553 * technology's persistent state. Hence we set the offline mode here
1554 * but save it & call the notifier only if its successful.
1557 global_offlinemode = offlinemode;
1559 /* Traverse technology list, enable/disable each technology. */
1560 for (list = technology_list; list; list = list->next) {
1561 struct connman_technology *technology = list->data;
1564 err = technology_disable(technology);
1566 if (technology->hardblocked)
1569 if (technology->enable_persistent) {
1570 err = technology_enable(technology);
1571 enabled_tech_count++;
1576 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1577 (err == -EINVAL && enabled_tech_count == 0)) {
1578 connman_technology_save_offlinemode();
1579 __connman_notifier_offlinemode(offlinemode);
1581 global_offlinemode = connman_technology_load_offlinemode();
1586 void __connman_technology_set_connected(enum connman_service_type type,
1589 struct connman_technology *technology;
1592 technology = technology_find(type);
1596 DBG("technology %p connected %d", technology, connected);
1598 technology->connected = connected;
1601 connman_dbus_property_changed_basic(technology->path,
1602 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1603 DBUS_TYPE_BOOLEAN, &val);
1606 static bool technology_apply_rfkill_change(struct connman_technology *technology,
1611 bool hardblock_changed = false;
1613 GList *start, *list;
1615 DBG("technology %p --> %d/%d vs %d/%d",
1616 technology, softblock, hardblock,
1617 technology->softblocked, technology->hardblocked);
1619 if (technology->hardblocked == hardblock)
1620 goto softblock_change;
1622 if (!(new_rfkill && !hardblock)) {
1623 start = g_hash_table_get_values(rfkill_list);
1625 for (list = start; list; list = list->next) {
1626 struct connman_rfkill *rfkill = list->data;
1628 if (rfkill->type != technology->type)
1631 if (rfkill->hardblock != hardblock)
1639 goto softblock_change;
1641 technology->hardblocked = hardblock;
1642 hardblock_changed = true;
1645 if (!apply && technology->softblocked != softblock)
1649 return technology->hardblocked;
1651 technology->softblocked = softblock;
1653 if (technology->hardblocked ||
1654 technology->softblocked) {
1655 if (technology_disabled(technology) != -EALREADY)
1656 technology_affect_devices(technology, false);
1657 } else if (!technology->hardblocked &&
1658 !technology->softblocked) {
1659 if (technology_enabled(technology) != -EALREADY)
1660 technology_affect_devices(technology, true);
1663 if (hardblock_changed) {
1664 if (technology->hardblocked) {
1665 DBG("%s is switched off.", get_name(technology->type));
1666 technology_dbus_unregister(technology);
1668 DBG("%s is switched on.", get_name(technology->type));
1669 technology_dbus_register(technology);
1671 if (global_offlinemode)
1672 __connman_rfkill_block(technology->type, true);
1676 return technology->hardblocked;
1679 int __connman_technology_add_rfkill(unsigned int index,
1680 enum connman_service_type type,
1684 struct connman_technology *technology;
1685 struct connman_rfkill *rfkill;
1687 DBG("index %u type %d soft %u hard %u", index, type,
1688 softblock, hardblock);
1690 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1694 rfkill = g_try_new0(struct connman_rfkill, 1);
1698 rfkill->index = index;
1699 rfkill->type = type;
1700 rfkill->softblock = softblock;
1701 rfkill->hardblock = hardblock;
1703 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1706 technology = technology_get(type);
1707 /* If there is no driver for this type, ignore it. */
1711 technology->rfkill_driven = true;
1713 /* If hardblocked, there is no need to handle softblocked state */
1714 if (technology_apply_rfkill_change(technology,
1715 softblock, hardblock, true))
1718 if (global_offlinemode)
1722 * Depending on softblocked state we unblock/block according to
1723 * offlinemode and persistente state.
1725 if (technology->softblocked &&
1726 technology->enable_persistent)
1727 return __connman_rfkill_block(type, false);
1728 else if (!technology->softblocked &&
1729 !technology->enable_persistent)
1730 return __connman_rfkill_block(type, true);
1735 int __connman_technology_update_rfkill(unsigned int index,
1736 enum connman_service_type type,
1740 struct connman_technology *technology;
1741 struct connman_rfkill *rfkill;
1743 DBG("index %u soft %u hard %u", index, softblock, hardblock);
1745 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1749 if (rfkill->softblock == softblock &&
1750 rfkill->hardblock == hardblock)
1753 rfkill->softblock = softblock;
1754 rfkill->hardblock = hardblock;
1756 technology = technology_find(type);
1757 /* If there is no driver for this type, ignore it. */
1761 technology_apply_rfkill_change(technology, softblock, hardblock,
1764 if (technology->hardblocked)
1765 DBG("%s hardblocked", get_name(technology->type));
1767 DBG("%s is%s softblocked", get_name(technology->type),
1768 technology->softblocked ? "" : " not");
1773 int __connman_technology_remove_rfkill(unsigned int index,
1774 enum connman_service_type type)
1776 struct connman_technology *technology;
1777 struct connman_rfkill *rfkill;
1779 DBG("index %u", index);
1781 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1785 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
1787 technology = technology_find(type);
1791 technology_apply_rfkill_change(technology,
1792 technology->softblocked, !technology->hardblocked, false);
1794 technology_put(technology);
1799 int __connman_technology_init(void)
1803 connection = connman_dbus_get_connection();
1805 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1808 global_offlinemode = connman_technology_load_offlinemode();
1810 /* This will create settings file if it is missing */
1811 connman_technology_save_offlinemode();
1816 void __connman_technology_cleanup(void)
1820 g_hash_table_destroy(rfkill_list);
1822 dbus_connection_unref(connection);