|
@@ -1594,11 +1594,12 @@ struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
|
|
|
*/
|
|
|
#define GREAT_SNR 30
|
|
|
|
|
|
+#define IS_5GHZ(n) (n > 4000)
|
|
|
+
|
|
|
/* Compare function for sorting scan results. Return >0 if @b is considered
|
|
|
* better. */
|
|
|
static int wpa_scan_result_compar(const void *a, const void *b)
|
|
|
{
|
|
|
-#define IS_5GHZ(n) (n > 4000)
|
|
|
#define MIN(a,b) a < b ? a : b
|
|
|
struct wpa_scan_res **_wa = (void *) a;
|
|
|
struct wpa_scan_res **_wb = (void *) b;
|
|
@@ -1626,18 +1627,18 @@ static int wpa_scan_result_compar(const void *a, const void *b)
|
|
|
(wb->caps & IEEE80211_CAP_PRIVACY) == 0)
|
|
|
return -1;
|
|
|
|
|
|
- if ((wa->flags & wb->flags & WPA_SCAN_LEVEL_DBM) &&
|
|
|
- !((wa->flags | wb->flags) & WPA_SCAN_NOISE_INVALID)) {
|
|
|
+ if (wa->flags & wb->flags & WPA_SCAN_LEVEL_DBM) {
|
|
|
snr_a = MIN(wa->level - wa->noise, GREAT_SNR);
|
|
|
snr_b = MIN(wb->level - wb->noise, GREAT_SNR);
|
|
|
} else {
|
|
|
- /* Not suitable information to calculate SNR, so use level */
|
|
|
+ /* Level is not in dBm, so we can't calculate
|
|
|
+ * SNR. Just use raw level (units unknown). */
|
|
|
snr_a = wa->level;
|
|
|
snr_b = wb->level;
|
|
|
}
|
|
|
|
|
|
- /* best/max rate preferred if SNR close enough */
|
|
|
- if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) ||
|
|
|
+ /* if SNR is close, decide by max rate or frequency band */
|
|
|
+ if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) ||
|
|
|
(wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
|
|
|
maxrate_a = wpa_scan_get_max_rate(wa);
|
|
|
maxrate_b = wpa_scan_get_max_rate(wb);
|
|
@@ -1647,8 +1648,6 @@ static int wpa_scan_result_compar(const void *a, const void *b)
|
|
|
return IS_5GHZ(wa->freq) ? -1 : 1;
|
|
|
}
|
|
|
|
|
|
- /* use freq for channel preference */
|
|
|
-
|
|
|
/* all things being equal, use SNR; if SNRs are
|
|
|
* identical, use quality values since some drivers may only report
|
|
|
* that value and leave the signal level zero */
|
|
@@ -1656,7 +1655,6 @@ static int wpa_scan_result_compar(const void *a, const void *b)
|
|
|
return wb->qual - wa->qual;
|
|
|
return snr_b - snr_a;
|
|
|
#undef MIN
|
|
|
-#undef IS_5GHZ
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1721,15 +1719,15 @@ static void dump_scan_res(struct wpa_scan_results *scan_res)
|
|
|
for (i = 0; i < scan_res->num; i++) {
|
|
|
struct wpa_scan_res *r = scan_res->res[i];
|
|
|
u8 *pos;
|
|
|
- if ((r->flags & (WPA_SCAN_LEVEL_DBM | WPA_SCAN_NOISE_INVALID))
|
|
|
- == WPA_SCAN_LEVEL_DBM) {
|
|
|
+ if (r->flags & WPA_SCAN_LEVEL_DBM) {
|
|
|
int snr = r->level - r->noise;
|
|
|
+ int noise_valid = !(r->flags & WPA_SCAN_NOISE_INVALID);
|
|
|
+
|
|
|
wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
|
|
|
- "noise=%d level=%d snr=%d%s flags=0x%x "
|
|
|
- "age=%u",
|
|
|
+ "noise=%d%s level=%d snr=%d%s flags=0x%x age=%u",
|
|
|
MAC2STR(r->bssid), r->freq, r->qual,
|
|
|
- r->noise, r->level, snr,
|
|
|
- snr >= GREAT_SNR ? "*" : "", r->flags,
|
|
|
+ r->noise, noise_valid ? "" : "~", r->level,
|
|
|
+ snr, snr >= GREAT_SNR ? "*" : "", r->flags,
|
|
|
r->age);
|
|
|
} else {
|
|
|
wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
|
|
@@ -1802,6 +1800,14 @@ static void filter_scan_res(struct wpa_supplicant *wpa_s,
|
|
|
}
|
|
|
|
|
|
|
|
|
+/*
|
|
|
+ * Noise floor values to use when we have signal strength
|
|
|
+ * measurements, but no noise floor measurments. These values were
|
|
|
+ * measured in an office environment with many APs.
|
|
|
+ */
|
|
|
+#define DEFAULT_NOISE_FLOOR_2GHZ (-89)
|
|
|
+#define DEFAULT_NOISE_FLOOR_5GHZ (-92)
|
|
|
+
|
|
|
/**
|
|
|
* wpa_supplicant_get_scan_results - Get scan results
|
|
|
* @wpa_s: Pointer to wpa_supplicant data
|
|
@@ -1835,6 +1841,17 @@ wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
|
|
|
}
|
|
|
filter_scan_res(wpa_s, scan_res);
|
|
|
|
|
|
+ for (i = 0; i < scan_res->num; i++) {
|
|
|
+ struct wpa_scan_res *scan_res_item = scan_res->res[i];
|
|
|
+
|
|
|
+ if (scan_res_item->flags & WPA_SCAN_NOISE_INVALID) {
|
|
|
+ scan_res_item->noise =
|
|
|
+ IS_5GHZ(scan_res_item->freq) ?
|
|
|
+ DEFAULT_NOISE_FLOOR_5GHZ :
|
|
|
+ DEFAULT_NOISE_FLOOR_2GHZ;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
#ifdef CONFIG_WPS
|
|
|
if (wpas_wps_searching(wpa_s)) {
|
|
|
wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS "
|