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 g_slist_free_full(specific_scan_list, g_free);
1236 return __connman_error_invalid_arguments(msg);
1239 dbus_message_iter_get_basic(&entry, &key);
1240 dbus_message_iter_next(&entry);
1242 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1243 g_slist_free_full(specific_scan_list, g_free);
1244 return __connman_error_invalid_arguments(msg);
1247 dbus_message_iter_recurse(&entry, &value2);
1248 type = dbus_message_iter_get_arg_type(&value2);
1249 if (g_str_equal(key, "SSID")) {
1250 if (type != DBUS_TYPE_STRING)
1251 return __connman_error_invalid_arguments(msg);
1253 scan_type = 1; /* SSID based scan */
1254 dbus_message_iter_get_basic(&value2, &name);
1255 DBG("name %s", name);
1256 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1257 } else if (g_str_equal(key, "Frequency")) {
1258 if (type != DBUS_TYPE_UINT16) {
1259 g_slist_free_full(specific_scan_list, g_free);
1260 return __connman_error_invalid_arguments(msg);
1263 scan_type = 2; /* Frequency based scan */
1264 dbus_message_iter_get_basic(&value2, &freq);
1265 DBG("freq %d", freq);
1266 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(freq));
1268 dbus_message_iter_next(&dict);
1271 dbus_message_ref(msg);
1273 err = __connman_device_request_specific_scan(technology->type, scan_type, specific_scan_list);
1275 return __connman_error_failed(msg, -err);
1278 guint list_size = g_slist_length(specific_scan_list);
1280 g_scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1282 g_scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1283 DBG("list_size %u g_scan_type %d", list_size, g_scan_type);
1285 technology->scan_pending =
1286 g_slist_prepend(technology->scan_pending, msg);
1288 if (scan_type == 1) {
1289 g_slist_free_full(specific_scan_list, g_free);
1295 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
1298 DBusMessageIter iter, dict;
1300 struct connman_technology *technology = data;
1301 dbus_bool_t scanning = false;
1303 DBG("technology %p", technology);
1305 for (list = technology->device_list; list; list = list->next) {
1306 struct connman_device *device = list->data;
1307 scanning = connman_device_get_scanning(device);
1312 DBG("scanning : %d", scanning);
1313 reply = dbus_message_new_method_return(msg);
1317 dbus_message_iter_init_append(reply, &iter);
1319 connman_dbus_dict_open(&iter, &dict);
1320 connman_dbus_dict_append_basic(&dict, "Scanstate",
1324 connman_dbus_dict_close(&iter, &dict);
1330 static const GDBusMethodTable technology_methods[] = {
1331 { GDBUS_DEPRECATED_METHOD("GetProperties",
1332 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1334 { GDBUS_ASYNC_METHOD("SetProperty",
1335 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1336 NULL, set_property) },
1337 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1338 #if defined TIZEN_EXT
1339 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
1340 NULL, specific_scan) },
1341 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
1347 static const GDBusSignalTable technology_signals[] = {
1348 { GDBUS_SIGNAL("PropertyChanged",
1349 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1350 { GDBUS_SIGNAL("DhcpConnected",
1351 GDBUS_ARGS({ "aptype", "s" },
1354 { "hostname", "s" })) },
1355 { GDBUS_SIGNAL("DhcpLeaseDeleted",
1356 GDBUS_ARGS({ "aptype", "s" },
1359 { "hostname", "s" })) },
1363 static bool technology_dbus_register(struct connman_technology *technology)
1365 if (technology->dbus_registered ||
1366 (technology->rfkill_driven &&
1367 technology->hardblocked))
1370 if (!g_dbus_register_interface(connection, technology->path,
1371 CONNMAN_TECHNOLOGY_INTERFACE,
1372 technology_methods, technology_signals,
1373 NULL, technology, NULL)) {
1374 connman_error("Failed to register %s", technology->path);
1378 technology_added_signal(technology);
1379 technology->dbus_registered = true;
1384 static void technology_dbus_unregister(struct connman_technology *technology)
1386 if (!technology->dbus_registered)
1389 technology_removed_signal(technology);
1390 g_dbus_unregister_interface(connection, technology->path,
1391 CONNMAN_TECHNOLOGY_INTERFACE);
1393 technology->dbus_registered = false;
1396 static void technology_put(struct connman_technology *technology)
1398 DBG("technology %p", technology);
1400 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1403 reply_scan_pending(technology, -EINTR);
1405 while (technology->driver_list) {
1406 struct connman_technology_driver *driver;
1408 driver = technology->driver_list->data;
1411 driver->remove(technology);
1413 technology->driver_list =
1414 g_slist_delete_link(technology->driver_list,
1415 technology->driver_list);
1418 technology_list = g_slist_remove(technology_list, technology);
1420 technology_dbus_unregister(technology);
1422 g_slist_free(technology->device_list);
1424 g_free(technology->path);
1425 g_free(technology->regdom);
1426 g_free(technology->tethering_ident);
1427 g_free(technology->tethering_passphrase);
1431 static struct connman_technology *technology_get(enum connman_service_type type)
1433 GSList *tech_drivers = NULL;
1434 struct connman_technology_driver *driver;
1435 struct connman_technology *technology;
1439 DBG("type %d", type);
1441 str = __connman_service_type2string(type);
1445 technology = technology_find(type);
1447 if (type != CONNMAN_SERVICE_TYPE_P2P)
1448 __sync_fetch_and_add(&technology->refcount, 1);
1452 /* First check if we have a driver for this technology type */
1453 for (list = driver_list; list; list = list->next) {
1454 driver = list->data;
1456 if (driver->type == type) {
1457 DBG("technology %p driver %p", technology, driver);
1458 tech_drivers = g_slist_append(tech_drivers, driver);
1462 if (!tech_drivers) {
1463 DBG("No matching drivers found for %s.",
1464 __connman_service_type2string(type));
1468 technology = g_try_new0(struct connman_technology, 1);
1472 technology->refcount = 1;
1473 technology->type = type;
1474 technology->tethering_hidden = FALSE;
1475 technology->path = g_strdup_printf("%s/technology/%s",
1478 technology_load(technology);
1479 technology_list = g_slist_prepend(technology_list, technology);
1480 technology->driver_list = tech_drivers;
1482 for (list = tech_drivers; list; list = list->next) {
1483 driver = list->data;
1485 if (driver->probe && driver->probe(technology) < 0)
1486 DBG("Driver probe failed for technology %p",
1490 if (!technology_dbus_register(technology)) {
1491 technology_put(technology);
1495 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1496 struct connman_technology *wifi;
1499 enable = technology->enable_persistent;
1501 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
1503 enable = wifi->enabled;
1505 technology_affect_devices(technology, enable);
1508 DBG("technology %p %s", technology, get_name(technology->type));
1513 int connman_technology_driver_register(struct connman_technology_driver *driver)
1516 struct connman_device *device;
1517 enum connman_service_type type;
1519 for (list = driver_list; list; list = list->next) {
1520 if (list->data == driver)
1524 DBG("Registering %s driver", driver->name);
1526 driver_list = g_slist_insert_sorted(driver_list, driver,
1530 * Check for technology less devices if this driver
1531 * can service any of them.
1533 for (list = techless_device_list; list; list = list->next) {
1534 device = list->data;
1536 type = __connman_device_get_service_type(device);
1537 if (type != driver->type)
1540 techless_device_list = g_slist_remove(techless_device_list,
1543 __connman_technology_add_device(device);
1546 /* Check for orphaned rfkill switches. */
1547 g_hash_table_foreach(rfkill_list, rfkill_check,
1548 GINT_TO_POINTER(driver->type));
1551 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1552 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
1559 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
1561 GSList *list, *tech_drivers;
1562 struct connman_technology *technology;
1563 struct connman_technology_driver *current;
1565 DBG("Unregistering driver %p name %s", driver, driver->name);
1567 for (list = technology_list; list; list = list->next) {
1568 technology = list->data;
1570 for (tech_drivers = technology->driver_list; tech_drivers;
1571 tech_drivers = g_slist_next(tech_drivers)) {
1572 current = tech_drivers->data;
1573 if (driver != current)
1577 driver->remove(technology);
1579 technology->driver_list =
1580 g_slist_remove(technology->driver_list,
1586 driver_list = g_slist_remove(driver_list, driver);
1588 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1589 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1591 technology_put(technology);
1595 void __connman_technology_add_interface(enum connman_service_type type,
1596 int index, const char *ident)
1598 struct connman_technology *technology;
1599 GSList *tech_drivers;
1600 struct connman_technology_driver *driver;
1604 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1605 case CONNMAN_SERVICE_TYPE_SYSTEM:
1607 case CONNMAN_SERVICE_TYPE_ETHERNET:
1608 case CONNMAN_SERVICE_TYPE_WIFI:
1609 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1610 case CONNMAN_SERVICE_TYPE_CELLULAR:
1611 case CONNMAN_SERVICE_TYPE_GPS:
1612 case CONNMAN_SERVICE_TYPE_VPN:
1613 case CONNMAN_SERVICE_TYPE_GADGET:
1614 case CONNMAN_SERVICE_TYPE_P2P:
1618 name = connman_inet_ifname(index);
1619 connman_info("Adding interface %s [ %s ]", name,
1620 __connman_service_type2string(type));
1622 technology = technology_find(type);
1627 for (tech_drivers = technology->driver_list; tech_drivers;
1628 tech_drivers = g_slist_next(tech_drivers)) {
1629 driver = tech_drivers->data;
1631 if (driver->add_interface)
1632 driver->add_interface(technology, index, name, ident);
1636 * At this point we can try to enable tethering automatically as
1637 * now the interfaces are set properly.
1639 if (technology->tethering_persistent)
1640 enable_tethering(technology);
1646 void __connman_technology_remove_interface(enum connman_service_type type,
1647 int index, const char *ident)
1649 struct connman_technology *technology;
1650 GSList *tech_drivers;
1651 struct connman_technology_driver *driver;
1655 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1656 case CONNMAN_SERVICE_TYPE_SYSTEM:
1658 case CONNMAN_SERVICE_TYPE_ETHERNET:
1659 case CONNMAN_SERVICE_TYPE_WIFI:
1660 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1661 case CONNMAN_SERVICE_TYPE_CELLULAR:
1662 case CONNMAN_SERVICE_TYPE_GPS:
1663 case CONNMAN_SERVICE_TYPE_VPN:
1664 case CONNMAN_SERVICE_TYPE_GADGET:
1665 case CONNMAN_SERVICE_TYPE_P2P:
1669 name = connman_inet_ifname(index);
1670 connman_info("Remove interface %s [ %s ]", name,
1671 __connman_service_type2string(type));
1674 technology = technology_find(type);
1679 for (tech_drivers = technology->driver_list; tech_drivers;
1680 tech_drivers = g_slist_next(tech_drivers)) {
1681 driver = tech_drivers->data;
1683 if (driver->remove_interface)
1684 driver->remove_interface(technology, index);
1688 int __connman_technology_add_device(struct connman_device *device)
1690 struct connman_technology *technology;
1691 enum connman_service_type type;
1693 type = __connman_device_get_service_type(device);
1695 DBG("device %p type %s", device, get_name(type));
1697 technology = technology_get(type);
1700 * Since no driver can be found for this device at the moment we
1701 * add it to the techless device list.
1703 techless_device_list = g_slist_prepend(techless_device_list,
1709 __sync_synchronize();
1710 if (technology->rfkill_driven) {
1711 if (technology->enabled)
1712 __connman_device_enable(device);
1714 __connman_device_disable(device);
1719 if (technology->enable_persistent &&
1720 !global_offlinemode) {
1721 int err = __connman_device_enable(device);
1723 * connman_technology_add_device() calls __connman_device_enable()
1724 * but since the device is already enabled, the calls does not
1725 * propagate through to connman_technology_enabled via
1726 * connman_device_set_powered.
1728 if (err == -EALREADY)
1729 __connman_technology_enabled(type);
1731 /* if technology persistent state is offline */
1732 if (!technology->enable_persistent)
1733 __connman_device_disable(device);
1736 technology->device_list = g_slist_prepend(technology->device_list,
1742 int __connman_technology_remove_device(struct connman_device *device)
1744 struct connman_technology *technology;
1745 enum connman_service_type type;
1747 DBG("device %p", device);
1749 type = __connman_device_get_service_type(device);
1751 technology = technology_find(type);
1753 techless_device_list = g_slist_remove(techless_device_list,
1758 technology->device_list = g_slist_remove(technology->device_list,
1761 if (technology->tethering)
1762 set_tethering(technology, false);
1764 technology_put(technology);
1769 int __connman_technology_enabled(enum connman_service_type type)
1771 struct connman_technology *technology;
1773 technology = technology_find(type);
1777 DBG("technology %p type %s rfkill %d enabled %d", technology,
1778 get_name(type), technology->rfkill_driven,
1779 technology->enabled);
1780 #if !defined TIZEN_EXT
1781 if (technology->rfkill_driven) {
1782 if (technology->tethering_persistent)
1783 enable_tethering(technology);
1788 return technology_enabled(technology);
1791 int __connman_technology_disabled(enum connman_service_type type)
1793 struct connman_technology *technology;
1796 technology = technology_find(type);
1799 #if !defined TIZEN_EXT
1800 if (technology->rfkill_driven)
1803 for (list = technology->device_list; list; list = list->next) {
1804 struct connman_device *device = list->data;
1806 if (connman_device_get_powered(device))
1810 return technology_disabled(technology);
1813 int __connman_technology_set_offlinemode(bool offlinemode)
1816 int err = -EINVAL, enabled_tech_count = 0;
1818 if (global_offlinemode == offlinemode)
1821 DBG("offlinemode %s", offlinemode ? "On" : "Off");
1824 * This is a bit tricky. When you set offlinemode, there is no
1825 * way to differentiate between attempting offline mode and
1826 * resuming offlinemode from last saved profile. We need that
1827 * information in rfkill_update, otherwise it falls back on the
1828 * technology's persistent state. Hence we set the offline mode here
1829 * but save it & call the notifier only if its successful.
1832 global_offlinemode = offlinemode;
1834 /* Traverse technology list, enable/disable each technology. */
1835 for (list = technology_list; list; list = list->next) {
1836 struct connman_technology *technology = list->data;
1839 err = technology_disable(technology);
1841 if (technology->hardblocked)
1844 if (technology->enable_persistent) {
1845 err = technology_enable(technology);
1846 enabled_tech_count++;
1851 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1852 (err == -EINVAL && enabled_tech_count == 0)) {
1853 connman_technology_save_offlinemode();
1854 __connman_notifier_offlinemode(offlinemode);
1856 global_offlinemode = connman_technology_load_offlinemode();
1861 void __connman_technology_set_connected(enum connman_service_type type,
1864 struct connman_technology *technology;
1867 technology = technology_find(type);
1871 DBG("technology %p connected %d", technology, connected);
1873 technology->connected = connected;
1876 connman_dbus_property_changed_basic(technology->path,
1877 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1878 DBUS_TYPE_BOOLEAN, &val);
1881 static bool technology_apply_rfkill_change(struct connman_technology *technology,
1886 bool hardblock_changed = false;
1888 GList *start, *list;
1890 DBG("technology %p --> %d/%d vs %d/%d",
1891 technology, softblock, hardblock,
1892 technology->softblocked, technology->hardblocked);
1894 if (technology->hardblocked == hardblock)
1895 goto softblock_change;
1897 if (!(new_rfkill && !hardblock)) {
1898 start = g_hash_table_get_values(rfkill_list);
1900 for (list = start; list; list = list->next) {
1901 struct connman_rfkill *rfkill = list->data;
1903 if (rfkill->type != technology->type)
1906 if (rfkill->hardblock != hardblock)
1914 goto softblock_change;
1916 technology->hardblocked = hardblock;
1917 hardblock_changed = true;
1920 if (!apply && technology->softblocked != softblock)
1924 return technology->hardblocked;
1926 technology->softblocked = softblock;
1928 if (technology->hardblocked ||
1929 technology->softblocked) {
1930 if (technology_disabled(technology) != -EALREADY)
1931 technology_affect_devices(technology, false);
1932 } else if (!technology->hardblocked &&
1933 !technology->softblocked) {
1934 if (technology_enabled(technology) != -EALREADY)
1935 technology_affect_devices(technology, true);
1938 if (hardblock_changed) {
1939 if (technology->hardblocked) {
1940 DBG("%s is switched off.", get_name(technology->type));
1941 technology_dbus_unregister(technology);
1943 DBG("%s is switched on.", get_name(technology->type));
1944 technology_dbus_register(technology);
1946 if (global_offlinemode)
1947 __connman_rfkill_block(technology->type, true);
1951 return technology->hardblocked;
1954 int __connman_technology_add_rfkill(unsigned int index,
1955 enum connman_service_type type,
1959 struct connman_technology *technology;
1960 struct connman_rfkill *rfkill;
1962 DBG("index %u type %d soft %u hard %u", index, type,
1963 softblock, hardblock);
1965 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1969 rfkill = g_try_new0(struct connman_rfkill, 1);
1973 rfkill->index = index;
1974 rfkill->type = type;
1975 rfkill->softblock = softblock;
1976 rfkill->hardblock = hardblock;
1978 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1981 #if defined TIZEN_EXT
1982 /* Fix Svace Issue [WGID: 1348]. */
1985 technology = technology_get(type);
1986 /* If there is no driver for this type, ignore it. */
1990 technology->rfkill_driven = true;
1992 #if !defined TIZEN_EXT
1993 /* If hardblocked, there is no need to handle softblocked state */
1994 if (technology_apply_rfkill_change(technology,
1995 softblock, hardblock, true))
1998 if (global_offlinemode)
2002 * Depending on softblocked state we unblock/block according to
2003 * offlinemode and persistente state.
2005 if (technology->softblocked &&
2006 technology->enable_persistent)
2007 return __connman_rfkill_block(type, false);
2008 else if (!technology->softblocked &&
2009 !technology->enable_persistent)
2010 return __connman_rfkill_block(type, true);
2015 int __connman_technology_update_rfkill(unsigned int index,
2016 enum connman_service_type type,
2020 struct connman_technology *technology;
2021 struct connman_rfkill *rfkill;
2023 DBG("index %u soft %u hard %u", index, softblock, hardblock);
2025 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2029 if (rfkill->softblock == softblock &&
2030 rfkill->hardblock == hardblock)
2033 rfkill->softblock = softblock;
2034 rfkill->hardblock = hardblock;
2036 technology = technology_find(type);
2037 /* If there is no driver for this type, ignore it. */
2041 technology_apply_rfkill_change(technology, softblock, hardblock,
2044 if (technology->hardblocked)
2045 DBG("%s hardblocked", get_name(technology->type));
2047 DBG("%s is%s softblocked", get_name(technology->type),
2048 technology->softblocked ? "" : " not");
2053 int __connman_technology_remove_rfkill(unsigned int index,
2054 enum connman_service_type type)
2056 struct connman_technology *technology;
2057 struct connman_rfkill *rfkill;
2059 DBG("index %u", index);
2061 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2065 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
2067 technology = technology_find(type);
2071 technology_apply_rfkill_change(technology,
2072 technology->softblocked, !technology->hardblocked, false);
2074 technology_put(technology);
2079 int __connman_technology_init(void)
2083 connection = connman_dbus_get_connection();
2085 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2088 global_offlinemode = connman_technology_load_offlinemode();
2090 /* This will create settings file if it is missing */
2091 connman_technology_save_offlinemode();
2096 void __connman_technology_cleanup(void)
2100 while (technology_list) {
2101 struct connman_technology *technology = technology_list->data;
2102 technology_list = g_slist_remove(technology_list, technology);
2103 technology_put(technology);
2106 g_hash_table_destroy(rfkill_list);
2108 dbus_connection_unref(connection);