wiki:linux/OTG

USB On-The-Go (OTG)

Certain devices have USB Device Controllers or Dual-Role controllers that can be used in either host mode or device mode.

This page aims to document how to use and configure USB OTG gadget devices on Linux for boards you wish to connect to a USB Host port and behave like a 'device'. See also USB_OTG

This wiki page is created for use on Gateworks Rugged and Industrial Single Board Computers Made in the USA.

Note: Newport SBC's do not support OTG/Device/Gadget modes.

USB Host Mode

A Host mode cable allows connecting to a USB device. No special configuration is necessary for this.

USB Device Mode

A Device mode cable allows connection to a USB host such as a PC.

When used in this mode, the device needs to have a 'Gadget driver' loaded which implements the personality of the device type you want.

There are several Linux gadget drivers in today's linux kernel. These can be found under the Device Drivers -> USB support -> USB Gadget Support menu:

  • g_zero (CONFIG_USB_ZERO)
  • g_audio (CONFIG_USB_AUDIO)
  • g_ether (CONFIG_USB_ETH) - implement a 'Communication Device Class' (CDC) Ethernet device to create a 'USB to Ethernet' network connection.
  • g_ncm (CONFIG_USB_G_NCM) - implement USB CDC NCM subclass standard. NCM is an advanced protocol for Ethernet encapsulation and allows grouping of several ethernet frames into one USB transfer.
  • g_mass_storage (CONFIG_USB_MASS_STORAGE) - acts as a USB Mass Storage disk driver. Its storage repository can use a regular file or a block device specified as a module parameter or sysfs option.
  • g_serial (CONFIG_USB_G_SERIAL) - behave as a ACM Serial device to create a 'USB to Serial' connection which can be used to interoperate with MS-Windows hosts or with the Linux-USB 'cdc-acm' driver.
  • g_midi (CONFIG_USB_MIDI_GADGET) - acts as a USB Audio device with one MIDI input and one MIDI output.
  • g_printer (CONFIG_USB_G_PRINTER) - channels data between the USB host and a userspace program driving the print engine.
  • g_cdc (CONFIG_USB_CDC_COMPOSITE) - provides two functions in one configuration: a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link
  • g_acm_ms (CONFIG_USB_G_ACM_MS) - provides two functions in one configuration: a USB Mass Storage device and a CDC ACM (serial port) link
  • g_multi (CONFIG_USB_G_MULTI) - A multifunction composite gadget that can provide Ethernet (RNDIS and/or CDC), mass storage, and ACM serial link interfaces
  • g_hid (CONFIG_USB_G_HID) - A Human Interface Device (HID) gadget that provides a generic interface for things such as keyboards, mice, touchscreens
  • g_webcam - A Webcam Device

Additionally The Linux Configfs (CONFIG_CONFIGFS_FS) support allows complete dynamic configuration of gadget devices from userspace in which case you can create a single configuration or multi-configuration composite device with one or more of the functions available from drivers/usb/gadget/udc/functions. See below for more details on how to use this.

Note that only one gadget driver (device personality) can be loaded at a time but there are some 'composite' gadget drivers that behave as 'composite devices' meaning they have multiple endpoints per USB device. This will seem familiar if you think of how a modern smart-phone works. Take an Android phone for example: When plugged into a host PC via micro-USB OTG, it will behave as a storage device (MTP), however if you want to have it behave as a serial debug device you have to go into the developer menu and select this option. Note that modern smartphones no longer behave as 'USB Mass Storage' devices as this protocol does not allow the device OS to access the filesystem at the same time the host PC does - instead these devices act as an MTP (​Media Transfer Protocol) device.

Note that the Vendor ID (VID) and Device ID (DID) that is presented to the USB host is configurable (see here for details)

g_ether Gadget

The g_ether gadget driver behaves as a USB-to-Ethernet dongle. Once loaded the device-mode system will add a 'usb<n>' network device which can be used the same as any other network device. On the USB host system, a similar network device will appear as long as a driver supporting the 'CDC Ethernet' standard is available.

This module can be built with additional support:

  • EEM: CDC Ethernet Emulation Model (EEM) is a newer standard that has a a simpler interface that can be used by more USB host hardware.
  • RNDIS: RNDIS support is an additional option (more CPU intensive) that may be more compatible with Windows drivers.

Example:

  • on target device (Gateworks board with OTG controller):
    modprobe g_ether
    
    • usb0 network interface appears on target (treat like any other network interface)
  • on host device (ie PC) a device with VID:PID 0525:a4a2 will appear conforming to the ​CDC Ethernet standard
    • usb0 appears on Linux host (using the cdc_ether driver)
  • module parameters can specify the VID, PID, device version, manufacturer string, product string, serialnumber
  • module parameters can specify the device and host ethernet address and whether or not to use CDC EEM mode

Linux Host Notes:

  • cdc_ether driver supports this and will create a 'usb<n>' device on the USB host

Windows Host Notes:

  • the g_ether driver is typically built with RNDIS support enabled which will make it compatible with drivers in Windows7 and above which will appear in the device manager as a 'USB Ethernet/RNDIS Gadget' and can be configured just as any other network interface.

Reference:

g_mass_storage - USB Mass Storage Device

The g_file_storage driver behaves as a USB Mass Storage device such as a USB hard-disk or USB flash drive. You can decide whether to use a 'file' as a backing store, or a block device (ie a flash partition, or a physical disk). The file/device is provided to the module via the 'file' module parameter.

If using a backing storage 'file' you must create it beforehand with its desired size. For example to create a 64MB backing store:

dd bs=1M count=64 if=/dev/zero of=/backing_file

To use this as a backing store:

modprobe g_mass_storage file=/backing_file

References:

g_serial - Serial Device Gadget

The Serial Gadget supports CDC-ACM and CDC-OBEX which can inter-operate with the MS-Windows hosts or with Linux hosts using the 'cdc-acm' driver to create a 'USB-to-Serial' connection.

Example:

  • on target device (Gateworks board with OTG controller):
    modprobe g_serial
    
  • on host device (ie PC) a USB CDC ACM device (VID:PID 0525:a4a7 by default) will appear and behave as a serial device
  • module parameters can specify the VID, PID, device version,

manufacturer string, product string, serialnumber

  • module parameters can specify whether or not to use CDC ACM, CDC OBEX, and the number of ports to create

Linux USB Host notes:

  • the cdc_acm driver will enumerate this device as '/dev/ttyACM<n>'

Windows USB Host notes:

Reference:

g_cdc - Composite Ethernet + Serial Gadget

The g_cdc gadget supports two functions in one configuration:

  • a CDC Ethernet (ECM) link (USB-to-Ethernet connection)
  • a CDC ACM (serial port) link (USB-to-Serial connection)

Example:

  • on target device (Gateworks board with OTG controller):
    modprobe g_cdc
    
  • on host device (ie PC) a USB CDC ACM device (VID:PID 0525:a4aa) will appear

Linux USB Host notes:

  • the cdc_acm driver will enumerate this device as '/dev/ttyACM<n>'
  • the cdc_ether driver will enumerate this device as a 'usb<n>' network device

Windows USB Host notes:

  • A CDC Composite Gadget device will appear in Device Manager
  • TODO: Is there a driver available that can use this in Windows? See g_multi below

g_multi - Composite Ethernet + Serial + Mass Storage Gadget

The g_multi gadget supports multiple functions in one configuration:

  • a CDC Ethernet (ECM) link
  • a CDC ACM (serial port) link
  • a USB Mass Storage device

Example:

  • on target device (Gateworks board with OTG controller):
    modprobe g_cdc
    
  • on host device (ie PC) a USB CDC ACM device (VID:PID 1d6b:0104 by default) will appear
  • module parameters can specify the VID, PID, device version, manufacturer string, product string, serialnumber
  • module parameters can specify the ethernet device and host address and queue length multiplier at high speed

Linux USB Host notes:

  • the cdc_acm driver will enumerate this device as '/dev/ttyACM<n>'
  • the cdc_ether driver will enumerate this device as a 'usb<n>' network device
  • the usb-storage driver will provide the USB Mass Storage feature

Windows USB Host notes:

  • A Multifunction Composite Gadget device will appear in Device Manager
  • see here for details on Windows configuration

References:

g_hid - Human Interface Device (HID) Gadget

The HID gadget driver provides generic emulation of USB Human Interface Devices (HID), for example keyboards, mice, touchscreens, etc

Example:

  • on target device (Gateworks board with OTG controller):
    modprobe g_hid
    
  • module parameters can specify the VID, PID, device version, manufacturer string, product string, serialnumber

References:

g_webcam - Composite USB Audio and Video Class Gadget

The g_webcam gadget driver provides a Composite USB Audio and Video Class device.

Example:

  • on target device (Gateworks board with OTG controller):
    modprobe g_webcam
    
  • on host device (ie PC) a 'Linux Foundation Webcam Gadget' device (VID:PID 1d6b:0102 by default) will appear
  • on target device (Gateworks board) a /dev/video<n> device will be created and avialable as a Video4Linux output device supporting 320/240 YUYV video
  • module parameters can specify the VID, PID, device version, manufacturer string, product string, serialnumber

Linux USB Host notes:

  • the uvcvideo driver will enumerate the device and create a /dev/video<n> video capture device

Windows USB Host notes:

  • A USB Composite device will appear in Device Manager
  • A UVC Camera device will appear under Imaging devices in the device manager and be available to capture video

g_ncm - USB CDC NCM subclass Ethernet Gadget

The g_ncm gadget driver provides a a USB CDC NCM subclass. NCM is an advanced protocol for Ethernet encapsulation, allowing grouping of several ethernet frames into one USB transfer with various alignment possibilities.

Example:

  • on target device (Gateworks board with OTG controller):
    modprobe g_ncm
    
  • on host device (ie PC) a 'Linux-USB Ethernet Gadget' device (VID:PID 0525:a4a1 by default) will appear
  • on target device (Gateworks board) a usb<n> network device will be created
  • module parameters can specify the VID, PID, device version, manufacturer string, product string, serialnumber
  • module parameters can specify the device and host ethernet addresses and the queue length multiplier used at high speeds

Linux USB Host notes:

  • the cdc_ncm driver will enumerate the device and create a network interface in /sys/class/net

Windows USB Host notes:

  • A NCM Gadget device will appear in Device Manager
  • see here for details about a Windows CDC NCM driver

ConfigFs

The Linux Configfs (CONFIG_CONFIGFS_FS) support allows complete dynamic configuration of gadget devices from userspace in which case you can create a single configuration or multi-configuration composite device with one or more of the functions available from drivers/usb/gadget/udc/functions:

  • usb_f_acm - CDC Serial (ACM - Abstract Control Model)
  • usb_f_ecm - CDC Ethernet (ECM - Ethernet Networking Control Model)
  • usb_f_eem - CDC Ethernet (EEM - Ethernet Emulation Model)
  • usb_f_fs - Filesystem
  • usb_f_hid - HID Interface
  • usb_f_mass_storage - USB Mass Storage class
  • usb_f_midi - MIDI
  • usb_f_ncm - CDC Network (NCM - Network Control Model Ethernet)
  • usb_f_obex - CDC OBEX (Object Exchange Model)
  • usb_f_phonet - CDC Phonet
  • usb_f_printer - Printer function
  • usb_f_rndis - (Remote Network Driver Interface Specification - Microsoft Ethernet over USB)
  • usb_f_serial - Generic serial function
  • usb_f_subset - CDC Subset (Ethernet with no control mechanism - just raw data transfer)
  • usb_f_uac1 - USB Audio class
  • usb_f_uac2 - USB Audio class 2.0
  • usb_f_uvc - USB Video class

Note that not all of the above kernel modules may be available depending on your kernel configuration or BSP.

Examples:

  • Create a CDC ACM Serial device:
    # mount configfs
    mount -t configfs none /sys/kernel/config
    # load libcomposite module
    modprobe libcomposite
    # create a gadget
    mkdir /sys/kernel/config/usb_gadget/g1
    # cd to its configfs node
    cd /sys/kernel/config/usb_gadget/g1
    # configure it (vid/pid can be anything if USB Class is used for driver compat)
    echo 0xabcd > idVendor
    echo 0x1234 > idProduct
    # configure its serial/mfg/product
    mkdir strings/0x409
    echo myserial > strings/0x409/serialnumber
    echo mymfg > strings/0x409/manufacturer
    echo myproduct > strings/0x409/product
    # create a config
    mkdir configs/c.1
    # configure it with attributes if needed
    echo 120 > configs/c.1/MaxPower
    # ensure function is loaded
    modprobe usb_f_acm
    # create the function (name must match a usb_f_<name> module such as 'acm')
    mkdir functions/acm.0
    # associate function with config
    ln -s functions/acm.0 configs/c.1
    # enable gadget by binding it to a UDC from /sys/class/udc
    echo 0000:01:00.0 > UDC
    # to unbind it: echo "" UDC; sleep 1; rm -rf /sys/kernel/config/usb_gadget/g1
    
  • Create a CDC ECM Ethernet device:
    # mount configfs
    mount -t configfs none /sys/kernel/config
    # load libcomposite module
    modprobe libcomposite
    # create a gadget
    mkdir /sys/kernel/config/usb_gadget/g1
    # cd to its configfs node
    cd /sys/kernel/config/usb_gadget/g1
    # configure it (vid/pid can be anything if USB Class is used for driver compat)
    echo 0xabcd > idVendor
    echo 0x1234 > idProduct
    # configure its serial/mfg/product
    mkdir strings/0x409
    echo myserial > strings/0x409/serialnumber
    echo mymfg > strings/0x409/manufacturer
    echo myproduct > strings/0x409/product
    # create a config
    mkdir configs/c.1
    # configure it with attributes if needed
    echo 120 > configs/c.1/MaxPower
    # ensure function is loaded
    modprobe usb_f_ecm
    # create the function (name must match a usb_f_<name> module such as 'ecm')
    mkdir functions/ecm.0
    # associate function with config
    ln -s functions/ecm.0 configs/c.1
    # enable gadget by binding it to a UDC from /sys/class/udc
    echo 0000:01:00.0 > UDC
    # to unbind it: echo "" UDC; sleep 1; rm -rf /sys/kernel/config/usb_gadget/g1
    
  • Create a USB Mass Storage device (with 2 LUN's 16MB each):
    # mount configfs
    mount -t configfs none /sys/kernel/config
    # load libcomposite module
    modprobe libcomposite
    # create a gadget
    mkdir /sys/kernel/config/usb_gadget/g1
    # cd to its configfs node
    cd /sys/kernel/config/usb_gadget/g1
    # configure it (vid/pid can be anything if USB Class is used for driver compat)
    echo 0xabcd > idVendor
    echo 0x1234 > idProduct
    # configure its serial/mfg/product
    mkdir strings/0x409
    echo myserial > strings/0x409/serialnumber
    echo mymfg > strings/0x409/manufacturer
    echo myproduct > strings/0x409/product
    # create configs
    mkdir configs/c.1
    mkdir configs/c.2
    mkdir configs/c.3
    # configure them with attributes if needed
    echo 120 > configs/c.1/MaxPower
    echo 120 > configs/c.2/MaxPower
    echo 120 > configs/c.2/MaxPower
    # ensure function is loaded
    modprobe usb_f_mass_storage
    # create the function (name must match a usb_f_<name> module such as 'acm')
    mkdir functions/mass_storage.0
    # create backing store(s): in this example 2 LUN's 16MB each
    dd bs=1M count=16 if=/dev/zero of=/tmp/lun0.img # 16MB
    dd bs=1M count=16 if=/dev/zero of=/tmp/lun1.img # 16MB
    # associate with partitions
    mkdir functions/mass_storage.0/lun.0
    echo /tmp/lun0.img > functions/mass_storage.0/lun.0/file
    mkdir functions/mass_storage.0/lun.1
    echo /tmp/lun1.img > functions/mass_storage.0/lun.1/file
    # associate function with config
    ln -s functions/mass_storage.0 configs/c.1
    # enable gadget by binding it to a UDC from /sys/class/udc
    echo 0000:01:00.0 > UDC
    # to unbind it: echo "" UDC; sleep 1; rm -rf /sys/kernel/config/usb_gadget/g1
    

References:

OpenWrt OTG

OpenWrt packages several of the above Linux kernel modules as packages:

  • g_ether - Kernel modules -> USB Support -> kmod-usb-eth-gadget
  • g_mass_storage - Kernel modules -> USB Support -> kmod-usb-mass-storage-gadget
  • g_serial - Kernel modules -> USB Support -> kmod-usb-serial-gadget

You must have gadget support enabled:

  • Kernel modules -> USB Support (kmod-usb-gadget)

Note that all of these packages will attempt to autoload their respective kernel module so whichever one is alphabetically first will be loaded. You can see what is loaded by looking at the current modules:

lsmod | grep g_*

OTG Mode selection

USB OTG host controllers are 'dual-role' controllers in that they can behave as a USB host or a USB peripheral. The decision on which mode to be in is typically controlled by the state of the OTG ID pin (OTG_ID) which is grounded on OTG to host cables, and left floating on OTG to device cables.

In some cases you may have a board without an OTG_ID signal where you still want to use USB OTG in device mode.

Dual-role controllers can be forced into 'host' mode or 'peripheral' mode via the device-tree 'dr_mode' property. For example to force an IMX6 OTG controller to peripheral mode add 'dr_mode = "peripheral";' to the dt such as:

&usbotg {
        vbus-supply = <&reg_5p0v>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usbotg>;
        disable-over-current;
        dr_mode = "peripheral";
        status = "okay";
};

This can be done in the bootloader, here's an example for GW54xx:

setenv fixfdt 'fdt addr ${fdt_addr}; fdt resize; fdt set /soc/aips-bus@2100000/usb@2184000 dr_mode host' # host mode
setenv fixfdt 'fdt addr ${fdt_addr}; fdt resize; fdt set /soc/aips-bus@2100000/usb@2184000 dr_mode gadget' # gadget mode
saveenv #once you have made your selection

Additionally some host controllers such as the Chips and Media controller used on the IMX6 have hooks that allow them to be configured at runtime in Linux Userspace. For example on IMX6 boards:

cat /sys/kernel/debug/ci_hdrc.0/role # see current role; default dictated by dr_mode dt property or state of OTG_ID pin if not set
echo gadget > /sys/kernel/debug/ci_hdrc.0/role # specify device mode
echo host > /sys/kernel/debug/ci_hdrc.0/role # specify host mode

Using a Non-OTG port in device mode

In some cases you can use a USB Type-A socket in device mode in a non-standard way. This can be used for example on boards that route a USB OTG controller to a Type-A socket which does not have an OTG_ID signal. In this case you need to isolate VBUS to ensure both the host and the device are not both driving it at the same time. This opportunity exists on certain Ventana boards (where the 'usbotg' host controller is enabled in the device-tree yet the signals route to a USB Type-A socket connector instead of an OTG controller).

In this case you can do the following:

  1. use a non-standard Type-A plug to Type-A plug cable and isolate the VBUS (red wire) to ensure host and device are not both driving VBUS
  2. configure the OTG controller for device-mode (see above)
  3. Load a gadget driver (see above)
Last modified 4 years ago Last modified on 03/29/2021 11:29:25 PM
Note: See TracWiki for help on using the wiki.