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