4.3.19. USB/USB Gadget调试指南
4.3.19.1. 概述
X5 内置了 USB2.0 和 USB3.0 控制器,其特性如下
USB 2.0 OTG
支持 Host 模式和 Device 模式
兼容性标准: USB 通用串行总线规范 (USB Specification Revision 2.0)
支持高速 (HS), 全速 (FS), 和低速 (LS) 模式
支持 LS 模式下的 Keep-Alive 特性,以及 HS/FS 模式下使用 (micro-)SOF (Start of Frame) 信号
硬件支持总线级和数据包级的错误处理
USB 3.0 OTG
支持 Host 模式和 Device 模式
兼容性标准: USB 通用串行总线规范 (USB Specification Revision 3.0)
支持超高速 (SS), 高速 (HS), 全速 (FS), 和低速 (LS) 模式
支持 PIPE3 PHY (125/250/500 MHz)
支持 LS 模式下的 Keep-Alive 特性,以及 HS/FS 模式下使用 (micro-)SOF (Start of Frame) 信号
硬件支持总线级和数据包级的错误处理
相关术语
| 术语 | 说明 |
|---|---|
| USB | Universal Serial Bus, 通用串行总线 |
| Gadget | 配件 |
| HCD | Host Controller Driver,主机控制器驱动 |
| UDC | USB Device Controller, USB 设备控制器 |
| HCI | Host Controller Interface,主机控制器接口 |
| EHCI | Enhanced Host Controller Interface,增强型主机控制器接口 |
| OHCI | Open Host Controller Interface,开放式主机控制器接口 |
| ADB | Android Debug Bridge,Android 调试桥 |
| HID | Human Interface Device,人机接口设备 |
| Rndis | Remote NDIS,远程 NDIS |
| ECM | Ethernet Networking Control Model |
| ACM | Abstract Control Model |
| MSD | Mass Storage Device,大容量存储设备 |
| UVC | USB video class |
| UAC | USB Audio class |
4.3.19.2. 功能描述
典型应用
USB Gadget 是一种用于模拟 USB 复合设备的技术。在 Linux 系统中,”gadget” 通常指通过 USB 接口连接到主机的虚拟设备,例如 USB 存储设备、网络适配器、串口设备、音频设备、HID 设备等。
USB Gadget 的关键特性之一是通过 configfs 提供了灵活且动态的配置和管理方式。configfs 是一个用户空间可操作的文件系统接口,开发者可以通过文件系统命令动态创建和配置 USB 设备的各个组件,如设备描述符、接口、端点等。不同于传统的需要编译内核或重启系统的方式,configfs 使得 USB gadget 配置变得更加灵活,能够在系统运行时动态调整和修改,极大地简化了开发和调试过程。
总之,USB Gadget 提供了一种无需修改内核代码即可快速实现和管理虚拟 USB 设备的方式,增强了 Linux 系统的可扩展性和灵活性,使其能够更方便地模拟各种 USB 设备功能,满足不同应用场景的需求。
功能原理
USB Gadget 驱动框架如下

在 USB Gadget 框架中,USB 设备的功能和行为是通过以下几个层次来实现的
USB Function Driver
USB Function Driver 负责实现设备的具体功能。它定义了 USB 设备在连接到主机时的行为和功能,例如虚拟串口、USB 存储、网络适配器等。每个 USB Gadget 设备通常会有一个或多个功能驱动,表示设备所支持的不同功能。configfs
configfs 是一个用户空间接口,通过文件系统的方式让用户动态配置 USB 设备。configfs 提供了一个非常灵活的方式来设置 USB Gadget 设备的各种参数,包括设备描述符、配置、接口以及功能。UDC Driver
UDC 驱动(USB Device Controller Driver)是与硬件 USB 控制器交互的驱动程序,负责管理 USB 设备的物理连接和数据传输。它充当 USB 控制器的底层接口,与 USB 设备的硬件层面交互。
4.3.19.3. 代码分析
USB Gadget 驱动
内核选项
内核需开启以下选项
CONFIG_USB_GADGET
CONFIG_USB_CONFIGFS
USB Gadget 功能是通过模块加载的,可以根据所需的 USB 功能来启用相应的 USB function
CONFIG_USB_CONFIGFS_SERIAL
CONFIG_USB_CONFIGFS_ACM
CONFIG_USB_CONFIGFS_OBEX
CONFIG_USB_CONFIGFS_NCM
CONFIG_USB_CONFIGFS_ECM
CONFIG_USB_CONFIGFS_ECM_SUBSET
CONFIG_USB_CONFIGFS_RNDIS
CONFIG_USB_CONFIGFS_EEM
CONFIG_USB_CONFIGFS_MASS_STORAGE
CONFIG_USB_CONFIGFS_F_LB_SS
CONFIG_USB_CONFIGFS_F_FS
CONFIG_USB_CONFIGFS_F_UAC1
CONFIG_USB_CONFIGFS_F_UAC2
CONFIG_USB_CONFIGFS_F_HID
CONFIG_USB_CONFIGFS_F_UVC
驱动代码
USB 驱动的源代码位于内核 drivers/usb 目录下
.
├── Kconfig
├── Makefile
├── core // USB 子系统核心代码
├── dwc3 // USB 控制器 dwc3 驱动程序
└── gadget // gadget 目录包含了与 USB gadget 相关驱动,实现了 USB Gadge 功能(如存储设备、串口、网络适配器等)
├── Kconfig
├── Makefile
├── composite.c // 创建和管理 USB 复合设备
├── config.c
├── configfs.c // configfs 文件系统源码
├── configfs.h
├── function // USB 设备端功能驱动程序,实现不同类型的 USB 设备功能
│ ├── Makefile
│ ├── f_acm.c
│ ├── f_ecm.c
│ ├── f_eem.c
│ ├── f_fs.c
│ ├── f_hid.c
│ ├── f_loopback.c
│ ├── f_mass_storage.c
│ ├── f_mass_storage.h
│ ├── f_midi.c
│ ├── f_ncm.c
│ ├── f_obex.c
│ ├── f_phonet.c
│ ├── f_printer.c
│ ├── f_rndis.c
│ ├── f_serial.c
│ ├── f_sourcesink.c
│ ├── f_subset.c
│ ├── f_tcm.c
│ ├── f_uac1.c
│ ├── f_uac1_legacy.c
│ ├── f_uac2.c
│ ├── f_uvc.c
│ ├── f_uvc.h
│ ├── g_zero.h
│ ├── ndis.h
│ ├── rndis.c
│ ├── rndis.h
│ ├── storage_common.c
│ ├── storage_common.h
│ ├── tcm.h
│ ├── u_audio.c
│ ├── u_audio.h
│ ├── u_ecm.h
│ ├── u_eem.h
│ ├── u_ether.c
│ ├── u_ether.h
│ ├── u_ether_configfs.h
│ ├── u_fs.h
│ ├── u_gether.h
│ ├── u_hid.h
│ ├── u_midi.h
│ ├── u_ncm.h
│ ├── u_phonet.h
│ ├── u_printer.h
│ ├── u_rndis.h
│ ├── u_serial.c
│ ├── u_serial.h
│ ├── u_tcm.h
│ ├── u_uac1.h
│ ├── u_uac1_legacy.c
│ ├── u_uac1_legacy.h
│ ├── u_uac2.h
│ ├── u_uvc.h
│ ├── uac_common.h
│ ├── uvc.h
│ ├── uvc_configfs.c
│ ├── uvc_configfs.h
│ ├── uvc_queue.c
│ ├── uvc_queue.h
│ ├── uvc_v4l2.c
│ ├── uvc_v4l2.h
│ ├── uvc_video.c
│ └── uvc_video.h
├── functions.c // 创建和管理 USB Function
├── udc // UDC 驱动程序
└── usbstring.c // 创建和管理 USB 设备字符串描述符
USB Gadget 脚本
usb-gadget.sh脚本配置流程
usb-gadget.sh 脚本位于/etc/init.d/usb-gadget.sh,主要作用是简化 USB 设备功能的启用过程,并提供一种自动化的方式来配置和管理 USB gadget 设备,其功能如下:
根据预设的 USB 配置文件,初始化 USB Gadget 驱动
配置 USB 复合设备的功能描述符,并通过 CONFIGFS 接口将这些配置应用到系统中
启用 USB 复合设备功能
usb-gadget.sh 的使用帮助信息,支持如下类型 USB 设备
USB 单一设备,包括 ADB / Rndis / ECM / HID / ACM /MSD / UVC / UAC
USB 复合设备,即通过同一 USB 设备同时支持多种设备功能
Usage: /etc/init.d/usb-gadget.sh {start|stop|restart} [options]
options:
detail gadget-composite config, using .usb/.default-config in default
adb launch adbd
msd run as gadget mass storage device
msd-ram run as gadget mass storage device(with ddr storage)
hid run as hid gadget
rndis run as rndis gadget
ecm run as cdc ether gadget
uvc run as uvc gadget
uac1 usb audio class specification 1
uac2 usb audio class specification 2
uvc-hid uvc + hid composite gadget
uvc-uac1 uvc + uac1 composite gadget
uvc-uac2 uvc + uac2 composite gadget
uvc-hid-uac1 uvc + hid + uac1 composite gadget
uvc-hid-uac2 uvc + hid + uac2 composite gadget
uvc-rndis uvc + rndis composite gadget
uvc-ecm uvc + cdc ether composite gadget
uvc-acm uvc + acm(serial) composite gadget
uvc-rndis-uac1 uvc + rndis + uac1 composite gadget
uvc-rndis-uac2 uvc + rndis + uac2 composite gadget
uvc-ecm-uac1 uvc + ecm + uac1 composite gadget
uvc-ecm-uac2 uvc + ecm + uac2 composite gadget
rndis-hid rndis + hid composite gadget
rndis-uac1 rndis + uac1 composite gadget
msd-uac1 msd + uac1 composite gadget
hid-uac1 hid + uac1 composite gadget
uvc-adb uvc + adb composite gadget
usb-gadget.sh 脚本配置流程如下
挂载 configfs,configfs 提供了一个用户空间接口,用于配置 USB 复合设备
创建 USB Gadget 目录:实例化一个新的 USB Gadget 设备。
配置 USB Gadget 信息:设置 USB 设备的配置,包括厂商 ID (VID)、产品 ID (PID)、设备描述符等基本信息
创建并配置 USB 功能:根据所需的设备功能(如虚拟串口、存储、网络等),创建并配置相应的 USB 功能
绑定 USB 配置与功能:将配置文件和功能进行关联,完成设备功能配置
启用 USB 控制器:启动并使能 USB 控制器,开始与主机进行通信
start_usb_gadget()
{
echo "Creating the USB gadget"
# 加载 libcomposite 驱动,usb gadget 依赖 libcomposite 模块
echo "Loading composite module"
modprobe libcomposite
# 挂载 configfs
echo "Mount ConfigFS and create Gadget"
CONFIGFS_MOUNT_POINT=$(mount | grep configfs | awk '{ print $3 }')
echo "configfs mount point: " ${CONFIGFS_MOUNT_POINT}
if [[ -n ${CONFIGFS_MOUNT_POINT} ]]; then
echo "Configfs already mounted..."
else
mount -t configfs none /sys/kernel/config
fi
# 创建 USB Gadget
echo "Creating gadget directory g_comp"
mkdir -p $USB_CONFIGFS
cd $USB_CONFIGFS
if [ $? -ne 0 ]; then
echo "Error creating usb gadget in configfs"
exit 1
else
echo "OK"
fi
# 创建并配置 USB Gadget configuration
echo "init configfs..."
configfs_init
# 配置 USB Function
echo "Init functions..."
function_init
echo "OK"
# 将 USB configuration 与 Function 绑定
echo "Bind functions..."
bind_functions
# 加载 USB Function 所需的后台程序
echo "Pre run userspace daemons(eg. adb)..."
pre_run_binary
# just with userspace daemon, needs to wait some time.
echo "waiting"
for i in `seq 0 $?`
do
echo "."
sleep 0.1
done
echo "OK"
# 使能 UDC
echo "Binding USB Device Controller"
echo $UDC > UDC
echo peripheral > $UDC_ROLE
cat $UDC_ROLE
echo "OK"
echo "Run some userspace daemons(eg. usb_camera)..."
run_binary
}
通过 configfs_init() 配置 USB Gadget 设备信息
configfs_init()
{
# 配置 USB PID/VID
echo "Setting Vendor and Product ID's"
echo $USB_VID > idVendor
echo $USB_PID > idProduct
echo "OK"
if $USE_RNDIS; then
echo 0100 > bcdDevice # v1.0.0, otherwise win10 rndis couldn't install
fi
# 配置 USB 设备类
if $IS_MULTI_FUNC; then
echo "Setting Multi-func Gadget for Windows"
echo 0xEF > bDeviceClass
echo 0x02 > bDeviceSubClass
echo 0x01 > bDeviceProtocol
elif $USE_UAC1; then
echo 0xEF > bDeviceClass
echo 0x02 > bDeviceSubClass
echo 0x01 > bDeviceProtocol
else
echo "single function gadget"
if $USE_RNDIS; then
echo 0x02 > bDeviceClass # same with legacy/ether.c
fi
fi
# 配置 USB 字符串描述符
echo "Setting English strings"
mkdir -p strings/0x409
echo $SERIAL > strings/0x409/serialnumber # 序列号
echo $MANUF > strings/0x409/manufacturer # 产商
echo $PRODUCT > strings/0x409/product # 设备型号
echo "OK"
# 创建 USB 配置
echo "Creating Config"
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "Conf 1" > configs/c.1/strings/0x409/configuration
echo 0xC0 > configs/c.1/bmAttributes
echo 0x01 > configs/c.1/MaxPower
}
4.3.19.4. USB Gadget 功能使用
ADB (Android Debug Bridge)
ADB(Android Debug Bridge) 是一个多功能的 Android 命令行工具,允许开发者与设备进行交互,通常用于嵌入式设备的开发和调试。
代码分析
通过 create_adb() 函数创建 ADB Function
create_adb()
{
CONFIG=$1
FUNCTION=$2
echo "Creating ADB gadget functionality"
mkdir functions/$FUNCTION
ln -s functions/$FUNCTION configs/c.1
}
USB ADB 功能依赖于 ADBD 后台服务
mkdir -p /dev/usb-ffs/adb
mount -o uid=2000,gid=2000 -t functionfs adb /dev/usb-ffs/adb # 挂载 FunctionFS 文件系统
start-stop-daemon -S -b -q -n adbd -a /usr/bin/adbd # 启动 ADBD 后台服务
使用方法
板端运行命令
/etc/init.d/usb-gadget.sh restart adb
USB ADB 使用方法可以参考 使用 adb 章节
Rndis 网卡
RNDIS(Remote Network Driver Interface Specification) 是一种用于通过 USB 接口实现网络通信的标准协议,通常用于将设备(如智能手机、嵌入式设备等)通过USB连接到计算机,并通过 USB 连接提供网络功能。RNDIS 允许设备通过 USB 与计算机进行数据传输,表现为一个虚拟的以太网接口,从而使设备可以像通过传统网络一样与计算机进行数据通信。
代码分析
通过 create_rndis() 创建 USB Rndis Function
create_rndis configs/c.1 rndis.0
create_rndis()
{
CONFIG=$1
FUNCTION=$2
echo "Creating RNDIS gadget functionality"
mkdir functions/$FUNCTION # 创建 USB Rndis Function 目录
mkdir -p os_desc
echo 1 > os_desc/use
echo 0xcd > os_desc/b_vendor_code
echo MSFT100 > os_desc/qw_sign
mkdir -p functions/$FUNCTION/os_desc/interface.rndis # 创建 Rndis 目录,用于存储 Rndis 相关的设备描述信息
echo RNDIS > functions/$FUNCTION/os_desc/interface.rndis/compatible_id # 写入 Rndis 协议标识符
echo 5162001 > functions/$FUNCTION/os_desc/interface.rndis/sub_compatible_id # 设置 Rndis 兼容ID与设备版本
ln -s functions/$FUNCTION configs/c.1 # 将 Rndis Function 与 config 绑定一起
ln -s configs/c.1/ os_desc
}
其他参数说明
dev_addr 设置网卡 MAC 地址
例如:echo "00:11:22:33:44:55" > functions/$FUNCTION/dev_addr
使用方法
板端运行命令
/etc/init.d/usb-gadget.sh restart rndis
USB Rndis 使用方法可以参考 虚拟网卡(rndis) 章节
ECM 网卡
ECM(Ethernet Control Model) 是一种通过USB连接进行以太网通信的协议,允许设备(如手机、嵌入式系统、路由器等) 通过 USB 与主机(通常是计算机或其他网络设备)建立虚拟以太网连接。ECM 协议使得通过 USB 的网络连接类似于传统的以太网连接,它定义了如何通过 USB 端口传输以太网数据包,使得设备能够与主机进行以太网层的通信。
代码分析
通过 create_ecm() 创建 USB ECM Function
create_ecm()
{
CONFIG=$1
FUNCTION=$2
echo "Creating CDC ECM gadget functionality"
mkdir functions/$FUNCTION # 创建 USB ECM Function 目录
ln -s functions/$FUNCTION configs/c.1 # 将 ECM Function 与 config 绑定一起
}
使用方法
板端运行命令
/etc/init.d/usb-gadget.sh restart ecm
USB ECM 使用方法可以参考 虚拟网卡(cdc-ecm) 章节
MSD (Mass Storage Device)
MSD(Mass Storage Device)是指通过 USB 端口连接的大容量存储设备。它允许设备像硬盘、U盘、SD卡等存储设备一样,提供数据存储和读取功能,并与主机(如个人电脑、智能手机、嵌入式设备等)进行通信。
代码分析
MSD 需要在板端分配一块存储空间作为存储源。这块存储空间可以是文件系统中的某个目录、一个存储镜像,或是一个 ramfs 镜像。主机可以像访问本地存储一样读写存储源。选择存储源的类型(目录、镜像或 ramfs)取决于具体的应用需求和系统架构。ramfs 镜像通常用于需要高速读写和临时存储的场景,而文件系统目录或镜像则适用于持久化存储。
BSP源码包默认使用文件系统镜像和 ramfs 镜像作为存储源。如果需要修改存储源路径,请分别修改变量 $MSD_FILE 和 $MSD_BLOCK_SIZE。
使用文件系统镜像作为存储源
| 镜像源路径 | 镜像大小 | 挂载目录 | 文件系统格式 |
|---|---|---|---|
/userdata/mass_storage.img |
128M | /media/mass_storage |
FAT32 |
执行命令
/etc/init.d/usb-gadget.sh restart msd
使用 ramfs 镜像作为存储源
| 镜像源路径 | 镜像大小 | 挂载目录 | 文件系统格式 |
|---|---|---|---|
/dev/shm/msd_ram.img |
512M | /media/mass_storage |
FAT32 |
执行命令
/etc/init.d/usb-gadget.sh restart msd-ram
使用方法
Host 端显示大容量存储外设插入

对比源目录与 Host 端目录文件一致
源目录
root@buildroot:/media/mass_storage# ls -al
total 11282
drwxr-xr-x 3 root root 16384 Jan 1 00:00 .
drwxrwxrwt 3 root root 60 Jan 1 00:00 ..
-rwxr-xr-x 1 root root 0 Jan 1 1980 file1
-rwxr-xr-x 1 root root 1048576 Jan 1 1980 file2
-rwxr-xr-x 1 root root 10485760 Jan 1 1980 file3
drwxr-xr-x 2 root root 2048 Jan 1 1980 folder
Host 端

HID (Human Interface Device)
USB HID(Human Interface Device) 是 USB 协议中定义的一种设备类,用于连接各种人机交互设备(如鼠标、键盘、游戏控制器、触摸屏等)到计算机或其他主机系统。
代码分析
HID 设备在创建 HID 功能时,需要提供报告描述符(Report Descriptor)来定义 HID 报告的格式。SDK 默认提供了一个报告描述符镜像文件:/etc/init.d/hid_report_desc.bin,用户可以根据自己的 HID 报告格式需求,替换该镜像文件。
报告描述符是 HID 设备与主机之间通信的核心,它定义了设备的输入、输出及特性信息,因此,正确配置报告描述符对于确保 HID 设备正常工作至关重要。
create_hid()
{
CONFIG=$1
FUNCTION=$2
echo "Creating HID gadget functionality"
mkdir functions/$FUNCTION
echo 1 > functions/$FUNCTION/protocol
echo 1 > functions/$FUNCTION/subclass
echo 1024 > functions/$FUNCTION/report_length # 设置 HID report 长度
cat $HID_REPORT_DESC > functions/$FUNCTION/report_desc # 设置 HID 报告描述符,用于设置 HID report 格式
ln -s functions/$FUNCTION configs/c.1
echo "OK"
}
使用方法
板端执行命令
/etc/init.d/usb-gadget.sh restart hid
Host 端显示 HID 外设插入

ACM 串口
ACM (Abstract Control Model) 是USB通信设备类(CDC,Communication Device Class)中的一种协议,主要用于支持基于串口通信的设备。通过 USB ACM 协议,设备可以模拟一个标准的串行端口(如RS-232串口)。 USB ACM 通常用于替代传统的 RS-232 或其他串行接口的通信。
代码分析
create_acm()
{
CONFIG=$1
FUNCTION=$2
echo "Creating ACM gadget functionality"
mkdir functions/$FUNCTION # 创建 USB ACM Function 目录
ln -s functions/$FUNCTION configs/c.1 # 创建 USB ACM Function 目录
}
使用方法
板端执行命令
/etc/init.d/usb-gadget.sh restart acm
板端将生成 tty 节点 /dev/ttyGS0
Host 端显示串口插入 (本示例为 COM4)

以下将通过简单的串口收发测试验证 USB ACM 功能
ACM 通路测试 - 方向 Device->Host
板端执行测试命令
echo "USB ACM Test: Device -> Host." > /dev/ttyGS0
Host 打开对应的虚拟串口 (本示例为 COM4,默认波特率9600),并接收到相同的字符串

ACM 通路测试 - 方向 Host -> Device
Host 打开对应的虚拟串口 (本示例为 COM4,默认波特率9600),并发送字符串

板端执行测试命令,并接收到相同的字符串
root@buildroot:/userdata# cat /dev/ttyGS0
USB ACM Test: Host -> Device.
UAC (USB Audio Class)
UAC(USB Audio Class) 是 USB 设备类的一部分,专门用于通过 USB 连接音频设备的标准协议。UAC 允许设备(如耳机、麦克风、扬声器、音频接口、USB 声卡等)通过 USB 总线与计算机或其他 USB 主机进行音频数据的传输。USB UAC 提供了一个通用、标准化的方式来实现音频设备的连接,从而使用户可以在各种操作系统上(如 Windows、Linux、macOS 等)以即插即用的方式使用这些设备。
代码分析
usb-gadget.sh 脚本通过函数 create_uac1() 配置 UAC 参数
create_uac1()
{
CONFIG=$1
FUNCTION=$2
echo "Creating UAC1 gadget functionality : $FUNCTION"
mkdir functions/$FUNCTION
echo 0x3 > functions/$FUNCTION/p_chmask # 使能声卡放音左右声道
echo 48000 > functions/$FUNCTION/c_srate # 设置采样率,示例 48K
echo 0x3 > functions/$FUNCTION/c_chmask # 使能声卡录音左右声道
ln -s functions/$FUNCTION configs/c.1 # 绑定 UAC Function 到 config
echo "OK"
}
常用的参数接口设置如下
p_srate, c_srate: 采样率,支持多采样率配置,采样率之间用逗号隔开,例如
echo 8000,16000,32000 > c_sratec_chmask, p_chmask: 声道掩码,支持多声道或删除对应声道
p_ssize, c_ssize: 数据位宽,例如: 16bit 位宽值为2
使用方法
板端执行命令生成 UAC 设备
/etc/init.d/usb-gadget.sh restart uac1
板端生成 UAC1 声卡
查看 UAC1 声卡的方法
root@buildroot:~# cat /proc/asound/cards
0 [guaaudio ]: gua-audio - gua-audio
gua-audio
1 [UAC1Gadget ]: UAC1_Gadget - UAC1_Gadget
UAC1_Gadget 0
root@buildroot:~# ls -al /proc/asound/card1
total 0
dr-xr-xr-x 5 root root 0 Jan 1 00:06 .
dr-xr-xr-x 11 root root 0 Jan 1 00:04 ..
-r--r--r-- 1 root root 0 Jan 1 00:06 id
dr-xr-xr-x 4 root root 0 Jan 1 00:06 pcm0c
dr-xr-xr-x 4 root root 0 Jan 1 00:06 pcm0p
root@buildroot:~# ls /dev/snd/pcmC1D0*
/dev/snd/pcmC1D0c /dev/snd/pcmC1D0p
可以看到 UAC1 对应 card1(UAC1Gadget),具有一个 playback 设备节点(pcmC1D0p),一个 capture 设备节点(pcmC1D0c)
Host 端显示音频设备接入

测试 UAC1 放音功能
注意: 由于 X5 EVB 主板并没有音频播放设备,所以采用录制音频文件方式验证 UAC1 放音功能。
Host端打开音频播放器,并选择 UAC1 对应的放音设备。
以 Audacity 为例,选择一段测试音频,并选择 UAC1 的放音设备(本示例为 2-AC Interface),点击播放。

板端执行命令
arecord -f dat -t wav -r 48000 -c 2 -D hw:1,0 /userdata/rec.wav
以上命令表示从 Card1(UAC1Gadget) 录音,指定格式为 wav,采样率48K,双声道,并保存成文件 /userdata/rec.wav
测试 UAC1 录音功能
注意: 由于 X5 EVB 主板并没有麦克风,所以采用播放音频文件方式验证 UAC1 录音功能。
使用 Windows 的录音侦听功能,实时播放录音的音频,方法如下:
Host端打开声音设置 -> 声音控制面板 -> 录制 -> 属性 -> 侦听,勾选侦听此设备(本示例为 2-AC Interface),并选择 Host 端可用于播放的扬声器。

板端执行命令
aplay /userdata/play.wav -c 2 -r 48000 -D hw:1,0
以上命令表示通过 Card1(UAC1Gadget) 播放音频文件,指定格式为 wav,采样率48K,双声道。
UVC (USB Video Class)
UVC(USB Video Class) 是 USB 设备类之一,用于支持视频设备(如摄像头、视频采集卡、网络摄像头等)通过 USB 总线与计算机或其他 USB 主机进行视频数据传输的标准协议。UVC 允许视频设备与操作系统(如 Windows、Linux、macOS 等)以即插即用的方式进行连接,并提供视频流的实时传输和控制。
代码分析
当前 X5 UVC 支持的分辨率以及格式
| 格式 | 分辨率 |
|---|---|
| YUV | 1280 x 720 |
| H264 | 640 x 480 1088 x 1280 1280 x 720 1920 x 1080 |
| MJPEG | 1280 x 720 1920 x 1080 |
UVC 分辨率列表通过以下两处代码设置,如果用户自定义分辨率列表,需注意列表内容与顺序保持一致。
通过 usb-gadget.sh 的
create_frame()函数添加
create_uvc() {
CONFIG=$1
FUNCTION=$2
echo " Creating UVC gadget functionality : $FUNCTION"
mkdir functions/$FUNCTION
# 添加分辨率与格式到支持列表
create_frame $FUNCTION 1280 720 uncompressed u
create_frame $FUNCTION 640 480 uncompressed f h264
create_frame $FUNCTION 1088 1280 uncompressed f h264
create_frame $FUNCTION 1280 720 uncompressed f h264
create_frame $FUNCTION 1920 1080 uncompressed f h264
create_frame $FUNCTION 1280 720 mjpeg m
create_frame $FUNCTION 1920 1080 mjpeg m
mkdir functions/$FUNCTION/streaming/header/h
cd functions/$FUNCTION/streaming/header/h
ln -s ../../uncompressed/u
ln -s ../../uncompressed/f
ln -s ../../mjpeg/m
cd ../../class/fs
ln -s ../../header/h
cd ../../class/hs
ln -s ../../header/h
cd ../../class/ss
ln -s ../../header/h
cd ../../../control
mkdir header/h
ln -s header/h class/fs
ln -s header/h class/ss
cd ../../../
# Set the packet size: uvc gadget max size is 3k...
echo 3072 > functions/$FUNCTION/streaming_maxpacket
echo 2048 > functions/$FUNCTION/streaming_maxpacket
echo 1024 > functions/$FUNCTION/streaming_maxpacket
# use usb2.0 isoc max bandwidth, using 3072 max packet size
echo 3072 > functions/$FUNCTION/streaming_maxpacket
ln -s functions/$FUNCTION configs/c.1
}
通过 libguvc 源码添加
路径app/samples/platform_samples/sample_usb/gadget/libguvc/src/uvc_gadget.c
// YUV 格式分辨率列表
static struct uvc_frame_info uvc_frames_yuyv[] = {
{ 1280, 720, { 333333, 0 }, 3072 }, /* Note: 720p */
{ 0, 0, { 0, }, 0},
};
// MJPEG 格式分辨率列表
static struct uvc_frame_info uvc_frames_mjpeg[] = {
{ 1280, 720, { 333333, 0 }, 384 }, /* Note: 720p, 80KB */
{ 1920, 1080, { 333333, 0 }, 800 }, /* Note: 1080p, 200KB */
{ 0, 0, { 0, }, },
};
// H264 格式分辨率列表
static struct uvc_frame_info uvc_frames_h264[] = {
{ 640, 480, { 333333, 0 }, 3072 }, /* Note: 480p */
{ 1088, 1280, { 333333, 0 }, 3072 }, /* Note: 1280p */
{ 1280, 720, { 333333, 0 }, 3072 }, /* Note: 720p */
{ 1920, 1080, { 333333, 0 }, 3072 }, /* Note: 1080p */
{ 0, 0, { 0, }, },
};
// UVC 支持格式与分辨率列表
static struct uvc_format_info uvc_formats[] = {
{V4L2_PIX_FMT_YUYV, uvc_frames_yuyv},
{V4L2_PIX_FMT_H264, uvc_frames_h264},
{V4L2_PIX_FMT_MJPEG, uvc_frames_mjpeg},
};
通过 potplayer 播放器获取 UVC 分辨率列表

使用方法
X5 UVC Host 端的使用方法可以参考 uvc_gadget_camera 章节
4.3.19.5. 常见问题
X5 EVB 主板 USB2.0 和 3.0 分别是哪个接口
USB2.0 对应 Micro-USB 接口

USB3.0 对应 USB Type-A 接口

使用 USB2.0 模拟设备提示 “usb-gadget is already running”
X5 EVB 启动后默认通过 USB2.0 生成 ADB,如果使用 USB2.0 生成其他 USB 设备提示此报错,说明系统已有 USB 设备运行,请先执行 /etc/init.d/usb-gadget.sh stop
如何使用 USB 3.0 Gadget
USB3.0 请使用 /etc/init.d/usb3.0-gadget.sh脚本
使用方法与 USB2.0 相同
USB 3.0 切换 Host & Device 模式
USB3.0 默认工作在 Host 模式,用户可以通过软件和硬件两种方式设置 USB3.0 工作在 Device 模式
硬件方式
短接该插针,启动后 USB3.0 自动切换到 Device 模式

软件方式
设置 USB3.0 为 Host模式
echo host > /sys/class/usb_role/35100000.usb-role-switch/role
设置 USB3.0 为 Device模式
echo device > /sys/class/usb_role/35100000.usb-role-switch/role