Linux USB ConfigFS


Learn about the basics of USB ConfigFS and how to utilize it to create your own USB composition!

Table of Contents

  1. Summary
  2. How to Initialize USB ConfigFS
  3. USB ConfigFS Parameters
  4. Creating a USB Configuration
  5. 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/FileSoftware Defined?Multiple Instances?Comments
<base>/usb_gadgetYesNoMount-point for USB configFS files and directories.
<base>/usb_gadget/<g1>NoYesCan 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/UDCYesNoCarries the UDC device the USB gadget is binded to. The UDC string is defined within the software.
<base>/usb_gadget/g1/idVendorYesNo
<base>/usb_gadget/g1/idProductYesNo
<base>/usb_gadget/g1/functions/*YesNoObjects 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>NoYesDefines 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/*NoNoSoftlinks to USB function driver files under the “functions” folder.
USB configFS files/parameters

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/idVendorecho 0x0001 > /sys/kernel/config/usb_gadget/g1/idProductmkdir /sys/kernel/config/usb_gadget/g1/functions/mass_storage.0 mkdir /sys/kernel/config/usb_gadget/g1/functions/adb.0mkdir /sys/kernel/config/usb_gadget/g1/functions/rndis.0mkdir /sys/kernel/config/usb_gadget/g1/configs/c.1ln -s /sys/kernel/config/usb_gadget/g1/functions/mass_storage.0 /sys/kernel/config/usb_gadget/g1/configs/c.1/f1ln -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 UDCsls -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.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *