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#include <getopt.h> 34244953Sadrian#include <errno.h> 35244953Sadrian#include <err.h> 36244953Sadrian#include <stdlib.h> 37244953Sadrian#include <string.h> 38244953Sadrian#include <ctype.h> 39244953Sadrian#include <unistd.h> 40244953Sadrian 41244953Sadrianstruct spectralhandler { 42244953Sadrian struct ath_diag atd; 43244953Sadrian int s; 44244953Sadrian struct ifreq ifr; 45244953Sadrian int ah_devid; 46244953Sadrian}; 47244953Sadrian 48244953Sadrianint 49244953Sadrianspectral_opendev(struct spectralhandler *spectral, const char *devid) 50244953Sadrian{ 51244953Sadrian HAL_REVS revs; 52244953Sadrian 53244953Sadrian spectral->s = socket(AF_INET, SOCK_DGRAM, 0); 54244953Sadrian if (spectral->s < 0) { 55244953Sadrian warn("socket"); 56244953Sadrian return 0; 57244953Sadrian } 58244953Sadrian 59244953Sadrian strncpy(spectral->atd.ad_name, devid, sizeof (spectral->atd.ad_name)); 60244953Sadrian 61244953Sadrian /* Get the hardware revision, just to verify things are working */ 62244953Sadrian spectral->atd.ad_id = HAL_DIAG_REVS; 63244953Sadrian spectral->atd.ad_out_data = (caddr_t) &revs; 64244953Sadrian spectral->atd.ad_out_size = sizeof(revs); 65244953Sadrian if (ioctl(spectral->s, SIOCGATHDIAG, &spectral->atd) < 0) { 66251737Sadrian warn("%s", spectral->atd.ad_name); 67244953Sadrian return 0; 68244953Sadrian } 69244953Sadrian spectral->ah_devid = revs.ah_devid; 70244953Sadrian return 1; 71244953Sadrian} 72244953Sadrian 73244953Sadrianvoid 74244953Sadrianspectral_closedev(struct spectralhandler *spectral) 75244953Sadrian{ 76244953Sadrian close(spectral->s); 77244953Sadrian spectral->s = -1; 78244953Sadrian} 79244953Sadrian 80244953Sadrianvoid 81244953Sadrianspectralset(struct spectralhandler *spectral, int op, u_int32_t param) 82244953Sadrian{ 83244953Sadrian HAL_SPECTRAL_PARAM pe; 84244953Sadrian 85244953Sadrian pe.ss_fft_period = HAL_SPECTRAL_PARAM_NOVAL; 86244953Sadrian pe.ss_period = HAL_SPECTRAL_PARAM_NOVAL; 87244953Sadrian pe.ss_count = HAL_SPECTRAL_PARAM_NOVAL; 88244953Sadrian pe.ss_short_report = HAL_SPECTRAL_PARAM_NOVAL; 89244953Sadrian pe.ss_spectral_pri = HAL_SPECTRAL_PARAM_NOVAL; 90244953Sadrian pe.ss_fft_period = HAL_SPECTRAL_PARAM_NOVAL; 91244953Sadrian pe.ss_enabled = HAL_SPECTRAL_PARAM_NOVAL; 92244953Sadrian pe.ss_active = HAL_SPECTRAL_PARAM_NOVAL; 93244953Sadrian 94244953Sadrian switch (op) { 95244953Sadrian case SPECTRAL_PARAM_FFT_PERIOD: 96244953Sadrian pe.ss_fft_period = param; 97244953Sadrian break; 98244953Sadrian case SPECTRAL_PARAM_SS_PERIOD: 99244953Sadrian pe.ss_period = param; 100244953Sadrian break; 101244953Sadrian case SPECTRAL_PARAM_SS_COUNT: 102244953Sadrian pe.ss_count = param; 103244953Sadrian break; 104244953Sadrian case SPECTRAL_PARAM_SS_SHORT_RPT: 105244953Sadrian pe.ss_short_report = param; 106244953Sadrian break; 107244953Sadrian } 108244953Sadrian 109244953Sadrian spectral->atd.ad_id = SPECTRAL_CONTROL_SET_PARAMS | ATH_DIAG_IN; 110244953Sadrian spectral->atd.ad_out_data = NULL; 111244953Sadrian spectral->atd.ad_out_size = 0; 112244953Sadrian spectral->atd.ad_in_data = (caddr_t) &pe; 113244953Sadrian spectral->atd.ad_in_size = sizeof(HAL_SPECTRAL_PARAM); 114244953Sadrian if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) 115251737Sadrian err(1, "%s", spectral->atd.ad_name); 116244953Sadrian} 117244953Sadrian 118244953Sadrianstatic void 119244953Sadrianspectral_get(struct spectralhandler *spectral) 120244953Sadrian{ 121244953Sadrian HAL_SPECTRAL_PARAM pe; 122244953Sadrian 123244953Sadrian spectral->atd.ad_id = SPECTRAL_CONTROL_GET_PARAMS | ATH_DIAG_DYN; 124244953Sadrian memset(&pe, 0, sizeof(pe)); 125244953Sadrian 126244953Sadrian spectral->atd.ad_in_data = NULL; 127244953Sadrian spectral->atd.ad_in_size = 0; 128244953Sadrian spectral->atd.ad_out_data = (caddr_t) &pe; 129244953Sadrian spectral->atd.ad_out_size = sizeof(pe); 130244953Sadrian 131244953Sadrian if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) 132251737Sadrian err(1, "%s", spectral->atd.ad_name); 133244953Sadrian 134244953Sadrian printf("Spectral parameters (raw):\n"); 135244953Sadrian printf(" ss_enabled: %d\n", pe.ss_enabled); 136244953Sadrian printf(" ss_active: %d\n", pe.ss_active); 137244953Sadrian printf(" ss_count: %d\n", pe.ss_count); 138244953Sadrian printf(" ss_fft_period: %d\n", pe.ss_fft_period); 139244953Sadrian printf(" ss_period: %d\n", pe.ss_period); 140244953Sadrian printf(" ss_short_report: %d\n", pe.ss_short_report); 141244953Sadrian printf(" radar_bin_thresh_sel: %d\n", pe.radar_bin_thresh_sel); 142244953Sadrian} 143244953Sadrian 144244953Sadrianstatic void 145244953Sadrianspectral_start(struct spectralhandler *spectral) 146244953Sadrian{ 147244953Sadrian HAL_SPECTRAL_PARAM pe; 148244953Sadrian 149244953Sadrian spectral->atd.ad_id = SPECTRAL_CONTROL_START | ATH_DIAG_DYN; 150244953Sadrian memset(&pe, 0, sizeof(pe)); 151244953Sadrian 152244953Sadrian /* 153244953Sadrian * XXX don't need these, but need to eliminate the ATH_DIAG_DYN flag 154244953Sadrian * and debug 155244953Sadrian */ 156244953Sadrian spectral->atd.ad_in_data = NULL; 157244953Sadrian spectral->atd.ad_in_size = 0; 158244953Sadrian spectral->atd.ad_out_data = (caddr_t) &pe; 159244953Sadrian spectral->atd.ad_out_size = sizeof(pe); 160244953Sadrian 161244953Sadrian if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) 162251737Sadrian err(1, "%s", spectral->atd.ad_name); 163244953Sadrian} 164244953Sadrian 165244953Sadrianstatic void 166244953Sadrianspectral_stop(struct spectralhandler *spectral) 167244953Sadrian{ 168244953Sadrian HAL_SPECTRAL_PARAM pe; 169244953Sadrian 170244953Sadrian spectral->atd.ad_id = SPECTRAL_CONTROL_STOP | ATH_DIAG_DYN; 171244953Sadrian memset(&pe, 0, sizeof(pe)); 172244953Sadrian 173244953Sadrian /* 174244953Sadrian * XXX don't need these, but need to eliminate the ATH_DIAG_DYN flag 175244953Sadrian * and debug 176244953Sadrian */ 177244953Sadrian spectral->atd.ad_in_data = NULL; 178244953Sadrian spectral->atd.ad_in_size = 0; 179244953Sadrian spectral->atd.ad_out_data = (caddr_t) &pe; 180244953Sadrian spectral->atd.ad_out_size = sizeof(pe); 181244953Sadrian 182244953Sadrian if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) 183251737Sadrian err(1, "%s", spectral->atd.ad_name); 184244953Sadrian} 185244953Sadrian 186245231Sadrianstatic void 187245231Sadrianspectral_enable_at_reset(struct spectralhandler *spectral, int val) 188245231Sadrian{ 189245231Sadrian int v = val; 190245231Sadrian 191245231Sadrian spectral->atd.ad_id = SPECTRAL_CONTROL_ENABLE_AT_RESET 192245231Sadrian | ATH_DIAG_IN; 193245231Sadrian 194245231Sadrian /* 195245231Sadrian * XXX don't need these, but need to eliminate the ATH_DIAG_DYN flag 196245231Sadrian * and debug 197245231Sadrian */ 198245231Sadrian spectral->atd.ad_out_data = NULL; 199245231Sadrian spectral->atd.ad_out_size = 0; 200245231Sadrian spectral->atd.ad_in_data = (caddr_t) &v; 201245231Sadrian spectral->atd.ad_in_size = sizeof(v); 202245231Sadrian 203245231Sadrian printf("%s: val=%d\n", __func__, v); 204245231Sadrian 205245231Sadrian if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) 206251737Sadrian err(1, "%s", spectral->atd.ad_name); 207245231Sadrian} 208245231Sadrian 209244953Sadrianstatic int 210244953Sadrianspectral_set_param(struct spectralhandler *spectral, const char *param, 211244953Sadrian const char *val) 212244953Sadrian{ 213244953Sadrian int v; 214244953Sadrian 215244953Sadrian v = atoi(val); 216244953Sadrian 217244953Sadrian if (strcmp(param, "ss_short_report") == 0) { 218244953Sadrian spectralset(spectral, SPECTRAL_PARAM_SS_SHORT_RPT, v); 219244953Sadrian } else if (strcmp(param, "ss_fft_period") == 0) { 220244953Sadrian spectralset(spectral, SPECTRAL_PARAM_FFT_PERIOD, v); 221244953Sadrian } else if (strcmp(param, "ss_period") == 0) { 222244953Sadrian spectralset(spectral, SPECTRAL_PARAM_SS_PERIOD, v); 223244953Sadrian } else if (strcmp(param, "ss_count") == 0) { 224244953Sadrian spectralset(spectral, SPECTRAL_PARAM_SS_COUNT, v); 225244953Sadrian } else { 226244953Sadrian return (0); 227244953Sadrian } 228244953Sadrian 229244953Sadrian#if 0 230244953Sadrian if (strcmp(param, "enabled") == 0) { 231244953Sadrian spectralset(spectral, DFS_PARAM_ENABLE, v); 232244953Sadrian } else if (strcmp(param, "firpwr") == 0) { 233244953Sadrian spectralset(spectral, DFS_PARAM_FIRPWR, v); 234244953Sadrian } else if (strcmp(param, "rrssi") == 0) { 235244953Sadrian spectralset(spectral, DFS_PARAM_RRSSI, v); 236244953Sadrian } else if (strcmp(param, "height") == 0) { 237244953Sadrian spectralset(spectral, DFS_PARAM_HEIGHT, v); 238244953Sadrian } else if (strcmp(param, "prssi") == 0) { 239244953Sadrian spectralset(spectral, DFS_PARAM_PRSSI, v); 240244953Sadrian } else if (strcmp(param, "inband") == 0) { 241244953Sadrian spectralset(spectral, DFS_PARAM_INBAND, v); 242244953Sadrian } else if (strcmp(param, "relpwr") == 0) { 243244953Sadrian spectralset(spectral, DFS_PARAM_RELPWR, v); 244244953Sadrian } else if (strcmp(param, "relstep") == 0) { 245244953Sadrian spectralset(spectral, DFS_PARAM_RELSTEP, v); 246244953Sadrian } else if (strcmp(param, "maxlen") == 0) { 247244953Sadrian spectralset(spectral, DFS_PARAM_MAXLEN, v); 248244953Sadrian } else if (strcmp(param, "usefir128") == 0) { 249244953Sadrian spectralset(spectral, DFS_PARAM_USEFIR128, v); 250244953Sadrian } else if (strcmp(param, "blockspectral") == 0) { 251244953Sadrian spectralset(spectral, DFS_PARAM_BLOCKRADAR, v); 252244953Sadrian } else if (strcmp(param, "enmaxrssi") == 0) { 253244953Sadrian spectralset(spectral, DFS_PARAM_MAXRSSI_EN, v); 254244953Sadrian } else if (strcmp(param, "extchannel") == 0) { 255244953Sadrian spectralset(spectral, DFS_PARAM_EN_EXTCH, v); 256244953Sadrian } else if (strcmp(param, "enrelpwr") == 0) { 257244953Sadrian spectralset(spectral, DFS_PARAM_RELPWR_EN, v); 258244953Sadrian } else if (strcmp(param, "en_relstep_check") == 0) { 259244953Sadrian spectralset(spectral, DFS_PARAM_RELSTEP_EN, v); 260244953Sadrian } else { 261244953Sadrian return 0; 262244953Sadrian } 263244953Sadrian#endif 264244953Sadrian 265244953Sadrian return 1; 266244953Sadrian} 267244953Sadrian 268244953Sadrianvoid 269244953Sadrianusage(const char *progname) 270244953Sadrian{ 271244953Sadrian printf("Usage:\n"); 272244953Sadrian printf("\t%s: [-i <interface>] <cmd> (<arg>)\n", progname); 273244953Sadrian printf("\t%s: [-h]\n", progname); 274244953Sadrian printf("\n"); 275244953Sadrian printf("Valid commands:\n"); 276244953Sadrian printf("\tget:\t\tGet current spectral parameters\n"); 277244953Sadrian printf("\tset <param> <value>:\t\tSet spectral parameter\n"); 278244953Sadrian printf("\tstart: Start spectral scan\n"); 279244953Sadrian printf("\tstop: Stop spectral scan\n"); 280245231Sadrian printf("\tenable_at_reset <0|1>: enable reporting upon channel reset\n"); 281244953Sadrian} 282244953Sadrian 283244953Sadrianint 284244953Sadrianmain(int argc, char *argv[]) 285244953Sadrian{ 286244953Sadrian struct spectralhandler spectral; 287244953Sadrian const char *devname = ATH_DEFAULT; 288244953Sadrian const char *progname = argv[0]; 289244953Sadrian 290244953Sadrian memset(&spectral, 0, sizeof(spectral)); 291244953Sadrian 292244953Sadrian /* Parse command line options */ 293244953Sadrian if (argc >= 2 && strcmp(argv[1], "-h") == 0) { 294244953Sadrian usage(progname); 295244953Sadrian exit(0); 296244953Sadrian } 297244953Sadrian if (argc >= 2 && strcmp(argv[1], "-?") == 0) { 298244953Sadrian usage(progname); 299244953Sadrian exit(0); 300244953Sadrian } 301244953Sadrian 302244953Sadrian if (argc >= 2 && strcmp(argv[1], "-i") == 0) { 303244953Sadrian if (argc == 2) { 304244953Sadrian usage(progname); 305244953Sadrian exit(127); 306244953Sadrian } 307244953Sadrian devname = argv[2]; 308244953Sadrian argc -= 2; argv += 2; 309244953Sadrian } 310244953Sadrian 311244953Sadrian /* At this point we require at least one command */ 312244953Sadrian if (argc == 1) { 313244953Sadrian usage(progname); 314244953Sadrian exit(127); 315244953Sadrian } 316244953Sadrian 317244953Sadrian if (spectral_opendev(&spectral, devname) == 0) 318244953Sadrian exit(127); 319244953Sadrian 320244953Sadrian if (strcasecmp(argv[1], "get") == 0) { 321244953Sadrian spectral_get(&spectral); 322244953Sadrian } else if (strcasecmp(argv[1], "set") == 0) { 323244953Sadrian if (argc < 4) { 324244953Sadrian usage(progname); 325244953Sadrian exit(127); 326244953Sadrian } 327244953Sadrian if (spectral_set_param(&spectral, argv[2], argv[3]) == 0) { 328244953Sadrian usage(progname); 329244953Sadrian exit(127); 330244953Sadrian } 331244953Sadrian } else if (strcasecmp(argv[1], "start") == 0) { 332244953Sadrian spectral_start(&spectral); 333244953Sadrian } else if (strcasecmp(argv[1], "stop") == 0) { 334244953Sadrian spectral_stop(&spectral); 335245231Sadrian } else if (strcasecmp(argv[1], "enable_at_reset") == 0) { 336245231Sadrian if (argc < 3) { 337245231Sadrian usage(progname); 338245231Sadrian exit(127); 339245231Sadrian } 340245231Sadrian spectral_enable_at_reset(&spectral, atoi(argv[2])); 341244953Sadrian } else { 342244953Sadrian usage(progname); 343244953Sadrian exit(127); 344244953Sadrian } 345244953Sadrian 346244953Sadrian /* wrap up */ 347244953Sadrian spectral_closedev(&spectral); 348244953Sadrian exit(0); 349244953Sadrian} 350