supplicant: Call scan callback if needed when removing interface
[framework/connectivity/connman.git] / plugins / wifi.c
index c303b6e..7cd5d81 100644 (file)
@@ -68,6 +68,7 @@ struct hidden_params {
        unsigned int ssid_len;
        char *identity;
        char *passphrase;
+       gpointer user_data;
 };
 
 /**
@@ -202,7 +203,7 @@ static void remove_networks(struct connman_device *device,
        wifi->networks = NULL;
 }
 
-static void stop_autoscan(struct connman_device *device)
+static void reset_autoscan(struct connman_device *device)
 {
        struct wifi_data *wifi = connman_device_get_data(device);
        struct autoscan_params *autoscan;
@@ -225,6 +226,13 @@ static void stop_autoscan(struct connman_device *device)
        connman_device_unref(device);
 }
 
+static void stop_autoscan(struct connman_device *device)
+{
+       reset_autoscan(device);
+
+       connman_device_set_scanning(device, FALSE);
+}
+
 static void wifi_remove(struct connman_device *device)
 {
        struct wifi_data *wifi = connman_device_get_data(device);
@@ -234,8 +242,6 @@ static void wifi_remove(struct connman_device *device)
        if (wifi == NULL)
                return;
 
-       stop_autoscan(device);
-
        iface_list = g_list_remove(iface_list, wifi);
 
        remove_networks(device, wifi);
@@ -399,6 +405,9 @@ static int throw_wifi_scan(struct connman_device *device,
        if (wifi->tethering == TRUE)
                return 0;
 
+       if (connman_device_get_scanning(device) == TRUE)
+               return -EALREADY;
+
        connman_device_ref(device);
 
        ret = g_supplicant_interface_scan(wifi->interface, NULL,
@@ -627,6 +636,14 @@ static int wifi_disable(struct connman_device *device)
        if (wifi->pending_network != NULL)
                wifi->pending_network = NULL;
 
+       stop_autoscan(device);
+
+       /* In case of a user scan, device is still referenced */
+       if (connman_device_get_scanning(device) == TRUE) {
+               connman_device_set_scanning(device, FALSE);
+               connman_device_unref(wifi->device);
+       }
+
        remove_networks(device, wifi);
 
        ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
@@ -655,6 +672,7 @@ static void scan_callback(int result, GSupplicantInterface *interface,
        DBG("result %d", result);
 
        if (wifi != NULL && wifi->hidden != NULL) {
+               connman_network_clear_hidden(wifi->hidden->user_data);
                hidden_free(wifi->hidden);
                wifi->hidden = NULL;
        }
@@ -799,7 +817,7 @@ static int get_latest_connections(int max_ssids,
 
 static int wifi_scan(struct connman_device *device)
 {
-       stop_autoscan(device);
+       reset_autoscan(device);
 
        return throw_wifi_scan(device, scan_callback);
 }
@@ -816,6 +834,9 @@ static int wifi_scan_fast(struct connman_device *device)
        if (wifi->tethering == TRUE)
                return 0;
 
+       if (connman_device_get_scanning(device) == TRUE)
+               return -EALREADY;
+
        driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
                                                        wifi->interface);
        DBG("max ssids %d", driver_max_ssids);
@@ -832,9 +853,9 @@ static int wifi_scan_fast(struct connman_device *device)
                return wifi_scan(device);
        }
 
-       stop_autoscan(device);
-
        connman_device_ref(device);
+       reset_autoscan(device);
+
        ret = g_supplicant_interface_scan(wifi->interface, scan_params,
                                                scan_callback, device);
        if (ret == 0)
@@ -853,7 +874,8 @@ static int wifi_scan_fast(struct connman_device *device)
  */
 static int wifi_scan_hidden(struct connman_device *device,
                const char *ssid, unsigned int ssid_len,
-               const char *identity, const char* passphrase)
+               const char *identity, const char* passphrase,
+               gpointer user_data)
 {
        struct wifi_data *wifi = connman_device_get_data(device);
        GSupplicantScanParams *scan_params = NULL;
@@ -869,6 +891,9 @@ static int wifi_scan_hidden(struct connman_device *device,
        if (ssid == NULL || ssid_len == 0 || ssid_len > 32)
                return -EINVAL;
 
+       if (connman_device_get_scanning(device) == TRUE)
+               return -EALREADY;
+
        scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
        if (scan_params == NULL)
                return -ENOMEM;
@@ -894,11 +919,13 @@ static int wifi_scan_hidden(struct connman_device *device,
        hidden->ssid_len = ssid_len;
        hidden->identity = g_strdup(identity);
        hidden->passphrase = g_strdup(passphrase);
+       hidden->user_data = user_data;
        wifi->hidden = hidden;
 
-       stop_autoscan(device);
-
        connman_device_ref(device);
+
+       reset_autoscan(device);
+
        ret = g_supplicant_interface_scan(wifi->interface, scan_params,
                        scan_callback, device);
        if (ret == 0)
@@ -1444,7 +1471,7 @@ static void interface_removed(GSupplicantInterface *interface)
                return;
 
        if (wifi == NULL || wifi->device == NULL) {
-               connman_error("Wrong wifi pointer");
+               DBG("wifi interface already removed");
                return;
        }
 
@@ -1551,13 +1578,15 @@ static void network_added(GSupplicantNetwork *supplicant_network)
        if (ssid != NULL)
                connman_network_set_group(network, group);
 
-       if (wifi->hidden != NULL) {
+       if (wifi->hidden != NULL && ssid != NULL) {
                if (wifi->hidden->ssid_len == ssid_len &&
                                memcmp(wifi->hidden->ssid, ssid,
                                                ssid_len) == 0) {
                        connman_network_connect_hidden(network,
                                        wifi->hidden->identity,
-                                       wifi->hidden->passphrase);
+                                       wifi->hidden->passphrase,
+                                       wifi->hidden->user_data);
+                       wifi->hidden->user_data = NULL;
                        hidden_free(wifi->hidden);
                        wifi->hidden = NULL;
                }