Zircon 提供了功能完善的 USB 子系统,可帮助开发 USB 主机和外围设备。它支持低速度、全速、高速和超速设备,以及各种标准自动协商机制。
在主机角色中,Zircon 的 USB 子系统假定采用分层方法,以便在总线连接或移除设备时方便对设备进行生命周期管理。在设备角色中,子系统将 USB 数据包编组到类专用驱动程序(或驱动程序层次结构)。
目标硬件平台可能包含多个 USB 控制器。因此,Zircon 可能在每个物理总线上充当主机或设备。但是,每个角色对于特定总线拓扑都是唯一的。除非另有说明,否则本文档将假定只有一个总线。
可将 USB 子系统组件总结为:
- 类专用硬件驱动程序
- USB 集线器驱动程序(类专用驱动程序的特殊情况)
- 公交车司机
- 主机或设备控制器接口驱动程序
Host 角色
作为 USB 主机运行时,Zircon 可充当权威总线仲裁器。连接的 USB 设备树位于根 USB 集线器的 root 权限。无论是否存在任何实际的 hub 硬件,都必须存在此根 hub。如果系统包含支持主机的控制器,但不包含实际的 hub 硬件,则必须在软件中模拟此根 hub。
为方便总线仲裁,Zircon 提供以下驱动程序:
- USB 根集线器驱动程序
- 公交车司机
- 主机控制器接口 (HCI) 驱动程序
这些驱动程序协同工作,以响应总线连接并管理已连接设备的生命周期。
设备角色
作为 USB 设备操作时,Zircon 会在总线和类专用驱动程序(或驱动程序层次结构)之间传输 USB 数据包数据。担任此角色时,总线驱动程序可促进 DCI 驱动程序与类专用驱动程序的上层之间的通信。
特定于类的驱动程序
类专用驱动程序可实现实现特定 USB 功能(例如 HID 类设备)所需的逻辑,同时与从实际总线读写物理数据包所需的硬件详细信息无关。
一般情况下,USB 设备驱动程序会将传输请求编码为 usb_request_t
结构。这些请求结构体通常具有与其关联的异步回调,该回调将在传输完成时执行。在大多数情况下,USB 堆栈的运行方式是采用较高顺序的设备驱动程序将请求发布到未完成的请求队列。在处理这些请求时,系统会调用其各自的回调,以通知上层请求已完成。
Hub 驱动程序
集线器驱动程序的用途是按照 USB 2.0 规范的 CH11 管理集线器设备。简而言之,在经历了设备枚举之后,USB 集线器会使用两个接口来实现其功能:
- 端口状态更改事件的 IN 类型中断端点
- 用于端口状态查询的 IN 类型控制传输
Zircon USB 堆栈(集线器驱动程序所属的)请求等待端口状态更改中断事件。USB 集线器使用 N 位位图报告端口状态更改事件,其中位 1 对应于端口 1、位 2 的端口 2 等... 请注意,bit-0 专用于 hub 状态更改事件,目前不支持。因此,4 端口集线器会使用 IN 类型的中断端点为 4 个端口中的每个端口写入一个 5 位值。
当 hub 设备检测到某个端口发生更改时,会发出对端口号的中断传输编码。此中断传输会取消屏蔽 hub 驱动程序,该驱动程序会读取端口状态更改位图并确定哪些端口具有相关 activity。
给定一个端口状态更改事件,USB 堆栈会使用集线器设备的控制接口查询各个端口状态,并按照规范继续操作。例如,如果端口的状态因连接事件而发生变化,则该端口会接通电源并重置,然后系统会继续进行枚举操作。
如需详细了解集线器生命周期的详细信息,请参阅 USB 2.0 规范的 CH11。
公交车司机
总线驱动程序的用途是向总线宣布设备存在(或移除),并向 USB 堆栈的其余部分注册集线器设备存在。在大多数情况下,总线驱动程序仅用于简化 USB 堆栈的不同部分之间的通信。
HCI 驱动程序(仅限主机)
在主机模式下操作时,主机控制器接口 (HCI) 驱动程序位于 USB 堆栈的底部。该实体负责将未完成的 usb_request_t
转换为能够处理请求的必要硬件指令。
HCI 驱动程序与 DCI 驱动程序的不同之处在于,它包含有助于进行设备枚举的功能。如果常规枚举分为两个阶段:
- 总线枚举(通过
set_address
命令向上)。 - 设备枚举(可寻址设备之后的所有内容)。
HCI 驱动程序会执行前半部分,而 USB 堆栈会接管并执行设备枚举的其余部分。
DCI 驱动程序(仅限设备)
在设备模式下运行时,设备控制器接口(DCI) 驱动程序位于 USB 堆栈的底部。该实体负责将未完成的 usb_request_t
转换为能够处理请求的必要硬件指令。
DCI 驱动程序与 HCI 驱动程序的不同之处在于,它向设备提供传入的 OUT 类型传输请求,以及设置向总线发出的传出 IN 类型传输请求。在这两种情况下,单次传输都可能导致每个方向有多个数据包。