测试 USB 设备

USB 虚拟总线框架是一个非常有用的框架,可将 USB 函数驱动程序连接到 USB 设备驱动程序,以便进行测试。

测试 USB 设备驱动程序时用到以下文件。所有这三个文件应存储在同一目录中:

  • {driver}.cc:要测试的 USB 设备驱动程序。
  • {driver}-function.cc:用于模拟底层 USB 设备硬件的 USB 函数驱动程序。
  • {driver}-test.cc:测试计划,用于设置驱动程序并运行测试。

USB 虚拟总线将 USB 外设总线连接到 USB 总线,如下图所示:

usb-peripheral-bus -> {Your usb-function driver}
^
|
usb-virtual-bus
|
v
usb-bus -> {Your usb-driver}

编写 USB 函数驱动程序

USB 函数驱动程序可使当前主机看起来像一个外设 USB 设备。例如,通过 USB 大容量存储设备 (ums) 功能设备,在将主机插入另一台机器时,主机可以显示为块设备。如果主机有必要为您的设备类设置一个 USB 函数驱动程序,那么应该创建一个真正的 USB 函数驱动程序。除此之外,编写一个模拟 USB 设备硬件的 USB 函数是测试 USB 驱动程序的最简单方法。

USB 虚拟总线将您的 USB 函数驱动程序连接到您尝试测试的实际 USB 设备驱动程序。这样,设备驱动程序就可以在测试模式下运行,而无需修改设备驱动程序。

USB 函数驱动程序示例:

USB 函数驱动程序需要实现 UsbFunctionInterface 班卓琴接口。这些是 USB 虚拟总线库在 USB 堆栈中设置驱动程序时调用的函数。

USB 函数驱动程序会根据 UsbFunction 协议进行绑定。通过这些调用,函数驱动程序可以分配端点、注册接口回调、将 USB 请求加入队列等。

绑定规则

USB 函数驱动程序需要绑定到 ZX_PROTOCOL_USB_FUNCTION 协议。可以针对 USB 类、USB 子类和 USB 协议添加其他绑定规则。

以下示例展示了一条绑定规则,其中 {} 表示应替换为您的信息的区域:

using fuchsia.usb;

fuchsia.BIND_PROTOCOL == fuchsia.usb.BIND_PROTOCOL.FUNCTION;
fuchsia.BIND_USB_CLASS == {usb_class}
fuchsia.BIND_USB_SUBCLASS == {usb_subclass}
fuchsia.BIND_USB_PROTOCOL == {usb_protocol}

编写 USB 虚拟总线测试

应使用 usb 虚拟总线启动器库编写测试。

测试启动的第一项内容是 USB 函数驱动程序,如编写 USB 函数驱动程序中所述。您可以通过将绑定规则添加到 usb_peripheral::FunctionDescriptor 并使用 SetupPeripheralDevice() 函数来启动此测试。例如:

// Set up your USB Device Descriptor.
usb_peripheral::DeviceDescriptor device_desc = {};

/ Set up your USB Function descriptors.
std::vector<usb_peripheral::FunctionDescriptor> function_descs;
usb_peripheral::FunctionDescriptor function_desc = {
    .interface_class = {usb_class},
    .interface_subclass = {usb_subclass},
    .interface_protocol = {usb_protocol},
};
function_descs.push_back(function_desc);

ASSERT_NO_FATAL_FAILURE(SetupPeripheralDevice(device_desc, std::move(function_descs)));

SetupPeripheralDevice 函数成功执行后,USB 函数驱动程序会进行绑定。

USB 虚拟总线将函数驱动程序连接到系统,然后绑定实际的设备驱动程序。然后,您的测试可以通过 devfs 连接到 USB 设备驱动程序。绑定是异步执行的,因此您必须等待 devfs 检测到驱动程序。监控文件的东方方法是使用 fdio_watch_directory 函数。

现在您已连接到设备,可以正常进行 FIDL 调用了。 驱动程序会处理这些 FIDL 调用,并像调用真实硬件一样调用 USB 函数驱动程序。