3.9.2. Use USB in Device Mode¶
3.9.2.1. Overview¶
This section describes how to use the AM64x 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 AM64x 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.
Warning
The Jumper J23 on the AM64x GPEVM (which is next to the USB micro-AB receptacle J24), should be left open for the USB module to work in device mode. Closing Jumper J23 forces the USB module to host-only mode.
Note
Before running any command listed below, please ensure the USB receptacle J24 has been connected to a USB host using a USB micro-B-to-type-A cable.
3.9.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 AM64x
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
AM64x 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.9.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:
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