Learn about the basics of USB ConfigFS and how to utilize it to create your own USB composition!
Table of Contents
- Summary
- How to Initialize USB ConfigFS
- USB ConfigFS Parameters
- Creating a USB Configuration
- Trigger USB Enumeration
Summary

As seen in the diagram, the USB configFS resides alongside the USB composite driver. The USB composite driver is the standard interface which interacts with the UDC core SW layers. This post won’t go over the details on USB composite, and focus solely on USB configFS, but there are callbacks registered between USB configFS and UDC core that utilize USB composite.
The basis and backbone behind USB configFS is utilizing the configFS filesystem, in order to define USB gadget parameters using files, directories, and links. The implementation comprises of the following:
- ConfigFS
- File Directory: fs/configfs/dir.c
- Comments:
- Filesystem driver that enables file and link creation for different functionalities, such as USB.
- USB ConfigFS
- File Directory: drivers/usb/gadget/configfs.c
- Comments:
- Registers USB configFS callbacks to the configFS filesystem. Exposes different configFS files to userspace/application, in order to configure the USB configuration. This entity interacts closely with USB composite.
How to Initialize USB ConfigFS
Since USB configFS is a filesystem, applications/users can use file commands to initialize an empty instance.
# mounts the configFS filesystem
mount -t configfs none /sys/kernel/config
# initialize USB configFS
mkdir /sys/kernel/config/usb_gadget
mkdir /sys/kernel/config/usb_gadget/g1
Once the “g1” directory is created, users will find files and directories already present within it. Technical details and code references for interested folks can be found in the Technical Details section.
Sample USB ConfigFS Layout:

USB ConfigFS Parameters
There are several USB configFS parameters throughout the hierarchy, but there are only a few that need to be populated in order to trigger USB enumeration.
Base Directory = /sys/kernel/config/
Directory/File | Software Defined? | Multiple Instances? | Comments |
---|---|---|---|
<base>/usb_gadget | Yes | No | Mount-point for USB configFS files and directories. |
<base>/usb_gadget/<g1> | No | Yes | Can define multiple USB gadget instances. Each instance will have its own set of files and directories. “g1” can be named differently. |
<base>/usb_gadget/g1/UDC | Yes | No | Carries the UDC device the USB gadget is binded to. The UDC string is defined within the software. |
<base>/usb_gadget/g1/idVendor | Yes | No | |
<base>/usb_gadget/g1/idProduct | Yes | No | |
<base>/usb_gadget/g1/functions/* | Yes | No | Objects within the “functions” directory define the available USB function drivers available. Examples can be: – ncm.<0> – ffs.<adb> – mass_storage.<0> Function drivers are identified with software defined strings when utilizing USB configFS. |
<base>/usb_gadget/g1/configs/<c.1> | No | Yes | Defines a set of USB functions that are included in your USB configuration. USB devices can have multiple USB configurations (if required) |
<base>/usb_gadget/g1/configs/c.1/* | No | No | Softlinks to USB function driver files under the “functions” folder. |
The above table highlights the bare minimum settings that will need to be added for defining a USB configuration, and binding to the USB UDC.
Creating a USB Configuration
Once initializing USB configFS, the following code snippet can be used to initialize a connection with the host.
It creates a USB device that exposes a USB composition which includes:
echo 0xa410 > /sys/kernel/config/usb_gadget/g1/idVendor
echo 0x0001 > /sys/kernel/config/usb_gadget/g1/idProduct
mkdir /sys/kernel/config/usb_gadget/g1/functions/mass_storage.0
mkdir /sys/kernel/config/usb_gadget/g1/functions/adb.0
mkdir /sys/kernel/config/usb_gadget/g1/functions/rndis.0
mkdir /sys/kernel/config/usb_gadget/g1/configs/c.1
ln -s /sys/kernel/config/usb_gadget/g1/functions/mass_storage.0
/sys/kernel/config/usb_gadget/g1/configs/c.1/f1
ln -s /sys/kernel/config/usb_gadget/g1/functions/adb.0
/sys/kernel/config/usb_gadget/g1/configs/c.1/f2
- USB VID: 0xa410
- USB PID: 0x0001
- USB Configuration #1
- USB Interface (function) #1 – USB mass storage
- USB Interface (function) #2 – USB Android Debug Bridge (ADB)
Trigger USB Enumeration
After setting up the USB configuration, the device can now attempt to enumerate with the host. In terms of USB, the USB device controller (UDC) is the hardware which initiates and handles device mode operations. For the device to be able to connect to a host, the USB software must have a UDC driver enabled.
Users can check if there is an available UDC by looking at the following directory:
# check for any available UDCs
ls -l /sys/class/udc
If there is an available UDC, this will be the string users will echo to the UDC configfs file.
# USB configFS currently has no associated UDC
root@raspberrypi0-wifi:/sys/kernel/config/usb_gadget/g1# cat UDC
# check for available UDCs
root@raspberrypi0-wifi:/sys/kernel/config/usb_gadget/g1# ls -l /sys/class/udc
lrwxrwxrwx 1 root root 0 Jan 4 07:58 20980000.usb -> ../../devices/platform/soc/20980000.usb/udc/20980000.usb
# trigger USB enumeration on the desired UDC
root@raspberrypi0-wifi:/sys/kernel/config/usb_gadget/g1# echo 20980000.usb > UDC
root@raspberrypi0-wifi:/sys/kernel/config/usb_gadget/g1# cat UDC
20980000.usb
Once a valid UDC is written, the PC/host should now have a device appear. In the previous examples, users would see a device that includes mass storage + adb interfaces/functions.
Leave a Reply