USB Gadget Configuration
Introduction
This page is mainly about how to configure USB Gadget on Linux kernel. There are two ways to configure the USB Gadget framework: from within Linux kernel or from user space using ConfigFS.
1. Problem statement
For both options, the USB stack decides the order in which the endpoints are enabled and most of the time the endpoints are not enabled in the order required by the SoC datasheet (DPRAM Management section - “ Endpoints can only be allocated in ascending order, from the endpoint 0 to the last endpoint to be allocated. The user shall therefore configure them in the same order.”) To solve this problem two possible solutions are implemented in the driver and are selected by the value of fifo_mode variable as follows:
fifo_mode = 0 is used to let the driver autoconfigure the endpoints. In this case 2 banks are allocated so that they could be used as isochronous endpoints. Only one bank is allocated for the rest of the endpoints. If unsure use this option as default.
fifo_mode = value different than 0 means that a predefined user optimized configuration is to be used by loading it form a table. The data structure that defines the table is the following:
struct usba_fifo_cfg { u8 hw_ep_num; u16 fifo_size; u8 nr_banks; };
hw_ep_num - is the endpoint number as assigned by datashet (it’s an ascending value starting from 0).
fifo size - is the maximum fifo size that will be used by an application.
nr_banks - is the maximum number of banks used by application. Possible values are 1, 2 and 3 for isochronous endpoints. Having more banks will increase performance of the application but will consume more USBA internal DPRAM memory.
For example for fifo_mode = 3 the following configuration is loaded:
static struct usba_fifo_cfg mode_3_cfg[] = { { .hw_ep_num = 0, .fifo_size = 64, .nr_banks = 1, }, { .hw_ep_num = 1, .fifo_size = 1024, .nr_banks = 2, }, { .hw_ep_num = 2, .fifo_size = 512, .nr_banks = 2, }, { .hw_ep_num = 3, .fifo_size = 512, .nr_banks = 2, }, { .hw_ep_num = 4, .fifo_size = 512, .nr_banks = 2, }, { .hw_ep_num = 5, .fifo_size = 512, .nr_banks = 2, }, { .hw_ep_num = 6, .fifo_size = 512, .nr_banks = 2, }, };
All fifo_mode configurations are declared in atmel_usba_udc.c file. The version used on 4.9 kernel can be accessed at the following link: https://github.com/linux4sam/linux-at91/blob/linux-4.9-at91/drivers/usb/gadget/udc/atmel_usba_udc.c#L348
Please refer to the SoC datasheet for more informations.
How to configure fifo_mode parameter
The default fifo_mode=0 should be fine for most configurations. If needed, the fifo_mode parameter can be changed by adding it to the kernel command line. For example if one wants to configure fifo_mode to 3 the following command must be appended to kernel command line.
atmel_usba_udc.fifo_mode=3
One way to accomplish this is by editing the bootargs environment variable from u-boot using editenv command.
=> editenv bootargs edit: console=ttyS0,115200 root=/dev/mmcblk1p1 rw rootfstype=ext4 rootwait atmel_usba_udc.fifo_mode=3
2. USB Gadget precomposed configurations from within Linux kernel
This option configures the gadget directly from the kernel config using precomposed configuration. The are multiple options here from simple devices like CDC ACM, Mass storgae, RNDIS, etc. to composite devices like Ethernet + ACM. In this section we will present how to configure a composite Ethernet + ACM device.
Configurations in Kernel
Atmel USBA hardware driver must be enabled in kernel configuration. Entering Linux source directory:
make menuconfig Device Drivers > USB support > USB Gadget Support > USB Peripheral Controller --> Atmel USBA Device Drivers > USB support > USB Gadget Support --> USB Gadget precomposed configurations (<choice> [=m])
The following configs will be enabled in .config
CONFIG_USB_GADGET=y CONFIG_USB_CDC_COMPOSITE=m The following will be selected automatically: CONFIG_USB_LIBCOMPSITE[=m], USB_U_SERIAL[=m], USB_U_ETHER[=m], USB_F_ACM[=m], USB_F_ECM[=m]
3. USB Gadget configured through ConfigFS from user space at runtime
USB Gadget ConfigFS is an interface that allows definition of arbitrary functions and configurations to define an application specific USB composite device from userspace. The problem with this approach is that the gadget
Configurations in Kernel
Atmel USBA hardware driver must be enabled in kernel configuration. Entering Linux source directory:
make menuconfig Device Drivers > USB support > USB Gadget Support > USB Peripheral Controller --> Atmel USBA Device Drivers > USB support > USB Gadget Support --> USB Gadget Drivers --> USB functions configurable through configfs
The following configs will be enabled in .config
CONFIG_USB_GADGET=y CONFIG_USB_CONFIGFS=m CONFIG_USB_CONFIGFS_...=y for various function drivers like: CONFIG_USB_CONFIGFS_ACM, CONFIG_USB_CONFIGFS_RNDIS, CONFIG_USB_CONFIGFS_MASS_STORAGE, CONFIG_USB_CONFIGFS_F_HID
Building CONFIG_USB_CONFIGFS as a module will need to load it at run time:
modprobe libcomposite
Applications
Simple USB Gadget script
The following script can be used to initialize a simple USB Gadget composite device (CDC ACM+RNDIS) from user space:
#! /bin/sh modprobe libcomposite mount -t configfs none /sys/kernel/config cd /sys/kernel/config/ cd usb_gadget mkdir g1 cd g1 echo "0x04D8" > idVendor echo "0x1234" > idProduct mkdir strings/0x409 echo "0123456789" > strings/0x409/serialnumber echo "Microchip Technology, Inc." > strings/0x409/manufacturer echo "Linux USB Gadget" > strings/0x409/product mkdir functions/rndis.usb0 mkdir functions/acm.usb0 mkdir configs/c.1 mkdir configs/c.1/strings/0x409 echo "CDC ACM+RNDIS" > configs/c.1/strings/0x409/configuration ln -s functions/rndis.usb0 configs/c.1 ln -s functions/acm.usb0 configs/c.1 echo "300000.gadget" > UDC
The string that needs to be written in the UDC is dependent on the address at which the usb device is mapped . Different SoC have different addresses. The address is described in the device tree of the SoC / Board or in the datasheet.
| |||||||||||||
Related Topics
Boards
Sama5d29Curiosity
Sam9x75Curiosity
Sam9x60Curiosity
Sama5d2icp
Sam9x60EK
Sama5d27WLSom1EK
Sama5d27Som1EK
Sama5d2PtcEK
Sama5d2Xplained
Sama5d3xek
Sama5d3Xplained
Sama5d4Xplained
Sama5d4ek
AT91sam9x5-ek,
other AT91SAM9 boards
Components
Kernel
linux 4.4
linux 4.9
linux 4.14
linux 4.19
linux 5.4,
linux 5.10
linux 5.15
linux 6.1
linux 6.6
Summary
Configure AT91 USB Gadget on Linux and Endpoint order management (composite USB)