diff --git a/src/drivers/driver.h b/src/drivers/driver.h index c5941ddae..99da31c71 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -273,6 +273,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 * diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 0373f430c..a30f2e3df 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -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); diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index a68b31e7b..427242d94 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -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 diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 46c4da247..9ae57d018 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -574,6 +574,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 */ diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index cb3e523bd..82dbf8694 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -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, ¶ms, 10 * 1000); os_free(params.filter_ssids); if (ret == 0)