Wireless driver quality information sucks

Dan Williams dcbw at redhat.com
Thu Sep 16 17:25:04 UTC 2004


On Thu, 2004-09-16 at 16:10 +0100, Jonathan Andrews wrote: 
> www.wildpackets.com/elements/ whitepapers/Converting_Signal_Strength.pdf
> 
> If RSSI is converted to a db scale by the driver and the kernel has the
> ability to map db back to RSSI then this solves the problems.
> 
> By doing it this way it wouldn't matter how linear the RSSI on the card
> is (as the driver can correct). It wouldn't matter how many bits the
> card used to represent RSSI internally. It also allows devices that have
> a true db reading to map in without (much?) conversion.
> 
> The kernel would then make available a meaningful and consistent RSSI
> derived from the db reading its using internally.
> 
> The applications can then read one or both of (db) and (RSSI - the new
> strict linux kernel defined one  - not the fluffy manufacturers one).
> 
> All thats needed is a conversion from RSSI to db for each device,
> simplest place to stick that is in the driver - why complicate life any
> further !

One particular problem I referred to was with the Cisco drivers.  There
are two ways to get strength for an access point, one is through the
wireless scan (if the drivers support it) and the other is using
iw_get_range()/iw_get_stats() for strength info on the currently
associated access point.  Atmel drivers currently don't return _any_
quality information from wireless scans.

Using iw_get_range/stats, the strength value returned is completely
different than the value returned when the same access point shows up in
the scan, even if you are associated with it right then.  Also on the
cisco drivers, there doesn't seem to be a good way to actually determine
the signal strength from a scan.

For both these methods, you get back an iw_quality structure that has:

struct iw_quality
{
    uint8 qual;
    uint8 level;
    uint8 noise;
}

----- snip from iwlib.c
  /* People are very often confused by the 8 bit arithmetic happening
   * here.
   * All the values here are encoded in a 8 bit integer. 8 bit integers
   * are either unsigned [0 ; 255], signed [-128 ; +127] or
   * negative [-255 ; 0].
   * Further, on 8 bits, 0x100 == 256 == 0.
   *
   * Relative/percent values are always encoded unsigned, between 0 and
255.
   * Absolute/dBm values are always encoded negative, between -255 and
0.
   *
   * How do we separate relative from absolute values ? We use the
   * range to do that. The range allow to specify the real min/max
   * of the value. As the range struct only specify one bound of the
   * value, we assume that the other bound is 0 (zero).
   * For relative values, range is [0 ; range->max].
   * For absolute values, range is [range->max ; 0].
   *
   * Let's take two example :
   * 1) value is 75%. qual->value = 75 ; range->max_qual.value = 100
   * 2) value is -54dBm. noise floor of the radio is -104dBm.
   *    qual->value = -54 = 202 ; range->max_qual.value = -104 = 152
   *
   * Jean II
   */
------

Now the "qual" field is kind of ambiguous, and drivers seem to put
different values in there (Cisco drivers _always_ set this to 0 for
wireless scans).  What we're interested in is the level/noise
structures.

All these values are either Relative or Absolute.  Absolute values are
in dBm/rssi (drivers seem to mix this up a _lot_) while Relative values
are 0-100 as a percentage.  The application itself has to figure out
which is being used.  Next, the dBm values are in the range of 0 - 255
which is in actuality -127 - 128.  Cisco drivers only return Noise
information when calling iw_get_stats() but not for a wireless scan, and
I've found you cannot use the noise value from stats() along with the
wireless scan data, which is where this problem lies.  Cisco drivers
also use some magic numbers here and there that don't quite add up (for
example, you'll see the RSSI subtracted from 256 in some places, or
subtracted from 321 then divided by two in other places).

Devices also have "max" and "average" quality information which may or
may not get used at various points.  If you are using Relative values,
then you need to compare the qual.level against the "max" quality level
and the qual.noise against the "max" noise.  Different drivers use
different methods.

So here's what we need to do:

1) DEFINE what quality mode drivers should use (ie Relative/Absolute).
As in, all values MUST be in dBm (mandating percentages would deprive
userspace of useful data)

2) ENSURE that drivers use consistent information between the
iw_get_range()/iw_get_stats() calls and wireless scanning quality data

3) ENSURE that drivers don't use any magic numbers

Dan







More information about the fedora-devel-list mailing list