Edit online

Host 侧 usbtest.ko

31 Jan 2024
Read time: 9 minute(s)
在 Host 侧的 usbtest.ko 是一个标准的 usb interface driver。它根据 Vendor ID = 0x0525Product 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()