1244953Sadrian/* 2244953Sadrian * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 3244953Sadrian * 4244953Sadrian * Redistribution and use in source and binary forms, with or without 5244953Sadrian * modification, are permitted provided that the following conditions 6244953Sadrian * are met: 7244953Sadrian * 1. Redistributions of source code must retain the above copyright 8244953Sadrian * notice, this list of conditions and the following disclaimer. 9244953Sadrian * 2. Redistributions in binary form must reproduce the above copyright 10244953Sadrian * notice, this list of conditions and the following disclaimer in the 11244953Sadrian * documentation and/or other materials provided with the distribution. 12244953Sadrian * 13244953Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14244953Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15244953Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16244953Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17244953Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18244953Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19244953Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20244953Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21244953Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22244953Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23244953Sadrian * SUCH DAMAGE. 24244953Sadrian * 25244953Sadrian * $FreeBSD$ 26244953Sadrian */ 27244953Sadrian 28244953Sadrian#include "diag.h" 29244953Sadrian 30244953Sadrian#include "ah.h" 31244953Sadrian#include "ah_internal.h" 32244953Sadrian 33244953Sadrian#ifndef ATH_DEFAULT 34244953Sadrian#define ATH_DEFAULT "ath0" 35244953Sadrian#endif 36244953Sadrian 37244953Sadrian#include <getopt.h> 38244953Sadrian#include <errno.h> 39244953Sadrian#include <err.h> 40244953Sadrian#include <stdlib.h> 41244953Sadrian#include <string.h> 42244953Sadrian#include <ctype.h> 43244953Sadrian#include <unistd.h> 44244953Sadrian 45244953Sadrianstruct spectralhandler { 46244953Sadrian struct ath_diag atd; 47244953Sadrian int s; 48244953Sadrian struct ifreq ifr; 49244953Sadrian int ah_devid; 50244953Sadrian}; 51244953Sadrian 52244953Sadrianint 53244953Sadrianspectral_opendev(struct spectralhandler *spectral, const char *devid) 54244953Sadrian{ 55244953Sadrian HAL_REVS revs; 56244953Sadrian 57244953Sadrian spectral->s = socket(AF_INET, SOCK_DGRAM, 0); 58244953Sadrian if (spectral->s < 0) { 59244953Sadrian warn("socket"); 60244953Sadrian return 0; 61244953Sadrian } 62244953Sadrian 63244953Sadrian strncpy(spectral->atd.ad_name, devid, sizeof (spectral->atd.ad_name)); 64244953Sadrian 65244953Sadrian /* Get the hardware revision, just to verify things are working */ 66244953Sadrian spectral->atd.ad_id = HAL_DIAG_REVS; 67244953Sadrian spectral->atd.ad_out_data = (caddr_t) &revs; 68244953Sadrian spectral->atd.ad_out_size = sizeof(revs); 69244953Sadrian if (ioctl(spectral->s, SIOCGATHDIAG, &spectral->atd) < 0) { 70251737Sadrian warn("%s", spectral->atd.ad_name); 71244953Sadrian return 0; 72244953Sadrian } 73244953Sadrian spectral->ah_devid = revs.ah_devid; 74244953Sadrian return 1; 75244953Sadrian} 76244953Sadrian 77244953Sadrianvoid 78244953Sadrianspectral_closedev(struct spectralhandler *spectral) 79244953Sadrian{ 80244953Sadrian close(spectral->s); 81244953Sadrian spectral->s = -1; 82244953Sadrian} 83244953Sadrian 84244953Sadrianvoid 85244953Sadrianspectralset(struct spectralhandler *spectral, int op, u_int32_t param) 86244953Sadrian{ 87244953Sadrian HAL_SPECTRAL_PARAM pe; 88244953Sadrian 89244953Sadrian pe.ss_fft_period = HAL_SPECTRAL_PARAM_NOVAL; 90244953Sadrian pe.ss_period = HAL_SPECTRAL_PARAM_NOVAL; 91244953Sadrian pe.ss_count = HAL_SPECTRAL_PARAM_NOVAL; 92244953Sadrian pe.ss_short_report = HAL_SPECTRAL_PARAM_NOVAL; 93244953Sadrian pe.ss_spectral_pri = HAL_SPECTRAL_PARAM_NOVAL; 94244953Sadrian pe.ss_fft_period = HAL_SPECTRAL_PARAM_NOVAL; 95244953Sadrian pe.ss_enabled = HAL_SPECTRAL_PARAM_NOVAL; 96244953Sadrian pe.ss_active = HAL_SPECTRAL_PARAM_NOVAL; 97244953Sadrian 98244953Sadrian switch (op) { 99244953Sadrian case SPECTRAL_PARAM_FFT_PERIOD: 100244953Sadrian pe.ss_fft_period = param; 101244953Sadrian break; 102244953Sadrian case SPECTRAL_PARAM_SS_PERIOD: 103244953Sadrian pe.ss_period = param; 104244953Sadrian break; 105244953Sadrian case SPECTRAL_PARAM_SS_COUNT: 106244953Sadrian pe.ss_count = param; 107244953Sadrian break; 108244953Sadrian case SPECTRAL_PARAM_SS_SHORT_RPT: 109244953Sadrian pe.ss_short_report = param; 110244953Sadrian break; 111244953Sadrian } 112244953Sadrian 113244953Sadrian spectral->atd.ad_id = SPECTRAL_CONTROL_SET_PARAMS | ATH_DIAG_IN; 114244953Sadrian spectral->atd.ad_out_data = NULL; 115244953Sadrian spectral->atd.ad_out_size = 0; 116244953Sadrian spectral->atd.ad_in_data = (caddr_t) &pe; 117244953Sadrian spectral->atd.ad_in_size = sizeof(HAL_SPECTRAL_PARAM); 118244953Sadrian if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) 119251737Sadrian err(1, "%s", spectral->atd.ad_name); 120244953Sadrian} 121244953Sadrian 122244953Sadrianstatic void 123244953Sadrianspectral_get(struct spectralhandler *spectral) 124244953Sadrian{ 125244953Sadrian HAL_SPECTRAL_PARAM pe; 126244953Sadrian 127244953Sadrian spectral->atd.ad_id = SPECTRAL_CONTROL_GET_PARAMS | ATH_DIAG_DYN; 128244953Sadrian memset(&pe, 0, sizeof(pe)); 129244953Sadrian 130244953Sadrian spectral->atd.ad_in_data = NULL; 131244953Sadrian spectral->atd.ad_in_size = 0; 132244953Sadrian spectral->atd.ad_out_data = (caddr_t) &pe; 133244953Sadrian spectral->atd.ad_out_size = sizeof(pe); 134244953Sadrian 135244953Sadrian if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) 136251737Sadrian err(1, "%s", spectral->atd.ad_name); 137244953Sadrian 138244953Sadrian printf("Spectral parameters (raw):\n"); 139244953Sadrian printf(" ss_enabled: %d\n", pe.ss_enabled); 140244953Sadrian printf(" ss_active: %d\n", pe.ss_active); 141244953Sadrian printf(" ss_count: %d\n", pe.ss_count); 142244953Sadrian printf(" ss_fft_period: %d\n", pe.ss_fft_period); 143244953Sadrian printf(" ss_period: %d\n", pe.ss_period); 144244953Sadrian printf(" ss_short_report: %d\n", pe.ss_short_report); 145244953Sadrian printf(" radar_bin_thresh_sel: %d\n", pe.radar_bin_thresh_sel); 146244953Sadrian} 147244953Sadrian 148244953Sadrianstatic void 149244953Sadrianspectral_start(struct spectralhandler *spectral) 150244953Sadrian{ 151244953Sadrian HAL_SPECTRAL_PARAM pe; 152244953Sadrian 153244953Sadrian spectral->atd.ad_id = SPECTRAL_CONTROL_START | ATH_DIAG_DYN; 154244953Sadrian memset(&pe, 0, sizeof(pe)); 155244953Sadrian 156244953Sadrian /* 157244953Sadrian * XXX don't need these, but need to eliminate the ATH_DIAG_DYN flag 158244953Sadrian * and debug 159244953Sadrian */ 160244953Sadrian spectral->atd.ad_in_data = NULL; 161244953Sadrian spectral->atd.ad_in_size = 0; 162244953Sadrian spectral->atd.ad_out_data = (caddr_t) &pe; 163244953Sadrian spectral->atd.ad_out_size = sizeof(pe); 164244953Sadrian 165244953Sadrian if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) 166251737Sadrian err(1, "%s", spectral->atd.ad_name); 167244953Sadrian} 168244953Sadrian 169244953Sadrianstatic void 170244953Sadrianspectral_stop(struct spectralhandler *spectral) 171244953Sadrian{ 172244953Sadrian HAL_SPECTRAL_PARAM pe; 173244953Sadrian 174244953Sadrian spectral->atd.ad_id = SPECTRAL_CONTROL_STOP | ATH_DIAG_DYN; 175244953Sadrian memset(&pe, 0, sizeof(pe)); 176244953Sadrian 177244953Sadrian /* 178244953Sadrian * XXX don't need these, but need to eliminate the ATH_DIAG_DYN flag 179244953Sadrian * and debug 180244953Sadrian */ 181244953Sadrian spectral->atd.ad_in_data = NULL; 182244953Sadrian spectral->atd.ad_in_size = 0; 183244953Sadrian spectral->atd.ad_out_data = (caddr_t) &pe; 184244953Sadrian spectral->atd.ad_out_size = sizeof(pe); 185244953Sadrian 186244953Sadrian if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) 187251737Sadrian err(1, "%s", spectral->atd.ad_name); 188244953Sadrian} 189244953Sadrian 190245231Sadrianstatic void 191245231Sadrianspectral_enable_at_reset(struct spectralhandler *spectral, int val) 192245231Sadrian{ 193245231Sadrian int v = val; 194245231Sadrian 195245231Sadrian spectral->atd.ad_id = SPECTRAL_CONTROL_ENABLE_AT_RESET 196245231Sadrian | ATH_DIAG_IN; 197245231Sadrian 198245231Sadrian /* 199245231Sadrian * XXX don't need these, but need to eliminate the ATH_DIAG_DYN flag 200245231Sadrian * and debug 201245231Sadrian */ 202245231Sadrian spectral->atd.ad_out_data = NULL; 203245231Sadrian spectral->atd.ad_out_size = 0; 204245231Sadrian spectral->atd.ad_in_data = (caddr_t) &v; 205245231Sadrian spectral->atd.ad_in_size = sizeof(v); 206245231Sadrian 207245231Sadrian printf("%s: val=%d\n", __func__, v); 208245231Sadrian 209245231Sadrian if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) 210251737Sadrian err(1, "%s", spectral->atd.ad_name); 211245231Sadrian} 212245231Sadrian 213244953Sadrianstatic int 214244953Sadrianspectral_set_param(struct spectralhandler *spectral, const char *param, 215244953Sadrian const char *val) 216244953Sadrian{ 217244953Sadrian int v; 218244953Sadrian 219244953Sadrian v = atoi(val); 220244953Sadrian 221244953Sadrian if (strcmp(param, "ss_short_report") == 0) { 222244953Sadrian spectralset(spectral, SPECTRAL_PARAM_SS_SHORT_RPT, v); 223244953Sadrian } else if (strcmp(param, "ss_fft_period") == 0) { 224244953Sadrian spectralset(spectral, SPECTRAL_PARAM_FFT_PERIOD, v); 225244953Sadrian } else if (strcmp(param, "ss_period") == 0) { 226244953Sadrian spectralset(spectral, SPECTRAL_PARAM_SS_PERIOD, v); 227244953Sadrian } else if (strcmp(param, "ss_count") == 0) { 228244953Sadrian spectralset(spectral, SPECTRAL_PARAM_SS_COUNT, v); 229244953Sadrian } else { 230244953Sadrian return (0); 231244953Sadrian } 232244953Sadrian 233244953Sadrian#if 0 234244953Sadrian if (strcmp(param, "enabled") == 0) { 235244953Sadrian spectralset(spectral, DFS_PARAM_ENABLE, v); 236244953Sadrian } else if (strcmp(param, "firpwr") == 0) { 237244953Sadrian spectralset(spectral, DFS_PARAM_FIRPWR, v); 238244953Sadrian } else if (strcmp(param, "rrssi") == 0) { 239244953Sadrian spectralset(spectral, DFS_PARAM_RRSSI, v); 240244953Sadrian } else if (strcmp(param, "height") == 0) { 241244953Sadrian spectralset(spectral, DFS_PARAM_HEIGHT, v); 242244953Sadrian } else if (strcmp(param, "prssi") == 0) { 243244953Sadrian spectralset(spectral, DFS_PARAM_PRSSI, v); 244244953Sadrian } else if (strcmp(param, "inband") == 0) { 245244953Sadrian spectralset(spectral, DFS_PARAM_INBAND, v); 246244953Sadrian } else if (strcmp(param, "relpwr") == 0) { 247244953Sadrian spectralset(spectral, DFS_PARAM_RELPWR, v); 248244953Sadrian } else if (strcmp(param, "relstep") == 0) { 249244953Sadrian spectralset(spectral, DFS_PARAM_RELSTEP, v); 250244953Sadrian } else if (strcmp(param, "maxlen") == 0) { 251244953Sadrian spectralset(spectral, DFS_PARAM_MAXLEN, v); 252244953Sadrian } else if (strcmp(param, "usefir128") == 0) { 253244953Sadrian spectralset(spectral, DFS_PARAM_USEFIR128, v); 254244953Sadrian } else if (strcmp(param, "blockspectral") == 0) { 255244953Sadrian spectralset(spectral, DFS_PARAM_BLOCKRADAR, v); 256244953Sadrian } else if (strcmp(param, "enmaxrssi") == 0) { 257244953Sadrian spectralset(spectral, DFS_PARAM_MAXRSSI_EN, v); 258244953Sadrian } else if (strcmp(param, "extchannel") == 0) { 259244953Sadrian spectralset(spectral, DFS_PARAM_EN_EXTCH, v); 260244953Sadrian } else if (strcmp(param, "enrelpwr") == 0) { 261244953Sadrian spectralset(spectral, DFS_PARAM_RELPWR_EN, v); 262244953Sadrian } else if (strcmp(param, "en_relstep_check") == 0) { 263244953Sadrian spectralset(spectral, DFS_PARAM_RELSTEP_EN, v); 264244953Sadrian } else { 265244953Sadrian return 0; 266244953Sadrian } 267244953Sadrian#endif 268244953Sadrian 269244953Sadrian return 1; 270244953Sadrian} 271244953Sadrian 272244953Sadrianvoid 273244953Sadrianusage(const char *progname) 274244953Sadrian{ 275244953Sadrian printf("Usage:\n"); 276244953Sadrian printf("\t%s: [-i <interface>] <cmd> (<arg>)\n", progname); 277244953Sadrian printf("\t%s: [-h]\n", progname); 278244953Sadrian printf("\n"); 279244953Sadrian printf("Valid commands:\n"); 280244953Sadrian printf("\tget:\t\tGet current spectral parameters\n"); 281244953Sadrian printf("\tset <param> <value>:\t\tSet spectral parameter\n"); 282244953Sadrian printf("\tstart: Start spectral scan\n"); 283244953Sadrian printf("\tstop: Stop spectral scan\n"); 284245231Sadrian printf("\tenable_at_reset <0|1>: enable reporting upon channel reset\n"); 285244953Sadrian} 286244953Sadrian 287244953Sadrianint 288244953Sadrianmain(int argc, char *argv[]) 289244953Sadrian{ 290244953Sadrian struct spectralhandler spectral; 291244953Sadrian const char *devname = ATH_DEFAULT; 292244953Sadrian const char *progname = argv[0]; 293244953Sadrian 294244953Sadrian memset(&spectral, 0, sizeof(spectral)); 295244953Sadrian 296244953Sadrian /* Parse command line options */ 297244953Sadrian if (argc >= 2 && strcmp(argv[1], "-h") == 0) { 298244953Sadrian usage(progname); 299244953Sadrian exit(0); 300244953Sadrian } 301244953Sadrian if (argc >= 2 && strcmp(argv[1], "-?") == 0) { 302244953Sadrian usage(progname); 303244953Sadrian exit(0); 304244953Sadrian } 305244953Sadrian 306244953Sadrian if (argc >= 2 && strcmp(argv[1], "-i") == 0) { 307244953Sadrian if (argc == 2) { 308244953Sadrian usage(progname); 309244953Sadrian exit(127); 310244953Sadrian } 311244953Sadrian devname = argv[2]; 312244953Sadrian argc -= 2; argv += 2; 313244953Sadrian } 314244953Sadrian 315244953Sadrian /* At this point we require at least one command */ 316244953Sadrian if (argc == 1) { 317244953Sadrian usage(progname); 318244953Sadrian exit(127); 319244953Sadrian } 320244953Sadrian 321244953Sadrian if (spectral_opendev(&spectral, devname) == 0) 322244953Sadrian exit(127); 323244953Sadrian 324244953Sadrian if (strcasecmp(argv[1], "get") == 0) { 325244953Sadrian spectral_get(&spectral); 326244953Sadrian } else if (strcasecmp(argv[1], "set") == 0) { 327244953Sadrian if (argc < 4) { 328244953Sadrian usage(progname); 329244953Sadrian exit(127); 330244953Sadrian } 331244953Sadrian if (spectral_set_param(&spectral, argv[2], argv[3]) == 0) { 332244953Sadrian usage(progname); 333244953Sadrian exit(127); 334244953Sadrian } 335244953Sadrian } else if (strcasecmp(argv[1], "start") == 0) { 336244953Sadrian spectral_start(&spectral); 337244953Sadrian } else if (strcasecmp(argv[1], "stop") == 0) { 338244953Sadrian spectral_stop(&spectral); 339245231Sadrian } else if (strcasecmp(argv[1], "enable_at_reset") == 0) { 340245231Sadrian if (argc < 3) { 341245231Sadrian usage(progname); 342245231Sadrian exit(127); 343245231Sadrian } 344245231Sadrian spectral_enable_at_reset(&spectral, atoi(argv[2])); 345244953Sadrian } else { 346244953Sadrian usage(progname); 347244953Sadrian exit(127); 348244953Sadrian } 349244953Sadrian 350244953Sadrian /* wrap up */ 351244953Sadrian spectral_closedev(&spectral); 352244953Sadrian exit(0); 353244953Sadrian} 354