USB Gadget 与 Configfs

USB Gadget

A USB Linux Gadget is a device which has a UDC (USB Device Controller) and can
be connected to a USB Host to extend it with additional functions like a serial

A gadget is seen by its host as a set of configurations, each of which contains
a number of interfaces which, from the gadget’s perspective, are known as
functions, each function representing e.g. a serial connection or a SCSI disk.

Linux provides a number of functions for gadgets to use.

USB Linux Gadget是USB设备控制器作为从设备,连接到USB Host,通过 USB 来模拟其它类型的设备,比如UAC、UVC、HID设备、串口等等

CDC类
USB的CDC类是USB通信设备类 (Communication Device Class)的简称。CDC类是USB组织定义的一类专门给各种通信设备(电信通信设备和中速网络通信设备)使用的USB子类
CDC,USB Driver支持以下子类: ECM、NCM、ACM、OBEX、设备管理。

Configfs

Documentation/filesystems/configfs.rst

configfs is a ram-based filesystem that provides the converse of
sysfs’s functionality. Where sysfs is a filesystem-based view of
kernel objects, configfs is a filesystem-based manager of kernel
objects, or config_items.

Userspace-driven Kernel Object Configuration
configfs是一个基于ram的文件系统,通过对该文件系统的操作实现对内核对象的配置
Documentation/filesystems/configfs.rst

不只是USB可以通过configfs进行配置,有些子系统也可以。理论上只要实现了configfs接口的应该都行

driver/usb/gadget/configfs.c:

通过configfs_register_subsystem(&gadget_subsys);,在configfs中注册了usb gadget子系统

使用configfs配置usb gadget

配置UAC

#!/bin/bash
function start_uac2()
{
    # usb_gadget依赖于libcomposite模块
    modprobe libcomposite
    # 挂载config文件系统
    mount -t configfs none /sys/kernel/config

    # 创建g1目录,实例化一个新的gadget模板
    echo "mkdir /sys/kernel/config/usb_gadget/g1"
    mkdir -m 0770 /sys/kernel/config/usb_gadget/g1

    # 设置产品的VendorID、ProductID及USB规范版本号
    echo "Setting Vendor Product ID's and bcdDevice"
    echo 0x2207 > /sys/kernel/config/usb_gadget/g1/idVendor
    echo 0x0019 > /sys/kernel/config/usb_gadget/g1/idProduct
    # 设备版本号
    echo 0x0200 > /sys/kernel/config/usb_gadget/g1/bcdDevice
    # USB 1.1: 0x0110
    # USB 2.0: 0x0200, USB 2.1: 0x0210, USB 2.5: 0x0250
    # USB 3.0: 0x0300, USB 3.1: 0x0310, USB 3.2: 0x0320
    # echo 0x0210 > /sys/kernel/config/usb_gadget/g1/bcdUSB

    # 实例化英语ID,开发商、产品和序列号字符串写入内核
    echo "Setting English strings"
    mkdir -m 0770 /sys/kernel/config/usb_gadget/g1/strings/0x409
    echo "0123456789ABCDEF" > /sys/kernel/config/usb_gadget/g1/strings/0x409/serialnumber
    echo "rockchip"  > /sys/kernel/config/usb_gadget/g1/strings/0x409/manufacturer
    echo "USB Audio Device"  > /sys/kernel/config/usb_gadget/g1/strings/0x409/product

    # Creating Config
    echo "Creating Config"
    mkdir -m 0770 /sys/kernel/config/usb_gadget/g1/configs/c.1
    mkdir -m 0770 /sys/kernel/config/usb_gadget/g1/configs/c.1/strings/0x409
    echo "uac2" > /sys/kernel/config/usb_gadget/g1/configs/c.1/strings/0x409/configuration
    echo 500 > /sys/kernel/config/usb_gadget/g1/configs/c.1/MaxPower
        
    # bind functions
    # uac2 need to put before uvc, otherwise uvc + uac2 enumerate failed in win10
    echo "Creating UAC2 gadget functionality : uac2.0"
    mkdir /sys/kernel/config/usb_gadget/g1/functions/uac2.0
    ln -s /sys/kernel/config/usb_gadget/g1/functions/uac2.0 /sys/kernel/config/usb_gadget/g1/configs/c.1

    # Binding USB Device Controller
    echo "Binding USB Device Controller"
    echo fe800000.dwc3 > /sys/kernel/config/usb_gadget/g1/UDC
}

function stop_uac2()
{
    # Disabling the gadget
    echo "Disabling the USB gadget"
    echo "" > /sys/kernel/config/usb_gadget/g1/UDC

    # Remove functions from configurations
    rm /sys/kernel/config/usb_gadget/g1/configs/c.1/uac2.0
    # Remove strings directories in configurations
    rmdir /sys/kernel/config/usb_gadget/g1/configs/c.1/strings/0x409
    # remove the configurations
    rmdir /sys/kernel/config/usb_gadget/g1/configs/c.1

    # Remove functions (function modules are not unloaded, though)
    rmdir /sys/kernel/config/usb_gadget/g1/functions/uac2.0

    # Remove strings directories in the gadget
    rmdir /sys/kernel/config/usb_gadget/g1/strings/0x409

    # finally remove the gadget
    rmdir /sys/kernel/config/usb_gadget/g1
}

usage()
{
    echo "Usage: ./usb-gadget-uac2.sh start|stop"
    echo " options:"
    echo "    start           start uac2.0 gadget"
    echo "    stop            stop uac2.0 gadget"
}

case $1 in
start)
    start_uac2
    ;;
stop)
    stop_uac2
    ;;
*)
    usage
    exit 1
    ;;
esac
exit 0

配置adb功能

on init
    setprop sys.usb.controller "31800000.usb2"

on boot
    mount configfs none /config
    mkdir /config/usb_gadget/g1 0770 shell shell
    mkdir /config/usb_gadget/g1/strings/0x409 0770 shell shell
    write /config/usb_gadget/g1/bcdUSB 0x0200
    write /config/usb_gadget/g1/driver_match_existing_only 0
    write /config/usb_gadget/g1/idVendor 0x18d1
    write /config/usb_gadget/g1/bcdDevice 0x0223
    write /config/usb_gadget/g1/strings/0x409/serialnumber "123456abc"
    write /config/usb_gadget/g1/strings/0x409/manufacturer "XXX"
    write /config/usb_gadget/g1/strings/0x409/product "YYY"
    mkdir /config/usb_gadget/g1/functions/ffs.adb
    mkdir /config/usb_gadget/g1/configs/b.1 0770 shell shell
    mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409 0770 shell shell
    write /config/usb_gadget/g1/os_desc/b_vendor_code 0x1
    write /config/usb_gadget/g1/configs/b.1/MaxPower 500
    mkdir /dev/usb-ffs 0775 shell shell
    mkdir /dev/usb-ffs/adb 0770 shell shell
    mount functionfs adb /dev/usb-ffs/adb uid=2000,gid=2000
    setprop sys.usb.configfs 1
    setprop sys.usb.ffs.aio_compat 1
    symlink /config/usb_gadget/g1/configs/b.1 /config/usb_gadget/g1/os_desc/b.1
on property:sys.usb.config=none && property:sys.usb.configfs=1
    write /config/usb_gadget/g1/os_desc/use 0
on property:sys.usb.config=adb && property:sys.usb.configfs=1
    write /config/usb_gadget/g1/idProduct 0x4ee7

参考