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
38 static DBusConnection *connection;
40 static GSList *technology_list = NULL;
43 * List of devices with no technology associated with them either because of
44 * no compiled in support or the driver is not yet loaded.
46 static GSList *techless_device_list = NULL;
47 static GHashTable *rfkill_list;
49 static bool global_offlinemode;
52 struct connman_scan_pending {
54 connman_scan_type_e scan_type;
58 struct connman_bssid_pending {
60 unsigned char bssid[6];
64 struct connman_rfkill {
66 enum connman_service_type type;
71 struct connman_technology {
73 enum connman_service_type type;
81 bool tethering_persistent; /* Tells the save status, needed
82 * as offline mode might set
85 char *tethering_ident;
86 char *tethering_passphrase;
88 bool enable_persistent; /* Save the tech state */
92 DBusMessage *pending_reply;
93 guint pending_timeout;
100 bool dbus_registered;
101 #if defined TIZEN_EXT
102 char **enabled_devices;
104 #if defined TIZEN_EXT_WIFI_MESH
105 DBusMessage *mesh_dbus_msg;
109 static GSList *driver_list = NULL;
111 static int technology_enabled(struct connman_technology *technology);
112 static int technology_disabled(struct connman_technology *technology);
114 static gint compare_priority(gconstpointer a, gconstpointer b)
116 const struct connman_technology_driver *driver1 = a;
117 const struct connman_technology_driver *driver2 = b;
119 return driver2->priority - driver1->priority;
122 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
124 struct connman_rfkill *rfkill = value;
125 enum connman_service_type type = GPOINTER_TO_INT(user_data);
127 /* Calling _technology_add_rfkill will update the tech. */
128 if (rfkill->type == type)
129 __connman_technology_add_rfkill(rfkill->index, type,
130 rfkill->softblock, rfkill->hardblock);
134 connman_technology_is_tethering_allowed(enum connman_service_type type)
136 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
138 const char *type_str = __connman_service_type2string(type);
145 allowed = connman_setting_get_string_list("TetheringTechnologies");
147 allowed = allowed_default;
149 for (i = 0; allowed[i]; i++) {
150 if (g_strcmp0(allowed[i], type_str) == 0)
157 static const char *get_name(enum connman_service_type type)
160 case CONNMAN_SERVICE_TYPE_UNKNOWN:
161 case CONNMAN_SERVICE_TYPE_SYSTEM:
162 case CONNMAN_SERVICE_TYPE_GPS:
163 case CONNMAN_SERVICE_TYPE_VPN:
165 case CONNMAN_SERVICE_TYPE_GADGET:
167 case CONNMAN_SERVICE_TYPE_ETHERNET:
169 case CONNMAN_SERVICE_TYPE_WIFI:
171 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
173 case CONNMAN_SERVICE_TYPE_CELLULAR:
175 case CONNMAN_SERVICE_TYPE_P2P:
177 #if defined TIZEN_EXT_WIFI_MESH
178 case CONNMAN_SERVICE_TYPE_MESH:
186 static void technology_save(struct connman_technology *technology)
190 const char *name = get_name(technology->type);
192 DBG("technology %p type %d name %s", technology, technology->type,
197 keyfile = __connman_storage_load_global();
199 keyfile = g_key_file_new();
201 identifier = g_strdup_printf("%s", name);
205 g_key_file_set_boolean(keyfile, identifier, "Enable",
206 technology->enable_persistent);
208 g_key_file_set_boolean(keyfile, identifier, "Tethering",
209 technology->tethering_persistent);
211 if (technology->tethering_ident)
212 g_key_file_set_string(keyfile, identifier,
213 "Tethering.Identifier",
214 technology->tethering_ident);
216 if (technology->tethering_passphrase)
217 g_key_file_set_string(keyfile, identifier,
218 "Tethering.Passphrase",
219 technology->tethering_passphrase);
224 __connman_storage_save_global(keyfile);
226 g_key_file_free(keyfile);
229 static void tethering_changed(struct connman_technology *technology)
231 dbus_bool_t tethering = technology->tethering;
233 connman_dbus_property_changed_basic(technology->path,
234 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
235 DBUS_TYPE_BOOLEAN, &tethering);
237 technology_save(technology);
240 int connman_technology_tethering_notify(struct connman_technology *technology,
245 DBG("technology %p enabled %u", technology, enabled);
247 if (technology->tethering == enabled)
251 err = __connman_tethering_set_enabled();
255 __connman_tethering_set_disabled();
257 technology->tethering = enabled;
258 tethering_changed(technology);
263 static int set_tethering(struct connman_technology *technology,
266 int result = -EOPNOTSUPP;
268 const char *ident, *passphrase, *bridge;
269 GSList *tech_drivers;
271 ident = technology->tethering_ident;
272 passphrase = technology->tethering_passphrase;
274 __sync_synchronize();
275 if (!technology->enabled)
278 bridge = __connman_tethering_get_bridge();
282 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
283 (!ident || !passphrase))
286 for (tech_drivers = technology->driver_list; tech_drivers;
287 tech_drivers = g_slist_next(tech_drivers)) {
288 struct connman_technology_driver *driver = tech_drivers->data;
290 if (!driver || !driver->set_tethering)
293 err = driver->set_tethering(technology, ident, passphrase,
296 if (result == -EINPROGRESS)
299 if (err == -EINPROGRESS || err == 0)
306 void connman_technology_regdom_notify(struct connman_technology *technology,
312 connman_error("Failed to set regulatory domain");
314 DBG("Regulatory domain set to %s", alpha2);
316 g_free(technology->regdom);
317 technology->regdom = g_strdup(alpha2);
320 static int set_regdom_by_device(struct connman_technology *technology,
325 for (list = technology->device_list; list; list = list->next) {
326 struct connman_device *device = list->data;
328 if (connman_device_set_regdom(device, alpha2) != 0)
335 int connman_technology_set_regdom(const char *alpha2)
337 GSList *list, *tech_drivers;
339 for (list = technology_list; list; list = list->next) {
340 struct connman_technology *technology = list->data;
342 if (set_regdom_by_device(technology, alpha2) != 0) {
344 for (tech_drivers = technology->driver_list;
346 tech_drivers = g_slist_next(tech_drivers)) {
348 struct connman_technology_driver *driver =
351 if (driver->set_regdom)
352 driver->set_regdom(technology, alpha2);
360 static struct connman_technology *technology_find(enum connman_service_type type)
364 DBG("type %d", type);
366 for (list = technology_list; list; list = list->next) {
367 struct connman_technology *technology = list->data;
369 if (technology->type == type)
376 enum connman_service_type connman_technology_get_type
377 (struct connman_technology *technology)
380 return CONNMAN_SERVICE_TYPE_UNKNOWN;
382 return technology->type;
385 bool connman_technology_get_wifi_tethering(const char **ssid,
388 struct connman_technology *technology;
395 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
399 if (!technology->tethering)
402 *ssid = technology->tethering_ident;
403 *psk = technology->tethering_passphrase;
408 #if defined TIZEN_EXT
409 const char *connman_techonology_get_path(enum connman_service_type type)
411 struct connman_technology *technology = technology_find(type);
416 return technology->path;
420 static void free_rfkill(gpointer data)
422 struct connman_rfkill *rfkill = data;
427 static void technology_load(struct connman_technology *technology)
431 GError *error = NULL;
432 bool enable, need_saving = false;
434 DBG("technology %p", technology);
436 keyfile = __connman_storage_load_global();
437 /* Fallback on disabling technology if file not found. */
439 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
440 /* We enable ethernet by default */
441 technology->enable_persistent = true;
443 technology->enable_persistent = false;
447 identifier = g_strdup_printf("%s", get_name(technology->type));
453 technology->enabled_devices = g_key_file_get_string_list(keyfile,
454 identifier, "Enable.Devices", &length, NULL);
455 if (technology->enabled_devices && length == 0) {
456 g_strfreev(technology->enabled_devices);
457 technology->enabled_devices = NULL;
461 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
463 technology->enable_persistent = enable;
465 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
466 technology->enable_persistent = true;
468 technology->enable_persistent = false;
471 g_clear_error(&error);
474 enable = g_key_file_get_boolean(keyfile, identifier,
475 "Tethering", &error);
477 technology->tethering_persistent = enable;
480 g_clear_error(&error);
484 technology_save(technology);
486 technology->tethering_ident = g_key_file_get_string(keyfile,
487 identifier, "Tethering.Identifier", NULL);
489 technology->tethering_passphrase = g_key_file_get_string(keyfile,
490 identifier, "Tethering.Passphrase", NULL);
494 g_key_file_free(keyfile);
497 bool __connman_technology_get_offlinemode(void)
499 return global_offlinemode;
502 static void connman_technology_save_offlinemode(void)
505 GError *error = NULL;
508 keyfile = __connman_storage_load_global();
511 keyfile = g_key_file_new();
512 g_key_file_set_boolean(keyfile, "global",
513 "OfflineMode", global_offlinemode);
515 __connman_storage_save_global(keyfile);
518 offlinemode = g_key_file_get_boolean(keyfile, "global",
519 "OfflineMode", &error);
521 if (error || offlinemode != global_offlinemode) {
522 g_key_file_set_boolean(keyfile, "global",
523 "OfflineMode", global_offlinemode);
525 g_clear_error(&error);
527 __connman_storage_save_global(keyfile);
531 g_key_file_free(keyfile);
534 static bool connman_technology_load_offlinemode(void)
537 GError *error = NULL;
540 /* If there is a error, we enable offlinemode */
541 keyfile = __connman_storage_load_global();
545 offlinemode = g_key_file_get_boolean(keyfile, "global",
546 "OfflineMode", &error);
549 g_clear_error(&error);
552 g_key_file_free(keyfile);
557 #if defined TIZEN_EXT
558 static void append_devices(DBusMessageIter *iter, void *user_data)
562 struct connman_technology *technology = user_data;
564 for (list = technology->device_list; list; list = list->next) {
565 struct connman_device *device = list->data;
567 const char *str = connman_device_get_string(device, "Interface");
568 struct connman_network *network = connman_device_get_default_network(device);
569 struct connman_service *service = connman_service_lookup_from_network(network);
571 connman_dbus_dict_append_basic(iter, "Ifname",
572 DBUS_TYPE_STRING, &str);
574 val = connman_device_get_powered(device);
575 connman_dbus_dict_append_basic(iter, "Powered",
576 DBUS_TYPE_BOOLEAN, &val);
578 if (__connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV4) ||
579 __connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV6))
584 connman_dbus_dict_append_basic(iter, "Connected",
585 DBUS_TYPE_BOOLEAN, &val);
587 str = connman_device_get_string(device, "Address");
588 connman_dbus_dict_append_basic(iter, "MAC.Address",
589 DBUS_TYPE_STRING, &str);
594 static void append_properties(DBusMessageIter *iter,
595 struct connman_technology *technology)
597 DBusMessageIter dict;
601 connman_dbus_dict_open(iter, &dict);
603 str = get_name(technology->type);
605 connman_dbus_dict_append_basic(&dict, "Name",
606 DBUS_TYPE_STRING, &str);
608 str = __connman_service_type2string(technology->type);
610 connman_dbus_dict_append_basic(&dict, "Type",
611 DBUS_TYPE_STRING, &str);
613 __sync_synchronize();
614 val = technology->enabled;
615 connman_dbus_dict_append_basic(&dict, "Powered",
619 val = technology->connected;
620 connman_dbus_dict_append_basic(&dict, "Connected",
624 val = technology->tethering;
625 connman_dbus_dict_append_basic(&dict, "Tethering",
629 if (technology->tethering_ident)
630 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
632 &technology->tethering_ident);
634 if (technology->tethering_passphrase)
635 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
637 &technology->tethering_passphrase);
638 #if defined TIZEN_EXT
639 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI)
640 connman_dbus_dict_append_dict(&dict, "Device.List",
641 append_devices, technology);
643 connman_dbus_dict_close(iter, &dict);
646 static void technology_added_signal(struct connman_technology *technology)
649 DBusMessageIter iter;
651 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
652 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
656 dbus_message_iter_init_append(signal, &iter);
657 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
659 append_properties(&iter, technology);
661 dbus_connection_send(connection, signal, NULL);
662 dbus_message_unref(signal);
665 static void technology_removed_signal(struct connman_technology *technology)
667 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
668 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
669 DBUS_TYPE_OBJECT_PATH, &technology->path,
673 static DBusMessage *get_properties(DBusConnection *conn,
674 DBusMessage *message, void *user_data)
676 struct connman_technology *technology = user_data;
678 DBusMessageIter iter;
680 reply = dbus_message_new_method_return(message);
684 dbus_message_iter_init_append(reply, &iter);
685 append_properties(&iter, technology);
690 void __connman_technology_list_struct(DBusMessageIter *array)
693 DBusMessageIter entry;
695 for (list = technology_list; list; list = list->next) {
696 struct connman_technology *technology = list->data;
698 if (!technology->path ||
699 (technology->rfkill_driven &&
700 technology->hardblocked))
703 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
705 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
707 append_properties(&entry, technology);
708 dbus_message_iter_close_container(array, &entry);
712 static gboolean technology_pending_reply(gpointer user_data)
714 struct connman_technology *technology = user_data;
717 /* Power request timed out, send ETIMEDOUT. */
718 if (technology->pending_reply) {
719 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
721 g_dbus_send_message(connection, reply);
723 dbus_message_unref(technology->pending_reply);
724 technology->pending_reply = NULL;
725 technology->pending_timeout = 0;
731 static int technology_affect_devices(struct connman_technology *technology,
734 int err = 0, err_dev;
737 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
739 __connman_technology_enabled(technology->type);
741 __connman_technology_disabled(technology->type);
745 #if defined TIZEN_EXT_WIFI_MESH
746 if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
750 for (list = technology->device_list; list; list = list->next) {
751 struct connman_device *device = list->data;
754 err_dev = __connman_device_enable(device);
756 err_dev = __connman_device_disable(device);
758 if (err_dev < 0 && err_dev != -EALREADY)
765 static void powered_changed(struct connman_technology *technology)
769 if (!technology->dbus_registered)
772 if (technology->pending_reply) {
773 g_dbus_send_reply(connection,
774 technology->pending_reply, DBUS_TYPE_INVALID);
775 dbus_message_unref(technology->pending_reply);
776 technology->pending_reply = NULL;
778 g_source_remove(technology->pending_timeout);
779 technology->pending_timeout = 0;
782 __sync_synchronize();
783 enabled = technology->enabled;
784 #if defined TIZEN_EXT
785 DBG("ConnMan, Powered : %s, %s",
786 enabled ? "TRUE" : "FALSE",technology->path);
788 connman_dbus_property_changed_basic(technology->path,
789 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
790 DBUS_TYPE_BOOLEAN, &enabled);
793 static void enable_tethering(struct connman_technology *technology)
797 if (!connman_setting_get_bool("PersistentTetheringMode"))
800 ret = set_tethering(technology, true);
801 if (ret < 0 && ret != -EALREADY)
802 DBG("Cannot enable tethering yet for %s (%d/%s)",
803 get_name(technology->type),
804 -ret, strerror(-ret));
807 static int technology_enabled(struct connman_technology *technology)
809 __sync_synchronize();
810 if (technology->enabled)
813 technology->enabled = true;
815 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
816 struct connman_technology *p2p;
818 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
819 if (p2p && !p2p->enabled && p2p->enable_persistent)
820 technology_enabled(p2p);
823 if (technology->tethering_persistent)
824 enable_tethering(technology);
826 powered_changed(technology);
831 static int technology_enable(struct connman_technology *technology)
836 DBG("technology %p enable", technology);
838 __sync_synchronize();
840 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
841 struct connman_technology *wifi;
843 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
844 if (wifi && wifi->enabled)
845 return technology_enabled(technology);
849 if (technology->enabled)
852 if (technology->pending_reply)
855 if (connman_setting_get_bool("PersistentTetheringMode") &&
856 technology->tethering)
857 set_tethering(technology, true);
859 if (technology->rfkill_driven)
860 err = __connman_rfkill_block(technology->type, false);
862 err_dev = technology_affect_devices(technology, true);
864 if (!technology->rfkill_driven)
870 static int technology_disabled(struct connman_technology *technology)
872 __sync_synchronize();
873 if (!technology->enabled)
876 technology->enabled = false;
878 powered_changed(technology);
883 static int technology_disable(struct connman_technology *technology)
887 DBG("technology %p disable", technology);
889 __sync_synchronize();
891 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
892 technology->enable_persistent = false;
893 __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P);
894 __connman_peer_disconnect_all();
895 return technology_disabled(technology);
896 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
897 struct connman_technology *p2p;
899 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
900 if (p2p && p2p->enabled) {
901 p2p->enable_persistent = true;
902 technology_disabled(p2p);
906 if (!technology->enabled)
909 if (technology->pending_reply)
912 if (technology->tethering)
913 set_tethering(technology, false);
915 err = technology_affect_devices(technology, false);
917 if (technology->rfkill_driven)
918 err = __connman_rfkill_block(technology->type, true);
923 static DBusMessage *set_powered(struct connman_technology *technology,
924 DBusMessage *msg, bool powered)
926 DBusMessage *reply = NULL;
929 if (technology->rfkill_driven && technology->hardblocked) {
935 err = technology_enable(technology);
937 err = technology_disable(technology);
940 technology->enable_persistent = powered;
941 technology_save(technology);
945 if (err == -EINPROGRESS) {
946 technology->pending_reply = dbus_message_ref(msg);
947 technology->pending_timeout = g_timeout_add_seconds(10,
948 technology_pending_reply, technology);
949 } else if (err == -EALREADY) {
951 reply = __connman_error_already_enabled(msg);
953 reply = __connman_error_already_disabled(msg);
955 reply = __connman_error_failed(msg, -err);
957 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
962 #if defined TIZEN_EXT
963 int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname)
965 static int bssid_len;
966 static const char *def_ifname = "default";
967 static GSList *bssid_list = NULL;
969 const char *local_ifname = ifname;
971 struct connman_bssid_pending *bssid_info;
973 DBG("mode: %d, ifname: %s", mode, ifname);
976 local_ifname = def_ifname;
978 for (list = bssid_list; list; list = list->next) {
979 bssid_info = list->data;
981 if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) {
987 if (mode == CHECK_BSSID) {
994 if (mode == GET_BSSID && bssid) {
996 memcpy(bssid, bssid_info->bssid, 6);
1002 if (mode == RESET_BSSID) {
1004 bssid_list = g_slist_remove(bssid_list, bssid_info);
1005 g_free(bssid_info->ifname);
1011 if (mode != SET_BSSID || !bssid) {
1012 DBG("Invalid parameter");
1017 bssid_list = g_slist_remove(bssid_list, bssid_info);
1018 g_free(bssid_info->ifname);
1022 bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending));
1024 DBG("Failed to allocate memory");
1028 unsigned char *bssid_data = bssid_info->bssid;
1030 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1031 &bssid_data[0], &bssid_data[1], &bssid_data[2],
1032 &bssid_data[3], &bssid_data[4], &bssid_data[5]);
1033 if (bssid_len != 6) {
1034 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
1039 DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s",
1041 bssid_data[0], bssid_data[1], bssid_data[2],
1042 bssid_data[3], bssid_data[4], bssid_data[5],
1045 bssid_info->ifname = g_strdup(ifname);
1046 bssid_list = g_slist_prepend(bssid_list, bssid_info);
1052 static DBusMessage *set_property(DBusConnection *conn,
1053 DBusMessage *msg, void *data)
1055 struct connman_technology *technology = data;
1056 DBusMessageIter iter, value;
1060 DBG("conn %p", conn);
1062 if (!dbus_message_iter_init(msg, &iter))
1063 return __connman_error_invalid_arguments(msg);
1065 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1066 return __connman_error_invalid_arguments(msg);
1068 dbus_message_iter_get_basic(&iter, &name);
1069 dbus_message_iter_next(&iter);
1071 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1072 return __connman_error_invalid_arguments(msg);
1074 dbus_message_iter_recurse(&iter, &value);
1076 type = dbus_message_iter_get_arg_type(&value);
1078 DBG("property %s", name);
1080 if (g_str_equal(name, "Tethering")) {
1081 dbus_bool_t tethering;
1084 if (type != DBUS_TYPE_BOOLEAN)
1085 return __connman_error_invalid_arguments(msg);
1087 if (!connman_technology_is_tethering_allowed(technology->type)) {
1088 DBG("%s tethering not allowed by config file",
1089 __connman_service_type2string(technology->type));
1090 return __connman_error_not_supported(msg);
1093 dbus_message_iter_get_basic(&value, &tethering);
1095 if (technology->tethering == tethering) {
1097 return __connman_error_already_disabled(msg);
1099 return __connman_error_already_enabled(msg);
1102 err = set_tethering(technology, tethering);
1104 return __connman_error_failed(msg, -err);
1106 technology->tethering_persistent = tethering;
1108 technology_save(technology);
1110 } else if (g_str_equal(name, "TetheringIdentifier")) {
1113 dbus_message_iter_get_basic(&value, &str);
1115 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1116 return __connman_error_not_supported(msg);
1118 if (strlen(str) < 1 || strlen(str) > 32)
1119 return __connman_error_invalid_arguments(msg);
1121 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1122 g_free(technology->tethering_ident);
1123 technology->tethering_ident = g_strdup(str);
1124 technology_save(technology);
1126 connman_dbus_property_changed_basic(technology->path,
1127 CONNMAN_TECHNOLOGY_INTERFACE,
1128 "TetheringIdentifier",
1130 &technology->tethering_ident);
1132 } else if (g_str_equal(name, "TetheringPassphrase")) {
1135 dbus_message_iter_get_basic(&value, &str);
1137 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1138 return __connman_error_not_supported(msg);
1140 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1143 return __connman_error_passphrase_required(msg);
1145 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1146 g_free(technology->tethering_passphrase);
1147 technology->tethering_passphrase = g_strdup(str);
1148 technology_save(technology);
1150 connman_dbus_property_changed_basic(technology->path,
1151 CONNMAN_TECHNOLOGY_INTERFACE,
1152 "TetheringPassphrase",
1154 &technology->tethering_passphrase);
1156 } else if (g_str_equal(name, "Powered")) {
1159 if (type != DBUS_TYPE_BOOLEAN)
1160 return __connman_error_invalid_arguments(msg);
1162 dbus_message_iter_get_basic(&value, &enable);
1164 return set_powered(technology, msg, enable);
1165 #if defined TIZEN_EXT
1166 } else if (g_str_equal(name, "SetBSSID")) {
1169 if (type != DBUS_TYPE_STRING)
1170 return __connman_error_invalid_arguments(msg);
1172 dbus_message_iter_get_basic(&value, &key);
1173 DBG("BSSID %s", key);
1174 set_connman_bssid(SET_BSSID, key, NULL);
1177 return __connman_error_invalid_property(msg);
1179 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1182 static void reply_scan_pending(struct connman_technology *technology, int err)
1186 DBG("technology %p err %d", technology, err);
1188 while (technology->scan_pending) {
1189 #if defined TIZEN_EXT
1190 struct connman_scan_pending *pending_data = technology->scan_pending->data;
1191 DBusMessage *msg = pending_data->msg;
1193 DBusMessage *msg = technology->scan_pending->data;
1195 DBG("reply to %s", dbus_message_get_sender(msg));
1198 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1200 reply = __connman_error_failed(msg, -err);
1201 g_dbus_send_message(connection, reply);
1202 dbus_message_unref(msg);
1204 technology->scan_pending =
1205 g_slist_delete_link(technology->scan_pending,
1206 technology->scan_pending);
1207 #if defined TIZEN_EXT
1208 g_free(pending_data->ifname);
1209 g_free(pending_data);
1214 #if defined TIZEN_EXT
1215 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1218 DBusMessage *signal;
1219 DBusMessageIter iter;
1220 dbus_bool_t result = FALSE;
1222 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1223 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1227 dbus_message_iter_init_append(signal, &iter);
1229 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1231 connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val);
1233 result = dbus_connection_send(connection, signal, NULL);
1234 dbus_message_unref(signal);
1236 DBG("Successfuly sent signal");
1241 void __connman_technology_notify_scan_done(const char *ifname, int val)
1244 DBusMessage *signal;
1245 DBusMessageIter iter;
1247 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1248 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1252 dbus_message_iter_init_append(signal, &iter);
1254 connman_dbus_property_append_basic(&iter, ifname,
1255 DBUS_TYPE_INT32, &val);
1257 connman_dbus_property_append_basic(&iter, "",
1258 DBUS_TYPE_INT32, &val);
1260 dbus_connection_send(connection, signal, NULL);
1261 dbus_message_unref(signal);
1263 DBG("Successfuly sent ScanDone signal");
1266 static void reply_scan_pending_device(
1267 struct connman_technology *technology, const char *ifname, int count)
1271 dbus_bool_t status = 0;
1272 connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN;
1274 DBG("technology %p ifname %d count %d", technology, ifname, count);
1276 list = technology->scan_pending;
1279 struct connman_scan_pending *pending_data = list->data;
1280 DBusMessage *msg = pending_data->msg;
1283 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1284 scan_type = pending_data->scan_type;
1286 if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0)
1289 scan_type = pending_data->scan_type;
1291 DBG("reply to %s", dbus_message_get_sender(msg));
1292 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1294 g_dbus_send_message(connection, reply);
1295 dbus_message_unref(msg);
1297 technology->scan_pending =
1298 g_slist_remove(technology->scan_pending, pending_data);
1300 g_free(pending_data->ifname);
1301 g_free(pending_data);
1304 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1305 scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1307 __connman_technology_notify_scan_changed(ifname, &status);
1308 __connman_technology_notify_scan_done(ifname, scan_type);
1311 static void __connman_technology_notify_device_detected(
1312 struct connman_technology *technology, const char *ifname, bool val)
1315 DBusMessage *signal;
1316 DBusMessageIter iter;
1317 dbus_bool_t detected = val;
1322 signal = dbus_message_new_signal(technology->path,
1323 CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected");
1327 dbus_message_iter_init_append(signal, &iter);
1328 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname);
1329 dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected);
1331 dbus_connection_send(connection, signal, NULL);
1332 dbus_message_unref(signal);
1334 DBG("Successfuly sent DeviceDetected signal");
1338 void __connman_technology_scan_started(struct connman_device *device)
1340 DBG("device %p", device);
1341 #if defined TIZEN_EXT
1342 dbus_bool_t status = 1;
1343 const char *ifname = connman_device_get_string(device, "Interface");
1345 __connman_technology_notify_scan_changed(ifname, &status);
1349 void __connman_technology_scan_stopped(struct connman_device *device,
1350 enum connman_service_type type)
1353 struct connman_technology *technology;
1356 technology = technology_find(type);
1358 DBG("technology %p device %p", technology, device);
1363 for (list = technology->device_list; list; list = list->next) {
1364 struct connman_device *other_device = list->data;
1366 if (device == other_device)
1369 if (connman_device_get_scanning(other_device, type))
1373 #if defined TIZEN_EXT
1374 const char *ifname = connman_device_get_string(device, "Interface");
1375 reply_scan_pending_device(technology, ifname, count);
1380 reply_scan_pending(technology, 0);
1383 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1384 int result, const char *alpha2)
1386 bool regdom_set = false;
1387 struct connman_technology *technology;
1388 enum connman_service_type type;
1389 GSList *tech_drivers;
1391 type = __connman_device_get_service_type(device);
1392 technology = technology_find(type);
1399 for (tech_drivers = technology->driver_list;
1401 tech_drivers = g_slist_next(tech_drivers)) {
1402 struct connman_technology_driver *driver =
1405 if (driver->set_regdom) {
1406 driver->set_regdom(technology, alpha2);
1416 connman_technology_regdom_notify(technology, alpha2);
1419 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1421 struct connman_technology *technology = data;
1424 DBG("technology %p request from %s", technology,
1425 dbus_message_get_sender(msg));
1427 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1428 !technology->enabled)
1429 return __connman_error_permission_denied(msg);
1431 #if !defined TIZEN_EXT
1432 dbus_message_ref(msg);
1433 technology->scan_pending =
1434 g_slist_prepend(technology->scan_pending, msg);
1437 err = __connman_device_request_scan_full(technology->type);
1439 #if defined TIZEN_EXT
1440 return __connman_error_failed(msg, -err);
1442 reply_scan_pending(technology, err);
1445 #if defined TIZEN_EXT
1446 struct connman_scan_pending *pending_data =
1447 g_try_malloc0(sizeof(struct connman_scan_pending));
1449 return __connman_error_failed(msg, ENOMEM);
1451 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1452 DBG("scan_type %d", pending_data->scan_type);
1454 pending_data->msg = dbus_message_ref(msg);
1456 technology->scan_pending =
1457 g_slist_prepend(technology->scan_pending, pending_data);
1462 #if defined TIZEN_EXT
1463 static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data)
1465 struct connman_technology *technology = data;
1466 DBusMessageIter iter;
1470 DBG("technology %p request from %s", technology,
1471 dbus_message_get_sender(msg));
1473 if (!dbus_message_iter_init(msg, &iter))
1474 return __connman_error_invalid_arguments(msg);
1476 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1477 return __connman_error_invalid_arguments(msg);
1479 dbus_message_iter_get_basic(&iter, &ifname);
1480 DBG("Interface name %s", ifname);
1482 if (!ifname || strlen(ifname) == 0)
1483 return __connman_error_invalid_arguments(msg);
1485 err = connman_device_request_device_scan(technology->type, ifname, true);
1487 return __connman_error_failed(msg, -err);
1489 struct connman_scan_pending *pending_data =
1490 g_try_malloc0(sizeof(struct connman_scan_pending));
1492 return __connman_error_failed(msg, ENOMEM);
1494 pending_data->ifname = g_strdup(ifname);
1495 if (pending_data->ifname == NULL) {
1496 g_free(pending_data);
1497 return __connman_error_failed(msg, ENOMEM);
1500 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1501 DBG("scan_type %d", pending_data->scan_type);
1503 pending_data->msg = dbus_message_ref(msg);
1505 technology->scan_pending =
1506 g_slist_prepend(technology->scan_pending, pending_data);
1511 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1513 struct connman_technology *technology = data;
1514 GSList *specific_scan_list = NULL;
1516 const char *name = NULL;
1517 const char *freq = NULL;
1518 const char *ifname = NULL;
1519 DBusMessageIter iter, dict;
1522 DBG("technology %p request from %s", technology,
1523 dbus_message_get_sender(msg));
1525 if (!dbus_message_iter_init(msg, &iter))
1526 return __connman_error_invalid_arguments(msg);
1528 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1529 return __connman_error_invalid_arguments(msg);
1531 dbus_message_iter_recurse(&iter, &dict);
1532 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1533 DBusMessageIter entry, value2;
1537 dbus_message_iter_recurse(&dict, &entry);
1538 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1539 g_slist_free_full(specific_scan_list, g_free);
1540 return __connman_error_invalid_arguments(msg);
1543 dbus_message_iter_get_basic(&entry, &key);
1544 dbus_message_iter_next(&entry);
1546 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1547 g_slist_free_full(specific_scan_list, g_free);
1548 return __connman_error_invalid_arguments(msg);
1551 dbus_message_iter_recurse(&entry, &value2);
1552 type = dbus_message_iter_get_arg_type(&value2);
1553 if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) {
1555 dbus_message_iter_get_basic(&value2, &ifname);
1556 DBG("ifname %s", ifname);
1557 } else if (g_str_equal(key, "SSID")) {
1558 if (type != DBUS_TYPE_STRING) {
1559 g_slist_free_full(specific_scan_list, g_free);
1560 return __connman_error_invalid_arguments(msg);
1563 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1564 dbus_message_iter_get_basic(&value2, &name);
1565 DBG("name %s", name);
1566 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1567 } else if (g_str_equal(key, "Frequency")) {
1568 if (type != DBUS_TYPE_STRING) {
1569 g_slist_free_full(specific_scan_list, g_free);
1570 return __connman_error_invalid_arguments(msg);
1573 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1574 dbus_message_iter_get_basic(&value2, &freq);
1575 DBG("freq %s", freq);
1576 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1577 } else if (g_str_equal(key, "SSID_Mixed")) {
1578 if (type != DBUS_TYPE_STRING) {
1579 g_slist_free_full(specific_scan_list, g_free);
1580 return __connman_error_invalid_arguments(msg);
1583 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1584 dbus_message_iter_get_basic(&value2, &name);
1586 connman_multi_scan_ap_s *ap =
1587 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1589 g_strlcpy(ap->str, name, strlen(name) + 1);
1591 specific_scan_list = g_slist_append(specific_scan_list, ap);
1593 DBG("Failed to allocate memory");
1595 } else if (g_str_equal(key, "Frequency_Mixed")) {
1596 if (type != DBUS_TYPE_STRING) {
1597 g_slist_free_full(specific_scan_list, g_free);
1598 return __connman_error_invalid_arguments(msg);
1601 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1602 dbus_message_iter_get_basic(&value2, &freq);
1604 connman_multi_scan_ap_s *ap =
1605 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1607 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1609 specific_scan_list = g_slist_append(specific_scan_list, ap);
1611 DBG("Failed to allocate memory");
1613 dbus_message_iter_next(&dict);
1616 err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list);
1618 return __connman_error_failed(msg, -err);
1620 guint list_size = g_slist_length(specific_scan_list);
1622 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
1623 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ)
1624 g_slist_free_full(specific_scan_list, g_free);
1626 struct connman_scan_pending *pending_data =
1627 g_try_malloc0(sizeof(struct connman_scan_pending));
1629 return __connman_error_failed(msg, ENOMEM);
1632 pending_data->ifname = g_strdup(ifname);
1633 if (pending_data->ifname == NULL) {
1634 g_free(pending_data);
1635 return __connman_error_failed(msg, ENOMEM);
1640 pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1642 pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1643 DBG("list_size %u scan_type %d", list_size, pending_data->scan_type);
1645 pending_data->msg = dbus_message_ref(msg);
1647 technology->scan_pending =
1648 g_slist_prepend(technology->scan_pending, pending_data);
1653 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
1656 DBusMessageIter iter, dict;
1658 struct connman_technology *technology = data;
1659 dbus_bool_t supported = false;
1660 const char *ifname = NULL;
1662 DBG("technology %p", technology);
1664 reply = dbus_message_new_method_return(msg);
1668 dbus_message_iter_init_append(reply, &iter);
1669 connman_dbus_dict_open(&iter, &dict);
1671 for (list = technology->device_list; list; list = list->next) {
1672 struct connman_device *device = list->data;
1674 supported = connman_device_get_wifi_5ghz_supported(device);
1675 ifname = connman_device_get_string(device, "Interface");
1677 DBG("ifname %s supported : %d", ifname, supported);
1678 connman_dbus_dict_append_basic(&dict, ifname,
1683 connman_dbus_dict_close(&iter, &dict);
1688 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
1691 DBusMessageIter iter, dict;
1693 struct connman_technology *technology = data;
1694 dbus_bool_t scanning = false;
1695 const char *ifname = NULL;
1697 DBG("technology %p", technology);
1699 reply = dbus_message_new_method_return(msg);
1703 dbus_message_iter_init_append(reply, &iter);
1704 connman_dbus_dict_open(&iter, &dict);
1706 for (list = technology->device_list; list; list = list->next) {
1707 struct connman_device *device = list->data;
1709 scanning = connman_device_get_scanning(device, technology->type);
1710 ifname = connman_device_get_string(device, "Interface");
1712 DBG("ifname %s scanning : %d", ifname, scanning);
1713 connman_dbus_dict_append_basic(&dict, ifname,
1718 connman_dbus_dict_close(&iter, &dict);
1723 static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
1726 DBusMessageIter iter, dict;
1728 struct connman_technology *technology = data;
1729 dbus_int32_t max_scan_ssids = 0;
1730 const char *ifname = NULL;
1732 DBG("technology %p", technology);
1734 reply = dbus_message_new_method_return(msg);
1738 dbus_message_iter_init_append(reply, &iter);
1739 connman_dbus_dict_open(&iter, &dict);
1741 for (list = technology->device_list; list; list = list->next) {
1742 struct connman_device *device = list->data;
1744 max_scan_ssids = connman_device_get_max_scan_ssids(device);
1745 ifname = connman_device_get_string(device, "Interface");
1747 DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids);
1748 connman_dbus_dict_append_basic(&dict, ifname,
1753 connman_dbus_dict_close(&iter, &dict);
1758 static DBusMessage *get_interfaces(DBusConnection *conn, DBusMessage *msg, void *data)
1761 DBusMessageIter iter, array;
1763 struct connman_technology *technology = data;
1764 const char *default_interface = connman_option_get_string("DefaultWifiInterface");
1766 DBG("technology %p", technology);
1768 reply = dbus_message_new_method_return(msg);
1772 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1775 dbus_message_iter_init_append(reply, &iter);
1776 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1777 DBUS_TYPE_STRING_AS_STRING, &array);
1779 dbus_message_iter_append_basic(&array,
1780 DBUS_TYPE_STRING, &default_interface);
1782 for (list = technology->device_list; list; list = list->next) {
1783 struct connman_device *device = list->data;
1784 const char *str = connman_device_get_string(device, "Interface");
1786 if (g_strcmp0(default_interface, str) == 0)
1789 dbus_message_iter_append_basic(&array,
1790 DBUS_TYPE_STRING, &str);
1793 dbus_message_iter_close_container(&iter, &array);
1797 static int technology_enable_device(struct connman_technology *technology,
1798 bool enable_device, const char *ifname, struct connman_device **device_out)
1803 for (list = technology->device_list; list; list = list->next) {
1804 struct connman_device *device = list->data;
1805 const char *str = connman_device_get_string(device, "Interface");
1807 if (g_strcmp0(str, ifname) != 0)
1811 err = __connman_device_enable(device);
1813 err = __connman_device_disable(device);
1815 *device_out = device;
1822 static DBusMessage *technology_set_device_powered(struct connman_technology *technology,
1823 DBusMessage *msg, bool powered, const char *ifname)
1825 DBusMessage *reply = NULL;
1826 struct connman_device *device = NULL;
1829 err = technology_enable_device(technology, powered, ifname, &device);
1831 if (err == -EINPROGRESS) {
1833 connman_device_set_pending_reply(device, msg);
1835 } else if (err == -EALREADY) {
1837 reply = __connman_error_already_enabled(msg);
1839 reply = __connman_error_already_disabled(msg);
1841 reply = __connman_error_failed(msg, -err);
1843 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1848 static DBusMessage *set_device_power(DBusConnection *conn,
1849 DBusMessage *msg, void *data)
1851 struct connman_technology *technology = data;
1852 DBusMessageIter iter;
1857 DBG("conn %p", conn);
1859 if (!dbus_message_iter_init(msg, &iter))
1860 return __connman_error_invalid_arguments(msg);
1862 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1863 return __connman_error_invalid_arguments(msg);
1865 dbus_message_iter_get_basic(&iter, &name);
1866 dbus_message_iter_next(&iter);
1868 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
1869 return __connman_error_invalid_arguments(msg);
1871 DBG("interface name %s", name);
1875 if (len + 1 > IFNAMSIZ)
1876 return __connman_error_invalid_arguments(msg);
1878 dbus_message_iter_get_basic(&iter, &enable);
1879 DBG("powered %s", enable ? "TRUE" : "FALSE");
1881 return technology_set_device_powered(technology, msg, enable, name);
1884 static DBusMessage *set_bssid(DBusConnection *conn,
1885 DBusMessage *msg, void *data)
1887 DBusMessageIter iter;
1891 DBG("conn %p", conn);
1893 if (!dbus_message_iter_init(msg, &iter))
1894 return __connman_error_invalid_arguments(msg);
1896 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1897 return __connman_error_invalid_arguments(msg);
1899 dbus_message_iter_get_basic(&iter, &name);
1900 dbus_message_iter_next(&iter);
1902 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1903 return __connman_error_invalid_arguments(msg);
1905 dbus_message_iter_get_basic(&iter, &bssid);
1907 DBG("interface name %s bssid %s", name, bssid);
1911 if (len + 1 > IFNAMSIZ)
1912 return __connman_error_invalid_arguments(msg);
1914 set_connman_bssid(SET_BSSID, bssid, name);
1916 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1918 static struct connman_technology *technology_get(enum connman_service_type type);
1920 void technology_save_device(struct connman_device *device)
1922 struct connman_technology *technology;
1923 enum connman_service_type type;
1925 type = __connman_device_get_service_type(device);
1926 technology = technology_get(type);
1932 const char *name = get_name(technology->type);
1934 DBG("technology %p type %d name %s", technology, technology->type,
1939 keyfile = __connman_storage_load_global();
1941 keyfile = g_key_file_new();
1943 identifier = g_strdup_printf("%s", name);
1947 GSList *list = NULL;
1948 gchar **ifname_list = NULL;
1949 guint dev_count = g_slist_length(technology->device_list);
1951 if (dev_count > 1) {
1952 GString *ifname_str = g_string_new(NULL);
1955 for (list = technology->device_list; list; list = list->next) {
1956 struct connman_device *device = list->data;
1958 if (connman_device_get_powered(device)) {
1959 const char *ifname = connman_device_get_string(device, "Interface");
1961 if (ifname_str->len > 0)
1962 g_string_append_printf(ifname_str, " %s", ifname);
1964 g_string_append(ifname_str, ifname);
1968 if (ifname_str->len > 0) {
1969 ifname_list = g_strsplit_set(ifname_str->str, " ", 0);
1970 dev_count = g_strv_length(ifname_list);
1971 g_key_file_set_string_list(keyfile, identifier, "Enable.Devices",
1972 (const gchar **) ifname_list, dev_count);
1974 technology->enable_persistent = true;
1976 g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL);
1977 technology->enable_persistent = false;
1980 g_strfreev(ifname_list);
1981 g_string_free(ifname_str, TRUE);
1985 g_key_file_set_boolean(keyfile, identifier, "Enable",
1986 technology->enable_persistent);
1988 g_key_file_set_boolean(keyfile, identifier, "Tethering",
1989 technology->tethering_persistent);
1991 if (technology->tethering_ident)
1992 g_key_file_set_string(keyfile, identifier,
1993 "Tethering.Identifier",
1994 technology->tethering_ident);
1996 if (technology->tethering_passphrase)
1997 g_key_file_set_string(keyfile, identifier,
1998 "Tethering.Passphrase",
1999 technology->tethering_passphrase);
2004 __connman_storage_save_global(keyfile);
2006 g_key_file_free(keyfile);
2010 #if defined TIZEN_EXT_WIFI_MESH
2011 bool __connman_technology_get_connected(enum connman_service_type type)
2013 struct connman_technology *technology;
2015 technology = technology_find(type);
2020 return technology->connected;
2023 void __connman_technology_mesh_interface_create_finished(
2024 enum connman_service_type type, bool success,
2028 struct connman_technology *technology;
2030 technology = technology_find(type);
2032 DBG("technology %p success %d", technology, success);
2037 msg = technology->mesh_dbus_msg;
2039 DBG("No pending dbus message");
2044 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2045 __connman_device_request_scan(technology->type);
2047 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
2048 ".MeshInterfaceAddFailed", "%s", error);
2049 g_dbus_send_message(connection, reply);
2050 dbus_message_unref(msg);
2051 technology->mesh_dbus_msg = NULL;
2054 void __connman_technology_mesh_interface_remove_finished(
2055 enum connman_service_type type, bool success)
2058 struct connman_technology *technology;
2060 technology = technology_find(type);
2062 DBG("technology %p success %d", technology, success);
2064 if (!technology || !technology->mesh_dbus_msg)
2067 msg = technology->mesh_dbus_msg;
2069 DBG("No pending dbus message");
2074 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2076 reply = __connman_error_failed(msg, EINVAL);
2077 g_dbus_send_message(connection, reply);
2078 dbus_message_unref(msg);
2079 technology->mesh_dbus_msg = NULL;
2082 void __connman_technology_notify_abort_scan(enum connman_service_type type,
2086 struct connman_technology *technology;
2088 technology = technology_find(type);
2090 DBG("technology %p result %d", technology, result);
2092 if (!technology || !technology->mesh_dbus_msg)
2095 msg = technology->mesh_dbus_msg;
2097 DBG("No pending dbus message");
2102 reply = __connman_error_scan_abort_failed(msg);
2104 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2106 g_dbus_send_message(connection, reply);
2107 dbus_message_unref(msg);
2108 technology->mesh_dbus_msg = NULL;
2111 static DBusMessage *mesh_commands(DBusConnection *conn,
2112 DBusMessage *msg, void *data)
2114 struct connman_technology *technology = data;
2115 DBusMessageIter iter, value, dict;
2116 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
2119 DBG("conn %p", conn);
2121 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
2122 return __connman_error_invalid_arguments(msg);
2124 if (!dbus_message_iter_init(msg, &iter))
2125 return __connman_error_invalid_arguments(msg);
2127 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2128 return __connman_error_invalid_arguments(msg);
2130 dbus_message_iter_get_basic(&iter, &cmd);
2131 dbus_message_iter_next(&iter);
2133 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
2134 return __connman_error_invalid_arguments(msg);
2136 dbus_message_iter_recurse(&iter, &value);
2138 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
2139 return __connman_error_invalid_arguments(msg);
2141 DBG("Mesh Command %s", cmd);
2142 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
2143 dbus_message_iter_recurse(&value, &dict);
2144 const char *bridge_ifname = NULL;
2145 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2146 DBusMessageIter entry, value2;
2150 dbus_message_iter_recurse(&dict, &entry);
2152 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2153 return __connman_error_invalid_arguments(msg);
2155 dbus_message_iter_get_basic(&entry, &key);
2156 dbus_message_iter_next(&entry);
2158 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2159 return __connman_error_invalid_arguments(msg);
2161 dbus_message_iter_recurse(&entry, &value2);
2163 type = dbus_message_iter_get_arg_type(&value2);
2165 if (g_str_equal(key, "Ifname")) {
2166 if (type != DBUS_TYPE_STRING)
2167 return __connman_error_invalid_arguments(msg);
2169 dbus_message_iter_get_basic(&value2, &ifname);
2170 } else if (g_str_equal(key, "ParentIfname")) {
2171 if (type != DBUS_TYPE_STRING)
2172 return __connman_error_invalid_arguments(msg);
2174 dbus_message_iter_get_basic(&value2, &parent_ifname);
2175 } else if (g_str_equal(key, "BridgeIfname")) {
2176 if (type != DBUS_TYPE_STRING)
2177 return __connman_error_invalid_arguments(msg);
2179 dbus_message_iter_get_basic(&value2, &bridge_ifname);
2181 dbus_message_iter_next(&dict);
2183 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
2184 bridge_ifname ? bridge_ifname : "NULL");
2185 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
2189 DBG("Failed to add virtual mesh interface");
2190 return __connman_error_failed(msg, -err);
2193 DBG("Successfully added virtual mesh interface");
2195 dbus_message_ref(msg);
2196 technology->mesh_dbus_msg = msg;
2198 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
2199 dbus_message_iter_recurse(&value, &dict);
2200 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2201 DBusMessageIter entry, value2;
2205 dbus_message_iter_recurse(&dict, &entry);
2207 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2208 return __connman_error_invalid_arguments(msg);
2210 dbus_message_iter_get_basic(&entry, &key);
2211 dbus_message_iter_next(&entry);
2213 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2214 return __connman_error_invalid_arguments(msg);
2216 dbus_message_iter_recurse(&entry, &value2);
2218 type = dbus_message_iter_get_arg_type(&value2);
2220 if (g_str_equal(key, "Ifname")) {
2221 if (type != DBUS_TYPE_STRING)
2222 return __connman_error_invalid_arguments(msg);
2224 dbus_message_iter_get_basic(&value2, &ifname);
2226 dbus_message_iter_next(&dict);
2228 DBG("Mesh Ifname %s", ifname);
2229 err = __connman_mesh_remove_virtual_interface(ifname);
2232 DBG("Failed to remove virtual mesh interface");
2233 return __connman_error_failed(msg, -err);
2236 DBG("Successfully removed virtual mesh interface");
2238 dbus_message_ref(msg);
2239 technology->mesh_dbus_msg = msg;
2241 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
2242 struct connman_mesh *connman_mesh;
2243 const char *name = NULL;
2244 const char *sec_type = NULL;
2245 const char *mesh_ifname = NULL;
2246 char *identifier, *group, *address;
2247 unsigned int freq = 0;
2248 unsigned int ieee80211w = 0;
2251 dbus_message_iter_recurse(&value, &dict);
2252 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2253 DBusMessageIter entry, value2;
2257 dbus_message_iter_recurse(&dict, &entry);
2259 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2260 return __connman_error_invalid_arguments(msg);
2262 dbus_message_iter_get_basic(&entry, &key);
2263 dbus_message_iter_next(&entry);
2265 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2266 return __connman_error_invalid_arguments(msg);
2268 dbus_message_iter_recurse(&entry, &value2);
2270 type = dbus_message_iter_get_arg_type(&value2);
2272 if (g_str_equal(key, "Name")) {
2273 if (type != DBUS_TYPE_STRING)
2274 return __connman_error_invalid_arguments(msg);
2276 dbus_message_iter_get_basic(&value2, &name);
2277 } else if (g_str_equal(key, "Frequency")) {
2278 if (type != DBUS_TYPE_UINT16)
2279 return __connman_error_invalid_arguments(msg);
2281 dbus_message_iter_get_basic(&value2, &freq);
2282 } else if (g_str_equal(key, "Security")) {
2283 if (type != DBUS_TYPE_STRING)
2284 return __connman_error_invalid_arguments(msg);
2286 dbus_message_iter_get_basic(&value2, &sec_type);
2287 } else if (g_str_equal(key, "Pmf")) {
2288 if (type != DBUS_TYPE_UINT16)
2289 return __connman_error_invalid_arguments(msg);
2291 dbus_message_iter_get_basic(&value2, &ieee80211w);
2293 dbus_message_iter_next(&dict);
2296 if (name == NULL || sec_type == NULL || freq == 0)
2297 return __connman_error_invalid_arguments(msg);
2299 DBG("Name %s Frequency %d Security type %s Pmf %u",
2300 name, freq, sec_type, ieee80211w);
2302 if (g_strcmp0(sec_type, "none") != 0 &&
2303 g_strcmp0(sec_type, "sae") != 0) {
2304 DBG("Unsupported security");
2305 return __connman_error_invalid_arguments(msg);
2308 mesh_ifname = connman_mesh_get_interface_name();
2310 if (!connman_mesh_is_interface_created()) {
2311 DBG("Mesh interface doesn't exists");
2312 return __connman_error_invalid_command(msg);
2315 str = g_string_sized_new((strlen(name) * 2) + 24);
2317 for (i = 0; name[i]; i++)
2318 g_string_append_printf(str, "%02x", name[i]);
2320 g_string_append_printf(str, "_mesh");
2322 if (g_strcmp0(sec_type, "none") == 0)
2323 g_string_append_printf(str, "_none");
2324 else if (g_strcmp0(sec_type, "sae") == 0)
2325 g_string_append_printf(str, "_sae");
2327 group = g_string_free(str, FALSE);
2329 identifier = connman_inet_ifaddr(mesh_ifname);
2330 address = connman_inet_ifname2addr(mesh_ifname);
2332 connman_mesh = connman_mesh_create(identifier, group);
2333 connman_mesh_set_name(connman_mesh, name);
2334 connman_mesh_set_address(connman_mesh, address);
2335 connman_mesh_set_security(connman_mesh, sec_type);
2336 connman_mesh_set_frequency(connman_mesh, freq);
2337 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
2338 connman_mesh_set_peer_type(connman_mesh,
2339 CONNMAN_MESH_PEER_TYPE_CREATED);
2340 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
2342 connman_mesh_register(connman_mesh);
2346 DBG("Successfully Created Mesh Network");
2347 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2349 } else if (g_str_equal(cmd, "AbortScan")) {
2350 DBG("Abort Scan method");
2351 err = __connman_device_abort_scan(technology->type);
2353 DBG("Failed to abort scan");
2354 return __connman_error_failed(msg, -err);
2357 DBG("Successfully requested to abort scan");
2358 dbus_message_ref(msg);
2359 technology->mesh_dbus_msg = msg;
2361 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
2362 const char *name = NULL;
2363 unsigned int freq = 0;
2364 dbus_message_iter_recurse(&value, &dict);
2365 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2366 DBusMessageIter entry, value2;
2370 dbus_message_iter_recurse(&dict, &entry);
2372 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2373 return __connman_error_invalid_arguments(msg);
2375 dbus_message_iter_get_basic(&entry, &key);
2376 dbus_message_iter_next(&entry);
2378 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2379 return __connman_error_invalid_arguments(msg);
2381 dbus_message_iter_recurse(&entry, &value2);
2383 type = dbus_message_iter_get_arg_type(&value2);
2385 if (g_str_equal(key, "Name")) {
2386 if (type != DBUS_TYPE_STRING)
2387 return __connman_error_invalid_arguments(msg);
2389 dbus_message_iter_get_basic(&value2, &name);
2390 } else if (g_str_equal(key, "Frequency")) {
2391 if (type != DBUS_TYPE_UINT16)
2392 return __connman_error_invalid_arguments(msg);
2394 dbus_message_iter_get_basic(&value2, &freq);
2396 dbus_message_iter_next(&dict);
2399 DBG("MeshID %s Frequency %d sender %s", name, freq,
2400 dbus_message_get_sender(msg));
2402 struct connman_scan_pending *pending_data =
2403 g_try_malloc0(sizeof(struct connman_scan_pending));
2405 return __connman_error_failed(msg, ENOMEM);
2407 pending_data->msg = dbus_message_ref(msg);
2409 technology->scan_pending =
2410 g_slist_prepend(technology->scan_pending, pending_data);
2412 err = __connman_device_request_mesh_specific_scan(technology->type,
2415 reply_scan_pending(technology, err);
2417 DBG("Successfully requested to scan specific Mesh Network");
2419 } else if (g_str_equal(cmd, "SetMeshGate")) {
2420 unsigned int hwmp_rootmode = 0;
2421 bool gate_announce = false;
2422 unsigned int stp = 0;
2424 dbus_message_iter_recurse(&value, &dict);
2425 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2426 DBusMessageIter entry, value2;
2430 dbus_message_iter_recurse(&dict, &entry);
2432 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2433 return __connman_error_invalid_arguments(msg);
2435 dbus_message_iter_get_basic(&entry, &key);
2436 dbus_message_iter_next(&entry);
2438 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2439 return __connman_error_invalid_arguments(msg);
2441 dbus_message_iter_recurse(&entry, &value2);
2443 type = dbus_message_iter_get_arg_type(&value2);
2445 if (g_str_equal(key, "GateAnnounce")) {
2446 if (type != DBUS_TYPE_BOOLEAN)
2447 return __connman_error_invalid_arguments(msg);
2449 dbus_message_iter_get_basic(&value2, &gate_announce);
2450 } else if (g_str_equal(key, "HWMPRootMode")) {
2451 if (type != DBUS_TYPE_UINT16)
2452 return __connman_error_invalid_arguments(msg);
2454 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
2455 } else if (g_str_equal(key, "STP")) {
2456 if (type != DBUS_TYPE_UINT16)
2457 return __connman_error_invalid_arguments(msg);
2459 dbus_message_iter_get_basic(&value2, &stp);
2461 dbus_message_iter_next(&dict);
2464 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
2465 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
2467 err = __connman_mesh_set_stp_gate_announce(gate_announce,
2472 return __connman_error_failed(msg, -err);
2474 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2476 return __connman_error_invalid_command(msg);
2481 static const GDBusMethodTable technology_methods[] = {
2482 { GDBUS_DEPRECATED_METHOD("GetProperties",
2483 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
2485 { GDBUS_ASYNC_METHOD("SetProperty",
2486 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2487 NULL, set_property) },
2488 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
2489 #if defined TIZEN_EXT
2490 { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }),
2491 NULL, scan_device) },
2492 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
2493 NULL, specific_scan) },
2494 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
2496 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
2497 get_5ghz_supported) },
2498 { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
2499 get_max_scan_ssid) },
2500 { GDBUS_METHOD("GetInterfaces", NULL, GDBUS_ARGS({ "interface_list", "as" }),
2502 { GDBUS_ASYNC_METHOD("SetDevicePower",
2503 GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }),
2504 NULL, set_device_power) },
2505 { GDBUS_ASYNC_METHOD("SetBSSID",
2506 GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }),
2509 #if defined TIZEN_EXT_WIFI_MESH
2510 { GDBUS_ASYNC_METHOD("MeshCommands",
2511 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2512 NULL, mesh_commands) },
2517 static const GDBusSignalTable technology_signals[] = {
2518 { GDBUS_SIGNAL("PropertyChanged",
2519 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
2520 #if defined TIZEN_EXT
2521 { GDBUS_SIGNAL("DeviceChanged",
2522 GDBUS_ARGS({ "device_property", "a{sv}" })) },
2523 { GDBUS_SIGNAL("DeviceDetected",
2524 GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) },
2529 static bool technology_dbus_register(struct connman_technology *technology)
2531 if (technology->dbus_registered ||
2532 (technology->rfkill_driven &&
2533 technology->hardblocked))
2536 if (!g_dbus_register_interface(connection, technology->path,
2537 CONNMAN_TECHNOLOGY_INTERFACE,
2538 technology_methods, technology_signals,
2539 NULL, technology, NULL)) {
2540 connman_error("Failed to register %s", technology->path);
2544 technology_added_signal(technology);
2545 technology->dbus_registered = true;
2550 static void technology_dbus_unregister(struct connman_technology *technology)
2552 if (!technology->dbus_registered)
2555 technology_removed_signal(technology);
2556 g_dbus_unregister_interface(connection, technology->path,
2557 CONNMAN_TECHNOLOGY_INTERFACE);
2559 technology->dbus_registered = false;
2562 static void technology_put(struct connman_technology *technology)
2564 DBG("technology %p", technology);
2566 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
2569 reply_scan_pending(technology, -EINTR);
2571 while (technology->driver_list) {
2572 struct connman_technology_driver *driver;
2574 driver = technology->driver_list->data;
2577 driver->remove(technology);
2579 technology->driver_list =
2580 g_slist_delete_link(technology->driver_list,
2581 technology->driver_list);
2584 technology_list = g_slist_remove(technology_list, technology);
2586 technology_dbus_unregister(technology);
2588 g_slist_free(technology->device_list);
2590 if (technology->pending_reply) {
2591 dbus_message_unref(technology->pending_reply);
2592 technology->pending_reply = NULL;
2593 g_source_remove(technology->pending_timeout);
2594 technology->pending_timeout = 0;
2597 g_strfreev(technology->enabled_devices);
2599 g_free(technology->path);
2600 g_free(technology->regdom);
2601 g_free(technology->tethering_ident);
2602 g_free(technology->tethering_passphrase);
2606 static struct connman_technology *technology_get(enum connman_service_type type)
2608 GSList *tech_drivers = NULL;
2609 struct connman_technology_driver *driver;
2610 struct connman_technology *technology;
2614 DBG("type %d", type);
2616 str = __connman_service_type2string(type);
2620 technology = technology_find(type);
2622 #if defined TIZEN_EXT_WIFI_MESH
2623 if (type != CONNMAN_SERVICE_TYPE_P2P &&
2624 type != CONNMAN_SERVICE_TYPE_MESH)
2626 if (type != CONNMAN_SERVICE_TYPE_P2P)
2628 __sync_fetch_and_add(&technology->refcount, 1);
2632 /* First check if we have a driver for this technology type */
2633 for (list = driver_list; list; list = list->next) {
2634 driver = list->data;
2636 if (driver->type == type) {
2637 DBG("technology %p driver %p", technology, driver);
2638 tech_drivers = g_slist_append(tech_drivers, driver);
2642 if (!tech_drivers) {
2643 DBG("No matching drivers found for %s.",
2644 __connman_service_type2string(type));
2648 technology = g_try_new0(struct connman_technology, 1);
2652 technology->refcount = 1;
2653 technology->type = type;
2654 technology->path = g_strdup_printf("%s/technology/%s",
2657 #if defined TIZEN_EXT_WIFI_MESH
2658 if (type == CONNMAN_SERVICE_TYPE_MESH) {
2659 struct connman_technology *wifi;
2661 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2663 technology->enabled = wifi->enabled;
2667 technology_load(technology);
2668 technology_list = g_slist_prepend(technology_list, technology);
2669 technology->driver_list = tech_drivers;
2671 for (list = tech_drivers; list; list = list->next) {
2672 driver = list->data;
2674 if (driver->probe && driver->probe(technology) < 0)
2675 DBG("Driver probe failed for technology %p",
2679 if (!technology_dbus_register(technology)) {
2680 technology_put(technology);
2684 if (type == CONNMAN_SERVICE_TYPE_P2P) {
2685 struct connman_technology *wifi;
2688 enable = technology->enable_persistent;
2690 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2692 enable = wifi->enabled;
2694 technology_affect_devices(technology, enable);
2697 DBG("technology %p %s", technology, get_name(technology->type));
2702 int connman_technology_driver_register(struct connman_technology_driver *driver)
2705 struct connman_device *device;
2706 enum connman_service_type type;
2708 for (list = driver_list; list; list = list->next) {
2709 if (list->data == driver)
2713 DBG("Registering %s driver", driver->name);
2715 driver_list = g_slist_insert_sorted(driver_list, driver,
2719 * Check for technology less devices if this driver
2720 * can service any of them.
2722 for (list = techless_device_list; list; list = list->next) {
2723 device = list->data;
2725 type = __connman_device_get_service_type(device);
2726 if (type != driver->type)
2729 techless_device_list = g_slist_remove(techless_device_list,
2732 __connman_technology_add_device(device);
2735 /* Check for orphaned rfkill switches. */
2736 g_hash_table_foreach(rfkill_list, rfkill_check,
2737 GINT_TO_POINTER(driver->type));
2740 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
2741 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
2745 #if defined TIZEN_EXT_WIFI_MESH
2746 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
2747 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
2755 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
2757 GSList *list, *tech_drivers;
2758 struct connman_technology *technology;
2759 struct connman_technology_driver *current;
2761 DBG("Unregistering driver %p name %s", driver, driver->name);
2763 for (list = technology_list; list; list = list->next) {
2764 technology = list->data;
2766 for (tech_drivers = technology->driver_list; tech_drivers;
2767 tech_drivers = g_slist_next(tech_drivers)) {
2768 current = tech_drivers->data;
2769 if (driver != current)
2773 driver->remove(technology);
2775 technology->driver_list =
2776 g_slist_remove(technology->driver_list,
2782 driver_list = g_slist_remove(driver_list, driver);
2784 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
2785 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
2787 technology_put(technology);
2789 #if defined TIZEN_EXT_WIFI_MESH
2790 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
2791 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
2793 technology_put(technology);
2798 void __connman_technology_add_interface(enum connman_service_type type,
2799 int index, const char *ident)
2801 struct connman_technology *technology;
2802 GSList *tech_drivers;
2803 struct connman_technology_driver *driver;
2807 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2808 case CONNMAN_SERVICE_TYPE_SYSTEM:
2810 case CONNMAN_SERVICE_TYPE_ETHERNET:
2811 case CONNMAN_SERVICE_TYPE_WIFI:
2812 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2813 case CONNMAN_SERVICE_TYPE_CELLULAR:
2814 case CONNMAN_SERVICE_TYPE_GPS:
2815 case CONNMAN_SERVICE_TYPE_VPN:
2816 case CONNMAN_SERVICE_TYPE_GADGET:
2817 case CONNMAN_SERVICE_TYPE_P2P:
2818 #if defined TIZEN_EXT_WIFI_MESH
2819 case CONNMAN_SERVICE_TYPE_MESH:
2824 name = connman_inet_ifname(index);
2825 connman_info("Adding interface %s [ %s ]", name,
2826 __connman_service_type2string(type));
2828 technology = technology_find(type);
2833 for (tech_drivers = technology->driver_list; tech_drivers;
2834 tech_drivers = g_slist_next(tech_drivers)) {
2835 driver = tech_drivers->data;
2837 if (driver->add_interface)
2838 driver->add_interface(technology, index, name, ident);
2842 * At this point we can try to enable tethering automatically as
2843 * now the interfaces are set properly.
2845 if (technology->tethering_persistent)
2846 enable_tethering(technology);
2852 void __connman_technology_remove_interface(enum connman_service_type type,
2853 int index, const char *ident)
2855 struct connman_technology *technology;
2856 GSList *tech_drivers;
2857 struct connman_technology_driver *driver;
2861 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2862 case CONNMAN_SERVICE_TYPE_SYSTEM:
2864 case CONNMAN_SERVICE_TYPE_ETHERNET:
2865 case CONNMAN_SERVICE_TYPE_WIFI:
2866 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2867 case CONNMAN_SERVICE_TYPE_CELLULAR:
2868 case CONNMAN_SERVICE_TYPE_GPS:
2869 case CONNMAN_SERVICE_TYPE_VPN:
2870 case CONNMAN_SERVICE_TYPE_GADGET:
2871 case CONNMAN_SERVICE_TYPE_P2P:
2872 #if defined TIZEN_EXT_WIFI_MESH
2873 case CONNMAN_SERVICE_TYPE_MESH:
2878 name = connman_inet_ifname(index);
2879 connman_info("Remove interface %s [ %s ]", name,
2880 __connman_service_type2string(type));
2883 technology = technology_find(type);
2888 for (tech_drivers = technology->driver_list; tech_drivers;
2889 tech_drivers = g_slist_next(tech_drivers)) {
2890 driver = tech_drivers->data;
2892 if (driver->remove_interface)
2893 driver->remove_interface(technology, index);
2897 int __connman_technology_add_device(struct connman_device *device)
2899 struct connman_technology *technology;
2900 enum connman_service_type type;
2902 type = __connman_device_get_service_type(device);
2904 DBG("device %p type %s", device, get_name(type));
2906 technology = technology_get(type);
2909 * Since no driver can be found for this device at the moment we
2910 * add it to the techless device list.
2912 techless_device_list = g_slist_prepend(techless_device_list,
2918 __sync_synchronize();
2919 if (technology->rfkill_driven) {
2920 if (technology->enabled)
2921 __connman_device_enable(device);
2923 __connman_device_disable(device);
2928 if (technology->enable_persistent &&
2929 !global_offlinemode) {
2930 #if defined TIZEN_EXT
2933 if (technology->enabled_devices) {
2936 const char *ifname = connman_device_get_string(device, "Interface");
2938 while (technology->enabled_devices[i]) {
2939 if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) {
2948 err = __connman_device_enable(device);
2950 int err = __connman_device_enable(device);
2953 * connman_technology_add_device() calls __connman_device_enable()
2954 * but since the device is already enabled, the call does not
2955 * propagate through to connman_technology_enabled via
2956 * connman_device_set_powered.
2958 if (err == -EALREADY)
2959 __connman_technology_enabled(type);
2961 /* if technology persistent state is offline */
2962 if (!technology->enable_persistent)
2963 __connman_device_disable(device);
2966 technology->device_list = g_slist_prepend(technology->device_list,
2969 #if defined TIZEN_EXT
2970 const char *ifname = connman_device_get_string(device, "Interface");
2971 __connman_technology_notify_device_detected(technology, ifname, true);
2976 int __connman_technology_remove_device(struct connman_device *device)
2978 struct connman_technology *technology;
2979 enum connman_service_type type;
2981 DBG("device %p", device);
2983 type = __connman_device_get_service_type(device);
2985 technology = technology_find(type);
2987 techless_device_list = g_slist_remove(techless_device_list,
2992 technology->device_list = g_slist_remove(technology->device_list,
2995 #if defined TIZEN_EXT
2996 const char *ifname = connman_device_get_string(device, "Interface");
2997 __connman_technology_notify_device_detected(technology, ifname, false);
3000 if (technology->tethering)
3001 set_tethering(technology, false);
3003 technology_put(technology);
3008 int __connman_technology_enabled(enum connman_service_type type)
3010 struct connman_technology *technology;
3012 technology = technology_find(type);
3016 DBG("technology %p type %s rfkill %d enabled %d", technology,
3017 get_name(type), technology->rfkill_driven,
3018 technology->enabled);
3020 #if !defined TIZEN_EXT
3021 if (technology->rfkill_driven) {
3022 if (technology->tethering_persistent)
3023 enable_tethering(technology);
3028 return technology_enabled(technology);
3031 int __connman_technology_disabled(enum connman_service_type type)
3033 struct connman_technology *technology;
3036 technology = technology_find(type);
3040 #if !defined TIZEN_EXT
3041 if (technology->rfkill_driven)
3045 for (list = technology->device_list; list; list = list->next) {
3046 struct connman_device *device = list->data;
3048 if (connman_device_get_powered(device))
3052 return technology_disabled(technology);
3055 int __connman_technology_set_offlinemode(bool offlinemode)
3058 int err = -EINVAL, enabled_tech_count = 0;
3060 if (global_offlinemode == offlinemode)
3063 DBG("offlinemode %s", offlinemode ? "On" : "Off");
3066 * This is a bit tricky. When you set offlinemode, there is no
3067 * way to differentiate between attempting offline mode and
3068 * resuming offlinemode from last saved profile. We need that
3069 * information in rfkill_update, otherwise it falls back on the
3070 * technology's persistent state. Hence we set the offline mode here
3071 * but save it & call the notifier only if it is successful.
3074 global_offlinemode = offlinemode;
3076 /* Traverse technology list, enable/disable each technology. */
3077 for (list = technology_list; list; list = list->next) {
3078 struct connman_technology *technology = list->data;
3081 err = technology_disable(technology);
3083 if (technology->hardblocked)
3086 if (technology->enable_persistent) {
3087 err = technology_enable(technology);
3088 enabled_tech_count++;
3093 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
3094 (err == -EINVAL && enabled_tech_count == 0)) {
3095 connman_technology_save_offlinemode();
3096 __connman_notifier_offlinemode(offlinemode);
3098 global_offlinemode = connman_technology_load_offlinemode();
3103 #if defined TIZEN_EXT_WIFI_MESH
3104 static gboolean __add_ethernet_to_bridge(gpointer data)
3107 __connman_mesh_add_ethernet_to_bridge();
3112 void __connman_technology_set_connected(enum connman_service_type type,
3115 struct connman_technology *technology;
3118 technology = technology_find(type);
3122 DBG("technology %p connected %d", technology, connected);
3124 technology->connected = connected;
3126 #if defined TIZEN_EXT_WIFI_MESH
3127 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
3128 g_idle_add(__add_ethernet_to_bridge, NULL);
3132 connman_dbus_property_changed_basic(technology->path,
3133 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
3134 DBUS_TYPE_BOOLEAN, &val);
3137 static bool technology_apply_rfkill_change(struct connman_technology *technology,
3142 bool hardblock_changed = false;
3144 GList *start, *list;
3146 DBG("technology %p --> %d/%d vs %d/%d",
3147 technology, softblock, hardblock,
3148 technology->softblocked, technology->hardblocked);
3150 if (technology->hardblocked == hardblock)
3151 goto softblock_change;
3153 if (!(new_rfkill && !hardblock)) {
3154 start = g_hash_table_get_values(rfkill_list);
3156 for (list = start; list; list = list->next) {
3157 struct connman_rfkill *rfkill = list->data;
3159 if (rfkill->type != technology->type)
3162 if (rfkill->hardblock != hardblock)
3170 goto softblock_change;
3172 technology->hardblocked = hardblock;
3173 hardblock_changed = true;
3176 if (!apply && technology->softblocked != softblock)
3180 return technology->hardblocked;
3182 technology->softblocked = softblock;
3184 if (technology->hardblocked ||
3185 technology->softblocked) {
3186 if (technology_disabled(technology) != -EALREADY)
3187 technology_affect_devices(technology, false);
3188 } else if (!technology->hardblocked &&
3189 !technology->softblocked) {
3190 if (technology_enabled(technology) != -EALREADY)
3191 technology_affect_devices(technology, true);
3194 if (hardblock_changed) {
3195 if (technology->hardblocked) {
3196 DBG("%s is switched off.", get_name(technology->type));
3197 technology_dbus_unregister(technology);
3199 DBG("%s is switched on.", get_name(technology->type));
3200 technology_dbus_register(technology);
3202 if (global_offlinemode)
3203 __connman_rfkill_block(technology->type, true);
3207 return technology->hardblocked;
3210 int __connman_technology_add_rfkill(unsigned int index,
3211 enum connman_service_type type,
3215 struct connman_technology *technology;
3216 struct connman_rfkill *rfkill;
3218 DBG("index %u type %d soft %u hard %u", index, type,
3219 softblock, hardblock);
3221 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3225 rfkill = g_try_new0(struct connman_rfkill, 1);
3229 rfkill->index = index;
3230 rfkill->type = type;
3231 rfkill->softblock = softblock;
3232 rfkill->hardblock = hardblock;
3234 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
3237 #if defined TIZEN_EXT
3238 /* Fix Svace Issue [WGID: 1348]. */
3241 technology = technology_get(type);
3242 /* If there is no driver for this type, ignore it. */
3246 technology->rfkill_driven = true;
3248 #if !defined TIZEN_EXT
3249 /* If hardblocked, there is no need to handle softblocked state */
3250 if (technology_apply_rfkill_change(technology,
3251 softblock, hardblock, true))
3255 if (global_offlinemode)
3259 * Depending on softblocked state we unblock/block according to
3260 * offlinemode and persistente state.
3262 if (technology->softblocked &&
3263 technology->enable_persistent)
3264 return __connman_rfkill_block(type, false);
3265 else if (!technology->softblocked &&
3266 !technology->enable_persistent)
3267 return __connman_rfkill_block(type, true);
3272 int __connman_technology_update_rfkill(unsigned int index,
3273 enum connman_service_type type,
3277 struct connman_technology *technology;
3278 struct connman_rfkill *rfkill;
3280 DBG("index %u soft %u hard %u", index, softblock, hardblock);
3282 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3286 if (rfkill->softblock == softblock &&
3287 rfkill->hardblock == hardblock)
3290 rfkill->softblock = softblock;
3291 rfkill->hardblock = hardblock;
3293 technology = technology_find(type);
3294 /* If there is no driver for this type, ignore it. */
3298 technology_apply_rfkill_change(technology, softblock, hardblock,
3301 if (technology->hardblocked)
3302 DBG("%s hardblocked", get_name(technology->type));
3304 DBG("%s is%s softblocked", get_name(technology->type),
3305 technology->softblocked ? "" : " not");
3310 int __connman_technology_remove_rfkill(unsigned int index,
3311 enum connman_service_type type)
3313 struct connman_technology *technology;
3314 struct connman_rfkill *rfkill;
3316 DBG("index %u", index);
3318 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3322 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
3324 technology = technology_find(type);
3328 technology_apply_rfkill_change(technology,
3329 technology->softblocked, !technology->hardblocked, false);
3331 technology_put(technology);
3336 int __connman_technology_init(void)
3340 connection = connman_dbus_get_connection();
3342 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3345 global_offlinemode = connman_technology_load_offlinemode();
3347 /* This will create settings file if it is missing */
3348 connman_technology_save_offlinemode();
3353 void __connman_technology_cleanup(void)
3357 while (technology_list) {
3358 struct connman_technology *technology = technology_list->data;
3359 technology_list = g_slist_remove(technology_list, technology);
3360 technology_put(technology);
3363 g_hash_table_destroy(rfkill_list);
3365 dbus_connection_unref(connection);