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 #if !defined TIZEN_EXT
1183 technology->scan_pending =
1184 g_slist_prepend(technology->scan_pending, msg);
1187 err = __connman_device_request_scan(technology->type);
1188 #if defined TIZEN_EXT
1190 return __connman_error_failed(msg, -err);
1193 reply_scan_pending(technology, err);
1196 #if defined TIZEN_EXT
1198 g_scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1199 DBG("g_scan_type %d", g_scan_type);
1201 technology->scan_pending =
1202 g_slist_prepend(technology->scan_pending, msg);
1207 #if defined TIZEN_EXT
1208 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1210 struct connman_technology *technology = data;
1211 GSList *specific_scan_list = NULL;
1213 const char *name = NULL;
1214 unsigned int freq = 0;
1215 DBusMessageIter iter, dict;
1218 DBG("technology %p request from %s", technology,
1219 dbus_message_get_sender(msg));
1221 if (!dbus_message_iter_init(msg, &iter))
1222 return __connman_error_invalid_arguments(msg);
1224 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1225 return __connman_error_invalid_arguments(msg);
1227 dbus_message_iter_recurse(&iter, &dict);
1228 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1229 DBusMessageIter entry, value2;
1233 dbus_message_iter_recurse(&dict, &entry);
1234 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1235 return __connman_error_invalid_arguments(msg);
1237 dbus_message_iter_get_basic(&entry, &key);
1238 dbus_message_iter_next(&entry);
1240 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1241 return __connman_error_invalid_arguments(msg);
1243 dbus_message_iter_recurse(&entry, &value2);
1244 type = dbus_message_iter_get_arg_type(&value2);
1245 if (g_str_equal(key, "SSID")) {
1246 if (type != DBUS_TYPE_STRING)
1247 return __connman_error_invalid_arguments(msg);
1249 scan_type = 1; /* SSID based scan */
1250 dbus_message_iter_get_basic(&value2, &name);
1251 DBG("name %s", name);
1252 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1253 } else if (g_str_equal(key, "Frequency")) {
1254 if (type != DBUS_TYPE_UINT16) {
1255 g_slist_free_full(specific_scan_list, g_free);
1256 return __connman_error_invalid_arguments(msg);
1259 scan_type = 2; /* Frequency based scan */
1260 dbus_message_iter_get_basic(&value2, &freq);
1261 DBG("freq %d", freq);
1262 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(freq));
1264 dbus_message_iter_next(&dict);
1267 dbus_message_ref(msg);
1269 err = __connman_device_request_specific_scan(technology->type, scan_type, specific_scan_list);
1271 return __connman_error_failed(msg, -err);
1274 guint list_size = g_slist_length(specific_scan_list);
1276 g_scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1278 g_scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1279 DBG("list_size %u g_scan_type %d", list_size, g_scan_type);
1281 technology->scan_pending =
1282 g_slist_prepend(technology->scan_pending, msg);
1284 if (scan_type == 1) {
1285 g_slist_free_full(specific_scan_list, g_free);
1291 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
1294 DBusMessageIter iter, dict;
1296 struct connman_technology *technology = data;
1297 dbus_bool_t scanning = false;
1299 DBG("technology %p", technology);
1301 for (list = technology->device_list; list; list = list->next) {
1302 struct connman_device *device = list->data;
1303 scanning = connman_device_get_scanning(device);
1308 DBG("scanning : %d", scanning);
1309 reply = dbus_message_new_method_return(msg);
1313 dbus_message_iter_init_append(reply, &iter);
1315 connman_dbus_dict_open(&iter, &dict);
1316 connman_dbus_dict_append_basic(&dict, "Scanstate",
1320 connman_dbus_dict_close(&iter, &dict);
1326 static const GDBusMethodTable technology_methods[] = {
1327 { GDBUS_DEPRECATED_METHOD("GetProperties",
1328 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1330 { GDBUS_ASYNC_METHOD("SetProperty",
1331 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1332 NULL, set_property) },
1333 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1334 #if defined TIZEN_EXT
1335 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
1336 NULL, specific_scan) },
1337 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
1343 static const GDBusSignalTable technology_signals[] = {
1344 { GDBUS_SIGNAL("PropertyChanged",
1345 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1346 { GDBUS_SIGNAL("DhcpConnected",
1347 GDBUS_ARGS({ "aptype", "s" },
1350 { "hostname", "s" })) },
1351 { GDBUS_SIGNAL("DhcpLeaseDeleted",
1352 GDBUS_ARGS({ "aptype", "s" },
1355 { "hostname", "s" })) },
1359 static bool technology_dbus_register(struct connman_technology *technology)
1361 if (technology->dbus_registered ||
1362 (technology->rfkill_driven &&
1363 technology->hardblocked))
1366 if (!g_dbus_register_interface(connection, technology->path,
1367 CONNMAN_TECHNOLOGY_INTERFACE,
1368 technology_methods, technology_signals,
1369 NULL, technology, NULL)) {
1370 connman_error("Failed to register %s", technology->path);
1374 technology_added_signal(technology);
1375 technology->dbus_registered = true;
1380 static void technology_dbus_unregister(struct connman_technology *technology)
1382 if (!technology->dbus_registered)
1385 technology_removed_signal(technology);
1386 g_dbus_unregister_interface(connection, technology->path,
1387 CONNMAN_TECHNOLOGY_INTERFACE);
1389 technology->dbus_registered = false;
1392 static void technology_put(struct connman_technology *technology)
1394 DBG("technology %p", technology);
1396 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1399 reply_scan_pending(technology, -EINTR);
1401 while (technology->driver_list) {
1402 struct connman_technology_driver *driver;
1404 driver = technology->driver_list->data;
1407 driver->remove(technology);
1409 technology->driver_list =
1410 g_slist_delete_link(technology->driver_list,
1411 technology->driver_list);
1414 technology_list = g_slist_remove(technology_list, technology);
1416 technology_dbus_unregister(technology);
1418 g_slist_free(technology->device_list);
1420 g_free(technology->path);
1421 g_free(technology->regdom);
1422 g_free(technology->tethering_ident);
1423 g_free(technology->tethering_passphrase);
1427 static struct connman_technology *technology_get(enum connman_service_type type)
1429 GSList *tech_drivers = NULL;
1430 struct connman_technology_driver *driver;
1431 struct connman_technology *technology;
1435 DBG("type %d", type);
1437 str = __connman_service_type2string(type);
1441 technology = technology_find(type);
1443 if (type != CONNMAN_SERVICE_TYPE_P2P)
1444 __sync_fetch_and_add(&technology->refcount, 1);
1448 /* First check if we have a driver for this technology type */
1449 for (list = driver_list; list; list = list->next) {
1450 driver = list->data;
1452 if (driver->type == type) {
1453 DBG("technology %p driver %p", technology, driver);
1454 tech_drivers = g_slist_append(tech_drivers, driver);
1458 if (!tech_drivers) {
1459 DBG("No matching drivers found for %s.",
1460 __connman_service_type2string(type));
1464 technology = g_try_new0(struct connman_technology, 1);
1468 technology->refcount = 1;
1469 technology->type = type;
1470 technology->tethering_hidden = FALSE;
1471 technology->path = g_strdup_printf("%s/technology/%s",
1474 technology_load(technology);
1475 technology_list = g_slist_prepend(technology_list, technology);
1476 technology->driver_list = tech_drivers;
1478 for (list = tech_drivers; list; list = list->next) {
1479 driver = list->data;
1481 if (driver->probe && driver->probe(technology) < 0)
1482 DBG("Driver probe failed for technology %p",
1486 if (!technology_dbus_register(technology)) {
1487 technology_put(technology);
1491 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1492 struct connman_technology *wifi;
1495 enable = technology->enable_persistent;
1497 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
1499 enable = wifi->enabled;
1501 technology_affect_devices(technology, enable);
1504 DBG("technology %p %s", technology, get_name(technology->type));
1509 int connman_technology_driver_register(struct connman_technology_driver *driver)
1512 struct connman_device *device;
1513 enum connman_service_type type;
1515 for (list = driver_list; list; list = list->next) {
1516 if (list->data == driver)
1520 DBG("Registering %s driver", driver->name);
1522 driver_list = g_slist_insert_sorted(driver_list, driver,
1526 * Check for technology less devices if this driver
1527 * can service any of them.
1529 for (list = techless_device_list; list; list = list->next) {
1530 device = list->data;
1532 type = __connman_device_get_service_type(device);
1533 if (type != driver->type)
1536 techless_device_list = g_slist_remove(techless_device_list,
1539 __connman_technology_add_device(device);
1542 /* Check for orphaned rfkill switches. */
1543 g_hash_table_foreach(rfkill_list, rfkill_check,
1544 GINT_TO_POINTER(driver->type));
1547 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1548 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
1555 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
1557 GSList *list, *tech_drivers;
1558 struct connman_technology *technology;
1559 struct connman_technology_driver *current;
1561 DBG("Unregistering driver %p name %s", driver, driver->name);
1563 for (list = technology_list; list; list = list->next) {
1564 technology = list->data;
1566 for (tech_drivers = technology->driver_list; tech_drivers;
1567 tech_drivers = g_slist_next(tech_drivers)) {
1568 current = tech_drivers->data;
1569 if (driver != current)
1573 driver->remove(technology);
1575 technology->driver_list =
1576 g_slist_remove(technology->driver_list,
1582 driver_list = g_slist_remove(driver_list, driver);
1584 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1585 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1587 technology_put(technology);
1591 void __connman_technology_add_interface(enum connman_service_type type,
1592 int index, const char *ident)
1594 struct connman_technology *technology;
1595 GSList *tech_drivers;
1596 struct connman_technology_driver *driver;
1600 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1601 case CONNMAN_SERVICE_TYPE_SYSTEM:
1603 case CONNMAN_SERVICE_TYPE_ETHERNET:
1604 case CONNMAN_SERVICE_TYPE_WIFI:
1605 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1606 case CONNMAN_SERVICE_TYPE_CELLULAR:
1607 case CONNMAN_SERVICE_TYPE_GPS:
1608 case CONNMAN_SERVICE_TYPE_VPN:
1609 case CONNMAN_SERVICE_TYPE_GADGET:
1610 case CONNMAN_SERVICE_TYPE_P2P:
1614 name = connman_inet_ifname(index);
1615 connman_info("Adding interface %s [ %s ]", name,
1616 __connman_service_type2string(type));
1618 technology = technology_find(type);
1623 for (tech_drivers = technology->driver_list; tech_drivers;
1624 tech_drivers = g_slist_next(tech_drivers)) {
1625 driver = tech_drivers->data;
1627 if (driver->add_interface)
1628 driver->add_interface(technology, index, name, ident);
1632 * At this point we can try to enable tethering automatically as
1633 * now the interfaces are set properly.
1635 if (technology->tethering_persistent)
1636 enable_tethering(technology);
1642 void __connman_technology_remove_interface(enum connman_service_type type,
1643 int index, const char *ident)
1645 struct connman_technology *technology;
1646 GSList *tech_drivers;
1647 struct connman_technology_driver *driver;
1651 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1652 case CONNMAN_SERVICE_TYPE_SYSTEM:
1654 case CONNMAN_SERVICE_TYPE_ETHERNET:
1655 case CONNMAN_SERVICE_TYPE_WIFI:
1656 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1657 case CONNMAN_SERVICE_TYPE_CELLULAR:
1658 case CONNMAN_SERVICE_TYPE_GPS:
1659 case CONNMAN_SERVICE_TYPE_VPN:
1660 case CONNMAN_SERVICE_TYPE_GADGET:
1661 case CONNMAN_SERVICE_TYPE_P2P:
1665 name = connman_inet_ifname(index);
1666 connman_info("Remove interface %s [ %s ]", name,
1667 __connman_service_type2string(type));
1670 technology = technology_find(type);
1675 for (tech_drivers = technology->driver_list; tech_drivers;
1676 tech_drivers = g_slist_next(tech_drivers)) {
1677 driver = tech_drivers->data;
1679 if (driver->remove_interface)
1680 driver->remove_interface(technology, index);
1684 int __connman_technology_add_device(struct connman_device *device)
1686 struct connman_technology *technology;
1687 enum connman_service_type type;
1689 type = __connman_device_get_service_type(device);
1691 DBG("device %p type %s", device, get_name(type));
1693 technology = technology_get(type);
1696 * Since no driver can be found for this device at the moment we
1697 * add it to the techless device list.
1699 techless_device_list = g_slist_prepend(techless_device_list,
1705 __sync_synchronize();
1706 if (technology->rfkill_driven) {
1707 if (technology->enabled)
1708 __connman_device_enable(device);
1710 __connman_device_disable(device);
1715 if (technology->enable_persistent &&
1716 !global_offlinemode) {
1717 int err = __connman_device_enable(device);
1719 * connman_technology_add_device() calls __connman_device_enable()
1720 * but since the device is already enabled, the calls does not
1721 * propagate through to connman_technology_enabled via
1722 * connman_device_set_powered.
1724 if (err == -EALREADY)
1725 __connman_technology_enabled(type);
1727 /* if technology persistent state is offline */
1728 if (!technology->enable_persistent)
1729 __connman_device_disable(device);
1732 technology->device_list = g_slist_prepend(technology->device_list,
1738 int __connman_technology_remove_device(struct connman_device *device)
1740 struct connman_technology *technology;
1741 enum connman_service_type type;
1743 DBG("device %p", device);
1745 type = __connman_device_get_service_type(device);
1747 technology = technology_find(type);
1749 techless_device_list = g_slist_remove(techless_device_list,
1754 technology->device_list = g_slist_remove(technology->device_list,
1757 if (technology->tethering)
1758 set_tethering(technology, false);
1760 technology_put(technology);
1765 int __connman_technology_enabled(enum connman_service_type type)
1767 struct connman_technology *technology;
1769 technology = technology_find(type);
1773 DBG("technology %p type %s rfkill %d enabled %d", technology,
1774 get_name(type), technology->rfkill_driven,
1775 technology->enabled);
1776 #if !defined TIZEN_EXT
1777 if (technology->rfkill_driven) {
1778 if (technology->tethering_persistent)
1779 enable_tethering(technology);
1784 return technology_enabled(technology);
1787 int __connman_technology_disabled(enum connman_service_type type)
1789 struct connman_technology *technology;
1792 technology = technology_find(type);
1795 #if !defined TIZEN_EXT
1796 if (technology->rfkill_driven)
1799 for (list = technology->device_list; list; list = list->next) {
1800 struct connman_device *device = list->data;
1802 if (connman_device_get_powered(device))
1806 return technology_disabled(technology);
1809 int __connman_technology_set_offlinemode(bool offlinemode)
1812 int err = -EINVAL, enabled_tech_count = 0;
1814 if (global_offlinemode == offlinemode)
1817 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1820 * This is a bit tricky. When you set offlinemode, there is no
1821 * way to differentiate between attempting offline mode and
1822 * resuming offlinemode from last saved profile. We need that
1823 * information in rfkill_update, otherwise it falls back on the
1824 * technology's persistent state. Hence we set the offline mode here
1825 * but save it & call the notifier only if its successful.
1828 global_offlinemode = offlinemode;
1830 /* Traverse technology list, enable/disable each technology. */
1831 for (list = technology_list; list; list = list->next) {
1832 struct connman_technology *technology = list->data;
1835 err = technology_disable(technology);
1837 if (technology->hardblocked)
1840 if (technology->enable_persistent) {
1841 err = technology_enable(technology);
1842 enabled_tech_count++;
1847 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1848 (err == -EINVAL && enabled_tech_count == 0)) {
1849 connman_technology_save_offlinemode();
1850 __connman_notifier_offlinemode(offlinemode);
1852 global_offlinemode = connman_technology_load_offlinemode();
1857 void __connman_technology_set_connected(enum connman_service_type type,
1860 struct connman_technology *technology;
1863 technology = technology_find(type);
1867 DBG("technology %p connected %d", technology, connected);
1869 technology->connected = connected;
1872 connman_dbus_property_changed_basic(technology->path,
1873 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1874 DBUS_TYPE_BOOLEAN, &val);
1877 static bool technology_apply_rfkill_change(struct connman_technology *technology,
1882 bool hardblock_changed = false;
1884 GList *start, *list;
1886 DBG("technology %p --> %d/%d vs %d/%d",
1887 technology, softblock, hardblock,
1888 technology->softblocked, technology->hardblocked);
1890 if (technology->hardblocked == hardblock)
1891 goto softblock_change;
1893 if (!(new_rfkill && !hardblock)) {
1894 start = g_hash_table_get_values(rfkill_list);
1896 for (list = start; list; list = list->next) {
1897 struct connman_rfkill *rfkill = list->data;
1899 if (rfkill->type != technology->type)
1902 if (rfkill->hardblock != hardblock)
1910 goto softblock_change;
1912 technology->hardblocked = hardblock;
1913 hardblock_changed = true;
1916 if (!apply && technology->softblocked != softblock)
1920 return technology->hardblocked;
1922 technology->softblocked = softblock;
1924 if (technology->hardblocked ||
1925 technology->softblocked) {
1926 if (technology_disabled(technology) != -EALREADY)
1927 technology_affect_devices(technology, false);
1928 } else if (!technology->hardblocked &&
1929 !technology->softblocked) {
1930 if (technology_enabled(technology) != -EALREADY)
1931 technology_affect_devices(technology, true);
1934 if (hardblock_changed) {
1935 if (technology->hardblocked) {
1936 DBG("%s is switched off.", get_name(technology->type));
1937 technology_dbus_unregister(technology);
1939 DBG("%s is switched on.", get_name(technology->type));
1940 technology_dbus_register(technology);
1942 if (global_offlinemode)
1943 __connman_rfkill_block(technology->type, true);
1947 return technology->hardblocked;
1950 int __connman_technology_add_rfkill(unsigned int index,
1951 enum connman_service_type type,
1955 struct connman_technology *technology;
1956 struct connman_rfkill *rfkill;
1958 DBG("index %u type %d soft %u hard %u", index, type,
1959 softblock, hardblock);
1961 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1965 rfkill = g_try_new0(struct connman_rfkill, 1);
1969 rfkill->index = index;
1970 rfkill->type = type;
1971 rfkill->softblock = softblock;
1972 rfkill->hardblock = hardblock;
1974 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1977 #if defined TIZEN_EXT
1978 /* Fix Svace Issue [WGID: 1348]. */
1981 technology = technology_get(type);
1982 /* If there is no driver for this type, ignore it. */
1986 technology->rfkill_driven = true;
1988 #if !defined TIZEN_EXT
1989 /* If hardblocked, there is no need to handle softblocked state */
1990 if (technology_apply_rfkill_change(technology,
1991 softblock, hardblock, true))
1994 if (global_offlinemode)
1998 * Depending on softblocked state we unblock/block according to
1999 * offlinemode and persistente state.
2001 if (technology->softblocked &&
2002 technology->enable_persistent)
2003 return __connman_rfkill_block(type, false);
2004 else if (!technology->softblocked &&
2005 !technology->enable_persistent)
2006 return __connman_rfkill_block(type, true);
2011 int __connman_technology_update_rfkill(unsigned int index,
2012 enum connman_service_type type,
2016 struct connman_technology *technology;
2017 struct connman_rfkill *rfkill;
2019 DBG("index %u soft %u hard %u", index, softblock, hardblock);
2021 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2025 if (rfkill->softblock == softblock &&
2026 rfkill->hardblock == hardblock)
2029 rfkill->softblock = softblock;
2030 rfkill->hardblock = hardblock;
2032 technology = technology_find(type);
2033 /* If there is no driver for this type, ignore it. */
2037 technology_apply_rfkill_change(technology, softblock, hardblock,
2040 if (technology->hardblocked)
2041 DBG("%s hardblocked", get_name(technology->type));
2043 DBG("%s is%s softblocked", get_name(technology->type),
2044 technology->softblocked ? "" : " not");
2049 int __connman_technology_remove_rfkill(unsigned int index,
2050 enum connman_service_type type)
2052 struct connman_technology *technology;
2053 struct connman_rfkill *rfkill;
2055 DBG("index %u", index);
2057 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2061 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
2063 technology = technology_find(type);
2067 technology_apply_rfkill_change(technology,
2068 technology->softblocked, !technology->hardblocked, false);
2070 technology_put(technology);
2075 int __connman_technology_init(void)
2079 connection = connman_dbus_get_connection();
2081 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2084 global_offlinemode = connman_technology_load_offlinemode();
2086 /* This will create settings file if it is missing */
2087 connman_technology_save_offlinemode();
2092 void __connman_technology_cleanup(void)
2096 while (technology_list) {
2097 struct connman_technology *technology = technology_list->data;
2098 technology_list = g_slist_remove(technology_list, technology);
2099 technology_put(technology);
2102 g_hash_table_destroy(rfkill_list);
2104 dbus_connection_unref(connection);