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>