1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* $(CROSS_COMPILE)cc -Wall -Wextra -g -lpthread -o testusb testusb.c */ 3 4 /* 5 * Copyright (c) 2002 by David Brownell 6 * Copyright (c) 2010 by Samsung Electronics 7 * Author: Michal Nazarewicz <mina86@mina86.com> 8 */ 9 10 /* 11 * This program issues ioctls to perform the tests implemented by the 12 * kernel driver. It can generate a variety of transfer patterns; you 13 * should make sure to test both regular streaming and mixes of 14 * transfer sizes (including short transfers). 15 * 16 * For more information on how this can be used and on USB testing 17 * refer to <URL:http://www.linux-usb.org/usbtest/>. 18 */ 19 20 #include <stdio.h> 21 #include <string.h> 22 #include <ftw.h> 23 #include <stdlib.h> 24 #include <pthread.h> 25 #include <unistd.h> 26 #include <errno.h> 27 #include <limits.h> 28 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <fcntl.h> 32 33 #include <sys/ioctl.h> 34 #include <linux/usbdevice_fs.h> 35 36 /*-------------------------------------------------------------------------*/ 37 38 #define TEST_CASES 30 39 40 // FIXME make these public somewhere; usbdevfs.h? 41 42 struct usbtest_param { 43 // inputs 44 unsigned test_num; /* 0..(TEST_CASES-1) */ 45 unsigned iterations; 46 unsigned length; 47 unsigned vary; 48 unsigned sglen; 49 50 // outputs 51 struct timeval duration; 52 }; 53 #define USBTEST_REQUEST _IOWR('U', 100, struct usbtest_param) 54 55 /*-------------------------------------------------------------------------*/ 56 57 /* #include <linux/usb_ch9.h> */ 58 59 #define USB_DT_DEVICE 0x01 60 #define USB_DT_INTERFACE 0x04 61 62 #define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ 63 #define USB_CLASS_VENDOR_SPEC 0xff 64 65 66 struct usb_device_descriptor { 67 __u8 bLength; 68 __u8 bDescriptorType; 69 __u16 bcdUSB; 70 __u8 bDeviceClass; 71 __u8 bDeviceSubClass; 72 __u8 bDeviceProtocol; 73 __u8 bMaxPacketSize0; 74 __u16 idVendor; 75 __u16 idProduct; 76 __u16 bcdDevice; 77 __u8 iManufacturer; 78 __u8 iProduct; 79 __u8 iSerialNumber; 80 __u8 bNumConfigurations; 81 } __attribute__ ((packed)); 82 83 struct usb_interface_descriptor { 84 __u8 bLength; 85 __u8 bDescriptorType; 86 87 __u8 bInterfaceNumber; 88 __u8 bAlternateSetting; 89 __u8 bNumEndpoints; 90 __u8 bInterfaceClass; 91 __u8 bInterfaceSubClass; 92 __u8 bInterfaceProtocol; 93 __u8 iInterface; 94 } __attribute__ ((packed)); 95 96 enum usb_device_speed { 97 USB_SPEED_UNKNOWN = 0, /* enumerating */ 98 USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ 99 USB_SPEED_HIGH /* usb 2.0 */ 100 }; 101 102 /*-------------------------------------------------------------------------*/ 103 104 static char *speed (enum usb_device_speed s) 105 { 106 switch (s) { 107 case USB_SPEED_UNKNOWN: return "unknown"; 108 case USB_SPEED_LOW: return "low"; 109 case USB_SPEED_FULL: return "full"; 110 case USB_SPEED_HIGH: return "high"; 111 default: return "??"; 112 } 113 } 114 115 struct testdev { 116 struct testdev *next; 117 char *name; 118 pthread_t thread; 119 enum usb_device_speed speed; 120 unsigned ifnum : 8; 121 unsigned forever : 1; 122 int test; 123 124 struct usbtest_param param; 125 }; 126 static struct testdev *testdevs; 127 128 static int testdev_ffs_ifnum(FILE *fd) 129 { 130 union { 131 char buf[255]; 132 struct usb_interface_descriptor intf; 133 } u; 134 135 for (;;) { 136 if (fread(u.buf, 1, 1, fd) != 1) 137 return -1; 138 if (fread(u.buf + 1, (unsigned char)u.buf[0] - 1, 1, fd) != 1) 139 return -1; 140 141 if (u.intf.bLength == sizeof u.intf 142 && u.intf.bDescriptorType == USB_DT_INTERFACE 143 && u.intf.bNumEndpoints == 2 144 && u.intf.bInterfaceClass == USB_CLASS_VENDOR_SPEC 145 && u.intf.bInterfaceSubClass == 0 146 && u.intf.bInterfaceProtocol == 0) 147 return (unsigned char)u.intf.bInterfaceNumber; 148 } 149 } 150 151 static int testdev_ifnum(FILE *fd) 152 { 153 struct usb_device_descriptor dev; 154 155 if (fread(&dev, sizeof dev, 1, fd) != 1) 156 return -1; 157 158 if (dev.bLength != sizeof dev || dev.bDescriptorType != USB_DT_DEVICE) 159 return -1; 160 161 /* FX2 with (tweaked) bulksrc firmware */ 162 if (dev.idVendor == 0x0547 && dev.idProduct == 0x1002) 163 return 0; 164 165 /*----------------------------------------------------*/ 166 167 /* devices that start up using the EZ-USB default device and 168 * which we can use after loading simple firmware. hotplug 169 * can fxload it, and then run this test driver. 170 * 171 * we return false positives in two cases: 172 * - the device has a "real" driver (maybe usb-serial) that 173 * renumerates. the device should vanish quickly. 174 * - the device doesn't have the test firmware installed. 175 */ 176 177 /* generic EZ-USB FX controller */ 178 if (dev.idVendor == 0x0547 && dev.idProduct == 0x2235) 179 return 0; 180 181 /* generic EZ-USB FX2 controller */ 182 if (dev.idVendor == 0x04b4 && dev.idProduct == 0x8613) 183 return 0; 184 185 /* CY3671 development board with EZ-USB FX */ 186 if (dev.idVendor == 0x0547 && dev.idProduct == 0x0080) 187 return 0; 188 189 /* Keyspan 19Qi uses an21xx (original EZ-USB) */ 190 if (dev.idVendor == 0x06cd && dev.idProduct == 0x010b) 191 return 0; 192 193 /*----------------------------------------------------*/ 194 195 /* "gadget zero", Linux-USB test software */ 196 if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4a0) 197 return 0; 198 199 /* user mode subset of that */ 200 if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4a4) 201 return testdev_ffs_ifnum(fd); 202 /* return 0; */ 203 204 /* iso version of usermode code */ 205 if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4a3) 206 return 0; 207 208 /* some GPL'd test firmware uses these IDs */ 209 210 if (dev.idVendor == 0xfff0 && dev.idProduct == 0xfff0) 211 return 0; 212 213 /*----------------------------------------------------*/ 214 215 /* iBOT2 high speed webcam */ 216 if (dev.idVendor == 0x0b62 && dev.idProduct == 0x0059) 217 return 0; 218 219 /*----------------------------------------------------*/ 220 221 /* the FunctionFS gadget can have the source/sink interface 222 * anywhere. We look for an interface descriptor that match 223 * what we expect. We ignore configuratiens thou. */ 224 225 if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4ac 226 && (dev.bDeviceClass == USB_CLASS_PER_INTERFACE 227 || dev.bDeviceClass == USB_CLASS_VENDOR_SPEC)) 228 return testdev_ffs_ifnum(fd); 229 230 return -1; 231 } 232 233 static int find_testdev(const char *name, const struct stat *sb, int flag) 234 { 235 FILE *fd; 236 int ifnum; 237 struct testdev *entry; 238 239 (void)sb; /* unused */ 240 241 if (flag != FTW_F) 242 return 0; 243 244 fd = fopen(name, "rb"); 245 if (!fd) { 246 perror(name); 247 return 0; 248 } 249 250 ifnum = testdev_ifnum(fd); 251 fclose(fd); 252 if (ifnum < 0) 253 return 0; 254 255 entry = calloc(1, sizeof *entry); 256 if (!entry) 257 goto nomem; 258 259 entry->name = strdup(name); 260 if (!entry->name) { 261 free(entry); 262 nomem: 263 perror("malloc"); 264 return 0; 265 } 266 267 entry->ifnum = ifnum; 268 269 /* FIXME update USBDEVFS_CONNECTINFO so it tells about high speed etc */ 270 271 fprintf(stderr, "%s speed\t%s\t%u\n", 272 speed(entry->speed), entry->name, entry->ifnum); 273 274 entry->next = testdevs; 275 testdevs = entry; 276 return 0; 277 } 278 279 static int 280 usbdev_ioctl (int fd, int ifno, unsigned request, void *param) 281 { 282 struct usbdevfs_ioctl wrapper; 283 284 wrapper.ifno = ifno; 285 wrapper.ioctl_code = request; 286 wrapper.data = param; 287 288 return ioctl (fd, USBDEVFS_IOCTL, &wrapper); 289 } 290 291 static void *handle_testdev (void *arg) 292 { 293 struct testdev *dev = arg; 294 int fd, i; 295 int status; 296 297 if ((fd = open (dev->name, O_RDWR)) < 0) { 298 perror ("can't open dev file r/w"); 299 return 0; 300 } 301 302 restart: 303 for (i = 0; i < TEST_CASES; i++) { 304 if (dev->test != -1 && dev->test != i) 305 continue; 306 dev->param.test_num = i; 307 308 status = usbdev_ioctl (fd, dev->ifnum, 309 USBTEST_REQUEST, &dev->param); 310 if (status < 0 && errno == EOPNOTSUPP) 311 continue; 312 313 /* FIXME need a "syslog it" option for background testing */ 314 315 /* NOTE: each thread emits complete lines; no fragments! */ 316 if (status < 0) { 317 char buf [80]; 318 int err = errno; 319 320 if (strerror_r (errno, buf, sizeof buf)) { 321 snprintf (buf, sizeof buf, "error %d", err); 322 errno = err; 323 } 324 printf ("%s test %d --> %d (%s)\n", 325 dev->name, i, errno, buf); 326 } else 327 printf ("%s test %d, %4d.%.06d secs\n", dev->name, i, 328 (int) dev->param.duration.tv_sec, 329 (int) dev->param.duration.tv_usec); 330 331 fflush (stdout); 332 } 333 if (dev->forever) 334 goto restart; 335 336 close (fd); 337 return arg; 338 } 339 340 static const char *usb_dir_find(void) 341 { 342 static char udev_usb_path[] = "/dev/bus/usb"; 343 344 if (access(udev_usb_path, F_OK) == 0) 345 return udev_usb_path; 346 347 return NULL; 348 } 349 350 static int parse_num(unsigned *num, const char *str) 351 { 352 unsigned long val; 353 char *end; 354 355 errno = 0; 356 val = strtoul(str, &end, 0); 357 if (errno || *end || val > UINT_MAX) 358 return -1; 359 *num = val; 360 return 0; 361 } 362 363 int main (int argc, char **argv) 364 { 365 366 int c; 367 struct testdev *entry; 368 char *device; 369 const char *usb_dir = NULL; 370 int all = 0, forever = 0, not = 0; 371 int test = -1 /* all */; 372 struct usbtest_param param; 373 374 /* pick defaults that works with all speeds, without short packets. 375 * 376 * Best per-frame data rates: 377 * super speed,bulk 1024 * 16 * 8 = 131072 378 * interrupt 1024 * 3 * 8 = 24576 379 * high speed, bulk 512 * 13 * 8 = 53248 380 * interrupt 1024 * 3 * 8 = 24576 381 * full speed, bulk/intr 64 * 19 = 1216 382 * interrupt 64 * 1 = 64 383 * low speed, interrupt 8 * 1 = 8 384 */ 385 param.iterations = 1000; 386 param.length = 1024; 387 param.vary = 1024; 388 param.sglen = 32; 389 390 /* for easy use when hotplugging */ 391 device = getenv ("DEVICE"); 392 393 while ((c = getopt (argc, argv, "D:aA:c:g:hlns:t:v:")) != EOF) 394 switch (c) { 395 case 'D': /* device, if only one */ 396 device = optarg; 397 continue; 398 case 'A': /* use all devices with specified USB dir */ 399 usb_dir = optarg; 400 /* FALL THROUGH */ 401 case 'a': /* use all devices */ 402 device = NULL; 403 all = 1; 404 continue; 405 case 'c': /* count iterations */ 406 if (parse_num(¶m.iterations, optarg)) 407 goto usage; 408 continue; 409 case 'g': /* scatter/gather entries */ 410 if (parse_num(¶m.sglen, optarg)) 411 goto usage; 412 continue; 413 case 'l': /* loop forever */ 414 forever = 1; 415 continue; 416 case 'n': /* no test running! */ 417 not = 1; 418 continue; 419 case 's': /* size of packet */ 420 if (parse_num(¶m.length, optarg)) 421 goto usage; 422 continue; 423 case 't': /* run just one test */ 424 test = atoi (optarg); 425 if (test < 0) 426 goto usage; 427 continue; 428 case 'v': /* vary packet size by ... */ 429 if (parse_num(¶m.vary, optarg)) 430 goto usage; 431 continue; 432 case '?': 433 case 'h': 434 default: 435 usage: 436 fprintf (stderr, 437 "usage: %s [options]\n" 438 "Options:\n" 439 "\t-D dev only test specific device\n" 440 "\t-A usb-dir\n" 441 "\t-a test all recognized devices\n" 442 "\t-l loop forever(for stress test)\n" 443 "\t-t testnum only run specified case\n" 444 "\t-n no test running, show devices to be tested\n" 445 "Case arguments:\n" 446 "\t-c iterations default 1000\n" 447 "\t-s transfer length default 1024\n" 448 "\t-g sglen default 32\n" 449 "\t-v vary default 1024\n", 450 argv[0]); 451 return 1; 452 } 453 if (optind != argc) 454 goto usage; 455 if (!all && !device) { 456 fprintf (stderr, "must specify '-a' or '-D dev', " 457 "or DEVICE=/dev/bus/usb/BBB/DDD in env\n"); 458 goto usage; 459 } 460 461 /* Find usb device subdirectory */ 462 if (!usb_dir) { 463 usb_dir = usb_dir_find(); 464 if (!usb_dir) { 465 fputs ("USB device files are missing\n", stderr); 466 return -1; 467 } 468 } 469 470 /* collect and list the test devices */ 471 if (ftw (usb_dir, find_testdev, 3) != 0) { 472 fputs ("ftw failed; are USB device files missing?\n", stderr); 473 return -1; 474 } 475 476 /* quit, run single test, or create test threads */ 477 if (!testdevs && !device) { 478 fputs ("no test devices recognized\n", stderr); 479 return -1; 480 } 481 if (not) 482 return 0; 483 if (testdevs && testdevs->next == 0 && !device) 484 device = testdevs->name; 485 for (entry = testdevs; entry; entry = entry->next) { 486 int status; 487 488 entry->param = param; 489 entry->forever = forever; 490 entry->test = test; 491 492 if (device) { 493 if (strcmp (entry->name, device)) 494 continue; 495 return handle_testdev (entry) != entry; 496 } 497 status = pthread_create (&entry->thread, 0, handle_testdev, entry); 498 if (status) 499 perror ("pthread_create"); 500 } 501 if (device) { 502 struct testdev dev; 503 504 /* kernel can recognize test devices we don't */ 505 fprintf (stderr, "%s: %s may see only control tests\n", 506 argv [0], device); 507 508 memset (&dev, 0, sizeof dev); 509 dev.name = device; 510 dev.param = param; 511 dev.forever = forever; 512 dev.test = test; 513 return handle_testdev (&dev) != &dev; 514 } 515 516 /* wait for tests to complete */ 517 for (entry = testdevs; entry; entry = entry->next) { 518 void *retval; 519 520 if (pthread_join (entry->thread, &retval)) 521 perror ("pthread_join"); 522 /* testing errors discarded! */ 523 } 524 525 return 0; 526 } 527