Embedded Xinu Operating System
An ongoing research project and educational operating system.
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Groups Pages
Files | Functions | Variables
USB Hub Driver

Driver for USB hub devices. More...

Files

file  usbhub.c
 

Functions

void usb_hub_for_device_in_tree (struct usb_device *dev, usb_status_t(*callback)(struct usb_device *))
 

Variables

struct usb_device_driver usb_hub_driver
 

Detailed Description

Driver for USB hub devices.

This is the USB Hub driver. Hubs are one of the fundamental devices in USB and are used to provide connection points (ports) for additional devices. Note that even if no "external" hub is plugged in, the USB still will have at least one logical hub (the root hub) and usually additional "internal" hubs. That is, a USB is a tree of devices where the root node and all non-leaf nodes are hubs. A port on a USB hub may correspond to a port you can physically plug a device into or may correspond to an internal port.

This hub driver is an example of a USB device driver, but it is somewhat special as it mandatory to include this driver if USB is supported at all. This is because it would be impossible to access any USB devices if a hub driver were not available. This hub driver also uses some interfaces in the core driver, such as usb_attach_device(), that are not useful to any other USB device driver.

The initial entry point of this USB hub driver is hub_bind_device(), which is called when the USB core has configured a newly attached USB device that may be a hub. hub_bind_device() is responsible for checking if the device is a hub, and if so, then doing hub-specific setup, including one-time driver initialization, reading the hub descriptor, powering on the ports, and submitting an asynchronous USB interrupt transfer request to the hub's status change endpoint.

Everything else this hub driver does happens asynchronously as a response to a status change request being completed. Every USB hub has exactly one IN interrupt endpoint called the "status change endpoint". The hub responds on this endpoint whenever the status of the hub or one of the hub's ports has changed— for example, when a USB device has been connected or disconnected from a port.

At the hardware level, when a hub has data to send on its status change endpoint, an interrupt will come in from the USB host controller. This eventually will result in the status change transfer being completed and hub_status_changed() being called. Thus, the detection of status changes is interrupt-driven and is not implemented by polling at the software level. (At the hardware level, USB is still a polled bus, but the host controller hardware handles that for us.) Upon detecting a status change on one or more ports on a hub, the hub driver then must submit one or more control messages to the hub to determine exactly what changed on the affected ports. However, we defer this work by passing it to a separate thread in order to avoid doing too much synchronous work in interrupt handlers.

Function Documentation

void usb_hub_for_device_in_tree ( struct usb_device *  dev,
usb_status_t(*)(struct usb_device *)  callback 
)

Call a function on each USB device in the tree. This can be used to iterate through every device on the USB. The calling code is responsible for making sure devices cannot be detached from the USB while this is executing (e.g. by executing with interrupts disabled or by calling usb_lock_bus()).

Parameters
devRoot of the USB device tree at which to do the iteration.
callbackCallback function to execute on each device.

Variable Documentation

struct usb_device_driver usb_hub_driver
Initial value:
= {
.name = "USB Hub Driver",
.bind_device = hub_bind_device,
.unbind_device = hub_unbind_device,
}

Declaration of the USB hub device driver.