summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohamed Abbas <mabbas@linux.intel.com>2010-12-20 11:07:33 -0800
committerSamuel Ortiz <sameo@linux.intel.com>2010-12-23 12:45:09 +0100
commit43e6e141ee352e77fdb894b918f280024785f3df (patch)
treee47d8aaa80c33ccd173cac0234c8b9404519264c
parent54deac67cf2bfdf33a267e96d9159ea10c10518e (diff)
downloadconnman-43e6e141ee352e77fdb894b918f280024785f3df.tar.gz
connman-43e6e141ee352e77fdb894b918f280024785f3df.tar.bz2
connman-43e6e141ee352e77fdb894b918f280024785f3df.zip
wifi: Dont start new connection until disassociation completes
Make sure disconnect is completed before start new connection otherwise we will disconnect the new network when we receive DISCONNECT signal from supplicant.
-rw-r--r--plugins/wifi.c83
1 files changed, 64 insertions, 19 deletions
diff --git a/plugins/wifi.c b/plugins/wifi.c
index 7b629e95..64322fdd 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -60,8 +60,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;
@@ -144,6 +146,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);
@@ -163,6 +166,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);
@@ -224,6 +232,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,
@@ -520,22 +534,6 @@ static void connect_callback(int result, GSupplicantInterface *interface,
connman_error("%s", __func__);
}
-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;
- }
-
- connman_network_unref(wifi->network);
-
- wifi->network = NULL;
-}
-
-
static GSupplicantSecurity network_security(const char *security)
{
if (g_str_equal(security, "none") == TRUE)
@@ -612,16 +610,54 @@ 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 void disconnect_callback(int result, GSupplicantInterface *interface,
+ void *user_data)
+{
+ struct wifi_data *wifi = user_data;
+
+ 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);
+ }
+
+ 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;
+ }
+
}
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);
@@ -631,8 +667,17 @@ 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;
+
+ wifi->disconnecting = TRUE;
+
+ err = g_supplicant_interface_disconnect(wifi->interface,
disconnect_callback, wifi);
+ if (err < 0)
+ wifi->disconnecting = FALSE;
+
+ return err;
}
static struct connman_network_driver network_driver = {