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
37 static DBusConnection *connection;
39 static GSList *technology_list = NULL;
42 * List of devices with no technology associated with them either because of
43 * no compiled in support or the driver is not yet loaded.
45 static GSList *techless_device_list = NULL;
46 static GHashTable *rfkill_list;
48 static bool global_offlinemode;
52 CONNMAN_SCAN_TYPE_FULL_CHANNEL = 0x00,
53 CONNMAN_SCAN_TYPE_SPECIFIC_AP,
54 CONNMAN_SCAN_TYPE_MULTI_AP,
55 } connman_scan_type_e;
57 static connman_scan_type_e g_scan_type = -1;
60 struct connman_rfkill {
62 enum connman_service_type type;
67 struct connman_technology {
69 enum connman_service_type type;
77 bool tethering_persistent; /* Tells the save status, needed
78 * as offline mode might set
81 char *tethering_ident;
82 char *tethering_passphrase;
83 bool tethering_hidden;
85 bool enable_persistent; /* Save the tech state */
89 DBusMessage *pending_reply;
90 guint pending_timeout;
98 #if defined TIZEN_EXT_WIFI_MESH
99 DBusMessage *mesh_dbus_msg;
101 #if defined TIZEN_EXT
102 bool is_5_0_ghz_supported;
107 static GSList *driver_list = NULL;
109 static int technology_enabled(struct connman_technology *technology);
110 static int technology_disabled(struct connman_technology *technology);
112 static gint compare_priority(gconstpointer a, gconstpointer b)
114 const struct connman_technology_driver *driver1 = a;
115 const struct connman_technology_driver *driver2 = b;
117 return driver2->priority - driver1->priority;
120 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
122 struct connman_rfkill *rfkill = value;
123 enum connman_service_type type = GPOINTER_TO_INT(user_data);
125 /* Calling _technology_rfkill_add will update the tech. */
126 if (rfkill->type == type)
127 __connman_technology_add_rfkill(rfkill->index, type,
128 rfkill->softblock, rfkill->hardblock);
132 connman_technology_is_tethering_allowed(enum connman_service_type type)
134 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
136 const char *type_str = __connman_service_type2string(type);
143 allowed = connman_setting_get_string_list("TetheringTechnologies");
145 allowed = allowed_default;
147 for (i = 0; allowed[i]; i++) {
148 if (g_strcmp0(allowed[i], type_str) == 0)
155 static const char *get_name(enum connman_service_type type)
158 case CONNMAN_SERVICE_TYPE_UNKNOWN:
159 case CONNMAN_SERVICE_TYPE_SYSTEM:
160 case CONNMAN_SERVICE_TYPE_GPS:
161 case CONNMAN_SERVICE_TYPE_VPN:
163 case CONNMAN_SERVICE_TYPE_GADGET:
165 case CONNMAN_SERVICE_TYPE_ETHERNET:
167 case CONNMAN_SERVICE_TYPE_WIFI:
169 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
171 case CONNMAN_SERVICE_TYPE_CELLULAR:
173 case CONNMAN_SERVICE_TYPE_P2P:
175 #if defined TIZEN_EXT_WIFI_MESH
176 case CONNMAN_SERVICE_TYPE_MESH:
184 static void technology_save(struct connman_technology *technology)
188 const char *name = get_name(technology->type);
190 DBG("technology %p type %d name %s", technology, technology->type,
195 keyfile = __connman_storage_load_global();
197 keyfile = g_key_file_new();
199 identifier = g_strdup_printf("%s", name);
203 g_key_file_set_boolean(keyfile, identifier, "Enable",
204 technology->enable_persistent);
206 g_key_file_set_boolean(keyfile, identifier, "Tethering",
207 technology->tethering_persistent);
209 g_key_file_set_boolean(keyfile, identifier, "Hidden",
210 technology->tethering_hidden);
212 if (technology->tethering_ident)
213 g_key_file_set_string(keyfile, identifier,
214 "Tethering.Identifier",
215 technology->tethering_ident);
217 if (technology->tethering_passphrase)
218 g_key_file_set_string(keyfile, identifier,
219 "Tethering.Passphrase",
220 technology->tethering_passphrase);
225 __connman_storage_save_global(keyfile);
227 g_key_file_free(keyfile);
232 static void tethering_changed(struct connman_technology *technology)
234 dbus_bool_t tethering = technology->tethering;
236 connman_dbus_property_changed_basic(technology->path,
237 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
238 DBUS_TYPE_BOOLEAN, &tethering);
240 technology_save(technology);
243 int connman_technology_tethering_notify(struct connman_technology *technology,
248 DBG("technology %p enabled %u", technology, enabled);
250 if (technology->tethering == enabled)
254 err = __connman_tethering_set_enabled();
258 __connman_tethering_set_disabled();
260 technology->tethering = enabled;
261 tethering_changed(technology);
266 static int set_tethering(struct connman_technology *technology,
269 int result = -EOPNOTSUPP;
271 const char *ident, *passphrase, *bridge;
272 GSList *tech_drivers;
274 ident = technology->tethering_ident;
275 passphrase = technology->tethering_passphrase;
277 __sync_synchronize();
278 if (!technology->enabled)
281 bridge = __connman_tethering_get_bridge();
285 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && (!ident))
288 for (tech_drivers = technology->driver_list; tech_drivers;
289 tech_drivers = g_slist_next(tech_drivers)) {
290 struct connman_technology_driver *driver = tech_drivers->data;
292 if (!driver || !driver->set_tethering)
295 err = driver->set_tethering(technology, ident, passphrase,
298 if (result == -EINPROGRESS)
301 if (err == -EINPROGRESS || err == 0)
308 void connman_technology_regdom_notify(struct connman_technology *technology,
314 connman_error("Failed to set regulatory domain");
316 DBG("Regulatory domain set to %s", alpha2);
318 g_free(technology->regdom);
319 technology->regdom = g_strdup(alpha2);
322 static int set_regdom_by_device(struct connman_technology *technology,
327 for (list = technology->device_list; list; list = list->next) {
328 struct connman_device *device = list->data;
330 if (connman_device_set_regdom(device, alpha2) != 0)
337 int connman_technology_set_regdom(const char *alpha2)
339 GSList *list, *tech_drivers;
341 for (list = technology_list; list; list = list->next) {
342 struct connman_technology *technology = list->data;
344 if (set_regdom_by_device(technology, alpha2) != 0) {
346 for (tech_drivers = technology->driver_list;
348 tech_drivers = g_slist_next(tech_drivers)) {
350 struct connman_technology_driver *driver =
353 if (driver->set_regdom)
354 driver->set_regdom(technology, alpha2);
362 static struct connman_technology *technology_find(enum connman_service_type type)
366 DBG("type %d", type);
368 for (list = technology_list; list; list = list->next) {
369 struct connman_technology *technology = list->data;
371 if (technology->type == type)
378 bool connman_technology_get_wifi_tethering(const char **ssid,
381 struct connman_technology *technology;
388 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
392 if (!technology->tethering)
395 *ssid = technology->tethering_ident;
396 *psk = technology->tethering_passphrase;
401 #if defined TIZEN_EXT
402 void connman_techonology_wifi_set_5ghz_supported(struct connman_technology *wifi_technology,
403 bool is_5_0_ghz_supported)
407 wifi_technology->is_5_0_ghz_supported = is_5_0_ghz_supported;
411 static void free_rfkill(gpointer data)
413 struct connman_rfkill *rfkill = data;
418 static void technology_load(struct connman_technology *technology)
422 GError *error = NULL;
423 bool enable, need_saving = false;
425 DBG("technology %p", technology);
427 keyfile = __connman_storage_load_global();
428 /* Fallback on disabling technology if file not found. */
430 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
431 /* We enable ethernet by default */
432 technology->enable_persistent = true;
434 technology->enable_persistent = false;
438 identifier = g_strdup_printf("%s", get_name(technology->type));
442 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
444 technology->enable_persistent = enable;
446 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
447 technology->enable_persistent = true;
449 technology->enable_persistent = false;
452 g_clear_error(&error);
455 enable = g_key_file_get_boolean(keyfile, identifier,
456 "Tethering", &error);
458 technology->tethering_persistent = enable;
461 g_clear_error(&error);
465 technology_save(technology);
467 technology->tethering_ident = g_key_file_get_string(keyfile,
468 identifier, "Tethering.Identifier", NULL);
470 technology->tethering_passphrase = g_key_file_get_string(keyfile,
471 identifier, "Tethering.Passphrase", NULL);
475 g_key_file_free(keyfile);
480 bool __connman_technology_get_offlinemode(void)
482 return global_offlinemode;
485 static void connman_technology_save_offlinemode(void)
488 GError *error = NULL;
491 keyfile = __connman_storage_load_global();
494 keyfile = g_key_file_new();
495 g_key_file_set_boolean(keyfile, "global",
496 "OfflineMode", global_offlinemode);
498 __connman_storage_save_global(keyfile);
501 offlinemode = g_key_file_get_boolean(keyfile, "global",
502 "OfflineMode", &error);
504 if (error || offlinemode != global_offlinemode) {
505 g_key_file_set_boolean(keyfile, "global",
506 "OfflineMode", global_offlinemode);
508 g_clear_error(&error);
510 __connman_storage_save_global(keyfile);
514 g_key_file_free(keyfile);
519 static bool connman_technology_load_offlinemode(void)
522 GError *error = NULL;
525 /* If there is a error, we enable offlinemode */
526 keyfile = __connman_storage_load_global();
530 offlinemode = g_key_file_get_boolean(keyfile, "global",
531 "OfflineMode", &error);
534 g_clear_error(&error);
537 g_key_file_free(keyfile);
542 static void append_properties(DBusMessageIter *iter,
543 struct connman_technology *technology)
545 DBusMessageIter dict;
549 connman_dbus_dict_open(iter, &dict);
551 str = get_name(technology->type);
553 connman_dbus_dict_append_basic(&dict, "Name",
554 DBUS_TYPE_STRING, &str);
556 str = __connman_service_type2string(technology->type);
558 connman_dbus_dict_append_basic(&dict, "Type",
559 DBUS_TYPE_STRING, &str);
561 __sync_synchronize();
562 val = technology->enabled;
563 connman_dbus_dict_append_basic(&dict, "Powered",
567 val = technology->connected;
568 connman_dbus_dict_append_basic(&dict, "Connected",
572 val = technology->tethering;
573 connman_dbus_dict_append_basic(&dict, "Tethering",
577 if (technology->tethering_ident)
578 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
580 &technology->tethering_ident);
582 if (technology->tethering_passphrase)
583 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
585 &technology->tethering_passphrase);
587 val = technology->tethering_hidden;
588 connman_dbus_dict_append_basic(&dict, "Hidden",
592 connman_dbus_dict_close(iter, &dict);
595 static void technology_added_signal(struct connman_technology *technology)
598 DBusMessageIter iter;
600 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
601 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
605 dbus_message_iter_init_append(signal, &iter);
606 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
608 append_properties(&iter, technology);
610 dbus_connection_send(connection, signal, NULL);
611 dbus_message_unref(signal);
614 static void technology_removed_signal(struct connman_technology *technology)
616 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
617 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
618 DBUS_TYPE_OBJECT_PATH, &technology->path,
622 static DBusMessage *get_properties(DBusConnection *conn,
623 DBusMessage *message, void *user_data)
625 struct connman_technology *technology = user_data;
627 DBusMessageIter iter;
629 reply = dbus_message_new_method_return(message);
633 dbus_message_iter_init_append(reply, &iter);
634 append_properties(&iter, technology);
639 void __connman_technology_list_struct(DBusMessageIter *array)
642 DBusMessageIter entry;
644 for (list = technology_list; list; list = list->next) {
645 struct connman_technology *technology = list->data;
647 if (!technology->path ||
648 (technology->rfkill_driven &&
649 technology->hardblocked))
652 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
654 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
656 append_properties(&entry, technology);
657 dbus_message_iter_close_container(array, &entry);
661 static gboolean technology_pending_reply(gpointer user_data)
663 struct connman_technology *technology = user_data;
666 /* Power request timedout, send ETIMEDOUT. */
667 if (technology->pending_reply) {
668 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
670 g_dbus_send_message(connection, reply);
672 dbus_message_unref(technology->pending_reply);
673 technology->pending_reply = NULL;
674 technology->pending_timeout = 0;
680 static int technology_affect_devices(struct connman_technology *technology,
683 int err = 0, err_dev;
686 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
688 __connman_technology_enabled(technology->type);
690 __connman_technology_disabled(technology->type);
694 #if defined TIZEN_EXT_WIFI_MESH
695 if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
699 for (list = technology->device_list; list; list = list->next) {
700 struct connman_device *device = list->data;
703 err_dev = __connman_device_enable(device);
705 err_dev = __connman_device_disable(device);
707 if (err_dev < 0 && err_dev != -EALREADY)
714 static void powered_changed(struct connman_technology *technology)
718 if (!technology->dbus_registered)
721 if (technology->pending_reply) {
722 g_dbus_send_reply(connection,
723 technology->pending_reply, DBUS_TYPE_INVALID);
724 dbus_message_unref(technology->pending_reply);
725 technology->pending_reply = NULL;
727 g_source_remove(technology->pending_timeout);
728 technology->pending_timeout = 0;
731 __sync_synchronize();
732 enabled = technology->enabled;
733 #if defined TIZEN_EXT
734 DBG("ConnMan, Powered : %s, %s",
735 enabled ? "TRUE" : "FALSE",technology->path);
737 connman_dbus_property_changed_basic(technology->path,
738 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
739 DBUS_TYPE_BOOLEAN, &enabled);
742 static void enable_tethering(struct connman_technology *technology)
746 if (!connman_setting_get_bool("PersistentTetheringMode"))
749 ret = set_tethering(technology, true);
750 if (ret < 0 && ret != -EALREADY)
751 DBG("Cannot enable tethering yet for %s (%d/%s)",
752 get_name(technology->type),
753 -ret, strerror(-ret));
756 static int technology_enabled(struct connman_technology *technology)
758 __sync_synchronize();
759 if (technology->enabled)
762 technology->enabled = true;
764 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
765 struct connman_technology *p2p;
767 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
768 if (p2p && !p2p->enabled && p2p->enable_persistent)
769 technology_enabled(p2p);
772 if (technology->tethering_persistent)
773 enable_tethering(technology);
775 powered_changed(technology);
780 static int technology_enable(struct connman_technology *technology)
785 DBG("technology %p enable", technology);
787 __sync_synchronize();
789 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
790 struct connman_technology *wifi;
792 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
793 if (wifi && wifi->enabled)
794 return technology_enabled(technology);
798 if (technology->enabled)
801 if (technology->pending_reply)
804 if (connman_setting_get_bool("PersistentTetheringMode") &&
805 technology->tethering)
806 set_tethering(technology, true);
808 if (technology->rfkill_driven)
809 err = __connman_rfkill_block(technology->type, false);
811 err_dev = technology_affect_devices(technology, true);
813 if (!technology->rfkill_driven)
819 static int technology_disabled(struct connman_technology *technology)
821 __sync_synchronize();
822 if (!technology->enabled)
825 technology->enabled = false;
827 powered_changed(technology);
832 static int technology_disable(struct connman_technology *technology)
836 DBG("technology %p disable", technology);
838 __sync_synchronize();
840 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
841 technology->enable_persistent = false;
842 return technology_disabled(technology);
843 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
844 struct connman_technology *p2p;
846 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
847 if (p2p && p2p->enabled) {
848 p2p->enable_persistent = true;
849 technology_disabled(p2p);
853 if (!technology->enabled)
856 if (technology->pending_reply)
859 if (technology->tethering)
860 set_tethering(technology, false);
862 err = technology_affect_devices(technology, false);
864 if (technology->rfkill_driven)
865 err = __connman_rfkill_block(technology->type, true);
870 static DBusMessage *set_powered(struct connman_technology *technology,
871 DBusMessage *msg, bool powered)
873 DBusMessage *reply = NULL;
876 if (technology->rfkill_driven && technology->hardblocked) {
882 err = technology_enable(technology);
884 err = technology_disable(technology);
887 technology->enable_persistent = powered;
888 technology_save(technology);
892 if (err == -EINPROGRESS) {
893 technology->pending_reply = dbus_message_ref(msg);
894 technology->pending_timeout = g_timeout_add_seconds(10,
895 technology_pending_reply, technology);
896 } else if (err == -EALREADY) {
898 reply = __connman_error_already_enabled(msg);
900 reply = __connman_error_already_disabled(msg);
902 reply = __connman_error_failed(msg, -err);
904 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
909 #if defined TIZEN_EXT
910 int set_connman_bssid(enum bssid_type mode, char *bssid)
912 static unsigned char bssid_for_connect[6];
913 static int bssid_len;
915 DBG("mode : %d", mode);
917 if (mode == CHECK_BSSID) {
921 if (mode == GET_BSSID && bssid) {
922 memcpy(bssid, bssid_for_connect, 6);
926 if (mode == RESET_BSSID) {
931 if (mode != SET_BSSID || !bssid) {
932 DBG("Invalid parameter");
936 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
937 &bssid_for_connect[0], &bssid_for_connect[1], &bssid_for_connect[2],
938 &bssid_for_connect[3], &bssid_for_connect[4], &bssid_for_connect[5]);
939 if (bssid_len != 6) {
940 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
944 DBG("SET BSSID len : %d, BSSID : %02x:%02x:%02x:%02x:%02x:%02x", bssid_len,
945 bssid_for_connect[0], bssid_for_connect[1], bssid_for_connect[2],
946 bssid_for_connect[3], bssid_for_connect[4], bssid_for_connect[5]);
952 static DBusMessage *set_property(DBusConnection *conn,
953 DBusMessage *msg, void *data)
955 struct connman_technology *technology = data;
956 DBusMessageIter iter, value;
960 DBG("conn %p", conn);
962 if (!dbus_message_iter_init(msg, &iter))
963 return __connman_error_invalid_arguments(msg);
965 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
966 return __connman_error_invalid_arguments(msg);
968 dbus_message_iter_get_basic(&iter, &name);
969 dbus_message_iter_next(&iter);
971 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
972 return __connman_error_invalid_arguments(msg);
974 dbus_message_iter_recurse(&iter, &value);
976 type = dbus_message_iter_get_arg_type(&value);
978 DBG("property %s", name);
980 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && technology->connected) {
982 if (connman_dbus_get_connection_unix_user_sync(conn,
983 dbus_message_get_sender(msg),
985 DBG("Can not get unix user id!");
986 return __connman_error_permission_denied(msg);
989 if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
990 DBG("Not allow this user to operate wifi technology now!");
991 return __connman_error_permission_denied(msg);
995 if (g_str_equal(name, "Tethering")) {
996 dbus_bool_t tethering;
999 if (type != DBUS_TYPE_BOOLEAN)
1000 return __connman_error_invalid_arguments(msg);
1002 if (!connman_technology_is_tethering_allowed(technology->type)) {
1003 DBG("%s tethering not allowed by config file",
1004 __connman_service_type2string(technology->type));
1005 return __connman_error_not_supported(msg);
1008 dbus_message_iter_get_basic(&value, &tethering);
1010 if (technology->tethering == tethering) {
1012 return __connman_error_already_disabled(msg);
1014 return __connman_error_already_enabled(msg);
1017 err = set_tethering(technology, tethering);
1019 return __connman_error_failed(msg, -err);
1021 technology->tethering_persistent = tethering;
1023 technology_save(technology);
1025 } else if (g_str_equal(name, "TetheringIdentifier")) {
1028 dbus_message_iter_get_basic(&value, &str);
1030 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1031 return __connman_error_not_supported(msg);
1033 if (strlen(str) < 1 || strlen(str) > 32)
1034 return __connman_error_invalid_arguments(msg);
1036 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1037 g_free(technology->tethering_ident);
1038 technology->tethering_ident = g_strdup(str);
1039 technology_save(technology);
1041 connman_dbus_property_changed_basic(technology->path,
1042 CONNMAN_TECHNOLOGY_INTERFACE,
1043 "TetheringIdentifier",
1045 &technology->tethering_ident);
1047 } else if (g_str_equal(name, "TetheringPassphrase")) {
1050 dbus_message_iter_get_basic(&value, &str);
1052 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1053 return __connman_error_not_supported(msg);
1055 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1058 return __connman_error_passphrase_required(msg);
1060 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1061 g_free(technology->tethering_passphrase);
1062 technology->tethering_passphrase = g_strdup(str);
1063 technology_save(technology);
1065 connman_dbus_property_changed_basic(technology->path,
1066 CONNMAN_TECHNOLOGY_INTERFACE,
1067 "TetheringPassphrase",
1069 &technology->tethering_passphrase);
1071 } else if (g_str_equal(name, "Hidden")) {
1074 if (type != DBUS_TYPE_BOOLEAN)
1075 return __connman_error_invalid_arguments(msg);
1077 dbus_message_iter_get_basic(&value, &hidden);
1079 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1080 return __connman_error_not_supported(msg);
1082 technology->tethering_hidden = hidden;
1083 technology_save(technology);
1085 connman_dbus_property_changed_basic(technology->path,
1086 CONNMAN_TECHNOLOGY_INTERFACE,
1090 } else if (g_str_equal(name, "Powered")) {
1093 if (type != DBUS_TYPE_BOOLEAN)
1094 return __connman_error_invalid_arguments(msg);
1096 dbus_message_iter_get_basic(&value, &enable);
1098 return set_powered(technology, msg, enable);
1099 #if defined TIZEN_EXT
1100 } else if (g_str_equal(name, "SetBSSID")) {
1103 if (type != DBUS_TYPE_STRING)
1104 return __connman_error_invalid_arguments(msg);
1106 dbus_message_iter_get_basic(&value, &key);
1107 DBG("BSSID %s", key);
1108 set_connman_bssid(SET_BSSID, key);
1111 return __connman_error_invalid_property(msg);
1113 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1116 static void reply_scan_pending(struct connman_technology *technology, int err)
1120 DBG("technology %p err %d", technology, err);
1122 while (technology->scan_pending) {
1123 DBusMessage *msg = technology->scan_pending->data;
1125 DBG("reply to %s", dbus_message_get_sender(msg));
1128 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1130 reply = __connman_error_failed(msg, -err);
1131 g_dbus_send_message(connection, reply);
1132 dbus_message_unref(msg);
1134 technology->scan_pending =
1135 g_slist_delete_link(technology->scan_pending,
1136 technology->scan_pending);
1140 #if defined TIZEN_EXT
1141 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1144 DBusMessage *signal;
1145 DBusMessageIter iter;
1146 dbus_bool_t result = FALSE;
1148 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1149 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1153 dbus_message_iter_init_append(signal, &iter);
1154 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1156 result = dbus_connection_send(connection, signal, NULL);
1157 dbus_message_unref(signal);
1159 DBG("Successfuly sent signal");
1165 void __connman_technology_scan_started(struct connman_device *device)
1167 DBG("device %p", device);
1168 #if defined TIZEN_EXT
1169 dbus_bool_t status = 1;
1170 __connman_technology_notify_scan_changed("scan_started", &status);
1174 void __connman_technology_scan_stopped(struct connman_device *device,
1175 enum connman_service_type type)
1178 struct connman_technology *technology;
1181 technology = technology_find(type);
1183 DBG("technology %p device %p", technology, device);
1188 for (list = technology->device_list; list; list = list->next) {
1189 struct connman_device *other_device = list->data;
1191 if (device == other_device)
1194 if (__connman_device_get_service_type(other_device) != type)
1197 if (connman_device_get_scanning(other_device))
1201 #if defined TIZEN_EXT
1203 DBusMessage *signal;
1204 DBusMessageIter iter;
1205 dbus_bool_t status = 0;
1206 __connman_technology_notify_scan_changed("scan_done", &status);
1208 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1209 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1213 dbus_message_iter_init_append(signal, &iter);
1214 connman_dbus_property_append_basic(&iter, "Scantype",
1215 DBUS_TYPE_INT32, &g_scan_type);
1217 dbus_connection_send(connection, signal, NULL);
1218 dbus_message_unref(signal);
1219 reply_scan_pending(technology, 0);
1221 DBG("Successfuly sent ScanDone signal");
1225 reply_scan_pending(technology, 0);
1229 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1230 int result, const char *alpha2)
1232 bool regdom_set = false;
1233 struct connman_technology *technology;
1234 enum connman_service_type type;
1235 GSList *tech_drivers;
1237 type = __connman_device_get_service_type(device);
1238 technology = technology_find(type);
1245 for (tech_drivers = technology->driver_list;
1247 tech_drivers = g_slist_next(tech_drivers)) {
1248 struct connman_technology_driver *driver =
1251 if (driver->set_regdom) {
1252 driver->set_regdom(technology, alpha2);
1262 connman_technology_regdom_notify(technology, alpha2);
1265 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1267 struct connman_technology *technology = data;
1270 DBG("technology %p request from %s", technology,
1271 dbus_message_get_sender(msg));
1273 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1274 !technology->enabled)
1275 return __connman_error_permission_denied(msg);
1277 dbus_message_ref(msg);
1278 #if !defined TIZEN_EXT
1279 technology->scan_pending =
1280 g_slist_prepend(technology->scan_pending, msg);
1283 err = __connman_device_request_scan(technology->type);
1284 #if defined TIZEN_EXT
1286 return __connman_error_failed(msg, -err);
1289 reply_scan_pending(technology, err);
1292 #if defined TIZEN_EXT
1294 g_scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1295 DBG("g_scan_type %d", g_scan_type);
1297 technology->scan_pending =
1298 g_slist_prepend(technology->scan_pending, msg);
1303 #if defined TIZEN_EXT
1304 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1306 struct connman_technology *technology = data;
1307 GSList *specific_scan_list = NULL;
1309 const char *name = NULL;
1310 const char *freq = NULL;
1311 DBusMessageIter iter, dict;
1314 DBG("technology %p request from %s", technology,
1315 dbus_message_get_sender(msg));
1317 if (!dbus_message_iter_init(msg, &iter))
1318 return __connman_error_invalid_arguments(msg);
1320 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1321 return __connman_error_invalid_arguments(msg);
1323 dbus_message_iter_recurse(&iter, &dict);
1324 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1325 DBusMessageIter entry, value2;
1329 dbus_message_iter_recurse(&dict, &entry);
1330 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1331 g_slist_free_full(specific_scan_list, g_free);
1332 return __connman_error_invalid_arguments(msg);
1335 dbus_message_iter_get_basic(&entry, &key);
1336 dbus_message_iter_next(&entry);
1338 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1339 g_slist_free_full(specific_scan_list, g_free);
1340 return __connman_error_invalid_arguments(msg);
1343 dbus_message_iter_recurse(&entry, &value2);
1344 type = dbus_message_iter_get_arg_type(&value2);
1345 if (g_str_equal(key, "SSID")) {
1346 if (type != DBUS_TYPE_STRING) {
1347 g_slist_free_full(specific_scan_list, g_free);
1348 return __connman_error_invalid_arguments(msg);
1351 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1352 dbus_message_iter_get_basic(&value2, &name);
1353 DBG("name %s", name);
1354 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1355 } else if (g_str_equal(key, "Frequency")) {
1356 if (type != DBUS_TYPE_STRING) {
1357 g_slist_free_full(specific_scan_list, g_free);
1358 return __connman_error_invalid_arguments(msg);
1361 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1362 dbus_message_iter_get_basic(&value2, &freq);
1363 DBG("freq %s", freq);
1364 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1365 } else if (g_str_equal(key, "SSID_Mixed")) {
1366 if (type != DBUS_TYPE_STRING) {
1367 g_slist_free_full(specific_scan_list, g_free);
1368 return __connman_error_invalid_arguments(msg);
1371 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1372 dbus_message_iter_get_basic(&value2, &name);
1374 connman_multi_scan_ap_s *ap = (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1376 g_strlcpy(ap->str, name, strlen(name) + 1);
1378 specific_scan_list = g_slist_append(specific_scan_list, ap);
1380 DBG("Failed to allocate memory");
1382 } else if (g_str_equal(key, "Frequency_Mixed")) {
1383 if (type != DBUS_TYPE_STRING) {
1384 g_slist_free_full(specific_scan_list, g_free);
1385 return __connman_error_invalid_arguments(msg);
1388 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1389 dbus_message_iter_get_basic(&value2, &freq);
1391 connman_multi_scan_ap_s *ap = (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1393 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1395 specific_scan_list = g_slist_append(specific_scan_list, ap);
1397 DBG("Failed to allocate memory");
1399 dbus_message_iter_next(&dict);
1402 dbus_message_ref(msg);
1404 err = __connman_device_request_specific_scan(technology->type, scan_type, specific_scan_list);
1406 return __connman_error_failed(msg, -err);
1409 guint list_size = g_slist_length(specific_scan_list);
1411 g_scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1413 g_scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1414 DBG("list_size %u g_scan_type %d", list_size, g_scan_type);
1416 technology->scan_pending =
1417 g_slist_prepend(technology->scan_pending, msg);
1419 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
1420 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) {
1421 g_slist_free_full(specific_scan_list, g_free);
1427 #if defined TIZEN_EXT
1428 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
1431 DBusMessageIter iter, dict;
1432 struct connman_technology *technology = data;
1433 dbus_bool_t supported = technology->is_5_0_ghz_supported;
1435 DBG("technology %p", technology);
1437 reply = dbus_message_new_method_return(msg);
1441 dbus_message_iter_init_append(reply, &iter);
1443 connman_dbus_dict_open(&iter, &dict);
1444 connman_dbus_dict_append_basic(&dict, "Is5GhzSupported",
1448 connman_dbus_dict_close(&iter, &dict);
1454 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
1457 DBusMessageIter iter, dict;
1459 struct connman_technology *technology = data;
1460 dbus_bool_t scanning = false;
1462 DBG("technology %p", technology);
1464 for (list = technology->device_list; list; list = list->next) {
1465 struct connman_device *device = list->data;
1466 scanning = connman_device_get_scanning(device);
1471 DBG("scanning : %d", scanning);
1472 reply = dbus_message_new_method_return(msg);
1476 dbus_message_iter_init_append(reply, &iter);
1478 connman_dbus_dict_open(&iter, &dict);
1479 connman_dbus_dict_append_basic(&dict, "Scanstate",
1483 connman_dbus_dict_close(&iter, &dict);
1488 void connman_techonology_set_max_scan_ssids(struct connman_technology *technology,
1492 technology->max_scan_ssids = max_scan_ssids;
1495 static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
1498 DBusMessageIter iter, dict;
1499 struct connman_technology *technology = data;
1500 dbus_int32_t max_scan_ssids = technology->max_scan_ssids;
1502 DBG("technology %p", technology);
1504 reply = dbus_message_new_method_return(msg);
1508 dbus_message_iter_init_append(reply, &iter);
1510 connman_dbus_dict_open(&iter, &dict);
1511 connman_dbus_dict_append_basic(&dict, "MaxScanSSID",
1515 connman_dbus_dict_close(&iter, &dict);
1521 #if defined TIZEN_EXT_WIFI_MESH
1522 bool __connman_technology_get_connected(enum connman_service_type type)
1524 struct connman_technology *technology;
1526 technology = technology_find(type);
1531 return technology->connected;
1534 void __connman_technology_mesh_interface_create_finished(
1535 enum connman_service_type type, bool success,
1539 struct connman_technology *technology;
1541 technology = technology_find(type);
1543 DBG("technology %p success %d", technology, success);
1548 msg = technology->mesh_dbus_msg;
1550 DBG("No pending dbus message");
1555 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1556 __connman_device_request_scan(technology->type);
1558 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
1559 ".MeshInterfaceAddFailed", "%s", error);
1560 g_dbus_send_message(connection, reply);
1561 dbus_message_unref(msg);
1562 technology->mesh_dbus_msg = NULL;
1565 void __connman_technology_mesh_interface_remove_finished(
1566 enum connman_service_type type, bool success)
1569 struct connman_technology *technology;
1571 technology = technology_find(type);
1573 DBG("technology %p success %d", technology, success);
1575 if (!technology || !technology->mesh_dbus_msg)
1578 msg = technology->mesh_dbus_msg;
1580 DBG("No pending dbus message");
1585 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1587 reply = __connman_error_failed(msg, EINVAL);
1588 g_dbus_send_message(connection, reply);
1589 dbus_message_unref(msg);
1590 technology->mesh_dbus_msg = NULL;
1593 void __connman_technology_notify_abort_scan(enum connman_service_type type,
1597 struct connman_technology *technology;
1599 technology = technology_find(type);
1601 DBG("technology %p result %d", technology, result);
1603 if (!technology || !technology->mesh_dbus_msg)
1606 msg = technology->mesh_dbus_msg;
1608 DBG("No pending dbus message");
1613 reply = __connman_error_scan_abort_failed(msg);
1615 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1617 g_dbus_send_message(connection, reply);
1618 dbus_message_unref(msg);
1619 technology->mesh_dbus_msg = NULL;
1622 static DBusMessage *mesh_commands(DBusConnection *conn,
1623 DBusMessage *msg, void *data)
1625 struct connman_technology *technology = data;
1626 DBusMessageIter iter, value, dict;
1627 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
1630 DBG("conn %p", conn);
1632 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
1633 return __connman_error_invalid_arguments(msg);
1635 if (!dbus_message_iter_init(msg, &iter))
1636 return __connman_error_invalid_arguments(msg);
1638 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1639 return __connman_error_invalid_arguments(msg);
1641 dbus_message_iter_get_basic(&iter, &cmd);
1642 dbus_message_iter_next(&iter);
1644 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1645 return __connman_error_invalid_arguments(msg);
1647 dbus_message_iter_recurse(&iter, &value);
1649 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
1650 return __connman_error_invalid_arguments(msg);
1652 DBG("Mesh Command %s", cmd);
1653 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
1654 dbus_message_iter_recurse(&value, &dict);
1655 const char *bridge_ifname = NULL;
1656 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1657 DBusMessageIter entry, value2;
1661 dbus_message_iter_recurse(&dict, &entry);
1663 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1664 return __connman_error_invalid_arguments(msg);
1666 dbus_message_iter_get_basic(&entry, &key);
1667 dbus_message_iter_next(&entry);
1669 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1670 return __connman_error_invalid_arguments(msg);
1672 dbus_message_iter_recurse(&entry, &value2);
1674 type = dbus_message_iter_get_arg_type(&value2);
1676 if (g_str_equal(key, "Ifname")) {
1677 if (type != DBUS_TYPE_STRING)
1678 return __connman_error_invalid_arguments(msg);
1680 dbus_message_iter_get_basic(&value2, &ifname);
1681 } else if (g_str_equal(key, "ParentIfname")) {
1682 if (type != DBUS_TYPE_STRING)
1683 return __connman_error_invalid_arguments(msg);
1685 dbus_message_iter_get_basic(&value2, &parent_ifname);
1686 } else if (g_str_equal(key, "BridgeIfname")) {
1687 if (type != DBUS_TYPE_STRING)
1688 return __connman_error_invalid_arguments(msg);
1690 dbus_message_iter_get_basic(&value2, &bridge_ifname);
1692 dbus_message_iter_next(&dict);
1694 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
1695 bridge_ifname ? bridge_ifname : "NULL");
1696 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
1700 DBG("Failed to add virtual mesh interface");
1701 return __connman_error_failed(msg, -err);
1704 DBG("Successfully added virtual mesh interface");
1706 dbus_message_ref(msg);
1707 technology->mesh_dbus_msg = msg;
1709 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
1710 dbus_message_iter_recurse(&value, &dict);
1711 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1712 DBusMessageIter entry, value2;
1716 dbus_message_iter_recurse(&dict, &entry);
1718 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1719 return __connman_error_invalid_arguments(msg);
1721 dbus_message_iter_get_basic(&entry, &key);
1722 dbus_message_iter_next(&entry);
1724 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1725 return __connman_error_invalid_arguments(msg);
1727 dbus_message_iter_recurse(&entry, &value2);
1729 type = dbus_message_iter_get_arg_type(&value2);
1731 if (g_str_equal(key, "Ifname")) {
1732 if (type != DBUS_TYPE_STRING)
1733 return __connman_error_invalid_arguments(msg);
1735 dbus_message_iter_get_basic(&value2, &ifname);
1737 dbus_message_iter_next(&dict);
1739 DBG("Mesh Ifname %s", ifname);
1740 err = __connman_mesh_remove_virtual_interface(ifname);
1743 DBG("Failed to remove virtual mesh interface");
1744 return __connman_error_failed(msg, -err);
1747 DBG("Successfully removed virtual mesh interface");
1749 dbus_message_ref(msg);
1750 technology->mesh_dbus_msg = msg;
1752 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
1753 struct connman_mesh *connman_mesh;
1754 const char *name = NULL;
1755 const char *sec_type = NULL;
1756 const char *mesh_ifname = NULL;
1757 char *identifier, *group, *address;
1758 unsigned int freq = 0;
1759 unsigned int ieee80211w = 0;
1762 dbus_message_iter_recurse(&value, &dict);
1763 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1764 DBusMessageIter entry, value2;
1768 dbus_message_iter_recurse(&dict, &entry);
1770 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1771 return __connman_error_invalid_arguments(msg);
1773 dbus_message_iter_get_basic(&entry, &key);
1774 dbus_message_iter_next(&entry);
1776 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1777 return __connman_error_invalid_arguments(msg);
1779 dbus_message_iter_recurse(&entry, &value2);
1781 type = dbus_message_iter_get_arg_type(&value2);
1783 if (g_str_equal(key, "Name")) {
1784 if (type != DBUS_TYPE_STRING)
1785 return __connman_error_invalid_arguments(msg);
1787 dbus_message_iter_get_basic(&value2, &name);
1788 } else if (g_str_equal(key, "Frequency")) {
1789 if (type != DBUS_TYPE_UINT16)
1790 return __connman_error_invalid_arguments(msg);
1792 dbus_message_iter_get_basic(&value2, &freq);
1793 } else if (g_str_equal(key, "Security")) {
1794 if (type != DBUS_TYPE_STRING)
1795 return __connman_error_invalid_arguments(msg);
1797 dbus_message_iter_get_basic(&value2, &sec_type);
1798 } else if (g_str_equal(key, "Pmf")) {
1799 if (type != DBUS_TYPE_UINT16)
1800 return __connman_error_invalid_arguments(msg);
1802 dbus_message_iter_get_basic(&value2, &ieee80211w);
1804 dbus_message_iter_next(&dict);
1807 if (name == NULL || sec_type == NULL || freq == 0)
1808 return __connman_error_invalid_arguments(msg);
1810 DBG("Name %s Frequency %d Security type %s Pmf %u",
1811 name, freq, sec_type, ieee80211w);
1813 if (g_strcmp0(sec_type, "none") != 0 &&
1814 g_strcmp0(sec_type, "sae") != 0) {
1815 DBG("Unsupported security");
1816 return __connman_error_invalid_arguments(msg);
1819 mesh_ifname = connman_mesh_get_interface_name();
1821 if (!connman_mesh_is_interface_created()) {
1822 DBG("Mesh interface doesn't exists");
1823 return __connman_error_invalid_command(msg);
1826 str = g_string_sized_new((strlen(name) * 2) + 24);
1828 for (i = 0; name[i]; i++)
1829 g_string_append_printf(str, "%02x", name[i]);
1831 g_string_append_printf(str, "_mesh");
1833 if (g_strcmp0(sec_type, "none") == 0)
1834 g_string_append_printf(str, "_none");
1835 else if (g_strcmp0(sec_type, "sae") == 0)
1836 g_string_append_printf(str, "_sae");
1838 group = g_string_free(str, FALSE);
1840 identifier = connman_inet_ifaddr(mesh_ifname);
1841 address = connman_inet_ifname2addr(mesh_ifname);
1843 connman_mesh = connman_mesh_create(identifier, group);
1844 connman_mesh_set_name(connman_mesh, name);
1845 connman_mesh_set_address(connman_mesh, address);
1846 connman_mesh_set_security(connman_mesh, sec_type);
1847 connman_mesh_set_frequency(connman_mesh, freq);
1848 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
1849 connman_mesh_set_peer_type(connman_mesh,
1850 CONNMAN_MESH_PEER_TYPE_CREATED);
1851 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
1853 connman_mesh_register(connman_mesh);
1857 DBG("Successfully Created Mesh Network");
1858 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1860 } else if (g_str_equal(cmd, "AbortScan")) {
1861 DBG("Abort Scan method");
1862 err = __connman_device_abort_scan(technology->type);
1864 DBG("Failed to abort scan");
1865 return __connman_error_failed(msg, -err);
1868 DBG("Successfully requested to abort scan");
1869 dbus_message_ref(msg);
1870 technology->mesh_dbus_msg = msg;
1872 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
1873 const char *name = NULL;
1874 unsigned int freq = 0;
1875 dbus_message_iter_recurse(&value, &dict);
1876 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1877 DBusMessageIter entry, value2;
1881 dbus_message_iter_recurse(&dict, &entry);
1883 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1884 return __connman_error_invalid_arguments(msg);
1886 dbus_message_iter_get_basic(&entry, &key);
1887 dbus_message_iter_next(&entry);
1889 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1890 return __connman_error_invalid_arguments(msg);
1892 dbus_message_iter_recurse(&entry, &value2);
1894 type = dbus_message_iter_get_arg_type(&value2);
1896 if (g_str_equal(key, "Name")) {
1897 if (type != DBUS_TYPE_STRING)
1898 return __connman_error_invalid_arguments(msg);
1900 dbus_message_iter_get_basic(&value2, &name);
1901 } else if (g_str_equal(key, "Frequency")) {
1902 if (type != DBUS_TYPE_UINT16)
1903 return __connman_error_invalid_arguments(msg);
1905 dbus_message_iter_get_basic(&value2, &freq);
1907 dbus_message_iter_next(&dict);
1910 DBG("MeshID %s Frequency %d sender %s", name, freq,
1911 dbus_message_get_sender(msg));
1913 dbus_message_ref(msg);
1914 technology->scan_pending =
1915 g_slist_prepend(technology->scan_pending, msg);
1917 err = __connman_device_request_mesh_specific_scan(technology->type,
1920 reply_scan_pending(technology, err);
1922 DBG("Successfully requested to scan specific Mesh Network");
1924 } else if (g_str_equal(cmd, "SetMeshGate")) {
1925 unsigned int hwmp_rootmode = 0;
1926 bool gate_announce = false;
1927 unsigned int stp = 0;
1929 dbus_message_iter_recurse(&value, &dict);
1930 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1931 DBusMessageIter entry, value2;
1935 dbus_message_iter_recurse(&dict, &entry);
1937 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1938 return __connman_error_invalid_arguments(msg);
1940 dbus_message_iter_get_basic(&entry, &key);
1941 dbus_message_iter_next(&entry);
1943 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1944 return __connman_error_invalid_arguments(msg);
1946 dbus_message_iter_recurse(&entry, &value2);
1948 type = dbus_message_iter_get_arg_type(&value2);
1950 if (g_str_equal(key, "GateAnnounce")) {
1951 if (type != DBUS_TYPE_BOOLEAN)
1952 return __connman_error_invalid_arguments(msg);
1954 dbus_message_iter_get_basic(&value2, &gate_announce);
1955 } else if (g_str_equal(key, "HWMPRootMode")) {
1956 if (type != DBUS_TYPE_UINT16)
1957 return __connman_error_invalid_arguments(msg);
1959 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
1960 } else if (g_str_equal(key, "STP")) {
1961 if (type != DBUS_TYPE_UINT16)
1962 return __connman_error_invalid_arguments(msg);
1964 dbus_message_iter_get_basic(&value2, &stp);
1966 dbus_message_iter_next(&dict);
1969 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
1970 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
1972 err = __connman_mesh_set_stp_gate_announce(gate_announce,
1977 return __connman_error_failed(msg, -err);
1979 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1981 return __connman_error_invalid_command(msg);
1986 static const GDBusMethodTable technology_methods[] = {
1987 { GDBUS_DEPRECATED_METHOD("GetProperties",
1988 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1990 { GDBUS_ASYNC_METHOD("SetProperty",
1991 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1992 NULL, set_property) },
1993 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1994 #if defined TIZEN_EXT
1995 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
1996 NULL, specific_scan) },
1997 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
1999 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
2000 get_5ghz_supported) },
2001 { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
2002 get_max_scan_ssid) },
2004 #if defined TIZEN_EXT_WIFI_MESH
2005 { GDBUS_ASYNC_METHOD("MeshCommands",
2006 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2007 NULL, mesh_commands) },
2012 static const GDBusSignalTable technology_signals[] = {
2013 { GDBUS_SIGNAL("PropertyChanged",
2014 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
2015 { GDBUS_SIGNAL("DhcpConnected",
2016 GDBUS_ARGS({ "aptype", "s" },
2019 { "hostname", "s" })) },
2020 { GDBUS_SIGNAL("DhcpLeaseDeleted",
2021 GDBUS_ARGS({ "aptype", "s" },
2024 { "hostname", "s" })) },
2028 static bool technology_dbus_register(struct connman_technology *technology)
2030 if (technology->dbus_registered ||
2031 (technology->rfkill_driven &&
2032 technology->hardblocked))
2035 if (!g_dbus_register_interface(connection, technology->path,
2036 CONNMAN_TECHNOLOGY_INTERFACE,
2037 technology_methods, technology_signals,
2038 NULL, technology, NULL)) {
2039 connman_error("Failed to register %s", technology->path);
2043 technology_added_signal(technology);
2044 technology->dbus_registered = true;
2049 static void technology_dbus_unregister(struct connman_technology *technology)
2051 if (!technology->dbus_registered)
2054 technology_removed_signal(technology);
2055 g_dbus_unregister_interface(connection, technology->path,
2056 CONNMAN_TECHNOLOGY_INTERFACE);
2058 technology->dbus_registered = false;
2061 static void technology_put(struct connman_technology *technology)
2063 DBG("technology %p", technology);
2065 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
2068 reply_scan_pending(technology, -EINTR);
2070 while (technology->driver_list) {
2071 struct connman_technology_driver *driver;
2073 driver = technology->driver_list->data;
2076 driver->remove(technology);
2078 technology->driver_list =
2079 g_slist_delete_link(technology->driver_list,
2080 technology->driver_list);
2083 technology_list = g_slist_remove(technology_list, technology);
2085 technology_dbus_unregister(technology);
2087 g_slist_free(technology->device_list);
2089 if (technology->pending_reply) {
2090 dbus_message_unref(technology->pending_reply);
2091 technology->pending_reply = NULL;
2092 g_source_remove(technology->pending_timeout);
2093 technology->pending_timeout = 0;
2096 g_free(technology->path);
2097 g_free(technology->regdom);
2098 g_free(technology->tethering_ident);
2099 g_free(technology->tethering_passphrase);
2103 static struct connman_technology *technology_get(enum connman_service_type type)
2105 GSList *tech_drivers = NULL;
2106 struct connman_technology_driver *driver;
2107 struct connman_technology *technology;
2111 DBG("type %d", type);
2113 str = __connman_service_type2string(type);
2117 technology = technology_find(type);
2119 #if defined TIZEN_EXT_WIFI_MESH
2120 if (type != CONNMAN_SERVICE_TYPE_P2P &&
2121 type != CONNMAN_SERVICE_TYPE_MESH)
2123 if (type != CONNMAN_SERVICE_TYPE_P2P)
2125 __sync_fetch_and_add(&technology->refcount, 1);
2129 /* First check if we have a driver for this technology type */
2130 for (list = driver_list; list; list = list->next) {
2131 driver = list->data;
2133 if (driver->type == type) {
2134 DBG("technology %p driver %p", technology, driver);
2135 tech_drivers = g_slist_append(tech_drivers, driver);
2139 if (!tech_drivers) {
2140 DBG("No matching drivers found for %s.",
2141 __connman_service_type2string(type));
2145 technology = g_try_new0(struct connman_technology, 1);
2149 technology->refcount = 1;
2150 technology->type = type;
2151 technology->tethering_hidden = FALSE;
2152 technology->path = g_strdup_printf("%s/technology/%s",
2155 #if defined TIZEN_EXT_WIFI_MESH
2156 if (type == CONNMAN_SERVICE_TYPE_MESH) {
2157 struct connman_technology *wifi;
2159 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2161 technology->enabled = wifi->enabled;
2165 technology_load(technology);
2166 technology_list = g_slist_prepend(technology_list, technology);
2167 technology->driver_list = tech_drivers;
2169 for (list = tech_drivers; list; list = list->next) {
2170 driver = list->data;
2172 if (driver->probe && driver->probe(technology) < 0)
2173 DBG("Driver probe failed for technology %p",
2177 if (!technology_dbus_register(technology)) {
2178 technology_put(technology);
2182 if (type == CONNMAN_SERVICE_TYPE_P2P) {
2183 struct connman_technology *wifi;
2186 enable = technology->enable_persistent;
2188 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2190 enable = wifi->enabled;
2192 technology_affect_devices(technology, enable);
2195 DBG("technology %p %s", technology, get_name(technology->type));
2200 int connman_technology_driver_register(struct connman_technology_driver *driver)
2203 struct connman_device *device;
2204 enum connman_service_type type;
2206 for (list = driver_list; list; list = list->next) {
2207 if (list->data == driver)
2211 DBG("Registering %s driver", driver->name);
2213 driver_list = g_slist_insert_sorted(driver_list, driver,
2217 * Check for technology less devices if this driver
2218 * can service any of them.
2220 for (list = techless_device_list; list; list = list->next) {
2221 device = list->data;
2223 type = __connman_device_get_service_type(device);
2224 if (type != driver->type)
2227 techless_device_list = g_slist_remove(techless_device_list,
2230 __connman_technology_add_device(device);
2233 /* Check for orphaned rfkill switches. */
2234 g_hash_table_foreach(rfkill_list, rfkill_check,
2235 GINT_TO_POINTER(driver->type));
2238 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
2239 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
2243 #if defined TIZEN_EXT_WIFI_MESH
2244 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
2245 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
2253 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
2255 GSList *list, *tech_drivers;
2256 struct connman_technology *technology;
2257 struct connman_technology_driver *current;
2259 DBG("Unregistering driver %p name %s", driver, driver->name);
2261 for (list = technology_list; list; list = list->next) {
2262 technology = list->data;
2264 for (tech_drivers = technology->driver_list; tech_drivers;
2265 tech_drivers = g_slist_next(tech_drivers)) {
2266 current = tech_drivers->data;
2267 if (driver != current)
2271 driver->remove(technology);
2273 technology->driver_list =
2274 g_slist_remove(technology->driver_list,
2280 driver_list = g_slist_remove(driver_list, driver);
2282 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
2283 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
2285 technology_put(technology);
2287 #if defined TIZEN_EXT_WIFI_MESH
2288 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
2289 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
2291 technology_put(technology);
2296 void __connman_technology_add_interface(enum connman_service_type type,
2297 int index, const char *ident)
2299 struct connman_technology *technology;
2300 GSList *tech_drivers;
2301 struct connman_technology_driver *driver;
2305 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2306 case CONNMAN_SERVICE_TYPE_SYSTEM:
2308 case CONNMAN_SERVICE_TYPE_ETHERNET:
2309 case CONNMAN_SERVICE_TYPE_WIFI:
2310 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2311 case CONNMAN_SERVICE_TYPE_CELLULAR:
2312 case CONNMAN_SERVICE_TYPE_GPS:
2313 case CONNMAN_SERVICE_TYPE_VPN:
2314 case CONNMAN_SERVICE_TYPE_GADGET:
2315 case CONNMAN_SERVICE_TYPE_P2P:
2316 #if defined TIZEN_EXT_WIFI_MESH
2317 case CONNMAN_SERVICE_TYPE_MESH:
2322 name = connman_inet_ifname(index);
2323 connman_info("Adding interface %s [ %s ]", name,
2324 __connman_service_type2string(type));
2326 technology = technology_find(type);
2331 for (tech_drivers = technology->driver_list; tech_drivers;
2332 tech_drivers = g_slist_next(tech_drivers)) {
2333 driver = tech_drivers->data;
2335 if (driver->add_interface)
2336 driver->add_interface(technology, index, name, ident);
2340 * At this point we can try to enable tethering automatically as
2341 * now the interfaces are set properly.
2343 if (technology->tethering_persistent)
2344 enable_tethering(technology);
2350 void __connman_technology_remove_interface(enum connman_service_type type,
2351 int index, const char *ident)
2353 struct connman_technology *technology;
2354 GSList *tech_drivers;
2355 struct connman_technology_driver *driver;
2359 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2360 case CONNMAN_SERVICE_TYPE_SYSTEM:
2362 case CONNMAN_SERVICE_TYPE_ETHERNET:
2363 case CONNMAN_SERVICE_TYPE_WIFI:
2364 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2365 case CONNMAN_SERVICE_TYPE_CELLULAR:
2366 case CONNMAN_SERVICE_TYPE_GPS:
2367 case CONNMAN_SERVICE_TYPE_VPN:
2368 case CONNMAN_SERVICE_TYPE_GADGET:
2369 case CONNMAN_SERVICE_TYPE_P2P:
2370 #if defined TIZEN_EXT_WIFI_MESH
2371 case CONNMAN_SERVICE_TYPE_MESH:
2376 name = connman_inet_ifname(index);
2377 connman_info("Remove interface %s [ %s ]", name,
2378 __connman_service_type2string(type));
2381 technology = technology_find(type);
2386 for (tech_drivers = technology->driver_list; tech_drivers;
2387 tech_drivers = g_slist_next(tech_drivers)) {
2388 driver = tech_drivers->data;
2390 if (driver->remove_interface)
2391 driver->remove_interface(technology, index);
2395 int __connman_technology_add_device(struct connman_device *device)
2397 struct connman_technology *technology;
2398 enum connman_service_type type;
2400 type = __connman_device_get_service_type(device);
2402 DBG("device %p type %s", device, get_name(type));
2404 technology = technology_get(type);
2407 * Since no driver can be found for this device at the moment we
2408 * add it to the techless device list.
2410 techless_device_list = g_slist_prepend(techless_device_list,
2416 __sync_synchronize();
2417 if (technology->rfkill_driven) {
2418 if (technology->enabled)
2419 __connman_device_enable(device);
2421 __connman_device_disable(device);
2426 if (technology->enable_persistent &&
2427 !global_offlinemode) {
2428 int err = __connman_device_enable(device);
2430 * connman_technology_add_device() calls __connman_device_enable()
2431 * but since the device is already enabled, the calls does not
2432 * propagate through to connman_technology_enabled via
2433 * connman_device_set_powered.
2435 if (err == -EALREADY)
2436 __connman_technology_enabled(type);
2438 /* if technology persistent state is offline */
2439 if (!technology->enable_persistent)
2440 __connman_device_disable(device);
2443 technology->device_list = g_slist_prepend(technology->device_list,
2449 int __connman_technology_remove_device(struct connman_device *device)
2451 struct connman_technology *technology;
2452 enum connman_service_type type;
2454 DBG("device %p", device);
2456 type = __connman_device_get_service_type(device);
2458 technology = technology_find(type);
2460 techless_device_list = g_slist_remove(techless_device_list,
2465 technology->device_list = g_slist_remove(technology->device_list,
2468 if (technology->tethering)
2469 set_tethering(technology, false);
2471 technology_put(technology);
2476 int __connman_technology_enabled(enum connman_service_type type)
2478 struct connman_technology *technology;
2480 technology = technology_find(type);
2484 DBG("technology %p type %s rfkill %d enabled %d", technology,
2485 get_name(type), technology->rfkill_driven,
2486 technology->enabled);
2487 #if !defined TIZEN_EXT
2488 if (technology->rfkill_driven) {
2489 if (technology->tethering_persistent)
2490 enable_tethering(technology);
2495 return technology_enabled(technology);
2498 int __connman_technology_disabled(enum connman_service_type type)
2500 struct connman_technology *technology;
2503 technology = technology_find(type);
2506 #if !defined TIZEN_EXT
2507 if (technology->rfkill_driven)
2510 for (list = technology->device_list; list; list = list->next) {
2511 struct connman_device *device = list->data;
2513 if (connman_device_get_powered(device))
2517 return technology_disabled(technology);
2520 int __connman_technology_set_offlinemode(bool offlinemode)
2523 int err = -EINVAL, enabled_tech_count = 0;
2525 if (global_offlinemode == offlinemode)
2528 DBG("offlinemode %s", offlinemode ? "On" : "Off");
2531 * This is a bit tricky. When you set offlinemode, there is no
2532 * way to differentiate between attempting offline mode and
2533 * resuming offlinemode from last saved profile. We need that
2534 * information in rfkill_update, otherwise it falls back on the
2535 * technology's persistent state. Hence we set the offline mode here
2536 * but save it & call the notifier only if its successful.
2539 global_offlinemode = offlinemode;
2541 /* Traverse technology list, enable/disable each technology. */
2542 for (list = technology_list; list; list = list->next) {
2543 struct connman_technology *technology = list->data;
2546 err = technology_disable(technology);
2548 if (technology->hardblocked)
2551 if (technology->enable_persistent) {
2552 err = technology_enable(technology);
2553 enabled_tech_count++;
2558 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
2559 (err == -EINVAL && enabled_tech_count == 0)) {
2560 connman_technology_save_offlinemode();
2561 __connman_notifier_offlinemode(offlinemode);
2563 global_offlinemode = connman_technology_load_offlinemode();
2568 #if defined TIZEN_EXT_WIFI_MESH
2569 static gboolean __add_ethernet_to_bridge(gpointer data)
2572 __connman_mesh_add_ethernet_to_bridge();
2577 void __connman_technology_set_connected(enum connman_service_type type,
2580 struct connman_technology *technology;
2583 technology = technology_find(type);
2587 DBG("technology %p connected %d", technology, connected);
2589 technology->connected = connected;
2591 #if defined TIZEN_EXT_WIFI_MESH
2592 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
2593 g_idle_add(__add_ethernet_to_bridge, NULL);
2597 connman_dbus_property_changed_basic(technology->path,
2598 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
2599 DBUS_TYPE_BOOLEAN, &val);
2602 static bool technology_apply_rfkill_change(struct connman_technology *technology,
2607 bool hardblock_changed = false;
2609 GList *start, *list;
2611 DBG("technology %p --> %d/%d vs %d/%d",
2612 technology, softblock, hardblock,
2613 technology->softblocked, technology->hardblocked);
2615 if (technology->hardblocked == hardblock)
2616 goto softblock_change;
2618 if (!(new_rfkill && !hardblock)) {
2619 start = g_hash_table_get_values(rfkill_list);
2621 for (list = start; list; list = list->next) {
2622 struct connman_rfkill *rfkill = list->data;
2624 if (rfkill->type != technology->type)
2627 if (rfkill->hardblock != hardblock)
2635 goto softblock_change;
2637 technology->hardblocked = hardblock;
2638 hardblock_changed = true;
2641 if (!apply && technology->softblocked != softblock)
2645 return technology->hardblocked;
2647 technology->softblocked = softblock;
2649 if (technology->hardblocked ||
2650 technology->softblocked) {
2651 if (technology_disabled(technology) != -EALREADY)
2652 technology_affect_devices(technology, false);
2653 } else if (!technology->hardblocked &&
2654 !technology->softblocked) {
2655 if (technology_enabled(technology) != -EALREADY)
2656 technology_affect_devices(technology, true);
2659 if (hardblock_changed) {
2660 if (technology->hardblocked) {
2661 DBG("%s is switched off.", get_name(technology->type));
2662 technology_dbus_unregister(technology);
2664 DBG("%s is switched on.", get_name(technology->type));
2665 technology_dbus_register(technology);
2667 if (global_offlinemode)
2668 __connman_rfkill_block(technology->type, true);
2672 return technology->hardblocked;
2675 int __connman_technology_add_rfkill(unsigned int index,
2676 enum connman_service_type type,
2680 struct connman_technology *technology;
2681 struct connman_rfkill *rfkill;
2683 DBG("index %u type %d soft %u hard %u", index, type,
2684 softblock, hardblock);
2686 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2690 rfkill = g_try_new0(struct connman_rfkill, 1);
2694 rfkill->index = index;
2695 rfkill->type = type;
2696 rfkill->softblock = softblock;
2697 rfkill->hardblock = hardblock;
2699 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
2702 #if defined TIZEN_EXT
2703 /* Fix Svace Issue [WGID: 1348]. */
2706 technology = technology_get(type);
2707 /* If there is no driver for this type, ignore it. */
2711 technology->rfkill_driven = true;
2713 #if !defined TIZEN_EXT
2714 /* If hardblocked, there is no need to handle softblocked state */
2715 if (technology_apply_rfkill_change(technology,
2716 softblock, hardblock, true))
2719 if (global_offlinemode)
2723 * Depending on softblocked state we unblock/block according to
2724 * offlinemode and persistente state.
2726 if (technology->softblocked &&
2727 technology->enable_persistent)
2728 return __connman_rfkill_block(type, false);
2729 else if (!technology->softblocked &&
2730 !technology->enable_persistent)
2731 return __connman_rfkill_block(type, true);
2736 int __connman_technology_update_rfkill(unsigned int index,
2737 enum connman_service_type type,
2741 struct connman_technology *technology;
2742 struct connman_rfkill *rfkill;
2744 DBG("index %u soft %u hard %u", index, softblock, hardblock);
2746 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2750 if (rfkill->softblock == softblock &&
2751 rfkill->hardblock == hardblock)
2754 rfkill->softblock = softblock;
2755 rfkill->hardblock = hardblock;
2757 technology = technology_find(type);
2758 /* If there is no driver for this type, ignore it. */
2762 technology_apply_rfkill_change(technology, softblock, hardblock,
2765 if (technology->hardblocked)
2766 DBG("%s hardblocked", get_name(technology->type));
2768 DBG("%s is%s softblocked", get_name(technology->type),
2769 technology->softblocked ? "" : " not");
2774 int __connman_technology_remove_rfkill(unsigned int index,
2775 enum connman_service_type type)
2777 struct connman_technology *technology;
2778 struct connman_rfkill *rfkill;
2780 DBG("index %u", index);
2782 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2786 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
2788 technology = technology_find(type);
2792 technology_apply_rfkill_change(technology,
2793 technology->softblocked, !technology->hardblocked, false);
2795 technology_put(technology);
2800 int __connman_technology_init(void)
2804 connection = connman_dbus_get_connection();
2806 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2809 global_offlinemode = connman_technology_load_offlinemode();
2811 /* This will create settings file if it is missing */
2812 connman_technology_save_offlinemode();
2817 void __connman_technology_cleanup(void)
2821 while (technology_list) {
2822 struct connman_technology *technology = technology_list->data;
2823 technology_list = g_slist_remove(technology_list, technology);
2824 technology_put(technology);
2827 g_hash_table_destroy(rfkill_list);
2829 dbus_connection_unref(connection);