1. USB Gadget 概述

USB Gadget 是嵌入式 Linux 系统中实现设备端 USB 功能的核心框架。它允许运行 Linux 的硬件(如开发板、手机、嵌入式设备)通过 USB 接口模拟出多种标准 USB 设备角色,例如 U 盘、串口、网卡或 MIDI 设备。理解 Gadget 框架是进行驱动调试和枚举失败定位的基础。

1.1 USB Gadget 框架介绍

Linux USB Gadget 框架采用分层的软件架构,从上到下依次为:Gadget Function 层、UDC (USB Device Controller) 核心层 和 UDC 驱动层。这种分层设计使得功能实现与硬件控制器解耦,便于移植和扩展。

Linux USB Gadget 软件架构 用户空间 (User Space) — 配置工具 / ConfigFS Gadget Function 层 g_serial.ko | g_mass_storage.ko | g_ether.ko | g_midi.ko 实现具体 USB 功能逻辑(串口、U盘、网卡、MIDI) UDC 核心层 (USB Device Controller Core) udc-core.c — 管理 Gadget 注册、枚举流程、EP 分配 UDC 驱动层 (Controller Driver) dwc2.ko | dwc3.ko | chipidea.ko | musb.ko 硬件层:USB Device Controller (DWC2 / DWC3 / ChipIdea)
调试要点: 枚举失败时,首先确认 UDC 驱动层是否成功绑定硬件。检查 /sys/kernel/debug/usb/ 下的设备状态,或使用 ls /sys/class/udc/ 查看是否有 UDC 设备节点。

1.2 Gadget 与 Host 的区别

在 USB 体系中,Host(主机) 和 Gadget(设备) 的角色有本质区别。理解这些差异有助于在调试时快速定位问题属于主机侧还是设备侧。

对比维度 USB Host(主机) USB Gadget(设备)
典型硬件 PC、笔记本、树莓派(Type-A 口) 嵌入式开发板、手机(Type-B / OTG 口)
软件栈 HCD (Host Controller Driver) + USB Core + Class Driver UDC Driver + Gadget Core + Function Driver
总线控制权 负责发起所有传输、调度、枚举 被动响应主机请求,不能主动发起传输
枚举角色 发送复位信号、获取描述符、配置设备 响应主机请求,返回描述符,配置端点
电源角色 提供 VBUS 电源(通常为 5V) 由 VBUS 供电或自供电
常见问题 驱动缺失、xHCI 控制器故障、电源不足 UDC 未注册、描述符错误、端点配置失败
关键概念: 在 OTG (On-The-Go) 模式下,同一硬件端口可以在 Host 和 Gadget 角色之间切换。调试时务必确认当前端口的工作模式,使用 cat /sys/kernel/debug/usb/otg_state 查看状态。

1.3 常见 Gadget 功能

Linux USB Gadget 框架支持多种标准 USB 设备类。以下是嵌入式开发中最常用的四种功能:

  • U 盘 (Mass Storage Class) — 将嵌入式设备模拟为 USB 大容量存储设备,用于文件传输、固件升级。
  • 串口 (Communication Device Class - ACM) — 模拟 USB 虚拟串口,用于控制台访问、日志输出、AT 命令交互。
  • 网卡 (Ethernet Control Model / RNDIS) — 模拟 USB 以太网适配器,实现设备与主机之间的网络通信。
  • MIDI (Audio Class - MIDI) — 模拟 USB MIDI 设备,用于音乐制作、合成器控制、音频信号处理。
常见 USB Gadget 功能与应用场景 嵌入式 Linux 设备 USB Gadget 框架 U 盘 (Mass Storage) 文件传输 / 固件升级 串口 (CDC ACM) 网卡 (ECM / RNDIS) 网络通信 / SSH 访问 MIDI (Audio Class)

1.4 Gadget 功能对比与选择

在实际项目中,选择哪种 Gadget 功能取决于应用需求。下表从传输速率、实时性、配置复杂度三个维度进行对比:

Gadget 功能 USB 类协议 典型传输速率 实时性 配置复杂度 典型应用
U 盘 Mass Storage (BOT / UAS) 20~400 MB/s 低 低 文件拷贝、系统升级
串口 CDC ACM 115200 bps ~ 12 Mbps 中 低 调试控制台、AT 指令
网卡 CDC ECM / RNDIS 10~1000 Mbps 中 中 网络共享、远程登录
MIDI Audio Class 1.0 / 2.0 31.25 Kbps (MIDI 1.0) 高 高 电子乐器、音序器
常见误区: 不要将 Gadget 功能与 USB 转串口芯片(如 FT232、CP2102)混淆。Gadget 是软件模拟的 USB 设备,而 USB 转串口芯片是硬件桥接器。调试时,主机侧看到的设备描述符和 VID/PID 完全不同。

1.5 Gadget 功能加载示例

在 Linux 内核中,Gadget 功能通常以内核模块形式加载。以下是通过 ConfigFS 配置一个 USB 串口 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  # Gadget Serial

# 4. 创建英文字符串
mkdir strings/0x409
echo "MyBoard" > strings/0x409/manufacturer
echo "USB Serial Gadget" > strings/0x409/product

# 5. 创建配置
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "Serial Config" > configs/c.1/strings/0x409/configuration

# 6. 绑定串口功能
mkdir functions/acm.usb0
ln -s functions/acm.usb0 configs/c.1

# 7. 绑定 UDC 控制器
echo musb-hdrc.0 > UDC   # 根据实际 UDC 名称调整
调试技巧: 如果 echo ... > UDC 失败,检查 dmesg 中是否有 "can't bind" 或 "UDC core: gadget not registered" 错误。常见原因是 UDC 驱动未加载或硬件未初始化。