1 /*-
2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
15 *
16 * NO WARRANTY
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.
28 *
29 * $FreeBSD$
30 */
31
32 /*
33 * athdebug [-i interface] flags
34 * (default interface is wlan0).
35 */
36
37 #include <sys/param.h>
38 #include <sys/file.h>
39 #include <sys/ioctl.h>
40 #include <sys/socket.h>
41 #include <sys/sysctl.h>
42
43 #include <ctype.h>
44 #include <err.h>
45 #include <getopt.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <strings.h>
50
51 const char *progname;
52
53 /* XXX TODO: include if_ath_debug.h */
54 enum {
55 ATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
56 ATH_DEBUG_XMIT_DESC = 0x00000002, /* xmit descriptors */
57 ATH_DEBUG_RECV = 0x00000004, /* basic recv operation */
58 ATH_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */
59 ATH_DEBUG_RATE = 0x00000010, /* rate control */
60 ATH_DEBUG_RESET = 0x00000020, /* reset processing */
61 ATH_DEBUG_MODE = 0x00000040, /* mode init/setup */
62 ATH_DEBUG_BEACON = 0x00000080, /* beacon handling */
63 ATH_DEBUG_WATCHDOG = 0x00000100, /* watchdog timeout */
64 ATH_DEBUG_INTR = 0x00001000, /* ISR */
65 ATH_DEBUG_TX_PROC = 0x00002000, /* tx ISR proc */
66 ATH_DEBUG_RX_PROC = 0x00004000, /* rx ISR proc */
67 ATH_DEBUG_BEACON_PROC = 0x00008000, /* beacon ISR proc */
68 ATH_DEBUG_CALIBRATE = 0x00010000, /* periodic calibration */
69 ATH_DEBUG_KEYCACHE = 0x00020000, /* key cache management */
70 ATH_DEBUG_STATE = 0x00040000, /* 802.11 state transitions */
71 ATH_DEBUG_NODE = 0x00080000, /* node management */
72 ATH_DEBUG_LED = 0x00100000, /* led management */
73 ATH_DEBUG_FF = 0x00200000, /* fast frames */
74 ATH_DEBUG_DFS = 0x00400000, /* DFS processing */
75 ATH_DEBUG_TDMA = 0x00800000, /* TDMA processing */
76 ATH_DEBUG_TDMA_TIMER = 0x01000000, /* TDMA timer processing */
77 ATH_DEBUG_REGDOMAIN = 0x02000000, /* regulatory processing */
78 ATH_DEBUG_FATAL = 0x80000000, /* fatal errors */
79 ATH_DEBUG_ANY = 0xffffffff
80 };
81
82 static struct {
83 const char *name;
84 uint64_t bit;
85 } flags[] = {
86 { "xmit", ATH_DEBUG_XMIT },
87 { "xmit_desc", ATH_DEBUG_XMIT_DESC },
88 { "recv", ATH_DEBUG_RECV },
89 { "recv_desc", ATH_DEBUG_RECV_DESC },
90 { "rate", ATH_DEBUG_RATE },
91 { "reset", ATH_DEBUG_RESET },
92 { "mode", ATH_DEBUG_MODE },
93 { "beacon", ATH_DEBUG_BEACON },
94 { "watchdog", ATH_DEBUG_WATCHDOG },
95 { "intr", ATH_DEBUG_INTR },
96 { "xmit_proc", ATH_DEBUG_TX_PROC },
97 { "recv_proc", ATH_DEBUG_RX_PROC },
98 { "beacon_proc",ATH_DEBUG_BEACON_PROC },
99 { "calibrate", ATH_DEBUG_CALIBRATE },
100 { "keycache", ATH_DEBUG_KEYCACHE },
101 { "state", ATH_DEBUG_STATE },
102 { "node", ATH_DEBUG_NODE },
103 { "led", ATH_DEBUG_LED },
104 { "ff", ATH_DEBUG_FF },
105 { "dfs", ATH_DEBUG_DFS },
106 { "tdma", ATH_DEBUG_TDMA },
107 { "tdma_timer", ATH_DEBUG_TDMA_TIMER },
108 { "regdomain", ATH_DEBUG_REGDOMAIN },
109 { "fatal", ATH_DEBUG_FATAL },
110 };
111
112 static uint64_t
getflag(const char * name,int len)113 getflag(const char *name, int len)
114 {
115 unsigned int i;
116
117 for (i = 0; i < nitems(flags); i++)
118 if (strncasecmp(flags[i].name, name, len) == 0)
119 return flags[i].bit;
120 return 0;
121 }
122
123 #if 0
124 static const char *
125 getflagname(u_int flag)
126 {
127 int i;
128
129 for (i = 0; i < nitems(flags); i++)
130 if (flags[i].bit == flag)
131 return flags[i].name;
132 return "???";
133 }
134 #endif
135
136 static void
usage(void)137 usage(void)
138 {
139 unsigned int i;
140
141 fprintf(stderr, "usage: %s [-i device] [flags]\n", progname);
142 fprintf(stderr, "where flags are:\n");
143 for (i = 0; i < nitems(flags); i++)
144 printf("%s\n", flags[i].name);
145 exit(-1);
146 }
147
148 int
main(int argc,char * argv[])149 main(int argc, char *argv[])
150 {
151 const char *ifname;
152 const char *cp, *tp;
153 const char *sep;
154 int op;
155 unsigned int i;
156 uint64_t debug, ndebug;
157 size_t debuglen;
158 char oid[256];
159
160 ifname = getenv("ATH");
161 if (ifname == NULL)
162 ifname = ATH_DEFAULT;
163 progname = argv[0];
164 if (argc > 1) {
165 if (strcmp(argv[1], "-i") == 0) {
166 if (argc < 2)
167 errx(1, "missing interface name for -i option");
168 ifname = argv[2];
169 if (strncmp(ifname, "ath", 3) != 0)
170 errx(2, "huh, this is for ath devices?");
171 argc -= 2, argv += 2;
172 } else if (strcmp(argv[1], "-?") == 0)
173 usage();
174 }
175
176 #ifdef __linux__
177 snprintf(oid, sizeof(oid), "dev.%s.debug", ifname);
178 #else
179 snprintf(oid, sizeof(oid), "dev.ath.%s.debug", ifname+3);
180 #endif
181 debuglen = sizeof(debug);
182 if (sysctlbyname(oid, &debug, &debuglen, NULL, 0) < 0)
183 err(1, "sysctl-get(%s)", oid);
184 ndebug = debug;
185 for (; argc > 1; argc--, argv++) {
186 cp = argv[1];
187 do {
188 u_int bit;
189
190 if (*cp == '-') {
191 cp++;
192 op = -1;
193 } else if (*cp == '+') {
194 cp++;
195 op = 1;
196 } else
197 op = 0;
198 for (tp = cp; *tp != '\0' && *tp != '+' && *tp != '-';)
199 tp++;
200 bit = getflag(cp, tp-cp);
201 if (op < 0)
202 ndebug &= ~bit;
203 else if (op > 0)
204 ndebug |= bit;
205 else {
206 if (bit == 0) {
207 if (isdigit(*cp))
208 bit = strtoul(cp, NULL, 0);
209 else
210 errx(1, "unknown flag %.*s",
211 (int) (tp-cp), cp);
212 }
213 ndebug = bit;
214 }
215 } while (*(cp = tp) != '\0');
216 }
217 if (debug != ndebug) {
218 printf("%s: 0x%llx => ", oid, (long long) debug);
219 if (sysctlbyname(oid, NULL, NULL, &ndebug, sizeof(ndebug)) < 0)
220 err(1, "sysctl-set(%s)", oid);
221 printf("0x%llx", (long long) ndebug);
222 debug = ndebug;
223 } else
224 printf("%s: 0x%llx", oid, (long long) debug);
225 sep = "<";
226 for (i = 0; i < nitems(flags); i++)
227 if (debug & flags[i].bit) {
228 printf("%s%s", sep, flags[i].name);
229 sep = ",";
230 }
231 printf("%s\n", *sep != '<' ? ">" : "");
232 return 0;
233 }
234