GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / tools / usb / testusb.c
blob2fd966c30a0b50fe9b257df3e49b8ef50928fe24
1 /* $(CROSS_COMPILE)cc -Wall -Wextra -g -lpthread -o testusb testusb.c */
3 /*
4 * Copyright (c) 2002 by David Brownell
5 * Copyright (c) 2010 by Samsung Electronics
6 * Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * This program issues ioctls to perform the tests implemented by the
25 * kernel driver. It can generate a variety of transfer patterns; you
26 * should make sure to test both regular streaming and mixes of
27 * transfer sizes (including short transfers).
29 * For more information on how this can be used and on USB testing
30 * refer to <URL:http://www.linux-usb.org/usbtest/>.
33 #include <stdio.h>
34 #include <string.h>
35 #include <ftw.h>
36 #include <stdlib.h>
37 #include <pthread.h>
38 #include <unistd.h>
39 #include <errno.h>
40 #include <limits.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
46 #include <sys/ioctl.h>
47 #include <linux/usbdevice_fs.h>
49 /*-------------------------------------------------------------------------*/
51 #define TEST_CASES 30
54 struct usbtest_param {
55 // inputs
56 unsigned test_num; /* 0..(TEST_CASES-1) */
57 unsigned iterations;
58 unsigned length;
59 unsigned vary;
60 unsigned sglen;
62 // outputs
63 struct timeval duration;
65 #define USBTEST_REQUEST _IOWR('U', 100, struct usbtest_param)
67 /*-------------------------------------------------------------------------*/
69 /* #include <linux/usb_ch9.h> */
71 #define USB_DT_DEVICE 0x01
72 #define USB_DT_INTERFACE 0x04
74 #define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
75 #define USB_CLASS_VENDOR_SPEC 0xff
78 struct usb_device_descriptor {
79 __u8 bLength;
80 __u8 bDescriptorType;
81 __u16 bcdUSB;
82 __u8 bDeviceClass;
83 __u8 bDeviceSubClass;
84 __u8 bDeviceProtocol;
85 __u8 bMaxPacketSize0;
86 __u16 idVendor;
87 __u16 idProduct;
88 __u16 bcdDevice;
89 __u8 iManufacturer;
90 __u8 iProduct;
91 __u8 iSerialNumber;
92 __u8 bNumConfigurations;
93 } __attribute__ ((packed));
95 struct usb_interface_descriptor {
96 __u8 bLength;
97 __u8 bDescriptorType;
99 __u8 bInterfaceNumber;
100 __u8 bAlternateSetting;
101 __u8 bNumEndpoints;
102 __u8 bInterfaceClass;
103 __u8 bInterfaceSubClass;
104 __u8 bInterfaceProtocol;
105 __u8 iInterface;
106 } __attribute__ ((packed));
108 enum usb_device_speed {
109 USB_SPEED_UNKNOWN = 0, /* enumerating */
110 USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
111 USB_SPEED_HIGH /* usb 2.0 */
114 /*-------------------------------------------------------------------------*/
116 static char *speed (enum usb_device_speed s)
118 switch (s) {
119 case USB_SPEED_UNKNOWN: return "unknown";
120 case USB_SPEED_LOW: return "low";
121 case USB_SPEED_FULL: return "full";
122 case USB_SPEED_HIGH: return "high";
123 default: return "??";
127 struct testdev {
128 struct testdev *next;
129 char *name;
130 pthread_t thread;
131 enum usb_device_speed speed;
132 unsigned ifnum : 8;
133 unsigned forever : 1;
134 int test;
136 struct usbtest_param param;
138 static struct testdev *testdevs;
140 static int testdev_ffs_ifnum(FILE *fd)
142 union {
143 char buf[255];
144 struct usb_interface_descriptor intf;
145 } u;
147 for (;;) {
148 if (fread(u.buf, 1, 1, fd) != 1)
149 return -1;
150 if (fread(u.buf + 1, (unsigned char)u.buf[0] - 1, 1, fd) != 1)
151 return -1;
153 if (u.intf.bLength == sizeof u.intf
154 && u.intf.bDescriptorType == USB_DT_INTERFACE
155 && u.intf.bNumEndpoints == 2
156 && u.intf.bInterfaceClass == USB_CLASS_VENDOR_SPEC
157 && u.intf.bInterfaceSubClass == 0
158 && u.intf.bInterfaceProtocol == 0)
159 return (unsigned char)u.intf.bInterfaceNumber;
163 static int testdev_ifnum(FILE *fd)
165 struct usb_device_descriptor dev;
167 if (fread(&dev, sizeof dev, 1, fd) != 1)
168 return -1;
170 if (dev.bLength != sizeof dev || dev.bDescriptorType != USB_DT_DEVICE)
171 return -1;
173 /* FX2 with (tweaked) bulksrc firmware */
174 if (dev.idVendor == 0x0547 && dev.idProduct == 0x1002)
175 return 0;
177 /*----------------------------------------------------*/
179 /* devices that start up using the EZ-USB default device and
180 * which we can use after loading simple firmware. hotplug
181 * can fxload it, and then run this test driver.
183 * we return false positives in two cases:
184 * - the device has a "real" driver (maybe usb-serial) that
185 * renumerates. the device should vanish quickly.
186 * - the device doesn't have the test firmware installed.
189 /* generic EZ-USB FX controller */
190 if (dev.idVendor == 0x0547 && dev.idProduct == 0x2235)
191 return 0;
193 /* generic EZ-USB FX2 controller */
194 if (dev.idVendor == 0x04b4 && dev.idProduct == 0x8613)
195 return 0;
197 /* CY3671 development board with EZ-USB FX */
198 if (dev.idVendor == 0x0547 && dev.idProduct == 0x0080)
199 return 0;
201 /* Keyspan 19Qi uses an21xx (original EZ-USB) */
202 if (dev.idVendor == 0x06cd && dev.idProduct == 0x010b)
203 return 0;
205 /*----------------------------------------------------*/
207 /* "gadget zero", Linux-USB test software */
208 if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4a0)
209 return 0;
211 /* user mode subset of that */
212 if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4a4)
213 return testdev_ffs_ifnum(fd);
214 /* return 0; */
216 /* iso version of usermode code */
217 if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4a3)
218 return 0;
220 /* some GPL'd test firmware uses these IDs */
222 if (dev.idVendor == 0xfff0 && dev.idProduct == 0xfff0)
223 return 0;
225 /*----------------------------------------------------*/
227 /* iBOT2 high speed webcam */
228 if (dev.idVendor == 0x0b62 && dev.idProduct == 0x0059)
229 return 0;
231 /*----------------------------------------------------*/
233 /* the FunctionFS gadget can have the source/sink interface
234 * anywhere. We look for an interface descriptor that match
235 * what we expect. We ignore configuratiens thou. */
237 if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4ac
238 && (dev.bDeviceClass == USB_CLASS_PER_INTERFACE
239 || dev.bDeviceClass == USB_CLASS_VENDOR_SPEC))
240 return testdev_ffs_ifnum(fd);
242 return -1;
245 static int find_testdev(const char *name, const struct stat *sb, int flag)
247 FILE *fd;
248 int ifnum;
249 struct testdev *entry;
251 (void)sb; /* unused */
253 if (flag != FTW_F)
254 return 0;
255 /* ignore /proc/bus/usb/{devices,drivers} */
256 if (strrchr(name, '/')[1] == 'd')
257 return 0;
259 fd = fopen(name, "rb");
260 if (!fd) {
261 perror(name);
262 return 0;
265 ifnum = testdev_ifnum(fd);
266 fclose(fd);
267 if (ifnum < 0)
268 return 0;
270 entry = calloc(1, sizeof *entry);
271 if (!entry)
272 goto nomem;
274 entry->name = strdup(name);
275 if (!entry->name) {
276 free(entry);
277 nomem:
278 perror("malloc");
279 return 0;
282 entry->ifnum = ifnum;
285 fprintf(stderr, "%s speed\t%s\t%u\n",
286 speed(entry->speed), entry->name, entry->ifnum);
288 entry->next = testdevs;
289 testdevs = entry;
290 return 0;
293 static int
294 usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
296 struct usbdevfs_ioctl wrapper;
298 wrapper.ifno = ifno;
299 wrapper.ioctl_code = request;
300 wrapper.data = param;
302 return ioctl (fd, USBDEVFS_IOCTL, &wrapper);
305 static void *handle_testdev (void *arg)
307 struct testdev *dev = arg;
308 int fd, i;
309 int status;
311 if ((fd = open (dev->name, O_RDWR)) < 0) {
312 perror ("can't open dev file r/w");
313 return 0;
316 restart:
317 for (i = 0; i < TEST_CASES; i++) {
318 if (dev->test != -1 && dev->test != i)
319 continue;
320 dev->param.test_num = i;
322 status = usbdev_ioctl (fd, dev->ifnum,
323 USBTEST_REQUEST, &dev->param);
324 if (status < 0 && errno == EOPNOTSUPP)
325 continue;
328 /* NOTE: each thread emits complete lines; no fragments! */
329 if (status < 0) {
330 char buf [80];
331 int err = errno;
333 if (strerror_r (errno, buf, sizeof buf)) {
334 snprintf (buf, sizeof buf, "error %d", err);
335 errno = err;
337 printf ("%s test %d --> %d (%s)\n",
338 dev->name, i, errno, buf);
339 } else
340 printf ("%s test %d, %4d.%.06d secs\n", dev->name, i,
341 (int) dev->param.duration.tv_sec,
342 (int) dev->param.duration.tv_usec);
344 fflush (stdout);
346 if (dev->forever)
347 goto restart;
349 close (fd);
350 return arg;
353 static const char *usbfs_dir_find(void)
355 static char usbfs_path_0[] = "/dev/usb/devices";
356 static char usbfs_path_1[] = "/proc/bus/usb/devices";
358 static char *const usbfs_paths[] = {
359 usbfs_path_0, usbfs_path_1
362 static char *const *
363 end = usbfs_paths + sizeof usbfs_paths / sizeof *usbfs_paths;
365 char *const *it = usbfs_paths;
366 do {
367 int fd = open(*it, O_RDONLY);
368 close(fd);
369 if (fd >= 0) {
370 strrchr(*it, '/')[0] = '\0';
371 return *it;
373 } while (++it != end);
375 return NULL;
378 static int parse_num(unsigned *num, const char *str)
380 unsigned long val;
381 char *end;
383 errno = 0;
384 val = strtoul(str, &end, 0);
385 if (errno || *end || val > UINT_MAX)
386 return -1;
387 *num = val;
388 return 0;
391 int main (int argc, char **argv)
394 int c;
395 struct testdev *entry;
396 char *device;
397 const char *usbfs_dir = NULL;
398 int all = 0, forever = 0, not = 0;
399 int test = -1 /* all */;
400 struct usbtest_param param;
402 /* pick defaults that works with all speeds, without short packets.
404 * Best per-frame data rates:
405 * high speed, bulk 512 * 13 * 8 = 53248
406 * interrupt 1024 * 3 * 8 = 24576
407 * full speed, bulk/intr 64 * 19 = 1216
408 * interrupt 64 * 1 = 64
409 * low speed, interrupt 8 * 1 = 8
411 param.iterations = 1000;
412 param.length = 512;
413 param.vary = 512;
414 param.sglen = 32;
416 /* for easy use when hotplugging */
417 device = getenv ("DEVICE");
419 while ((c = getopt (argc, argv, "D:aA:c:g:hns:t:v:")) != EOF)
420 switch (c) {
421 case 'D': /* device, if only one */
422 device = optarg;
423 continue;
424 case 'A': /* use all devices with specified usbfs dir */
425 usbfs_dir = optarg;
426 /* FALL THROUGH */
427 case 'a': /* use all devices */
428 device = NULL;
429 all = 1;
430 continue;
431 case 'c': /* count iterations */
432 if (parse_num(&param.iterations, optarg))
433 goto usage;
434 continue;
435 case 'g': /* scatter/gather entries */
436 if (parse_num(&param.sglen, optarg))
437 goto usage;
438 continue;
439 case 'l': /* loop forever */
440 forever = 1;
441 continue;
442 case 'n': /* no test running! */
443 not = 1;
444 continue;
445 case 's': /* size of packet */
446 if (parse_num(&param.length, optarg))
447 goto usage;
448 continue;
449 case 't': /* run just one test */
450 test = atoi (optarg);
451 if (test < 0)
452 goto usage;
453 continue;
454 case 'v': /* vary packet size by ... */
455 if (parse_num(&param.vary, optarg))
456 goto usage;
457 continue;
458 case '?':
459 case 'h':
460 default:
461 usage:
462 fprintf (stderr, "usage: %s [-n] [-D dev | -a | -A usbfs-dir]\n"
463 "\t[-c iterations] [-t testnum]\n"
464 "\t[-s packetsize] [-g sglen] [-v vary]\n",
465 argv [0]);
466 return 1;
468 if (optind != argc)
469 goto usage;
470 if (!all && !device) {
471 fprintf (stderr, "must specify '-a' or '-D dev', "
472 "or DEVICE=/proc/bus/usb/BBB/DDD in env\n");
473 goto usage;
476 /* Find usbfs mount point */
477 if (!usbfs_dir) {
478 usbfs_dir = usbfs_dir_find();
479 if (!usbfs_dir) {
480 fputs ("usbfs files are missing\n", stderr);
481 return -1;
485 /* collect and list the test devices */
486 if (ftw (usbfs_dir, find_testdev, 3) != 0) {
487 fputs ("ftw failed; is usbfs missing?\n", stderr);
488 return -1;
491 /* quit, run single test, or create test threads */
492 if (!testdevs && !device) {
493 fputs ("no test devices recognized\n", stderr);
494 return -1;
496 if (not)
497 return 0;
498 if (testdevs && testdevs->next == 0 && !device)
499 device = testdevs->name;
500 for (entry = testdevs; entry; entry = entry->next) {
501 int status;
503 entry->param = param;
504 entry->forever = forever;
505 entry->test = test;
507 if (device) {
508 if (strcmp (entry->name, device))
509 continue;
510 return handle_testdev (entry) != entry;
512 status = pthread_create (&entry->thread, 0, handle_testdev, entry);
513 if (status) {
514 perror ("pthread_create");
515 continue;
518 if (device) {
519 struct testdev dev;
521 /* kernel can recognize test devices we don't */
522 fprintf (stderr, "%s: %s may see only control tests\n",
523 argv [0], device);
525 memset (&dev, 0, sizeof dev);
526 dev.name = device;
527 dev.param = param;
528 dev.forever = forever;
529 dev.test = test;
530 return handle_testdev (&dev) != &dev;
533 /* wait for tests to complete */
534 for (entry = testdevs; entry; entry = entry->next) {
535 void *retval;
537 if (pthread_join (entry->thread, &retval))
538 perror ("pthread_join");
539 /* testing errors discarded! */
542 return 0;