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()