1. USB Gadget 概述

USB Gadget 是嵌入式 Linux 系统中一种特殊的 USB 设备角色实现方式。它允许嵌入式设备(如开发板、路由器、工业控制器)通过 USB 接口模拟成键盘、鼠标、U盘、网卡、串口等标准 USB 设备,从而与 USB Host(通常是 PC 或手机)进行通信。

核心认知:USB Gadget 让嵌入式设备从“USB 主控者”转变为“USB 外设”,极大地扩展了嵌入式系统的互联能力。

1.1 USB Gadget 与传统 USB Host 的区别

在传统 USB 体系中,Host 负责管理总线、发起传输、分配地址;Device 则被动响应。USB Gadget 将嵌入式设备置于 Device 角色,但通过软件配置使其能模拟多种标准设备类型。下表列出了两者的关键差异:

对比维度 USB Host USB Gadget (Device)
总线控制权 拥有总线主控权,发起所有传输事务 被动响应 Host 请求,不能主动发起传输
硬件接口 使用 Host 控制器(EHCI/XHCI) 使用 Device 控制器(UDC)或 OTG 双角色
典型设备 PC、笔记本、手机(作为 Host 时) 开发板、嵌入式模块、工业控制器
软件栈 USB Core + HCD + 驱动 USB Gadget Framework + UDC 驱动 + Function 驱动
供电角色 对外提供 5V 电源(VBUS) 从 VBUS 取电,或自供电
应用场景 连接外设(U盘、鼠标、打印机) 模拟外设,与 PC/手机通信
关键理解:USB Gadget 不是硬件上的“降级”,而是角色上的“转换”。同一块硬件(如带有 OTG 接口的 SoC)可以在软件层面切换为 Host 或 Gadget 模式。

1.2 USB Gadget 在嵌入式系统中的应用场景

USB Gadget 在嵌入式领域应用广泛,几乎覆盖了所有需要与 PC 或手机进行数据交互的场景。以下是几种典型应用:

  • 模拟 U盘(Mass Storage Gadget):将嵌入式设备的存储分区或文件系统镜像暴露为 U盘,用于固件升级、日志导出、数据备份。
  • 模拟虚拟串口(Serial Gadget / ACM):通过 USB 模拟串口,用于调试终端、AT 指令通信、传感器数据采集。
  • 模拟以太网卡(Ethernet Gadget / RNDIS / ECM):使嵌入式设备通过 USB 线缆获得网络连接,常用于开发板网络共享、IoT 网关配置。
  • 模拟 HID 设备(HID Gadget):模拟键盘、鼠标、游戏手柄,用于自动化测试、远程控制、人机交互。
  • 模拟音频设备(Audio Gadget):模拟 USB 麦克风或扬声器,用于语音采集、音频播放。
  • 多功能复合设备(Composite Gadget):将上述多种功能组合到一个 USB 设备中,例如同时模拟 U盘 + 虚拟串口 + 以太网卡。
注意事项:复合设备需要 Host 端支持多个接口描述符,且每个 Function 必须使用不同的接口号。Windows 和 Linux Host 对复合设备的支持程度不同,开发时需针对性测试。

1.3 USB Gadget 软件架构

Linux 内核中的 USB Gadget 子系统采用分层架构设计,从底层硬件到上层功能接口清晰分离。下图展示了核心组件及其关系:

USB Gadget 软件架构分层图 用户空间 (User Space) ConfigFS / GadgetFS / 用户态工具 (gt, mkudc) Function 驱动层 (Function Drivers) Mass Storage | Serial | Ethernet | HID | Audio | ... 实现具体设备行为,处理请求与数据 Gadget API 层 (usb_gadget_driver) bind() / unbind() / setup() / disconnect() 回调 UDC 驱动层 (UDC Drivers) DWC2 / DWC3 / Chipidea / Renesas / ... 硬件层 (USB Device Controller) SoC 内置 USB OTG 外设 / 独立 UDC 芯片 数据流方向:Host → USB 线缆 → UDC 硬件 → UDC 驱动 → Gadget API → Function 驱动 → 用户空间

各层职责简述:

  • 硬件层:SoC 内部的 USB Device Controller 或独立 UDC 芯片,负责物理层信号处理与端点管理。
  • UDC 驱动层:硬件抽象层,向上提供统一的 usb_gadget_ops 接口,向下操作具体寄存器。
  • Gadget API 层:核心框架,管理 Gadget 生命周期,分发控制请求(Setup Packet)到对应的 Function 驱动。
  • Function 驱动层:实现具体 USB 设备类的协议逻辑,如 SCSI 命令处理(Mass Storage)、CDC 封装(Serial/Ethernet)。
  • 用户空间层:通过 ConfigFS 或 GadgetFS 动态配置 Gadget 的字符串描述符、配置描述符、Function 绑定。
实践要点:在嵌入式 Linux 中,最常用的 Gadget 配置方式是 ConfigFS。它通过 sysfs 文件系统暴露配置接口,无需重新编译内核即可动态组合多个 Function,是实现复合设备的核心技术。

1.4 本章小结