Show received signal strength information
This patch allows user space tools such as iwconfig, iwlist and
NetworkManager show the relative received signal strength. It is still
incomplete in the sense that:
* The only PHY data reported by the tested acx111 chip was the RSSI, but
the mapping from RSSI units to dBm or the maximum RSSI value (in order
to estimate a percentage) is still unknown.
* The Windows XP driver (using ndiswrapper) reports quality, signal
level and noise level. The first one in percentage, the latter two in
dBm. Whether these values are right, remains to be determined. The
GPL'ed part of the AVM FRITZ!WLAN USB Stick sources show that at least
on the TNETW1450 only the RSSI value (mapped to signal level) seems to
be supported.
* There is currently a mapping from RSSI to percentage in the
acx_signal_to_winlevel() function. However, the same function in the
FreeBSD/DragonFlyBSD driver uses different calculation constants
depending on the chip type. Furthermore, the OpenBSD driver defines
maximum RSSI levels depending on the type of radio transceiver (i.e.
Maxim, Ralink, Radia, etc.). Contacting them in order to find out how
they got to those results would probably be a good idea.
| |   |
| 387 | 387 | |
| 388 | 388 | /*********************************************************************** |
| 389 | 389 | ** Calculate level like the feb 2003 windows driver seems to do |
| 390 | * |
| 391 | * Note: the FreeBSD and DragonFlyBSD drivers seems to use different |
| 392 | * so-called correction constants depending on the chip. They will be |
| 393 | * defined for now, but as it is still unknown whether they are correct |
| 394 | * or not, only the original value will be used. Something else to take |
| 395 | * into account is that the OpenBSD driver uses another approach and |
| 396 | * defines the maximum RSSI value depending on the chip, rather than |
| 397 | * using a value of 100 for all of them, as it is currently done here. |
| 390 | 398 | */ |
| 399 | #define ACX100_RSSI_CORR 8 |
| 400 | #define ACX111_RSSI_CORR 5 |
| 391 | 401 | static u8 acx_signal_to_winlevel(u8 rawlevel) |
| 392 | 402 | { |
| 393 | 403 | /* u8 winlevel = (u8) (0.5 + 0.625 * rawlevel); */ |
| 394 | | u8 winlevel = ((4 + (rawlevel * 5)) / 8); |
| 404 | u8 winlevel = (((ACX100_RSSI_CORR / 2) + (rawlevel * 5)) / |
| 405 | ACX100_RSSI_CORR); |
| 395 | 406 | |
| 396 | 407 | if (winlevel > 100) |
| 397 | 408 | winlevel = 100; |
| … | … | |
| 2154 | 2154 | adev->tx_level_dbm = 15; |
| 2155 | 2155 | } |
| 2156 | 2156 | if (level_dbm != adev->tx_level_dbm) |
| 2157 | | acx_log(LOG_WARNING, L_INIT, "acx111 firmware has specific " |
| 2158 | | "power levels only: adjusted %d dBm to %d dBm!\n", |
| 2159 | | level_dbm, adev->tx_level_dbm); |
| 2157 | acx_log(LOG_WARNING, L_INIT, "only predefined transmission " |
| 2158 | "power levels are supported at this time: " |
| 2159 | "adjusted %d dBm to %d dBm\n", level_dbm, |
| 2160 | adev->tx_level_dbm); |
| 2160 | 2161 | |
| 2161 | 2162 | return acx_s_configure(adev, &tx_level, ACX1xx_REG_DOT11_TX_POWER_LEVEL); |
| 2162 | 2163 | } |
| … | … | |
| 2356 | 2356 | /* length of frame from control field to first byte of FCS */ |
| 2357 | 2357 | buf_len = RXBUF_BYTES_RCVD(adev, rxbuf); |
| 2358 | 2358 | |
| 2359 | | acx_log_dump(LOG_DEBUG, L_DATA, hdr, buf_len, "RX: 802.11 buffer:\n"); |
| 2359 | acx_log_dump(LOG_DEBUG, L_XFER | L_DATA, hdr, buf_len, |
| 2360 | "rx: 802.11 buffer:\n"); |
| 2360 | 2361 | |
| 2361 | 2362 | acx_l_rx(adev, rxbuf); |
| 2362 | 2363 | /* Now check Rx quality level, AFTER processing packet. |
| … | … | |
| 2367 | 2367 | * be expressed in dBm, or it's some pretty complicated |
| 2368 | 2368 | * calculation. */ |
| 2369 | 2369 | |
| 2370 | | #ifdef FROM_SCAN_SOURCE_ONLY |
| 2371 | | /* only consider packets originating from the MAC |
| 2372 | | * address of the device that's managing our BSSID. |
| 2373 | | * Disable it for now, since it removes information (levels |
| 2374 | | * from different peers) and slows the Rx path. *//* |
| 2375 | | if (adev->ap_client && mac_is_equal(hdr->a2, adev->ap_client->address)) { |
| 2376 | | */ |
| 2377 | | #endif |
| 2370 | /* TODO: only the RSSI seems to be reported */ |
| 2371 | adev->rx_status.ssi = acx_signal_to_winlevel(rxbuf->phy_level); |
| 2378 | 2372 | |
| 2379 | 2373 | FN_EXIT0; |
| 2380 | 2374 | } |
| … | … | |
| 2683 | 2683 | // memset(&status, 0, sizeof(status)); |
| 2684 | 2684 | |
| 2685 | 2685 | status->mactime = rxbuf->time; |
| 2686 | status->ssi = acx_signal_to_winlevel(rxbuf->phy_level); |
| 2687 | /* TODO: they do not seem to be reported, at least on the acx111 |
| 2688 | * (and TNETW1450?), therefore commenting them out |
| 2686 | 2689 | status->signal = acx_signal_to_winlevel(rxbuf->phy_level); |
| 2687 | | status->noise = acx_signal_to_winlevel(rxbuf->phy_snr); |
| 2690 | status->noise = acx_signal_to_winlevel(rxbuf->phy_snr); */ |
| 2688 | 2691 | status->flag = 0; |
| 2689 | 2692 | status->rate = rxbuf->phy_plcp_signal; |
| 2690 | 2693 | status->antenna = 1; |
| toggle raw diff |
--- a/common.c
+++ b/common.c
@@ -387,11 +387,22 @@ u8 acx_rate111to100(u16 r)
/***********************************************************************
** Calculate level like the feb 2003 windows driver seems to do
+*
+* Note: the FreeBSD and DragonFlyBSD drivers seems to use different
+* so-called correction constants depending on the chip. They will be
+* defined for now, but as it is still unknown whether they are correct
+* or not, only the original value will be used. Something else to take
+* into account is that the OpenBSD driver uses another approach and
+* defines the maximum RSSI value depending on the chip, rather than
+* using a value of 100 for all of them, as it is currently done here.
*/
+#define ACX100_RSSI_CORR 8
+#define ACX111_RSSI_CORR 5
static u8 acx_signal_to_winlevel(u8 rawlevel)
{
/* u8 winlevel = (u8) (0.5 + 0.625 * rawlevel); */
- u8 winlevel = ((4 + (rawlevel * 5)) / 8);
+ u8 winlevel = (((ACX100_RSSI_CORR / 2) + (rawlevel * 5)) /
+ ACX100_RSSI_CORR);
if (winlevel > 100)
winlevel = 100;
@@ -2143,9 +2154,10 @@ static int acx111_s_set_tx_level(acx_device_t * adev, u8 level_dbm)
adev->tx_level_dbm = 15;
}
if (level_dbm != adev->tx_level_dbm)
- acx_log(LOG_WARNING, L_INIT, "acx111 firmware has specific "
- "power levels only: adjusted %d dBm to %d dBm!\n",
- level_dbm, adev->tx_level_dbm);
+ acx_log(LOG_WARNING, L_INIT, "only predefined transmission "
+ "power levels are supported at this time: "
+ "adjusted %d dBm to %d dBm\n", level_dbm,
+ adev->tx_level_dbm);
return acx_s_configure(adev, &tx_level, ACX1xx_REG_DOT11_TX_POWER_LEVEL);
}
@@ -2344,7 +2356,8 @@ void acx_l_process_rxbuf(acx_device_t * adev, rxbuffer_t * rxbuf)
/* length of frame from control field to first byte of FCS */
buf_len = RXBUF_BYTES_RCVD(adev, rxbuf);
- acx_log_dump(LOG_DEBUG, L_DATA, hdr, buf_len, "RX: 802.11 buffer:\n");
+ acx_log_dump(LOG_DEBUG, L_XFER | L_DATA, hdr, buf_len,
+ "rx: 802.11 buffer:\n");
acx_l_rx(adev, rxbuf);
/* Now check Rx quality level, AFTER processing packet.
@@ -2354,14 +2367,8 @@ void acx_l_process_rxbuf(acx_device_t * adev, rxbuffer_t * rxbuf)
* be expressed in dBm, or it's some pretty complicated
* calculation. */
-#ifdef FROM_SCAN_SOURCE_ONLY
- /* only consider packets originating from the MAC
- * address of the device that's managing our BSSID.
- * Disable it for now, since it removes information (levels
- * from different peers) and slows the Rx path. *//*
- if (adev->ap_client && mac_is_equal(hdr->a2, adev->ap_client->address)) {
-*/
-#endif
+ /* TODO: only the RSSI seems to be reported */
+ adev->rx_status.ssi = acx_signal_to_winlevel(rxbuf->phy_level);
FN_EXIT0;
}
@@ -2676,8 +2683,11 @@ static void acx_l_rx(acx_device_t * adev, rxbuffer_t * rxbuf)
// memset(&status, 0, sizeof(status));
status->mactime = rxbuf->time;
+ status->ssi = acx_signal_to_winlevel(rxbuf->phy_level);
+ /* TODO: they do not seem to be reported, at least on the acx111
+ * (and TNETW1450?), therefore commenting them out
status->signal = acx_signal_to_winlevel(rxbuf->phy_level);
- status->noise = acx_signal_to_winlevel(rxbuf->phy_snr);
+ status->noise = acx_signal_to_winlevel(rxbuf->phy_snr); */
status->flag = 0;
status->rate = rxbuf->phy_plcp_signal;
status->antenna = 1; |
| |   |
| 1485 | 1485 | */ |
| 1486 | 1486 | ieee->queues = 1; |
| 1487 | 1487 | |
| 1488 | /* TODO: although in the original driver the maximum value was 100, |
| 1489 | * the OpenBSD driver assigns maximum values depending on the type of |
| 1490 | * radio transceiver (i.e. Radia, Maxim, etc.). This value is always a |
| 1491 | * positive integer which most probably indicates the gain of the AGC |
| 1492 | * in the rx path of the chip, in dB steps (0.625 dB, for example?). |
| 1493 | * The mapping of this rssi value to dBm is still unknown, but it can |
| 1494 | * nevertheless be used as a measure of relative signal strength. The |
| 1495 | * other two values, i.e. max_signal and max_noise, do not seem to be |
| 1496 | * supported on my acx111 card (they are always 0), although iwconfig |
| 1497 | * reports them (in dBm) when using ndiswrapper with the Windows XP |
| 1498 | * driver. The GPL-licensed part of the AVM FRITZ!WLAN USB Stick |
| 1499 | * driver sources (for the TNETW1450, though) seems to also indicate |
| 1500 | * that only the RSSI is supported. In conclusion, the max_signal and |
| 1501 | * max_noise values will not be initialised by now, as they do not |
| 1502 | * seem to be supported or how to acquire them is still unknown. */ |
| 1503 | ieee->max_rssi = 100; |
| 1504 | |
| 1488 | 1505 | adev = ieee2adev(ieee); |
| 1489 | 1506 | |
| 1490 | 1507 | memset(adev, 0, sizeof(*adev)); |
| toggle raw diff |
--- a/pci.c
+++ b/pci.c
@@ -1485,6 +1485,23 @@ acxpci_e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
*/
ieee->queues = 1;
+ /* TODO: although in the original driver the maximum value was 100,
+ * the OpenBSD driver assigns maximum values depending on the type of
+ * radio transceiver (i.e. Radia, Maxim, etc.). This value is always a
+ * positive integer which most probably indicates the gain of the AGC
+ * in the rx path of the chip, in dB steps (0.625 dB, for example?).
+ * The mapping of this rssi value to dBm is still unknown, but it can
+ * nevertheless be used as a measure of relative signal strength. The
+ * other two values, i.e. max_signal and max_noise, do not seem to be
+ * supported on my acx111 card (they are always 0), although iwconfig
+ * reports them (in dBm) when using ndiswrapper with the Windows XP
+ * driver. The GPL-licensed part of the AVM FRITZ!WLAN USB Stick
+ * driver sources (for the TNETW1450, though) seems to also indicate
+ * that only the RSSI is supported. In conclusion, the max_signal and
+ * max_noise values will not be initialised by now, as they do not
+ * seem to be supported or how to acquire them is still unknown. */
+ ieee->max_rssi = 100;
+
adev = ieee2adev(ieee);
memset(adev, 0, sizeof(*adev)); |