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