1 /* $OpenBSD: usbdevs.c,v 1.29 2018/07/12 07:58:23 mpi Exp $ */ 2 /* $NetBSD: usbdevs.c,v 1.19 2002/02/21 00:34:31 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Lennart Augustsson (augustss@netbsd.org). 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/types.h> 34 #include <dev/usb/usb.h> 35 36 #include <err.h> 37 #include <errno.h> 38 #include <fcntl.h> 39 #include <limits.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <unistd.h> 44 45 #ifndef nitems 46 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) 47 #endif 48 49 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 50 51 #define USBDEV "/dev/usb" 52 53 int verbose = 0; 54 55 void usage(void); 56 void usbdev(int f, uint8_t); 57 void usbdump(int f); 58 void dumpone(char *name, int f, int addr); 59 int main(int, char **); 60 61 extern char *__progname; 62 63 void 64 usage(void) 65 { 66 fprintf(stderr, "usage: %s [-v] [-a addr] [-d usbdev]\n", __progname); 67 exit(1); 68 } 69 70 char done[USB_MAX_DEVICES]; 71 72 void 73 usbdev(int f, uint8_t addr) 74 { 75 struct usb_device_info di; 76 int e, i, port, nports; 77 uint16_t change, status; 78 79 di.udi_addr = addr; 80 e = ioctl(f, USB_DEVICEINFO, &di); 81 if (e) { 82 if (errno != ENXIO) 83 printf("addr %d: I/O error\n", addr); 84 return; 85 } 86 87 printf("addr %02u: ", addr); 88 done[addr] = 1; 89 printf("%04x:%04x %s, %s", di.udi_vendorNo, di.udi_productNo, 90 di.udi_vendor, di.udi_product); 91 92 if (verbose) { 93 printf("\n\t "); 94 switch (di.udi_speed) { 95 case USB_SPEED_LOW: 96 printf("low speed, "); 97 break; 98 case USB_SPEED_FULL: 99 printf("full speed, "); 100 break; 101 case USB_SPEED_HIGH: 102 printf("high speed, "); 103 break; 104 case USB_SPEED_SUPER: 105 printf("super speed, "); 106 break; 107 default: 108 break; 109 } 110 111 if (di.udi_power) 112 printf("power %d mA, ", di.udi_power); 113 else 114 printf("self powered, "); 115 if (di.udi_config) 116 printf("config %d, ", di.udi_config); 117 else 118 printf("unconfigured, "); 119 120 printf("rev %s", di.udi_release); 121 if (strlen(di.udi_serial)) 122 printf(", iSerialNumber %s", di.udi_serial); 123 } 124 printf("\n"); 125 126 if (verbose) { 127 for (i = 0; i < USB_MAX_DEVNAMES; i++) 128 if (di.udi_devnames[i][0]) 129 printf("\t driver: %s\n", di.udi_devnames[i]); 130 } 131 132 if (verbose > 1) { 133 nports = MINIMUM(di.udi_nports, nitems(di.udi_ports)); 134 for (port = 0; port < nports; port++) { 135 status = di.udi_ports[port] & 0xffff; 136 change = di.udi_ports[port] >> 16; 137 printf("\t port %02u: %04x.%04x", port+1, change, 138 status); 139 140 if (status & UPS_CURRENT_CONNECT_STATUS) 141 printf(" connect"); 142 143 if (status & UPS_PORT_ENABLED) 144 printf(" enabled"); 145 146 if (status & UPS_SUSPEND) 147 printf(" supsend"); 148 149 if (status & UPS_OVERCURRENT_INDICATOR) 150 printf(" overcurrent"); 151 152 if (di.udi_speed < USB_SPEED_SUPER) { 153 if (status & UPS_PORT_L1) 154 printf(" l1"); 155 156 if (status & UPS_PORT_POWER) 157 printf(" power"); 158 } else { 159 if (status & UPS_PORT_POWER_SS) 160 printf(" power"); 161 162 switch (UPS_PORT_LS_GET(status)) { 163 case UPS_PORT_LS_U0: 164 printf(" U0"); 165 break; 166 case UPS_PORT_LS_U1: 167 printf(" U1"); 168 break; 169 case UPS_PORT_LS_U2: 170 printf(" U2"); 171 break; 172 case UPS_PORT_LS_U3: 173 printf(" U3"); 174 break; 175 case UPS_PORT_LS_SS_DISABLED: 176 printf(" SS.disabled"); 177 break; 178 case UPS_PORT_LS_RX_DETECT: 179 printf(" Rx.detect"); 180 break; 181 case UPS_PORT_LS_SS_INACTIVE: 182 printf(" ss.inactive"); 183 break; 184 case UPS_PORT_LS_POLLING: 185 printf(" polling"); 186 break; 187 case UPS_PORT_LS_RECOVERY: 188 printf(" recovery"); 189 break; 190 case UPS_PORT_LS_HOT_RESET: 191 printf(" hot.reset"); 192 break; 193 case UPS_PORT_LS_COMP_MOD: 194 printf(" comp.mod"); 195 break; 196 case UPS_PORT_LS_LOOPBACK: 197 printf(" loopback"); 198 break; 199 } 200 } 201 202 printf("\n"); 203 } 204 } 205 } 206 207 void 208 usbdump(int f) 209 { 210 uint8_t addr; 211 212 for (addr = 1; addr < USB_MAX_DEVICES; addr++) { 213 if (!done[addr]) 214 usbdev(f, addr); 215 } 216 } 217 218 void 219 dumpone(char *name, int f, int addr) 220 { 221 if (!addr) 222 printf("Controller %s:\n", name); 223 memset(done, 0, sizeof done); 224 if (addr) 225 usbdev(f, addr); 226 else 227 usbdump(f); 228 } 229 230 int 231 main(int argc, char **argv) 232 { 233 int ch, i, f; 234 char buf[50]; 235 char *dev = NULL; 236 const char *errstr; 237 int addr = 0; 238 int ncont; 239 240 while ((ch = getopt(argc, argv, "a:d:v?")) != -1) { 241 switch (ch) { 242 case 'a': 243 addr = strtonum(optarg, 1, USB_MAX_DEVICES, &errstr); 244 if (errstr) 245 errx(1, "addr %s", errstr); 246 break; 247 case 'd': 248 dev = optarg; 249 break; 250 case 'v': 251 verbose++; 252 break; 253 default: 254 usage(); 255 } 256 } 257 argc -= optind; 258 argv += optind; 259 260 if (argc != 0) 261 usage(); 262 263 if (dev == 0) { 264 for (ncont = 0, i = 0; i < 10; i++) { 265 snprintf(buf, sizeof buf, "%s%d", USBDEV, i); 266 f = open(buf, O_RDONLY); 267 if (f >= 0) { 268 dumpone(buf, f, addr); 269 close(f); 270 } else { 271 if (errno == ENOENT || errno == ENXIO) 272 continue; 273 warn("%s", buf); 274 } 275 ncont++; 276 } 277 if (verbose && ncont == 0) 278 printf("%s: no USB controllers found\n", 279 __progname); 280 } else { 281 f = open(dev, O_RDONLY); 282 if (f >= 0) { 283 dumpone(dev, f, addr); 284 close(f); 285 } else 286 err(1, "%s", dev); 287 } 288 289 return 0; 290 } 291