summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2003-09-05 22:29:30 +0000
committersam <sam@FreeBSD.org>2003-09-05 22:29:30 +0000
commit61e32060ebe88a1fcc239db7013c06647fbee902 (patch)
treea8eb3baa11e3cf856200c165c59b988b0842970d
parent92be79f8718c8d556f13d3526d8a1886a858be2b (diff)
downloadFreeBSD-src-61e32060ebe88a1fcc239db7013c06647fbee902.zip
FreeBSD-src-61e32060ebe88a1fcc239db7013c06647fbee902.tar.gz
o add experimental radiotap capture format
o add netbsd logic to convert rssi to device-independent values Obtained from: NetBSD (rssi conversion code)
-rw-r--r--sys/dev/wi/if_wi.c68
-rw-r--r--sys/dev/wi/if_wi_pccard.c3
-rw-r--r--sys/dev/wi/if_wi_pci.c3
-rw-r--r--sys/dev/wi/if_wireg.h36
-rw-r--r--sys/dev/wi/if_wivar.h28
5 files changed, 125 insertions, 13 deletions
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index 2fd33d5..e8182d0 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -100,6 +100,7 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_ioctl.h>
+#include <net80211/ieee80211_radiotap.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -110,8 +111,8 @@ __FBSDID("$FreeBSD$");
#include <net/bpf.h>
#include <dev/wi/if_wavelan_ieee.h>
-#include <dev/wi/if_wivar.h>
#include <dev/wi/if_wireg.h>
+#include <dev/wi/if_wivar.h>
#define IF_POLL(ifq, m) ((m) = (ifq)->ifq_head)
#define IFQ_POLL(ifq, m) IF_POLL((ifq), (m))
@@ -372,6 +373,10 @@ wi_attach(device_t dev)
ic->ic_caps |= IEEE80211_C_MONITOR;
}
sc->sc_ibss_port = htole16(1);
+
+ sc->sc_min_rssi = WI_LUCENT_MIN_RSSI;
+ sc->sc_max_rssi = WI_LUCENT_MAX_RSSI;
+ sc->sc_dbm_offset = WI_LUCENT_DBM_OFFSET;
break;
case WI_INTERSIL:
@@ -393,6 +398,10 @@ wi_attach(device_t dev)
if (sc->sc_sta_firmware_ver >= 803)
ic->ic_caps |= IEEE80211_C_HOSTAP;
sc->sc_ibss_port = htole16(0);
+
+ sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
+ sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
+ sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
break;
case WI_SYMBOL:
@@ -401,6 +410,10 @@ wi_attach(device_t dev)
if (sc->sc_sta_firmware_ver >= 25000)
ic->ic_caps |= IEEE80211_C_IBSS;
sc->sc_ibss_port = htole16(4);
+
+ sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
+ sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
+ sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
break;
}
@@ -431,9 +444,8 @@ wi_attach(device_t dev)
buflen = sizeof(val);
if ((sc->sc_flags & WI_FLAGS_HAS_DBMADJUST) &&
wi_read_rid(sc, WI_RID_DBM_ADJUST, &val, &buflen) == 0) {
- sc->sc_dbm_adjust = le16toh(val);
- } else
- sc->sc_dbm_adjust = 100; /* default */
+ sc->sc_dbm_offset = le16toh(val);
+ }
sc->sc_max_datalen = 2304;
sc->sc_system_scale = 1;
@@ -460,6 +472,23 @@ wi_attach(device_t dev)
ic->ic_newstate = wi_newstate;
ieee80211_media_init(ifp, wi_media_change, wi_media_status);
+#if NBPFILTER > 0
+ bpfattach2(ifp, DLT_IEEE802_11_RADIO,
+ sizeof(struct ieee80211_frame) + sizeof(sc->sc_tx_th),
+ &sc->sc_drvbpf);
+ /*
+ * Initialize constant fields.
+ *
+ * NB: the channel is setup each time we transition to the
+ * RUN state to avoid filling it in for each frame.
+ */
+ sc->sc_tx_th.wt_ihdr.it_len = sizeof(sc->sc_tx_th);
+ sc->sc_tx_th.wt_ihdr.it_present = WI_TX_RADIOTAP_PRESENT;
+
+ sc->sc_rx_th.wr_ihdr.it_len = sizeof(sc->sc_rx_th);
+ sc->sc_rx_th.wr_ihdr.it_present = WI_RX_RADIOTAP_PRESENT0;
+ sc->sc_rx_th.wr_present1 = WI_RX_RADIOTAP_PRESENT1;
+#endif
return (0);
}
@@ -477,6 +506,9 @@ wi_detach(device_t dev)
wi_stop(ifp, 0);
+#if NBPFILTER > 0
+ bpfdetach(ifp);
+#endif
ieee80211_ifdetach(ifp);
WI_UNLOCK(sc);
bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
@@ -902,10 +934,9 @@ wi_start(struct ifnet *ifp)
MGETHDR(mb, M_DONTWAIT, m0->m_type);
if (mb != NULL) {
- (void) m_dup_pkthdr(mb, m0, M_DONTWAIT);
mb->m_next = m0;
- mb->m_data = (caddr_t)&frmhdr;
- mb->m_len = sizeof(frmhdr);
+ mb->m_data = (caddr_t)&sc->sc_tx_th;
+ mb->m_len = sizeof(sc->sc_tx_th);
mb->m_pkthdr.len += mb->m_len;
bpf_mtap(sc->sc_drvbpf, mb);
m_free(mb);
@@ -1449,12 +1480,23 @@ wi_rx_intr(struct wi_softc *sc)
if (sc->sc_drvbpf) {
struct mbuf *mb;
+ /* XXX pre-allocate space when setting up recv's */
MGETHDR(mb, M_DONTWAIT, m->m_type);
if (mb != NULL) {
+ /* XXX replace divide by table */
+ sc->sc_rx_th.wr_rate = frmhdr.wi_rx_rate / 5;
+ sc->sc_rx_th.wr_antsignal =
+ WI_RSSI_TO_DBM(sc, frmhdr.wi_rx_signal);
+ sc->sc_rx_th.wr_antnoise =
+ WI_RSSI_TO_DBM(sc, frmhdr.wi_rx_silence);
+ sc->sc_rx_th.wr_time =
+ htole32((frmhdr.wi_rx_tstamp1 << 16) |
+ frmhdr.wi_rx_tstamp0);
+
(void) m_dup_pkthdr(mb, m, M_DONTWAIT);
mb->m_next = m;
- mb->m_data = (caddr_t)&frmhdr;
- mb->m_len = sizeof(frmhdr);
+ mb->m_data = (caddr_t)&sc->sc_rx_th;
+ mb->m_len = sizeof(sc->sc_rx_th);
mb->m_pkthdr.len += mb->m_len;
bpf_mtap(sc->sc_drvbpf, mb);
m_free(mb);
@@ -1837,7 +1879,7 @@ wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
&len);
break;
}
- wreq.wi_val[0] = htole16(sc->sc_dbm_adjust);
+ wreq.wi_val[0] = htole16(sc->sc_dbm_offset);
len = sizeof(u_int16_t);
break;
@@ -2608,6 +2650,12 @@ wi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen);
/* XXX validate channel */
ni->ni_chan = &ic->ic_channels[le16toh(val)];
+#if NBPFILTER > 0
+ sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
+ htole16(ni->ni_chan->ic_freq);
+ sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
+ htole16(ni->ni_chan->ic_flags);
+#endif
if (IEEE80211_ADDR_EQ(old_bssid, ni->ni_bssid))
sc->sc_false_syns++;
diff --git a/sys/dev/wi/if_wi_pccard.c b/sys/dev/wi/if_wi_pccard.c
index f5fb334..23d3f2e 100644
--- a/sys/dev/wi/if_wi_pccard.c
+++ b/sys/dev/wi/if_wi_pccard.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <net/if_types.h>
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
#include <dev/pccard/pccardvar.h>
#if __FreeBSD_version >= 500000
@@ -69,8 +70,8 @@ __FBSDID("$FreeBSD$");
#endif
#include <dev/wi/if_wavelan_ieee.h>
-#include <dev/wi/if_wivar.h>
#include <dev/wi/if_wireg.h>
+#include <dev/wi/if_wivar.h>
#ifdef WI_SYMBOL_FIRMWARE
#include <dev/wi/spectrum24t_cf.h>
#endif
diff --git a/sys/dev/wi/if_wi_pci.c b/sys/dev/wi/if_wi_pci.c
index 78dd0a2..6639fc1 100644
--- a/sys/dev/wi/if_wi_pci.c
+++ b/sys/dev/wi/if_wi_pci.c
@@ -62,10 +62,11 @@
#include <net/if_types.h>
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
#include <dev/wi/if_wavelan_ieee.h>
-#include <dev/wi/if_wivar.h>
#include <dev/wi/if_wireg.h>
+#include <dev/wi/if_wivar.h>
static int wi_pci_probe(device_t);
static int wi_pci_attach(device_t);
diff --git a/sys/dev/wi/if_wireg.h b/sys/dev/wi/if_wireg.h
index a415405..5d17211 100644
--- a/sys/dev/wi/if_wireg.h
+++ b/sys/dev/wi/if_wireg.h
@@ -679,3 +679,39 @@ struct wi_frame {
*/
#define WI_HFA386X_CR_A_D_TEST_MODES2 0x1A
#define WI_HFA386X_CR_MANUAL_TX_POWER 0x3E
+
+#ifdef IEEE80211_RADIOTAP_F_CFP
+/*
+ * Radio capture format for Prism.
+ */
+#define WI_RX_RADIOTAP_PRESENT0 \
+ ((1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_RATE) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \
+ (1 << IEEE80211_RADIOTAP_DB_ANTNOISE) | \
+ (1 << IEEE80211_RADIOTAP_EXT))
+
+#define WI_RX_RADIOTAP_PRESENT1 (1 << (IEEE80211_RADIOTAP_TIME - 32))
+
+struct wi_rx_radiotap_header {
+ struct ieee80211_radiotap_header wr_ihdr;
+ u_int32_t wr_present1;
+ u_int8_t wr_flags;
+ u_int8_t wr_rate;
+ u_int16_t wr_chan_freq;
+ u_int16_t wr_chan_flags;
+ u_int8_t wr_antsignal;
+ u_int8_t wr_antnoise;
+ u_int32_t wr_time;
+};
+
+#define WI_TX_RADIOTAP_PRESENT \
+ ((1 << IEEE80211_RADIOTAP_CHANNEL))
+
+struct wi_tx_radiotap_header {
+ struct ieee80211_radiotap_header wt_ihdr;
+ u_int16_t wt_chan_freq;
+ u_int16_t wt_chan_flags;
+};
+#endif /* IEEE80211_RADIOTAP_F_CFP */
diff --git a/sys/dev/wi/if_wivar.h b/sys/dev/wi/if_wivar.h
index 0ec3df3..dbfc627 100644
--- a/sys/dev/wi/if_wivar.h
+++ b/sys/dev/wi/if_wivar.h
@@ -106,7 +106,11 @@ struct wi_softc {
u_int16_t sc_procframe;
u_int16_t sc_portnum;
- u_int16_t sc_dbm_adjust;
+ /* RSSI interpretation */
+ u_int16_t sc_min_rssi; /* clamp sc_min_rssi < RSSI */
+ u_int16_t sc_max_rssi; /* clamp RSSI < sc_max_rssi */
+ u_int16_t sc_dbm_offset; /* dBm ~ RSSI - sc_dbm_offset */
+
u_int16_t sc_max_datalen;
u_int16_t sc_system_scale;
u_int16_t sc_cnfauthmode;
@@ -158,8 +162,19 @@ struct wi_softc {
int sc_false_syns;
u_int16_t sc_txbuf[IEEE80211_MAX_LEN/2];
+
+ union {
+ struct wi_tx_radiotap_header th;
+ u_int8_t pad[64];
+ } u_tx_rt;
+ union {
+ struct wi_rx_radiotap_header th;
+ u_int8_t pad[64];
+ } u_rx_rt;
};
#define sc_if sc_ic.ic_if
+#define sc_tx_th u_tx_rt.th
+#define sc_rx_th u_rx_rt.th
/* maximum consecutive false change-of-BSSID indications */
#define WI_MAX_FALSE_SYNS 10
@@ -184,6 +199,17 @@ struct wi_card_ident {
u_int8_t firm_type;
};
+#define WI_PRISM_MIN_RSSI 0x1b
+#define WI_PRISM_MAX_RSSI 0x9a
+#define WI_PRISM_DBM_OFFSET 100 /* XXX */
+
+#define WI_LUCENT_MIN_RSSI 47
+#define WI_LUCENT_MAX_RSSI 138
+#define WI_LUCENT_DBM_OFFSET 149
+
+#define WI_RSSI_TO_DBM(sc, rssi) (MIN((sc)->sc_max_rssi, \
+ MAX((sc)->sc_min_rssi, (rssi))) - (sc)->sc_dbm_offset)
+
#if __FreeBSD_version < 500000
/*
* Various compat hacks/kludges
OpenPOWER on IntegriCloud