2. Linux USB子系统架构:USB主机侧与设备侧、USB Core、HCD、UDC、Gadget API分层
在深入UVC Gadget驱动开发之前,必须理解Linux USB子系统的整体架构。USB子系统采用分层的模块化设计,既支持传统的USB主机侧(Host Side),也支持USB设备侧(Device Side/Gadget Side)。这种对称架构使得Linux既能作为USB主机连接外设,也能作为USB设备被其他主机识别。
2.1 USB子系统全景架构
下图展示了Linux USB子系统的核心分层结构,清晰区分了主机侧与设备侧的对应关系:
2.2 USB主机侧架构详解
USB主机侧是Linux最成熟的USB子系统部分,负责管理连接到系统的所有USB外设。其分层结构自底向上包括:
2.2.1 主机控制器硬件 (Host Controller)
位于最底层的物理硬件,负责USB总线的电气信号传输。常见的主机控制器标准包括:
| 标准 | 全称 | 速度 | 典型应用 |
|---|---|---|---|
| UHCI | Universal Host Controller Interface | USB 1.1 (12 Mbps) | Intel/VIA芯片组,软件开销大 |
| OHCI | Open Host Controller Interface | USB 1.1 (12 Mbps) | 非Intel平台,硬件开销大 |
| EHCI | Enhanced Host Controller Interface | USB 2.0 (480 Mbps) | 高速USB设备 |
| xHCI | eXtensible Host Controller Interface | USB 3.x (5/10/20 Gbps) | 现代平台,兼容所有速度 |
2.2.2 HCD (Host Controller Driver)
HCD是主机控制器驱动的内核模块,直接操作硬件寄存器,向上层提供统一的接口。Linux内核中对应的驱动文件位于 drivers/usb/host/ 目录下:
drivers/usb/host/
├── ehci-hcd.c # EHCI主机控制器驱动
├── ohci-hcd.c # OHCI主机控制器驱动
├── uhci-hcd.c # UHCI主机控制器驱动
├── xhci-hcd.c # xHCI主机控制器驱动
└── ...
2.2.3 USB Core (usbcore.ko)
USB Core是主机侧的核心层,实现了USB协议栈的通用逻辑:
- 总线管理:维护USB总线拓扑结构,处理设备热插拔
- 设备枚举:分配地址、读取描述符、配置设备
- 数据传输:管理URB(USB Request Block)的提交与完成
- 驱动匹配:根据设备描述符匹配对应的USB设备驱动
关键概念:URB — USB Request Block是USB主机侧数据传输的核心数据结构。所有与USB设备的数据交换都通过URB进行,URB包含传输类型(控制/批量/中断/等时)、目标端点、数据缓冲区、回调函数等信息。
2.2.4 USB设备驱动层
最上层的设备驱动实现具体的USB设备功能,例如UVC摄像头驱动、USB存储驱动、HID驱动等。这些驱动通过USB Core提供的API与硬件交互。
2.3 USB设备侧架构详解
设备侧(Gadget侧)是Linux USB子系统的另一面,使嵌入式设备能够模拟USB外设。其分层结构与主机侧对称但方向相反:
2.3.1 UDC硬件 (USB Device Controller)
UDC是嵌入式SoC内部集成的USB设备控制器硬件,负责处理USB协议的数据包收发。常见的UDC硬件包括:
- DWC2 (DesignWare USB 2.0 OTG) — 广泛用于STM32、Allwinner等平台
- DWC3 (DesignWare USB 3.0) — 用于高通、瑞芯微等高端平台
- ChipIdea — NXP i.MX系列常用
- FUSB — 某些FPGA或ASIC实现
2.3.2 UDC驱动层
UDC驱动直接操作UDC硬件寄存器,实现端点管理、DMA传输、中断处理等底层功能。Linux内核中对应的驱动位于 drivers/usb/gadget/udc/:
drivers/usb/gadget/udc/
├── dwc2.c # DWC2 UDC驱动
├── dwc3.c # DWC3 UDC驱动
├── chipidea/ # ChipIdea UDC驱动
├── fsl_qe_udc.c # Freescale QE UDC
└── ...
2.3.3 Gadget API层 (Gadget Core)
Gadget API是设备侧的核心抽象层,相当于主机侧的USB Core。它提供了:
- UDC抽象:统一不同UDC硬件的操作接口
- 端点管理:分配、配置、释放USB端点
- 请求管理:管理USB Request(类似主机侧的URB)
- 配置管理:处理USB配置、接口、备用设置
开发提示:Gadget API的核心数据结构是 struct usb_gadget 和 struct usb_ep。UVC Gadget驱动通过这两个结构体与底层UDC交互,无需关心具体硬件细节。
2.3.4 Gadget Function驱动层
最上层是Gadget功能驱动,实现具体的USB设备功能。常见的Gadget功能驱动包括:
| 功能驱动 | 模拟设备 | 内核模块 |
|---|---|---|
| g_ether.ko | USB网卡 (RNDIS/ECM) | drivers/usb/gadget/function/f_ecm.c |
| g_mass_storage.ko | USB存储设备 | drivers/usb/gadget/function/f_mass_storage.c |
| g_serial.ko | USB串口 | drivers/usb/gadget/function/f_serial.c |
| g_uvc.ko | USB摄像头 (UVC) | drivers/usb/gadget/function/f_uvc.c |
| g_hid.ko | USB HID设备 | drivers/usb/gadget/function/f_hid.c |
2.4 主机侧与设备侧的关键差异
理解两侧的差异对于UVC Gadget开发至关重要:
| 对比维度 | 主机侧 (Host) | 设备侧 (Gadget) |
|---|---|---|
| 角色 | 总线主控,发起所有传输 | 从设备,响应主机请求 |
| 数据传输 | 通过URB提交请求 | 通过usb_request提交数据 |
| 枚举过程 | 主动分配地址、读取描述符 | 被动响应主机的枚举请求 |
| 核心层 | USB Core (usbcore.ko) | Gadget API (udc-core.ko) |
| 驱动目录 | drivers/usb/host/ | drivers/usb/gadget/ |
| 电源管理 | 管理下游设备挂起/唤醒 | 响应主机的挂起/唤醒信号 |
2.5 UVC Gadget在架构中的位置
UVC Gadget驱动位于设备侧的最上层,其调用关系如下:
重要提醒:UVC Gadget驱动开发的核心工作集中在最上层(f_uvc.c),但必须理解下层Gadget API和UDC驱动的接口约定。常见的开发陷阱包括:端点类型选择错误(UVC需要等时端点)、数据传输大小未对齐、描述符配置与硬件能力不匹配等。
2.6 关键数据结构关系
在设备侧,核心数据结构之间的关联关系如下:
struct usb_gadget // 代表一个UDC设备
├── struct usb_ep *ep0 // 控制端点0
├── struct usb_ep *in_ep // IN端点(主机到设备方向)
├── struct usb_ep *out_ep // OUT端点(设备到主机方向)
└── struct usb_gadget_driver *driver // 当前绑定的Gadget驱动
struct usb_gadget_driver // Gadget功能驱动
├── char *function_name // 功能名称,如 "uvc"
├── int (*bind)(...) // 绑定回调:配置端点、分配资源
├── int (*unbind)(...) // 解绑回调
├── int (*setup)(...) // 处理标准请求(如SET_CONFIGURATION)
└── void (*disconnect)(...) // 断开连接回调
struct usb_request // USB请求(类似主机侧URB)
├── struct usb_ep *ep // 所属端点
├── void *buf // 数据缓冲区
├── unsigned int length // 数据长度
├── void (*complete)(...) // 完成回调函数
└── int status // 传输状态
2.7 本章小结
Linux USB子系统的分层架构为UVC Gadget驱动开发提供了清晰的抽象边界:
- 主机侧:USB Core + HCD + 设备驱动,适用于开发USB主机功能
- 设备侧:Gadget API + UDC驱动 + 功能驱动,适用于开发USB设备功能
- UVC Gadget:位于设备侧最上层,通过Gadget API与UDC交互,模拟USB摄像头
- 核心接口:
usb_gadget、usb_ep、usb_request是设备侧编程的三个核心数据结构