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;
48 CONNMAN_SCAN_TYPE_FULL_CHANNEL = 0x00,
49 CONNMAN_SCAN_TYPE_SPECIFIC_AP,
50 CONNMAN_SCAN_TYPE_MULTI_AP,
51 } connman_scan_type_e;
53 static connman_scan_type_e g_scan_type = -1;
56 struct connman_rfkill {
58 enum connman_service_type type;
63 struct connman_technology {
65 enum connman_service_type type;
73 bool tethering_persistent; /* Tells the save status, needed
74 * as offline mode might set
77 char *tethering_ident;
78 char *tethering_passphrase;
79 bool tethering_hidden;
81 bool enable_persistent; /* Save the tech state */
85 DBusMessage *pending_reply;
86 guint pending_timeout;
96 static GSList *driver_list = NULL;
98 static int technology_enabled(struct connman_technology *technology);
99 static int technology_disabled(struct connman_technology *technology);
101 static gint compare_priority(gconstpointer a, gconstpointer b)
103 const struct connman_technology_driver *driver1 = a;
104 const struct connman_technology_driver *driver2 = b;
106 return driver2->priority - driver1->priority;
109 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
111 struct connman_rfkill *rfkill = value;
112 enum connman_service_type type = GPOINTER_TO_INT(user_data);
114 /* Calling _technology_rfkill_add will update the tech. */
115 if (rfkill->type == type)
116 __connman_technology_add_rfkill(rfkill->index, type,
117 rfkill->softblock, rfkill->hardblock);
121 connman_technology_is_tethering_allowed(enum connman_service_type type)
123 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
125 const char *type_str = __connman_service_type2string(type);
132 allowed = connman_setting_get_string_list("TetheringTechnologies");
134 allowed = allowed_default;
136 for (i = 0; allowed[i]; i++) {
137 if (g_strcmp0(allowed[i], type_str) == 0)
144 static const char *get_name(enum connman_service_type type)
147 case CONNMAN_SERVICE_TYPE_UNKNOWN:
148 case CONNMAN_SERVICE_TYPE_SYSTEM:
149 case CONNMAN_SERVICE_TYPE_GPS:
150 case CONNMAN_SERVICE_TYPE_VPN:
152 case CONNMAN_SERVICE_TYPE_GADGET:
154 case CONNMAN_SERVICE_TYPE_ETHERNET:
156 case CONNMAN_SERVICE_TYPE_WIFI:
158 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
160 case CONNMAN_SERVICE_TYPE_CELLULAR:
162 case CONNMAN_SERVICE_TYPE_P2P:
169 static void technology_save(struct connman_technology *technology)
173 const char *name = get_name(technology->type);
175 DBG("technology %p type %d name %s", technology, technology->type,
180 keyfile = __connman_storage_load_global();
182 keyfile = g_key_file_new();
184 identifier = g_strdup_printf("%s", name);
188 g_key_file_set_boolean(keyfile, identifier, "Enable",
189 technology->enable_persistent);
191 g_key_file_set_boolean(keyfile, identifier, "Tethering",
192 technology->tethering_persistent);
194 g_key_file_set_boolean(keyfile, identifier, "Hidden",
195 technology->tethering_hidden);
197 if (technology->tethering_ident)
198 g_key_file_set_string(keyfile, identifier,
199 "Tethering.Identifier",
200 technology->tethering_ident);
202 if (technology->tethering_passphrase)
203 g_key_file_set_string(keyfile, identifier,
204 "Tethering.Passphrase",
205 technology->tethering_passphrase);
210 __connman_storage_save_global(keyfile);
212 g_key_file_free(keyfile);
217 static void tethering_changed(struct connman_technology *technology)
219 dbus_bool_t tethering = technology->tethering;
221 connman_dbus_property_changed_basic(technology->path,
222 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
223 DBUS_TYPE_BOOLEAN, &tethering);
225 technology_save(technology);
228 void connman_technology_tethering_notify(struct connman_technology *technology,
231 DBG("technology %p enabled %u", technology, enabled);
233 if (technology->tethering == enabled)
236 technology->tethering = enabled;
238 tethering_changed(technology);
241 __connman_tethering_set_enabled();
243 __connman_tethering_set_disabled();
246 static int set_tethering(struct connman_technology *technology,
249 int result = -EOPNOTSUPP;
251 const char *ident, *passphrase, *bridge;
252 GSList *tech_drivers;
255 ident = technology->tethering_ident;
256 passphrase = technology->tethering_passphrase;
257 hidden = technology->tethering_hidden;
259 __sync_synchronize();
260 if (!technology->enabled)
263 bridge = __connman_tethering_get_bridge();
267 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && (!ident))
270 for (tech_drivers = technology->driver_list; tech_drivers;
271 tech_drivers = g_slist_next(tech_drivers)) {
272 struct connman_technology_driver *driver = tech_drivers->data;
274 if (!driver || !driver->set_tethering)
277 err = driver->set_tethering(technology, ident, passphrase,
278 bridge, enabled, hidden);
280 if (result == -EINPROGRESS)
283 if (err == -EINPROGRESS || err == 0) {
292 void connman_technology_regdom_notify(struct connman_technology *technology,
298 connman_error("Failed to set regulatory domain");
300 DBG("Regulatory domain set to %s", alpha2);
302 g_free(technology->regdom);
303 technology->regdom = g_strdup(alpha2);
306 static int set_regdom_by_device(struct connman_technology *technology,
311 for (list = technology->device_list; list; list = list->next) {
312 struct connman_device *device = list->data;
314 if (connman_device_set_regdom(device, alpha2) != 0)
321 int connman_technology_set_regdom(const char *alpha2)
323 GSList *list, *tech_drivers;
325 for (list = technology_list; list; list = list->next) {
326 struct connman_technology *technology = list->data;
328 if (set_regdom_by_device(technology, alpha2) != 0) {
330 for (tech_drivers = technology->driver_list;
332 tech_drivers = g_slist_next(tech_drivers)) {
334 struct connman_technology_driver *driver =
337 if (driver->set_regdom)
338 driver->set_regdom(technology, alpha2);
346 static struct connman_technology *technology_find(enum connman_service_type type)
350 DBG("type %d", type);
352 for (list = technology_list; list; list = list->next) {
353 struct connman_technology *technology = list->data;
355 if (technology->type == type)
362 bool connman_technology_get_wifi_tethering(const char **ssid,
365 struct connman_technology *technology;
372 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
376 if (!technology->tethering)
379 *ssid = technology->tethering_ident;
380 *psk = technology->tethering_passphrase;
385 static void free_rfkill(gpointer data)
387 struct connman_rfkill *rfkill = data;
392 static void technology_load(struct connman_technology *technology)
396 GError *error = NULL;
397 bool enable, need_saving = false;
399 DBG("technology %p", technology);
401 keyfile = __connman_storage_load_global();
402 /* Fallback on disabling technology if file not found. */
404 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
405 /* We enable ethernet by default */
406 technology->enable_persistent = true;
408 technology->enable_persistent = false;
412 identifier = g_strdup_printf("%s", get_name(technology->type));
416 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
418 technology->enable_persistent = enable;
420 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
421 technology->enable_persistent = true;
423 technology->enable_persistent = false;
426 g_clear_error(&error);
429 enable = g_key_file_get_boolean(keyfile, identifier,
430 "Tethering", &error);
432 technology->tethering_persistent = enable;
435 g_clear_error(&error);
439 technology_save(technology);
441 technology->tethering_ident = g_key_file_get_string(keyfile,
442 identifier, "Tethering.Identifier", NULL);
444 technology->tethering_passphrase = g_key_file_get_string(keyfile,
445 identifier, "Tethering.Passphrase", NULL);
449 g_key_file_free(keyfile);
454 bool __connman_technology_get_offlinemode(void)
456 return global_offlinemode;
459 static void connman_technology_save_offlinemode(void)
463 keyfile = __connman_storage_load_global();
465 keyfile = g_key_file_new();
467 g_key_file_set_boolean(keyfile, "global",
468 "OfflineMode", global_offlinemode);
470 __connman_storage_save_global(keyfile);
472 g_key_file_free(keyfile);
477 static bool connman_technology_load_offlinemode(void)
480 GError *error = NULL;
483 /* If there is a error, we enable offlinemode */
484 keyfile = __connman_storage_load_global();
488 offlinemode = g_key_file_get_boolean(keyfile, "global",
489 "OfflineMode", &error);
492 g_clear_error(&error);
495 g_key_file_free(keyfile);
500 static void append_properties(DBusMessageIter *iter,
501 struct connman_technology *technology)
503 DBusMessageIter dict;
507 connman_dbus_dict_open(iter, &dict);
509 str = get_name(technology->type);
511 connman_dbus_dict_append_basic(&dict, "Name",
512 DBUS_TYPE_STRING, &str);
514 str = __connman_service_type2string(technology->type);
516 connman_dbus_dict_append_basic(&dict, "Type",
517 DBUS_TYPE_STRING, &str);
519 __sync_synchronize();
520 val = technology->enabled;
521 connman_dbus_dict_append_basic(&dict, "Powered",
525 val = technology->connected;
526 connman_dbus_dict_append_basic(&dict, "Connected",
530 val = technology->tethering;
531 connman_dbus_dict_append_basic(&dict, "Tethering",
535 if (technology->tethering_ident)
536 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
538 &technology->tethering_ident);
540 if (technology->tethering_passphrase)
541 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
543 &technology->tethering_passphrase);
545 val = technology->tethering_hidden;
546 connman_dbus_dict_append_basic(&dict, "Hidden",
550 connman_dbus_dict_close(iter, &dict);
553 static void technology_added_signal(struct connman_technology *technology)
556 DBusMessageIter iter;
558 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
559 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
563 dbus_message_iter_init_append(signal, &iter);
564 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
566 append_properties(&iter, technology);
568 dbus_connection_send(connection, signal, NULL);
569 dbus_message_unref(signal);
572 static void technology_removed_signal(struct connman_technology *technology)
574 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
575 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
576 DBUS_TYPE_OBJECT_PATH, &technology->path,
580 static DBusMessage *get_properties(DBusConnection *conn,
581 DBusMessage *message, void *user_data)
583 struct connman_technology *technology = user_data;
585 DBusMessageIter iter;
587 reply = dbus_message_new_method_return(message);
591 dbus_message_iter_init_append(reply, &iter);
592 append_properties(&iter, technology);
597 void __connman_technology_list_struct(DBusMessageIter *array)
600 DBusMessageIter entry;
602 for (list = technology_list; list; list = list->next) {
603 struct connman_technology *technology = list->data;
605 if (!technology->path ||
606 (technology->rfkill_driven &&
607 technology->hardblocked))
610 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
612 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
614 append_properties(&entry, technology);
615 dbus_message_iter_close_container(array, &entry);
619 static gboolean technology_pending_reply(gpointer user_data)
621 struct connman_technology *technology = user_data;
624 /* Power request timedout, send ETIMEDOUT. */
625 if (technology->pending_reply) {
626 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
628 g_dbus_send_message(connection, reply);
630 dbus_message_unref(technology->pending_reply);
631 technology->pending_reply = NULL;
632 technology->pending_timeout = 0;
638 static int technology_affect_devices(struct connman_technology *technology,
641 int err = 0, err_dev;
644 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
646 __connman_technology_enabled(technology->type);
648 __connman_technology_disabled(technology->type);
652 for (list = technology->device_list; list; list = list->next) {
653 struct connman_device *device = list->data;
656 err_dev = __connman_device_enable(device);
658 err_dev = __connman_device_disable(device);
660 if (err_dev < 0 && err_dev != -EALREADY)
667 static void powered_changed(struct connman_technology *technology)
671 if (!technology->dbus_registered)
674 if (technology->pending_reply) {
675 g_dbus_send_reply(connection,
676 technology->pending_reply, DBUS_TYPE_INVALID);
677 dbus_message_unref(technology->pending_reply);
678 technology->pending_reply = NULL;
680 g_source_remove(technology->pending_timeout);
681 technology->pending_timeout = 0;
684 __sync_synchronize();
685 enabled = technology->enabled;
686 #if defined TIZEN_EXT
687 DBG("ConnMan, Powered : %s, %s",
688 enabled ? "TRUE" : "FALSE",technology->path);
690 connman_dbus_property_changed_basic(technology->path,
691 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
692 DBUS_TYPE_BOOLEAN, &enabled);
695 static void enable_tethering(struct connman_technology *technology)
699 if (!connman_setting_get_bool("PersistentTetheringMode"))
702 ret = set_tethering(technology, true);
703 if (ret < 0 && ret != -EALREADY)
704 DBG("Cannot enable tethering yet for %s (%d/%s)",
705 get_name(technology->type),
706 -ret, strerror(-ret));
709 static int technology_enabled(struct connman_technology *technology)
711 __sync_synchronize();
712 if (technology->enabled)
715 technology->enabled = true;
717 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
718 struct connman_technology *p2p;
720 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
721 if (p2p && !p2p->enabled && p2p->enable_persistent)
722 technology_enabled(p2p);
725 if (technology->tethering_persistent)
726 enable_tethering(technology);
728 powered_changed(technology);
733 static int technology_enable(struct connman_technology *technology)
738 DBG("technology %p enable", technology);
740 __sync_synchronize();
742 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
743 struct connman_technology *wifi;
745 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
746 if (wifi && wifi->enabled)
747 return technology_enabled(technology);
751 if (technology->enabled)
754 if (technology->pending_reply)
757 if (connman_setting_get_bool("PersistentTetheringMode") &&
758 technology->tethering)
759 set_tethering(technology, true);
761 if (technology->rfkill_driven)
762 err = __connman_rfkill_block(technology->type, false);
764 err_dev = technology_affect_devices(technology, true);
766 if (!technology->rfkill_driven)
772 static int technology_disabled(struct connman_technology *technology)
774 __sync_synchronize();
775 if (!technology->enabled)
778 technology->enabled = false;
780 powered_changed(technology);
785 static int technology_disable(struct connman_technology *technology)
789 DBG("technology %p disable", technology);
791 __sync_synchronize();
793 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
794 technology->enable_persistent = false;
795 return technology_disabled(technology);
796 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
797 struct connman_technology *p2p;
799 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
800 if (p2p && p2p->enabled) {
801 p2p->enable_persistent = true;
802 technology_disabled(p2p);
806 if (!technology->enabled)
809 if (technology->pending_reply)
812 if (technology->tethering)
813 set_tethering(technology, false);
815 err = technology_affect_devices(technology, false);
817 if (technology->rfkill_driven)
818 err = __connman_rfkill_block(technology->type, true);
823 static DBusMessage *set_powered(struct connman_technology *technology,
824 DBusMessage *msg, bool powered)
826 DBusMessage *reply = NULL;
829 if (technology->rfkill_driven && technology->hardblocked) {
835 err = technology_enable(technology);
837 err = technology_disable(technology);
840 technology->enable_persistent = powered;
841 technology_save(technology);
845 if (err == -EINPROGRESS) {
846 technology->pending_reply = dbus_message_ref(msg);
847 technology->pending_timeout = g_timeout_add_seconds(10,
848 technology_pending_reply, technology);
849 } else if (err == -EALREADY) {
851 reply = __connman_error_already_enabled(msg);
853 reply = __connman_error_already_disabled(msg);
855 reply = __connman_error_failed(msg, -err);
857 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
862 static DBusMessage *set_property(DBusConnection *conn,
863 DBusMessage *msg, void *data)
865 struct connman_technology *technology = data;
866 DBusMessageIter iter, value;
870 DBG("conn %p", conn);
872 if (!dbus_message_iter_init(msg, &iter))
873 return __connman_error_invalid_arguments(msg);
875 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
876 return __connman_error_invalid_arguments(msg);
878 dbus_message_iter_get_basic(&iter, &name);
879 dbus_message_iter_next(&iter);
881 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
882 return __connman_error_invalid_arguments(msg);
884 dbus_message_iter_recurse(&iter, &value);
886 type = dbus_message_iter_get_arg_type(&value);
888 DBG("property %s", name);
890 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && technology->connected) {
892 if (connman_dbus_get_connection_unix_user_sync(conn,
893 dbus_message_get_sender(msg),
895 DBG("Can not get unix user id!");
896 return __connman_error_permission_denied(msg);
899 if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
900 DBG("Not allow this user to operate wifi technology now!");
901 return __connman_error_permission_denied(msg);
905 if (g_str_equal(name, "Tethering")) {
906 dbus_bool_t tethering;
909 if (type != DBUS_TYPE_BOOLEAN)
910 return __connman_error_invalid_arguments(msg);
912 if (!connman_technology_is_tethering_allowed(technology->type)) {
913 DBG("%s tethering not allowed by config file",
914 __connman_service_type2string(technology->type));
915 return __connman_error_not_supported(msg);
918 dbus_message_iter_get_basic(&value, &tethering);
920 if (technology->tethering == tethering) {
922 return __connman_error_already_disabled(msg);
924 return __connman_error_already_enabled(msg);
927 err = set_tethering(technology, tethering);
929 return __connman_error_failed(msg, -err);
931 technology->tethering_persistent = tethering;
933 technology_save(technology);
935 } else if (g_str_equal(name, "TetheringIdentifier")) {
938 dbus_message_iter_get_basic(&value, &str);
940 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
941 return __connman_error_not_supported(msg);
943 if (strlen(str) < 1 || strlen(str) > 32)
944 return __connman_error_invalid_arguments(msg);
946 if (g_strcmp0(technology->tethering_ident, str) != 0) {
947 g_free(technology->tethering_ident);
948 technology->tethering_ident = g_strdup(str);
949 technology_save(technology);
951 connman_dbus_property_changed_basic(technology->path,
952 CONNMAN_TECHNOLOGY_INTERFACE,
953 "TetheringIdentifier",
955 &technology->tethering_ident);
957 } else if (g_str_equal(name, "TetheringPassphrase")) {
960 dbus_message_iter_get_basic(&value, &str);
962 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
963 return __connman_error_not_supported(msg);
965 if (strlen(str) < 8 || strlen(str) > 63) {
966 if (g_str_equal(str, "")) {
967 technology->tethering_passphrase = NULL;
969 connman_dbus_property_changed_basic(technology->path,
970 CONNMAN_TECHNOLOGY_INTERFACE,
971 "TetheringPassphrase",
976 return __connman_error_passphrase_required(msg);
978 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
979 g_free(technology->tethering_passphrase);
980 technology->tethering_passphrase = g_strdup(str);
981 technology_save(technology);
983 connman_dbus_property_changed_basic(technology->path,
984 CONNMAN_TECHNOLOGY_INTERFACE,
985 "TetheringPassphrase",
987 &technology->tethering_passphrase);
990 } else if (g_str_equal(name, "Hidden")) {
993 if (type != DBUS_TYPE_BOOLEAN)
994 return __connman_error_invalid_arguments(msg);
996 dbus_message_iter_get_basic(&value, &hidden);
998 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
999 return __connman_error_not_supported(msg);
1001 technology->tethering_hidden = hidden;
1002 technology_save(technology);
1004 connman_dbus_property_changed_basic(technology->path,
1005 CONNMAN_TECHNOLOGY_INTERFACE,
1009 } else if (g_str_equal(name, "Powered")) {
1012 if (type != DBUS_TYPE_BOOLEAN)
1013 return __connman_error_invalid_arguments(msg);
1015 dbus_message_iter_get_basic(&value, &enable);
1017 return set_powered(technology, msg, enable);
1019 return __connman_error_invalid_property(msg);
1021 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1024 static void reply_scan_pending(struct connman_technology *technology, int err)
1028 DBG("technology %p err %d", technology, err);
1030 while (technology->scan_pending) {
1031 DBusMessage *msg = technology->scan_pending->data;
1033 DBG("reply to %s", dbus_message_get_sender(msg));
1036 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1038 reply = __connman_error_failed(msg, -err);
1039 g_dbus_send_message(connection, reply);
1040 dbus_message_unref(msg);
1042 technology->scan_pending =
1043 g_slist_delete_link(technology->scan_pending,
1044 technology->scan_pending);
1048 #if defined TIZEN_EXT
1049 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1052 DBusMessage *signal;
1053 DBusMessageIter iter;
1054 dbus_bool_t result = FALSE;
1056 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1057 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1061 dbus_message_iter_init_append(signal, &iter);
1062 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1064 result = dbus_connection_send(connection, signal, NULL);
1065 dbus_message_unref(signal);
1067 DBG("Successfuly sent signal");
1073 void __connman_technology_scan_started(struct connman_device *device)
1075 DBG("device %p", device);
1076 #if defined TIZEN_EXT
1077 dbus_bool_t status = 1;
1078 __connman_technology_notify_scan_changed("scan_started", &status);
1082 void __connman_technology_scan_stopped(struct connman_device *device,
1083 enum connman_service_type type)
1086 struct connman_technology *technology;
1089 technology = technology_find(type);
1091 DBG("technology %p device %p", technology, device);
1096 for (list = technology->device_list; list; list = list->next) {
1097 struct connman_device *other_device = list->data;
1099 if (device == other_device)
1102 if (__connman_device_get_service_type(other_device) != type)
1105 if (connman_device_get_scanning(other_device))
1109 #if defined TIZEN_EXT
1111 DBusMessage *signal;
1112 DBusMessageIter iter;
1113 dbus_bool_t status = 0;
1114 __connman_technology_notify_scan_changed("scan_done", &status);
1116 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1117 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1121 dbus_message_iter_init_append(signal, &iter);
1122 connman_dbus_property_append_basic(&iter, "Scantype",
1123 DBUS_TYPE_INT32, &g_scan_type);
1125 dbus_connection_send(connection, signal, NULL);
1126 dbus_message_unref(signal);
1127 reply_scan_pending(technology, 0);
1129 DBG("Successfuly sent ScanDone signal");
1133 reply_scan_pending(technology, 0);
1137 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1138 int result, const char *alpha2)
1140 bool regdom_set = false;
1141 struct connman_technology *technology;
1142 enum connman_service_type type;
1143 GSList *tech_drivers;
1145 type = __connman_device_get_service_type(device);
1146 technology = technology_find(type);
1153 for (tech_drivers = technology->driver_list;
1155 tech_drivers = g_slist_next(tech_drivers)) {
1156 struct connman_technology_driver *driver =
1159 if (driver->set_regdom) {
1160 driver->set_regdom(technology, alpha2);
1170 connman_technology_regdom_notify(technology, alpha2);
1173 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1175 struct connman_technology *technology = data;
1178 DBG("technology %p request from %s", technology,
1179 dbus_message_get_sender(msg));
1181 dbus_message_ref(msg);
1182 technology->scan_pending =
1183 g_slist_prepend(technology->scan_pending, msg);
1185 err = __connman_device_request_scan(technology->type);
1187 reply_scan_pending(technology, err);
1189 #if defined TIZEN_EXT
1191 g_scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1192 DBG("g_scan_type %d", g_scan_type);
1198 #if defined TIZEN_EXT
1199 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1201 struct connman_technology *technology = data;
1202 GSList *specific_scan_list = NULL;
1204 const char *name = NULL;
1205 unsigned int freq = 0;
1206 DBusMessageIter iter, dict;
1209 DBG("technology %p request from %s", technology,
1210 dbus_message_get_sender(msg));
1212 if (!dbus_message_iter_init(msg, &iter))
1213 return __connman_error_invalid_arguments(msg);
1215 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1216 return __connman_error_invalid_arguments(msg);
1218 dbus_message_iter_recurse(&iter, &dict);
1219 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1220 DBusMessageIter entry, value2;
1224 dbus_message_iter_recurse(&dict, &entry);
1225 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1226 return __connman_error_invalid_arguments(msg);
1228 dbus_message_iter_get_basic(&entry, &key);
1229 dbus_message_iter_next(&entry);
1231 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1232 return __connman_error_invalid_arguments(msg);
1234 dbus_message_iter_recurse(&entry, &value2);
1235 type = dbus_message_iter_get_arg_type(&value2);
1236 if (g_str_equal(key, "SSID")) {
1237 if (type != DBUS_TYPE_STRING)
1238 return __connman_error_invalid_arguments(msg);
1240 scan_type = 1; /* SSID based scan */
1241 dbus_message_iter_get_basic(&value2, &name);
1242 DBG("name %s", name);
1243 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1244 } else if (g_str_equal(key, "Frequency")) {
1245 if (type != DBUS_TYPE_UINT16) {
1246 g_slist_free_full(specific_scan_list, g_free);
1247 return __connman_error_invalid_arguments(msg);
1250 scan_type = 2; /* Frequency based scan */
1251 dbus_message_iter_get_basic(&value2, &freq);
1252 DBG("freq %d", freq);
1253 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(freq));
1255 dbus_message_iter_next(&dict);
1258 dbus_message_ref(msg);
1259 technology->scan_pending =
1260 g_slist_prepend(technology->scan_pending, msg);
1262 err = __connman_device_request_specific_scan(technology->type, scan_type, specific_scan_list);
1264 reply_scan_pending(technology, err);
1267 guint list_size = g_slist_length(specific_scan_list);
1269 g_scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1271 g_scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1272 DBG("list_size %u g_scan_type %d", list_size, g_scan_type);
1275 if (scan_type == 1) {
1276 g_slist_free_full(specific_scan_list, g_free);
1282 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
1285 DBusMessageIter iter, dict;
1287 struct connman_technology *technology = data;
1288 dbus_bool_t scanning = false;
1290 DBG("technology %p", technology);
1292 for (list = technology->device_list; list; list = list->next) {
1293 struct connman_device *device = list->data;
1294 scanning = connman_device_get_scanning(device);
1299 DBG("scanning : %d", scanning);
1300 reply = dbus_message_new_method_return(msg);
1304 dbus_message_iter_init_append(reply, &iter);
1306 connman_dbus_dict_open(&iter, &dict);
1307 connman_dbus_dict_append_basic(&dict, "Scanstate",
1311 connman_dbus_dict_close(&iter, &dict);
1317 static const GDBusMethodTable technology_methods[] = {
1318 { GDBUS_DEPRECATED_METHOD("GetProperties",
1319 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1321 { GDBUS_ASYNC_METHOD("SetProperty",
1322 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1323 NULL, set_property) },
1324 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1325 #if defined TIZEN_EXT
1326 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
1327 NULL, specific_scan) },
1328 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
1334 static const GDBusSignalTable technology_signals[] = {
1335 { GDBUS_SIGNAL("PropertyChanged",
1336 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1337 { GDBUS_SIGNAL("DhcpConnected",
1338 GDBUS_ARGS({ "aptype", "s" },
1341 { "hostname", "s" })) },
1342 { GDBUS_SIGNAL("DhcpLeaseDeleted",
1343 GDBUS_ARGS({ "aptype", "s" },
1346 { "hostname", "s" })) },
1350 static bool technology_dbus_register(struct connman_technology *technology)
1352 if (technology->dbus_registered ||
1353 (technology->rfkill_driven &&
1354 technology->hardblocked))
1357 if (!g_dbus_register_interface(connection, technology->path,
1358 CONNMAN_TECHNOLOGY_INTERFACE,
1359 technology_methods, technology_signals,
1360 NULL, technology, NULL)) {
1361 connman_error("Failed to register %s", technology->path);
1365 technology_added_signal(technology);
1366 technology->dbus_registered = true;
1371 static void technology_dbus_unregister(struct connman_technology *technology)
1373 if (!technology->dbus_registered)
1376 technology_removed_signal(technology);
1377 g_dbus_unregister_interface(connection, technology->path,
1378 CONNMAN_TECHNOLOGY_INTERFACE);
1380 technology->dbus_registered = false;
1383 static void technology_put(struct connman_technology *technology)
1385 DBG("technology %p", technology);
1387 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1390 reply_scan_pending(technology, -EINTR);
1392 while (technology->driver_list) {
1393 struct connman_technology_driver *driver;
1395 driver = technology->driver_list->data;
1398 driver->remove(technology);
1400 technology->driver_list =
1401 g_slist_delete_link(technology->driver_list,
1402 technology->driver_list);
1405 technology_list = g_slist_remove(technology_list, technology);
1407 technology_dbus_unregister(technology);
1409 g_slist_free(technology->device_list);
1411 g_free(technology->path);
1412 g_free(technology->regdom);
1413 g_free(technology->tethering_ident);
1414 g_free(technology->tethering_passphrase);
1418 static struct connman_technology *technology_get(enum connman_service_type type)
1420 GSList *tech_drivers = NULL;
1421 struct connman_technology_driver *driver;
1422 struct connman_technology *technology;
1426 DBG("type %d", type);
1428 str = __connman_service_type2string(type);
1432 technology = technology_find(type);
1434 if (type != CONNMAN_SERVICE_TYPE_P2P)
1435 __sync_fetch_and_add(&technology->refcount, 1);
1439 /* First check if we have a driver for this technology type */
1440 for (list = driver_list; list; list = list->next) {
1441 driver = list->data;
1443 if (driver->type == type) {
1444 DBG("technology %p driver %p", technology, driver);
1445 tech_drivers = g_slist_append(tech_drivers, driver);
1449 if (!tech_drivers) {
1450 DBG("No matching drivers found for %s.",
1451 __connman_service_type2string(type));
1455 technology = g_try_new0(struct connman_technology, 1);
1459 technology->refcount = 1;
1460 technology->type = type;
1461 technology->tethering_hidden = FALSE;
1462 technology->path = g_strdup_printf("%s/technology/%s",
1465 technology_load(technology);
1466 technology_list = g_slist_prepend(technology_list, technology);
1467 technology->driver_list = tech_drivers;
1469 for (list = tech_drivers; list; list = list->next) {
1470 driver = list->data;
1472 if (driver->probe && driver->probe(technology) < 0)
1473 DBG("Driver probe failed for technology %p",
1477 if (!technology_dbus_register(technology)) {
1478 technology_put(technology);
1482 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1483 struct connman_technology *wifi;
1486 enable = technology->enable_persistent;
1488 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
1490 enable = wifi->enabled;
1492 technology_affect_devices(technology, enable);
1495 DBG("technology %p %s", technology, get_name(technology->type));
1500 int connman_technology_driver_register(struct connman_technology_driver *driver)
1503 struct connman_device *device;
1504 enum connman_service_type type;
1506 for (list = driver_list; list; list = list->next) {
1507 if (list->data == driver)
1511 DBG("Registering %s driver", driver->name);
1513 driver_list = g_slist_insert_sorted(driver_list, driver,
1517 * Check for technology less devices if this driver
1518 * can service any of them.
1520 for (list = techless_device_list; list; list = list->next) {
1521 device = list->data;
1523 type = __connman_device_get_service_type(device);
1524 if (type != driver->type)
1527 techless_device_list = g_slist_remove(techless_device_list,
1530 __connman_technology_add_device(device);
1533 /* Check for orphaned rfkill switches. */
1534 g_hash_table_foreach(rfkill_list, rfkill_check,
1535 GINT_TO_POINTER(driver->type));
1538 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1539 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
1546 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
1548 GSList *list, *tech_drivers;
1549 struct connman_technology *technology;
1550 struct connman_technology_driver *current;
1552 DBG("Unregistering driver %p name %s", driver, driver->name);
1554 for (list = technology_list; list; list = list->next) {
1555 technology = list->data;
1557 for (tech_drivers = technology->driver_list; tech_drivers;
1558 tech_drivers = g_slist_next(tech_drivers)) {
1559 current = tech_drivers->data;
1560 if (driver != current)
1564 driver->remove(technology);
1566 technology->driver_list =
1567 g_slist_remove(technology->driver_list,
1573 driver_list = g_slist_remove(driver_list, driver);
1575 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1576 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1578 technology_put(technology);
1582 void __connman_technology_add_interface(enum connman_service_type type,
1583 int index, const char *ident)
1585 struct connman_technology *technology;
1586 GSList *tech_drivers;
1587 struct connman_technology_driver *driver;
1591 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1592 case CONNMAN_SERVICE_TYPE_SYSTEM:
1594 case CONNMAN_SERVICE_TYPE_ETHERNET:
1595 case CONNMAN_SERVICE_TYPE_WIFI:
1596 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1597 case CONNMAN_SERVICE_TYPE_CELLULAR:
1598 case CONNMAN_SERVICE_TYPE_GPS:
1599 case CONNMAN_SERVICE_TYPE_VPN:
1600 case CONNMAN_SERVICE_TYPE_GADGET:
1601 case CONNMAN_SERVICE_TYPE_P2P:
1605 name = connman_inet_ifname(index);
1606 connman_info("Adding interface %s [ %s ]", name,
1607 __connman_service_type2string(type));
1609 technology = technology_find(type);
1614 for (tech_drivers = technology->driver_list; tech_drivers;
1615 tech_drivers = g_slist_next(tech_drivers)) {
1616 driver = tech_drivers->data;
1618 if (driver->add_interface)
1619 driver->add_interface(technology, index, name, ident);
1623 * At this point we can try to enable tethering automatically as
1624 * now the interfaces are set properly.
1626 if (technology->tethering_persistent)
1627 enable_tethering(technology);
1633 void __connman_technology_remove_interface(enum connman_service_type type,
1634 int index, const char *ident)
1636 struct connman_technology *technology;
1637 GSList *tech_drivers;
1638 struct connman_technology_driver *driver;
1642 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1643 case CONNMAN_SERVICE_TYPE_SYSTEM:
1645 case CONNMAN_SERVICE_TYPE_ETHERNET:
1646 case CONNMAN_SERVICE_TYPE_WIFI:
1647 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1648 case CONNMAN_SERVICE_TYPE_CELLULAR:
1649 case CONNMAN_SERVICE_TYPE_GPS:
1650 case CONNMAN_SERVICE_TYPE_VPN:
1651 case CONNMAN_SERVICE_TYPE_GADGET:
1652 case CONNMAN_SERVICE_TYPE_P2P:
1656 name = connman_inet_ifname(index);
1657 connman_info("Remove interface %s [ %s ]", name,
1658 __connman_service_type2string(type));
1661 technology = technology_find(type);
1666 for (tech_drivers = technology->driver_list; tech_drivers;
1667 tech_drivers = g_slist_next(tech_drivers)) {
1668 driver = tech_drivers->data;
1670 if (driver->remove_interface)
1671 driver->remove_interface(technology, index);
1675 int __connman_technology_add_device(struct connman_device *device)
1677 struct connman_technology *technology;
1678 enum connman_service_type type;
1680 type = __connman_device_get_service_type(device);
1682 DBG("device %p type %s", device, get_name(type));
1684 technology = technology_get(type);
1687 * Since no driver can be found for this device at the moment we
1688 * add it to the techless device list.
1690 techless_device_list = g_slist_prepend(techless_device_list,
1696 __sync_synchronize();
1697 if (technology->rfkill_driven) {
1698 if (technology->enabled)
1699 __connman_device_enable(device);
1701 __connman_device_disable(device);
1706 if (technology->enable_persistent &&
1707 !global_offlinemode) {
1708 int err = __connman_device_enable(device);
1710 * connman_technology_add_device() calls __connman_device_enable()
1711 * but since the device is already enabled, the calls does not
1712 * propagate through to connman_technology_enabled via
1713 * connman_device_set_powered.
1715 if (err == -EALREADY)
1716 __connman_technology_enabled(type);
1718 /* if technology persistent state is offline */
1719 if (!technology->enable_persistent)
1720 __connman_device_disable(device);
1723 technology->device_list = g_slist_prepend(technology->device_list,
1729 int __connman_technology_remove_device(struct connman_device *device)
1731 struct connman_technology *technology;
1732 enum connman_service_type type;
1734 DBG("device %p", device);
1736 type = __connman_device_get_service_type(device);
1738 technology = technology_find(type);
1740 techless_device_list = g_slist_remove(techless_device_list,
1745 technology->device_list = g_slist_remove(technology->device_list,
1748 if (technology->tethering)
1749 set_tethering(technology, false);
1751 technology_put(technology);
1756 int __connman_technology_enabled(enum connman_service_type type)
1758 struct connman_technology *technology;
1760 technology = technology_find(type);
1764 DBG("technology %p type %s rfkill %d enabled %d", technology,
1765 get_name(type), technology->rfkill_driven,
1766 technology->enabled);
1767 #if !defined TIZEN_EXT
1768 if (technology->rfkill_driven) {
1769 if (technology->tethering_persistent)
1770 enable_tethering(technology);
1775 return technology_enabled(technology);
1778 int __connman_technology_disabled(enum connman_service_type type)
1780 struct connman_technology *technology;
1783 technology = technology_find(type);
1786 #if !defined TIZEN_EXT
1787 if (technology->rfkill_driven)
1790 for (list = technology->device_list; list; list = list->next) {
1791 struct connman_device *device = list->data;
1793 if (connman_device_get_powered(device))
1797 return technology_disabled(technology);
1800 int __connman_technology_set_offlinemode(bool offlinemode)
1803 int err = -EINVAL, enabled_tech_count = 0;
1805 if (global_offlinemode == offlinemode)
1808 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1811 * This is a bit tricky. When you set offlinemode, there is no
1812 * way to differentiate between attempting offline mode and
1813 * resuming offlinemode from last saved profile. We need that
1814 * information in rfkill_update, otherwise it falls back on the
1815 * technology's persistent state. Hence we set the offline mode here
1816 * but save it & call the notifier only if its successful.
1819 global_offlinemode = offlinemode;
1821 /* Traverse technology list, enable/disable each technology. */
1822 for (list = technology_list; list; list = list->next) {
1823 struct connman_technology *technology = list->data;
1826 err = technology_disable(technology);
1828 if (technology->hardblocked)
1831 if (technology->enable_persistent) {
1832 err = technology_enable(technology);
1833 enabled_tech_count++;
1838 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1839 (err == -EINVAL && enabled_tech_count == 0)) {
1840 connman_technology_save_offlinemode();
1841 __connman_notifier_offlinemode(offlinemode);
1843 global_offlinemode = connman_technology_load_offlinemode();
1848 void __connman_technology_set_connected(enum connman_service_type type,
1851 struct connman_technology *technology;
1854 technology = technology_find(type);
1858 DBG("technology %p connected %d", technology, connected);
1860 technology->connected = connected;
1863 connman_dbus_property_changed_basic(technology->path,
1864 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1865 DBUS_TYPE_BOOLEAN, &val);
1868 static bool technology_apply_rfkill_change(struct connman_technology *technology,
1873 bool hardblock_changed = false;
1875 GList *start, *list;
1877 DBG("technology %p --> %d/%d vs %d/%d",
1878 technology, softblock, hardblock,
1879 technology->softblocked, technology->hardblocked);
1881 if (technology->hardblocked == hardblock)
1882 goto softblock_change;
1884 if (!(new_rfkill && !hardblock)) {
1885 start = g_hash_table_get_values(rfkill_list);
1887 for (list = start; list; list = list->next) {
1888 struct connman_rfkill *rfkill = list->data;
1890 if (rfkill->type != technology->type)
1893 if (rfkill->hardblock != hardblock)
1901 goto softblock_change;
1903 technology->hardblocked = hardblock;
1904 hardblock_changed = true;
1907 if (!apply && technology->softblocked != softblock)
1911 return technology->hardblocked;
1913 technology->softblocked = softblock;
1915 if (technology->hardblocked ||
1916 technology->softblocked) {
1917 if (technology_disabled(technology) != -EALREADY)
1918 technology_affect_devices(technology, false);
1919 } else if (!technology->hardblocked &&
1920 !technology->softblocked) {
1921 if (technology_enabled(technology) != -EALREADY)
1922 technology_affect_devices(technology, true);
1925 if (hardblock_changed) {
1926 if (technology->hardblocked) {
1927 DBG("%s is switched off.", get_name(technology->type));
1928 technology_dbus_unregister(technology);
1930 DBG("%s is switched on.", get_name(technology->type));
1931 technology_dbus_register(technology);
1933 if (global_offlinemode)
1934 __connman_rfkill_block(technology->type, true);
1938 return technology->hardblocked;
1941 int __connman_technology_add_rfkill(unsigned int index,
1942 enum connman_service_type type,
1946 struct connman_technology *technology;
1947 struct connman_rfkill *rfkill;
1949 DBG("index %u type %d soft %u hard %u", index, type,
1950 softblock, hardblock);
1952 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1956 rfkill = g_try_new0(struct connman_rfkill, 1);
1960 rfkill->index = index;
1961 rfkill->type = type;
1962 rfkill->softblock = softblock;
1963 rfkill->hardblock = hardblock;
1965 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1968 #if defined TIZEN_EXT
1969 /* Fix Svace Issue [WGID: 1348]. */
1972 technology = technology_get(type);
1973 /* If there is no driver for this type, ignore it. */
1977 technology->rfkill_driven = true;
1979 #if !defined TIZEN_EXT
1980 /* If hardblocked, there is no need to handle softblocked state */
1981 if (technology_apply_rfkill_change(technology,
1982 softblock, hardblock, true))
1985 if (global_offlinemode)
1989 * Depending on softblocked state we unblock/block according to
1990 * offlinemode and persistente state.
1992 if (technology->softblocked &&
1993 technology->enable_persistent)
1994 return __connman_rfkill_block(type, false);
1995 else if (!technology->softblocked &&
1996 !technology->enable_persistent)
1997 return __connman_rfkill_block(type, true);
2002 int __connman_technology_update_rfkill(unsigned int index,
2003 enum connman_service_type type,
2007 struct connman_technology *technology;
2008 struct connman_rfkill *rfkill;
2010 DBG("index %u soft %u hard %u", index, softblock, hardblock);
2012 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2016 if (rfkill->softblock == softblock &&
2017 rfkill->hardblock == hardblock)
2020 rfkill->softblock = softblock;
2021 rfkill->hardblock = hardblock;
2023 technology = technology_find(type);
2024 /* If there is no driver for this type, ignore it. */
2028 technology_apply_rfkill_change(technology, softblock, hardblock,
2031 if (technology->hardblocked)
2032 DBG("%s hardblocked", get_name(technology->type));
2034 DBG("%s is%s softblocked", get_name(technology->type),
2035 technology->softblocked ? "" : " not");
2040 int __connman_technology_remove_rfkill(unsigned int index,
2041 enum connman_service_type type)
2043 struct connman_technology *technology;
2044 struct connman_rfkill *rfkill;
2046 DBG("index %u", index);
2048 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2052 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
2054 technology = technology_find(type);
2058 technology_apply_rfkill_change(technology,
2059 technology->softblocked, !technology->hardblocked, false);
2061 technology_put(technology);
2066 int __connman_technology_init(void)
2070 connection = connman_dbus_get_connection();
2072 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2075 global_offlinemode = connman_technology_load_offlinemode();
2077 /* This will create settings file if it is missing */
2078 connman_technology_save_offlinemode();
2083 void __connman_technology_cleanup(void)
2087 while (technology_list) {
2088 struct connman_technology *technology = technology_list->data;
2089 technology_list = g_slist_remove(technology_list, technology);
2090 technology_put(technology);
2093 g_hash_table_destroy(rfkill_list);
2095 dbus_connection_unref(connection);