]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
bgscan: Add signal strength change events
authorJouni Malinen <j@w1.fi>
Sun, 28 Mar 2010 22:32:34 +0000 (15:32 -0700)
committerJouni Malinen <j@w1.fi>
Sun, 28 Mar 2010 22:32:34 +0000 (15:32 -0700)
This allows bgscan modules to use more information to decide on when
to perform background scans. bgscan_simple can now change between
short and long background scan intervals based on signal strength
and in addition, it can trigger immediate scans when the signal
strength is detected to be dropping.

bgscan_simple takes following parameters now:
short interval:signal strength threshold:long interval
For example:
bgscan="simple:30:-45:300"

wpa_supplicant/bgscan.c
wpa_supplicant/bgscan.h
wpa_supplicant/bgscan_simple.c
wpa_supplicant/events.c

index 60dcd0d67dc4ab26d185c33313613620b7455183..31b5d278f3e5dbd40796f6fd12d58eb8f8cbbd25 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - background scan and roaming interface
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
  *
  * 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
@@ -103,8 +103,8 @@ void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s)
 }
 
 
-void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s)
+void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above)
 {
        if (wpa_s->bgscan && wpa_s->bgscan_priv)
-               wpa_s->bgscan->notify_signal_change(wpa_s->bgscan_priv);
+               wpa_s->bgscan->notify_signal_change(wpa_s->bgscan_priv, above);
 }
index dfd4cab8a5bcccec8a2b7854b63a3c2a253b1c54..69e99b614cb2397fba27cd0640b79e8f5d69474f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - background scan and roaming interface
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
  *
  * 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
@@ -27,7 +27,7 @@ struct bgscan_ops {
 
        int (*notify_scan)(void *priv);
        void (*notify_beacon_loss)(void *priv);
-       void (*notify_signal_change)(void *priv);
+       void (*notify_signal_change)(void *priv, int above);
 };
 
 #ifdef CONFIG_BGSCAN
@@ -36,7 +36,7 @@ int bgscan_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
 void bgscan_deinit(struct wpa_supplicant *wpa_s);
 int bgscan_notify_scan(struct wpa_supplicant *wpa_s);
 void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s);
-void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s);
+void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above);
 
 #else /* CONFIG_BGSCAN */
 
@@ -59,7 +59,8 @@ static inline void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s)
 {
 }
 
-static inline void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s)
+static inline void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s,
+                                              int above)
 {
 }
 
index bf780d5e191d6e5d3e0fd5da95c602847f7e1c9a..a932553f49c8869048fbcc6406005d7cf6c9bb81 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - background scan and roaming module: simple
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
  *
  * 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
@@ -19,6 +19,7 @@
 #include "drivers/driver.h"
 #include "config_ssid.h"
 #include "wpa_supplicant_i.h"
+#include "driver_i.h"
 #include "scan.h"
 #include "bgscan.h"
 
@@ -26,6 +27,10 @@ struct bgscan_simple_data {
        struct wpa_supplicant *wpa_s;
        const struct wpa_ssid *ssid;
        int scan_interval;
+       int signal_threshold;
+       int short_interval; /* use if signal < threshold */
+       int long_interval; /* use if signal > threshold */
+       struct os_time last_bgscan;
 };
 
 
@@ -52,7 +57,36 @@ static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
                wpa_printf(MSG_DEBUG, "bgscan simple: Failed to trigger scan");
                eloop_register_timeout(data->scan_interval, 0,
                                       bgscan_simple_timeout, data, NULL);
+       } else
+               os_get_time(&data->last_bgscan);
+}
+
+
+static int bgscan_simple_get_params(struct bgscan_simple_data *data,
+                                   const char *params)
+{
+       const char *pos;
+
+       if (params == NULL)
+               return 0;
+
+       data->short_interval = atoi(params);
+
+       pos = os_strchr(params, ':');
+       if (pos == NULL)
+               return 0;
+       pos++;
+       data->signal_threshold = atoi(pos);
+       pos = os_strchr(pos, ':');
+       if (pos == NULL) {
+               wpa_printf(MSG_ERROR, "bgscan simple: Missing scan interval "
+                          "for high signal");
+               return -1;
        }
+       pos++;
+       data->long_interval = atoi(pos);
+
+       return 0;
 }
 
 
@@ -67,10 +101,27 @@ static void * bgscan_simple_init(struct wpa_supplicant *wpa_s,
                return NULL;
        data->wpa_s = wpa_s;
        data->ssid = ssid;
-       if (params)
-               data->scan_interval = atoi(params);
-       if (data->scan_interval <= 0)
-               data->scan_interval = 30;
+       if (bgscan_simple_get_params(data, params) < 0) {
+               os_free(data);
+               return NULL;
+       }
+       if (data->short_interval <= 0)
+               data->short_interval = 30;
+       if (data->long_interval <= 0)
+               data->long_interval = 30;
+
+       wpa_printf(MSG_DEBUG, "bgscan simple: Signal strength threshold %d  "
+                  "Short bgscan interval %d  Long bgscan interval %d",
+                  data->signal_threshold, data->short_interval,
+                  data->long_interval);
+
+       if (data->signal_threshold &&
+           wpa_drv_signal_monitor(wpa_s, data->signal_threshold, 4) < 0) {
+               wpa_printf(MSG_ERROR, "bgscan simple: Failed to enable "
+                          "signal strength monitoring");
+       }
+
+       data->scan_interval = data->short_interval;
        eloop_register_timeout(data->scan_interval, 0, bgscan_simple_timeout,
                               data, NULL);
        return data;
@@ -81,6 +132,8 @@ static void bgscan_simple_deinit(void *priv)
 {
        struct bgscan_simple_data *data = priv;
        eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
+       if (data->signal_threshold)
+               wpa_drv_signal_monitor(data->wpa_s, 0, 0);
        os_free(data);
 }
 
@@ -113,11 +166,46 @@ static void bgscan_simple_notify_beacon_loss(void *priv)
 }
 
 
-static void bgscan_simple_notify_signal_change(void *priv)
+static void bgscan_simple_notify_signal_change(void *priv, int above)
 {
-       wpa_printf(MSG_DEBUG, "bgscan simple: signal level changed");
-       /* TODO: if signal strength dropped enough, speed up background
-        * scanning */
+       struct bgscan_simple_data *data = priv;
+
+       if (data->short_interval == data->long_interval ||
+           data->signal_threshold == 0)
+               return;
+
+       wpa_printf(MSG_DEBUG, "bgscan simple: signal level changed "
+                  "(above=%d)", above);
+       if (data->scan_interval == data->long_interval && !above) {
+               wpa_printf(MSG_DEBUG, "bgscan simple: Trigger immediate scan "
+                          "and start using short bgscan interval");
+               data->scan_interval = data->short_interval;
+               eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
+               eloop_register_timeout(0, 0, bgscan_simple_timeout, data,
+                                      NULL);
+       } else if (data->scan_interval == data->short_interval && above) {
+               wpa_printf(MSG_DEBUG, "bgscan simple: Start using long bgscan "
+                          "interval");
+               data->scan_interval = data->long_interval;
+               eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
+               eloop_register_timeout(data->scan_interval, 0,
+                                      bgscan_simple_timeout, data, NULL);
+       } else if (!above) {
+               struct os_time now;
+               /*
+                * Signal dropped further 4 dB. Request a new scan if we have
+                * not yet scanned in a while.
+                */
+               os_get_time(&now);
+               if (now.sec > data->last_bgscan.sec + 10) {
+                       wpa_printf(MSG_DEBUG, "bgscan simple: Trigger "
+                                  "immediate scan");
+                       eloop_cancel_timeout(bgscan_simple_timeout, data,
+                                            NULL);
+                       eloop_register_timeout(0, 0, bgscan_simple_timeout,
+                                              data, NULL);
+               }
+       }
 }
 
 
index 70dccace4d23cfab3579d5f2a29720035bb38322..734e7e93927e4c3839d941431e10a928f56cd650 100644 (file)
@@ -1740,6 +1740,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                                        data->eapol_rx.data,
                                        data->eapol_rx.data_len);
                break;
+       case EVENT_SIGNAL_CHANGE:
+               bgscan_notify_signal_change(
+                       wpa_s, data->signal_change.above_threshold);
+               break;
        default:
                wpa_printf(MSG_INFO, "Unknown event %d", event);
                break;