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.

SoC UDC
at91sam9x5 500000.gadget
sam9x60 500000.gadget
sama5d3 500000.gadget
sama5d4 400000.gadget
sama5d2 300000.gadget
r28 - 09 Nov 2023 - 13:19:57 - AndreiSimion
 
Linux & Open Source for AT91 Microchip Microprocessors

Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.

Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries.

Microchip® and others, are registered trademarks or trademarks of Microchip Technology Inc. and its subsidiaries. This site is powered by the TWiki collaboration platform

Arm® and others are registered trademarks or trademarks of Arm Limited (or its affiliates). Other terms and product names may be trademarks of others.

Ideas, requests, contributions ? Connect to LinksToCommunities page.

Syndicate this siteRSS ATOM