5 * Copyright (C) 2007-2014 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
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <linux/if_arp.h>
34 #include <linux/wireless.h>
35 #include <net/ethernet.h>
38 #define IFF_LOWER_UP 0x10000
41 #include <dbus/dbus.h>
44 #define CONNMAN_API_SUBJECT_TO_CHANGE
45 #include <connman/plugin.h>
46 #include <connman/inet.h>
47 #include <connman/device.h>
48 #include <connman/rtnl.h>
49 #include <connman/technology.h>
50 #include <connman/service.h>
51 #include <connman/peer.h>
52 #include <connman/log.h>
53 #include <connman/option.h>
54 #include <connman/storage.h>
55 #include <include/setting.h>
56 #include <connman/provision.h>
57 #include <connman/utsname.h>
58 #include <connman/machine.h>
60 #include <gsupplicant/gsupplicant.h>
62 #define CLEANUP_TIMEOUT 8 /* in seconds */
63 #define INACTIVE_TIMEOUT 12 /* in seconds */
64 #define FAVORITE_MAXIMUM_RETRIES 2
66 #define BGSCAN_DEFAULT "simple:30:-45:300"
67 #define AUTOSCAN_DEFAULT "exponential:3:300"
69 #define P2P_FIND_TIMEOUT 30
70 #define P2P_CONNECTION_TIMEOUT 100
71 #define P2P_LISTEN_PERIOD 500
72 #define P2P_LISTEN_INTERVAL 2000
75 static struct connman_technology *wifi_technology = NULL;
76 static struct connman_technology *p2p_technology = NULL;
78 struct hidden_params {
80 unsigned int ssid_len;
84 GSupplicantScanParams *scan_params;
89 * Used for autoscan "emulation".
90 * Should be removed when wpa_s autoscan support will be by default.
92 struct autoscan_params {
101 struct connman_device *device;
102 struct connman_network *network;
103 struct connman_network *pending_network;
105 GSupplicantInterface *interface;
106 GSupplicantState state;
111 bool interface_ready;
117 struct hidden_params *hidden;
118 bool postpone_hidden;
120 * autoscan "emulation".
122 struct autoscan_params *autoscan;
124 GSupplicantScanParams *scan_params;
125 unsigned int p2p_find_timeout;
126 unsigned int p2p_connection_timeout;
127 struct connman_peer *pending_peer;
128 GSupplicantPeer *peer;
132 #if defined TIZEN_EXT
133 int assoc_retry_count;
134 struct connman_network *scan_pending_network;
135 bool allow_full_scan;
141 #if defined TIZEN_EXT
145 #define TIZEN_ASSOC_RETRY_COUNT 4
147 static gboolean wifi_first_scan = false;
148 static gboolean found_with_first_scan = false;
149 static gboolean is_wifi_notifier_registered = false;
153 static GList *iface_list = NULL;
155 static GList *pending_wifi_device = NULL;
156 static GList *p2p_iface_list = NULL;
157 bool wfd_service_registered = false;
159 static void start_autoscan(struct connman_device *device);
161 #if defined TIZEN_EXT
162 #define NETCONFIG_SERVICE "net.netconfig"
163 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
164 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
166 struct enc_method_call_data {
167 DBusConnection *connection;
168 struct connman_network *network;
171 static struct enc_method_call_data encrypt_request_data;
173 static void encryption_request_reply(DBusPendingCall *call,
178 DBusMessageIter args;
180 struct connman_service *service;
181 gchar* encrypted_value = NULL;
182 struct connman_network *network = encrypt_request_data.network;
186 reply = dbus_pending_call_steal_reply(call);
188 dbus_error_init(&error);
189 if (dbus_set_error_from_message(&error, reply)) {
190 DBG("send_encryption_request() %s %s", error.name, error.message);
191 dbus_error_free(&error);
195 if (dbus_message_iter_init(reply, &args) == FALSE)
198 dbus_message_iter_get_basic(&args, &out_data);
200 encrypted_value = g_strdup((const gchar *)out_data);
201 service = connman_service_lookup_from_network(network);
204 DBG("encryption result: no service");
208 if (connman_service_get_favorite(service)) {
209 __connman_service_set_passphrase(service, encrypted_value);
210 __connman_service_save(service);
212 connman_network_set_string(network, "WiFi.Passphrase",
215 DBG("encryption result: succeeded");
218 dbus_message_unref(reply);
219 dbus_pending_call_unref(call);
220 dbus_connection_unref(encrypt_request_data.connection);
221 g_free(encrypted_value);
223 encrypt_request_data.connection = NULL;
224 encrypt_request_data.network = NULL;
227 static int send_encryption_request(const char *passphrase,
228 struct connman_network *network)
230 DBusConnection *connection = NULL;
231 DBusMessage *msg = NULL;
232 DBusPendingCall *call;
235 DBG("Invalid parameter");
239 connection = connman_dbus_get_connection();
241 DBG("dbus connection does not exist");
245 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
246 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
248 dbus_connection_unref(connection);
252 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
255 if (!dbus_connection_send_with_reply(connection, msg,
256 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
257 dbus_message_unref(msg);
258 dbus_connection_unref(connection);
263 dbus_message_unref(msg);
264 dbus_connection_unref(connection);
268 encrypt_request_data.connection = connection;
269 encrypt_request_data.network = network;
271 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
272 dbus_message_unref(msg);
278 static int p2p_tech_probe(struct connman_technology *technology)
280 p2p_technology = technology;
285 static void p2p_tech_remove(struct connman_technology *technology)
287 p2p_technology = NULL;
290 static struct connman_technology_driver p2p_tech_driver = {
292 .type = CONNMAN_SERVICE_TYPE_P2P,
293 .probe = p2p_tech_probe,
294 .remove = p2p_tech_remove,
297 static bool is_p2p_connecting(void)
301 for (list = iface_list; list; list = list->next) {
302 struct wifi_data *wifi = list->data;
304 if (wifi->p2p_connecting)
311 static void add_pending_wifi_device(struct wifi_data *wifi)
313 if (g_list_find(pending_wifi_device, wifi))
316 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
319 static struct wifi_data *get_pending_wifi_data(const char *ifname)
323 for (list = pending_wifi_device; list; list = list->next) {
324 struct wifi_data *wifi;
325 const char *dev_name;
328 if (!wifi || !wifi->device)
331 dev_name = connman_device_get_string(wifi->device, "Interface");
332 if (!g_strcmp0(ifname, dev_name)) {
333 pending_wifi_device = g_list_delete_link(
334 pending_wifi_device, list);
342 static void remove_pending_wifi_device(struct wifi_data *wifi)
346 link = g_list_find(pending_wifi_device, wifi);
351 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
354 static void peer_cancel_timeout(struct wifi_data *wifi)
356 if (wifi->p2p_connection_timeout > 0)
357 g_source_remove(wifi->p2p_connection_timeout);
359 wifi->p2p_connection_timeout = 0;
360 wifi->p2p_connecting = false;
362 if (wifi->pending_peer) {
363 connman_peer_unref(wifi->pending_peer);
364 wifi->pending_peer = NULL;
370 static gboolean peer_connect_timeout(gpointer data)
372 struct wifi_data *wifi = data;
376 if (wifi->p2p_connecting) {
377 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
379 if (g_supplicant_peer_has_requested_connection(wifi->peer))
380 state = CONNMAN_PEER_STATE_IDLE;
382 connman_peer_set_state(wifi->pending_peer, state);
385 peer_cancel_timeout(wifi);
390 static void peer_connect_callback(int result, GSupplicantInterface *interface,
393 struct wifi_data *wifi = user_data;
394 struct connman_peer *peer = wifi->pending_peer;
396 DBG("peer %p - %d", peer, result);
402 peer_connect_timeout(wifi);
406 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
408 wifi->p2p_connection_timeout = g_timeout_add_seconds(
409 P2P_CONNECTION_TIMEOUT,
410 peer_connect_timeout, wifi);
413 static int peer_connect(struct connman_peer *peer,
414 enum connman_peer_wps_method wps_method,
417 struct connman_device *device = connman_peer_get_device(peer);
418 GSupplicantPeerParams *peer_params;
419 GSupplicantPeer *gs_peer;
420 struct wifi_data *wifi;
424 DBG("peer %p", peer);
429 wifi = connman_device_get_data(device);
433 if (wifi->p2p_connecting)
438 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
439 connman_peer_get_identifier(peer));
443 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
444 pin = g_supplicant_peer_is_wps_pin(gs_peer);
446 switch (wps_method) {
447 case CONNMAN_PEER_WPS_UNKNOWN:
448 if ((pbc && pin) || pin)
451 case CONNMAN_PEER_WPS_PBC:
456 case CONNMAN_PEER_WPS_PIN:
457 if (!pin || !wps_pin)
462 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
466 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
468 peer_params->wps_pin = g_strdup(wps_pin);
470 peer_params->master = connman_peer_service_is_master();
472 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
473 peer_connect_callback, wifi);
474 if (ret == -EINPROGRESS) {
475 wifi->pending_peer = connman_peer_ref(peer);
476 wifi->peer = gs_peer;
477 wifi->p2p_connecting = true;
484 static int peer_disconnect(struct connman_peer *peer)
486 struct connman_device *device = connman_peer_get_device(peer);
487 GSupplicantPeerParams peer_params = {};
488 GSupplicantPeer *gs_peer;
489 struct wifi_data *wifi;
492 DBG("peer %p", peer);
497 wifi = connman_device_get_data(device);
501 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
502 connman_peer_get_identifier(peer));
506 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
508 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
510 g_free(peer_params.path);
512 if (ret == -EINPROGRESS)
513 peer_cancel_timeout(wifi);
518 struct peer_service_registration {
519 peer_service_registration_cb_t callback;
523 static bool is_service_wfd(const unsigned char *specs, int length)
525 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
531 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
533 struct wifi_data *wifi = data;
535 if (!wifi->interface ||
536 !g_supplicant_interface_has_p2p(wifi->interface))
539 if (!wifi->servicing) {
540 g_supplicant_interface_p2p_listen(wifi->interface,
541 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
547 static void register_wfd_service_cb(int result,
548 GSupplicantInterface *iface, void *user_data)
550 struct peer_service_registration *reg_data = user_data;
555 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
557 if (reg_data && reg_data->callback) {
558 reg_data->callback(result, reg_data->user_data);
563 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
564 const unsigned char *spec,
565 int spec_length, const unsigned char *query,
566 int query_length, int version)
568 GSupplicantP2PServiceParams *params;
570 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
575 params->version = version;
576 params->service = g_memdup(spec, spec_length);
577 } else if (query_length > 0 && spec_length > 0) {
578 params->query = g_memdup(query, query_length);
579 params->query_length = query_length;
581 params->response = g_memdup(spec, spec_length);
582 params->response_length = spec_length;
584 params->wfd_ies = g_memdup(spec, spec_length);
585 params->wfd_ies_length = spec_length;
591 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
596 g_free(params->service);
597 g_free(params->query);
598 g_free(params->response);
599 g_free(params->wfd_ies);
604 static int peer_register_wfd_service(const unsigned char *specification,
605 int specification_length,
606 peer_service_registration_cb_t callback,
609 struct peer_service_registration *reg_data = NULL;
610 static GSupplicantP2PServiceParams *params;
615 if (wfd_service_registered)
618 params = fill_in_peer_service_params(specification,
619 specification_length, NULL, 0, 0);
623 reg_data = g_try_malloc0(sizeof(*reg_data));
629 reg_data->callback = callback;
630 reg_data->user_data = user_data;
632 ret = g_supplicant_set_widi_ies(params,
633 register_wfd_service_cb, reg_data);
634 if (ret < 0 && ret != -EINPROGRESS)
637 wfd_service_registered = true;
641 free_peer_service_params(params);
647 static void register_peer_service_cb(int result,
648 GSupplicantInterface *iface, void *user_data)
650 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
651 struct peer_service_registration *reg_data = user_data;
653 #if defined TIZEN_EXT
661 apply_p2p_listen_on_iface(wifi, NULL);
663 if (reg_data->callback)
664 reg_data->callback(result, reg_data->user_data);
669 static int peer_register_service(const unsigned char *specification,
670 int specification_length,
671 const unsigned char *query,
672 int query_length, int version,
673 peer_service_registration_cb_t callback,
676 struct peer_service_registration *reg_data;
677 GSupplicantP2PServiceParams *params;
684 if (specification && !version && !query &&
685 is_service_wfd(specification, specification_length)) {
686 return peer_register_wfd_service(specification,
687 specification_length, callback, user_data);
690 reg_data = g_try_malloc0(sizeof(*reg_data));
694 reg_data->callback = callback;
695 reg_data->user_data = user_data;
699 for (list = iface_list; list; list = list->next) {
700 struct wifi_data *wifi = list->data;
701 GSupplicantInterface *iface = wifi->interface;
703 if (!g_supplicant_interface_has_p2p(iface))
706 params = fill_in_peer_service_params(specification,
707 specification_length, query,
708 query_length, version);
715 ret_f = g_supplicant_interface_p2p_add_service(iface,
716 register_peer_service_cb, params, reg_data);
717 if (ret_f == 0 || ret_f == -EINPROGRESS)
721 ret = g_supplicant_interface_p2p_add_service(iface,
722 register_peer_service_cb, params, NULL);
723 if (ret != 0 && ret != -EINPROGRESS)
724 free_peer_service_params(params);
727 if (ret_f != 0 && ret_f != -EINPROGRESS)
733 static int peer_unregister_wfd_service(void)
735 GSupplicantP2PServiceParams *params;
738 if (!wfd_service_registered)
741 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
745 wfd_service_registered = false;
747 g_supplicant_set_widi_ies(params, NULL, NULL);
749 for (list = iface_list; list; list = list->next) {
750 struct wifi_data *wifi = list->data;
752 if (!g_supplicant_interface_has_p2p(wifi->interface))
756 if (!wifi->servicing || wifi->servicing < 0) {
757 g_supplicant_interface_p2p_listen(wifi->interface,
766 static int peer_unregister_service(const unsigned char *specification,
767 int specification_length,
768 const unsigned char *query,
769 int query_length, int version)
771 GSupplicantP2PServiceParams *params;
776 if (specification && !version && !query &&
777 is_service_wfd(specification, specification_length)) {
778 ret = peer_unregister_wfd_service();
779 if (ret != 0 && ret != -EINPROGRESS)
784 for (list = iface_list; list; list = list->next) {
785 struct wifi_data *wifi = list->data;
786 GSupplicantInterface *iface = wifi->interface;
791 if (!g_supplicant_interface_has_p2p(iface))
794 params = fill_in_peer_service_params(specification,
795 specification_length, query,
796 query_length, version);
802 ret = g_supplicant_interface_p2p_del_service(iface, params);
803 if (ret != 0 && ret != -EINPROGRESS)
804 free_peer_service_params(params);
807 if (!wifi->servicing || wifi->servicing < 0) {
808 g_supplicant_interface_p2p_listen(iface, 0, 0);
816 static struct connman_peer_driver peer_driver = {
817 .connect = peer_connect,
818 .disconnect = peer_disconnect,
819 .register_service = peer_register_service,
820 .unregister_service = peer_unregister_service,
823 static void handle_tethering(struct wifi_data *wifi)
825 if (!wifi->tethering)
834 DBG("index %d bridge %s", wifi->index, wifi->bridge);
836 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
839 wifi->bridged = true;
842 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
844 struct connman_device *device = user_data;
845 struct wifi_data *wifi = connman_device_get_data(device);
850 DBG("index %d flags %d change %d", wifi->index, flags, change);
852 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
856 DBG("interface down");
859 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
860 if (flags & IFF_LOWER_UP) {
863 handle_tethering(wifi);
871 static int wifi_probe(struct connman_device *device)
873 struct wifi_data *wifi;
875 DBG("device %p", device);
877 wifi = g_try_new0(struct wifi_data, 1);
881 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
883 connman_device_set_data(device, wifi);
884 wifi->device = connman_device_ref(device);
886 wifi->index = connman_device_get_index(device);
889 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
890 wifi_newlink, device);
891 if (is_p2p_connecting())
892 add_pending_wifi_device(wifi);
894 iface_list = g_list_append(iface_list, wifi);
899 static void remove_networks(struct connman_device *device,
900 struct wifi_data *wifi)
904 for (list = wifi->networks; list; list = list->next) {
905 struct connman_network *network = list->data;
907 connman_device_remove_network(device, network);
908 connman_network_unref(network);
911 g_slist_free(wifi->networks);
912 wifi->networks = NULL;
915 static void reset_autoscan(struct connman_device *device)
917 struct wifi_data *wifi = connman_device_get_data(device);
918 struct autoscan_params *autoscan;
922 if (!wifi || !wifi->autoscan)
925 autoscan = wifi->autoscan;
927 if (autoscan->timeout == 0 && autoscan->interval == 0)
930 g_source_remove(autoscan->timeout);
932 autoscan->timeout = 0;
933 autoscan->interval = 0;
935 connman_device_unref(device);
938 static void stop_autoscan(struct connman_device *device)
940 const struct wifi_data *wifi = connman_device_get_data(device);
942 if (!wifi || !wifi->autoscan)
945 reset_autoscan(device);
947 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
950 static void check_p2p_technology(void)
952 bool p2p_exists = false;
955 for (list = iface_list; list; list = list->next) {
956 struct wifi_data *w = list->data;
959 g_supplicant_interface_has_p2p(w->interface))
964 connman_technology_driver_unregister(&p2p_tech_driver);
965 connman_peer_driver_unregister(&peer_driver);
969 static void wifi_remove(struct connman_device *device)
971 struct wifi_data *wifi = connman_device_get_data(device);
973 DBG("device %p wifi %p", device, wifi);
978 stop_autoscan(device);
980 if (wifi->p2p_device)
981 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
983 iface_list = g_list_remove(iface_list, wifi);
985 check_p2p_technology();
987 remove_pending_wifi_device(wifi);
989 if (wifi->p2p_find_timeout) {
990 g_source_remove(wifi->p2p_find_timeout);
991 connman_device_unref(wifi->device);
994 if (wifi->p2p_connection_timeout)
995 g_source_remove(wifi->p2p_connection_timeout);
997 remove_networks(device, wifi);
999 connman_device_set_powered(device, false);
1000 connman_device_set_data(device, NULL);
1001 connman_device_unref(wifi->device);
1002 connman_rtnl_remove_watch(wifi->watch);
1004 g_supplicant_interface_set_data(wifi->interface, NULL);
1006 g_supplicant_interface_cancel(wifi->interface);
1008 if (wifi->scan_params)
1009 g_supplicant_free_scan_params(wifi->scan_params);
1011 g_free(wifi->autoscan);
1012 g_free(wifi->identifier);
1016 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1020 for (iter = list; iter; iter = g_slist_next(iter)) {
1021 struct scan_ssid *scan_ssid = iter->data;
1023 if (ssid_len == scan_ssid->ssid_len &&
1024 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1031 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1032 int freq, GSupplicantScanParams *scan_data,
1033 int driver_max_scan_ssids, char *ssid_name)
1036 struct scan_ssid *scan_ssid;
1038 if ((driver_max_scan_ssids == 0 ||
1039 driver_max_scan_ssids > scan_data->num_ssids) &&
1040 (hex_ssid || raw_ssid)) {
1042 unsigned int j = 0, hex;
1045 size_t hex_ssid_len = strlen(hex_ssid);
1047 ssid = g_try_malloc0(hex_ssid_len / 2);
1051 for (i = 0; i < hex_ssid_len; i += 2) {
1052 sscanf(hex_ssid + i, "%02x", &hex);
1061 * If we have already added hidden AP to the list,
1062 * then do not do it again. This might happen if you have
1063 * used or are using multiple wifi cards, so in that case
1064 * you might have multiple service files for same AP.
1066 if (is_duplicate(scan_data->ssids, ssid, j)) {
1072 scan_ssid = g_try_new(struct scan_ssid, 1);
1079 memcpy(scan_ssid->ssid, ssid, j);
1080 scan_ssid->ssid_len = j;
1081 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1084 scan_data->num_ssids++;
1086 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1087 scan_data->num_ssids);
1094 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1096 if (!scan_data->freqs) {
1097 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1098 if (!scan_data->freqs) {
1099 g_slist_free_full(scan_data->ssids, g_free);
1103 scan_data->num_freqs = 1;
1104 scan_data->freqs[0] = freq;
1106 bool duplicate = false;
1108 /* Don't add duplicate entries */
1109 for (i = 0; i < scan_data->num_freqs; i++) {
1110 if (scan_data->freqs[i] == freq) {
1117 scan_data->num_freqs++;
1118 scan_data->freqs = g_try_realloc(scan_data->freqs,
1119 sizeof(uint16_t) * scan_data->num_freqs);
1120 if (!scan_data->freqs) {
1121 g_slist_free_full(scan_data->ssids, g_free);
1124 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1131 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1133 struct connman_config_entry **entries;
1139 int num_ssids = 0, add_param_failed = 0;
1141 services = connman_storage_get_services();
1142 for (i = 0; services && services[i]; i++) {
1143 if (strncmp(services[i], "wifi_", 5) != 0)
1146 keyfile = connman_storage_load_service(services[i]);
1150 value = g_key_file_get_boolean(keyfile,
1151 services[i], "Hidden", NULL);
1153 g_key_file_free(keyfile);
1157 value = g_key_file_get_boolean(keyfile,
1158 services[i], "Favorite", NULL);
1160 g_key_file_free(keyfile);
1164 #if defined TIZEN_EXT
1165 value = g_key_file_get_boolean(keyfile,
1166 services[i], "AutoConnect", NULL);
1168 g_key_file_free(keyfile);
1173 ssid = g_key_file_get_string(keyfile,
1174 services[i], "SSID", NULL);
1176 name = g_key_file_get_string(keyfile, services[i], "Name",
1179 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1187 g_key_file_free(keyfile);
1191 * Check if there are any hidden AP that needs to be provisioned.
1193 entries = connman_config_get_entries("wifi");
1194 for (i = 0; entries && entries[i]; i++) {
1197 if (!entries[i]->hidden)
1200 if (!entries[i]->ssid) {
1201 ssid = entries[i]->name;
1204 ssid = entries[i]->ssid;
1205 len = entries[i]->ssid_len;
1211 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1218 connman_config_free_entries(entries);
1220 if (add_param_failed > 0)
1221 DBG("Unable to scan %d out of %d SSIDs",
1222 add_param_failed, num_ssids);
1224 g_strfreev(services);
1229 static int get_hidden_connections_params(struct wifi_data *wifi,
1230 GSupplicantScanParams *scan_params)
1232 int driver_max_ssids, i;
1233 GSupplicantScanParams *orig_params;
1236 * Scan hidden networks so that we can autoconnect to them.
1237 * We will assume 1 as a default number of ssid to scan.
1239 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1241 if (driver_max_ssids == 0)
1242 driver_max_ssids = 1;
1244 DBG("max ssids %d", driver_max_ssids);
1246 if (!wifi->scan_params) {
1247 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1248 if (!wifi->scan_params)
1251 if (get_hidden_connections(wifi->scan_params) == 0) {
1252 g_supplicant_free_scan_params(wifi->scan_params);
1253 wifi->scan_params = NULL;
1259 orig_params = wifi->scan_params;
1261 /* Let's transfer driver_max_ssids params */
1262 for (i = 0; i < driver_max_ssids; i++) {
1263 struct scan_ssid *ssid;
1265 if (!wifi->scan_params->ssids)
1268 ssid = orig_params->ssids->data;
1269 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1270 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1274 scan_params->num_ssids = i;
1275 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1277 scan_params->freqs = g_memdup(orig_params->freqs,
1278 sizeof(uint16_t) * orig_params->num_freqs);
1279 if (!scan_params->freqs)
1282 scan_params->num_freqs = orig_params->num_freqs;
1287 orig_params->num_ssids -= scan_params->num_ssids;
1289 return scan_params->num_ssids;
1292 g_slist_free_full(scan_params->ssids, g_free);
1293 g_supplicant_free_scan_params(wifi->scan_params);
1294 wifi->scan_params = NULL;
1299 static int throw_wifi_scan(struct connman_device *device,
1300 GSupplicantInterfaceCallback callback)
1302 struct wifi_data *wifi = connman_device_get_data(device);
1308 DBG("device %p %p", device, wifi->interface);
1310 if (wifi->tethering)
1312 #if defined TIZEN_EXT
1313 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1315 if (connman_device_get_scanning(device))
1319 connman_device_ref(device);
1321 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1324 connman_device_set_scanning(device,
1325 CONNMAN_SERVICE_TYPE_WIFI, true);
1327 connman_device_unref(device);
1332 static void hidden_free(struct hidden_params *hidden)
1337 if (hidden->scan_params)
1338 g_supplicant_free_scan_params(hidden->scan_params);
1339 g_free(hidden->identity);
1340 g_free(hidden->passphrase);
1341 g_free(hidden->security);
1345 #if defined TIZEN_EXT
1346 static void service_state_changed(struct connman_service *service,
1347 enum connman_service_state state);
1349 static int network_connect(struct connman_network *network);
1351 static struct connman_notifier notifier = {
1353 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1354 .service_state_changed = service_state_changed,
1357 static void service_state_changed(struct connman_service *service,
1358 enum connman_service_state state)
1360 enum connman_service_type type;
1362 type = connman_service_get_type(service);
1363 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1366 DBG("service %p state %d", service, state);
1369 case CONNMAN_SERVICE_STATE_READY:
1370 case CONNMAN_SERVICE_STATE_ONLINE:
1371 case CONNMAN_SERVICE_STATE_FAILURE:
1372 connman_notifier_unregister(¬ifier);
1373 is_wifi_notifier_registered = FALSE;
1375 __connman_device_request_scan(type);
1384 static void scan_callback(int result, GSupplicantInterface *interface,
1387 struct connman_device *device = user_data;
1388 struct wifi_data *wifi = connman_device_get_data(device);
1391 DBG("result %d wifi %p", result, wifi);
1394 if (wifi->hidden && !wifi->postpone_hidden) {
1395 connman_network_clear_hidden(wifi->hidden->user_data);
1396 hidden_free(wifi->hidden);
1397 wifi->hidden = NULL;
1400 if (wifi->scan_params) {
1401 g_supplicant_free_scan_params(wifi->scan_params);
1402 wifi->scan_params = NULL;
1407 connman_device_reset_scanning(device);
1409 /* User is connecting to a hidden AP, let's wait for finished event */
1410 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1411 GSupplicantScanParams *scan_params;
1414 wifi->postpone_hidden = false;
1415 scan_params = wifi->hidden->scan_params;
1416 wifi->hidden->scan_params = NULL;
1418 reset_autoscan(device);
1420 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1421 scan_callback, device);
1425 /* On error, let's recall scan_callback, which will cleanup */
1426 return scan_callback(ret, interface, user_data);
1429 #if defined TIZEN_EXT
1430 if (wifi && wifi->allow_full_scan) {
1432 DBG("Trigger Full Channel Scan");
1433 wifi->allow_full_scan = FALSE;
1435 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1436 scan_callback, device);
1440 /* On error, let's recall scan_callback, which will cleanup */
1441 return scan_callback(ret, interface, user_data);
1445 scanning = connman_device_get_scanning(device);
1447 connman_device_set_scanning(device,
1448 CONNMAN_SERVICE_TYPE_WIFI, false);
1450 if (result != -ENOLINK)
1451 #if defined TIZEN_EXT
1454 start_autoscan(device);
1457 * If we are here then we were scanning; however, if we are
1458 * also mid-flight disabling the interface, then wifi_disable
1459 * has already cleared the device scanning state and
1460 * unreferenced the device, obviating the need to do it here.
1464 connman_device_unref(device);
1466 #if defined TIZEN_EXT
1467 if (wifi && wifi->scan_pending_network && result != -EIO) {
1468 network_connect(wifi->scan_pending_network);
1469 wifi->scan_pending_network = NULL;
1470 connman_network_set_connecting(wifi->network);
1473 if (is_wifi_notifier_registered != true &&
1474 wifi_first_scan == true && found_with_first_scan == true) {
1475 wifi_first_scan = false;
1476 found_with_first_scan = false;
1478 connman_notifier_register(¬ifier);
1479 is_wifi_notifier_registered = true;
1484 static void scan_callback_hidden(int result,
1485 GSupplicantInterface *interface, void *user_data)
1487 struct connman_device *device = user_data;
1488 struct wifi_data *wifi = connman_device_get_data(device);
1489 GSupplicantScanParams *scan_params;
1492 DBG("result %d wifi %p", result, wifi);
1497 /* User is trying to connect to a hidden AP */
1498 if (wifi->hidden && wifi->postpone_hidden)
1501 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1505 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1506 ret = g_supplicant_interface_scan(wifi->interface,
1508 scan_callback_hidden,
1514 g_supplicant_free_scan_params(scan_params);
1517 scan_callback(result, interface, user_data);
1520 static gboolean autoscan_timeout(gpointer data)
1522 struct connman_device *device = data;
1523 struct wifi_data *wifi = connman_device_get_data(device);
1524 struct autoscan_params *autoscan;
1530 autoscan = wifi->autoscan;
1532 if (autoscan->interval <= 0) {
1533 interval = autoscan->base;
1536 interval = autoscan->interval * autoscan->base;
1538 #if defined TIZEN_EXT
1539 if (autoscan->interval >= autoscan->limit)
1541 if (interval > autoscan->limit)
1543 interval = autoscan->limit;
1545 throw_wifi_scan(wifi->device, scan_callback_hidden);
1548 DBG("interval %d", interval);
1550 autoscan->interval = interval;
1552 autoscan->timeout = g_timeout_add_seconds(interval,
1553 autoscan_timeout, device);
1558 static void start_autoscan(struct connman_device *device)
1560 struct wifi_data *wifi = connman_device_get_data(device);
1561 struct autoscan_params *autoscan;
1568 if (wifi->p2p_device)
1571 if (wifi->connected)
1574 autoscan = wifi->autoscan;
1578 if (autoscan->timeout > 0 || autoscan->interval > 0)
1581 connman_device_ref(device);
1583 autoscan_timeout(device);
1586 static struct autoscan_params *parse_autoscan_params(const char *params)
1588 struct autoscan_params *autoscan;
1593 DBG("Emulating autoscan");
1595 list_params = g_strsplit(params, ":", 0);
1596 if (list_params == 0)
1599 if (g_strv_length(list_params) < 3) {
1600 g_strfreev(list_params);
1604 base = atoi(list_params[1]);
1605 limit = atoi(list_params[2]);
1607 g_strfreev(list_params);
1609 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1611 DBG("Could not allocate memory for autoscan");
1615 DBG("base %d - limit %d", base, limit);
1616 autoscan->base = base;
1617 autoscan->limit = limit;
1622 static void setup_autoscan(struct wifi_data *wifi)
1624 if (!wifi->autoscan)
1625 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1627 start_autoscan(wifi->device);
1630 static void finalize_interface_creation(struct wifi_data *wifi)
1632 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1634 if (!wifi->device) {
1635 connman_error("WiFi device not set");
1639 connman_device_set_powered(wifi->device, true);
1641 if (!connman_setting_get_bool("BackgroundScanning"))
1644 if (wifi->p2p_device)
1647 setup_autoscan(wifi);
1650 static void interface_create_callback(int result,
1651 GSupplicantInterface *interface,
1654 struct wifi_data *wifi = user_data;
1656 DBG("result %d ifname %s, wifi %p", result,
1657 g_supplicant_interface_get_ifname(interface),
1660 if (result < 0 || !wifi)
1663 wifi->interface = interface;
1664 g_supplicant_interface_set_data(interface, wifi);
1666 if (g_supplicant_interface_get_ready(interface)) {
1667 wifi->interface_ready = true;
1668 finalize_interface_creation(wifi);
1672 static int wifi_enable(struct connman_device *device)
1674 struct wifi_data *wifi = connman_device_get_data(device);
1677 const char *driver = connman_option_get_string("wifi");
1680 DBG("device %p %p", device, wifi);
1682 index = connman_device_get_index(device);
1683 if (!wifi || index < 0)
1686 if (is_p2p_connecting())
1687 return -EINPROGRESS;
1689 interface = connman_inet_ifname(index);
1690 ret = g_supplicant_interface_create(interface, driver, NULL,
1691 interface_create_callback,
1698 return -EINPROGRESS;
1701 static int wifi_disable(struct connman_device *device)
1703 struct wifi_data *wifi = connman_device_get_data(device);
1706 DBG("device %p wifi %p", device, wifi);
1711 wifi->connected = false;
1712 wifi->disconnecting = false;
1714 if (wifi->pending_network)
1715 wifi->pending_network = NULL;
1717 stop_autoscan(device);
1719 if (wifi->p2p_find_timeout) {
1720 g_source_remove(wifi->p2p_find_timeout);
1721 wifi->p2p_find_timeout = 0;
1722 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1723 connman_device_unref(wifi->device);
1726 /* In case of a user scan, device is still referenced */
1727 if (connman_device_get_scanning(device)) {
1728 connman_device_set_scanning(device,
1729 CONNMAN_SERVICE_TYPE_WIFI, false);
1730 connman_device_unref(wifi->device);
1733 remove_networks(device, wifi);
1735 #if defined TIZEN_EXT
1736 wifi->scan_pending_network = NULL;
1738 if (is_wifi_notifier_registered == true) {
1739 connman_notifier_unregister(¬ifier);
1740 is_wifi_notifier_registered = false;
1744 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1748 return -EINPROGRESS;
1751 struct last_connected {
1757 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1759 GTimeVal *aval = (GTimeVal *)a;
1760 GTimeVal *bval = (GTimeVal *)b;
1762 /* Note that the sort order is descending */
1763 if (aval->tv_sec < bval->tv_sec)
1766 if (aval->tv_sec > bval->tv_sec)
1772 static void free_entry(gpointer data)
1774 struct last_connected *entry = data;
1776 g_free(entry->ssid);
1780 static int get_latest_connections(int max_ssids,
1781 GSupplicantScanParams *scan_data)
1783 GSequenceIter *iter;
1784 GSequence *latest_list;
1785 struct last_connected *entry;
1794 latest_list = g_sequence_new(free_entry);
1798 services = connman_storage_get_services();
1799 for (i = 0; services && services[i]; i++) {
1800 if (strncmp(services[i], "wifi_", 5) != 0)
1803 keyfile = connman_storage_load_service(services[i]);
1807 str = g_key_file_get_string(keyfile,
1808 services[i], "Favorite", NULL);
1809 if (!str || g_strcmp0(str, "true")) {
1811 g_key_file_free(keyfile);
1816 str = g_key_file_get_string(keyfile,
1817 services[i], "AutoConnect", NULL);
1818 if (!str || g_strcmp0(str, "true")) {
1820 g_key_file_free(keyfile);
1825 str = g_key_file_get_string(keyfile,
1826 services[i], "Modified", NULL);
1828 g_key_file_free(keyfile);
1831 g_time_val_from_iso8601(str, &modified);
1834 ssid = g_key_file_get_string(keyfile,
1835 services[i], "SSID", NULL);
1837 freq = g_key_file_get_integer(keyfile, services[i],
1840 entry = g_try_new(struct last_connected, 1);
1842 g_sequence_free(latest_list);
1843 g_key_file_free(keyfile);
1849 entry->modified = modified;
1852 g_sequence_insert_sorted(latest_list, entry,
1858 g_key_file_free(keyfile);
1861 g_strfreev(services);
1863 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1865 iter = g_sequence_get_begin_iter(latest_list);
1867 for (i = 0; i < num_ssids; i++) {
1868 entry = g_sequence_get(iter);
1870 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1871 entry->modified.tv_sec);
1873 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1874 max_ssids, entry->ssid);
1876 iter = g_sequence_iter_next(iter);
1879 g_sequence_free(latest_list);
1883 static int wifi_scan_simple(struct connman_device *device)
1885 reset_autoscan(device);
1887 return throw_wifi_scan(device, scan_callback_hidden);
1890 static gboolean p2p_find_stop(gpointer data)
1892 struct connman_device *device = data;
1893 struct wifi_data *wifi = connman_device_get_data(device);
1897 wifi->p2p_find_timeout = 0;
1899 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1901 g_supplicant_interface_p2p_stop_find(wifi->interface);
1903 connman_device_unref(device);
1904 reset_autoscan(device);
1909 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1912 struct connman_device *device = user_data;
1913 struct wifi_data *wifi = connman_device_get_data(device);
1915 DBG("result %d wifi %p", result, wifi);
1917 if (wifi->p2p_find_timeout) {
1918 g_source_remove(wifi->p2p_find_timeout);
1919 wifi->p2p_find_timeout = 0;
1925 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1926 p2p_find_stop, device);
1927 if (!wifi->p2p_find_timeout)
1932 p2p_find_stop(device);
1935 static int p2p_find(struct connman_device *device)
1937 struct wifi_data *wifi;
1942 if (!p2p_technology)
1945 wifi = connman_device_get_data(device);
1947 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
1950 reset_autoscan(device);
1951 connman_device_ref(device);
1953 ret = g_supplicant_interface_p2p_find(wifi->interface,
1954 p2p_find_callback, device);
1956 connman_device_unref(device);
1957 start_autoscan(device);
1959 connman_device_set_scanning(device,
1960 CONNMAN_SERVICE_TYPE_P2P, true);
1966 #if defined TIZEN_EXT
1967 static void specific_scan_callback(int result, GSupplicantInterface *interface,
1970 struct connman_device *device = user_data;
1971 struct wifi_data *wifi = connman_device_get_data(device);
1974 DBG("result %d wifi %p", result, wifi);
1976 if (wifi && wifi->scan_params) {
1977 g_supplicant_free_scan_params(wifi->scan_params);
1978 wifi->scan_params = NULL;
1981 scanning = connman_device_get_scanning(device);
1983 connman_device_set_scanning(device,
1984 CONNMAN_SERVICE_TYPE_WIFI, false);
1985 connman_device_unref(device);
1989 static int wifi_specific_scan(enum connman_service_type type,
1990 struct connman_device *device, int scan_type,
1991 GSList *specific_scan_list, void *user_data)
1993 GSList *list = NULL;
1995 struct wifi_data *wifi = connman_device_get_data(device);
1996 GSupplicantScanParams *scan_params = NULL;
1997 struct scan_ssid *scan_ssid = NULL;
2006 if (wifi->p2p_device)
2009 if (type == CONNMAN_SERVICE_TYPE_P2P)
2010 return p2p_find(device);
2012 if (wifi->tethering)
2015 scanning = connman_device_get_scanning(device);
2019 DBG("scan_type: %d", scan_type);
2020 if (scan_type == 1) { /* ssid based scan */
2021 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2023 DBG("Failed to allocate memory.");
2027 for (list = specific_scan_list; list; list = list->next) {
2028 ssid = (char *)list->data;
2029 int ssid_len = strlen(ssid);
2031 scan_ssid = g_try_new0(struct scan_ssid, 1);
2033 DBG("Failed to allocate memory.");
2034 g_supplicant_free_scan_params(scan_params);
2038 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2039 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
2040 scan_ssid->ssid_len = ssid_len;
2041 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2044 scan_params->num_ssids = count;
2046 } else if (scan_type == 2) { /* frequency based scan */
2048 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2050 DBG("Failed to allocate memory.");
2054 guint num_freqs = g_slist_length(specific_scan_list);
2055 DBG("num_freqs: %d", num_freqs);
2057 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2058 if (!scan_params->freqs) {
2059 DBG("Failed to allocate memory.");
2060 g_free(scan_params);
2065 for (list = specific_scan_list; list; list = list->next) {
2066 freq = (int)list->data;
2068 scan_params->freqs[count] = freq;
2069 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2072 scan_params->num_freqs = count;
2075 DBG("Invalid scan");
2079 reset_autoscan(device);
2080 connman_device_ref(device);
2082 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2083 specific_scan_callback, device);
2086 connman_device_set_scanning(device,
2087 CONNMAN_SERVICE_TYPE_WIFI, true);
2089 g_supplicant_free_scan_params(scan_params);
2090 connman_device_unref(device);
2098 * Note that the hidden scan is only used when connecting to this specific
2099 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2101 static int wifi_scan(enum connman_service_type type,
2102 struct connman_device *device,
2103 const char *ssid, unsigned int ssid_len,
2104 const char *identity, const char* passphrase,
2105 const char *security, void *user_data)
2107 struct wifi_data *wifi = connman_device_get_data(device);
2108 GSupplicantScanParams *scan_params = NULL;
2109 struct scan_ssid *scan_ssid;
2110 struct hidden_params *hidden;
2112 int driver_max_ssids = 0;
2119 if (wifi->p2p_device)
2122 if (type == CONNMAN_SERVICE_TYPE_P2P)
2123 return p2p_find(device);
2125 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2127 if (wifi->tethering)
2130 scanning = connman_device_get_scanning(device);
2132 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2136 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2138 DBG("max ssids %d", driver_max_ssids);
2139 if (driver_max_ssids == 0)
2140 return wifi_scan_simple(device);
2144 if (scanning && wifi->hidden && wifi->postpone_hidden)
2150 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2155 scan_ssid = g_try_new(struct scan_ssid, 1);
2157 g_free(scan_params);
2161 memcpy(scan_ssid->ssid, ssid, ssid_len);
2162 scan_ssid->ssid_len = ssid_len;
2163 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2165 scan_params->num_ssids = 1;
2167 hidden = g_try_new0(struct hidden_params, 1);
2169 g_supplicant_free_scan_params(scan_params);
2174 hidden_free(wifi->hidden);
2175 wifi->hidden = NULL;
2178 memcpy(hidden->ssid, ssid, ssid_len);
2179 hidden->ssid_len = ssid_len;
2180 hidden->identity = g_strdup(identity);
2181 hidden->passphrase = g_strdup(passphrase);
2182 hidden->security = g_strdup(security);
2183 hidden->user_data = user_data;
2184 wifi->hidden = hidden;
2187 /* Let's keep this active scan for later,
2188 * when current scan will be over. */
2189 wifi->postpone_hidden = TRUE;
2190 hidden->scan_params = scan_params;
2194 } else if (wifi->connected) {
2195 g_supplicant_free_scan_params(scan_params);
2196 return wifi_scan_simple(device);
2198 ret = get_latest_connections(driver_max_ssids, scan_params);
2200 g_supplicant_free_scan_params(scan_params);
2201 return wifi_scan_simple(device);
2205 connman_device_ref(device);
2207 reset_autoscan(device);
2209 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2210 scan_callback, device);
2213 connman_device_set_scanning(device,
2214 CONNMAN_SERVICE_TYPE_WIFI, true);
2215 #if defined TIZEN_EXT
2216 /*To allow the Full Scan after ssid based scan, set the flag here
2217 It is required because Tizen does not use the ConnMan specific
2218 backgroung Scan feature.Tizen has added the BG Scan feature in
2219 net-config. To sync with up ConnMan, we need to issue the Full Scan
2220 after SSID specific scan.*/
2221 wifi->allow_full_scan = TRUE;
2224 g_supplicant_free_scan_params(scan_params);
2225 connman_device_unref(device);
2228 hidden_free(wifi->hidden);
2229 wifi->hidden = NULL;
2236 static void wifi_regdom_callback(int result,
2240 struct connman_device *device = user_data;
2242 connman_device_regdom_notify(device, result, alpha2);
2244 connman_device_unref(device);
2247 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
2249 struct wifi_data *wifi = connman_device_get_data(device);
2255 connman_device_ref(device);
2257 ret = g_supplicant_interface_set_country(wifi->interface,
2258 wifi_regdom_callback,
2261 connman_device_unref(device);
2266 static struct connman_device_driver wifi_ng_driver = {
2268 .type = CONNMAN_DEVICE_TYPE_WIFI,
2269 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2270 .probe = wifi_probe,
2271 .remove = wifi_remove,
2272 .enable = wifi_enable,
2273 .disable = wifi_disable,
2275 .set_regdom = wifi_set_regdom,
2276 #if defined TIZEN_EXT
2277 .specific_scan = wifi_specific_scan,
2281 static void system_ready(void)
2285 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2286 connman_error("Failed to register WiFi driver");
2289 static void system_killed(void)
2293 connman_device_driver_unregister(&wifi_ng_driver);
2296 static int network_probe(struct connman_network *network)
2298 DBG("network %p", network);
2303 static void network_remove(struct connman_network *network)
2305 struct connman_device *device = connman_network_get_device(network);
2306 struct wifi_data *wifi;
2308 DBG("network %p", network);
2310 wifi = connman_device_get_data(device);
2314 if (wifi->network != network)
2317 wifi->network = NULL;
2319 #if defined TIZEN_EXT
2320 wifi->disconnecting = false;
2322 if (wifi->pending_network == network)
2323 wifi->pending_network = NULL;
2325 if (wifi->scan_pending_network == network)
2326 wifi->scan_pending_network = NULL;
2330 static void connect_callback(int result, GSupplicantInterface *interface,
2333 #if defined TIZEN_EXT
2335 struct wifi_data *wifi;
2337 struct connman_network *network = user_data;
2339 DBG("network %p result %d", network, result);
2341 #if defined TIZEN_EXT
2342 for (list = iface_list; list; list = list->next) {
2345 if (wifi && wifi->network == network)
2349 /* wifi_data may be invalid because wifi is already disabled */
2354 if (result == -ENOKEY) {
2355 connman_network_set_error(network,
2356 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2357 } else if (result < 0) {
2358 connman_network_set_error(network,
2359 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2362 connman_network_unref(network);
2365 static GSupplicantSecurity network_security(const char *security)
2367 if (g_str_equal(security, "none"))
2368 return G_SUPPLICANT_SECURITY_NONE;
2369 else if (g_str_equal(security, "wep"))
2370 return G_SUPPLICANT_SECURITY_WEP;
2371 else if (g_str_equal(security, "psk"))
2372 return G_SUPPLICANT_SECURITY_PSK;
2373 else if (g_str_equal(security, "wpa"))
2374 return G_SUPPLICANT_SECURITY_PSK;
2375 else if (g_str_equal(security, "rsn"))
2376 return G_SUPPLICANT_SECURITY_PSK;
2377 else if (g_str_equal(security, "ieee8021x"))
2378 return G_SUPPLICANT_SECURITY_IEEE8021X;
2379 #if defined TIZEN_EXT
2380 else if (g_str_equal(security, "ft_psk") == TRUE)
2381 return G_SUPPLICANT_SECURITY_FT_PSK;
2382 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2383 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2386 return G_SUPPLICANT_SECURITY_UNKNOWN;
2389 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2391 const char *security;
2393 memset(ssid, 0, sizeof(*ssid));
2394 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2395 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2397 ssid->scan_ssid = 1;
2398 security = connman_network_get_string(network, "WiFi.Security");
2399 ssid->security = network_security(security);
2400 ssid->passphrase = connman_network_get_string(network,
2402 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2405 * If our private key password is unset,
2406 * we use the supplied passphrase. That is needed
2407 * for PEAP where 2 passphrases (identity and client
2408 * cert may have to be provided.
2410 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2411 connman_network_set_string(network,
2412 "WiFi.PrivateKeyPassphrase",
2414 /* We must have an identity for both PEAP and TLS */
2415 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2417 /* Use agent provided identity as a fallback */
2418 if (!ssid->identity || strlen(ssid->identity) == 0)
2419 ssid->identity = connman_network_get_string(network,
2420 "WiFi.AgentIdentity");
2422 ssid->ca_cert_path = connman_network_get_string(network,
2424 ssid->client_cert_path = connman_network_get_string(network,
2425 "WiFi.ClientCertFile");
2426 ssid->private_key_path = connman_network_get_string(network,
2427 "WiFi.PrivateKeyFile");
2428 ssid->private_key_passphrase = connman_network_get_string(network,
2429 "WiFi.PrivateKeyPassphrase");
2430 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2432 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2433 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2435 #if defined TIZEN_EXT
2436 ssid->bssid = connman_network_get_bssid(network);
2438 #if defined TIZEN_EXT
2439 ssid->freq = connman_network_get_frequency(network);
2442 if (connman_setting_get_bool("BackgroundScanning"))
2443 ssid->bgscan = BGSCAN_DEFAULT;
2446 static int network_connect(struct connman_network *network)
2448 struct connman_device *device = connman_network_get_device(network);
2449 struct wifi_data *wifi;
2450 GSupplicantInterface *interface;
2451 GSupplicantSSID *ssid;
2453 DBG("network %p", network);
2458 wifi = connman_device_get_data(device);
2462 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2466 interface = wifi->interface;
2468 ssid_init(ssid, network);
2470 if (wifi->disconnecting) {
2471 wifi->pending_network = network;
2474 wifi->network = connman_network_ref(network);
2476 #if defined TIZEN_EXT
2477 wifi->scan_pending_network = NULL;
2480 return g_supplicant_interface_connect(interface, ssid,
2481 connect_callback, network);
2484 return -EINPROGRESS;
2487 static void disconnect_callback(int result, GSupplicantInterface *interface,
2490 #if defined TIZEN_EXT
2492 struct wifi_data *wifi;
2493 struct connman_network *network = user_data;
2495 DBG("network %p result %d", network, result);
2497 for (list = iface_list; list; list = list->next) {
2500 if (wifi->network == NULL && wifi->disconnecting == true)
2501 wifi->disconnecting = false;
2503 if (wifi->network == network)
2507 /* wifi_data may be invalid because wifi is already disabled */
2512 struct wifi_data *wifi = user_data;
2515 DBG("result %d supplicant interface %p wifi %p",
2516 result, interface, wifi);
2518 if (result == -ECONNABORTED) {
2519 DBG("wifi interface no longer available");
2523 if (wifi->network) {
2525 * if result < 0 supplican return an error because
2526 * the network is not current.
2527 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2528 * failed, call connman_network_set_connected to report
2529 * disconnect is completed.
2532 connman_network_set_connected(wifi->network, false);
2535 wifi->network = NULL;
2537 wifi->disconnecting = false;
2539 if (wifi->pending_network) {
2540 network_connect(wifi->pending_network);
2541 wifi->pending_network = NULL;
2544 start_autoscan(wifi->device);
2547 static int network_disconnect(struct connman_network *network)
2549 struct connman_device *device = connman_network_get_device(network);
2550 struct wifi_data *wifi;
2552 #if defined TIZEN_EXT
2553 struct connman_service *service;
2556 DBG("network %p", network);
2558 wifi = connman_device_get_data(device);
2559 if (!wifi || !wifi->interface)
2562 #if defined TIZEN_EXT
2563 if (connman_network_get_associating(network) == true) {
2564 connman_network_clear_associating(network);
2565 connman_network_set_bool(network, "WiFi.UseWPS", false);
2567 service = connman_service_lookup_from_network(network);
2569 if (service != NULL &&
2570 (__connman_service_is_connected_state(service,
2571 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2572 __connman_service_is_connected_state(service,
2573 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2574 (connman_service_get_favorite(service) == false))
2575 __connman_service_set_passphrase(service, NULL);
2578 if (wifi->pending_network == network)
2579 wifi->pending_network = NULL;
2581 if (wifi->scan_pending_network == network)
2582 wifi->scan_pending_network = NULL;
2585 connman_network_set_associating(network, false);
2587 if (wifi->disconnecting)
2590 wifi->disconnecting = true;
2592 #if defined TIZEN_EXT
2593 err = g_supplicant_interface_disconnect(wifi->interface,
2594 disconnect_callback, network);
2596 err = g_supplicant_interface_disconnect(wifi->interface,
2597 disconnect_callback, wifi);
2601 wifi->disconnecting = false;
2606 static struct connman_network_driver network_driver = {
2608 .type = CONNMAN_NETWORK_TYPE_WIFI,
2609 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2610 .probe = network_probe,
2611 .remove = network_remove,
2612 .connect = network_connect,
2613 .disconnect = network_disconnect,
2616 static void interface_added(GSupplicantInterface *interface)
2618 const char *ifname = g_supplicant_interface_get_ifname(interface);
2619 const char *driver = g_supplicant_interface_get_driver(interface);
2620 struct wifi_data *wifi;
2622 wifi = g_supplicant_interface_get_data(interface);
2624 wifi = get_pending_wifi_data(ifname);
2628 g_supplicant_interface_set_data(interface, wifi);
2629 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2630 wifi->p2p_device = true;
2633 DBG("ifname %s driver %s wifi %p tethering %d",
2634 ifname, driver, wifi, wifi->tethering);
2636 if (!wifi->device) {
2637 connman_error("WiFi device not set");
2641 connman_device_set_powered(wifi->device, true);
2644 static bool is_idle(struct wifi_data *wifi)
2646 DBG("state %d", wifi->state);
2648 switch (wifi->state) {
2649 case G_SUPPLICANT_STATE_UNKNOWN:
2650 case G_SUPPLICANT_STATE_DISABLED:
2651 case G_SUPPLICANT_STATE_DISCONNECTED:
2652 case G_SUPPLICANT_STATE_INACTIVE:
2653 case G_SUPPLICANT_STATE_SCANNING:
2656 case G_SUPPLICANT_STATE_AUTHENTICATING:
2657 case G_SUPPLICANT_STATE_ASSOCIATING:
2658 case G_SUPPLICANT_STATE_ASSOCIATED:
2659 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2660 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2661 case G_SUPPLICANT_STATE_COMPLETED:
2668 static bool is_idle_wps(GSupplicantInterface *interface,
2669 struct wifi_data *wifi)
2671 /* First, let's check if WPS processing did not went wrong */
2672 if (g_supplicant_interface_get_wps_state(interface) ==
2673 G_SUPPLICANT_WPS_STATE_FAIL)
2676 /* Unlike normal connection, being associated while processing wps
2677 * actually means that we are idling. */
2678 switch (wifi->state) {
2679 case G_SUPPLICANT_STATE_UNKNOWN:
2680 case G_SUPPLICANT_STATE_DISABLED:
2681 case G_SUPPLICANT_STATE_DISCONNECTED:
2682 case G_SUPPLICANT_STATE_INACTIVE:
2683 case G_SUPPLICANT_STATE_SCANNING:
2684 case G_SUPPLICANT_STATE_ASSOCIATED:
2686 case G_SUPPLICANT_STATE_AUTHENTICATING:
2687 case G_SUPPLICANT_STATE_ASSOCIATING:
2688 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2689 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2690 case G_SUPPLICANT_STATE_COMPLETED:
2697 static bool handle_wps_completion(GSupplicantInterface *interface,
2698 struct connman_network *network,
2699 struct connman_device *device,
2700 struct wifi_data *wifi)
2704 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2706 const unsigned char *ssid, *wps_ssid;
2707 unsigned int ssid_len, wps_ssid_len;
2708 const char *wps_key;
2710 /* Checking if we got associated with requested
2712 ssid = connman_network_get_blob(network, "WiFi.SSID",
2715 wps_ssid = g_supplicant_interface_get_wps_ssid(
2716 interface, &wps_ssid_len);
2718 if (!wps_ssid || wps_ssid_len != ssid_len ||
2719 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2720 connman_network_set_associating(network, false);
2721 #if defined TIZEN_EXT
2722 g_supplicant_interface_disconnect(wifi->interface,
2723 disconnect_callback, wifi->network);
2725 connman_network_set_bool(network, "WiFi.UseWPS", false);
2726 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2728 g_supplicant_interface_disconnect(wifi->interface,
2729 disconnect_callback, wifi);
2734 wps_key = g_supplicant_interface_get_wps_key(interface);
2735 #if defined TIZEN_EXT
2736 /* Check the passphrase and encrypt it
2739 gchar *passphrase = g_strdup(wps_key);
2741 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2743 if (check_passphrase_ext(network, passphrase) < 0) {
2744 DBG("[WPS] Invalid passphrase");
2749 ret = send_encryption_request(passphrase, network);
2754 DBG("[WPS] Encryption request succeeded");
2756 DBG("[WPS] Encryption request failed %d", ret);
2759 connman_network_set_string(network, "WiFi.Passphrase",
2762 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2769 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2770 struct connman_network *network,
2771 struct wifi_data *wifi)
2773 #if defined TIZEN_EXT
2774 const char *security;
2775 struct connman_service *service;
2777 if (wifi->connected)
2780 security = connman_network_get_string(network, "WiFi.Security");
2782 if (security && g_str_equal(security, "ieee8021x") == true &&
2783 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2785 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2790 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2793 struct connman_service *service;
2795 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2798 if (wifi->connected)
2802 service = connman_service_lookup_from_network(network);
2808 if (connman_service_get_favorite(service)) {
2809 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2814 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2819 #if defined TIZEN_EXT
2820 static bool handle_wifi_assoc_retry(struct connman_network *network,
2821 struct wifi_data *wifi)
2823 const char *security;
2825 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2826 connman_network_get_connecting(network) != true) {
2827 wifi->assoc_retry_count = 0;
2831 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2832 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2833 wifi->assoc_retry_count = 0;
2837 security = connman_network_get_string(network, "WiFi.Security");
2838 if (security && g_str_equal(security, "ieee8021x") == true &&
2839 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2840 wifi->assoc_retry_count = 0;
2844 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2845 wifi->assoc_retry_count = 0;
2847 /* Honestly it's not an invalid-key error,
2848 * however QA team recommends that the invalid-key error
2849 * might be better to display for user experience.
2851 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2860 static void interface_state(GSupplicantInterface *interface)
2862 struct connman_network *network;
2863 struct connman_device *device;
2864 struct wifi_data *wifi;
2865 GSupplicantState state = g_supplicant_interface_get_state(interface);
2868 wifi = g_supplicant_interface_get_data(interface);
2870 DBG("wifi %p interface state %d", wifi, state);
2875 device = wifi->device;
2879 if (g_supplicant_interface_get_ready(interface) &&
2880 !wifi->interface_ready) {
2881 wifi->interface_ready = true;
2882 finalize_interface_creation(wifi);
2885 network = wifi->network;
2890 case G_SUPPLICANT_STATE_SCANNING:
2893 case G_SUPPLICANT_STATE_AUTHENTICATING:
2894 case G_SUPPLICANT_STATE_ASSOCIATING:
2895 #if defined TIZEN_EXT
2896 reset_autoscan(device);
2898 stop_autoscan(device);
2901 if (!wifi->connected)
2902 connman_network_set_associating(network, true);
2906 case G_SUPPLICANT_STATE_COMPLETED:
2907 #if defined TIZEN_EXT
2908 /* though it should be already reset: */
2909 reset_autoscan(device);
2911 wifi->assoc_retry_count = 0;
2913 wifi->scan_pending_network = NULL;
2915 /* should be cleared scanning flag */
2916 bool scanning = connman_device_get_scanning(device);
2918 connman_device_set_scanning(device,
2919 CONNMAN_SERVICE_TYPE_WIFI, false);
2920 connman_device_unref(device);
2923 /* though it should be already stopped: */
2924 stop_autoscan(device);
2927 if (!handle_wps_completion(interface, network, device, wifi))
2930 connman_network_set_connected(network, true);
2931 wifi->disconnect_code = 0;
2932 wifi->assoc_code = 0;
2935 case G_SUPPLICANT_STATE_DISCONNECTED:
2937 * If we're in one of the idle modes, we have
2938 * not started association yet and thus setting
2939 * those ones to FALSE could cancel an association
2942 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2944 if (is_idle_wps(interface, wifi))
2950 /* If previous state was 4way-handshake, then
2951 * it's either: psk was incorrect and thus we retry
2952 * or if we reach the maximum retries we declare the
2954 if (handle_4way_handshake_failure(interface,
2958 /* See table 8-36 Reason codes in IEEE Std 802.11 */
2959 switch (wifi->disconnect_code) {
2960 case 1: /* Unspecified reason */
2961 /* Let's assume it's because we got blocked */
2963 case 6: /* Class 2 frame received from nonauthenticated STA */
2964 connman_network_set_error(network,
2965 CONNMAN_NETWORK_ERROR_BLOCKED);
2973 /* We disable the selected network, if not then
2974 * wpa_supplicant will loop retrying */
2975 if (g_supplicant_interface_enable_selected_network(interface,
2977 DBG("Could not disables selected network");
2979 #if defined TIZEN_EXT
2982 err = g_supplicant_interface_remove_network(wifi->interface);
2984 DBG("Failed to remove network(%d)", err);
2987 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2988 * Retry association until its retry count is expired */
2989 if (handle_wifi_assoc_retry(network, wifi) == true) {
2990 throw_wifi_scan(wifi->device, scan_callback);
2991 wifi->scan_pending_network = wifi->network;
2995 if(wifi->disconnect_code > 0){
2996 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
2997 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
3000 /* To avoid unnecessary repeated association in wpa_supplicant,
3001 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
3002 if (wps != true && wifi->network && wifi->disconnecting == false) {
3003 wifi->disconnecting = true;
3004 err = g_supplicant_interface_disconnect(wifi->interface,
3005 disconnect_callback, wifi->network);
3007 wifi->disconnecting = false;
3009 connman_network_set_connected(network, false);
3010 connman_network_set_associating(network, false);
3012 start_autoscan(device);
3018 connman_network_set_connected(network, false);
3019 connman_network_set_associating(network, false);
3020 wifi->disconnecting = false;
3022 start_autoscan(device);
3026 case G_SUPPLICANT_STATE_INACTIVE:
3027 #if defined TIZEN_EXT
3028 if (handle_wps_completion(interface, network, device, wifi) == false)
3031 connman_network_set_associating(network, false);
3032 start_autoscan(device);
3036 case G_SUPPLICANT_STATE_UNKNOWN:
3037 case G_SUPPLICANT_STATE_DISABLED:
3038 case G_SUPPLICANT_STATE_ASSOCIATED:
3039 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3040 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3044 wifi->state = state;
3046 /* Saving wpa_s state policy:
3047 * If connected and if the state changes are roaming related:
3048 * --> We stay connected
3050 * --> We are connected
3052 * --> We are not connected
3055 #if defined TIZEN_EXT
3056 case G_SUPPLICANT_STATE_SCANNING:
3059 case G_SUPPLICANT_STATE_AUTHENTICATING:
3060 case G_SUPPLICANT_STATE_ASSOCIATING:
3061 case G_SUPPLICANT_STATE_ASSOCIATED:
3062 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3063 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3064 if (wifi->connected)
3065 connman_warn("Probably roaming right now!"
3066 " Staying connected...");
3068 wifi->connected = false;
3070 case G_SUPPLICANT_STATE_COMPLETED:
3071 wifi->connected = true;
3074 wifi->connected = false;
3081 static void interface_removed(GSupplicantInterface *interface)
3083 const char *ifname = g_supplicant_interface_get_ifname(interface);
3084 struct wifi_data *wifi;
3086 DBG("ifname %s", ifname);
3088 wifi = g_supplicant_interface_get_data(interface);
3091 wifi->interface = NULL;
3093 if (wifi && wifi->tethering)
3096 if (!wifi || !wifi->device) {
3097 DBG("wifi interface already removed");
3101 connman_device_set_powered(wifi->device, false);
3103 check_p2p_technology();
3106 static void set_device_type(const char *type, char dev_type[17])
3108 const char *oui = "0050F204";
3109 const char *category = "0100";
3110 const char *sub_category = "0000";
3112 if (!g_strcmp0(type, "handset")) {
3114 sub_category = "0500";
3115 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
3116 sub_category = "0100";
3117 else if (!g_strcmp0(type, "server"))
3118 sub_category = "0200";
3119 else if (!g_strcmp0(type, "laptop"))
3120 sub_category = "0500";
3121 else if (!g_strcmp0(type, "desktop"))
3122 sub_category = "0600";
3123 else if (!g_strcmp0(type, "tablet"))
3124 sub_category = "0900";
3125 else if (!g_strcmp0(type, "watch"))
3128 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
3131 static void p2p_support(GSupplicantInterface *interface)
3133 char dev_type[17] = {};
3134 const char *hostname;
3138 if (!g_supplicant_interface_has_p2p(interface))
3141 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
3142 DBG("Could not register P2P technology driver");
3146 hostname = connman_utsname_get_hostname();
3148 hostname = "ConnMan";
3150 set_device_type(connman_machine_get_type(), dev_type);
3151 g_supplicant_interface_set_p2p_device_config(interface,
3152 hostname, dev_type);
3153 connman_peer_driver_register(&peer_driver);
3156 static void scan_started(GSupplicantInterface *interface)
3161 static void scan_finished(GSupplicantInterface *interface)
3163 #if defined TIZEN_EXT
3164 struct wifi_data *wifi;
3165 bool is_associating = false;
3166 static bool is_scanning = true;
3171 #if defined TIZEN_EXT
3172 wifi = g_supplicant_interface_get_data(interface);
3173 if (wifi && wifi->scan_pending_network) {
3174 network_connect(wifi->scan_pending_network);
3175 wifi->scan_pending_network = NULL;
3178 //service state - associating
3179 if(!wifi || !wifi->network)
3182 is_associating = connman_network_get_associating(wifi->network);
3183 if(is_associating && is_scanning){
3184 is_scanning = false;
3185 DBG("send scan for connecting");
3186 throw_wifi_scan(wifi->device, scan_callback);
3197 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3199 unsigned char strength;
3201 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3203 #if !defined TIZEN_EXT
3210 static void network_added(GSupplicantNetwork *supplicant_network)
3212 struct connman_network *network;
3213 GSupplicantInterface *interface;
3214 struct wifi_data *wifi;
3215 const char *name, *identifier, *security, *group, *mode;
3216 const unsigned char *ssid;
3217 unsigned int ssid_len;
3221 bool wps_advertizing;
3223 #if defined TIZEN_EXT
3224 GSList *vsie_list = NULL;
3227 mode = g_supplicant_network_get_mode(supplicant_network);
3228 identifier = g_supplicant_network_get_identifier(supplicant_network);
3230 DBG("%s", identifier);
3232 if (!g_strcmp0(mode, "adhoc"))
3235 interface = g_supplicant_network_get_interface(supplicant_network);
3236 wifi = g_supplicant_interface_get_data(interface);
3237 name = g_supplicant_network_get_name(supplicant_network);
3238 security = g_supplicant_network_get_security(supplicant_network);
3239 group = g_supplicant_network_get_identifier(supplicant_network);
3240 wps = g_supplicant_network_get_wps(supplicant_network);
3241 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3242 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3243 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3244 supplicant_network);
3249 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3251 network = connman_device_get_network(wifi->device, identifier);
3254 network = connman_network_create(identifier,
3255 CONNMAN_NETWORK_TYPE_WIFI);
3259 connman_network_set_index(network, wifi->index);
3261 if (connman_device_add_network(wifi->device, network) < 0) {
3262 connman_network_unref(network);
3266 wifi->networks = g_slist_prepend(wifi->networks, network);
3269 if (name && name[0] != '\0')
3270 connman_network_set_name(network, name);
3272 connman_network_set_blob(network, "WiFi.SSID",
3274 #if defined TIZEN_EXT
3275 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
3277 connman_network_set_vsie_list(network, vsie_list);
3279 DBG("vsie_list is NULL");
3281 connman_network_set_string(network, "WiFi.Security", security);
3282 connman_network_set_strength(network,
3283 calculate_strength(supplicant_network));
3284 connman_network_set_bool(network, "WiFi.WPS", wps);
3287 /* Is AP advertizing for WPS association?
3288 * If so, we decide to use WPS by default */
3289 if (wps_ready && wps_pbc &&
3291 #if !defined TIZEN_EXT
3292 connman_network_set_bool(network, "WiFi.UseWPS", true);
3294 DBG("wps is activating by ap but ignore it.");
3299 connman_network_set_frequency(network,
3300 g_supplicant_network_get_frequency(supplicant_network));
3301 #if defined TIZEN_EXT
3302 connman_network_set_bssid(network,
3303 g_supplicant_network_get_bssid(supplicant_network));
3304 connman_network_set_maxrate(network,
3305 g_supplicant_network_get_maxrate(supplicant_network));
3306 connman_network_set_enc_mode(network,
3307 g_supplicant_network_get_enc_mode(supplicant_network));
3308 connman_network_set_rsn_mode(network,
3309 g_supplicant_network_get_rsn_mode(supplicant_network));
3310 connman_network_set_keymgmt(network,
3311 g_supplicant_network_get_keymgmt(supplicant_network));
3312 connman_network_set_bool(network, "WiFi.HS20AP",
3313 g_supplicant_network_is_hs20AP(supplicant_network));
3315 connman_network_set_available(network, true);
3316 connman_network_set_string(network, "WiFi.Mode", mode);
3318 #if defined TIZEN_EXT
3323 connman_network_set_group(network, group);
3325 #if defined TIZEN_EXT
3326 if (wifi_first_scan == true)
3327 found_with_first_scan = true;
3330 if (wifi->hidden && ssid) {
3331 #if defined TIZEN_EXT
3332 if (network_security(wifi->hidden->security) ==
3333 network_security(security) &&
3335 if (!g_strcmp0(wifi->hidden->security, security) &&
3337 wifi->hidden->ssid_len == ssid_len &&
3338 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3339 connman_network_connect_hidden(network,
3340 wifi->hidden->identity,
3341 wifi->hidden->passphrase,
3342 wifi->hidden->user_data);
3343 wifi->hidden->user_data = NULL;
3344 hidden_free(wifi->hidden);
3345 wifi->hidden = NULL;
3350 static void network_removed(GSupplicantNetwork *network)
3352 GSupplicantInterface *interface;
3353 struct wifi_data *wifi;
3354 const char *name, *identifier;
3355 struct connman_network *connman_network;
3357 interface = g_supplicant_network_get_interface(network);
3358 wifi = g_supplicant_interface_get_data(interface);
3359 identifier = g_supplicant_network_get_identifier(network);
3360 name = g_supplicant_network_get_name(network);
3362 DBG("name %s", name);
3367 connman_network = connman_device_get_network(wifi->device, identifier);
3368 if (!connman_network)
3371 #if defined TIZEN_EXT
3372 if (connman_network == wifi->scan_pending_network)
3373 wifi->scan_pending_network = NULL;
3375 if (connman_network == wifi->pending_network)
3376 wifi->pending_network = NULL;
3378 if(connman_network_get_connecting(connman_network) == true){
3379 connman_network_set_connected(connman_network, false);
3383 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3385 connman_device_remove_network(wifi->device, connman_network);
3386 connman_network_unref(connman_network);
3389 static void network_changed(GSupplicantNetwork *network, const char *property)
3391 GSupplicantInterface *interface;
3392 struct wifi_data *wifi;
3393 const char *name, *identifier;
3394 struct connman_network *connman_network;
3396 #if defined TIZEN_EXT
3397 const unsigned char *bssid;
3398 unsigned int maxrate;
3403 interface = g_supplicant_network_get_interface(network);
3404 wifi = g_supplicant_interface_get_data(interface);
3405 identifier = g_supplicant_network_get_identifier(network);
3406 name = g_supplicant_network_get_name(network);
3408 DBG("name %s", name);
3413 connman_network = connman_device_get_network(wifi->device, identifier);
3414 if (!connman_network)
3417 if (g_str_equal(property, "Signal")) {
3418 connman_network_set_strength(connman_network,
3419 calculate_strength(network));
3420 connman_network_update(connman_network);
3423 #if defined TIZEN_EXT
3424 bssid = g_supplicant_network_get_bssid(network);
3425 maxrate = g_supplicant_network_get_maxrate(network);
3426 frequency = g_supplicant_network_get_frequency(network);
3427 wps = g_supplicant_network_get_wps(network);
3429 connman_network_set_bssid(connman_network, bssid);
3430 connman_network_set_maxrate(connman_network, maxrate);
3431 connman_network_set_frequency(connman_network, frequency);
3432 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3436 static void apply_peer_services(GSupplicantPeer *peer,
3437 struct connman_peer *connman_peer)
3439 const unsigned char *data;
3444 connman_peer_reset_services(connman_peer);
3446 data = g_supplicant_peer_get_widi_ies(peer, &length);
3448 connman_peer_add_service(connman_peer,
3449 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3453 static void add_station(const char *mac)
3455 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3459 static void remove_station(const char *mac)
3461 connman_technology_tethering_remove_station(mac);
3464 static void peer_found(GSupplicantPeer *peer)
3466 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3467 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3468 struct connman_peer *connman_peer;
3469 const char *identifier, *name;
3471 #if defined TIZEN_EXT
3475 identifier = g_supplicant_peer_get_identifier(peer);
3476 name = g_supplicant_peer_get_name(peer);
3478 DBG("ident: %s", identifier);
3480 connman_peer = connman_peer_get(wifi->device, identifier);
3484 connman_peer = connman_peer_create(identifier);
3485 connman_peer_set_name(connman_peer, name);
3486 connman_peer_set_device(connman_peer, wifi->device);
3487 apply_peer_services(peer, connman_peer);
3489 ret = connman_peer_register(connman_peer);
3490 if (ret < 0 && ret != -EALREADY)
3491 connman_peer_unref(connman_peer);
3494 static void peer_lost(GSupplicantPeer *peer)
3496 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3497 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3498 struct connman_peer *connman_peer;
3499 const char *identifier;
3504 identifier = g_supplicant_peer_get_identifier(peer);
3506 DBG("ident: %s", identifier);
3508 connman_peer = connman_peer_get(wifi->device, identifier);
3510 if (wifi->p2p_connecting &&
3511 wifi->pending_peer == connman_peer) {
3512 peer_connect_timeout(wifi);
3514 connman_peer_unregister(connman_peer);
3515 connman_peer_unref(connman_peer);
3519 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3521 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3522 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3523 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3524 struct connman_peer *connman_peer;
3525 const char *identifier;
3527 #if defined TIZEN_EXT
3532 identifier = g_supplicant_peer_get_identifier(peer);
3534 DBG("ident: %s", identifier);
3536 connman_peer = connman_peer_get(wifi->device, identifier);
3541 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3542 apply_peer_services(peer, connman_peer);
3543 connman_peer_services_changed(connman_peer);
3545 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3546 if (!g_supplicant_peer_is_in_a_group(peer))
3547 p_state = CONNMAN_PEER_STATE_IDLE;
3549 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3551 case G_SUPPLICANT_PEER_GROUP_STARTED:
3553 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3554 p_state = CONNMAN_PEER_STATE_IDLE;
3556 case G_SUPPLICANT_PEER_GROUP_JOINED:
3557 connman_peer_set_iface_address(connman_peer,
3558 g_supplicant_peer_get_iface_address(peer));
3560 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3561 p_state = CONNMAN_PEER_STATE_IDLE;
3563 case G_SUPPLICANT_PEER_GROUP_FAILED:
3564 if (g_supplicant_peer_has_requested_connection(peer))
3565 p_state = CONNMAN_PEER_STATE_IDLE;
3567 p_state = CONNMAN_PEER_STATE_FAILURE;
3571 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3572 p_state == CONNMAN_PEER_STATE_FAILURE) {
3573 if (wifi->p2p_connecting
3574 && connman_peer == wifi->pending_peer)
3575 peer_cancel_timeout(wifi);
3577 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3580 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3583 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3584 GSupplicantInterface *g_iface;
3585 struct wifi_data *g_wifi;
3587 g_iface = g_supplicant_peer_get_group_interface(peer);
3591 g_wifi = g_supplicant_interface_get_data(g_iface);
3595 connman_peer_set_as_master(connman_peer,
3596 !g_supplicant_peer_is_client(peer));
3597 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3600 connman_peer_set_state(connman_peer, p_state);
3603 static void peer_request(GSupplicantPeer *peer)
3605 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3606 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3607 struct connman_peer *connman_peer;
3608 const char *identifier;
3610 #if defined TIZEN_EXT
3615 identifier = g_supplicant_peer_get_identifier(peer);
3617 DBG("ident: %s", identifier);
3619 connman_peer = connman_peer_get(wifi->device, identifier);
3623 connman_peer_request_connection(connman_peer);
3626 #if defined TIZEN_EXT
3627 static void system_power_off(void)
3630 struct wifi_data *wifi;
3631 struct connman_service *service;
3632 struct connman_ipconfig *ipconfig_ipv4;
3634 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3635 for (list = iface_list; list; list = list->next) {
3638 if (wifi->network != NULL) {
3639 service = connman_service_lookup_from_network(wifi->network);
3640 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3641 __connman_dhcp_stop(ipconfig_ipv4);
3647 static void network_merged(GSupplicantNetwork *network)
3649 GSupplicantInterface *interface;
3650 GSupplicantState state;
3651 struct wifi_data *wifi;
3652 const char *identifier;
3653 struct connman_network *connman_network;
3657 interface = g_supplicant_network_get_interface(network);
3661 state = g_supplicant_interface_get_state(interface);
3662 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3665 wifi = g_supplicant_interface_get_data(interface);
3669 identifier = g_supplicant_network_get_identifier(network);
3671 connman_network = connman_device_get_network(wifi->device, identifier);
3672 if (!connman_network)
3675 DBG("merged identifier %s", identifier);
3677 if (wifi->connected == FALSE) {
3679 case G_SUPPLICANT_STATE_AUTHENTICATING:
3680 case G_SUPPLICANT_STATE_ASSOCIATING:
3681 case G_SUPPLICANT_STATE_ASSOCIATED:
3682 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3683 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3684 connman_network_set_associating(connman_network, TRUE);
3686 case G_SUPPLICANT_STATE_COMPLETED:
3687 connman_network_set_connected(connman_network, TRUE);
3690 DBG("Not handled the state : %d", state);
3695 ishs20AP = g_supplicant_network_is_hs20AP(network);
3698 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3699 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3700 connman_network_set_string(connman_network, "WiFi.EAP",
3702 connman_network_set_string(connman_network, "WiFi.Identity",
3703 g_supplicant_network_get_identity(network));
3704 connman_network_set_string(connman_network, "WiFi.Phase2",
3705 g_supplicant_network_get_phase2(network));
3710 wifi->network = connman_network;
3713 static void assoc_failed(void *user_data)
3715 struct connman_network *network = user_data;
3716 connman_network_set_associating(network, false);
3720 static void debug(const char *str)
3722 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3723 connman_debug("%s", str);
3726 static void disconnect_reasoncode(GSupplicantInterface *interface,
3729 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3731 wifi->disconnect_code = reasoncode;
3735 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
3737 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3739 #if defined TIZEN_EXT
3740 struct connman_network *network;
3744 wifi->assoc_code = status_code;
3746 #if defined TIZEN_EXT
3747 network = wifi->network;
3748 connman_network_set_assoc_status_code(network,status_code);
3754 static const GSupplicantCallbacks callbacks = {
3755 .system_ready = system_ready,
3756 .system_killed = system_killed,
3757 .interface_added = interface_added,
3758 .interface_state = interface_state,
3759 .interface_removed = interface_removed,
3760 .p2p_support = p2p_support,
3761 .scan_started = scan_started,
3762 .scan_finished = scan_finished,
3763 .network_added = network_added,
3764 .network_removed = network_removed,
3765 .network_changed = network_changed,
3766 .add_station = add_station,
3767 .remove_station = remove_station,
3768 .peer_found = peer_found,
3769 .peer_lost = peer_lost,
3770 .peer_changed = peer_changed,
3771 .peer_request = peer_request,
3772 #if defined TIZEN_EXT
3773 .system_power_off = system_power_off,
3774 .network_merged = network_merged,
3775 .assoc_failed = assoc_failed,
3777 .disconnect_reasoncode = disconnect_reasoncode,
3778 .assoc_status_code = assoc_status_code,
3783 static int tech_probe(struct connman_technology *technology)
3785 wifi_technology = technology;
3790 static void tech_remove(struct connman_technology *technology)
3792 wifi_technology = NULL;
3795 struct wifi_tethering_info {
3796 struct wifi_data *wifi;
3797 struct connman_technology *technology;
3799 GSupplicantSSID *ssid;
3802 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3803 const char *passphrase, bool hidden)
3805 GSupplicantSSID *ap;
3807 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3811 ap->mode = G_SUPPLICANT_MODE_MASTER;
3813 ap->ssid_len = strlen(ssid);
3817 if (!passphrase || strlen(passphrase) == 0) {
3818 ap->security = G_SUPPLICANT_SECURITY_NONE;
3819 ap->passphrase = NULL;
3821 ap->security = G_SUPPLICANT_SECURITY_PSK;
3822 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3823 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3824 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3825 ap->passphrase = passphrase;
3829 ap->ignore_broadcast_ssid =
3830 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3832 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3837 static void ap_start_callback(int result, GSupplicantInterface *interface,
3840 struct wifi_tethering_info *info = user_data;
3842 DBG("result %d index %d bridge %s",
3843 result, info->wifi->index, info->wifi->bridge);
3846 connman_inet_remove_from_bridge(info->wifi->index,
3847 info->wifi->bridge);
3848 connman_technology_tethering_notify(info->technology, false);
3851 g_free(info->ifname);
3855 static void ap_create_callback(int result,
3856 GSupplicantInterface *interface,
3859 struct wifi_tethering_info *info = user_data;
3861 DBG("result %d ifname %s", result,
3862 g_supplicant_interface_get_ifname(interface));
3865 connman_inet_remove_from_bridge(info->wifi->index,
3866 info->wifi->bridge);
3867 connman_technology_tethering_notify(info->technology, false);
3869 g_free(info->ifname);
3875 info->wifi->interface = interface;
3876 g_supplicant_interface_set_data(interface, info->wifi);
3878 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3879 connman_error("Failed to set interface ap_scan property");
3881 g_supplicant_interface_connect(interface, info->ssid,
3882 ap_start_callback, info);
3885 static void sta_remove_callback(int result,
3886 GSupplicantInterface *interface,
3889 struct wifi_tethering_info *info = user_data;
3890 const char *driver = connman_option_get_string("wifi");
3892 DBG("ifname %s result %d ", info->ifname, result);
3895 info->wifi->tethering = true;
3897 g_free(info->ifname);
3903 info->wifi->interface = NULL;
3905 connman_technology_tethering_notify(info->technology, true);
3907 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3912 static int tech_set_tethering(struct connman_technology *technology,
3913 const char *identifier, const char *passphrase,
3914 const char *bridge, bool enabled, bool hidden)
3917 GSupplicantInterface *interface;
3918 struct wifi_data *wifi;
3919 struct wifi_tethering_info *info;
3927 for (list = iface_list; list; list = list->next) {
3930 if (wifi->tethering) {
3931 wifi->tethering = false;
3933 connman_inet_remove_from_bridge(wifi->index,
3935 wifi->bridged = false;
3939 connman_technology_tethering_notify(technology, false);
3944 for (list = iface_list; list; list = list->next) {
3947 interface = wifi->interface;
3952 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3954 mode = g_supplicant_interface_get_mode(interface);
3955 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3956 DBG("%s does not support AP mode", ifname);
3960 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3965 info->technology = technology;
3966 info->wifi->bridge = bridge;
3967 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3972 info->ifname = g_strdup(ifname);
3973 if (!info->ifname) {
3979 info->wifi->tethering = true;
3981 err = g_supplicant_interface_remove(interface,
3982 sta_remove_callback,
3991 static void regdom_callback(int result, const char *alpha2, void *user_data)
3995 if (!wifi_technology)
4001 connman_technology_regdom_notify(wifi_technology, alpha2);
4004 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
4006 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
4009 static struct connman_technology_driver tech_driver = {
4011 .type = CONNMAN_SERVICE_TYPE_WIFI,
4012 .probe = tech_probe,
4013 .remove = tech_remove,
4014 .set_tethering = tech_set_tethering,
4015 .set_regdom = tech_set_regdom,
4018 static int wifi_init(void)
4022 err = connman_network_driver_register(&network_driver);
4026 err = g_supplicant_register(&callbacks);
4028 connman_network_driver_unregister(&network_driver);
4032 err = connman_technology_driver_register(&tech_driver);
4034 g_supplicant_unregister(&callbacks);
4035 connman_network_driver_unregister(&network_driver);
4042 static void wifi_exit(void)
4046 connman_technology_driver_unregister(&tech_driver);
4048 g_supplicant_unregister(&callbacks);
4050 connman_network_driver_unregister(&network_driver);
4053 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
4054 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)