2. USB协议栈分层:Host层、Device层、Hub层、功能层,以及各层在枚举中的职责
USB枚举过程并非由单一模块独立完成,而是由USB协议栈中多个层次协同配合的结果。理解各层的职责边界与交互关系,是移植适配不同Host驱动枚举行为的基础。USB协议栈从拓扑结构上可划分为四个核心层次:Host层、Hub层、Device层与功能层。
核心观点:枚举的本质是Host层通过Hub层发现并配置Device层,最终使功能层(Function)可用的过程。每一层在枚举中承担不同的状态机与数据交互职责。
2.1 协议栈四层架构总览
下图展示了USB协议栈的层次化结构,以及各层在枚举过程中的主要交互关系:
2.2 各层在枚举中的详细职责
2.2.1 Host层(主机层)
Host层是枚举过程的总控者,运行在主机端(如PC、嵌入式Host控制器)。它负责发起所有枚举相关的控制传输,并维护枚举状态机。
- 检测设备连接:通过Hub层上报的端口状态变化(Port Status Change)感知设备插入。
- 复位设备:向Hub层发送端口复位请求,使设备进入默认状态(地址0,端点0可用)。
- 地址分配:发送Set Address请求,为设备分配唯一地址。
- 描述符获取:依次请求设备描述符、配置描述符、接口描述符、端点描述符及字符串描述符。
- 驱动匹配与加载:根据解析后的描述符信息(VID/PID、类代码等)选择并加载对应的设备驱动。
- 配置选择:发送Set Configuration请求,激活设备的工作配置。
移植关注点:不同Host驱动在枚举状态机的实现细节上存在差异,例如复位时序、描述符请求顺序、对错误描述符的容错策略等。这些差异是移植适配的核心挑战。
2.2.2 Hub层(集线器层)
Hub层是Host与Device之间的桥梁,负责物理层信号的中继与端口管理。在枚举过程中,Hub层承担以下关键职责:
| 职责 | 说明 | 枚举阶段 |
|---|---|---|
| 连接检测 | 监测下行端口D+/D-线路状态,检测设备插入/拔出 | 初始阶段 |
| 事件上报 | 通过中断传输向Host上报端口状态变化 | 初始阶段 |
| 端口复位 | 执行Host发起的端口复位信号(SE0状态持续至少10ms) | 复位阶段 |
| 速度协商 | 通过D+/D-下拉电阻检测设备速度(LS/FS/HS) | 复位阶段 |
| 电源管理 | 控制端口电源开关,检测过流情况 | 全阶段 |
2.2.3 Device层(设备层)
Device层是枚举过程中的响应者,运行在USB设备端。它负责处理Host通过端点0发送的所有标准请求,并返回符合USB规范的数据。
- 默认地址响应:在复位后,设备以地址0响应Host的控制传输。
- 描述符提供:设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符等。
- 地址分配确认:接收Set Address请求,更新设备地址,并返回0长度状态包。
- 配置选择:接收Set Configuration请求,激活指定的配置。
- 端点0管理:控制传输的Setup、Data、Status三个阶段的状态机处理。
常见移植陷阱:某些设备在枚举过程中对控制传输的Data阶段长度有严格限制,或对标准请求的响应时序有特殊要求。不同Host驱动对这些“非标准”行为的容忍度不同,可能导致枚举失败。
2.2.4 功能层(Function层)
功能层代表USB设备实现的具体功能,如HID键盘、大容量存储、UVC摄像头等。在枚举阶段,功能层的职责相对被动,但至关重要:
| 职责 | 说明 | 与枚举的关系 |
|---|---|---|
| 接口描述 | 通过接口描述符和类特定描述符声明功能类型 | Host据此匹配类驱动 |
| 端点声明 | 在端点描述符中定义传输类型、方向、最大包大小 | Host据此配置通信管道 |
| 类特定请求 | 某些功能需要在枚举阶段响应类特定请求(如HID Report Descriptor) | 扩展枚举流程 |
| 配置激活 | 接收Set Configuration后,功能层开始正常工作 | 枚举完成的标志 |
2.3 各层在枚举阶段的交互时序
下表总结了枚举过程中各层的主要交互动作与数据流向:
| 枚举阶段 | Host层动作 | Hub层动作 | Device层动作 | 功能层动作 |
|---|---|---|---|---|
| 连接检测 | 轮询Hub中断端点 | 检测端口状态变化,上报 | 上拉电阻激活,指示速度 | — |
| 端口复位 | 发送SetPortFeature(PORT_RESET) | 驱动D+/-为SE0 ≥ 10ms | 检测复位,进入默认状态 | — |
| 速度检测 | 读取端口状态寄存器 | 检测D+/D-电平,确定速度 | 复位后释放上拉电阻 | — |
| 获取设备描述符 | 发送GetDescriptor(DEVICE) | 转发控制传输 | 返回18字节设备描述符 | — |
| 地址分配 | 发送Set Address | 转发控制传输 | 存储新地址,返回状态 | — |
| 获取配置描述符 | 发送GetDescriptor(CONFIG) | 转发控制传输 | 返回配置+接口+端点描述符 | 提供接口/端点信息 |
| 加载驱动 | 匹配VID/PID/类代码 | — | — | 声明功能类 |
| 设置配置 | 发送Set Configuration | 转发控制传输 | 激活配置,使能端点 | 开始功能操作 |
移植适配要点:在移植USB Host驱动时,需要确保上述各层之间的接口(如Hub事件上报机制、控制传输管道、描述符解析逻辑)与目标硬件平台和操作系统完全对齐。任何一层的实现偏差都可能导致枚举失败或设备兼容性问题。