Skip to main content
Version: BSP 7.x.y

USB Host Mode (Linux)

Introduction

The USB (Universal Serial Bus) standard specifies two possible roles:

  • USB Host: The device controls the USB bus, provides power and manages communication with the peripherals. A USB Bus can only have one host connected to it. In most cases a host PC or controlling embedded devices act in Host Mode.
  • USB Peripheral/Device/Function: The device acts as a peripheral, and responds to commands from the host. A USB Bus can have multiple peripherals connected to it. Some examples are boards emulating a USB flash drive, or a network adapter.

This article guides you on how to use Toradex System-on-Modules (SoMs) as USB Hosts. For information on using our SoMs in Peripheral Mode, refer to USB Device Mode (Linux).

All Toradex SoMs provide one or more USB Host ports which allow connecting USB devices.

Some ports can take both roles, depending on HW/SW configuration they can switch between host and device role. More info can be found here: USB Device Mode (Linux).

USB Protocol Structure

The USB protocol organizes devices in a tree structure. To understand and manage USB devices, it is useful to be familiar with the USB terminology and structure:

  • USB Bus: Consists of a USB Host and all the Peripherals connected to it, directly or indirectly.
  • USB Host: The device that controls the USB bus, provides power and manages communication with the peripherals. A USB Bus can only have one host connected to it. In most cases a host PC or controlling embedded devices act in Host Mode.
  • USB Peripheral/Device: A device acts as a peripheral, and responds to commands from the host. A USB Bus can have multiple peripherals connected to it. Some examples are boards emulating a USB flash drive, or a network adapter.
  • USB Hub: A device that expands one USB port into multiple ports.
  • USB Root Hub: A Hub integrated into the Host controller. Note that a Host can provide multiple Root Hubs.

The USB bus generally follows a structure like the scheme below. The Root Hub Controller is a driver installed in the host device (your SoM, in this case), and in this example it provides two Root Hubs, each with their own peripheral devices connected. In this example, an external Hub is also connected to Root Hub 1, and the Host can also control Device 3, which is connected to the external hub.

Root Hub Controller (Host)
├── Root Hub 1
│   ├── Device 1
│   ├── Device 2
│   └── Hub (external)
│   └── Device 3
└── Root Hub 2
└── Device 4

The following sections show you how to manage and control USB peripherals on Toradex SoMs.

Manage USB Devices

Using Toradex SoMs as Host USBs is similar to how it's generally done on desktop Linux environments.

For the examples shown below, we used the following setup:

  • A Verdin iMX8M Mini on a Dahlia Carrier Board.
  • A mass storage device connected to the Dahlia's X3 connector
  • An External Hub connected to the Dahlia's X4 connector.
  • A keyboard and mouse connected to ports 3 and 4 of the External Hub

To see the connected USB devices, use lsusb:

# lsusb | sort
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0951:162d Kingston Technology DataTraveler 102
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 0424:2744 Standard Microsystems Corp. Hub
Bus 002 Device 003: ID 1a40:0101 Terminus Technology Inc. Hub
Bus 002 Device 004: ID 0424:2740 Standard Microsystems Corp.
Bus 002 Device 005: ID 0dc6:3100 Precision Squared Technology Corp.
Bus 002 Device 006: ID 0458:0036 KYE Systems Corp. (Mouse Systems) Pocket Mouse LE

To see the connected devices with a tree-like USB structure, pass the flag -t:

# lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ci_hdrc/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 2: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 3: Dev 5, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
|__ Port 4: Dev 6, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
|__ Port 4: Dev 4, If 0, Class=Vendor Specific Class, Driver=, 480M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ci_hdrc/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=usb-storage, 480M

In the previous commands, we highlighted the actual peripheral devices connected to the board (the keyboard, mouse and mass storage device).

Note that the output shows a hub connected to the root hub of Bus 02, and a second hub connected to the first, which is where the keyboard and mouse are connected. These hubs correspond to the following: The root hub is from the SoM itself, the first hub is the USB Hub of the Dahlia carrier board (connector X4), the second hub is the external hub we connected to X4, and the keyboard and mouse are connected to it.

Configure USB speed

When you connect a USB peripheral to the host, the host initiates a negotiation protocol. Through this protocol, the devices define a communication speed they can both work with.

You can configure a maximum speed for the host when negotiating with a newly connected USB Device. For instructions on how to configure the USB speed, refer to USB 2.0 High Speed (480Mbps)

Switch the Power of USB Hubs

Our BSP packages include the uhubctl tool, which allows you to switch the power of USB downstream ports. You can also toggle the root hub's power, if the one on your SoM has power-switch control. For more information, check out uhubctl's README.

Run uhubctl to show only the USB hubs that can be toggled on/off:

# uhubctl 
Current status for hub 2-1 [0424:2744 Microchip Tech USB2744, USB 2.10, 4 ports]
Port 1: 0100 power
Port 2: 0503 power highspeed enable connect [1a40:0101 USB 2.0 Hub]
Port 3: 0100 power
Port 4: 0503 power highspeed enable connect [0424:2740 Microchip Tech Hub Controller]
Current status for hub 2 [1d6b:0002 Linux 4.14.170-4.0.0-devel+git.5c643afa32be ehci_hcd EHCI Host Controller ci_hdrc.1]
Port 1: 0503 power highspeed enable connect [0424:2744 Microchip Tech USB2744, USB 2.10, 4 ports]
Current status for hub 1 [1d6b:0002 Linux 4.14.170-4.0.0-devel+git.5c643afa32be ehci_hcd EHCI Host Controller ci_hdrc.0]
Port 1: 0503 power highspeed enable connect [0951:162d Kingston DataTraveler 102 001372877298BB31C0000009]

From this output, the following hubs can be toggled on/off:

  • Root hub 1
  • Root hub 2
  • Hub 2-1 (The hub connected to port 1 of root hub 2)

Notice that the external hub connected to X4 can not be switched on/off, and thus it doesn't appear in the output of uhubctl.

To switch off the power of a USB Hub, use the uhubctl command with the -a (action) flag. Specify also the USB Hub with the -l (location) flag and the port with -p (port):

# uhubctl -l 2-1 -p 2 -a off
Current status for hub 2-1 [0424:2744 Microchip Tech USB2744, USB 2.10, 4 ports]
Port 2: 0503 power highspeed enable connect [1a40:0101 USB 2.0 Hub]
Sent power off request
New status for hub 2-1 [0424:2744 Microchip Tech USB2744, USB 2.10, 4 ports]
Port 2: 0000 off
[ 2944.305210] usb 2-1.2-port4: cannot reset (err = -71)
[ 2944.314338] usb 2-1.2-port4: cannot reset (err = -71)
[ 2944.323451] usb 2-1.2-port4: cannot reset (err = -71)
[ 2944.332574] usb 2-1.2-port4: cannot reset (err = -71)
[ 2944.341694] usb 2-1.2-port4: cannot reset (err = -71)
[ 2944.346783] usb 2-1.2-port4: Cannot enable. Maybe the USB cable is bad?
[ 2944.357892] usb 2-1.2-port4: cannot disable (err = -71)
[ 2944.367204] usb 2-1.2-port3: cannot reset (err = -71)
[ 2944.376319] usb 2-1.2-port3: cannot reset (err = -71)

From the previous output, the external hub throws an error when it receives the power off request, due to the mouse and keyboard connected to it.

Some drivers re-enable power if power got switched off. To prevent this, you can first remove the USB device from the runtime USB configuration and only then switch off power.

To solve this, first remove the driver instances handling the mouse, keyboard and the hub itself connected to X4. Only then remove power the port:

# echo 1 > /sys/bus/usb/devices/2-1.2.3/remove 
# echo 1 > /sys/bus/usb/devices/2-1.2.4/remove
# echo 1 > /sys/bus/usb/devices/2-1.2/remove

# uhubctl -l 2-1 -p 2 -a off
Current status for hub 2-1 [0424:2744 Microchip Tech USB2744, USB 2.10, 4 ports]
Port 2: 0101 power connect []
Sent power off request
New status for hub 2-1 [0424:2744 Microchip Tech USB2744, USB 2.10, 4 ports]
Port 2: 0000 off

To re-enable the power, execute the uhubctl command with the action (-a) on. You should see logs showing the USB devices and their respective drivers announcing themselves:

# uhubctl -l 2-1 -p 2 -a on 
Current status for hub 2-1 [0424:2744 Microchip Tech USB2744, USB 2.10, 4 ports]
Port 2: 0000 off
Sent power on request
New status for hub 2-1 [0424:2744 Microchip Tech USB2744, USB 2.10, 4 ports]
Port 2: 0100 power
[ 267.500712] usb 2-1.2: new high-speed USB device number 7 using ci_hdrc
[ 267.615831] hub 2-1.2:1.0: USB hub found
[ 267.619994] hub 2-1.2:1.0: 4 ports detected
[ 267.912724] usb 2-1.2.3: new low-speed USB device number 8 using ci_hdrc
[ 268.051938] input: SCISSORS Keyboard as /devices/platform/32e50000.usb/ci_hdrc.1/usb2/2-1/2-1.2/2-1.2.3/2-1.2.3:1.0/0003:0DC6:3100.0003/input/input4
[ 268.126362] hid-generic 0003:0DC6:3100.0003: input,hidraw0: USB HID v1.00 Keyboard [ SCISSORS Keyboard] on usb-ci_hdrc.1-1.2.3/input0
[ 268.216380] usb 2-1.2.4: new low-speed USB device number 9 using ci_hdrc
[ 268.341552] input: Genius NetScroll + Mini Traveler as /devices/platform/32e50000.usb/ci_hdrc.1/usb2/2-1/2-1.2/2-1.2.4/2-1.2.4:1.0/0003:0458:0036.0004/input/input5
[ 268.356900] hid-generic 0003:0458:0036.0004: input,hidraw1: USB HID v1.10 Mouse [Genius NetScroll + Mini Traveler] on usb-ci_hdrc.1-1.2.4/input0

Similarly, to power off the port where the mass storage device is connected, first eject the device, remove its driver instance, and then power off the port.

# eject /dev/sda
# echo 1 > /sys/bus/usb/devices/1-1/remove
# uhubctl -l 1 -p 1 -a off
Current status for hub 1 [1d6b:0002 Linux 4.14.170-4.0.0-devel+git.5c643afa32be ehci_hcd EHCI Host Controller ci_hdrc.0]
Port 1: 0101 power connect []
Sent power off request
New status for hub 1 [1d6b:0002 Linux 4.14.170-4.0.0-devel+git.5c643afa32be ehci_hcd EHCI Host Controller ci_hdrc.0]
Port 1: 0000 off
Send Feedback!