Hot-Plugging USB

Hot-Plugging USB

Learn how to get the most out of USB hardware in Linux.

When Linux was created, it supported the common hardware of the day, including ATA hard disks, parallel ports, and RS-232 serial ports. Those devices are all fairly straightforward, especially when compared to recent hardware interfaces.
In particular, the very popular Universal Serial Bus (USB) connection technology has a number of features that require special configuration in Linux. To further complicate matters, the methods of using USB devices have changed over time. Most notably, libusb and the USB filesystem are now the preferred means to access many USB devices, displacing the more traditional /dev/ file entries. Configuring the USB filesystem requires making adjustments to Linux’s hot-plugging subsystem.
This month, let’s take an in-depth look at connecting USB peripherals to Linux systems.

USB Principles

USB has become the interface of choice for many external devices, including mice, printers, scanners, digital cameras, and more, for three primary reasons:
1.Speed. USB 1.x is capable of 12 Mbps speeds, while USB 2.0 is capable of much faster speeds of about 480 Mbps. The latter transfer rate lay between the capabilities of Ultra2 SCSI and Ultra2 Wide SCSI, making USB 2.0 suitable for use even with hard disks. (USB 1.x is more than fast enough for mice, keyboards, and other lower-performance devices.)
2.Multiple devices. A single USB port can theoretically support up to 127 devices. To connect more than a few devices to a computer, though, you’ll need the help of a USB hub, which multiplies the physical connectors much like a power strip multiplies electrical outlets.
3.Hot-plugging. USB was designed so that users could attach and detach devices while the computer is running. This can be a tremendous advantage, but it poses a challenge to Linux, which wasn’t designed with hot-plugging in mind.
To facilitate changes to device access on hot-plugging ports such as USB, the 2.4.x and later kernels support a hot-plugging subsystem. For USB devices, the kernel works in conjunction with the USB filesystem (at /proc/bus/usb) and libusb (a cross-platform library for USB access) to replace traditional /dev files for many USB devices. (You can learn more about libusb at http://libusb.sourceforge.net.) In Linux, libusb is built atop Linux’s USB filesystem driver. Of course, all of this depends on Linux USB drivers. Understanding how all of these features fit together and are configured should help you use USB devices.
You should be aware that some USB devices must still be accessed using traditional /dev files. For instance, Linux ties its drivers for USB hard disks to the Linux SCSI subsystem, making USB hard disks (and removable disks, such as USB Zip drives) look like SCSI disks.

Linux USB Drivers

The first step to configure USB devices is tweaking kernel options. If you’re using a mainstream Linux distribution and its default kernel, chances are you won’t need to adjust these options, because most major Linux distributions ship with USB support enabled. However, if you’re using a distribution that lacks USB support or are trying to connect an unusual UDB device that’s not commonly supported, you might have to change kernel options and recompile your kernel.
To configure your Linux kernel, type make xconfig in the kernel source directory. (You can also use another command, such as make menuconfig, if you prefer.) The main set of USB options are available in the “Device Drivers, USB Support” area, as shown in Figure One.
Figure One: The Linux kernel provides a wide range of USB options



To use USB devices via libusb, you must ensure that several options are active:
*Support for Host-Side USB. This option is the most basic form of USB support and is required to use USB on a Linux host.
*USB Device Filesystem. This option delivers the /proc/bus/usb filesystem. (You might need to explicitly mount /proc/bus/usb in /etc/fstab. If so, specify a device filename of none and a filesystem type code of usbfs.) This option relies on the /proc filesystem support option, which appears under “File Systems, Pseudo Filesystems” in the kernel configuration menu.
*USB interface options. The “EHCI HCD (USB 2.0) Support”, “OHCI HDC Support”, “UHCI HCD (Most Intel and VIA) Support”, and “SL811HS HCD Support” options provide drivers for the EHCI, OHCI, UHCI, and SL811HS USB hardware interfaces, respectively. Most modern motherboards use either OHCI or UHCI hardware for USB 1.x support, in conjunction with EHCI for USB 2.0 support. If in doubt, enable support for all three protocols. SL811HS hardware is rarer than the others, but compile it if you believe your motherboard (or plug-in USB card) uses this controller chip.
These drivers handle many of the devices that are accessed via libusb. The remaining drivers and options are important if you want to use devices that are accessed in other ways, and some even if you use libusb to access the devices. Some particularly common options include:
*USB Printer Support. As you might guess by the name, this option enables support for USB printers. This option is required even for tools, like the Common Unix Printing System (CUPS) that access printers via libusb, so be sure to enable it if you’ve got a USB printer.
*USB Mass Storage Support. This option is important for USB hard disks, USB floppy drives, and other USB storage devices. It includes sub-options for some common devices that require special treatment. To use this option, you must also activate basic SCSI support (in “Device Drivers, SCSI Device Support”), including SCSI disk support.
*USB Human Interface Device(Full HID)Support. This option supports keyboards, mice, and other human input devices. It’s what you’d normally use to access such devices; however, you may need to use another driver in conjunction with this one, depending on the device and how you intend to use it. The “HID Input Layer Support” option is the most common sub-option to select. You may also need to activate options in the “Device Drivers, Input Device Support” area.
*Camera and scanner options. Several options are pertinent to digital cameras and scanners. In most cases, you can ignore these, because popular Linux digital imaging and scanning software now uses libusb to access devices.
*Network, RS-232 serial, and parallel port adapters. Adapters that enable you to connect RS-232 serial or parallel port devices, or to use a USB port as a network port, are popular. Most of these require special USB drivers, as well as activation of the appropriate subsystems elsewhere in the kernel.
If you reconfigured your kernel, you should recompile it, install your new kernel modules, adjust your boot loader configuration to point to the new kernel, and reboot your computer. You can then proceed to check your USB filesystem and use libusb.

The Linux USB Filesystem

In many ways, the Linux USB filesystem, based at /proc/bus/usb, serves as a USB-specific substitute for the better-understood /dev directory. One important difference is that the files in /proc/bus/usb are created and destroyed automatically as USB devices are added to and removed from the system. Another difference is that the actual device files on the USB filesystem have numbers as names, referring to their USB busses and positions on the busses. This latter fact means that you can’t refer to a particular device by a fixed name to access it — there’s no equivalent to, say, /dev/lp0 for a printer connected to a parallel port.
Unless you’re modifying the kernel, chances are you’ll only deal directly with one file in the USB filesystem: /proc/bus/usb/devices. Try viewing this file with less.. You should see a number of entries that look like Figure Two.
FIGURE TWO: The contents of /proc/bus/usb/devices
T:  Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#=  2 Spd=1.5 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=05fe ProdID=0001 Rev= 0.00
S: Manufacturer=Cypress Sem
S: Product=Cypress USB Mouse
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID) Sub=01 Prot=02 Driver=usbhid
E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl=10ms
You’ll see entries for both USB devices (mice, printers, and so on) and for the USB controllers to which they attach. This information can be helpful because it verifies that Linux has identified a USB device and tells you to which bus the device is attached. Information you might want to check when setting up or debugging USB devices includes:
*The bus. The first line includes an entry entitled Bus. You can use this information to identify the controller and driver used by a device.
*The speed. The Spd entry in the T: line specifies the speed of the device. In this example, it’s 1.5 Mbps, which is below even the USB 1.x maximum of 12 Mbps. This isn’t a problem because the device is a mouse (as described shortly), which requires very little USB bandwidth to operate properly.
*Vendor and product IDs. The P: line contains vendor and product ID codes (05fe and 0001, respectively, for this example). This information may be necessary for telling libusb about the device, if your distribution hasn’t already done so.
*Vendor and product names. For human consumption, /proc/bus/usb/devices reports the vendor and product names on the S: lines. Figure Two clearly identifies the device as a mouse.
*Driver. The I: line includes various entries, including one (Driver) that identifies the Linux kernel driver that’s managing the device. If a device lacks an in-kernel driver, the driver is listed as (none). This means that, if you’re to use the device from Linux, you must either load a kernel-level driver or use software with libusb support.
In addition to /proc/bus/usb/devices, the USB filesystem provides files that deliver access to individual USB devices. These appear in subdirectories numbered after the USB busses to which they refer, such as /proc/bus/usb/001 for bus 1. Each file within these subdirectories is also numbered, as in /proc/bus/usb/001/002, to refer to the second device on the first bus. The exact placement of a device file can vary from one system to another. A USB printer might be /proc/bus/usb/001/002 on one computer but /proc/bus/usb/004/001 if moved to another computer. Part of the job of libusb is to deal with these changes. The library also provides high-level interfaces to USB devices, which can help simplify the task of programs that need to access USB hardware.

Using libusb

Ideally, libusb works correctly out-of-the-box. Sometimes, though, you may need to tweak its configuration to enable software to access your USB hardware. You can also use various utilities that are provided with libusb (and a companion package, usbutils) to check on your USB hardware.
One of the most basic of these tools is lsusb, which lists the USB devices attached to your system. You can use it with its –t option to see the devices in a tree view, as shown in Figure Three.
FIGURE THREE: List the USB devices attached to your system with lsusb –t
# lsusb –t
Bus# 5
`-Dev# 1 Vendor 0×0000 Product 0×0000
`-Dev# 3 Vendor 0×04b8 Product 0×0807
Bus# 4
`-Dev# 1 Vendor 0×0000 Product 0×0000
Bus# 3
`-Dev# 1 Vendor 0×0000 Product 0×0000
Bus# 2
`-Dev# 1 Vendor 0×0000 Product 0×0000
Bus# 1
`-Dev# 1 Vendor 0×0000 Product 0×0000
`-Dev# 2 Vendor 0×05fe Product 0×0001
In many respects, the lsusb output is similar to the contents of the /proc/bus/usb/devices file, but is more succinct. Options other than –t are also available, and some produce quite copious output; consult the lsusb man page for details.

Hot-Plugging Configuration

The biggest challenge of USB configuration is managing hot-plugging.
Recent versions of Linux use kernel support for hot-plugging devices. You can
configure these tools using files in the /etc/hotplug directory tree. If you’re lucky, your USB hardware is already configured. If not, though, you may need to make some changes.
One of the most common problems is incorrect permissions, which typically enable root, but no other user, to access a device.
First, check the /etc/hotplug/usb.usermap file. This file contains many lines with mysterious-looking entries that identify USB devices, like this (the very long line has been wrapped to fit the column):
epson_scanner  0x0003  0x04b8  0x0807 
0×0000 0×0000 0×00 0×00 0×00 0×00
0×00 0×00 0×00000000
The key entries are the second and third hexadecimal numbers — 0×04b8 and 0×0807 in this example. These numbers correspond to the vendor and product IDs from the output of lsusb or from the /proc/bus/usb/devices file.
If you can’t find an entry in /etc/hotplug/usb.usermap corresponding to the device you want to use, the hot-plugging system might not be able to correctly configure the device. The device might still be accessible, but probably only by root. To make the device accessible by a wider range of users, you need to create an entry in /etc/hotplug/usb.usermap and provide a script in the /etc/hotplug/usb directory.
Model your /etc/hotplug/usb.usermap entry on the epson_scanner example abive (remembering to make your entry a single line, though) or on an existing entry. Substitute the USB vendor and product ID codes and change the entry epson_scanner to the filename of the script you create in /etc/hotplug/usb.
This script should modify the permissions on the USB filesystem entry for the device. Listing One shows an example. This script changes the owner of the device file to root, changes its group to scanner, and changes its permissions to 660 (readable and writeable by onwer and group). The result is that anybody who’s a member of the scanner group can access the USB device. Be sure that the script is executable, using chmod a+x.
Listing One: Sample script to modify USB filesystem entry permissions

#!/bin/bash

if [ “${ACTION}” = “add” ] && \
[ –f “${DEVICE}” ]
then
chown root “${DEVICE}”
chgrp scanner “${DEVICE}”
chmod 660 “${DEVICE}”
fi

You should realize that the hot-plug subsystem runs these scripts only when a device is plugged in or turned on. You may also need to restart the ho-tplug subsystem via its startup script to have your changes take effect.
Once you’ve made these changes, ordinary users should be able to access the USB device you’ve configured. If you have problems, try examining the ownership and permissions on the USB device files in /proc/bus/usb. Watch the files as you attach and detach (or power on and off) a USB device.

No comments: