summaryrefslogtreecommitdiff
path: root/plugins/wifi.c
diff options
context:
space:
mode:
authorTomasz Bursztyka <tomasz.bursztyka@linux.intel.com>2012-04-23 11:22:16 +0300
committerPatrik Flykt <patrik.flykt@linux.intel.com>2012-04-23 13:49:45 +0300
commitc9759d3781dfdeb0a53531c42686ee58cd91c2c7 (patch)
tree83c1227e590352cd5255714e333b315b5a3ea2d6 /plugins/wifi.c
parent4d8856bf6328c5e59e114d8db338c53b6a88b1b8 (diff)
downloadconnman-c9759d3781dfdeb0a53531c42686ee58cd91c2c7.tar.gz
connman-c9759d3781dfdeb0a53531c42686ee58cd91c2c7.tar.bz2
connman-c9759d3781dfdeb0a53531c42686ee58cd91c2c7.zip
wifi: Adding support for autoscan emulation
Diffstat (limited to 'plugins/wifi.c')
-rw-r--r--plugins/wifi.c198
1 files changed, 182 insertions, 16 deletions
diff --git a/plugins/wifi.c b/plugins/wifi.c
index aea53ae7..cbc6cdb5 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -58,6 +58,7 @@
#define MAXIMUM_RETRIES 4
#define BGSCAN_DEFAULT "simple:30:-45:300"
+#define AUTOSCAN_DEFAULT "exponential:2:3600"
struct connman_technology *wifi_technology = NULL;
@@ -68,6 +69,17 @@ struct hidden_params {
char *passphrase;
};
+/**
+ * Used for autoscan "emulation".
+ * Should be removed when wpa_s autoscan support will be by default.
+ */
+struct autoscan_params {
+ int base;
+ int limit;
+ int interval;
+ unsigned int timeout;
+};
+
struct wifi_data {
char *identifier;
struct connman_device *device;
@@ -86,6 +98,10 @@ struct wifi_data {
unsigned int watch;
int retries;
struct hidden_params *hidden;
+ /**
+ * autoscan "emulation".
+ */
+ struct autoscan_params *autoscan;
};
static GList *iface_list = NULL;
@@ -185,6 +201,27 @@ static void remove_networks(struct connman_device *device,
wifi->networks = NULL;
}
+static void stop_autoscan(struct connman_device *device)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+ struct autoscan_params *autoscan;
+
+ DBG("");
+
+ if (wifi == NULL || wifi->autoscan == NULL)
+ return;
+
+ autoscan = wifi->autoscan;
+
+ if (autoscan->timeout > 0)
+ g_source_remove(autoscan->timeout);
+
+ autoscan->timeout = 0;
+ autoscan->interval = 0;
+
+ connman_device_unref(device);
+}
+
static void wifi_remove(struct connman_device *device)
{
struct wifi_data *wifi = connman_device_get_data(device);
@@ -194,6 +231,8 @@ 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);
@@ -205,10 +244,141 @@ static void wifi_remove(struct connman_device *device)
g_supplicant_interface_set_data(wifi->interface, NULL);
+ g_free(wifi->autoscan);
g_free(wifi->identifier);
g_free(wifi);
}
+static int throw_wifi_scan(struct connman_device *device,
+ GSupplicantInterfaceCallback callback)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+ int ret;
+
+ DBG("device %p %p", device, wifi->interface);
+
+ if (wifi->tethering == TRUE)
+ return 0;
+
+ connman_device_ref(device);
+
+ ret = g_supplicant_interface_scan(wifi->interface, NULL,
+ callback, device);
+ if (ret == 0)
+ connman_device_set_scanning(device, TRUE);
+ else
+ connman_device_unref(device);
+
+ return ret;
+}
+
+static void autoscan_scan_callback(int result,
+ GSupplicantInterface *interface, void *user_data)
+{
+ struct connman_device *device = user_data;
+
+ DBG("");
+
+ connman_device_set_scanning(device, FALSE);
+}
+
+static gboolean autoscan_timeout(gpointer data)
+{
+ struct connman_device *device = data;
+ struct wifi_data *wifi = connman_device_get_data(device);
+ struct autoscan_params *autoscan;
+ int interval;
+
+ autoscan = wifi->autoscan;
+
+ if (autoscan->interval <= 0) {
+ interval = autoscan->base;
+ goto set_interval;
+ } else
+ interval = autoscan->interval * autoscan->base;
+
+ if (autoscan->interval >= autoscan->limit)
+ interval = autoscan->limit;
+
+ throw_wifi_scan(wifi->device, autoscan_scan_callback);
+
+set_interval:
+ DBG("interval %d", interval);
+
+ autoscan->interval = interval;
+
+ autoscan->timeout = g_timeout_add_seconds(interval,
+ autoscan_timeout, device);
+
+ return FALSE;
+}
+
+static void start_autoscan(struct connman_device *device)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+ struct autoscan_params *autoscan;
+
+ DBG("");
+
+ if (wifi == NULL)
+ return;
+
+ autoscan = wifi->autoscan;
+ if (autoscan == NULL)
+ return;
+
+ if (autoscan->timeout > 0 || autoscan->interval > 0)
+ return;
+
+ connman_device_ref(device);
+
+ autoscan_timeout(device);
+}
+
+static struct autoscan_params *parse_autoscan_params(const char *params)
+{
+ struct autoscan_params *autoscan;
+ char **list_params;
+ int limit;
+ int base;
+
+ DBG("Emulating autoscan");
+
+ list_params = g_strsplit(params, ":", 0);
+ if (list_params == 0)
+ return NULL;
+
+ if (g_strv_length(list_params) < 3) {
+ g_strfreev(list_params);
+ return NULL;
+ }
+
+ base = atoi(list_params[1]);
+ limit = atoi(list_params[2]);
+
+ g_strfreev(list_params);
+
+ autoscan = g_try_malloc0(sizeof(struct autoscan_params));
+ if (autoscan == NULL) {
+ DBG("Could not allocate memory for autoscan");
+ return NULL;
+ }
+
+ DBG("base %d - limit %d", base, limit);
+ autoscan->base = base;
+ autoscan->limit = limit;
+
+ return autoscan;
+}
+
+static void setup_autoscan(struct wifi_data *wifi)
+{
+ if (wifi->autoscan == NULL)
+ wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
+
+ start_autoscan(wifi->device);
+}
+
static void interface_create_callback(int result,
GSupplicantInterface *interface,
void *user_data)
@@ -236,6 +406,9 @@ static void interface_create_callback(int result,
}
connman_device_set_powered(wifi->device, TRUE);
+
+ /* Setting up automatic scanning */
+ setup_autoscan(wifi);
}
static int wifi_enable(struct connman_device *device)
@@ -306,6 +479,8 @@ static void scan_callback(int result, GSupplicantInterface *interface,
connman_device_set_scanning(device, FALSE);
connman_device_unref(device);
+
+ start_autoscan(device);
}
static int add_scan_param(gchar *hex_ssid, int freq,
@@ -479,23 +654,9 @@ static int get_latest_connections(int max_ssids,
static int wifi_scan(struct connman_device *device)
{
- struct wifi_data *wifi = connman_device_get_data(device);
- int ret;
-
- DBG("device %p %p", device, wifi->interface);
-
- if (wifi->tethering == TRUE)
- return 0;
-
- connman_device_ref(device);
- ret = g_supplicant_interface_scan(wifi->interface, NULL,
- scan_callback, device);
- if (ret == 0)
- connman_device_set_scanning(device, TRUE);
- else
- connman_device_unref(device);
+ stop_autoscan(device);
- return ret;
+ return throw_wifi_scan(device, scan_callback);
}
static int wifi_scan_fast(struct connman_device *device)
@@ -526,6 +687,8 @@ static int wifi_scan_fast(struct connman_device *device)
return wifi_scan(device);
}
+ stop_autoscan(device);
+
connman_device_ref(device);
ret = g_supplicant_interface_scan(wifi->interface, scan_params,
scan_callback, device);
@@ -574,6 +737,8 @@ static int wifi_scan_hidden(struct connman_device *device,
hidden->passphrase = g_strdup(passphrase);
wifi->hidden = hidden;
+ stop_autoscan(device);
+
connman_device_ref(device);
ret = g_supplicant_interface_scan(wifi->interface, scan_params,
scan_callback, device);
@@ -801,6 +966,7 @@ static void disconnect_callback(int result, GSupplicantInterface *interface,
wifi->pending_network = NULL;
}
+ start_autoscan(wifi->device);
}
static int network_disconnect(struct connman_network *network)