2 * Copyright (c) 2019 Adrian Chadd <adrian@FreeBSD.org>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
34 #include "ah_internal.h"
42 #include "../common/ctrl.h"
45 * This is a simple wrapper program around the ANI diagnostic interface.
46 * It is for fetching and setting the live ANI configuration when trying
47 * to diagnose a noisy environment.
51 * HAL_DIAG_ANI_CMD is used to set the ANI configuration.
52 * HAL_DIAG_ANI_CURRENT is used to fetch the current ANI configuration.
60 static struct ani_var ani_labels[] = {
61 { "ofdm_noise_immunity_level", 1, },
62 { "noise_immunity_level", 1, },
63 { "ofdm_weak_signal_detect", 2, },
64 { "cck_weak_signal_threshold", 3, },
65 { "firstep_level", 4, },
66 { "spur_immunity_level", 5, },
68 { "cck_noise_immunity_level", 9, },
75 fprintf(stderr, "usage: athani [-i interface] [-l]\n");
76 fprintf(stderr, " -i: interface\n");
77 fprintf(stderr, " -l: list ANI labels\n");
78 fprintf(stderr, " If no args are given after flags, the ANI state will be listed.\n");
79 fprintf(stderr, " To set, use '<label> <value>' to set the state\n");
88 for (i = 0; ani_labels[i].name != NULL; i++) {
89 printf("%s (%d)\n", ani_labels[i].name, ani_labels[i].id);
94 ani_write_state(struct ath_driver_req *req, const char *ifname,
95 const char *label, const char *value)
105 for (i = 0; ani_labels[i].name != NULL; i++) {
106 if ((strlen(ani_labels[i].name) == sl) &&
107 (strcmp(label, ani_labels[i].name) == 0)) {
108 cmd = ani_labels[i].id;
112 if (ani_labels[i].name == NULL) {
113 fprintf(stderr, "%s: couldn't find ANI label (%s)\n",
118 val = strtoul(value, NULL, 0);
121 * Whilst we're doing the ath_diag pieces, we have to set this
124 strncpy(atd.ad_name, ifname, sizeof (atd.ad_name));
127 * Populate HAL_DIAG_ANI_CMD fields.
132 atd.ad_id = HAL_DIAG_ANI_CMD | ATH_DIAG_IN;
133 atd.ad_out_data = NULL;
135 atd.ad_in_data = (void *) &args;
136 atd.ad_in_size = sizeof(args);
138 if (ath_driver_req_fetch_diag(req, SIOCGATHDIAG, &atd) < 0) {
139 warn("SIOCGATHDIAG HAL_DIAG_ANI_CMD (%s)", atd.ad_name);
147 ani_read_state(struct ath_driver_req *req, const char *ifname)
153 * Whilst we're doing the ath_diag pieces, we have to set this
156 strncpy(atd.ad_name, ifname, sizeof (atd.ad_name));
158 atd.ad_id = HAL_DIAG_ANI_CURRENT; /* XXX | DIAG_DYN? */
159 atd.ad_out_data = (caddr_t) &state;
160 atd.ad_out_size = sizeof(state);
162 if (ath_driver_req_fetch_diag(req, SIOCGATHDIAG, &atd) < 0)
163 err(1, "%s", atd.ad_name);
166 printf(" ofdm_noise_immunity_level=%d\n", state.noiseImmunityLevel);
167 printf(" cck_noise_immunity_level=%d\n", state.cckNoiseImmunityLevel);
168 printf(" spur_immunity_level=%d\n", state.spurImmunityLevel);
169 printf(" firstep_level=%d\n", state.firstepLevel);
170 printf(" ofdm_weak_signal_detect=%d\n", state.ofdmWeakSigDetectOff);
171 printf(" cck_weak_signal_threshold=%d\n", state.cckWeakSigThreshold);
172 printf(" mrc_cck=%d\n", state.mrcCck);
173 /* XXX TODO: cycle counts? */
177 main(int argc, char *argv[])
181 struct ath_driver_req req;
184 ath_driver_req_init(&req);
186 ifname = getenv("ATH");
188 ifname = ATH_DEFAULT;
191 while ((c = getopt(argc, argv, "i:l")) != -1)
204 /* Initialise the driver interface */
205 if (ath_driver_req_open(&req, ifname) < 0) {
213 ani_read_state(&req, ifname);
222 if (ani_write_state(&req, ifname, argv[0], argv[1]) != 0)