Zircon 提供功能完备的 USB 子系统,支持开发 USB 主机和外围设备。它支持低速、全速、高速和超高速设备,以及各种标准自动协商机制。
在主机角色中,Zircon 的 USB 子系统采用分层方法,以便在设备连接到总线或从总线中移除时,轻松管理设备的生命周期。 在设备角色中,该子系统会编组进出特定于类的驱动程序(或驱动程序层次结构)的 USB 数据包。
目标硬件平台可能包含多个 USB 控制器。因此,Zircon 可能会在每个相应的物理总线上充当主机或设备。 不过,每个角色都是特定于特定总线拓扑的。除非另有说明,否则本文档将假定仅存在一条总线。
USB 子系统组件汇总如下:
- 特定于类的硬件驱动程序
- USB 集线器驱动程序(特定于类的驱动程序的特例)
- 总线驱动程序
- 主机或设备控制器接口驱动程序
主机角色
当作为 USB 主机运行时,Zircon 会充当权威的总线仲裁器。所连接 USB 设备的树以根 USB 集线器为根。无论是否存在任何实际的 hub 硬件,都必须存在此根 hub。对于包含支持主机的控制器但没有实际 hub 硬件的系统,必须在软件中模拟此根 hub。
为了便于总线仲裁,Zircon 运行以下驱动程序:
- USB 根 hub 驱动程序
- 总线驱动程序
- 主机控制器接口 (HCI) 驱动程序
这些驱动程序协同运行,以响应总线连接并管理所连接设备的生命周期。
设备角色
当作为 USB 设备运行时,Zircon 会在总线和特定于类的驱动程序(或驱动程序层次结构)之间传输 USB 数据包数据。在此角色中,总线驱动程序有助于 DCI 驱动程序与特定于类的驱动程序的上层之间进行通信。
特定于类的驱动程序
特定于类的驱动程序实现履行特定 USB 功能(例如 HID 类设备)所需的逻辑,同时保持对从实际总线读取和向实际总线写入物理数据包所需的硬件详细信息的不可知性。
一般来说,USB 设备驱动程序使用 FIDL 协议
fuchsia.hardware.usb.endpoint.Endpoint 与端点交互,并将传输
请求构建为 fuchsia.hardware.usb.request.Request 对象。
存在 usb::EndpointClient 和
usb::FidlRequest 等 C++ 辅助类,以便简化使用。驱动程序不会为每次传输分配请求,而是使用 RegisterVmos(或 EndpointClient::AddRequests)预注册 VMO 数据缓冲区。更高级别的设备驱动程序使用 QueueRequests 将请求发布到端点队列。由于传输由硬件提供服务,因此 USB 堆栈会通过异步 OnCompletion 事件(携带已完成请求和传输状态的矢量)通知上层。
Hub 驱动程序
hub 驱动程序的目的是根据 USB 2.0 规范的 CH11 管理 hub 设备。简而言之,在经过设备枚举后,USB 集线器使用两个接口来实现其功能:
- 用于端口状态更改事件的 IN 型中断端点
- 用于端口状态查询的 IN 型控制传输
Zircon USB 堆栈(hub 驱动程序是其中的一部分)会发出请求,等待端口状态更改中断事件。USB 集线器使用 N 位位图报告端口状态更改事件,其中位 1 对应于端口 1,位 2 对应于端口 2,依此类推。请注意,位 0 保留用于 hub 状态更改事件,目前不受支持。因此,4 端口 hub 使用 IN 型中断端点为 4 个端口中的每个端口写入 5 位值。
当 hub 设备检测到其某个端口发生更改时,它会发出对端口号进行编码的中断传输。此中断传输会取消阻止 hub 驱动程序,该驱动程序会读取端口状态更改位图并确定哪些端口具有相关活动。
给定端口状态更改事件后,USB 堆栈会使用 hub 设备的控制接口查询各个端口状态,并按照规范进行操作。例如,如果端口的状态因连接事件而发生更改,则端口将通电、重置,并且枚举将继续进行。
如需详细了解 hub 生命周期,请参阅 USB 2.0 规范的 CH11。
总线驱动程序
总线驱动程序的目的是向总线公布设备的存在(或移除),并向 USB 堆栈的其余部分注册 hub 设备的存在。在大多数情况下,总线驱动程序只是为了方便 USB 堆栈的不同部分之间进行通信。
HCI 驱动程序(仅限主机)
主机控制器接口 (HCI) 驱动程序在以主机模式运行时位于 USB 堆栈的底层。此实体负责将未完成的 FIDL 端点请求 (fuchsia.hardware.usb.request.Request) 转换为能够处理请求的必要硬件指令。
HCI 驱动程序与 DCI 驱动程序的区别在于,它包含有助于设备枚举的功能。如果一般枚举分为两个阶段:
- 总线枚举(直到
set_address命令)。 - 设备枚举(所有内容都遵循可寻址设备)。
HCI 驱动程序执行前半部分,而 USB 堆栈接管并执行设备枚举的其余部分。
DCI 驱动程序(仅限设备)
设备控制器接口(DCI) 驱动程序在以设备模式运行时位于 USB 堆栈的底层。此实体负责将未完成的 FIDL 端点请求 (fuchsia.hardware.usb.request.Request) 转换为能够处理请求的必要硬件指令。
DCI 驱动程序与 HCI 驱动程序的区别在于,它用于向设备呈现传入的 OUT 型传输请求,以及向总线设置传出的 IN 型传输请求。在这两种情况下,单个传输可能会导致多个数据包在每个方向上传输。