1. USB Gadget子系统概述
USB Gadget 子系统是 Linux 内核中用于让嵌入式设备(如开发板、手机、IoT 网关)模拟成 USB 外设(如 U 盘、串口、网卡、音频设备)的核心框架。它位于内核的 drivers/usb/gadget/ 目录下,与主机侧的 USB 驱动栈(Host Stack)对称存在,但设计目标完全不同:主机栈负责枚举和管理外设,而 Gadget 栈负责被枚举并提供功能。
1.1 在 Linux 内核中的位置
USB Gadget 子系统处于内核 USB 子系统的“设备端”分支,与主机端(Host)并列。其代码层次关系如下表所示:
| 层级 | 目录/文件 | 职责 |
|---|---|---|
| 用户空间接口 | configfs/、functionfs/ |
通过 ConfigFS 或 FunctionFS 动态配置 Gadget 功能 |
| Gadget Function 层 | functions/ |
实现具体 USB 功能(Mass Storage、Serial、ECM、RNDIS 等) |
| Gadget API 层 | udc-core.c、composite.c |
提供统一的 UDC 操作接口和复合设备管理 |
| UDC 驱动层 | udc/ |
直接操作 USB 设备控制器硬件(DWC2、DWC3、Chipidea 等) |
从内核源码树视角看,Gadget 子系统与主机栈共享 drivers/usb/ 根目录,但拥有独立的 Kconfig 和 Makefile 体系:
drivers/usb/
├── host/ # 主机侧驱动(EHCI、OHCI、xHCI)
├── gadget/ # 设备侧驱动(Gadget 子系统)
│ ├── udc/ # UDC 硬件驱动
│ ├── function/ # Gadget Function 实现
│ ├── configfs.c # ConfigFS 接口
│ ├── composite.c# 复合设备框架
│ └── u_fs.h # FunctionFS 接口
├── core/ # USB 核心(urb、hub、端点分配等)
└── common/ # 通用工具函数
1.2 核心组件详解
Gadget 子系统由三大核心组件构成:UDC(USB Device Controller)驱动、Gadget Function 和 ConfigFS。三者之间的关系可以用下面的 SVG 架构图清晰展示:
1.2.1 UDC(USB Device Controller)驱动
UDC 驱动是 Gadget 子系统的硬件抽象层,直接与 SoC 内部的 USB 设备控制器寄存器交互。它负责:
- 端点管理:分配、配置和释放 USB 端点(Endpoint 0 控制端点 + 若干数据端点)。
- DMA 传输:发起和完成 USB 数据包的 DMA 传输。
- 中断处理:处理 USB 总线事件(复位、挂起、恢复、端点中断)。
- 连接状态:通过 VBUS 检测或软件控制,管理 D+ / D- 上拉电阻的使能。
dwc2(Synopsys)、dwc3(Synopsys)、chipidea(NXP)、musb(TI)等。移植时通常需要修改设备树(Device Tree)中的 UDC 节点,并确保时钟、电源、复位信号正确配置。
1.2.2 Gadget Function
Gadget Function 是功能逻辑的实现单元,每个 Function 对应一种 USB 设备类。内核提供了丰富的内置 Function:
| Function 名称 | 内核模块 | 模拟的设备类型 | 典型应用 |
|---|---|---|---|
| Mass Storage | usb_f_mass_storage.ko |
U 盘 / 读卡器 | 文件传输、系统安装盘 |
| Serial / ACM | usb_f_acm.ko |
USB 虚拟串口 | 调试终端、AT 指令 |
| ECM / RNDIS | usb_f_ecm.ko / usb_f_rndis.ko |
USB 以太网适配器 | 网络共享、ADB |
| Audio | usb_f_uac1.ko / usb_f_uac2.ko |
USB 声卡 | 音频播放/录制 |
| HID | usb_f_hid.ko |
键盘 / 鼠标 / 游戏手柄 | 人机交互设备 |
| FunctionFS | usb_f_fs.ko |
用户自定义功能 | 私有协议、高速数据采集 |
每个 Function 都实现了 struct usb_function 接口,包含 bind()、unbind()、set_alt()、disable() 等回调。多个 Function 可以组合成一个复合设备(Composite Device),例如同时提供 Mass Storage + Serial + ECM 三个功能。
1.2.3 ConfigFS
ConfigFS(Configuration Filesystem)是 Gadget 子系统的用户空间配置接口,挂载在 /sys/kernel/config/usb_gadget/ 下。它允许用户在运行时动态创建、配置和启动 Gadget 设备,无需重新编译内核或编写内核模块。
ConfigFS 的典型配置流程如下:
- 创建 Gadget 目录:
mkdir /sys/kernel/config/usb_gadget/g1 - 设置 VID/PID:写入
idVendor和idProduct文件 - 创建配置(Configuration):
mkdir configs/c.1 - 创建功能(Function):
mkdir functions/mass_storage.usb0 - 绑定功能到配置:
ln -s functions/mass_storage.usb0 configs/c.1 - 绑定 UDC:将 UDC 名称写入
UDC文件,启动枚举
CONFIG_USB_CONFIGFS 和对应的 Function 模块。在嵌入式系统中,如果使用 Buildroot 或 Yocto,需要确保内核配置中包含 CONFIGFS_FS=y 和 CONFIG_USB_GADGET=y。另外,ConfigFS 的路径和文件权限需要正确设置,否则用户空间脚本无法正常操作。
1.3 三组件协作流程
当用户通过 ConfigFS 配置好 Gadget 并绑定 UDC 后,三个组件的协作流程如下面的 SVG 时序图所示:
1.4 小结
USB Gadget 子系统通过UDC 驱动屏蔽硬件差异,通过Gadget Function 提供标准化的 USB 功能实现,通过 ConfigFS 提供灵活的用户空间配置能力。三者的分层设计使得嵌入式 Linux 设备可以轻松模拟成多种 USB 外设,且功能组合和切换完全在运行时完成,无需重新烧录固件。