USB系统概述
Zircon提供了一个功能完备的USB子系统,它能够使您开发USB主设备(USB host) 和外围设备。它支持低速、全速、高速和超高速传输USB设备,以及各种标准的 自动协商(auto-negotiation)机制。
在Zircon的USB子系统作为主设备(host)时,随着USB设备连接到总线(bus)或者从 总线中移除,Zircon的USB子系统会使用一种层级式的方式,以便于USB设备的生命周期 管理。在Zircon的USB子系统作为从属设备时,子系统借助特定种类的驱动(或者多重等级 的USB驱动)发送或者接收USB数据包。
目标硬件平台可能会包含许多个USB控制器。因此,Zircon在各个物理总线上的工作模式 既有可能是主设备(host)模式,也有可能是从属设备模式。但是,对于一个特定的 总线拓扑,每个工作模式是唯一的。除非另外提及,这篇文档一般考虑的是只有一个总线 的情况。
USB子系统的组件概括如下:
- 特定种类的硬件驱动
- USB集线器驱动(特定种类的硬件驱动的一种特殊情形)
- 总线驱动
- 主设备或从属设备控制器的接口驱动
Zircon的USB主设备模式
当作为一个USB主设备时,Zircon是一个权威的仲裁者。所连接的USB设备形成的 树状拓扑的根部(root)是一个USB根集线器(USB root hub)。无论总线设备 是否实际存在,这个USB根集线器都是必须要有的。对于包含具有主设备功能的 控制器,但是没有实际的总线设备的系统,必须使用软件来模拟一个这样的USB 根集线器。
为了便于总线仲裁(bus arbitration),Zircon会使用下面的驱动进行操作:
- USB根集线器驱动
- 总线驱动
- 主机控制器接口(Host controller interface,HCI)驱动
这些驱动协同工作,来对接入总线的设备作出反应,以及管理接入的设备的生命周期。
Zircon的USB从属设备模式
当作为一个USB从属设备时,Zircon在总线和特定种类的驱动(或者多重等级的驱动) 传输USB数据包。在这个模式下,总线驱动使得DCI驱动和特定种类的驱动的顶部 抽象层之间能够进行通信。
特定种类的驱动
为了实现特定的USB功能(例如,HID种类的设备),特定种类的驱动里面会相应地 实现必要的逻辑。与此同时,它不会关心向实际的总线读取或写入物理数据包所需要的 硬件信息。
注意:集线器驱动是特定种类的驱动的一个例子。
一般而言,USB设备的驱动将数据传输请求编码成一个“usb_request_t”结构体。这些 请求结构体一般具有相应的一个异步的回调(callback)函数,在数据传输完成时,这个 回调函数会被执行。通常而言,USB协议栈的运作是通过高阶(higher order)设备驱动 向尚未处理的请求队列发送请求来实现的。当这些请求被处理,与它们对应的回调函数会 被调用,以通知顶部抽象层:该请求已经处理完成。
集线器驱动
集线器驱动的目的是根据USB 2.0 规格中的第11章来 管理集线器设备。简单而言,在进行设备枚举之后,USB集线器使用两种接口来实现 它们的功能:
- 对于端口状态改变的事件,使用IN类型中断端点(interrupt endpoint)
- 对于端口状态查询,使用IN类型控制传输
Zircon的USB协议栈(集线器驱动是其中的一个部分)发出一个请求,等待端口状态 改变的中断事件。USB集线器使用一个包含N个比特的位图(bitmap)来报告端口状态 改变的中断事件,这个位图中,第1个比特对应端口#1,第二个比特对应端口#2,等等。 请注意,第0个比特是为集线器状态改变的事件而保留的,此功能目前还不支持。因此, 一个包含4个端口的集线器会使用IN类型中断端点向每一个端口写入一个包含5个比特的值。
请注意:虽然没有做出要求,但是大多数集线器只在有端口状态改变事件实际发生的时候 产生一个中断传输(interrupt transfer)。
当集线器设备侦测到它的一个端口的状态发生了改变,它对端口号进行编码并产生 一个中断传输。这个中断传输使集线器驱动进行下面的工作:读取端口状态改变位图, 并且判断决定哪个端口有相关的活动。
在一个端口状态改变事件发生的情况下,USB协议栈使用集线器设备的控制接口 (control interface)来查询各个端口的状态,并且按照USB规格说明进行工作。 例如,如果一个端口的状态因为有了连接事件(connection event)而发生了改变, 这个端口将会通电,重置,并且继续进行这种枚举查询工作。
要获取关于集线器生命周期的细节的信息,参考USB 2.0 规格的第11章。
总线驱动
总线驱动的目的是向总线通知设备的接入(或移除),并且向USB协议栈的其他 部分登记集线器设备的接入。通常来说,总线驱动只是方便USB协议栈的不同部分 之间的通信。
主机控制器接口(Host controller interface,HCI)驱动(只有USB主设备模式)
当运行在USB主设备模式时,主机控制器接口(Host controller interface,HCI)驱动
存在于USB协议栈的底层。它负责将尚未处理的usb_request_t
翻译成必要的、能够
为请求提供服务的硬件指令。
HCI驱动与DCI驱动的区别在于它包含了便于设备枚举的功能。如果将一般的枚举 划分成两个阶段:
- 总线枚举(通过
set_address
命令来做到)。 - 设备枚举(所有设备都跟随一个能够寻址的设备)。
HCI驱动执行前半部分,然后USB协议栈对该枚举任务进行接管,并执行设备 枚举任务的其余部分。
DCI驱动(只有USB从属设备模式)
当运行在USB从属设备模式时,设备控制器接口(Device controller interface,DCI) 驱动存在于USB协议栈的底层。它负责将尚未处理的“usb_request_t”转变成必要的、能够 为请求提供服务的硬件指令。
DCI驱动与HCI驱动的区别在于它用于向设备提供传入的OUT类型传输请求, 并且向总线设置传出的IN类型的传输请求。在这两种情况下,一个独立的传输可能都会 造成多个数据包在传入和传出方向上同时进行传输。