1. USB Gadget 框架概述
USB Gadget 子系统是 Linux 内核中用于让嵌入式设备模拟 USB 外设(如键盘、鼠标、U盘、网卡)的核心框架。与 USB Host 侧不同,Gadget 侧负责实现设备端(Device/Peripheral)的功能。理解其分层架构是进行驱动调试与中断端点通信的基础。
核心概念: Linux USB Gadget 子系统将硬件控制、协议处理与功能实现解耦为三层:UDC 驱动层、Gadget 功能驱动层、以及上层的配置接口(Legacy 或 ConfigFS)。
1.1 三层架构总览
整个子系统从上到下分为三个层次,每一层职责明确,通过标准 API 进行交互。下图展示了这三层之间的调用关系与数据流。
1.2 UDC 驱动层(底层)
UDC(USB Device Controller)驱动是直接与硬件 USB 控制器交互的软件模块。它负责管理 USB 控制器的寄存器、端点(Endpoint)资源、以及处理 USB 总线上的标准事件(如复位、挂起、SETUP 包)。
- 职责: 初始化硬件、分配端点、处理中断、收发数据包。
- 关键结构体:
struct usb_gadget代表一个 USB 设备控制器;struct usb_ep代表一个端点。 - 常见驱动: dwc2(常用于树莓派、Allwinner)、dwc3(高通、TI)、chipidea(NXP i.MX)、musb(TI OMAP)。
- 调试入口: 通过
/sys/kernel/debug/usb/<udc-name>/查看端点状态和请求队列。
调试提示: 当遇到端点通信无响应时,首先检查 UDC 驱动是否成功绑定。执行
cat /sys/kernel/debug/usb/devices 查看 UDC 状态,确认控制器是否进入配置状态。
1.3 Gadget 功能驱动层(中间层)
功能驱动实现了具体的 USB 设备功能。例如,g_serial 实现串口功能,g_ether 实现以太网功能,g_mass_storage 实现 U 盘功能。这些驱动通过调用 UDC 层提供的 API 来操作端点。
| 功能驱动模块 | 模拟设备类型 | 使用的端点类型 | 典型应用场景 |
|---|---|---|---|
g_serial.ko |
CDC ACM 串口 | Bulk IN / Bulk OUT | 嵌入式设备调试、AT 命令 |
g_ether.ko |
CDC ECM / RNDIS 网卡 | Bulk IN / Bulk OUT | 设备网络共享、IoT 网关 |
g_mass_storage.ko |
USB 大容量存储设备 | Bulk IN / Bulk OUT | U 盘、读卡器 |
f_hid.ko |
HID 设备(键盘/鼠标) | Interrupt IN | 人机交互设备、自定义按键 |
f_uac1/2.ko |
USB 音频设备 | Isochronous | USB 麦克风、扬声器 |
注意: 中断端点(Interrupt Endpoint)主要用于 HID 类设备或需要低延迟通知的场景。在调试中断端点通信时,务必确认功能驱动正确配置了端点描述符中的
bInterval 字段,该字段决定了主机轮询间隔。
1.4 ConfigFS 与 Legacy 模式对比
上层配置接口决定了如何将功能驱动绑定到 UDC 控制器上。Legacy 模式是旧有的内核模块绑定方式,而 ConfigFS 是当前推荐的用户空间配置方式。
1.5 如何选择配置方式
下表从开发调试和生产部署两个维度,给出了选择建议。
| 场景 | 推荐模式 | 理由 |
|---|---|---|
| 快速原型验证 | Legacy(g_xxx 模块) | 加载模块即用,无需编写配置脚本 |
| 多功能复合设备 | ConfigFS | 支持多配置、多接口组合,灵活性强 |
| 中断端点调试 | ConfigFS | 可单独加载 f_hid 功能,配合 usbmon 抓包分析 |
| 产品量产固件 | ConfigFS 或 定制 Legacy | ConfigFS 更通用;Legacy 可减少用户空间依赖 |