From patchwork Wed Apr 4 06:40:00 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Bursztyka X-Patchwork-Id: 150607 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from maxx.maxx.shmoo.com (maxx.shmoo.com [205.134.188.171]) by ozlabs.org (Postfix) with ESMTP id 02964B6FC4 for ; Wed, 4 Apr 2012 16:39:16 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id E33179D2BB; Wed, 4 Apr 2012 02:39:14 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 4164WuO+3mFe; Wed, 4 Apr 2012 02:39:14 -0400 (EDT) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 3EEEC9D2C0; Wed, 4 Apr 2012 02:38:38 -0400 (EDT) X-Original-To: mailman-post+hostap@maxx.shmoo.com Delivered-To: mailman-post+hostap@maxx.shmoo.com Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 3F37817C00F for ; Wed, 4 Apr 2012 02:38:36 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id cqCOKhUjcDQJ for ; Wed, 4 Apr 2012 02:38:32 -0400 (EDT) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 7C2FB17C005 for ; Wed, 4 Apr 2012 02:38:30 -0400 (EDT) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 03 Apr 2012 23:38:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.67,351,1309762800"; d="scan'208";a="128488025" Received: from mriya.fi.intel.com ([10.237.68.33]) by orsmga002.jf.intel.com with ESMTP; 03 Apr 2012 23:38:29 -0700 From: Tomasz Bursztyka To: hostap@lists.shmoo.com Subject: [PATCH 3/5] Automatic Scanning support added Date: Wed, 4 Apr 2012 09:40:00 +0300 Message-Id: <1333521602-6216-4-git-send-email-tomasz.bursztyka@linux.intel.com> X-Mailer: git-send-email 1.7.8.5 In-Reply-To: <1333521602-6216-1-git-send-email-tomasz.bursztyka@linux.intel.com> References: <1333521602-6216-1-git-send-email-tomasz.bursztyka@linux.intel.com> Organization: Intel Finland Oy - BIC 0357606-4 - PL 281, 00181 Helsinki X-BeenThere: hostap@lists.shmoo.com X-Mailman-Version: 2.1.9 Precedence: list List-Id: HostAP Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: hostap-bounces@lists.shmoo.com Errors-To: hostap-bounces@lists.shmoo.com Like bgscan, autoscan is an optional module based feature to automate scanning but in all other states than 'completed' one (used by bgscan). 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. 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. --- wpa_supplicant/Makefile | 5 + wpa_supplicant/autoscan.c | 130 +++++++++++++++++++++++++++++++ wpa_supplicant/autoscan.h | 54 +++++++++++++ wpa_supplicant/dbus/dbus_new_handlers.c | 4 + wpa_supplicant/events.c | 6 ++ wpa_supplicant/scan.c | 3 +- wpa_supplicant/wpa_supplicant.c | 24 +++++- wpa_supplicant/wpa_supplicant_i.h | 3 + 8 files changed, 226 insertions(+), 3 deletions(-) create mode 100644 wpa_supplicant/autoscan.c create mode 100644 wpa_supplicant/autoscan.h diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 22df8a0..6128282 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1284,6 +1284,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 diff --git a/wpa_supplicant/autoscan.c b/wpa_supplicant/autoscan.c new file mode 100644 index 0000000..84e7546 --- /dev/null +++ b/wpa_supplicant/autoscan.c @@ -0,0 +1,130 @@ +/* + * WPA Supplicant - auto scan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING 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_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; +} diff --git a/wpa_supplicant/autoscan.h b/wpa_supplicant/autoscan.h new file mode 100644 index 0000000..4efb869 --- /dev/null +++ b/wpa_supplicant/autoscan.h @@ -0,0 +1,54 @@ +/* + * WPA Supplicant - auto scan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING 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 */ diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index b662fa4..8f4a5af 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -29,6 +29,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]: " diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 1c3b9eb..584f74e 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -41,6 +41,7 @@ #include "gas_query.h" #include "p2p_supplicant.h" #include "bgscan.h" +#include "autoscan.h" #include "ap.h" #include "bss.h" #include "scan.h" @@ -1086,6 +1087,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); diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index afa3be4..68f05ce 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -741,7 +741,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 = 2; + if (wpa_s->sched_scan_interval == 0) + wpa_s->sched_scan_interval = 2; wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2; wpa_s->first_sched_scan = 1; ssid = wpa_s->conf->ssid; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index ff54444..dc862a6 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -48,6 +48,7 @@ #include "p2p_supplicant.h" #include "notify.h" #include "bgscan.h" +#include "autoscan.h" #include "bss.h" #include "scan.h" #include "offchannel.h" @@ -389,6 +390,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); @@ -588,6 +590,21 @@ static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s) } +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 @@ -638,10 +655,13 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, } wpa_s->wpa_state = state; - if (state == WPA_COMPLETED) + if (state == WPA_COMPLETED) { + wpa_supplicant_stop_autoscan(wpa_s); wpa_supplicant_start_bgscan(wpa_s); - else + } else { wpa_supplicant_stop_bgscan(wpa_s); + 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); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 9698c68..abb64e8 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -484,6 +484,9 @@ struct wpa_supplicant { const struct bgscan_ops *bgscan; void *bgscan_priv; + const struct autoscan_ops *autoscan; + void *autoscan_priv; + struct wpa_ssid *connect_without_scan; int after_wps;