设备解决方案

Linux 协议栈中,USB 设备称为 Gadget 。

在 Gadget 模式下,USB OTG 控制器可被 USB 主机枚举,并响应传输请求。

Gadget 驱动支持两种配置方式:

Configfs 模式:通过用户空间的文件系统接口动态配置 Gadget 功能。 传统模式:通过加载特定内核模块使用预设配置。

本节主要介绍 Configfs 模式下的使用。

有关设备类的更多详细信息,请参考内核文档 usb support v5.4usb support v6.18

如何使能与禁用 Gadget

在 ConfigFS gadget 配置完成后,需要将 gadget 绑定到 UDC(USB Device Controller)才能使设备对 USB 主机可见。这一步骤称为**使能 gadget**。

查看可用 UDC

ls /sys/class/udc/

UDC 名称为 40080000.usb

使能 gadget

echo 40080000.usb > /sys/kernel/config/usb_gadget/<gadget_name>/UDC

绑定后,UDC 开始向 USB 主机发起枚举,主机将识别到该 USB 设备。

查看当前状态

cat /sys/class/udc/40080000.usb/state

常见状态值:

  • not-attached:未绑定任何 gadget。

  • configured:已枚举成功,设备正常工作。

  • suspended:已枚举但当前处于挂起状态。

停用 gadget(断开连接但保留配置)

echo "" > /sys/kernel/config/usb_gadget/<gadget_name>/UDC

解绑后设备从主机断开,但 ConfigFS 中的 gadget 配置保留,可再次使能。

备注

各子章节的 ConfigFS 示例均以 cd /mnt/config/usb_gadget/<gadget_name> 作为工作目录,因此绑定 UDC 时写作 echo 40080000.usb > UDC (相对路径),与本节的绝对路径写法等价。

如何配置 ConfigFS

每个 ConfigFS gadget 都遵循相同的目录结构。以下步骤创建 gadget 目录并配置通用目录项,功能相关的目录项在各子章节中说明。

mkdir -p /mnt/config
mount none /mnt/config -t configfs
cd /mnt/config/usb_gadget
mkdir <gadget_name> && cd <gadget_name>

echo 0x0200 > bcdUSB
echo 0x0BDA > idVendor
echo 0x8731 > idProduct

mkdir strings/0x409
echo "Realtek" > strings/0x409/manufacturer
echo "Ameba Gadget" > strings/0x409/product
cat /proc/realtek/uuid > strings/0x409/serialnumber

mkdir configs/c.1
echo 120 > configs/c.1/MaxPower
mkdir configs/c.1/strings/0x409
echo "config1" > configs/c.1/strings/0x409/configuration

各通用目录项的含义如下:

  • bcdUSB —— 以 BCD 表示的 USB 规范版本号(如 USB 2.0 为 0x0200),报告在设备描述符中。

  • bDeviceClass / bDeviceSubClass / bDeviceProtocol —— 设备级类代码。单功能 gadget 保持为 0x00``(类在接口级定义);使用 IAD 的复合设备须将 ``bDeviceClass 设为 0xEF``(Miscellaneous)、``bDeviceSubClass 设为 0x02bDeviceProtocol 设为 0x01

  • bMaxPacketSize0 —— 端点 0 的最大包大小,全速/高速通常为 64

  • idVendor / idProduct —— 用于向主机标识设备的 Vendor ID 和 Product ID,请设置为分配到的 VID/PID。

  • strings/0x409 —— 语言 0x409(美式英语)的字符串描述符,manufacturerproductserialnumber 会在主机枚举时显示。

  • configs/c.1 —— 配置目录(.1 后缀为配置编号)。每个要使能的功能都通过软链接挂到该目录下。

  • configs/c.1/MaxPower —— 设备从总线上取用的最大电流,单位 mA。

  • configs/c.1/strings/0x409/configuration —— 该配置的描述字符串。

  • functions/<func>.<inst> —— 功能实例目录(如 acm.ttyS1hid.usb0),按功能创建后用 ln -sf 链接到 configs/c.1 以将该功能加入配置。

通用目录项与功能实例配置完成后,按 如何使能与禁用 Gadget 所述将 gadget 绑定到 UDC。

透传设备方案

配置

启用 CDC ACM 类需在基础 USB 配置之上进行额外设置。用户可将其配置为内核内建功能或独立模块。

内置配置:

进入 USB Gadget Support 菜单,输入 Y 选择:

Device Drivers  --->
    USB support  --->
        USB Gadget Support  --->
            [*] USB Gadget functions configurable through configfs
            [*] Serial gadget console support
            [*] Abstract Control Model (CDC ACM)

应用 APIs

请参考 usb guide

使用示例

本示例展示如何将开发板配置为 CDC ACM 设备。

  1. 使用 USB 线缆连接开发板与 PC。

  2. 在开发板终端执行以下命令进行 Configfs 配置:

    mkdir /mnt/config
    mount none /mnt/config -t configfs
    cd /mnt/config/usb_gadget
    mkdir cdc && cd cdc
    echo 0x0200 > bcdUSB
    echo 0x02 > bDeviceClass
    echo 0x02 > bDeviceSubClass
    echo 64 > bMaxPacketSize0
    echo 0x8730 > idProduct
    echo 0x0BDA > idVendor
    mkdir strings/0x409
    echo "Realtek" > strings/0x409/manufacturer
    echo "VCOM" > strings/0x409/product
    echo "123456789AB" > strings/0x409/serialnumber
    mkdir configs/c.1
    echo 120 > configs/c.1/MaxPower
    mkdir configs/c.1/strings/0x409
    echo "acm" > configs/c.1/strings/0x409/configuration
    mkdir functions/acm.ttyS1
    ln -s functions/acm.ttyS1 configs/c.1/
    
  3. 绑定 UDC 使能 gadget(详见 Gadget 使能与禁用 章节):

    echo 40080000.usb > UDC
    
  4. 在开发板终端执行回环测试:

    在开发板终端输入发送命令:

    echo 122 > /dev/ttyACM0
    

    再执行读取命令:

    cat /dev/ttyACM0
    

    应显示 122,说明数据收发正常。

  5. 测试通过的条件:板端发送的数据可从 /dev/ttyACM0 读回,输出与发送内容一致。

备注

Windows 7 不支持 CDC ACM 设备。需要安装特定驱动程序: <sdk>/tools/image_tool/RtkUsbCdcAcmSetup.INF 。此驱动程序中的 PID 和 VID 须与 CDC ACM 设备描述符一致。

备注

如果 PC COM 无法打开,请在 <linux>/drivers/usb/gadget/function/f_acm.c 中注释以下代码以临时解决问题:

static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value,
void *data, unsigned length)
{
/* ep_queue() can complete immediately if it fills the fifo... */
spin_unlock(&acm->lock);
//status = usb_ep_queue(ep, req, GFP_ATOMIC);
spin_lock(&acm->lock);
}

人机交互设备方案

配置

启用 HID 类需在基础 USB 配置之上进行额外设置。用户可将其配置为内核内建功能或独立模块。

内置配置:

进入 USB Gadget Support 菜单,输入 Y 选择:

Device Drivers  --->
    USB support  --->
        USB Gadget Support  --->
            [*] USB Gadget functions configurable through configfs
            [*] HID function

应用 APIs

无。

使用示例

本示例展示如何将开发板配置为 HID 设备。

  1. 使用 USB 线缆连接开发板与 PC。

  2. 在开发板终端执行以下命令进行 Configfs 配置:

    键盘:
    mkdir /mnt/config
    mount none /mnt/config -t configfs
    cd /mnt/config/usb_gadget
    mkdir hid && cd hid
    echo 0x0200 > bcdUSB
    echo 0x03 > bDeviceClass
    echo 0x00 > bDeviceSubClass
    echo 0x01 > bDeviceProtocol
    echo 64 > bMaxPacketSize0
    echo 0x0BDA > idVendor
    echo 0x8730 > idProduct
    mkdir strings/0x409
    echo "Realtek" > strings/0x409/manufacturer
    echo "HID" > strings/0x409/product
    cat /proc/realtek/uuid > strings/0x409/serialnumber
    mkdir configs/c.1
    echo 120 > configs/c.1/MaxPower
    mkdir configs/c.1/strings/0x409
    echo "hid" > configs/c.1/strings/0x409/configuration
    mkdir functions/hid.usb0
    echo 1 > functions/hid.usb0/subclass
    echo 1 > functions/hid.usb0/protocol
    echo 8 > functions/hid.usb0/report_length
    echo -ne \x05\x01\x09\x06\xa1\x01\x05\x07\x19\xe0\x29\xe7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x03\x95\x05\x75\x01\x05\x08\x19\x01\x29\x05\x91\x02\x95\x01\x75\x03\x91\x03\x95\x06\x75\x08\x15\x00\x25\x65\x05\x07\x19\x00\x29\x65\x81\x00\xc0 > functions/hid.usb0/report_desc
    ln -sf functions/hid.usb0 configs/c.1/
    
  3. 绑定 UDC 使能 gadget(详见 Gadget 使能与禁用 章节):

    echo 40080000.usb > UDC
    
  4. 测试通过的条件:PC 检测到 HID 设备,开发板可通过 /dev/hidg0 节点发送输入事件。

Android 调试桥设备方案

配置

启用 ADB 类需在基础 USB 配置之上进行额外设置。用户可将其配置为内核内建功能或独立模块。

内置配置:

进入 USB Gadget Support 菜单,输入 Y 选择:

Device Drivers  --->
    USB support  --->
        USB Gadget Support  --->
            [*] USB Gadget functions configurable through configfs
            [*] Accessory gadget

应用 APIs

无。

使用示例

本示例展示如何将开发板配置为 ADB 设备。

  1. 使用 USB 线缆连接开发板与 PC。

  2. 在开发板终端执行以下命令进行 Configfs 配置:

    mkdir /mnt/config
    mount none /mnt/config -t configfs
    cd /mnt/config/usb_gadget
    mkdir acc && cd acc
    echo 0x0200 > bcdUSB
    echo 64 > bMaxPacketSize0
    echo 0xff > bDeviceClass
    echo 0x42 > bDeviceSubClass
    echo 0x01 > bDeviceProtocol
    echo 0x0BDA > idVendor
    echo 0x8730 > idProduct
    mkdir strings/0x409
    echo "Realtek" > strings/0x409/manufacturer
    echo "ADB Interface" > strings/0x409/product
    cat /proc/realtek/uuid > strings/0x409/serialnumber
    mkdir configs/c.1
    echo 120 > configs/c.1/MaxPower
    mkdir configs/c.1/strings/0x409
    echo "accessary" > configs/c.1/strings/0x409/configuration
    mkdir functions/accessory.adb
    ln -sf functions/accessory.adb configs/c.1/
    
  3. 绑定 UDC 使能 gadget(详见 Gadget 使能与禁用 章节):

    echo 40080000.usb > UDC
    
  4. 启动 ADB 守护进程:

    /bin/adbd &
    
  5. 测试通过的条件:PC 检测到 ADB 设备,可通过 adb devices 查看设备,并使用 adb shell 登录。

存储设备方案

配置

启用 MSC 类需在基础 USB 配置之上进行额外设置。用户可将其配置为内核内建功能或独立模块。

内置配置:

进入 USB Gadget Support 菜单,输入 Y 选择:

Device Drivers  --->
    USB support  --->
        USB Gadget Support  --->
            [*] USB Gadget functions configurable through configfs
            [*] Mass storage

应用 APIs

无。

使用示例

本示例展示如何将开发板配置为 MSC 设备(大容量存储设备)。

  1. 确保存储设备 /dev/mmcblk0 已准备好。

  2. 使用 USB 线缆连接开发板与 PC。

  3. 在开发板终端执行以下命令进行 Configfs 配置:

    mkdir /mnt/config
    mount none /mnt/config -t configfs
    cd /mnt/config/usb_gadget
    mkdir msc && cd msc
    echo 0x0200 > bcdUSB
    echo 0x0BDA > idVendor
    echo 0x8730 > idProduct
    mkdir strings/0x409
    echo "Realtek" > strings/0x409/manufacturer
    echo "MSC device" > strings/0x409/product
    cat /proc/realtek/uuid > strings/0x409/serialnumber
    mkdir configs/c.1
    echo 120 > configs/c.1/MaxPower
    mkdir configs/c.1/strings/0x409
    echo "msc" > configs/c.1/strings/0x409/configuration
    mkdir functions/mass_storage.0
    echo /dev/mmcblk0 > functions/mass_storage.0/lun.0/file
    echo 1 > functions/mass_storage.0/lun.0/removable
    echo 0 > functions/mass_storage.0/lun.0/nofua
    ln -sf functions/mass_storage.0 configs/c.1/
    
  4. 绑定 UDC 使能 gadget(详见 Gadget 使能与禁用 章节):

    echo 40080000.usb > UDC
    
  5. 测试通过的条件:PC 检测到 USB 存储设备,可正常读写 /dev/mmcblk0 上的数据。

音频设备方案

在 USB 设备模式下,SoC 可以通过 Linux 内核 ConfigFS Gadget 框架配置为 UAC(USB 音频类)设备。开发板可作为 USB 音频接口,主机 PC 可通过板载 3.5mm 耳机接口或扬声器播放音频。

Linux 内核中的 UAC Gadget 类实现于以下文件:

  • linux-xx/drivers/usb/gadget/function/u_audio.c

  • linux-xx/drivers/usb/gadget/function/f_uac2.c

配置

启用 UAC2 类需在基础 USB 配置之上进行额外设置。用户可将其配置为内核内建功能或独立模块。

内置配置:

进入 USB Gadget Support 菜单,输入 Y 选择:

Device Drivers  --->
    USB support  --->
        USB Gadget Support  --->
            [*] USB Gadget functions configurable through configfs
            [*] Audio Class 2.0

应用 APIs

无。

使用示例

本示例展示如何将开发板配置为 UAC2 音频设备。

  1. 使用 USB 线缆连接开发板与 PC。

  2. 在开发板终端执行以下命令进行 Configfs 配置:

    mkdir /mnt/config
    mount none /mnt/config -t configfs
    cd /mnt/config/usb_gadget
    mkdir uac2 && cd uac2
    echo 0x0200 > bcdUSB
    echo 0x00 > bDeviceClass
    echo 0x00 > bDeviceSubClass
    echo 0x00 > bDeviceProtocol
    echo 64 > bMaxPacketSize0
    echo 0x0BDA > idVendor
    echo 0x8730 > idProduct
    mkdir strings/0x409
    echo "Realtek" > strings/0x409/manufacturer
    echo "UAC2 device" > strings/0x409/product
    cat /proc/realtek/uuid > strings/0x409/serialnumber
    mkdir configs/c.1
    echo 120 > configs/c.1/MaxPower
    mkdir configs/c.1/strings/0x409
    echo "uac2" > configs/c.1/strings/0x409/configuration
    mkdir functions/uac2.0
    echo 3 > functions/uac2.0/c_chmask
    echo 48000 > functions/uac2.0/c_srate
    echo 2 > functions/uac2.0/c_ssize
    echo 3 > functions/uac2.0/p_chmask
    echo 48000 > functions/uac2.0/p_srate
    echo 2 > functions/uac2.0/p_ssize
    echo adaptive > functions/uac2.0/c_sync
    ln -sf functions/uac2.0 configs/c.1/
    
  3. 绑定 UDC 使能 gadget(详见 Gadget 使能与禁用 章节):

    echo 40080000.usb > UDC
    
  4. 测试通过的条件:PC 检测到 USB 音频设备(声卡),可通过 arecord/aplay 进行录音和播放测试。

备注

由于开发板没有板载音频 Codec,录音时采集到的数据为全零(0x00),属于预期行为。

自定义设备方案

Vendor 类支持开发自定义的 USB 设备类。

配置

启用 Vendor 类需在基础 USB 配置之上进行额外设置。用户可将其配置为内核内建功能或独立模块。

内置配置:

进入 USB Gadget Support 菜单,输入 Y 选择:

Device Drivers  --->
    USB support  --->
        USB Gadget Support  --->
            [*] USB Gadget functions configurable through configfs
            [*] Loopback and sourcesink function (for testing)

应用 APIs

无。

使用示例

本示例展示如何将开发板配置为 Vendor 设备。

  1. 使用 USB 线缆连接开发板与 PC。

  2. 在开发板终端执行以下命令进行 Configfs 配置:

    mkdir /mnt/config
    mount none /mnt/config -t configfs
    cd /mnt/config/usb_gadget
    mkdir vendor && cd vendor
    echo 0x0200 > bcdUSB
    echo 0xa4a0 > idProduct
    echo 0x0525 > idVendor
    mkdir strings/0x409
    echo "Realtek" > strings/0x409/manufacturer
    echo "Vendor" > strings/0x409/product
    echo "123456789AB" > strings/0x409/serialnumber
    mkdir configs/c.1
    mkdir configs/c.2
    echo 120 > configs/c.1/MaxPower
    echo 120 > configs/c.2/MaxPower
    mkdir configs/c.1/strings/0x409
    mkdir configs/c.2/strings/0x409
    echo "vendor1" > configs/c.1/strings/0x409/configuration
    echo "vendor2" > configs/c.2/strings/0x409/configuration
    mkdir functions/SourceSink.0
    mkdir functions/Loopback.0
    ln -sf functions/SourceSink.0 configs/c.1/
    ln -sf functions/Loopback.0 configs/c.2/
    
  3. 绑定 UDC 使能 gadget(详见 Gadget 使能与禁用 章节):

    echo 40080000.usb > UDC
    
  4. 测试通过的条件:PC 检测到 Vendor 设备(VID 0x0525 / PID 0xa4a0),可通过 usbtest 工具进行环回和源/汇测试。

复合设备方案

在 Linux ConfigFS 框架下,将多个功能类实例链接到同一配置(configs/c.1)即可实现复合 USB 设备,无需额外驱动。

配置

复合设备复用各功能类的内核配置,无需额外选项。以 CDC ACM + HID 组合为例:

内置配置:

进入 USB Gadget Support 菜单,输入 Y 选择:

Device Drivers  --->
    USB support  --->
        USB Gadget Support  --->
            [*] USB Gadget functions configurable through configfs
            [*] Serial gadget console support
            [*] Abstract Control Model (CDC ACM)
            [*] HID function

应用 APIs

无。

使用示例

本示例将开发板配置为同时提供 CDC ACM 和 HID 键盘两个功能的复合 USB 设备。

  1. 使用 USB 线缆连接开发板与 PC。

  2. 在开发板终端执行以下命令进行 Configfs 配置:

    mkdir -p /mnt/config
    mount none /mnt/config -t configfs
    cd /mnt/config/usb_gadget
    mkdir composite && cd composite
    
    # IAD 描述符:多功能设备必须将 bDeviceClass 设为 0xEF
    echo 0x0200 > bcdUSB
    echo 0xEF > bDeviceClass
    echo 0x02 > bDeviceSubClass
    echo 0x01 > bDeviceProtocol
    echo 64 > bMaxPacketSize0
    echo 0x0BDA > idVendor
    echo 0x8731 > idProduct
    
    mkdir strings/0x409
    echo "Realtek" > strings/0x409/manufacturer
    echo "Composite ACM+HID" > strings/0x409/product
    cat /proc/realtek/uuid > strings/0x409/serialnumber
    
    mkdir configs/c.1
    echo 120 > configs/c.1/MaxPower
    mkdir configs/c.1/strings/0x409
    echo "composite" > configs/c.1/strings/0x409/configuration
    
    # Function 1:CDC ACM
    mkdir functions/acm.ttyS1
    ln -sf functions/acm.ttyS1 configs/c.1/
    
    # Function 2:HID 键盘
    mkdir functions/hid.usb0
    echo 1 > functions/hid.usb0/subclass
    echo 1 > functions/hid.usb0/protocol
    echo 8 > functions/hid.usb0/report_length
    echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.usb0/report_desc
    ln -sf functions/hid.usb0 configs/c.1/
    
  3. 绑定 UDC 使能 gadget(详见 Gadget 使能与禁用 章节):

    echo 40080000.usb > UDC
    
  4. 在 PC 上确认设备枚举:

    lsusb -d 0x0BDA:0x8731 -v
    

    输出中应可见两个接口,Interface 0 为 CDC ACM,Interface 2 为 HID。

  5. 验证 ACM 接口(板端回环测试):

    在开发板终端执行发送命令:

    echo 122 > /dev/ttyACM0
    

    再执行读取命令:

    cat /dev/ttyACM0
    

    应显示 122,说明 ACM 接口数据收发正常。

  6. 验证 HID 接口(板端模拟按键):

    在开发板终端向 HID 设备节点写入一个按键报告(以 Enter 键为例):

    echo -ne '\x00\x00\x28\x00\x00\x00\x00\x00' > /dev/hidg0
    echo -ne '\x00\x00\x00\x00\x00\x00\x00\x00' > /dev/hidg0
    

    在 PC 上可观察到一次回车键输入事件。

  7. 测试通过的条件:PC lsusb 显示复合设备(含 ACM 和 HID 两个接口),/dev/ttyACM0 ACM 回环正常,/dev/hidg0 写入后 PC 收到输入事件。

备注

复合设备必须将 bDeviceClass 设为 0xEF``(Miscellaneous)、``bDeviceSubClass 设为 0x02bDeviceProtocol 设为 0x01,以使 USB 主机通过 IAD(Interface Association Descriptor)正确识别各功能类。若使用单功能类的 bDeviceClass 值,主机可能无法正确枚举所有接口。

备注

ConfigFS 复合设备的详细说明请参考 Linux 内核文档 USB Gadget configfs