nl80211: Support setting sched scan RSSI threshold
authorThomas Pedersen <c_tpeder@qca.qualcomm.com>
Wed, 25 Jul 2012 13:56:43 +0000 (16:56 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 25 Jul 2012 13:56:43 +0000 (16:56 +0300)
Allow the user to configure an RSSI threshold in dBm below which the
nl80211 driver won't report scan results. Currently only supported
during scheduled (PNO) scans.

Signed-off-by: Thomas Pedersen <c_tpeder@qca.qualcomm.com>
Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/drivers/driver.h
src/drivers/driver_nl80211.c
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/ctrl_iface.c

index c5941dd..99da31c 100644 (file)
@@ -274,6 +274,15 @@ struct wpa_driver_scan_params {
        size_t num_filter_ssids;
 
        /**
+        * filter_rssi - Filter by RSSI
+        *
+        * The driver may filter scan results in firmware to reduce host
+        * wakeups and thereby save power. Specify the RSSI threshold in s32
+        * dBm.
+        */
+       s32 filter_rssi;
+
+       /**
         * p2p_probe - Used to disable CCK (802.11b) rates for P2P probes
         *
         * When set, the driver is expected to remove rates 1, 2, 5.5, and 11
index 0373f43..a30f2e3 100644 (file)
@@ -3612,6 +3612,7 @@ static int wpa_driver_nl80211_sched_scan(void *priv,
        struct wpa_driver_nl80211_data *drv = bss->drv;
        int ret = 0;
        struct nl_msg *msg, *ssids, *freqs, *match_set_ssid, *match_sets;
+       struct nl_msg *match_set_rssi;
        size_t i;
 
 #ifdef ANDROID
@@ -3640,8 +3641,9 @@ static int wpa_driver_nl80211_sched_scan(void *priv,
 
        NLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval);
 
-       if (drv->num_filter_ssids &&
-           (int) drv->num_filter_ssids <= drv->capa.max_match_sets) {
+       if ((drv->num_filter_ssids &&
+           (int) drv->num_filter_ssids <= drv->capa.max_match_sets) ||
+           params->filter_rssi) {
                match_sets = nlmsg_alloc();
 
                for (i = 0; i < drv->num_filter_ssids; i++) {
@@ -3661,6 +3663,18 @@ static int wpa_driver_nl80211_sched_scan(void *priv,
                        nlmsg_free(match_set_ssid);
                }
 
+               if (params->filter_rssi) {
+                       match_set_rssi = nlmsg_alloc();
+                       NLA_PUT_U32(match_set_rssi,
+                                   NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
+                                   params->filter_rssi);
+                       wpa_printf(MSG_MSGDUMP,
+                                  "nl80211: Sched scan RSSI filter %d dBm",
+                                  params->filter_rssi);
+                       nla_put_nested(match_sets, 0, match_set_rssi);
+                       nlmsg_free(match_set_rssi);
+               }
+
                nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH,
                               match_sets);
                nlmsg_free(match_sets);
index a68b31e..427242d 100644 (file)
@@ -2908,6 +2908,7 @@ static const struct global_parse_data global_fields[] = {
        { INT(bss_expiration_age), 0 },
        { INT(bss_expiration_scan_count), 0 },
        { INT_RANGE(filter_ssids, 0, 1), 0 },
+       { INT_RANGE(filter_rssi, -100, 0), 0 },
        { INT(max_num_sta), 0 },
        { INT_RANGE(disassoc_low_ack, 0, 1), 0 },
 #ifdef CONFIG_HS20
index 46c4da2..9ae57d0 100644 (file)
@@ -575,6 +575,14 @@ struct wpa_config {
        int filter_ssids;
 
        /**
+        * filter_rssi - RSSI-based scan result filtering
+        *
+        * 0 = do not filter scan results
+        * -n = filter scan results below -n dBm
+        */
+       int filter_rssi;
+
+       /**
         * max_num_sta - Maximum number of STAs in an AP/P2P GO
         */
        unsigned int max_num_sta;
index cb3e523..82dbf86 100644 (file)
@@ -98,6 +98,9 @@ static int pno_start(struct wpa_supplicant *wpa_s)
                ssid = ssid->next;
        }
 
+       if (wpa_s->conf->filter_rssi)
+               params.filter_rssi = wpa_s->conf->filter_rssi;
+
        ret = wpa_drv_sched_scan(wpa_s, &params, 10 * 1000);
        os_free(params.filter_ssids);
        if (ret == 0)