Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 31 Dec 2012 07:50:03 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r244898 - user/adrian/ath_radar_stuff/lib/libradarpkt
Message-ID:  <201212310750.qBV7o3Z3086641@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Mon Dec 31 07:50:02 2012
New Revision: 244898
URL: http://svnweb.freebsd.org/changeset/base/244898

Log:
  Begin fleshing out support to parse HT20 spectral scan samples.
  
  These haven't yet even remotely been verified as correct; please don't
  try to use it.
  
  The frequency is hard-coded; I need to decode ic_freq.
  
  Also, it's assuming HT20 format; I need to decode the MCS channel flags
  from the radiotap header to determine whether it's a HT20 or HT40 channel
  (and subsequent channel configuration for pri/ext frequencies.)

Modified:
  user/adrian/ath_radar_stuff/lib/libradarpkt/ar9280_radar.c
  user/adrian/ath_radar_stuff/lib/libradarpkt/pkt.h

Modified: user/adrian/ath_radar_stuff/lib/libradarpkt/ar9280_radar.c
==============================================================================
--- user/adrian/ath_radar_stuff/lib/libradarpkt/ar9280_radar.c	Mon Dec 31 07:30:07 2012	(r244897)
+++ user/adrian/ath_radar_stuff/lib/libradarpkt/ar9280_radar.c	Mon Dec 31 07:50:02 2012	(r244898)
@@ -45,11 +45,164 @@
 #include "pkt.h"
 #include "ar9280_radar.h"
 
+/* Relevant on Merlin and later */
+#define	CH_SPECTRAL_EVENT		0x10
 /* Relevant for Sowl and later */
 #define	EXT_CH_RADAR_EARLY_FOUND	0x04
 #define	EXT_CH_RADAR_FOUND	0x02
 #define	PRI_CH_RADAR_FOUND	0x01
 
+#define	AR9280_SPECTRAL_SAMPLE_SIZE_HT20	60
+#define	AR9280_SPECTRAL_SAMPLE_SIZE_HT40	135
+
+/*
+ * GPLed snippet from Zefir on the linux-wireless list; rewrite this
+ * soon!
+ */
+#if 0
+/*
+ * In my system the post-processed FFT raw data is transferred via a netlink
+ * interface to a spectral_proxy, that forwards it to a connected host for real-time
+ * inspection and visualization.
+
+ * The interpretation of the data is as follows: the reported values are given as
+ * magnitudes, which need to be scaled and converted to absolute power values based
+ * on the packets noise floor and RSSI values as follows:
+ * bin_sum = 10*log(sum[i=1..56](b(i)^2)
+ * power(i) = noise_floor + RSSI + 10*log(b(i)^2) - bin_sum
+
+ * The code fragment to convert magnitude to absolute power values looks like this
+ * (assuming you transferred the FFT and magnitude data to user space):
+*/
+bool
+convert_data(struct spectral_ht20_msg *msg)
+{
+       uint8_t *bin_pwr = msg->bin;
+       uint8_t *dc_pwr = msg->bin + SPECTRAL_NUM_BINS / 2;
+       int pwr_count = SPECTRAL_NUM_BINS;
+       int8_t rssi = msg->rssi;
+       int8_t max_scale = 1 << msg->max_exp;
+       int16_t max_mag = msg->max_magnitude;
+       int i;
+       int nf0 = msg->noise_floor;
+
+       float bsum = 0.0;
+
+       // DC value is invalid -> interpolate
+       *dc_pwr = (dc_pwr[-1] + dc_pwr[1]) / 2;
+
+       for (i = 0; i < pwr_count; i++)
+               bsum += (bin_pwr[i] * max_scale) * (bin_pwr[i] * max_scale);
+       bsum = log10f(bsum) * 10;
+
+       for (i = 0; i < pwr_count; i++) {
+               float pwr_val;
+               int16_t val = bin_pwr[i];
+
+               if (val == 0)
+                       val = 1;
+
+               pwr_val = 20 * log10f((float) val * max_scale);
+               pwr_val += nf0 + rssi - bsum;
+
+               val = pwr_val;
+               bin_pwr[i] = val;
+       }
+       return true;
+}
+#endif
+
+/* XXX why do we need this? */
+static int8_t
+fix_max_index(uint8_t max_index)
+{
+       int8_t maxindex = max_index;
+       if (max_index > 32)
+               maxindex |= 0xe0;
+       else
+               maxindex &= ~0xe0;
+       maxindex += 29;
+       return maxindex;
+}
+
+static int
+ar9280_radar_spectral_decode_ht20(struct ieee80211_radiotap_header *rh,
+    const unsigned char *pkt, int len, struct radar_entry *re,
+    int cur_sample)
+{
+	int i;
+	struct radar_fft_entry *fe;
+
+	if (len < AR9280_SPECTRAL_SAMPLE_SIZE_HT20) {
+		return (-1);
+	}
+
+	fe = &re->re_spectral_entries[cur_sample];
+
+	/* Decode the bitmap weight, magnitude, max index */
+
+	fe->pri.max_magnitude =
+	    (pkt[57] << 2) |
+	    ((pkt[56] & 0xc0) >> 6) |
+	    ((pkt[58] & 0x03) << 10);
+	fe->pri.bitmap_weight = pkt[56] & 0x3f;
+	fe->pri.max_index = fix_max_index(pkt[58] & 0x3f);
+	fe->max_exp = pkt[59] & 0x0f;
+
+	/* Decode each bin - the dBm calculation will come later */
+	for (i = 0; i < 56; i++) {
+		fe->pri.bins[i].raw_mag = pkt[i];
+		fe->pri.bins[i].adj_mag = fe->pri.bins[i].raw_mag << fe->max_exp;
+	}
+
+	/* Return OK */
+	return (0);
+}
+
+/*
+ * Decode a spectral scan frame, complete with whatever
+ * hilarity / bugs ensue.
+ *
+ * The known quirks:
+ *
+ * + The MAC may corrupt a frame - inserting, deleting
+ *   and/or realigning things.
+ * + The FFT data can terminate at any time; there's no
+ *   guarantee that we'll get a complete frame.
+ *
+ * Let's not handle these for now; we'll just tinker with this
+ * in the future.
+ */
+static int
+ar9280_radar_spectral_decode(struct ieee80211_radiotap_header *rh,
+    const unsigned char *pkt, int len, struct radar_entry *re)
+{
+	int i;
+	const unsigned char *fr = pkt;
+	int fr_len = len;
+
+	
+	for (i = 0; i < MAX_SPECTRAL_SCAN_SAMPLES_PER_PKT; i++) {
+		/* HT20 or HT40? */
+		/* XXX hard-code HT20 */
+		if (ar9280_radar_spectral_decode_ht20(rh, fr, fr_len, re, i) != 0) {
+			break;
+		}
+		fr_len -= AR9280_SPECTRAL_SAMPLE_SIZE_HT20;
+		fr += AR9280_SPECTRAL_SAMPLE_SIZE_HT20;
+		if (fr_len < 0)
+			break;
+	}
+
+//	printf("  Spectral: %d samples\n", i);
+	re->re_num_spectral_entries = i;
+
+	return (0);
+}
+
+/*
+ * Decode a normal radar frame.
+ */
 int
 ar9280_radar_decode(struct ieee80211_radiotap_header *rh,
     const unsigned char *pkt, int len, struct radar_entry *re)
@@ -93,10 +246,11 @@ ar9280_radar_decode(struct ieee80211_rad
 	printf(", pri/ext rssi: %d/%d", pri_rssi, ext_rssi);
 	printf(" pri: %u", pkt[len - 3] & 0xff);
 	printf(" ext: %u", pkt[len - 2] & 0xff);
-	printf(" flags: %s %s %s\n",
+	printf(" flags: %s %s %s %s\n",
 	    pkt[len - 1] & PRI_CH_RADAR_FOUND ? "pri" : "",
 	    pkt[len - 1] & EXT_CH_RADAR_FOUND ? "ext" : "",
-	    pkt[len - 1] & EXT_CH_RADAR_EARLY_FOUND ? "extearly" : ""
+	    pkt[len - 1] & EXT_CH_RADAR_EARLY_FOUND ? "extearly" : "",
+	    pkt[len - 1] & CH_SPECTRAL_EVENT ? "spectral" : ""
 	    );
 #endif
 
@@ -124,8 +278,13 @@ ar9280_radar_decode(struct ieee80211_rad
 	re->re_timestamp = tsf;
 	re->re_rssi = pri_rssi;	/* XXX extension rssi? */
 	re->re_dur = pkt[len - 3];	/* XXX extension duration? */
-	re->re_freq = 0;
+	re->re_freq = 2412;	/* XXX DO this! */
+	re->re_num_spectral_entries = 0;
 	/* XXX flags? */
 
+	if (pkt[len - 1] & CH_SPECTRAL_EVENT) {
+		(void) ar9280_radar_spectral_decode(rh, pkt, len - 3, re);
+	}
+
 	return(1);
 }

Modified: user/adrian/ath_radar_stuff/lib/libradarpkt/pkt.h
==============================================================================
--- user/adrian/ath_radar_stuff/lib/libradarpkt/pkt.h	Mon Dec 31 07:30:07 2012	(r244897)
+++ user/adrian/ath_radar_stuff/lib/libradarpkt/pkt.h	Mon Dec 31 07:50:02 2012	(r244898)
@@ -35,6 +35,31 @@
 extern "C" {
 #endif
 
+#define	PKT_NUM_BINS	64
+
+#define	MAX_SPECTRAL_SCAN_SAMPLES_PER_PKT	64
+
+struct radar_fft_bin {
+	int32_t	dBm;
+	int32_t	adj_mag;
+	uint8_t	raw_mag;	/* original magnitude */
+	uint8_t	bitmap;	/* whether this is strong/weak */
+	uint8_t	pad[2];
+};
+
+struct radar_fft_entry {
+	int is_ht40;	/* 1=HT40, 0=HT20 */
+
+	struct {
+		struct radar_fft_bin bins[PKT_NUM_BINS];
+		uint8_t	max_index;
+		uint8_t	bitmap_weight;
+		uint16_t	max_magnitude;
+	} pri, ext;
+
+	uint8_t	max_exp;
+};
+
 struct radar_entry {
 	uint64_t	re_timestamp;
 	uint32_t	re_freq;
@@ -45,6 +70,10 @@ struct radar_entry {
 	 */
 	int32_t		re_rssi;
 	uint32_t	re_dur;
+
+	/* XXX make these optional at some point */
+	int 		re_num_spectral_entries;
+	struct radar_fft_entry re_spectral_entries[MAX_SPECTRAL_SCAN_SAMPLES_PER_PKT];
 };
 
 #ifdef	__cplusplus



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212310750.qBV7o3Z3086641>