USB Gadget/Configfs
The Linux kernel USB gadget subsystem features a configfs
interface, to create and parametrise USB gadgets at runtime, through creating directories, echo'ing values into special files, and creating symlinks. This can be done directly on the shell (for experiments or debugging), or via any script or compiled program. It can completely replace the legacy way of creating gadgets via loading modules with preconfigured setups (like g_ether
). While it might be more elaborate to type initially than a mere modprobe g_ether
, it provides more flexibility, allows multiple instances and arbitrary combinations of functions (like two serial lines and a mass storage device), and can be easily scripted.
The USB gadget configfs is not Allwinner specific, but a generic Linux kernel feature, and can be used on any board that supports USB device functionality. Consequently the instructions below are also not sunxi specific.
Example (to create a serial gadget)
This is an example to give an overview of how the configfs method works. For details and prerequisites see below.
# mountpoint -q /sys/kernel/config || mount -t configfs configfs /sys/kernel/config # mkdir /sys/kernel/config/usb_gadget/g1 # cd /sys/kernel/config/usb_gadget/g1 # echo 0x1d6b > idVendor # Linux foundation # echo 0x0104 > idProduct # Multifunction Composite Gadget # mkdir strings/0x409 # US English # echo Allwinner > strings/0x409/manufacturer # echo "Serial ACM gadget" > strings/0x409/product # mkdir configs/c.1 # mkdir functions/acm.ser0 # "acm" selects the functionality, ".ser0" tags the instance # ln -s functions/acm.ser0 configs/c.1 # basename /sys/class/udc/* > UDC # activate the gadget, assuming one USB device controller, on sunxi typically: musb-hdrc.2.auto # # echo "Test" > /dev/ttyGS0 # # echo "" > UDC # deactivate the gadget
Linux kernel config requirements
To make use of the USB gadget configfs interface, on top of the USB OTG hardware driver (CONFIG_USB_MUSB_SUNXI
), you need a few options in the kernel config:
CONFIG_CONFIGFS_FS
: the general configfs feature. Enabled by arm64's defconfig and arm's multi_v7_defconfig, but not by sunxi_defconfig.CONFIG_USB_CONFIGFS
: the USB gadget specific configfs functionality. Enabled by arm64's defconfig and arm's multi_v7_defconfig, but not by sunxi_defconfig.CONFIG_USB_CONFIGFS_xxx
: the USB device specific functionality, like ACM, MASS_STORAGE. The most common are enabled by arm64/defconfig and multi_v7_defconfig.CONFIG_USB_CONFIGFS_F_xxx
: another set of USB device specific functionality, including HID, AUDIO(UAC), or UVC.
You can compile those options into the kernel (=y) or use a module (=m), there is little difference, as the functionality will be configured at runtime.
Runtime configuration of USB gadgets
The gadget(s) to use and their parameters are configured at runtime, through files and directories. The example above should be mostly self-explanatory, just some comments:
- The toplevel directory can be any unique name, most examples use "g1" and keep increasing the number for subsequent gadgets.
- The configuration name in the config/ directory (c.1 above) must end with a dot and a number, to provide the configuration index.
- Use the Linux foundation reserved USB vendor (0x1d6b) and product IDs (0x0104), unless you have reserved your own, or try to mimic a very specific USB device (though this is not recommended).
- 0x409 is the language identifier for US English, typically that's the only language provided and also queried on the host side.
- The strings echo'ed into the
manufacturer
andproduct
files will often be shown on the host side. A Linux system might use those to create speaking names or links, like udev does for serial devices, like/dev/serial/by-id/usb-Allwinner_Serial_ACM_gadget-if00
. - The name of the directory created under functions/ consists of two parts: the USB device functionality to use (the gadget driver), and a tag, separate by a dot. The most common driver names are:
- acm: CDC serial communication driver, originally for modems, most compatible on the host side. Uses three endpoints (RX, TX, config).
- gser: generic serial driver, with just two endpoints. Requires either specific vendor and product IDs, or the selected ones to be echoed into
/sys/bus/usb-serial/drivers/generic/new_id
on the host side. - mass_storage: USB mass storage driver, for emulating hard disks, CD-ROMs or USB pen drive functionality.
- hid: Human Interface Device, so keyboards, mice, joysticks, or any custom device with buttons and controls.
- The full list of possible gadget drivers can be queried from a kernel source directory:
$ git grep -h DECLARE_USB_FUNCTION_INIT drivers/usb/gadget/function
. - The string to echo into the
UDC
file, to activate the gadget, is the USB hardware device driver name, as listed in/sys/class/udc/
on the device.