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