1. USB Gadget框架概述

1.1 Linux USB Gadget子系统架构

USB Gadget子系统是Linux内核中用于让嵌入式设备模拟USB外设(如U盘、串口、网卡、音频设备等)的核心框架。与USB Host驱动不同,Gadget驱动运行在Device端,通过UDC(USB Device Controller)硬件与Host通信。

核心概念: USB Gadget子系统将复杂的USB协议栈抽象为三层结构,使开发者能够以模块化方式组合不同的USB功能。
USB Gadget子系统三层架构 用户空间 (User Space) ConfigFS配置接口 / Legacy Gadget驱动 / 应用程序 Gadget Function层 Function 驱动:Mass Storage / Serial / ECM / RNDIS / Audio / HID FunctionFS / u_serial / f_mass_storage / f_ecm / f_rndis UDC Core层 (Gadget API) usb_gadget_probe_driver / usb_ep_enable / usb_ep_queue Composite Framework / Config / String 管理 UDC硬件驱动层 (Device Controller) DWC2 / DWC3 / Chipidea / Renesas / 各SoC厂商UDC驱动 数据流向 Host ←→ Device

1.2 UDC / UDC Core / Gadget Function层关系

三层之间通过标准API进行交互,每一层职责清晰、接口明确:

层次 职责 关键数据结构 典型文件路径
UDC层 直接操作USB Device Controller硬件寄存器,处理中断、端点传输 struct usb_gadget
struct usb_ep
struct usb_request
drivers/usb/gadget/udc/
UDC Core层 提供Gadget API抽象,管理Composite设备、配置、字符串描述符 struct usb_gadget_driver
struct usb_composite_dev
drivers/usb/gadget/
composite.c / configfs.c
Gadget Function层 实现具体USB功能协议,如Mass Storage、Serial、ECM等 struct usb_function
struct f_xxx_opts
drivers/usb/gadget/function/
开发要点: 大多数工程问题出现在Function层与UDC Core层的接口对接处,尤其是端点分配、描述符长度对齐、以及DMA缓冲区管理方面。

1.3 核心数据结构关系

理解以下关键数据结构之间的关联,是掌握Gadget驱动开发的基础:

Gadget核心数据结构关系图 struct usb_gadget ops / ep0 / speed / is_otg struct usb_gadget_driver bind / unbind / setup / suspend struct usb_ composite_dev config / gadget / req struct usb_ep ops / maxpacket / address struct usb_request buf / length / dma / complete struct usb_function bind / unbind / set_alt / disable struct usb_configuration label / bmAttributes / MaxPower 关系说明 gadget 包含多个 ep driver 绑定到 gadget

1.4 ConfigFS与Legacy模式对比

Linux内核提供了两种Gadget配置模式:传统的Legacy模式和现代的ConfigFS模式。理解两者的差异对于选择合适的开发路径至关重要。

对比维度 Legacy模式 ConfigFS模式
配置方式 内核编译时静态配置,或通过模块参数 运行时通过sysfs/configfs动态配置
灵活性 低,修改配置需重新编译内核或加载模块 高,用户空间可动态绑定/解绑Function
适用场景 产品功能固定、不需要运行时切换 原型开发、多配置切换、用户定制
代码路径 drivers/usb/gadget/legacy/ drivers/usb/gadget/configfs.c
调试难度 较低,逻辑集中 较高,涉及用户空间与内核空间交互
内核配置 CONFIG_USB_GADGET + 具体Function CONFIG_USB_CONFIGFS + 各Function
工程建议: 新项目推荐使用ConfigFS模式,它提供了更好的灵活性和可维护性。Legacy模式适合对启动时间有严格要求的嵌入式产品,因为其初始化路径更短、依赖更少。

1.5 ConfigFS配置流程示例

以下是一个典型的ConfigFS配置流程,用于创建一个同时包含Mass Storage和Serial功能的复合Gadget设备:

# 1. 挂载configfs
mount -t configfs none /sys/kernel/config

# 2. 创建Gadget实例
mkdir /sys/kernel/config/usb_gadget/g1
cd /sys/kernel/config/usb_gadget/g1

# 3. 设置VID/PID
echo 0x1d6b > idVendor   # Linux Foundation
echo 0x0104 > idProduct  # Multifunction Composite Gadget

# 4. 创建配置(英文)
mkdir configs/c.1
echo "MultiFunction" > configs/c.1/strings/0x409/configuration

# 5. 创建Mass Storage Function
mkdir functions/mass_storage.usb0
echo /dev/mmcblk0p1 > functions/mass_storage.usb0/lun.0/file

# 6. 创建Serial Function
mkdir functions/serial.usb0
echo 0x1234 > functions/serial.usb0/idProduct

# 7. 绑定Function到配置
ln -s functions/mass_storage.usb0 configs/c.1
ln -s functions/serial.usb0 configs/c.1

# 8. 绑定到UDC(启用设备)
echo musb-hdrc.0 > UDC
关键点: 第8步将Gadget绑定到UDC后,USB设备立即生效。如果UDC文件写入失败,常见原因包括:UDC驱动未加载、端点资源不足、或描述符配置错误。

1.6 Legacy模式代码结构示例

Legacy模式下,Gadget驱动通常以内核模块形式编写,直接在bind回调中完成所有配置:

#include <linux/usb/composite.h>

static struct usb_composite_driver my_gadget_driver = {
    .name       = "my_gadget",
    .dev        = &my_device_desc,
    .strings    = my_strings,
    .max_speed  = USB_SPEED_HIGH,
    .bind       = my_bind,
};

static int __init my_bind(struct usb_composite_dev *cdev)
{
    struct usb_configuration *config;
    struct usb_function *f_mass, *f_serial;

    // 创建配置
    config = usb_get_configuration(cdev, 1);
    config->label = "My Config";
    config->bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER;
    config->MaxPower = 100;

    // 创建并绑定Mass Storage Function
    f_mass = usb_get_function_instance("mass_storage");
    usb_add_function(config, f_mass);

    // 创建并绑定Serial Function
    f_serial = usb_get_function_instance("serial");
    usb_add_function(config, f_serial);

    return 0;
}

module_init(my_bind);
对比总结: Legacy模式代码更紧凑,但每次修改Function组合都需要重新编译模块;ConfigFS模式将配置逻辑移到用户空间,更适合快速迭代和产品定制。

1.7 本章小结

USB Gadget子系统的三层架构(UDC → UDC Core → Gadget Function)为嵌入式设备提供了灵活的外设模拟能力。理解各层职责、核心数据结构关系以及ConfigFS与Legacy两种配置模式的差异,是后续章节解决具体工程问题的基础。

  • UDC层:硬件相关,处理端点传输和中断
  • UDC Core层:提供通用API,管理Composite设备和描述符
  • Gadget Function层:实现具体USB协议功能
  • ConfigFS模式:动态配置,适合开发和定制
  • Legacy模式:静态配置,适合固定功能产品