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