Host 侧 usbtest.ko
usbtest.ko
是一个标准的 usb interface driver
。它根据
Vendor ID = 0x0525
、 Product ID = 0xa4a0
适配上一节
Composite Device
中的 SourceSink Interface
或者
Loopback
Interface
。static const struct usb_device_id id_table[] = { /* "Gadget Zero" firmware runs under Linux */ { USB_DEVICE(0x0525, 0xa4a0), .driver_info = (unsigned long) &gz_info, }, } MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver usbtest_driver = { .name = "usbtest", .id_table = id_table, .probe = usbtest_probe, .unlocked_ioctl = usbtest_ioctl, .disconnect = usbtest_disconnect, .suspend = usbtest_suspend, .resume = usbtest_resume, };
TestCase
SourceSink Interface
提供的 4 个测试 endpoint、或者 Loopback
Interface
提供的 2 个测试 endpoint + Composite Device
本身的
ep0 control endpoint 基础之上,提供了 30 个
testcase:drivers\usb\misc\usbtest.c: usbtest_do_ioctl()
index | type | iterations | vary | sglen | unaligned | testcase | |
---|---|---|---|---|---|---|---|
0 | nop | | | | | “TEST 0: NOPn” | |
1 | bulk | Y | | | |
“TEST 1: write %d bytes %u timesn”, param->length, param->iterations |
Simple non-queued bulk I/O tests |
2 | bulk | Y | | | |
“TEST 2: read %d bytes %u timesn”, param->length, param->iterations |
|
3 | bulk | Y | Y | | |
“TEST 3: write/%d 0..%d bytes %u timesn”, param->vary, param->length, param->iterations |
|
4 | bulk | Y | Y | | |
“TEST 4: read/%d 0..%d bytes %u timesn”, param->vary, param->length, param->iterations |
|
5 | bulk | Y | | Y | |
“TEST 5: write %d sglists %d entries of %d bytesn”, param->iterations,param->sglen, param->length |
|
6 | bulk | Y | | Y | |
“TEST 6: read %d sglists %d entries of %d bytesn”, param->iterations,param->sglen, param->length |
|
7 | bulk | Y | Y | Y | |
“TEST 7: write/%d %d sglists %d entries 0..%d bytesn”, param->vary, param->iterations,param->sglen, param->length |
|
8 | bulk | Y | Y | Y | |
“TEST 8: read/%d %d sglists %d entries 0..%d bytesn”, param->vary, param->iterations,param->sglen, param->length |
|
9 | control | Y | | | |
“TEST 9: ch9 (subset) control tests, %d timesn”, param->iterations |
non-queued sanity tests for control (chapter 9 subset) |
10 | control | Y | | Y | |
“TEST 10: queue %d control calls, %d timesn”, param->sglen, param->iterations) |
queued control messaging |
11 | bulk | Y | | | |
“TEST 11: unlink %d reads of %dn”, param->iterations, param->length |
simple non-queued unlinks (ring with one urb) |
12 | bulk | Y | | | |
“TEST 12: unlink %d writes of %dn”, param->iterations, param->length |
|
13 | control | Y | | | |
“TEST 13: set/clear %d haltsn” param->iterations |
ep halt tests |
14 | control | Y | Y | | |
“TEST 14: %d ep0out, %d..%d vary %dn”, param->iterations,realworld ? 1 : 0, param->length,param->vary |
control write tests |
15 | iso | Y | | Y | |
“TEST 15: write %d iso, %d entries of %d bytesn”, param->iterations, param->sglen, param->length |
iso write tests |
16 | iso | Y | | Y | |
“TEST 16: read %d iso, %d entries of %d bytesn”, param->iterations, param->sglen, param->length |
iso read tests |
17 | bulk | Y | | | Y |
“TEST 17: write odd addr %d bytes %u times core mapn” param->length, param->iterations |
Tests for bulk I/O using DMA mapping by core and odd address |
18 | bulk | Y | | | Y |
“TEST 18: read odd addr %d bytes %u times core mapn”, param->length, param->iterations |
|
19 | bulk | Y | | | Y |
“TEST 19: write odd addr %d bytes %u times premappedn”, param->length, param->iterations |
Tests for bulk I/O using premapped coherent buffer and odd address |
20 | bulk | Y | | | Y |
“TEST 20: read odd addr %d bytes %u times premappedn”, param->length, param->iterations |
|
21 | control | Y | Y | | Y |
“TEST 21: %d ep0out odd addr, %d..%d vary %dn”,param->iterations,realworld ? 1 : 0, param->length, param->vary |
control write tests with unaligned buffer |
22 | iso | Y | | Y | Y |
“TEST 22: write %d iso odd, %d entries of %d bytesn”, param->iterations, param->sglen, param->length |
unaligned iso tests |
23 | iso | Y | | Y | Y |
“TEST 23: read %d iso odd, %d entries of %d bytesn”, param->iterations, param->sglen, param->length |
|
24 | bulk | Y | | Y | |
“TEST 24: unlink from %d queues of %d %d-byte writesn”, param->iterations, param->sglen, param->length |
unlink URBs from a bulk-OUT queue |
25 | int | Y | | | |
“TEST 25: write %d bytes %u timesn”, param->length, param->iterations |
Simple non-queued interrupt I/O tests |
26 | int | Y | | | |
“TEST 26: read %d bytes %u timesn”, param->length, param->iterations |
|
27 | bulk | Y | | Y | |
“TEST 27: bulk write %dMbytesn”, (param->iterations * param->sglen * param->length) / (1024 * 1024)) |
Performance test |
28 | bulk | Y | | Y | |
“TEST 28: bulk read %dMbytesn”, (param->iterations * param->sglen * param->length) / (1024 * 1024)) |
|
29 | bulk | Y | | | |
“TEST 29: Clear toggle between bulk writes %d timesn”, param->iterations |
|
Ioctl
usbtest.ko 以 ioctl 的形式向用户态提供对 testcase 的调用:
usbdev_file_operations → usbdev_ioctl() → usbdev_do_ioctl() → proc_ioctl_default() → proc_ioctl(): static int proc_ioctl(struct usb_dev_state *ps, struct usbdevfs_ioctl *ctl) { /* (1) 找到对应的 usb interface device */ else if (!(intf = usb_ifnum_to_if(ps->dev, ctl->ifno))) retval = -EINVAL; /* talk directly to the interface's driver */ default: if (intf->dev.driver) /* (2) 找到 usb interface device 对应的 driver */ driver = to_usb_driver(intf->dev.driver); if (driver == NULL || driver->unlocked_ioctl == NULL) { retval = -ENOTTY; } else { /* (3) 调用 driver 的 ioctl 函数 */ retval = driver->unlocked_ioctl(intf, ctl->ioctl_code, buf); if (retval == -ENOIOCTLCMD) retval = -ENOTTY; } } ↓ usbtest_ioctl() → usbtest_do_ioctl()