2. Linux USB驱动框架

USB驱动体系是Linux内核中最为复杂的子系统之一,其分层设计兼顾了主机侧与设备侧的双向通信需求。理解USB驱动框架的分层结构,是掌握设备树绑定与PHY配置的前提。本章将从全局视角剖析USB核心层、主机控制器驱动(HCD)、设备控制器驱动(UDC)以及Gadget框架的职责与协作关系。

2.1 USB驱动整体分层架构

Linux USB驱动体系采用树形分层设计,以USB核心层为枢纽,向上对接各类USB设备驱动(如存储、HID、网络),向下通过HCD或UDC桥接硬件控制器。Gadget框架则在内核中模拟设备侧行为,使嵌入式设备能够作为USB外设工作。

核心概念: USB驱动框架的对称性——主机侧通过HCD管理总线,设备侧通过UDC暴露功能,而Gadget框架在设备侧实现了与主机侧“类驱动”对应的功能抽象。
Linux USB驱动整体分层架构 Linux USB驱动整体分层架构 主机侧 (Host Side) 设备侧 (Device Side) USB设备驱动 (usb-storage, usbhid, cdc_ether) USB核心层 (usbcore) HCD (主机控制器驱动) USB主机控制器 (xHCI/EHCI/OHCI) Gadget功能驱动 (serial, mass_storage, ether) USB核心层 (usbcore / gadget.ko) UDC (设备控制器驱动) USB设备控制器 (DWC2/DWC3/Chipidea) USB总线抽象 说明 主机侧与设备侧通过USB电缆物理连接,核心层提供统一的设备模型和URB/请求管理

2.2 USB核心层(usbcore)

USB核心层是驱动框架的中枢神经系统,它不直接操作硬件,而是提供一套标准化的数据结构和接口,使主机侧与设备侧的驱动开发得以解耦。核心层以内核模块usbcore.ko形式存在,主要职责包括:

  • 总线管理: 注册USB总线类型,维护USB设备与接口的枚举、配置、热插拔。
  • URB(USB Request Block)管理: 提供URB分配、提交、取消、完成回调机制,是主机侧数据传输的基本单元。
  • 设备模型抽象: 定义usb_device、usb_interface、usb_driver等核心数据结构。
  • 协议处理: 实现标准设备请求(如Get Descriptor、Set Configuration)的默认处理路径。
USB核心层关键数据结构
数据结构作用域核心字段/用途
usb_device主机侧代表一个物理USB设备,包含设备描述符、配置列表、端点信息
usb_interface主机侧代表设备中的一个功能接口,是驱动绑定的基本单位
usb_driver主机侧USB设备驱动结构体,通过id_table匹配接口
urb主机侧USB请求块,包含传输类型、端点、数据缓冲区、完成函数
usb_gadget设备侧代表设备侧的USB控制器抽象,包含端点列表和操作函数
usb_request设备侧设备侧的数据传输请求,对应主机侧的URB
开发提示: 在设备树中配置USB控制器时,核心层并不直接解析设备树属性。设备树信息由HCD或UDC驱动读取,再通过核心层提供的注册接口(如usb_add_hcd())将硬件能力上报给核心层。

2.3 HCD(主机控制器驱动)

HCD是主机侧最接近硬件的软件层,直接管理USB主机控制器寄存器,负责:

  • 根Hub模拟: 实现虚拟根Hub,处理端口状态变化(连接/断开/复位)。
  • 传输管理: 将核心层下发的URB转换为控制器硬件可执行的传输描述符(如TRB、TD)。
  • 中断处理: 响应控制器中断,完成数据传输并回调URB完成函数。
  • 电源管理: 控制端口供电、挂起/唤醒、PHY时钟门控。

Linux内核支持多种主机控制器标准,其驱动实现差异显著:

主流HCD标准对比
标准速度驱动文件特点
OHCI (Open HCI)USB 1.1 (全速/低速)ohci-hcd.c寄存器接口简单,中断处理开销较大
EHCI (Enhanced HCI)USB 2.0 (高速)ehci-hcd.c支持高速传输,通常与OHCI/UHCI配合实现速率降级
xHCI (eXtensible HCI)USB 3.0/3.1/3.2xhci-hcd.c统一处理所有速度,支持Streaming、LPM,结构最复杂
设备树绑定注意: xHCI控制器在设备树中通常需要配置usb3-lpm-capable、snps,dis-u2-freeclk-exists-quirk等属性。错误的PHY引用或时钟配置会导致HCD初始化失败,表现为“xhci-hcd: probe of xhci-hcd.0 failed with error -22”。

2.4 UDC(设备控制器驱动)

UDC是设备侧的核心驱动,负责管理USB设备控制器硬件,使嵌入式设备能够作为USB外设(如虚拟串口、U盘、网卡)被主机识别。UDC的主要职责包括:

  • 端点管理: 配置和控制控制端点(Endpoint 0)及功能端点(IN/OUT)。
  • 请求处理: 接收Gadget框架下发的usb_request,将其转换为控制器DMA或FIFO操作。
  • 事件处理: 响应控制器中断(如SETUP包到达、传输完成、总线复位)。
  • 连接状态管理: 通过VBUS检测或软件控制实现连接/断开模拟。

常见的UDC驱动实现包括:

  • DWC2: 广泛用于STM32、Allwinner、Rockchip等平台,支持OTG模式,驱动文件dwc2.c。
  • DWC3: 高通、TI、Intel等高端SoC使用,支持USB 3.0/2.0,驱动文件dwc3.c。
  • Chipidea: NXP i.MX系列常用,驱动文件ci_hdrc_imx.c。
  • Fotg210: Faraday控制器,用于部分嵌入式平台。
UDC与Gadget框架交互流程 UDC与Gadget框架交互流程 Gadget功能驱动 (g_serial.ko / g_mass_storage.ko) Gadget核心层 (udc-core.ko) usb_gadget_probe_driver() UDC驱动 (dwc2/3, ci_hdrc) usb_ep_queue() / usb_ep_dequeue() USB设备控制器硬件 DMA / FIFO / 中断控制器 关键交互流程 1. 功能驱动注册到Gadget核心 2. 核心层绑定UDC实例 3. UDC分配端点资源 4. 功能驱动提交usb_request 5. UDC将请求转为硬件操作 6. 硬件完成传输触发中断 7. UDC回调请求完成函数 8. 功能驱动处理数据/状态

2.5 Gadget框架

Gadget框架是Linux设备侧USB驱动的灵魂,它允许嵌入式设备通过UDC模拟任意USB设备类型。Gadget框架分为三层:

  1. Gadget功能驱动(Function Driver): 实现具体的USB设备功能,如串口(g_serial)、大容量存储(g_mass_storage)、以太网(g_ether)、音频(g_audio)。
  2. Gadget核心层(udc-core): 管理UDC设备的注册与绑定,提供usb_gadget_probe_driver()接口,负责将功能驱动与UDC实例配对。
  3. 配置层(ConfigFS / Legacy): 提供用户空间配置接口,ConfigFS方式允许在运行时动态组合多个功能(如同时模拟串口+U盘)。
实战要点: 在嵌入式Linux中,Gadget功能驱动的选择直接影响设备树中UDC节点的配置。例如,使用g_mass_storage时,需要确保UDC支持Bulk传输且端点数量足够;使用g_ether时,需关注MAC地址的生成策略(设备树中可通过local-mac-address属性指定)。

2.6 分层协作实例:主机识别Gadget设备

以下流程展示了一个完整的USB通信链路,从主机侧应用层到设备侧硬件:

主机识别Gadget设备的分层协作流程
步骤主机侧设备侧
1主机控制器检测端口电平变化UDC使能上拉电阻,通知主机连接
2HCD复位端口,开始枚举UDC响应复位,将端点0设为控制端点
3核心层发送Get Descriptor请求Gadget功能驱动构建设备描述符,通过UDC返回
4核心层分配地址,发送Set AddressUDC接收地址,更新控制器寄存器
5核心层获取配置描述符Gadget核心层组合配置/接口/端点描述符
6核心层选择配置(Set Configuration)UDC激活非控制端点,功能驱动准备数据传输
7类驱动绑定接口,开始数据通信功能驱动通过UDC提交/接收usb_request

2.7 设备树视角的分层映射

设备树描述的是硬件拓扑,与USB驱动分层存在明确的映射关系:

  • 控制器节点: 对应HCD或UDC实例,包含compatible、reg、interrupts、phys等属性。
  • PHY节点: 对应USB PHY硬件,通过phy-handle或phys属性引用,由PHY框架管理。
  • 时钟与电源: 通过clocks、power-domains属性关联,影响HCD/UDC的初始化时序。
  • Gadget配置: 部分平台在设备树中通过dr_mode(host/peripheral/otg)指定控制器工作模式。