Device Solution
In the Linux protocol stack, USB devices are referred to as Gadgets.
In Gadget mode, the USB OTG controller can be enumerated by a USB host and respond to transfer requests.
The Gadget driver supports two configuration methods:
Configfs mode: Dynamically configure Gadget functions through a user-space file system interface. Legacy mode: Use preset configurations by loading specific kernel modules.
This section primarily covers usage in Configfs mode.
For more details on device classes, refer to the kernel documentation usb support v5.4 or usb support v6.18.
How to Activate and Deactivate Gadget
After completing the ConfigFS gadget configuration, the gadget must be bound to the UDC (USB Device Controller) to make the device visible to a USB host. This step is called activating the gadget.
List Available UDCs
ls /sys/class/udc/
The UDC name for RTL8730E is 40080000.usb.
Activate Gadget
echo 40080000.usb > /sys/kernel/config/usb_gadget/<gadget_name>/UDC
After binding, the UDC begins enumeration with the USB host, which will recognize the USB device.
Check Current State
cat /sys/class/udc/40080000.usb/state
Common state values:
not-attached: No gadget is bound.configured: Successfully enumerated; device is operating normally.suspended: Enumerated but currently suspended.
Deactivate Gadget (Disconnect Without Losing Configuration)
echo "" > /sys/kernel/config/usb_gadget/<gadget_name>/UDC
After unbinding, the device disconnects from the host, but the ConfigFS gadget configuration is retained and can be activated again.
Note
The ConfigFS examples in each sub-section use cd /mnt/config/usb_gadget/<gadget_name> as the working directory, so the UDC binding step in each example is written as echo 40080000.usb > UDC (relative path), which is equivalent to the absolute path used in this section.
How to Configure ConfigFS
Every ConfigFS gadget shares the same directory layout. The following steps create the gadget directory and set up the common entries; the function-specific entries are described in each sub-section.
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
The meaning of each common entry is as follows:
bcdUSB— USB specification release number in BCD (e.g.0x0200for USB 2.0), reported in the device descriptor.bDeviceClass/bDeviceSubClass/bDeviceProtocol— Device-level class code. Kept at0x00for a single-function gadget (class defined at interface level); a composite device using an IAD must setbDeviceClassto0xEF(Miscellaneous),bDeviceSubClassto0x02andbDeviceProtocolto0x01.bMaxPacketSize0— Maximum packet size for endpoint 0. Typically64for full/high-speed.idVendor/idProduct— Vendor ID and Product ID that identify the device to the host. Set these to your assigned VID/PID.strings/0x409— String descriptors for language 0x409 (English, US).manufacturer,productandserialnumberare shown by the host when enumerating.configs/c.1— A configuration directory (the.1suffix is the configuration number). Each function to be enabled is symlinked under this directory.configs/c.1/MaxPower— Maximum current the device draws from the bus, in mA.configs/c.1/strings/0x409/configuration— Description string of this configuration.functions/<func>.<inst>— A function instance directory (e.g.acm.ttyS1,hid.usb0). It is created per function and then linked intoconfigs/c.1withln -sfto add the function to the configuration.
After the common entries and the function instances are set up, bind the gadget to the UDC as described in How to Activate and Deactivate Gadget.
CDC ACM Device Solution
Configuration
Enabling the CDC ACM class requires additional settings on top of the basic USB configuration. Users can configure it as a kernel built-in feature or as a separate module.
Enter the USB Gadget Support menu and press Y to select:
Device Drivers --->
USB support --->
USB Gadget Support --->
[*] USB Gadget functions configurable through configfs
[*] Serial gadget console support
[*] Abstract Control Model (CDC ACM)
Configure the following options in Gadget support:
Device Drivers ---> USB support ---> USB Gadget Support ---> [M] USB Gadget functions configurable through configfs [*] Serial gadget console support [*] Abstract Control Model (CDC ACM)After loading the common USB device modules, load the CDC ACM class kernel modules.
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/u_serial.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_acm.ko
Application APIs
Refer to usb guide.
Usage Example
This example demonstrates how to configure the development board as a CDC ACM device.
Use
rtk_usb_test.shto quickly start the USB ACM device mode:sh /bin/rtk_usb_test.sh -r usbd_acmUse a USB cable to connect the development board to the PC.
Perform a loopback test on the development board terminal:
Enter the send command on the development board terminal:
echo 122 > /dev/ttyACM0Then execute the read command:
cat /dev/ttyACM0122should be displayed, indicating normal data transmission and reception.Pass criterion: The data sent from the board can be read back from
/dev/ttyACM0, and the output matches the sent content.
Note
Windows 7 does not support CDC ACM devices. You need to install a specific driver: <sdk>/tools/image_tool/RtkUsbCdcAcmSetup.INF. The PID and VID in this driver must match the CDC ACM device descriptor.
Note
If the PC COM port cannot be opened, comment out the following code in <linux>/drivers/usb/gadget/function/f_acm.c as a temporary workaround:
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 Device Solution
Configuration
Beyond Basic USB Configuration, to enable the HID class, ensure the kernel has selected HID bus support and Generic HID driver.
Device Drivers --->
HID support --->
[*] HID bus support
[*] Generic HID driver
The above configurations are enabled by default in the SDK to support ADB.
Enter the USB Gadget Support menu and select
Y:Device Drivers ---> USB support ---> USB Gadget Support ---> [*] USB Gadget functions configurable through configfs [*] Serial gadget console support [*] HID function
Configure the following options under Gadget support:
Device Drivers ---> USB support ---> USB Gadget Support ---> [M] USB Gadget functions configurable through configfs [*] HID functionAfter loading the generic USB device modules, load the kernel module for the HID class:
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_hid.ko
Application APIs
Please refer to usb guide x498.
Usage Example
This example demonstrates how to configure the development board as an HID keyboard device.
Use
rtk_usb_test.shto quickly start the USB HID device mode:sh /bin/rtk_usb_test.sh -r usbd_hidUse a USB cable to connect the development board to the PC.
After connecting to the host, communicate with the host via the device node
/dev/hidg0. The following commands send the keyboard report for the ‘a’ key to the host and then release the key:echo -ne "\x00\x00\x04\x00\x00\x00\x00\x00" > /dev/hidg0 sleep 1 echo -ne "\x00\x00\x00\x00\x00\x00\x00\x00" > /dev/hidg0
The character ‘a’ should be observed on the PC side. On Linux, you can use
evtestto verify HID events.Pass criterion: After sending the HID keyboard report, the character ‘a’ appears on the PC.
Note
Keyboard report format (8 bytes):
BYTE0: Modifier keys (Ctrl/Shift/Alt/GUI bitmask)
BYTE1: Reserved (always 0x00)
BYTE2~BYTE7: Keycode[0]~Keycode[5] (HID Usage ID)
Common key Usage IDs: a=0x04, b=0x05, Enter=0x28, Space=0x2C
ADB Device Solution
Configuration
In addition to Basic USB Configuration, enabling ADB requires enabling the ACC gadget function and the HID function in the kernel, as well as support for the Input/HID subsystem:
Enter the USB Gadget Support menu and select
Y:Device Drivers ---> Input device support ---> [*] Generic input layer HID support ---> [*] HID bus support [*] Generic HID driver USB support ---> USB Gadget Support ---> [*] USB Gadget functions configurable through configfs [*] Accessory gadget [*] HID function
Configure the following options under Gadget support:
Device Drivers --->
Input device support --->
[*] Generic input layer
HID support --->
<M> HID bus support
<M> Generic HID driver
USB support --->
USB Gadget Support --->
[*] USB Gadget functions configurable through configfs
<M> Accessory gadget
<M> HID function
After loading the generic USB device modules, load the kernel modules for ADB:
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_accessory.ko
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_hid.ko
Application APIs
Please refer to Android Open Accessory (AOA) protocol documentation
Usage Example
This example demonstrates how to configure the development board as an ADB device and have it recognized by the adb tool on a Windows PC.
Use
rtk_usb_test.shto quickly start the ADB device mode:sh /bin/rtk_usb_test.sh -r usbd_adbUse a USB cable to connect the development board to the PC.
Verify device recognition on the Windows PC command line:
adb devicesExample output:
List of devices attached 1712532505 device
Pass criterion: The device status is
devicein the output ofadb devices.
Note
A Windows PC must have the adb tool preinstalled (Android SDK Platform-Tools). The idVendor and idProduct must match the Google Accessory IDs in the ADB protocol (default values 0x18d1/0x4125).
MSC Device Solution
Configuration
In addition to the basic USB configuration, additional configuration is required to support the USB MSC class, which can be configured as a built-in feature or as a separate kernel module.
Enter the USB Gadget Support menu and press
Yto select:Device Drivers ---> USB support ---> USB Gadget Support ---> [*] USB Gadget functions configurable through configfs [*] Mass storage
Configure the following options in Gadget support:
Device Drivers ---> USB support ---> USB Gadget Support ---> [M] USB Gadget functions configurable through configfs [*] Mass storageAfter loading the common USB device modules, load the MSC class kernel modules.
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_mass_storage.ko
Application APIs
Refer to usb guide x498.
Usage Example
This example demonstrates configuring the development board as a USB MSC device using an SD card as the storage medium.
Prerequisites:
An SD card is inserted and formatted (FAT32 recommended), accessible at
/dev/mmcblk0.
Use
rtk_usb_test.shto quickly start USB MSC device mode:sh /bin/rtk_usb_test.sh -r usbd_mscConnect the development board to a PC using a USB cable.
After successful configuration, the PC will recognize a new removable disk (UDISK). Verify on the PC:
Run the following command:
lsblk # Expected: A new block device appears (e.g., /dev/sdb) mount /dev/sdb1 /mnt/usb cat /mnt/usb/test.txt # Confirm SD card content is accessible umount /mnt/usb
Test pass criteria: The PC recognizes the development board as a storage device and can read and write
files on the SD card via the USB connection.
UAC Device Solution
Configuration
Enabling the UAC2 class requires additional settings on top of the basic USB configuration. Users can configure it as a kernel built-in feature or as a separate module.
Enter the USB Gadget Support menu and press Y to select:
Device Drivers --->
USB support --->
USB Gadget Support --->
[*] USB Gadget functions configurable through configfs
[*] Audio Class 2.0
Configure the following options in Gadget support:
Device Drivers ---> USB support ---> USB Gadget Support ---> [M] USB Gadget functions configurable through configfs [M] Audio Class 2.0After loading the common USB device modules, load the UAC class kernel modules.
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/u_audio.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_uac2.ko
Application APIs
UAC Gadget devices expose an ALSA sound card interface. Refer to Linux ALSA documentation for more details.
Usage Example
This example demonstrates configuring the development board as a UAC device and verifying audio playback from the host PC.
Use
rtk_usb_test.shto quickly start USB UAC2 device mode:sh /bin/rtk_usb_test.sh -r usbd_uac2Connect the development board to a PC using a USB cable.
Confirm the ALSA devices on the board:
cat /proc/asound/cards # Expected output: # 0 [Amebasnd ]: Ameba-snd - Ameba-snd # 1 [UAC2Gadget ]: UAC2_Gadget - UAC2_Gadget
Start audio loopback (USB capture to codec playback):
alsaloop -C hw:1,0 -P hw:0,0 -f S16_LE -r 48000 -c 2 </dev/null >/dev/null 2>&1 & pidof alsaloop
Note
alsaloopis provided by thealsa-utilspackage. AddIMAGE_INSTALL:append = " alsa-utils"tolocal.confto include it in the Yocto firmware. After rebuilding the firmware, manually sync the rootfs:cp build_xx/tmp/deploy/images/xx/*.rootfs.squashfs images/rootfs.imgVerify the USB audio device on the host PC:
Run the following commands:
# Confirm USB device lsusb | grep 0bda # Expected: Bus XXX Device YYY: ID 0bda:8730 Realtek Semiconductor Corp. UAC2 device # Confirm ALSA device aplay -l | grep uac2 # Expected: card 1: device [UAC2 device], device 0: USB Audio # Recording test (5 seconds) arecord -D plughw:CARD=1,DEV=0 -f S16_LE -r 48000 -c 2 -d 5 /tmp/uac2_test.wav
Parameter description:
-D plughw:CARD=1,DEV=0: Use the ALSA plugin device, Card 1, Device 0. -f S16_LE: Sample format, 16-bit signed little-endian. -r 48000: Sample rate 48000 Hz. -c 2: Number of channels 2 (stereo). -d 5: Recording duration 5 seconds.
# Playback test (audio output through the development board 3.5mm jack) aplay -D plughw:CARD=1,DEV=0 /tmp/uac2_test.wav
Parameter description:
-D plughw:CARD=1,DEV=0: Use the ALSA plugin device, Card 1, Device 0.
Note
The c_sync attribute must be set to adaptive. The dwc2 controller does not support async
feedback endpoints.
Without an audio codec bridge, captured audio data will be all zeros. This is expected behavior.
Speaker volume may be too high by default. Use the amixer cset command to adjust the volume.
Vendor Device Solution
Configuration
In addition to the basic USB configuration, additional configuration is required to support the USB Vendor class driver. It can be configured as a built-in feature or as a separate kernel module.
Enter the USB Gadget Support menu and press
Yto select:Device Drivers ---> USB support ---> USB Gadget Support ---> [*] USB Gadget functions configurable through configfs [*] Loopback and sourcesink function (for testing)
Configure the following options in Gadget support:
Device Drivers ---> USB support ---> USB Gadget Support ---> [M] USB Gadget functions configurable through configfs [*] Loopback and sourcesink function (for testing)After loading the common USB device modules, load the Vendor class kernel modules.
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/udc-core.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_ss_lb.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/libcomposite.ko
Application APIs
None.
Usage Example
This example configures a USB Composite Device via configfs, containing two USB Configurations:
Configuration 1 (configs/c.1) provides the SourceSink test function:
ln -s functions/SourceSink.0 configs/c.1/
Configuration 2 (configs/c.2) provides the Loopback test function:
ln -s functions/Loopback.0 configs/c.2/
After USB enumeration completes, both configurations are presented to the host. If the host does not explicitly select a configuration, it typically defaults to Configuration 1, so the device operates in SourceSink mode by default.
Configuration Switching
To test the Loopback function in Configuration 2, satisfy any of the following conditions:
Bind the Loopback function to configs/c.1 before enumeration.
Have the host explicitly send SET_CONFIGURATION(2).
Re-enumerate the gadget by unbinding/binding the UDC.
For example, in a user-space application, you can switch the configuration via libusb_set_configuration():
libusb_open(dev, &handle);
libusb_set_configuration(handle, 2); /* Switch to configs/c.2 (Loopback) */
After switching, run testusb to execute the corresponding Loopback test cases.
Note
The USB gadget side cannot force a default configuration; the configuration is selected by the host during enumeration.
If the host does not explicitly send
SET_CONFIGURATION, it typically defaults to Configuration 1.After modifying the configuration or function bindings in configfs, you must re-enumerate the device
(e.g., unbind/bind the UDC) for the changes to take effect.
The term “default mode” in this document refers to the host’s de facto selection of Configuration 1,
not an active choice by the gadget.
The following steps demonstrate testing the Gadget Vendor-class functionality:
Use
rtk_usb_test.shto quickly start USB Vendor device mode:sh /bin/rtk_usb_test.sh -r usbd_vendorConnect the development board to the USB host.
Run host-versus-device Vendor interaction tests (with the
testusbtool):Function
sourcesink
loopback
Configuration setup
ln -s functions/Loopback.0 configs/c.1/
ln -s functions/SourceSink.0 configs/c.2/
Host console command
testusb -a -c1 -tx -s256 -g32 -v1
testusb -a -c1 -t30 -s256 -g32 -v1
Device console cmd
Not required
Not required
Note
In the host test commands:
Case 30 (
-t30) is dedicated to Loopback testing.Cases 0~29 (
-tx, x=0..29) are used for SourceSink testing; parameters can be adjusted as needed.The
-cparameter indicates the number of iterations, not the USB Configuration index.
Composite Device Solution
In the Linux ConfigFS framework, linking multiple function instances to the same configuration (configs/c.1) implements a composite USB device without additional drivers.
Configuration
A composite device reuses the kernel configuration of each function class and requires no additional options. Using a CDC ACM + HID combination as an example:
Enter the USB Gadget Support menu and press Y to select:
Device Drivers --->
USB support --->
USB Gadget Support --->
[*] USB Gadget functions configurable through configfs
[*] Serial gadget console support
[*] Abstract Control Model (CDC ACM)
[*] HID function
Configure the following options in Gadget support:
Device Drivers ---> USB support ---> USB Gadget Support ---> [M] USB Gadget functions configurable through configfs [*] Serial gadget console support [*] Abstract Control Model (CDC ACM) [*] HID functionAfter loading the common USB device modules, load the function-specific kernel modules.
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/u_serial.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_acm.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_hid.ko
Application APIs
None.
Example
This example configures the board as a composite USB device that simultaneously provides CDC ACM and HID keyboard functions.
Connect the board to a PC with a USB cable.
Run the following commands in the board terminal to configure via 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/
Bind the UDC to activate the gadget (see Activate and Deactivate Gadget):
echo 40080000.usb > UDCVerify device enumeration on the PC:
lsusb -d 0x0BDA:0x8731 -vThe output should show two interfaces: Interface 0 is CDC ACM, Interface 2 is HID.
Verify the ACM interface (loopback test on the board):
In the board terminal, run the send command:
echo 122 > /dev/ttyACM0Then run the receive command:
cat /dev/ttyACM0The output should show
122, confirming the ACM interface is transmitting and receiving correctly.Verify the HID interface (simulate a key press on the board):
In the board terminal, write a key report to the HID device node (using the Enter key as an example):
echo -ne '\x00\x00\x28\x00\x00\x00\x00\x00' > /dev/hidg0 echo -ne '\x00\x00\x00\x00\x00\x00\x00\x00' > /dev/hidg0
A Return key input event should be observed on the PC.
Pass criteria: PC
lsusbshows a composite device with both ACM and HID interfaces;/dev/ttyACM0ACM loopback works correctly; writing to/dev/hidg0triggers an input event on the PC.
Note
A composite device must set bDeviceClass to 0xEF (Miscellaneous), bDeviceSubClass to 0x02, and bDeviceProtocol to 0x01 so that the USB host correctly identifies each function class via IAD (Interface Association Descriptor). Using the bDeviceClass value of a single function class may prevent the host from enumerating all interfaces correctly.
Note
For more details on ConfigFS composite devices, refer to the Linux kernel documentation USB Gadget configfs.