1. USB Gadget 概述:概念、应用场景与传统 Host 的区别

USB Gadget 是嵌入式 Linux 系统中一种特殊的 USB 设备模式。它允许一个嵌入式设备(如开发板、手机、路由器)作为 USB 外设(Peripheral)连接到另一台 USB Host(如 PC、笔记本电脑),并模拟出多种标准 USB 设备功能,例如虚拟网卡、U 盘、摄像头或串口。

理解 USB Gadget 的核心在于区分 USB 系统中的两种角色:Host(主机) 和 Peripheral(外设/Gadget)。传统 PC 通常作为 Host,而 Gadget 则让嵌入式设备能够“扮演”外设。

1.1 USB Gadget 与传统 USB Host 的核心区别

下表从硬件控制器、角色定位、供电关系、通信发起方和典型应用五个维度,对比了 USB Host 与 USB Gadget 的差异:

对比维度 USB Host(主机) USB Gadget(外设/设备)
硬件控制器 EHCI / XHCI / OHCI / UHCI UDC(USB Device Controller)
角色定位 总线主控,管理总线枚举与调度 总线从设备,响应 Host 请求
供电关系 向下游外设提供 5V 电源(VBUS) 通常由 Host 供电(VBUS 输入)
通信发起方 主动发起所有传输(IN/OUT Token) 被动响应,不能主动发起事务
典型应用 PC、笔记本、树莓派(标准 A 口) 手机(MTP)、开发板(RNDIS)、嵌入式摄像头(UVC)
关键理解: 在硬件层面,Host 控制器(如 EHCI)与 Gadget 控制器(UDC)的寄存器接口、DMA 方式和中断逻辑完全不同。移植 USB Gadget 时,核心工作之一就是正确初始化并驱动 SoC 内部的 UDC 模块。

1.2 USB Gadget 的典型应用场景

USB Gadget 通过软件配置,可以将一个物理 UDC 硬件模拟成多种标准 USB 设备类。以下是嵌入式开发中最常见的三种应用场景:

  • RNDIS(Remote Network Driver Interface Specification):将嵌入式设备模拟为虚拟以太网卡。Host 端无需额外驱动即可通过 TCP/IP 访问设备,常用于开发板调试、网络共享。
  • MTP(Media Transfer Protocol):将设备模拟为媒体传输设备。广泛用于智能手机与 PC 之间的文件传输,支持双向操作且无需卸载存储介质。
  • UVC(USB Video Class):将设备模拟为标准的 USB 摄像头。嵌入式摄像头模组通过 UVC Gadget 可直接被 PC 的相机应用识别,无需私有驱动。

下图展示了这三种 Gadget 功能在同一个嵌入式设备上的软件架构层次:

USB Gadget 软件架构与典型应用场景 USB Gadget 软件架构与典型应用场景 硬件层:SoC UDC 控制器(如 DWC2、ChipIdea、Fotg210) 内核驱动层:UDC 驱动 + Gadget API(usb_gadget_probe_driver) RNDIS 功能 g_ether.ko MTP 功能 g_mtp.ko UVC 功能 g_uvc.ko 配置层:ConfigFS / Gadget 复合设备(多功能组合) USB 物理连接(VBUS + D+ / D-)
实践提示: 在设备树中,你需要为 UDC 节点正确配置 dr_mode = "peripheral" 或 "otg",并确保 usb_phy 或 usb2-phy 节点状态为 okay。这是 Gadget 功能正常工作的硬件前提。

1.3 Gadget 复合设备与 ConfigFS

现代 Linux 内核通过 ConfigFS(Config File System)提供了一种用户空间配置 Gadget 功能的灵活方式。开发者可以在运行时动态创建、组合和启用多个 USB 功能,而无需重新编译内核模块。

一个典型的 ConfigFS 配置流程包含以下步骤:

  1. 挂载 ConfigFS 文件系统:mount -t configfs none /sys/kernel/config
  2. 创建 Gadget 目录:mkdir /sys/kernel/config/usb_gadget/g1
  3. 设置 VID/PID 和产品信息:echo 0x1d6b > idVendor、echo 0x0104 > idProduct
  4. 创建配置(Configuration)并绑定功能(Function):mkdir configs/c.1、ln -s functions/ecm.usb0 configs/c.1
  5. 绑定 UDC 设备:echo musb-hdrc.0 > UDC
常见错误: 在绑定 UDC 之前,必须确保 UDC 驱动已经加载且设备树中对应的节点状态为 okay。如果出现 write error: No such device,请首先检查 /sys/class/udc/ 目录下是否存在对应的 UDC 实例。

1.4 为什么需要硬件适配与移植

不同 SoC 厂商的 UDC 控制器实现差异很大。即使都使用 DWC2 IP 核,各厂商的时钟门控、复位逻辑、引脚复用和电源管理策略也可能不同。硬件适配与移植的核心工作包括:

  • 设备树绑定:为 UDC 节点添加正确的 compatible 字符串、时钟、中断和 phy 引用。
  • 时钟与电源:确保 UDC 模块的时钟使能、复位释放和电源域配置正确。
  • 引脚复用:配置 SoC 的 USB D+/D- 引脚为 UDC 功能模式,而非 Host 模式。
  • DMA 与中断:验证 UDC 的 DMA 通道和中断号是否与硬件手册一致。

下图展示了从硬件寄存器到最终 Gadget 功能的完整数据流:

USB Gadget 数据流与硬件适配点 USB Gadget 数据流与硬件适配点 UDC 硬件寄存器 FIFO / EP / DMA 适配点:时钟/复位/引脚 UDC 驱动 dwc2_udc_irq / ep_queue Gadget API usb_gadget / usb_ep Gadget 功能 RNDIS / MTP / UVC 适配点:设备树 compatible / 中断号