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 子系统采用分层架构设计,从底层硬件到上层功能接口清晰分离。下图展示了核心组件及其关系:
各层职责简述:
- 硬件层: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,是实现复合设备的核心技术。