Add automatic scanning support
Like bgscan, autoscan is an optional module based feature to automate scanning but while disconnected or inactive. Instead of requesting directly a scan, it only sets the scan_interval and the sched_scan_interval. So, if the driver supports sched_scan, autoscan will be able to tweak its interval. Otherwise, the tweaked scan_interval will be used. If scan parameters needs to be tweaked, an autoscan_params pointer in wpa_s will provide those. So req_scan / req_sched_scan will not set the scan parameters as they usually do, but instead will use this pointer. Modules will not have to request a scan directly, like bgscan does. Instead, it will need to return the interval it wants after each notification. Signed-hostap: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
parent
b0786fba71
commit
7c865c6853
10 changed files with 252 additions and 4 deletions
|
@ -1304,6 +1304,11 @@ L_CFLAGS += -DCONFIG_BGSCAN
|
|||
OBJS += bgscan.c
|
||||
endif
|
||||
|
||||
ifdef NEED_AUTOSCAN
|
||||
L_CFLAGS += -DCONFIG_AUTOSCAN
|
||||
OBJS += autoscan.c
|
||||
endif
|
||||
|
||||
ifdef NEED_GAS
|
||||
OBJS += ../src/common/gas.c
|
||||
OBJS += gas_query.c
|
||||
|
|
|
@ -1321,6 +1321,11 @@ CFLAGS += -DCONFIG_BGSCAN
|
|||
OBJS += bgscan.o
|
||||
endif
|
||||
|
||||
ifdef NEED_AUTOSCAN
|
||||
CFLAGS += -DCONFIG_AUTOSCAN
|
||||
OBJS += autoscan.o
|
||||
endif
|
||||
|
||||
ifdef NEED_GAS
|
||||
OBJS += ../src/common/gas.o
|
||||
OBJS += gas_query.o
|
||||
|
|
127
wpa_supplicant/autoscan.c
Normal file
127
wpa_supplicant/autoscan.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* WPA Supplicant - auto scan
|
||||
* Copyright (c) 2012, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "bss.h"
|
||||
#include "scan.h"
|
||||
#include "autoscan.h"
|
||||
|
||||
static const struct autoscan_ops * autoscan_modules[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static void request_scan(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
wpa_s->scan_req = 2;
|
||||
|
||||
if (wpa_supplicant_req_sched_scan(wpa_s))
|
||||
wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval, 0);
|
||||
}
|
||||
|
||||
|
||||
int autoscan_init(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
const char *name = wpa_s->conf->autoscan;
|
||||
const char *params;
|
||||
size_t nlen;
|
||||
int i;
|
||||
const struct autoscan_ops *ops = NULL;
|
||||
|
||||
if (wpa_s->autoscan && wpa_s->autoscan_priv)
|
||||
return 0;
|
||||
|
||||
if (name == NULL)
|
||||
return 0;
|
||||
|
||||
params = os_strchr(name, ':');
|
||||
if (params == NULL) {
|
||||
params = "";
|
||||
nlen = os_strlen(name);
|
||||
} else {
|
||||
nlen = params - name;
|
||||
params++;
|
||||
}
|
||||
|
||||
for (i = 0; autoscan_modules[i]; i++) {
|
||||
if (os_strncmp(name, autoscan_modules[i]->name, nlen) == 0) {
|
||||
ops = autoscan_modules[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ops == NULL) {
|
||||
wpa_printf(MSG_ERROR, "autoscan: Could not find module "
|
||||
"matching the parameter '%s'", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_s->autoscan_params = NULL;
|
||||
|
||||
wpa_s->autoscan_priv = ops->init(wpa_s, params);
|
||||
if (wpa_s->autoscan_priv == NULL)
|
||||
return -1;
|
||||
wpa_s->autoscan = ops;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "autoscan: Initialized module '%s' with "
|
||||
"parameters '%s'", ops->name, params);
|
||||
|
||||
/*
|
||||
* Cancelling existing scan requests, if any.
|
||||
*/
|
||||
wpa_supplicant_cancel_sched_scan(wpa_s);
|
||||
wpa_supplicant_cancel_scan(wpa_s);
|
||||
|
||||
/*
|
||||
* Firing first scan, which will lead to call autoscan_notify_scan.
|
||||
*/
|
||||
request_scan(wpa_s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void autoscan_deinit(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (wpa_s->autoscan && wpa_s->autoscan_priv) {
|
||||
wpa_printf(MSG_DEBUG, "autoscan: Deinitializing module '%s'",
|
||||
wpa_s->autoscan->name);
|
||||
wpa_s->autoscan->deinit(wpa_s->autoscan_priv);
|
||||
wpa_s->autoscan = NULL;
|
||||
wpa_s->autoscan_priv = NULL;
|
||||
|
||||
wpa_s->scan_interval = 5;
|
||||
wpa_s->sched_scan_interval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int autoscan_notify_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
int interval;
|
||||
|
||||
if (wpa_s->autoscan && wpa_s->autoscan_priv) {
|
||||
interval = wpa_s->autoscan->notify_scan(wpa_s->autoscan_priv,
|
||||
scan_res);
|
||||
|
||||
if (interval <= 0)
|
||||
return -1;
|
||||
|
||||
wpa_s->scan_interval = interval;
|
||||
wpa_s->sched_scan_interval = interval;
|
||||
|
||||
request_scan(wpa_s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
49
wpa_supplicant/autoscan.h
Normal file
49
wpa_supplicant/autoscan.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* WPA Supplicant - auto scan
|
||||
* Copyright (c) 2012, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef AUTOSCAN_H
|
||||
#define AUTOSCAN_H
|
||||
|
||||
struct wpa_supplicant;
|
||||
|
||||
struct autoscan_ops {
|
||||
const char *name;
|
||||
|
||||
void * (*init)(struct wpa_supplicant *wpa_s, const char *params);
|
||||
void (*deinit)(void *priv);
|
||||
|
||||
int (*notify_scan)(void *priv, struct wpa_scan_results *scan_res);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_AUTOSCAN
|
||||
|
||||
int autoscan_init(struct wpa_supplicant *wpa_s);
|
||||
void autoscan_deinit(struct wpa_supplicant *wpa_s);
|
||||
int autoscan_notify_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_results *scan_res);
|
||||
|
||||
#else /* CONFIG_AUTOSCAN */
|
||||
|
||||
static inline int autoscan_init(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void autoscan_deinit(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int autoscan_notify_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_AUTOSCAN */
|
||||
|
||||
#endif /* AUTOSCAN_H */
|
|
@ -28,6 +28,7 @@
|
|||
#include "../bss.h"
|
||||
#include "../scan.h"
|
||||
#include "../ctrl_iface.h"
|
||||
#include "../autoscan.h"
|
||||
#include "dbus_new_helpers.h"
|
||||
#include "dbus_new.h"
|
||||
#include "dbus_new_handlers.h"
|
||||
|
@ -1287,6 +1288,9 @@ DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
|
|||
/* Add wildcard ssid */
|
||||
params.num_ssids++;
|
||||
}
|
||||
#ifdef CONFIG_AUTOSCAN
|
||||
autoscan_deinit(wpa_s);
|
||||
#endif /* CONFIG_AUTOSCAN */
|
||||
wpa_supplicant_trigger_scan(wpa_s, ¶ms);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
|
||||
|
|
|
@ -500,3 +500,8 @@ CONFIG_PEERKEY=y
|
|||
# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
|
||||
# more information on P2P operations.
|
||||
#CONFIG_P2P=y
|
||||
|
||||
# Autoscan
|
||||
# This can be used to enable automatic scan support in wpa_supplicant.
|
||||
# See wpa_supplicant.conf for more information on autoscan usage.
|
||||
#CONFIG_AUTOSCAN=y
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "gas_query.h"
|
||||
#include "p2p_supplicant.h"
|
||||
#include "bgscan.h"
|
||||
#include "autoscan.h"
|
||||
#include "ap.h"
|
||||
#include "bss.h"
|
||||
#include "scan.h"
|
||||
|
@ -1095,6 +1096,11 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (autoscan_notify_scan(wpa_s, scan_res)) {
|
||||
wpa_scan_results_free(scan_res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wpa_s->disconnected) {
|
||||
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
|
||||
wpa_scan_results_free(scan_res);
|
||||
|
|
|
@ -434,6 +434,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
|||
int scan_req = 0, ret;
|
||||
struct wpabuf *extra_ie;
|
||||
struct wpa_driver_scan_params params;
|
||||
struct wpa_driver_scan_params *scan_params;
|
||||
size_t max_ssids;
|
||||
enum wpa_states prev_state;
|
||||
|
||||
|
@ -499,6 +500,14 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
|||
wpa_s->wpa_state == WPA_INACTIVE)
|
||||
wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
|
||||
|
||||
/*
|
||||
* If autoscan has set its own scanning parameters
|
||||
*/
|
||||
if (wpa_s->autoscan_params != NULL) {
|
||||
scan_params = wpa_s->autoscan_params;
|
||||
goto scan;
|
||||
}
|
||||
|
||||
if (scan_req != 2 && wpa_s->connect_without_scan) {
|
||||
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
|
||||
if (ssid == wpa_s->connect_without_scan)
|
||||
|
@ -659,7 +668,10 @@ ssid_list_set:
|
|||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
ret = wpa_supplicant_trigger_scan(wpa_s, ¶ms);
|
||||
scan_params = ¶ms;
|
||||
|
||||
scan:
|
||||
ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
|
||||
|
||||
wpabuf_free(extra_ie);
|
||||
os_free(params.freqs);
|
||||
|
@ -748,8 +760,9 @@ int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
|
|||
int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct wpa_driver_scan_params params;
|
||||
struct wpa_driver_scan_params *scan_params;
|
||||
enum wpa_states prev_state;
|
||||
struct wpa_ssid *ssid;
|
||||
struct wpa_ssid *ssid = NULL;
|
||||
struct wpabuf *wps_ie = NULL;
|
||||
int ret;
|
||||
unsigned int max_sched_scan_ssids;
|
||||
|
@ -825,6 +838,11 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
|
|||
wpa_s->wpa_state == WPA_INACTIVE)
|
||||
wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
|
||||
|
||||
if (wpa_s->autoscan_params != NULL) {
|
||||
scan_params = wpa_s->autoscan_params;
|
||||
goto scan;
|
||||
}
|
||||
|
||||
/* Find the starting point from which to continue scanning */
|
||||
ssid = wpa_s->conf->ssid;
|
||||
if (wpa_s->prev_sched_ssid) {
|
||||
|
@ -840,7 +858,8 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
|
|||
if (!ssid || !wpa_s->prev_sched_ssid) {
|
||||
wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
|
||||
|
||||
wpa_s->sched_scan_interval = 10;
|
||||
if (wpa_s->sched_scan_interval == 0)
|
||||
wpa_s->sched_scan_interval = 10;
|
||||
wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
|
||||
wpa_s->first_sched_scan = 1;
|
||||
ssid = wpa_s->conf->ssid;
|
||||
|
@ -909,6 +928,9 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
|
|||
if (wpa_s->wps)
|
||||
wps_ie = wpa_supplicant_extra_ies(wpa_s, ¶ms);
|
||||
|
||||
scan_params = ¶ms;
|
||||
|
||||
scan:
|
||||
if (ssid || !wpa_s->first_sched_scan) {
|
||||
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||
"Starting sched scan: interval %d timeout %d",
|
||||
|
@ -919,7 +941,7 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
|
|||
wpa_s->sched_scan_interval);
|
||||
}
|
||||
|
||||
ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms,
|
||||
ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params,
|
||||
wpa_s->sched_scan_interval);
|
||||
wpabuf_free(wps_ie);
|
||||
os_free(params.filter_ssids);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "p2p_supplicant.h"
|
||||
#include "notify.h"
|
||||
#include "bgscan.h"
|
||||
#include "autoscan.h"
|
||||
#include "bss.h"
|
||||
#include "scan.h"
|
||||
#include "offchannel.h"
|
||||
|
@ -368,6 +369,7 @@ void free_hw_features(struct wpa_supplicant *wpa_s)
|
|||
static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
bgscan_deinit(wpa_s);
|
||||
autoscan_deinit(wpa_s);
|
||||
scard_deinit(wpa_s->scard);
|
||||
wpa_s->scard = NULL;
|
||||
wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
|
||||
|
@ -570,6 +572,19 @@ static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
|
|||
#endif /* CONFIG_BGSCAN */
|
||||
|
||||
|
||||
static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (autoscan_init(wpa_s))
|
||||
wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
autoscan_deinit(wpa_s);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_supplicant_set_state - Set current connection state
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
|
@ -630,6 +645,12 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
|
|||
wpa_supplicant_stop_bgscan(wpa_s);
|
||||
#endif /* CONFIG_BGSCAN */
|
||||
|
||||
if (state == WPA_AUTHENTICATING)
|
||||
wpa_supplicant_stop_autoscan(wpa_s);
|
||||
|
||||
if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
|
||||
wpa_supplicant_start_autoscan(wpa_s);
|
||||
|
||||
if (wpa_s->wpa_state != old_state) {
|
||||
wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
|
||||
|
||||
|
|
|
@ -538,6 +538,10 @@ struct wpa_supplicant {
|
|||
const struct bgscan_ops *bgscan;
|
||||
void *bgscan_priv;
|
||||
|
||||
const struct autoscan_ops *autoscan;
|
||||
struct wpa_driver_scan_params *autoscan_params;
|
||||
void *autoscan_priv;
|
||||
|
||||
struct wpa_ssid *connect_without_scan;
|
||||
|
||||
int after_wps;
|
||||
|
|
Loading…
Reference in a new issue