Make sure disconnect is completed before start new connection
otherwise we will disconnect the new network when we receive
DISCONNECT signal from supplicant.
---
 plugins/wifi.c |   62 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 54 insertions(+), 8 deletions(-)

diff --git a/plugins/wifi.c b/plugins/wifi.c
index b12aa06..6319bfa 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -57,8 +57,10 @@ struct wifi_data {
        char *identifier;
        struct connman_device *device;
        struct connman_network *network;
+       struct connman_network *pending_network;
        GSupplicantInterface *interface;
        connman_bool_t connected;
+       connman_bool_t disconnecting;
        int index;
        unsigned flags;
        unsigned int watch;
@@ -141,6 +143,7 @@ static int wifi_probe(struct connman_device *device)
                return -ENOMEM;
 
        wifi->connected = FALSE;
+       wifi->disconnecting = FALSE;
 
        connman_device_set_data(device, wifi);
        wifi->device = connman_device_ref(device);
@@ -160,6 +163,11 @@ static void wifi_remove(struct connman_device *device)
 
        DBG("device %p", device);
 
+       if (wifi->pending_network != NULL) {
+               connman_network_unref(wifi->pending_network);
+               wifi->pending_network = NULL;
+       }
+
        connman_device_set_data(device, NULL);
        connman_device_unref(wifi->device);
        connman_rtnl_remove_watch(wifi->watch);
@@ -221,6 +229,12 @@ static int wifi_disable(struct connman_device *device)
        DBG("device %p", device);
 
        wifi->connected = FALSE;
+       wifi->disconnecting = FALSE;
+
+       if (wifi->pending_network != NULL) {
+               connman_network_unref(wifi->pending_network);
+               wifi->pending_network = NULL;
+       }
 
        return g_supplicant_interface_remove(wifi->interface,
                                                interface_remove_callback,
@@ -508,19 +522,37 @@ static void connect_callback(int result, 
GSupplicantInterface *interface,
        connman_error("%s", __func__);
 }
 
+static int network_connect(struct connman_network *network);
+
 static void disconnect_callback(int result, GSupplicantInterface *interface,
                                                        void *user_data)
 {
        struct wifi_data *wifi = user_data;
 
-       if (result < 0) {
-               connman_error("%s", __func__);
-               return;
+       if (wifi->network != NULL) {
+               /*
+                * if result < 0 supplican return an error because
+                * the network is not current.
+                * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
+                * failed, call connman_network_set_connected to report
+                * disconnect is completed
+                */
+               if (result < 0)
+                       connman_network_set_connected(wifi->network, FALSE);
+
+               connman_network_unref(wifi->network);
        }
 
-       connman_network_unref(wifi->network);
-
        wifi->network = NULL;
+
+       wifi->disconnecting = FALSE;
+
+       if (wifi->pending_network != NULL) {
+               network_connect(wifi->pending_network);
+               connman_network_unref(wifi->pending_network);
+               wifi->pending_network = NULL;
+       }
+
 }
 
 
@@ -600,16 +632,23 @@ static int network_connect(struct connman_network 
*network)
 
        ssid_init(&ssid, network);
 
-       wifi->network = connman_network_ref(network);
+       if (wifi->disconnecting == TRUE)
+               wifi->pending_network = connman_network_ref(network);
+       else {
+               wifi->network = connman_network_ref(network);
 
-       return g_supplicant_interface_connect(interface, &ssid,
+               return g_supplicant_interface_connect(interface, &ssid,
                                                connect_callback, NULL);
+       }
+
+       return -EINPROGRESS;
 }
 
 static int network_disconnect(struct connman_network *network)
 {
        struct connman_device *device = connman_network_get_device(network);
        struct wifi_data *wifi;
+       int err;
 
        DBG("network %p", network);
 
@@ -619,8 +658,15 @@ static int network_disconnect(struct connman_network 
*network)
 
        connman_network_set_associating(network, FALSE);
 
-       return g_supplicant_interface_disconnect(wifi->interface,
+       if (wifi->disconnecting == TRUE)
+               return -EALREADY;
+
+       err = g_supplicant_interface_disconnect(wifi->interface,
                                                disconnect_callback, wifi);
+       if (err >= 0)
+               wifi->disconnecting = TRUE;
+
+       return err;
 }
 
 static struct connman_network_driver network_driver = {
-- 
1.7.2.3

_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to