94553989f1db72aac66a5040fa4f6b70aec42b50
[dragonfly.git] / usr.sbin / usbdevs / usbdevs.c
1 /*
2  * $NetBSD: usbdevs.c,v 1.17 2001/02/19 23:22:48 cgd Exp $
3  * $FreeBSD: src/usr.sbin/usbdevs/usbdevs.c,v 1.8 2002/04/22 13:44:47 des Exp $
4  * $DragonFly: src/usr.sbin/usbdevs/usbdevs.c,v 1.4 2003/12/30 01:01:48 dillon Exp $
5  */
6
7 /*
8  * Copyright (c) 1998 The NetBSD Foundation, Inc.
9  * All rights reserved.
10  *
11  * This code is derived from software contributed to The NetBSD Foundation
12  * by Lennart Augustsson (augustss@netbsd.org).
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. All advertising materials mentioning features or use of this software
23  *    must display the following acknowledgement:
24  *        This product includes software developed by the NetBSD
25  *        Foundation, Inc. and its contributors.
26  * 4. Neither the name of The NetBSD Foundation nor the names of its
27  *    contributors may be used to endorse or promote products derived
28  *    from this software without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
31  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
32  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
34  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40  * POSSIBILITY OF SUCH DAMAGE.
41  */
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <sys/types.h>
47 #include <fcntl.h>
48 #include <unistd.h>
49 #include <err.h>
50 #include <errno.h>
51 #include <bus/usb/usb.h>
52 #if defined(__FreeBSD__)
53 #include <sys/ioctl.h>
54 #endif
55
56 #define USBDEV "/dev/usb"
57
58 int verbose = 0;
59 int showdevs = 0;
60
61 void usage(void);
62 void usbdev(int f, int a, int rec);
63 void usbdump(int f);
64 void dumpone(char *name, int f, int addr);
65 int main(int, char **);
66
67 void
68 usage()
69 {
70         fprintf(stderr, "usage: %s [-a addr] [-d] [-f dev] [-v]\n",
71             getprogname());
72         exit(1);
73 }
74
75 char done[USB_MAX_DEVICES];
76 int indent;
77
78 void
79 usbdev(int f, int a, int rec)
80 {
81         struct usb_device_info di;
82         int e, p, i;
83
84         di.udi_addr = a;
85         e = ioctl(f, USB_DEVICEINFO, &di);
86         if (e) {
87                 if (errno != ENXIO)
88                         printf("addr %d: I/O error\n", a);
89                 return;
90         }
91         printf("addr %d: ", a);
92         done[a] = 1;
93         if (verbose) {
94                 switch (di.udi_speed) {
95                 case USB_SPEED_LOW:  printf("low speed, "); break;
96                 case USB_SPEED_FULL: printf("full speed, "); break;
97                 case USB_SPEED_HIGH: printf("high speed, "); break;
98                 default: break;
99                 }
100                 if (di.udi_power)
101                         printf("power %d mA, ", di.udi_power);
102                 else
103                         printf("self powered, ");
104                 if (di.udi_config)
105                         printf("config %d, ", di.udi_config);
106                 else
107                         printf("unconfigured, ");
108         }
109         if (verbose) {
110                 printf("%s(0x%04x), %s(0x%04x), rev %s",
111                        di.udi_product, di.udi_productNo,
112                        di.udi_vendor, di.udi_vendorNo, di.udi_release);
113         } else
114                 printf("%s, %s", di.udi_product, di.udi_vendor);
115         printf("\n");
116         if (showdevs) {
117                 for (i = 0; i < USB_MAX_DEVNAMES; i++)
118                         if (di.udi_devnames[i][0])
119                                 printf("%*s  %s\n", indent, "",
120                                        di.udi_devnames[i]);
121         }
122         if (!rec)
123                 return;
124         for (p = 0; p < di.udi_nports; p++) {
125                 int s = di.udi_ports[p];
126                 if (s >= USB_MAX_DEVICES) {
127                         if (verbose) {
128                                 printf("%*sport %d %s\n", indent+1, "", p+1,
129                                        s == USB_PORT_ENABLED ? "enabled" :
130                                        s == USB_PORT_SUSPENDED ? "suspended" : 
131                                        s == USB_PORT_POWERED ? "powered" :
132                                        s == USB_PORT_DISABLED ? "disabled" :
133                                        "???");
134                                 
135                         }
136                         continue;
137                 }
138                 indent++;
139                 printf("%*s", indent, "");
140                 if (verbose)
141                         printf("port %d ", p+1);
142                 if (s == 0)
143                         printf("addr 0 should never happen!\n");
144                 else
145                         usbdev(f, s, 1);
146                 indent--;
147         }
148 }
149
150 void
151 usbdump(int f)
152 {
153         int a;
154
155         for (a = 1; a < USB_MAX_DEVICES; a++) {
156                 if (!done[a])
157                         usbdev(f, a, 1);
158         }
159 }
160
161 void
162 dumpone(char *name, int f, int addr)
163 {
164         if (verbose)
165                 printf("Controller %s:\n", name);
166         indent = 0;
167         memset(done, 0, sizeof done);
168         if (addr)
169                 usbdev(f, addr, 0);
170         else
171                 usbdump(f);
172 }
173
174 int
175 main(int argc, char **argv)
176 {
177         int ch, i, f;
178         char buf[50];
179         char *dev = 0;
180         int addr = 0;
181         int ncont;
182
183         while ((ch = getopt(argc, argv, "a:df:v?")) != -1) {
184                 switch(ch) {
185                 case 'a':
186                         addr = atoi(optarg);
187                         break;
188                 case 'd':
189                         showdevs++;
190                         break;
191                 case 'f':
192                         dev = optarg;
193                         break;
194                 case 'v':
195                         verbose = 1;
196                         break;
197                 case '?':
198                 default:
199                         usage();
200                 }
201         }
202         argc -= optind;
203         argv += optind;
204
205         if (dev == 0) {
206                 for (ncont = 0, i = 0; i < 10; i++) {
207                         sprintf(buf, "%s%d", USBDEV, i);
208                         f = open(buf, O_RDONLY);
209                         if (f >= 0) {
210                                 dumpone(buf, f, addr);
211                                 close(f);
212                         } else {
213                                 if (errno == ENOENT || errno == ENXIO)
214                                         continue;
215                                 warn("%s", buf);
216                         }
217                         ncont++;
218                 }
219                 if (verbose && ncont == 0)
220                         printf("%s: no USB controllers found\n",
221                             getprogname());
222         } else {
223                 f = open(dev, O_RDONLY);
224                 if (f >= 0)
225                         dumpone(dev, f, addr);
226                 else
227                         err(1, "%s", dev);
228         }
229         exit(0);
230 }