wifi: fix scanned signal strength calculation for WEXT-based drivers

The new wpa_supplicant D-Bus interface only passes back the 'level'
of the scanned BSS, which with nl80211 drivers is almost always dBm,
which NM handled fine.  But WEXT-based drivers (ipw2x00, other older
ones, and some vendor drivers) use a mix of values for the 'level'
parameter, including the old WEXT 8-bit signed-value-in-unsigned-int
scheme.  Handle that.

Alternatively, we could have the supplicant expose the 'flags' value
from its internal BSS list over the bus.
This commit is contained in:
Dan Williams
2011-03-13 12:50:40 -05:00
parent 0e348bad2a
commit 32dedf4b83
4 changed files with 83 additions and 10 deletions

View File

@@ -18,7 +18,9 @@
* (C) Copyright 2011 Red Hat, Inc.
*/
#include <config.h>
#include <string.h>
#include <stdlib.h>
#include "nm-wifi-ap-utils.h"
@@ -706,3 +708,24 @@ nm_ap_utils_complete_connection (const GByteArray *ap_ssid,
return TRUE;
}
guint32
nm_ap_utils_level_to_quality (gint val)
{
if (val < 0) {
/* Assume dBm already; rough conversion: best = -40, worst = -100 */
val = abs (CLAMP (val, -100, -40) + 40); /* normalize to 0 */
val = 100 - (int) ((100.0 * (double) val) / 60.0);
} else if (val > 110 && val < 256) {
/* assume old-style WEXT 8-bit unsigned signal level */
val -= 256; /* subtract 256 to convert to dBm */
val = abs (CLAMP (val, -100, -40) + 40); /* normalize to 0 */
val = 100 - (int) ((100.0 * (double) val) / 60.0);
} else {
/* Assume signal is a "quality" percentage */
val = CLAMP (val, 0, 100);
}
g_assert (val >= 0);
return (guint32) val;
}

View File

@@ -39,5 +39,7 @@ gboolean nm_ap_utils_complete_connection (const GByteArray *ssid,
gboolean lock_bssid,
GError **error);
guint32 nm_ap_utils_level_to_quality (gint val);
#endif /* NM_WIFI_AP_UTILS_H */

View File

@@ -500,16 +500,8 @@ foreach_property_cb (gpointer key, gpointer value, gpointer user_data)
} else if (G_VALUE_HOLDS_INT (variant)) {
gint val = g_value_get_int (variant);
if (!strcmp (key, "Signal")) {
if (val < 0) {
/* Rough conversion: best = -40, worst = -100 */
val = abs (CLAMP (val, -100, -40) + 40);
val = 100 - (int) ((100.0 * (double) val) / 60.0);
} else
val /= 100;
nm_ap_set_strength (ap, val);
}
if (!strcmp (key, "Signal"))
nm_ap_set_strength (ap, nm_ap_utils_level_to_quality (val));
} else if (G_VALUE_HOLDS_STRING (variant)) {
const char *val = g_value_get_string (variant);

View File

@@ -1238,6 +1238,57 @@ test_wpa_ap_wpa_psk_connection_5 (guint idx)
/*******************************************/
static void
test_strength_dbm (void)
{
/* boundary conditions first */
g_assert_cmpint (nm_ap_utils_level_to_quality (-1), ==, 100);
g_assert_cmpint (nm_ap_utils_level_to_quality (-40), ==, 100);
g_assert_cmpint (nm_ap_utils_level_to_quality (-30), ==, 100);
g_assert_cmpint (nm_ap_utils_level_to_quality (-100), ==, 0);
g_assert_cmpint (nm_ap_utils_level_to_quality (-200), ==, 0);
g_assert_cmpint (nm_ap_utils_level_to_quality (-81), ==, 32);
g_assert_cmpint (nm_ap_utils_level_to_quality (-92), ==, 14);
g_assert_cmpint (nm_ap_utils_level_to_quality (-74), ==, 44);
g_assert_cmpint (nm_ap_utils_level_to_quality (-81), ==, 32);
g_assert_cmpint (nm_ap_utils_level_to_quality (-66), ==, 57);
}
static void
test_strength_percent (void)
{
int i;
/* boundary conditions first */
g_assert_cmpint (nm_ap_utils_level_to_quality (0), ==, 0);
g_assert_cmpint (nm_ap_utils_level_to_quality (100), ==, 100);
g_assert_cmpint (nm_ap_utils_level_to_quality (110), ==, 100);
for (i = 0; i <= 100; i++)
g_assert_cmpint (nm_ap_utils_level_to_quality (i), ==, i);
}
static void
test_strength_wext (void)
{
/* boundary conditions that we assume aren't WEXT first */
g_assert_cmpint (nm_ap_utils_level_to_quality (256), ==, 100);
g_assert_cmpint (nm_ap_utils_level_to_quality (110), ==, 100);
/* boundary conditions that we assume are WEXT */
g_assert_cmpint (nm_ap_utils_level_to_quality (111), ==, 0);
g_assert_cmpint (nm_ap_utils_level_to_quality (150), ==, 0);
g_assert_cmpint (nm_ap_utils_level_to_quality (225), ==, 100);
g_assert_cmpint (nm_ap_utils_level_to_quality (255), ==, 100);
g_assert_cmpint (nm_ap_utils_level_to_quality (157), ==, 2);
g_assert_cmpint (nm_ap_utils_level_to_quality (200), ==, 74);
g_assert_cmpint (nm_ap_utils_level_to_quality (215), ==, 99);
}
/*******************************************/
#if GLIB_CHECK_VERSION(2,25,12)
typedef GTestFixtureFunc TCFunc;
#else
@@ -1339,6 +1390,11 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_ap_wpa_eap_connection_4, IDX_RSN_PSK));
g_test_suite_add (suite, TESTCASE (test_ap_wpa_eap_connection_5, IDX_RSN_PSK));
/* Scanned signal strength conversion tests */
g_test_suite_add (suite, TESTCASE (test_strength_dbm, NULL));
g_test_suite_add (suite, TESTCASE (test_strength_percent, NULL));
g_test_suite_add (suite, TESTCASE (test_strength_wext, NULL));
return g_test_run ();
}