Skip site navigation (1)Skip section navigation (2)
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>