blob: d2ecd407c5ec0644a44a7016ca53ef88cbb97a02 [file] [log] [blame] [view]
<!--
(C) Copyright 2019 The Fuchsia Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
# USB system overview
Zircon provides a full featured USB subsystem enabling the development of USB
host and peripheral devices. Low, full, high, and super-speed devices are
supported as well as various standard auto-negotiation mechanisms.
In the host role, Zircon's USB subsystem assumes a tiered approach facilitating
the lifetime management of devices as they are attached or removed from the bus.
In the device role, the subsystem marshals USB packets in and out of a
class-specific driver (or hierarchy of drivers).
A target hardware platform may contain numerous USB controllers. As a result,
Zircon may be acting as either a host or device on each respective physical bus.
However, each role is unique to a particular bus topology. This document will
assume that only a single bus is present unless noted otherwise.
The USB subsystem components are summarized as:
- Class-specific hardware driver(s)
- USB hub driver (special case of a class-specific driver)
- Bus driver
- Host or device controller interface driver
## Host role
When operating as a USB host, Zircon acts as the authoritative bus arbiter. The
tree of attached USB devices is rooted at a root USB hub. The presence of this
root hub is required regardless of whether any actual hub hardware exists. For
systems that contain a host-capable controller, but no actual hub hardware, this
root hub must be emulated in software.
To facilitate bus arbitration, Zircon operates the following drivers:
- USB root hub driver
- Bus driver
- Host controller interface (HCI) driver
These drivers operate together to respond to bus attachment and manage the
lifetime of the attached devices.
## Device role
When operating as a USB device, Zircon transports USB packet data between the
bus and the class-specific driver (or hierarchy of drivers). In this role, the
bus driver facilitates communication between the DCI driver and the upper layers
of the class-specific driver(s).
## Class-specific driver
Class-specific drivers implement the logic necessary to fulfill a specific USB
function (e.g. HID-class device) while remaining agnostic of the hardware
details necessary to read and write physical packets from or to the actual bus.
Note: that the hub driver is one example of a class-specific device driver.
In general, USB device drivers encode transfer requests into a `usb_request_t`
structure. These request structs generally have an asynchronous callback
associated with them to be executed upon transfer completion. For the most
part, the USB stack functions by the higher order device drivers publishing
requests to a queue of outstanding requests. As these requests are serviced,
their respective callbacks are invoked notifying the upper layers that the
request is complete.
## Hub driver
The purpose of the hub driver is to manage a hub device according to CH11 of the
[USB 2.0 specification][USB 2.0 spec]. In brief, having undergone device
enumeration, USB hubs use two interfaces to achieve their function:
1. IN-type interrupt endpoint for port status change events
2. IN-type control transfers for port status queries
The Zircon USB stack (which the hub driver is part of) issues a request awaiting
a port status change interrupt event. USB hubs report port status change events
using an N-bit bitmap where bit-1 corresponds to port#1, bit-2 port#2, etc...
Note that bit-0 is reserved for hub status change events, and is currently
unsupported. Thus, a 4-port hub writes a 5-bit value for each of the 4 ports
using an IN-type interrupt endpoint.
Note: While not a requirement, most hubs only produce an interrupt transfer when
there is an actual port status change event.
When the hub device detects a change to one of its ports, it issues an interrupt
transfer encoding the port number. This interrupt transfer unblocks the hub
driver, which reads the port status change bitmap and determines which port(s)
have relevant activity.
Given a port status change event, the USB stack uses the control interface
of the hub device to query the individual port status and proceed as per the
spec. For example, if a port's status changed due to a connection event, the
port would be powered, reset, and enumeration would proceed.
For more information about the specifics of hub lifetime, see CH11 of the [USB
2.0 specification][USB 2.0 spec].
## Bus driver
The purpose of the bus driver is to announce the presence (or removal) of
devices to the bus, and to register the presence of a hub device with the rest
of the USB stack. For the most part, the bus driver simply facilitates
communication between the different parts of the USB stack.
## HCI driver (host only)
The host controller interface (HCI) driver exists at the bottom layer of the USB
stack when operating in host mode. This is the entity responsible for
translating outstanding `usb_request_t` into the necessary hardware directives
capable of servicing the request.
The HCI driver is distinguished from the DCI driver in that it contains
functionality to facilitate device enumeration. If general enumeration is
separated into two phases:
- Bus enumeration (up through the `set_address` command).
- Device enumeration (everything to follow an addressable device).
The HCI driver performs the former half while the USB stack takes over and
performs the rest of the device enumeration.
## DCI driver (device only)
The device controller interface(DCI) driver exists at the bottom layer of the
USB stack when operating in device mode. This is the entity responsible for
translating outstanding `usb_request_t` into the necessary hardware directives
capable of servicing the request.
The DCI driver is distinguished from the HCI driver in that it serves to present
incoming OUT-type transfer requests to the device as well as set up outgoing
IN-type transfer requests to the bus. In both cases, an individual transfer may
result in multiple packets going each direction.
## See also
+ [USB 2.0 spec]
<!-- xref -->
[USB 2.0 spec]: https://www.usb.org/document-library/usb-20-specification