3.11.2. Use USB in Device Mode

3.11.2.1. Overview

This section describes how to use the AM62x USB module in device mode (also called peripheral or gadget mode) in Linux user space applications. USB device mode exposes one or more USB device class functions through its USB connection to the USB host. This turns the entire AM62x into a USB gadget from the USB host’s perspective.

When the USB instance is enabled in the kernel devicetree and the corresponding USB kernel drivers and USB gadget function drivers are enabled in the kernel config (see details in Porting USB), the USB module works in device mode when a selected USB gadget driver is loaded.

The Linux kernel provides many standard USB gadget drivers, such as serial, mass-storage, ethernet, printer, HID, and more. These gadget function drivers are provided in two different formats, legacy and configfs.

3.11.2.2. USB Legacy Gadgets

The legacy USB gadget driver wraps the USB descriptors to the USB gadget function into a standard kernel USB gadget driver which can be directly loaded and used. Examples showing how to use the USB legacy gadget drivers are below. For more details, please refer to the kernel USB documentation at https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/Documentation/usb?h=08.04.01.005.

USB Serial Gadget

The legacy USB serial gadget driver is named g_serial.ko (when configured and built as a kernel module). Use the following command to manually load the driver:

# modprobe g_serial

Once device node /dev/ttyGS0 is created on AM62x EVM (the index may vary), any TTY program can open this node and communicate with the USB serial port on the USB host.

Use the following command to unload the driver when it is no longer needed:

# modprobe -r g_serial

USB Mass Storage Gadget

The legacy USB mass-storage gadget driver is named g_mass_storage.ko (when configured and built as a kernel module). Use the following command to manually load the kernel module. A backend storage should be specified using the file= parameter:

# modprobe g_mass_storage file=<a-backend-storage>

The backend storage will be enumerated as /dev/sd<X> on the USB host. A host application can then access it as a regular block device.

Warning

Modifying the backend storage simultaneously from the USB host and the USB device could cause data corruption on the backend storage.

Use the following command to unload the driver when it is no longer needed:

# modprobe -r g_mass_storage

USB Ethernet Gadget

The legacy USB ethernet gadget driver is named g_ether.ko (when configured and built as a kernel module). Use the following command to manually load the driver:

# modprobe g_ether

Then network interface usb0 will be created on AM62x EVM (the index may vary). A new network interface usb<X> will also be created on the USB host. Applications on both USB host and USB device can communicate through these two network interfaces.

The mac addresses on the two network interfaces can be specified using the module parameters. For example,

# modprobe g_ether dev_addr=11:22:33:44:55:66 host_addr=66:55:44:33:22:11

Use the following command to unload the driver when it is no longer needed:

# modprobe -r g_ether

3.11.2.3. USB Configfs Gadgets

The USB descriptors and functions are already hardcoded in the legacy gadget drivers. Any change requires kernel source code modification and a kernel rebuild. On the other hand, USB gadget configfs provides the flexibility of customizing the USB descriptors and composing multi-function USB gadget drivers via Linux sysfs.

Refer to the following kernel document for details about USB configfs:

https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/Documentation/usb/gadget_configfs.rst?h=08.04.01.005

Here is an example of creating a mass_storage gadget using gadget configfs. Please ensure option CONFIGFS_FS has been enabled in the kernel config.

# init
lsmod | grep libcomposite || modprobe libcomposite
mount | grep configfs || mount -t configfs none /sys/kernel/config/usb_gadget
mkdir /sys/kernel/config/usb_gadget/g1
cd /sys/kernel/config/usb_gadget/g1

# set gadget parameters
ehco "0x1d6d" > idVendor
ehco "0x0104" > idProduct
mkdir strings/0x409
echo "0123456789" > strings/0x409/serialnumber
echo "Foo Inc" > strings/0x409/manufacturer
echo "Bar gadget" > strings/0x409/product

# create configs
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "conf1" > configs/c.1/strings/0x409/configuration

# create usb functions
mkdir functions/mass_storage.usb0
echo <a-backend-storage> > functions/mass_storage.usb0/lun.0/file
ln -s functions/mass_storage.usb0 configs/c.1

# activate
_udc=$(ls -1 /sys/class/udc | head -1)
echo "$_udc" > UDC