1224266Sadrian/*
2224266Sadrian * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd.
3224266Sadrian *
4224266Sadrian * Redistribution and use in source and binary forms, with or without
5224266Sadrian * modification, are permitted provided that the following conditions
6224266Sadrian * are met:
7224266Sadrian * 1. Redistributions of source code must retain the above copyright
8224266Sadrian *    notice, this list of conditions and the following disclaimer.
9224266Sadrian * 2. Redistributions in binary form must reproduce the above copyright
10224266Sadrian *    notice, this list of conditions and the following disclaimer in the
11224266Sadrian *    documentation and/or other materials provided with the distribution.
12224266Sadrian *
13224266Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14224266Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15224266Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16224266Sadrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17224266Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18224266Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19224266Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20224266Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21224266Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22224266Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23224266Sadrian * SUCH DAMAGE.
24224266Sadrian *
25224266Sadrian * $FreeBSD$
26224266Sadrian */
27224266Sadrian
28224266Sadrian#include "diag.h"
29224266Sadrian
30224266Sadrian#include "ah.h"
31224266Sadrian#include "ah_internal.h"
32224266Sadrian
33224266Sadrian#ifndef	ATH_DEFAULT
34224266Sadrian#define	ATH_DEFAULT	"ath0"
35224266Sadrian#endif
36224266Sadrian
37224266Sadrian#include <getopt.h>
38224266Sadrian#include <errno.h>
39224266Sadrian#include <err.h>
40224266Sadrian#include <stdlib.h>
41224266Sadrian#include <string.h>
42224266Sadrian#include <ctype.h>
43224266Sadrian#include <unistd.h>
44224266Sadrian
45224266Sadrianstruct radarhandler {
46224266Sadrian	struct		ath_diag atd;
47224266Sadrian	int		s;
48224266Sadrian	struct ifreq	ifr;
49224266Sadrian	int		ah_devid;
50224266Sadrian};
51224266Sadrian
52224266Sadrianint
53224266Sadrianradar_opendev(struct radarhandler *radar, const char *devid)
54224266Sadrian{
55224266Sadrian	HAL_REVS revs;
56224266Sadrian
57224266Sadrian	radar->s = socket(AF_INET, SOCK_DGRAM, 0);
58224266Sadrian	if (radar->s < 0) {
59224266Sadrian		warn("socket");
60224266Sadrian		return 0;
61224266Sadrian	}
62224266Sadrian
63224266Sadrian	strncpy(radar->atd.ad_name, devid, sizeof (radar->atd.ad_name));
64224266Sadrian
65224266Sadrian	/* Get the hardware revision, just to verify things are working */
66224266Sadrian	radar->atd.ad_id = HAL_DIAG_REVS;
67224266Sadrian	radar->atd.ad_out_data = (caddr_t) &revs;
68224266Sadrian	radar->atd.ad_out_size = sizeof(revs);
69224266Sadrian	if (ioctl(radar->s, SIOCGATHDIAG, &radar->atd) < 0) {
70224266Sadrian		warn(radar->atd.ad_name);
71224266Sadrian		return 0;
72224266Sadrian	}
73224266Sadrian	radar->ah_devid = revs.ah_devid;
74224266Sadrian	return 1;
75224266Sadrian}
76224266Sadrian
77224266Sadrianvoid
78224266Sadrianradar_closedev(struct radarhandler *radar)
79224266Sadrian{
80224266Sadrian	close(radar->s);
81224266Sadrian	radar->s = -1;
82224266Sadrian}
83224266Sadrian
84224266Sadrianvoid
85224266Sadrianradarset(struct radarhandler *radar, int op, u_int32_t param)
86224266Sadrian{
87224266Sadrian	HAL_PHYERR_PARAM pe;
88224266Sadrian
89224266Sadrian	pe.pe_firpwr = HAL_PHYERR_PARAM_NOVAL;
90224266Sadrian	pe.pe_rrssi = HAL_PHYERR_PARAM_NOVAL;
91224266Sadrian	pe.pe_height = HAL_PHYERR_PARAM_NOVAL;
92224266Sadrian	pe.pe_prssi = HAL_PHYERR_PARAM_NOVAL;
93224266Sadrian	pe.pe_inband = HAL_PHYERR_PARAM_NOVAL;
94224266Sadrian	pe.pe_enabled = HAL_PHYERR_PARAM_NOVAL;
95224266Sadrian
96224266Sadrian	pe.pe_relpwr = HAL_PHYERR_PARAM_NOVAL;
97224266Sadrian	pe.pe_relstep = HAL_PHYERR_PARAM_NOVAL;
98224266Sadrian	pe.pe_maxlen = HAL_PHYERR_PARAM_NOVAL;
99224266Sadrian	pe.pe_usefir128 = HAL_PHYERR_PARAM_NOVAL;
100224266Sadrian	pe.pe_blockradar = HAL_PHYERR_PARAM_NOVAL;
101224266Sadrian	pe.pe_enmaxrssi = HAL_PHYERR_PARAM_NOVAL;
102224266Sadrian
103224266Sadrian	pe.pe_extchannel = HAL_PHYERR_PARAM_NOVAL;
104231710Sadrian	pe.pe_enrelpwr = HAL_PHYERR_PARAM_NOVAL;
105231710Sadrian	pe.pe_en_relstep_check = HAL_PHYERR_PARAM_NOVAL;
106224266Sadrian
107224266Sadrian	switch (op) {
108224266Sadrian	case DFS_PARAM_ENABLE:
109224266Sadrian		pe.pe_enabled = param;
110224266Sadrian		break;
111224266Sadrian	case DFS_PARAM_FIRPWR:
112224266Sadrian		pe.pe_firpwr = param;
113224266Sadrian		break;
114224266Sadrian	case DFS_PARAM_RRSSI:
115224266Sadrian		pe.pe_rrssi = param;
116224266Sadrian		break;
117224266Sadrian	case DFS_PARAM_HEIGHT:
118224266Sadrian		pe.pe_height = param;
119224266Sadrian		break;
120224266Sadrian	case DFS_PARAM_PRSSI:
121224266Sadrian		pe.pe_prssi = param;
122224266Sadrian		break;
123224266Sadrian	case DFS_PARAM_INBAND:
124224266Sadrian		pe.pe_inband = param;
125224266Sadrian		break;
126224266Sadrian	case DFS_PARAM_RELPWR:
127224266Sadrian		pe.pe_relpwr = param;
128224266Sadrian		break;
129224266Sadrian	case DFS_PARAM_RELSTEP:
130224266Sadrian		pe.pe_relstep = param;
131224266Sadrian		break;
132224266Sadrian	case DFS_PARAM_MAXLEN:
133224266Sadrian		pe.pe_maxlen = param;
134224266Sadrian		break;
135224266Sadrian	case DFS_PARAM_USEFIR128:
136224266Sadrian		pe.pe_usefir128 = param;
137224266Sadrian		break;
138224266Sadrian	case DFS_PARAM_BLOCKRADAR:
139224266Sadrian		pe.pe_blockradar = param;
140224266Sadrian		break;
141224266Sadrian	case DFS_PARAM_MAXRSSI_EN:
142224266Sadrian		pe.pe_enmaxrssi = param;
143224266Sadrian		break;
144224266Sadrian	case DFS_PARAM_EN_EXTCH:
145224266Sadrian		pe.pe_extchannel = param;
146224266Sadrian		break;
147231710Sadrian	case DFS_PARAM_RELPWR_EN:
148231710Sadrian		pe.pe_enrelpwr = param;
149231710Sadrian		break;
150231710Sadrian	case DFS_PARAM_RELSTEP_EN:
151231710Sadrian		pe.pe_en_relstep_check = param;
152231710Sadrian		break;
153224266Sadrian	}
154231710Sadrian
155224266Sadrian	radar->atd.ad_id = DFS_SET_THRESH | ATH_DIAG_IN;
156224266Sadrian	radar->atd.ad_out_data = NULL;
157224266Sadrian	radar->atd.ad_out_size = 0;
158224266Sadrian	radar->atd.ad_in_data = (caddr_t) &pe;
159224266Sadrian	radar->atd.ad_in_size = sizeof(HAL_PHYERR_PARAM);
160224266Sadrian	if (ioctl(radar->s, SIOCGATHPHYERR, &radar->atd) < 0)
161224266Sadrian		err(1, radar->atd.ad_name);
162224266Sadrian}
163224266Sadrian
164224266Sadrianstatic void
165224266Sadrianradar_get(struct radarhandler *radar)
166224266Sadrian{
167224266Sadrian	HAL_PHYERR_PARAM pe;
168224266Sadrian
169224266Sadrian	radar->atd.ad_id = DFS_GET_THRESH | ATH_DIAG_DYN;
170224266Sadrian	memset(&pe, 0, sizeof(pe));
171224266Sadrian
172224266Sadrian	radar->atd.ad_in_data = NULL;
173224266Sadrian	radar->atd.ad_in_size = 0;
174224266Sadrian	radar->atd.ad_out_data = (caddr_t) &pe;
175224266Sadrian	radar->atd.ad_out_size = sizeof(pe);
176224266Sadrian
177224266Sadrian	if (ioctl(radar->s, SIOCGATHPHYERR, &radar->atd) < 0)
178224266Sadrian		err(1, radar->atd.ad_name);
179224266Sadrian
180224266Sadrian	printf("Radar parameters (raw):\n");
181224266Sadrian	printf("    pe_enabled: %d\n", pe.pe_enabled);
182224266Sadrian	printf("    pe_firpwr: %d\n", pe.pe_firpwr);
183224266Sadrian	printf("    pe_rrssi: %d\n", pe.pe_rrssi);
184224266Sadrian	printf("    pe_height: %d\n", pe.pe_height);
185224266Sadrian	printf("    pe_prssi: %d\n", pe.pe_prssi);
186224266Sadrian	printf("    pe_inband: %d\n", pe.pe_inband);
187224266Sadrian	printf("    pe_relpwr: %d\n", pe.pe_relpwr);
188224266Sadrian	printf("    pe_relstep: %d\n", pe.pe_relstep);
189224266Sadrian	printf("    pe_maxlen: %d\n", pe.pe_maxlen);
190224266Sadrian	printf("    pe_usefir128: %d\n", pe.pe_usefir128);
191224266Sadrian	printf("    pe_blockradar: %d\n", pe.pe_blockradar);
192224266Sadrian	printf("    pe_enmaxrssi: %d\n", pe.pe_enmaxrssi);
193224266Sadrian	printf("    pe_extchannel: %d\n", pe.pe_extchannel);
194231710Sadrian	printf("    pe_enrelpwr: %d\n", pe.pe_enrelpwr);
195231710Sadrian	printf("    pe_en_relstep_check: %d\n", pe.pe_en_relstep_check);
196224266Sadrian}
197224266Sadrian
198224266Sadrianstatic int
199231710Sadrianradar_set_param(struct radarhandler *radar, const char *param,
200231710Sadrian    const char *val)
201224266Sadrian{
202224266Sadrian	int v;
203224266Sadrian
204224266Sadrian	v = atoi(val);
205224266Sadrian
206231710Sadrian	if (strcmp(param, "enabled") == 0) {
207231710Sadrian		radarset(radar, DFS_PARAM_ENABLE, v);
208231710Sadrian	} else if (strcmp(param, "firpwr") == 0) {
209224266Sadrian		radarset(radar, DFS_PARAM_FIRPWR, v);
210224266Sadrian	} else if (strcmp(param, "rrssi") == 0) {
211224266Sadrian		radarset(radar, DFS_PARAM_RRSSI, v);
212224266Sadrian	} else if (strcmp(param, "height") == 0) {
213224266Sadrian		radarset(radar, DFS_PARAM_HEIGHT, v);
214224266Sadrian	} else if (strcmp(param, "prssi") == 0) {
215224266Sadrian		radarset(radar, DFS_PARAM_PRSSI, v);
216224266Sadrian	} else if (strcmp(param, "inband") == 0) {
217224266Sadrian		radarset(radar, DFS_PARAM_INBAND, v);
218224266Sadrian	} else if (strcmp(param, "relpwr") == 0) {
219224266Sadrian		radarset(radar, DFS_PARAM_RELPWR, v);
220224266Sadrian	} else if (strcmp(param, "relstep") == 0) {
221224266Sadrian		radarset(radar, DFS_PARAM_RELSTEP, v);
222224266Sadrian	} else if (strcmp(param, "maxlen") == 0) {
223224266Sadrian		radarset(radar, DFS_PARAM_MAXLEN, v);
224230923Sadrian	} else if (strcmp(param, "usefir128") == 0) {
225230923Sadrian		radarset(radar, DFS_PARAM_USEFIR128, v);
226230923Sadrian	} else if (strcmp(param, "blockradar") == 0) {
227230923Sadrian		radarset(radar, DFS_PARAM_BLOCKRADAR, v);
228230923Sadrian	} else if (strcmp(param, "enmaxrssi") == 0) {
229230923Sadrian		radarset(radar, DFS_PARAM_MAXRSSI_EN, v);
230224266Sadrian	} else if (strcmp(param, "extchannel") == 0) {
231224266Sadrian		radarset(radar, DFS_PARAM_EN_EXTCH, v);
232231710Sadrian	} else if (strcmp(param, "enrelpwr") == 0) {
233231710Sadrian		radarset(radar, DFS_PARAM_RELPWR_EN, v);
234231710Sadrian	} else if (strcmp(param, "en_relstep_check") == 0) {
235231710Sadrian		radarset(radar, DFS_PARAM_RELSTEP_EN, v);
236224266Sadrian	} else {
237224266Sadrian		return 0;
238224266Sadrian	}
239224266Sadrian
240224266Sadrian	return 1;
241224266Sadrian}
242224266Sadrian
243224266Sadrianvoid
244224266Sadrianusage(const char *progname)
245224266Sadrian{
246224266Sadrian	printf("Usage:\n");
247224266Sadrian	printf("\t%s: [-i <interface>] <cmd> (<arg>)\n", progname);
248224266Sadrian	printf("\t%s: [-h]\n", progname);
249224266Sadrian	printf("\n");
250224266Sadrian	printf("Valid commands:\n");
251224266Sadrian	printf("\tget:\t\tGet current radar parameters\n");
252224266Sadrian	printf("\tset <param> <value>:\t\tSet radar parameter\n");
253224266Sadrian}
254224266Sadrian
255224266Sadrianint
256224266Sadrianmain(int argc, char *argv[])
257224266Sadrian{
258224266Sadrian	struct radarhandler radar;
259224266Sadrian	const char *devname = ATH_DEFAULT;
260224266Sadrian	const char *progname = argv[0];
261224266Sadrian
262224266Sadrian	memset(&radar, 0, sizeof(radar));
263224266Sadrian
264224266Sadrian	/* Parse command line options */
265224266Sadrian	if (argc >= 2 && strcmp(argv[1], "-h") == 0) {
266224266Sadrian		usage(progname);
267224266Sadrian		exit(0);
268224266Sadrian	}
269224266Sadrian	if (argc >= 2 && strcmp(argv[1], "-?") == 0) {
270224266Sadrian		usage(progname);
271224266Sadrian		exit(0);
272224266Sadrian	}
273224266Sadrian
274224266Sadrian	if (argc >= 2 && strcmp(argv[1], "-i") == 0) {
275224266Sadrian		if (argc == 2) {
276224266Sadrian			usage(progname);
277224266Sadrian			exit(127);
278224266Sadrian		}
279224266Sadrian		devname = argv[2];
280224266Sadrian		argc -= 2; argv += 2;
281224266Sadrian	}
282224266Sadrian
283224266Sadrian	/* At this point we require at least one command */
284224266Sadrian	if (argc == 1) {
285224266Sadrian		usage(progname);
286224266Sadrian		exit(127);
287224266Sadrian	}
288224266Sadrian
289224266Sadrian	if (radar_opendev(&radar, devname) == 0)
290224266Sadrian		exit(127);
291224266Sadrian
292224266Sadrian	if (strcasecmp(argv[1], "get") == 0) {
293224266Sadrian		radar_get(&radar);
294224266Sadrian	} else if (strcasecmp(argv[1], "set") == 0) {
295224266Sadrian		if (argc < 4) {
296224266Sadrian			usage(progname);
297224266Sadrian			exit(127);
298224266Sadrian		}
299224266Sadrian		if (radar_set_param(&radar, argv[2], argv[3]) == 0) {
300224266Sadrian			usage(progname);
301224266Sadrian			exit(127);
302224266Sadrian		}
303224266Sadrian	} else {
304224266Sadrian		usage(progname);
305224266Sadrian		exit(127);
306224266Sadrian	}
307224266Sadrian
308224266Sadrian	/* wrap up */
309224266Sadrian	radar_closedev(&radar);
310224266Sadrian	exit(0);
311224266Sadrian}
312