Date: Sat, 15 Dec 2001 16:00:09 -0500 (EST) From: "Douglas S. J. De Couto" <decouto@amsterdam.lcs.mit.edu> To: FreeBSD-gnats-submit@freebsd.org Subject: kern/32880: Signal Strength patched for aironet driver Message-ID: <200112152100.fBFL09I40716@bermuda.lcs.mit.edu>
next in thread | raw e-mail | index | archive | help
>Number: 32880 >Category: kern >Synopsis: Update aironet driver to correct signal strengt units, and add ``quality'' information. >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: update >Submitter-Id: current-users >Arrival-Date: Sat Dec 15 13:10:00 PST 2001 >Closed-Date: >Last-Modified: >Originator: Douglas S. J. De Couto >Release: FreeBSD 4.4-RELEASE i386 >Organization: MIT LCS >Environment: These patches change the ``an'' driver to use a table from the aironet card's frimware to convert signal strength values into proper units (dBm). If the firmware table is not available, a close approximation is used instead. ancontrol is also patched to allow users to see what their card's firmware table looks like (e.g. to convert old data). The pactches also cause the driver to extract the signal ``quality'' level for each received packet. I have no idea what the units and or meaning of that number is. The patches are against the 4.4 release source, and I have tested them on my laptop. I am also sending them to the driver author (Bill Paul). -------------- ancontrol.c.patch ---------------- --- ancontrol.c Sat Dec 15 15:23:37 2001 +++ /home/ny3/decouto/an-patches/freebsd.new/ancontrol/ancontrol.c Sat Dec 15 15:06:57 2001 @@ -85,6 +85,7 @@ static void an_str2key __P((char *, struct an_ltv_key *)); static void an_setkeys __P((const char *, char *, int)); static void an_enable_tx_key __P((const char *, char *)); +static void an_dumprssimap __P((const char *)); static void usage __P((char *)); int main __P((int, char **)); @@ -128,6 +129,8 @@ #define ACT_SET_KEYS 35 #define ACT_ENABLE_TX_KEY 36 +#define ACT_DUMPRSSIMAP 37 + static void an_getval(iface, areq) const char *iface; struct an_req *areq; @@ -813,6 +816,31 @@ return; } +static void an_dumprssimap(iface) + const char *iface; +{ + struct an_ltv_rssi_map *rssi; + struct an_req areq; + int i; + + areq.an_len = sizeof(areq); + areq.an_type = AN_RID_RSSI_MAP; + + an_getval(iface, &areq); + + rssi = (struct an_ltv_rssi_map *)&areq; + + printf("idx pct dBm\n"); + for (i = 0; i < 0xFF;i++) { + struct an_rssi_entry *entry = (struct an_rssi_entry *) &rssi->an_entries[i]; + /* negate the dBm value: it's the only way the power level makes sense */ + printf("%3u %3u -%3u\n", i, + (unsigned int) entry->an_rss_pct, + (unsigned int) entry->an_rss_dbm); + } + + return; +} static void usage(p) char *p; @@ -823,6 +851,7 @@ fprintf(stderr, "\t%s -i iface -I (show NIC capabilities)\n", p); fprintf(stderr, "\t%s -i iface -T (show stats counters)\n", p); fprintf(stderr, "\t%s -i iface -C (show current config)\n", p); + fprintf(stderr, "\t%s -i iface -R (show RSSI map)\n", p); fprintf(stderr, "\t%s -i iface -t 0|1|2|3|4 (set TX speed)\n", p); fprintf(stderr, "\t%s -i iface -s 0|1|2|3 (set power same mode)\n", p); fprintf(stderr, "\t%s -i iface [-v 1|2|3|4] -a AP (specify AP)\n", p); @@ -1371,7 +1400,7 @@ opterr = 1; while ((ch = getopt(argc, argv, - "ANISCTht:a:e:o:s:n:v:d:j:b:c:r:p:w:m:l:k:K:W:QZ")) != -1) { + "ANISCTRht:a:e:o:s:n:v:d:j:b:c:r:p:w:m:l:k:K:W:QZ")) != -1) { switch(ch) { case 'Z': #ifdef ANCACHE @@ -1405,6 +1434,9 @@ case 'C': act = ACT_DUMPCONFIG; break; + case 'R': + act = ACT_DUMPRSSIMAP; + break; case 't': act = ACT_SET_TXRATE; arg = optarg; @@ -1561,6 +1593,9 @@ break; case ACT_DUMPAP: an_dumpap(iface); + break; + case ACT_DUMPRSSIMAP: + an_dumprssimap(iface); break; case ACT_SET_SSID1: case ACT_SET_SSID2: ------------- an.patch ------------------ diff -u ./if_aironet_ieee.h /home/ny3/decouto/an-patches/freebsd.new/an/if_aironet_ieee.h --- ./if_aironet_ieee.h Sat Dec 15 15:41:52 2001 +++ /home/ny3/decouto/an-patches/freebsd.new/an/if_aironet_ieee.h Sat Dec 15 15:18:01 2001 @@ -132,6 +132,25 @@ }; #endif +/* + * The card provides an 8-bit signal strength value (RSSI), which can + * be converted to a dBm power value (or a percent) using a table in + * the card's firmware (when available). The tables are slightly + * different in individual cards, even of the same model. If the + * table is not available, the mapping can be approximated by dBm = + * RSSI - 100. This approximation can be seen by plotting a few + * tables, and also matches some info on the Intersil web site (I + * think they make the RF front end for the cards. However, the linux + * driver uses the approximation dBm = RSSI/2 - 95. I think that is + * just wrong. + */ + +struct an_rssi_entry { + u_int8_t an_rss_pct; + u_int8_t an_rss_dbm; +}; + + struct an_ltv_key { u_int16_t an_len; u_int16_t an_type; @@ -335,6 +354,7 @@ #define AN_RXMODE_80211_MONITOR_ANYBSS 0x0004 #define AN_RXMODE_LAN_MONITOR_CURBSS 0x0005 #define AN_RXMODE_NO_8023_HEADER 0x0100 +#define AN_RXMODE_NORMALIZED_RSSI 0x0200 #define AN_RATE_1MBPS 0x0002 #define AN_RATE_2MBPS 0x0004 @@ -501,6 +521,16 @@ /* ??? */ }; +/* + * RSSI map. If available in the card's firmware, this can be used to + * convert the 8-bit RSSI values from the card into dBm. + */ +struct an_ltv_rssi_map { + u_int16_t an_len; + u_int16_t an_type; + u_int16_t an_entries[256]; +}; + /* * Status (read only). Note: the manual claims this RID is 108 bytes * long (0x6A is the last datum, which is 2 bytes long) however when @@ -510,8 +540,7 @@ * field is 8 bytes long.) * * Also, the channel_set and current_channel fields appear to be - * reversed. Either that, or the hop_period field is unused. - */ + * reversed. Either that, or the hop_period field is unused. */ struct an_ltv_status { u_int16_t an_len; /* 0x00 */ u_int16_t an_type; /* 0xXX */ @@ -591,6 +620,7 @@ #define AN_RID_CAPABILITIES 0xFF00 /* PC 4500/4800 capabilities */ #define AN_RID_AP_INFO 0xFF01 /* Access point info */ #define AN_RID_RADIO_INFO 0xFF02 /* Radio info */ +#define AN_RID_RSSI_MAP 0xFF04 /* RSSI <-> dBm table */ #define AN_RID_STATUS 0xFF50 /* Current status info */ #define AN_RID_BEACONS_HST 0xFF51 #define AN_RID_BUSY_HST 0xFF52 diff -u ./if_an.c /home/ny3/decouto/an-patches/freebsd.new/an/if_an.c --- ./if_an.c Sat Dec 15 15:41:52 2001 +++ /home/ny3/decouto/an-patches/freebsd.new/an/if_an.c Sat Dec 15 15:05:34 2001 @@ -162,7 +162,7 @@ static void an_setdef __P((struct an_softc *, struct an_req *)); #ifdef ANCACHE static void an_cache_store __P((struct an_softc *, struct ether_header *, - struct mbuf *, unsigned short)); + struct mbuf *, u_int8_t, u_int8_t)); #endif static void an_dump_record __P((struct an_softc *,struct an_ltv_gen *, @@ -344,6 +344,18 @@ return(EIO); } +#ifdef ANCACHE + /* Read the RSSI <-> dBm map */ + sc->an_rssimap.an_type = AN_RID_RSSI_MAP; + sc->an_rssimap.an_len = sizeof(struct an_ltv_rssi_map); + if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_rssimap)) { + printf("an%d: unable to get RSSI <-> dBM map\n", sc->an_unit); + sc->an_have_rssimap = 0; + } + else + sc->an_have_rssimap = 1; +#endif + bcopy((char *)&sc->an_caps.an_oemaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); @@ -493,7 +505,8 @@ /* Receive packet. */ m_adj(m, sizeof(struct ether_header)); #ifdef ANCACHE - an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength); + an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength, + rx_frame.an_rsvd0); #endif ether_input(ifp, eh, m); } @@ -1894,11 +1907,12 @@ * strength in MAC (src) indexed cache. */ static -void an_cache_store (sc, eh, m, rx_quality) +void an_cache_store (sc, eh, m, rx_rssi, rx_quality) struct an_softc *sc; struct ether_header *eh; struct mbuf *m; - unsigned short rx_quality; + u_int8_t rx_rssi; + u_int8_t rx_quality; { struct ip *ip = 0; int i; @@ -1930,7 +1944,7 @@ #ifdef SIGDEBUG printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n", - rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff); + rx_rssi & 0xffff, rx_rssi >> 8, rx_rssi & 0xff); #endif /* find the ip header. we want to store the ip_src @@ -2007,7 +2021,16 @@ } bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc, 6); - sc->an_sigcache[cache_slot].signal = rx_quality; + + if (sc->an_have_rssimap) { + struct an_rssi_entry *e; + e = (struct an_rssi_entry *) &sc->an_rssimap.an_entries[rx_rssi]; + sc->an_sigcache[cache_slot].signal = -(e->an_rss_dbm); + } + else + sc->an_sigcache[cache_slot].signal = rx_rssi - 100; + sc->an_sigcache[cache_slot].quality = rx_quality; + sc->an_sigcache[cache_slot].noise = 0; return; } diff -u ./if_anreg.h /home/ny3/decouto/an-patches/freebsd.new/an/if_anreg.h --- ./if_anreg.h Sat Dec 15 15:41:52 2001 +++ /home/ny3/decouto/an-patches/freebsd.new/an/if_anreg.h Sat Dec 15 15:05:35 2001 @@ -378,6 +378,8 @@ int an_sigitems; struct an_sigcache an_sigcache[MAXANCACHE]; int an_nextitem; + int an_have_rssimap; + struct an_ltv_rssi_map an_rssimap; #endif struct callout_handle an_stat_ch; device_t an_dev; >Description: >How-To-Repeat: >Fix: >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200112152100.fBFL09I40716>