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