With support for mass storage, just about any USB host can communicate with off-the-shelf mass-storage devices, including hard drives and flash drives. This chapter looks at what’s involved in designing and programming an embedded system that functions as a USB host. Much of this information can be helpful to device designers as well, especially the information about common device problems that hosts experience.
Inside an Embedded Host
As Chapter 1 explained, a host’s function is in many ways a mirror image of a device’s function. All USB hosts must detect device attachment and removal and manage power and bus traffic. Chip vendors typically provide example firmware for performing these tasks.
On detecting a device with an interface descriptor that specifies the mass-storage class, a host that supports mass storage should examine the interface descriptor and the device’s response to a SCSI INQUIRY command to learn which SCSI command set the device claims to support. The host can then proceed with other mass-storage communications. A host that supports a file system can also create, read, write to, and delete files on its own.
OTG Devices and Conventional Hosts
A USB host in an embedded system can be a conventional USB host or an On-The-Go device. A system that never functions as a USB device must function as a conventional host. If the system must function as a USB host and device at the same time, the system must contain separate SIEs for the USB host and device functions. The SIEs can be on a single chip or different chips. If the system functions as both a USB host and device but not both at the same time, the system can be an OTG device.
Conventional hosts and OTG hosts have different requirements in some areas. Support for external hubs is required in a conventional host and optional in an OTG device. A conventional host must provide 500 mA per port (or 100 mA if battery powered), while an OTG device needs to provide just 8 mA per port unless a supported peripheral requires more. A conventional host must provide bus power at all times, while an OTG device can switch off bus power when unneeded.
General Host Functions
The host enumerates each device to learn about its capabilities. To enumerate a device, a host typically issues the following standard USB requests:
Set Address. To set the device’s address on the bus.
Get Descriptor (device). To read the device descriptor.
Get Descriptor (configuration). To read the configuration descriptor and subordinate descriptors, including the interface and endpoint descriptors.
Set Configuration. To configure the device and enable communications.
The host can also request any string descriptors the device supports, including the descriptor containing the serial number.
Figure 11-1 shows bus events and host requests directed to a newly attached USB flash drive on a Windows XP host. The host requests some descriptors multiple times and resets the bus after the first Get Descriptor request. This
Figure 11-1: Requests sent by a Windows host to enumerate a mass-storage device. (Screen capture from Ellisys USB Explorer.)
is one example of host communications. Hosts aren’t required to use this exact sequence of requests. The device doesn’t need to know or care why the host is sending a request or resetting the bus and shouldn’t assume anything about what a host will do next. The device just needs to respond appropriately when something happens.
Mass Storage Functions
After enumeration, a host can use USB requests and SCSI commands to learn more about a device and to prepare to read and write to the storage media. Figure 11-2 shows communications from a Windows host after com-
Figure 11-2: Commands used by a Windows host after enumerating a flash drive. (Screen capture from Ellisys USB Explorer.)
pleting enumeration. These requests and commands are typical for Windows XP, but hosts aren’t required to use this exact sequence:
Get Max LUN. This USB class-specific request asks for the highest LUN number supported by the device. Devices with single LUNs are the only ones allowed to stall this request. The host can use the commands below to initialize communications with each logical unit from zero up to the value returned.
INQUIRY. The host requests 36 bytes of data about a logical unit.
READ FORMAT CAPACITIES. The host requests a structure containing one or more descriptors that specify a number of blocks and a block length that the media can be formatted for.
READ CAPACITY(10). The host requests the highest LBA supported by the logical unit and the number of bytes in that logical block (typically 512).
READ(10). The host reads sector zero, which should be either an MBR sector with a partition table or a FAT boot sector (assuming the volume is formatted for a FAT file system).
MODE SENSE(6) with PAGE CODE = 1Ch and SUBPAGE CODE = 00h. The host requests the Informational Exceptions Control Mode page in page_0 format.
MODE SENSE(6) with PAGE CODE = 3Fh and SUBPAGE CODE = 00h. The host requests all mode pages with subpage = 00h in page_0 format.
TEST UNIT READY. The host requests a CSW and checks the value in bCSWStatus to determine if the logical unit is ready for use. If bCSWStatus = 00h, the logical unit is ready. If the value isn’t zero, the host can issue a REQUEST SENSE command to learn more.
READ(10). The host can use additional READ commands to read the boot sector, root directory, and other information in a volume.