Date: Tue, 1 Jan 2013 20:19:09 -0800 From: Adrian Chadd <adrian@freebsd.org> To: freebsd-wireless@freebsd.org Subject: Skeleton spectral scan driver support is in -HEAD (was Re: svn commit: r244953 - in head/tools/tools/ath: . athspectral) Message-ID: <CAJ-VmomtPvAprXBV9qSgm7H_Od4kiNrnc64o-6pxDD9T9e6COg@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
... and with that, anyone wishing to write a spectral scan visualisation application now has all the basic bits they need to do so. ie: * create interface in monitor mode * sysctl dev.ath.0.monpass=0xff (just to ensure you get spectral scan errors) * ifconfig wlan0 channel 1:ht/20 * ifconfig wlan0 up * athspectral -i ath0 start * sleep 0.5 * ifconfig wlan0 down ; ifconfig wlan0 channel 6:ht/20; ifconfig wlan0 up * athspectral -i ath0 start * sleep 0.5 * ifconfig wlan0 down ; ifconfig wlan0 channel 11:ht/20; ifconfig wlan0 up * athspectral -i ath0 start * sleep 0.5 ... etc. All someone(!) now needs to do is write an application that sniffs the spectral scan FFT data from a radiotap interface and you're done. There's more interesting things one can do (eg not use the short repeat functionality, so you get big sets of continuous spectral scan reports; play with "continuous" reporting, etc.) once the basic FFT visualisation is done. Go forth and do interesting things. Oh, and please open source some of them. :) Adrian On 1 January 2013 20:02, Adrian Chadd <adrian@freebsd.org> wrote: > Author: adrian > Date: Wed Jan 2 04:02:27 2013 > New Revision: 244953 > URL: http://svnweb.freebsd.org/changeset/base/244953 > > Log: > Add a very skeletal spectral scan control application. > > The main use for this is to manually trigger spectral scan operations > (athspectral -i athX start) whilst doing debugging. > > Added: > head/tools/tools/ath/athspectral/ > head/tools/tools/ath/athspectral/Makefile (contents, props changed) > head/tools/tools/ath/athspectral/athspectral.c (contents, props changed) > Modified: > head/tools/tools/ath/Makefile > > Modified: head/tools/tools/ath/Makefile > ============================================================================== > --- head/tools/tools/ath/Makefile Wed Jan 2 04:00:54 2013 (r244952) > +++ head/tools/tools/ath/Makefile Wed Jan 2 04:02:27 2013 (r244953) > @@ -3,6 +3,6 @@ > SUBDIR= arcode athdebug athdecode athkey athpoke athprom athrd athregs > SUBDIR+= athstats ath_prom_read athradar athaggrstats > SUBDIR+= ath_ee_v14_print ath_ee_v4k_print ath_ee_9287_print > -SUBDIR+= athsurvey athratestats > +SUBDIR+= athsurvey athratestats athspectral > > .include <bsd.subdir.mk> > > Added: head/tools/tools/ath/athspectral/Makefile > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/tools/tools/ath/athspectral/Makefile Wed Jan 2 04:02:27 2013 (r244953) > @@ -0,0 +1,16 @@ > +# $FreeBSD$ > + > +PROG= athspectral > + > +.include <../Makefile.inc> > + > +SRCS= athspectral.c > +SRCS+= opt_ah.h > +CLEANFILES+= opt_ah.h > + > +opt_ah.h: > + echo "#define AH_DEBUG 1" > opt_ah.h > + echo "#define AH_DEBUG_COUNTRY 1" >> opt_ah.h > + echo "#define AH_SUPPORT_AR5416 1" >> opt_ah.h > + > +.include <bsd.prog.mk> > > Added: head/tools/tools/ath/athspectral/athspectral.c > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/tools/tools/ath/athspectral/athspectral.c Wed Jan 2 04:02:27 2013 (r244953) > @@ -0,0 +1,323 @@ > +/* > + * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + * > + * $FreeBSD$ > + */ > + > +#include "diag.h" > + > +#include "ah.h" > +#include "ah_internal.h" > + > +#ifndef ATH_DEFAULT > +#define ATH_DEFAULT "ath0" > +#endif > + > +#include <getopt.h> > +#include <errno.h> > +#include <err.h> > +#include <stdlib.h> > +#include <string.h> > +#include <ctype.h> > +#include <unistd.h> > + > +struct spectralhandler { > + struct ath_diag atd; > + int s; > + struct ifreq ifr; > + int ah_devid; > +}; > + > +int > +spectral_opendev(struct spectralhandler *spectral, const char *devid) > +{ > + HAL_REVS revs; > + > + spectral->s = socket(AF_INET, SOCK_DGRAM, 0); > + if (spectral->s < 0) { > + warn("socket"); > + return 0; > + } > + > + strncpy(spectral->atd.ad_name, devid, sizeof (spectral->atd.ad_name)); > + > + /* Get the hardware revision, just to verify things are working */ > + spectral->atd.ad_id = HAL_DIAG_REVS; > + spectral->atd.ad_out_data = (caddr_t) &revs; > + spectral->atd.ad_out_size = sizeof(revs); > + if (ioctl(spectral->s, SIOCGATHDIAG, &spectral->atd) < 0) { > + warn(spectral->atd.ad_name); > + return 0; > + } > + spectral->ah_devid = revs.ah_devid; > + return 1; > +} > + > +void > +spectral_closedev(struct spectralhandler *spectral) > +{ > + close(spectral->s); > + spectral->s = -1; > +} > + > +void > +spectralset(struct spectralhandler *spectral, int op, u_int32_t param) > +{ > + HAL_SPECTRAL_PARAM pe; > + > + pe.ss_fft_period = HAL_SPECTRAL_PARAM_NOVAL; > + pe.ss_period = HAL_SPECTRAL_PARAM_NOVAL; > + pe.ss_count = HAL_SPECTRAL_PARAM_NOVAL; > + pe.ss_short_report = HAL_SPECTRAL_PARAM_NOVAL; > + pe.ss_spectral_pri = HAL_SPECTRAL_PARAM_NOVAL; > + pe.ss_fft_period = HAL_SPECTRAL_PARAM_NOVAL; > + pe.ss_enabled = HAL_SPECTRAL_PARAM_NOVAL; > + pe.ss_active = HAL_SPECTRAL_PARAM_NOVAL; > + > + switch (op) { > + case SPECTRAL_PARAM_FFT_PERIOD: > + pe.ss_fft_period = param; > + break; > + case SPECTRAL_PARAM_SS_PERIOD: > + pe.ss_period = param; > + break; > + case SPECTRAL_PARAM_SS_COUNT: > + pe.ss_count = param; > + break; > + case SPECTRAL_PARAM_SS_SHORT_RPT: > + pe.ss_short_report = param; > + break; > + } > + > + spectral->atd.ad_id = SPECTRAL_CONTROL_SET_PARAMS | ATH_DIAG_IN; > + spectral->atd.ad_out_data = NULL; > + spectral->atd.ad_out_size = 0; > + spectral->atd.ad_in_data = (caddr_t) &pe; > + spectral->atd.ad_in_size = sizeof(HAL_SPECTRAL_PARAM); > + if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) > + err(1, spectral->atd.ad_name); > +} > + > +static void > +spectral_get(struct spectralhandler *spectral) > +{ > + HAL_SPECTRAL_PARAM pe; > + > + spectral->atd.ad_id = SPECTRAL_CONTROL_GET_PARAMS | ATH_DIAG_DYN; > + memset(&pe, 0, sizeof(pe)); > + > + spectral->atd.ad_in_data = NULL; > + spectral->atd.ad_in_size = 0; > + spectral->atd.ad_out_data = (caddr_t) &pe; > + spectral->atd.ad_out_size = sizeof(pe); > + > + if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) > + err(1, spectral->atd.ad_name); > + > + printf("Spectral parameters (raw):\n"); > + printf(" ss_enabled: %d\n", pe.ss_enabled); > + printf(" ss_active: %d\n", pe.ss_active); > + printf(" ss_count: %d\n", pe.ss_count); > + printf(" ss_fft_period: %d\n", pe.ss_fft_period); > + printf(" ss_period: %d\n", pe.ss_period); > + printf(" ss_short_report: %d\n", pe.ss_short_report); > + printf(" radar_bin_thresh_sel: %d\n", pe.radar_bin_thresh_sel); > +} > + > +static void > +spectral_start(struct spectralhandler *spectral) > +{ > + HAL_SPECTRAL_PARAM pe; > + > + spectral->atd.ad_id = SPECTRAL_CONTROL_START | ATH_DIAG_DYN; > + memset(&pe, 0, sizeof(pe)); > + > + /* > + * XXX don't need these, but need to eliminate the ATH_DIAG_DYN flag > + * and debug > + */ > + spectral->atd.ad_in_data = NULL; > + spectral->atd.ad_in_size = 0; > + spectral->atd.ad_out_data = (caddr_t) &pe; > + spectral->atd.ad_out_size = sizeof(pe); > + > + if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) > + err(1, spectral->atd.ad_name); > +} > + > +static void > +spectral_stop(struct spectralhandler *spectral) > +{ > + HAL_SPECTRAL_PARAM pe; > + > + spectral->atd.ad_id = SPECTRAL_CONTROL_STOP | ATH_DIAG_DYN; > + memset(&pe, 0, sizeof(pe)); > + > + /* > + * XXX don't need these, but need to eliminate the ATH_DIAG_DYN flag > + * and debug > + */ > + spectral->atd.ad_in_data = NULL; > + spectral->atd.ad_in_size = 0; > + spectral->atd.ad_out_data = (caddr_t) &pe; > + spectral->atd.ad_out_size = sizeof(pe); > + > + if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) > + err(1, spectral->atd.ad_name); > +} > + > +static int > +spectral_set_param(struct spectralhandler *spectral, const char *param, > + const char *val) > +{ > + int v; > + > + v = atoi(val); > + > + if (strcmp(param, "ss_short_report") == 0) { > + spectralset(spectral, SPECTRAL_PARAM_SS_SHORT_RPT, v); > + } else if (strcmp(param, "ss_fft_period") == 0) { > + spectralset(spectral, SPECTRAL_PARAM_FFT_PERIOD, v); > + } else if (strcmp(param, "ss_period") == 0) { > + spectralset(spectral, SPECTRAL_PARAM_SS_PERIOD, v); > + } else if (strcmp(param, "ss_count") == 0) { > + spectralset(spectral, SPECTRAL_PARAM_SS_COUNT, v); > + } else { > + return (0); > + } > + > +#if 0 > + if (strcmp(param, "enabled") == 0) { > + spectralset(spectral, DFS_PARAM_ENABLE, v); > + } else if (strcmp(param, "firpwr") == 0) { > + spectralset(spectral, DFS_PARAM_FIRPWR, v); > + } else if (strcmp(param, "rrssi") == 0) { > + spectralset(spectral, DFS_PARAM_RRSSI, v); > + } else if (strcmp(param, "height") == 0) { > + spectralset(spectral, DFS_PARAM_HEIGHT, v); > + } else if (strcmp(param, "prssi") == 0) { > + spectralset(spectral, DFS_PARAM_PRSSI, v); > + } else if (strcmp(param, "inband") == 0) { > + spectralset(spectral, DFS_PARAM_INBAND, v); > + } else if (strcmp(param, "relpwr") == 0) { > + spectralset(spectral, DFS_PARAM_RELPWR, v); > + } else if (strcmp(param, "relstep") == 0) { > + spectralset(spectral, DFS_PARAM_RELSTEP, v); > + } else if (strcmp(param, "maxlen") == 0) { > + spectralset(spectral, DFS_PARAM_MAXLEN, v); > + } else if (strcmp(param, "usefir128") == 0) { > + spectralset(spectral, DFS_PARAM_USEFIR128, v); > + } else if (strcmp(param, "blockspectral") == 0) { > + spectralset(spectral, DFS_PARAM_BLOCKRADAR, v); > + } else if (strcmp(param, "enmaxrssi") == 0) { > + spectralset(spectral, DFS_PARAM_MAXRSSI_EN, v); > + } else if (strcmp(param, "extchannel") == 0) { > + spectralset(spectral, DFS_PARAM_EN_EXTCH, v); > + } else if (strcmp(param, "enrelpwr") == 0) { > + spectralset(spectral, DFS_PARAM_RELPWR_EN, v); > + } else if (strcmp(param, "en_relstep_check") == 0) { > + spectralset(spectral, DFS_PARAM_RELSTEP_EN, v); > + } else { > + return 0; > + } > +#endif > + > + return 1; > +} > + > +void > +usage(const char *progname) > +{ > + printf("Usage:\n"); > + printf("\t%s: [-i <interface>] <cmd> (<arg>)\n", progname); > + printf("\t%s: [-h]\n", progname); > + printf("\n"); > + printf("Valid commands:\n"); > + printf("\tget:\t\tGet current spectral parameters\n"); > + printf("\tset <param> <value>:\t\tSet spectral parameter\n"); > + printf("\tstart: Start spectral scan\n"); > + printf("\tstop: Stop spectral scan\n"); > +} > + > +int > +main(int argc, char *argv[]) > +{ > + struct spectralhandler spectral; > + const char *devname = ATH_DEFAULT; > + const char *progname = argv[0]; > + > + memset(&spectral, 0, sizeof(spectral)); > + > + /* Parse command line options */ > + if (argc >= 2 && strcmp(argv[1], "-h") == 0) { > + usage(progname); > + exit(0); > + } > + if (argc >= 2 && strcmp(argv[1], "-?") == 0) { > + usage(progname); > + exit(0); > + } > + > + if (argc >= 2 && strcmp(argv[1], "-i") == 0) { > + if (argc == 2) { > + usage(progname); > + exit(127); > + } > + devname = argv[2]; > + argc -= 2; argv += 2; > + } > + > + /* At this point we require at least one command */ > + if (argc == 1) { > + usage(progname); > + exit(127); > + } > + > + if (spectral_opendev(&spectral, devname) == 0) > + exit(127); > + > + if (strcasecmp(argv[1], "get") == 0) { > + spectral_get(&spectral); > + } else if (strcasecmp(argv[1], "set") == 0) { > + if (argc < 4) { > + usage(progname); > + exit(127); > + } > + if (spectral_set_param(&spectral, argv[2], argv[3]) == 0) { > + usage(progname); > + exit(127); > + } > + } else if (strcasecmp(argv[1], "start") == 0) { > + spectral_start(&spectral); > + } else if (strcasecmp(argv[1], "stop") == 0) { > + spectral_stop(&spectral); > + } else { > + usage(progname); > + exit(127); > + } > + > + /* wrap up */ > + spectral_closedev(&spectral); > + exit(0); > +}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJ-VmomtPvAprXBV9qSgm7H_Od4kiNrnc64o-6pxDD9T9e6COg>