iPXE
Data Structures | Functions | Variables
usb.c File Reference

Universal Serial Bus (USB) More...

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <ipxe/usb.h>
#include <ipxe/cdc.h>

Go to the source code of this file.

Data Structures

struct  usb_control_pseudo_header
 USB control transfer pseudo-header. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static const char * usb_speed_name (unsigned int speed)
 Get USB speed name (for debugging)
static const char * usb_bcd (uint16_t bcd)
 Transcribe USB BCD-coded value (for debugging)
static struct
usb_interface_association_descriptor
usb_interface_association_descriptor (struct usb_configuration_descriptor *config, unsigned int first)
 Locate USB interface association descriptor.
struct usb_interface_descriptorusb_interface_descriptor (struct usb_configuration_descriptor *config, unsigned int interface, unsigned int alternate)
 Locate USB interface descriptor.
struct usb_endpoint_descriptorusb_endpoint_descriptor (struct usb_configuration_descriptor *config, struct usb_interface_descriptor *interface, unsigned int type, unsigned int index)
 Locate USB endpoint descriptor.
struct
usb_endpoint_companion_descriptor
usb_endpoint_companion_descriptor (struct usb_configuration_descriptor *config, struct usb_endpoint_descriptor *desc)
 Locate USB endpoint companion descriptor.
const char * usb_endpoint_name (struct usb_endpoint *ep)
 Get USB endpoint name (for debugging)
int usb_endpoint_described (struct usb_endpoint *ep, struct usb_configuration_descriptor *config, struct usb_interface_descriptor *interface, unsigned int type, unsigned int index)
 Describe USB endpoint from device configuration.
int usb_endpoint_open (struct usb_endpoint *ep)
 Open USB endpoint.
static int usb_endpoint_clear_tt (struct usb_endpoint *ep)
 Clear transaction translator (if applicable)
void usb_endpoint_close (struct usb_endpoint *ep)
 Close USB endpoint.
static int usb_endpoint_reset (struct usb_endpoint *ep)
 Reset USB endpoint.
static int usb_endpoint_mtu (struct usb_endpoint *ep, size_t mtu)
 Update endpoint MTU.
int usb_message (struct usb_endpoint *ep, unsigned int request, unsigned int value, unsigned int index, struct io_buffer *iobuf)
 Enqueue USB message transfer.
int usb_stream (struct usb_endpoint *ep, struct io_buffer *iobuf, int terminate)
 Enqueue USB stream transfer.
void usb_complete_err (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete transfer (possibly with error)
int usb_prefill (struct usb_endpoint *ep)
 Prefill endpoint recycled buffer list.
int usb_refill (struct usb_endpoint *ep)
 Refill endpoint.
void usb_flush (struct usb_endpoint *ep)
 Discard endpoint recycled buffer list.
static void usb_control_complete (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete USB control transfer.
int usb_control (struct usb_device *usb, unsigned int request, unsigned int value, unsigned int index, void *data, size_t len)
 Issue USB control transaction.
static unsigned int usb_get_default_language (struct usb_device *usb)
 Get default language ID.
int usb_get_string_descriptor (struct usb_device *usb, unsigned int index, unsigned int language, char *buf, size_t len)
 Get USB string descriptor.
static int usb_config_descriptor (struct usb_device *usb, unsigned int index, struct usb_configuration_descriptor **config)
 Get USB configuration descriptor.
static int usb_describe (struct usb_device *usb, struct usb_configuration_descriptor *config, unsigned int first, uint8_t *interfaces, struct usb_function_descriptor *desc)
 Describe USB function.
static int usb_used (struct usb_device *usb, unsigned int count, uint8_t *interface, uint8_t *used)
 Update list of used interface.
struct usb_driverusb_find_driver (struct usb_function_descriptor *desc, struct usb_device_id **id)
 Find USB device driver.
static int usb_score (struct usb_device *usb, struct usb_configuration_descriptor *config)
 Get USB device configuration score.
static int usb_probe (struct usb_function *func, struct usb_configuration_descriptor *config)
 Probe USB device driver.
static void usb_remove (struct usb_function *func)
 Remove USB device driver.
static void usb_probe_all (struct usb_device *usb, struct usb_configuration_descriptor *config)
 Probe all USB device drivers.
static void usb_remove_all (struct usb_device *usb)
 Remove all device drivers.
static void usb_deconfigure (struct usb_device *usb)
 Clear USB device configuration.
static int usb_autoconfigure (struct usb_device *usb)
 Choose our preferred USB device configuration.
static struct usb_devicealloc_usb (struct usb_port *port)
 Allocate USB device.
static int register_usb (struct usb_device *usb)
 Register USB device.
static void unregister_usb (struct usb_device *usb)
 Unregister USB device.
static void free_usb (struct usb_device *usb)
 Free USB device.
static int usb_attached (struct usb_port *port)
 Handle newly attached USB device.
static void usb_detached (struct usb_port *port)
 Handle newly detached USB device.
static int usb_hotplugged (struct usb_port *port)
 Handle newly attached or detached USB device.
void usb_port_changed (struct usb_port *port)
 Report port status change.
static void usb_hotplug (void)
 Handle newly attached or detached USB device.
static void usb_step (struct process *process __unused)
 USB process.
 PERMANENT_PROCESS (usb_process, usb_step)
 USB process.
struct usb_huballoc_usb_hub (struct usb_bus *bus, struct usb_device *usb, unsigned int ports, struct usb_hub_driver_operations *driver)
 Allocate USB hub.
int register_usb_hub (struct usb_hub *hub)
 Register USB hub.
void unregister_usb_hub (struct usb_hub *hub)
 Unregister USB hub.
void free_usb_hub (struct usb_hub *hub)
 Free USB hub.
struct usb_busalloc_usb_bus (struct device *dev, unsigned int ports, size_t mtu, struct usb_host_operations *op)
 Allocate USB bus.
int register_usb_bus (struct usb_bus *bus)
 Register USB bus.
void unregister_usb_bus (struct usb_bus *bus)
 Unregister USB bus.
void free_usb_bus (struct usb_bus *bus)
 Free USB bus.
struct usb_busfind_usb_bus_by_location (unsigned int bus_type, unsigned int location)
 Find USB bus by device location.
int usb_alloc_address (struct usb_bus *bus)
 Allocate device address.
void usb_free_address (struct usb_bus *bus, unsigned int address)
 Free device address.
unsigned int usb_route_string (struct usb_device *usb)
 Get USB route string.
unsigned int usb_depth (struct usb_device *usb)
 Get USB depth.
struct usb_portusb_root_hub_port (struct usb_device *usb)
 Get USB root hub port.
struct usb_portusb_transaction_translator (struct usb_device *usb)
 Get USB transaction translator.
 REQUIRING_SYMBOL (register_usb_bus)
 REQUIRE_OBJECT (config_usb)
 REQUIRE_OBJECT (usbhub)

Variables

struct list_head usb_buses = LIST_HEAD_INIT ( usb_buses )
 List of USB buses.
static struct list_head usb_changed = LIST_HEAD_INIT ( usb_changed )
 List of changed ports.
static struct list_head usb_halted = LIST_HEAD_INIT ( usb_halted )
 List of halted endpoints.
static struct
usb_endpoint_driver_operations 
usb_control_operations
 USB control endpoint driver operations.

Detailed Description

Universal Serial Bus (USB)

Definition in file usb.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static const char* usb_speed_name ( unsigned int  speed) [inline, static]

Get USB speed name (for debugging)

Parameters:
speedSpeed
Return values:
nameSpeed name

Definition at line 65 of file usb.c.

References snprintf(), USB_SPEED_EXPONENT, USB_SPEED_FULL, USB_SPEED_HIGH, USB_SPEED_LOW, USB_SPEED_MANTISSA, USB_SPEED_NONE, and USB_SPEED_SUPER.

Referenced by register_usb().

                                                                 {
        static const char *exponents[4] = { "", "k", "M", "G" };
        static char buf[ 10 /* "xxxxxXbps" + NUL */ ];
        unsigned int mantissa;
        unsigned int exponent;

        /* Extract mantissa and exponent */
        mantissa = USB_SPEED_MANTISSA ( speed );
        exponent = USB_SPEED_EXPONENT ( speed );

        /* Name speed */
        switch ( speed ) {
        case USB_SPEED_NONE:            return "DETACHED";
        case USB_SPEED_LOW:             return "low";
        case USB_SPEED_FULL:            return "full";
        case USB_SPEED_HIGH:            return "high";
        case USB_SPEED_SUPER:           return "super";
        default:
                snprintf ( buf, sizeof ( buf ), "%d%sbps",
                           mantissa, exponents[exponent] );
                return buf;
        }
}
static const char* usb_bcd ( uint16_t  bcd) [inline, static]

Transcribe USB BCD-coded value (for debugging)

Parameters:
bcdBCD-coded value
Return values:
stringTranscribed value

Definition at line 95 of file usb.c.

References high, low, and snprintf().

Referenced by register_usb().

                                                    {
        static char buf[ 6 /* "xx.xx" + NUL */ ];
        uint8_t high = ( bcd >> 8 );
        uint8_t low = ( bcd >> 0 );

        snprintf ( buf, sizeof ( buf ), "%x.%02x", high, low );
        return buf;
}
static struct usb_interface_association_descriptor* usb_interface_association_descriptor ( struct usb_configuration_descriptor config,
unsigned int  first 
) [static, read]

Locate USB interface association descriptor.

Parameters:
configConfiguraton descriptor
firstFirst interface number
Return values:
descInterface association descriptor, or NULL if not found

Definition at line 119 of file usb.c.

References usb_interface_association_descriptor::first, for_each_config_descriptor, usb_interface_association_descriptor::header, NULL, usb_descriptor_header::type, and USB_INTERFACE_ASSOCIATION_DESCRIPTOR.

Referenced by usb_describe().

                                                            {
        struct usb_interface_association_descriptor *desc;

        /* Find a matching interface association descriptor */
        for_each_config_descriptor ( desc, config ) {
                if ( ( desc->header.type ==
                       USB_INTERFACE_ASSOCIATION_DESCRIPTOR ) &&
                     ( desc->first == first ) )
                        return desc;
        }
        return NULL;
}
struct usb_interface_descriptor* usb_interface_descriptor ( struct usb_configuration_descriptor config,
unsigned int  interface,
unsigned int  alternate 
) [read]

Locate USB interface descriptor.

Parameters:
configConfiguraton descriptor
interfaceInterface number
alternateAlternate setting
Return values:
descInterface descriptor, or NULL if not found

Definition at line 143 of file usb.c.

References usb_interface_descriptor::alternate, for_each_config_descriptor, usb_interface_descriptor::header, usb_interface_descriptor::interface, NULL, and usb_descriptor_header::type.

Referenced by ecm_probe(), efi_usb_get_interface_descriptor(), ncm_probe(), usbhid_describe(), usbnet_comms_describe(), and usbnet_data_describe().

                                                                            {
        struct usb_interface_descriptor *desc;

        /* Find a matching interface descriptor */
        for_each_config_descriptor ( desc, config ) {
                if ( ( desc->header.type == USB_INTERFACE_DESCRIPTOR ) &&
                     ( desc->interface == interface ) &&
                     ( desc->alternate == alternate ) )
                        return desc;
        }
        return NULL;
}
struct usb_endpoint_descriptor* usb_endpoint_descriptor ( struct usb_configuration_descriptor config,
struct usb_interface_descriptor interface,
unsigned int  type,
unsigned int  index 
) [read]

Locate USB endpoint descriptor.

Parameters:
configConfiguration descriptor
interfaceInterface descriptor
typeEndpoint (internal) type
indexEndpoint index
Return values:
descDescriptor, or NULL if not found

Definition at line 167 of file usb.c.

References usb_endpoint_descriptor::attributes, direction, usb_endpoint_descriptor::endpoint, for_each_interface_descriptor, usb_endpoint_descriptor::header, NULL, usb_descriptor_header::type, USB_DIR_IN, and USB_ENDPOINT_ATTR_TYPE_MASK.

Referenced by usb_endpoint_described().

                                                                  {
        struct usb_endpoint_descriptor *desc;
        unsigned int attributes = ( type & USB_ENDPOINT_ATTR_TYPE_MASK );
        unsigned int direction = ( type & USB_DIR_IN );

        /* Find a matching endpoint descriptor */
        for_each_interface_descriptor ( desc, config, interface ) {
                if ( ( desc->header.type == USB_ENDPOINT_DESCRIPTOR ) &&
                     ( ( desc->attributes &
                         USB_ENDPOINT_ATTR_TYPE_MASK ) == attributes ) &&
                     ( ( desc->endpoint & USB_DIR_IN ) == direction ) &&
                     ( index-- == 0 ) )
                        return desc;
        }
        return NULL;
}

Locate USB endpoint companion descriptor.

Parameters:
configConfiguration descriptor
descEndpoint descriptor
Return values:
descxCompanion descriptor, or NULL if not found

Definition at line 194 of file usb.c.

References container_of, header, usb_endpoint_descriptor::header, usb_endpoint_companion_descriptor::header, NULL, usb_descriptor_header::type, USB_ENDPOINT_COMPANION_DESCRIPTOR, usb_is_within_config(), and usb_next_descriptor().

Referenced by usb_endpoint_described().

                                                                           {
        struct usb_endpoint_companion_descriptor *descx;

        /* Get companion descriptor, if present */
        descx = container_of ( usb_next_descriptor ( &desc->header ),
                               struct usb_endpoint_companion_descriptor,
                               header );
        return ( ( usb_is_within_config ( config, &descx->header ) &&
                   descx->header.type == USB_ENDPOINT_COMPANION_DESCRIPTOR )
                 ? descx : NULL );
}
const char* usb_endpoint_name ( struct usb_endpoint ep)

Get USB endpoint name (for debugging)

Parameters:
epUSB endpoint
Return values:
nameEndpoint name

Definition at line 220 of file usb.c.

References address, usb_endpoint::address, snprintf(), USB_ENDPOINT_IN, and USB_ENDPOINT_MAX.

Referenced by efi_usb_async_start(), efi_usb_close(), efi_usb_open(), efi_usb_sync_transfer(), ehci_endpoint_close(), ehci_endpoint_poll(), ehci_root_clear_tt(), uhci_endpoint_poll(), uhci_root_clear_tt(), usb_complete_err(), usb_endpoint_clear_tt(), usb_endpoint_mtu(), usb_endpoint_open(), usb_endpoint_reset(), usb_message(), usb_stream(), usbio_bulk_in_poll(), usbio_bulk_out_poll(), usbio_control_poll(), usbio_endpoint_open(), usbio_interface(), usbio_interrupt_callback(), usbio_interrupt_open(), usbkbd_probe(), and xhci_root_clear_tt().

                                                           {
        static char buf[ 9 /* "EPxx OUT" + NUL */ ];
        unsigned int address = ep->address;

        snprintf ( buf, sizeof ( buf ), "EP%d%s",
                   ( address & USB_ENDPOINT_MAX ),
                   ( address ?
                     ( ( address & USB_ENDPOINT_IN ) ? " IN" : " OUT" ) : "" ));
        return buf;
}
int usb_endpoint_described ( struct usb_endpoint ep,
struct usb_configuration_descriptor config,
struct usb_interface_descriptor interface,
unsigned int  type,
unsigned int  index 
)

Describe USB endpoint from device configuration.

Parameters:
epUSB endpoint
configConfiguration descriptor
interfaceInterface descriptor
typeEndpoint (internal) type
indexEndpoint index
Return values:
rcReturn status code

Definition at line 241 of file usb.c.

References usb_endpoint_descriptor::attributes, usb_endpoint_companion_descriptor::burst, usb_endpoint_descriptor::endpoint, ENOENT, usb_endpoint_descriptor::interval, le16_to_cpu, mtu, usb_endpoint_descriptor::sizes, usb_device::speed, usb_endpoint::usb, USB_ENDPOINT_ATTR_INTERRUPT, USB_ENDPOINT_ATTR_TYPE_MASK, USB_ENDPOINT_BURST, usb_endpoint_companion_descriptor(), usb_endpoint_describe(), usb_endpoint_descriptor(), USB_ENDPOINT_MTU, and USB_SPEED_HIGH.

Referenced by hub_probe(), usbhid_describe(), usbnet_comms_describe(), and usbnet_data_describe().

                                                                     {
        struct usb_device *usb = ep->usb;
        struct usb_endpoint_descriptor *desc;
        struct usb_endpoint_companion_descriptor *descx;
        unsigned int sizes;
        unsigned int burst;
        unsigned int interval;
        size_t mtu;

        /* Locate endpoint descriptor */
        desc = usb_endpoint_descriptor ( config, interface, type, index );
        if ( ! desc )
                return -ENOENT;

        /* Locate companion descriptor, if any */
        descx = usb_endpoint_companion_descriptor ( config, desc );

        /* Calculate MTU and burst size */
        sizes = le16_to_cpu ( desc->sizes );
        mtu = USB_ENDPOINT_MTU ( sizes );
        burst = ( descx ? descx->burst : USB_ENDPOINT_BURST ( sizes ) );

        /* Calculate interval */
        if ( ( type & USB_ENDPOINT_ATTR_TYPE_MASK ) ==
             USB_ENDPOINT_ATTR_INTERRUPT ) {
                if ( usb->speed >= USB_SPEED_HIGH ) {
                        /* 2^(desc->interval-1) is a microframe count */
                        interval = ( 1 << ( desc->interval - 1 ) );
                } else {
                        /* desc->interval is a (whole) frame count */
                        interval = ( desc->interval << 3 );
                }
        } else {
                /* desc->interval is a microframe count */
                interval = desc->interval;
        }

        /* Describe endpoint */
        usb_endpoint_describe ( ep, desc->endpoint, desc->attributes,
                                mtu, burst, interval );
        return 0;
}
int usb_endpoint_open ( struct usb_endpoint ep)

Open USB endpoint.

Parameters:
epUSB endpoint
Return values:
rcReturn status code

Definition at line 293 of file usb.c.

References usb_endpoint::address, usb_endpoint::burst, usb_hub::bus, usb_endpoint_host_operations::close, DBGC, DBGC2, EALREADY, usb_host_operations::endpoint, usb_device::ep, usb_endpoint::halted, usb_endpoint::host, usb_port::hub, INIT_LIST_HEAD, usb_endpoint::interval, usb_endpoint::max, usb_endpoint::mtu, usb_device::name, NULL, usb_bus::op, usb_endpoint::open, usb_endpoint_host_operations::open, usb_device::port, rc, strerror(), usb_endpoint::usb, USB_ENDPOINT_IDX, usb_endpoint_name(), and usb_flush().

Referenced by efi_usb_open(), hub_open(), register_usb(), usbhid_open(), and usbnet_open().

                                                  {
        struct usb_device *usb = ep->usb;
        unsigned int idx = USB_ENDPOINT_IDX ( ep->address );
        int rc;

        /* Populate host controller operations */
        ep->host = &usb->port->hub->bus->op->endpoint;

        /* Add to endpoint list */
        if ( usb->ep[idx] != NULL ) {
                DBGC ( usb, "USB %s %s is already open\n",
                       usb->name, usb_endpoint_name ( ep ) );
                rc = -EALREADY;
                goto err_already;
        }
        usb->ep[idx] = ep;
        INIT_LIST_HEAD ( &ep->halted );

        /* Open endpoint */
        if ( ( rc = ep->host->open ( ep ) ) != 0 ) {
                DBGC ( usb, "USB %s %s could not open: %s\n", usb->name,
                       usb_endpoint_name ( ep ), strerror ( rc ) );
                goto err_open;
        }
        ep->open = 1;

        DBGC2 ( usb, "USB %s %s opened with MTU %zd, burst %d, interval %d\n",
                usb->name, usb_endpoint_name ( ep ), ep->mtu, ep->burst,
                ep->interval );
        return 0;

        ep->open = 0;
        ep->host->close ( ep );
 err_open:
        usb->ep[idx] = NULL;
 err_already:
        if ( ep->max )
                usb_flush ( ep );
        return rc;
}
static int usb_endpoint_clear_tt ( struct usb_endpoint ep) [static]

Clear transaction translator (if applicable)

Parameters:
epUSB endpoint
Return values:
rcReturn status code

Definition at line 340 of file usb.c.

References usb_endpoint::attributes, usb_hub_driver_operations::clear_tt, DBGC, usb_hub::driver, usb_port::hub, usb_device::name, rc, strerror(), usb_endpoint::usb, USB_ENDPOINT_ATTR_PERIODIC, usb_endpoint_name(), and usb_transaction_translator().

Referenced by usb_endpoint_close(), and usb_endpoint_reset().

                                                             {
        struct usb_device *usb = ep->usb;
        struct usb_port *tt;
        int rc;

        /* Do nothing if this is a periodic endpoint */
        if ( ep->attributes & USB_ENDPOINT_ATTR_PERIODIC )
                return 0;

        /* Do nothing if this endpoint is not behind a transaction translator */
        tt = usb_transaction_translator ( usb );
        if ( ! tt )
                return 0;

        /* Clear transaction translator buffer */
        if ( ( rc = tt->hub->driver->clear_tt ( tt->hub, tt, ep ) ) != 0 ) {
                DBGC ( usb, "USB %s %s could not clear transaction translator: "
                       "%s\n", usb->name, usb_endpoint_name ( ep ),
                       strerror ( rc ) );
                return rc;
        }

        return 0;
}
void usb_endpoint_close ( struct usb_endpoint ep)

Close USB endpoint.

Parameters:
epUSB endpoint

Definition at line 370 of file usb.c.

References usb_endpoint::address, assert, usb_endpoint_host_operations::close, usb_device::ep, usb_endpoint::fill, usb_endpoint::halted, usb_endpoint::host, list_del, usb_endpoint::max, NULL, usb_endpoint::open, usb_endpoint::usb, usb_endpoint_clear_tt(), USB_ENDPOINT_IDX, and usb_flush().

Referenced by efi_usb_close(), efi_usb_open(), hub_close(), hub_open(), register_usb(), unregister_usb(), usbhid_close(), usbhid_open(), usbnet_close(), and usbnet_open().

                                                    {
        struct usb_device *usb = ep->usb;
        unsigned int idx = USB_ENDPOINT_IDX ( ep->address );

        /* Sanity checks */
        assert ( usb->ep[idx] == ep );

        /* Close endpoint */
        ep->open = 0;
        ep->host->close ( ep );
        assert ( ep->fill == 0 );

        /* Remove from endpoint list */
        usb->ep[idx] = NULL;
        list_del ( &ep->halted );

        /* Discard any recycled buffers, if applicable */
        if ( ep->max )
                usb_flush ( ep );

        /* Clear transaction translator, if applicable */
        usb_endpoint_clear_tt ( ep );
}
static int usb_endpoint_reset ( struct usb_endpoint ep) [static]

Reset USB endpoint.

Parameters:
epUSB endpoint
Return values:
rcReturn status code

Definition at line 400 of file usb.c.

References usb_endpoint::address, assert, usb_endpoint::attributes, DBGC, usb_endpoint::halted, usb_endpoint::host, INIT_LIST_HEAD, list_del, list_empty, usb_device::name, rc, usb_endpoint_host_operations::reset, strerror(), type, usb_endpoint::usb, usb_clear_feature(), USB_ENDPOINT_ATTR_CONTROL, USB_ENDPOINT_ATTR_TYPE_MASK, usb_endpoint_clear_tt(), USB_ENDPOINT_HALT, usb_endpoint_name(), and USB_RECIP_ENDPOINT.

Referenced by usb_message(), usb_step(), and usb_stream().

                                                          {
        struct usb_device *usb = ep->usb;
        unsigned int type;
        int rc;

        /* Sanity check */
        assert ( ! list_empty ( &ep->halted ) );

        /* Reset endpoint */
        if ( ( rc = ep->host->reset ( ep ) ) != 0 ) {
                DBGC ( usb, "USB %s %s could not reset: %s\n",
                       usb->name, usb_endpoint_name ( ep ), strerror ( rc ) );
                return rc;
        }

        /* Clear transaction translator, if applicable */
        if ( ( rc = usb_endpoint_clear_tt ( ep ) ) != 0 )
                return rc;

        /* Clear endpoint halt, if applicable */
        type = ( ep->attributes & USB_ENDPOINT_ATTR_TYPE_MASK );
        if ( ( type != USB_ENDPOINT_ATTR_CONTROL ) &&
             ( ( rc = usb_clear_feature ( usb, USB_RECIP_ENDPOINT,
                                          USB_ENDPOINT_HALT,
                                          ep->address ) ) != 0 ) ) {
                DBGC ( usb, "USB %s %s could not clear endpoint halt: %s\n",
                       usb->name, usb_endpoint_name ( ep ), strerror ( rc ) );
                return rc;
        }

        /* Remove from list of halted endpoints */
        list_del ( &ep->halted );
        INIT_LIST_HEAD ( &ep->halted );

        DBGC ( usb, "USB %s %s reset\n",
               usb->name, usb_endpoint_name ( ep ) );
        return 0;
}
static int usb_endpoint_mtu ( struct usb_endpoint ep,
size_t  mtu 
) [static]

Update endpoint MTU.

Parameters:
epUSB endpoint
mtuNew MTU
Return values:
rcReturn status code

Definition at line 446 of file usb.c.

References DBGC, usb_endpoint::host, mtu, usb_endpoint::mtu, usb_endpoint_host_operations::mtu, usb_device::name, rc, strerror(), usb_endpoint::usb, and usb_endpoint_name().

Referenced by register_usb().

                                                                    {
        struct usb_device *usb = ep->usb;
        int rc;

        /* Update MTU */
        ep->mtu = mtu;
        if ( ( rc = ep->host->mtu ( ep ) ) != 0 ) {
                DBGC ( usb, "USB %s %s could not update MTU: %s\n",
                       usb->name, usb_endpoint_name ( ep ), strerror ( rc ) );
                return rc;
        }

        return 0;
}
int usb_message ( struct usb_endpoint ep,
unsigned int  request,
unsigned int  value,
unsigned int  index,
struct io_buffer iobuf 
)

Enqueue USB message transfer.

Parameters:
epUSB endpoint
requestRequest
valueValue parameter
indexIndex parameter
iobufI/O buffer
Return values:
rcReturn status code

The I/O buffer must have sufficient headroom to contain a setup packet.

Definition at line 474 of file usb.c.

References assert, cpu_to_le16, io_buffer::data, DBGC, usb_port::disconnected, ENODEV, usb_endpoint::fill, usb_endpoint::halted, usb_endpoint::host, usb_setup_packet::index, iob_headroom(), iob_len(), iob_push, usb_setup_packet::len, len, list_empty, memset(), usb_endpoint_host_operations::message, usb_device::name, port, usb_device::port, rc, usb_setup_packet::request, strerror(), usb_endpoint::usb, USB_DIR_IN, usb_endpoint_name(), usb_endpoint_reset(), and usb_setup_packet::value.

Referenced by usb_control().

                                            {
        struct usb_device *usb = ep->usb;
        struct usb_port *port = usb->port;
        struct usb_setup_packet *packet;
        size_t len = iob_len ( iobuf );
        int rc;

        /* Sanity check */
        assert ( iob_headroom ( iobuf ) >= sizeof ( *packet ) );

        /* Fail immediately if device has been unplugged */
        if ( port->disconnected )
                return -ENODEV;

        /* Reset endpoint if required */
        if ( ( ! list_empty ( &ep->halted ) ) &&
             ( ( rc = usb_endpoint_reset ( ep ) ) != 0 ) )
                return rc;

        /* Zero input data buffer (if applicable) */
        if ( request & USB_DIR_IN )
                memset ( iobuf->data, 0, len );

        /* Construct setup packet */
        packet = iob_push ( iobuf, sizeof ( *packet ) );
        packet->request = cpu_to_le16 ( request );
        packet->value = cpu_to_le16 ( value );
        packet->index = cpu_to_le16 ( index );
        packet->len = cpu_to_le16 ( len );

        /* Enqueue message transfer */
        if ( ( rc = ep->host->message ( ep, iobuf ) ) != 0 ) {
                DBGC ( usb, "USB %s %s could not enqueue message transfer: "
                       "%s\n", usb->name, usb_endpoint_name ( ep ),
                       strerror ( rc ) );
                return rc;
        }

        /* Increment fill level */
        ep->fill++;

        return 0;
}
int usb_stream ( struct usb_endpoint ep,
struct io_buffer iobuf,
int  terminate 
)

Enqueue USB stream transfer.

Parameters:
epUSB endpoint
iobufI/O buffer
terminateTerminate using a short packet
Return values:
rcReturn status code

Definition at line 528 of file usb.c.

References DBGC, usb_port::disconnected, ENODEV, usb_endpoint::fill, usb_endpoint::halted, usb_endpoint::host, iob_len(), list_empty, usb_endpoint::mtu, usb_device::name, port, usb_device::port, rc, usb_endpoint_host_operations::stream, strerror(), usb_endpoint::usb, usb_endpoint_name(), and usb_endpoint_reset().

Referenced by acm_out_transmit(), axge_out_transmit(), dm96xx_out_transmit(), ecm_out_transmit(), efi_usb_sync_transfer(), ncm_out_transmit(), smsc75xx_out_transmit(), smsc95xx_out_transmit(), and usb_refill().

                                 {
        struct usb_device *usb = ep->usb;
        struct usb_port *port = usb->port;
        int zlp;
        int rc;

        /* Fail immediately if device has been unplugged */
        if ( port->disconnected )
                return -ENODEV;

        /* Reset endpoint if required */
        if ( ( ! list_empty ( &ep->halted ) ) &&
             ( ( rc = usb_endpoint_reset ( ep ) ) != 0 ) )
                return rc;

        /* Append a zero-length packet if necessary */
        zlp = terminate;
        if ( iob_len ( iobuf ) & ( ep->mtu - 1 ) )
                zlp = 0;

        /* Enqueue stream transfer */
        if ( ( rc = ep->host->stream ( ep, iobuf, zlp ) ) != 0 ) {
                DBGC ( usb, "USB %s %s could not enqueue stream transfer: %s\n",
                       usb->name, usb_endpoint_name ( ep ), strerror ( rc ) );
                return rc;
        }

        /* Increment fill level */
        ep->fill++;

        return 0;
}
void usb_complete_err ( struct usb_endpoint ep,
struct io_buffer iobuf,
int  rc 
)

Complete transfer (possibly with error)

Parameters:
epUSB endpoint
iobufI/O buffer
rcCompletion status code

Definition at line 569 of file usb.c.

References assert, usb_endpoint_driver_operations::complete, DBGC, usb_endpoint::driver, usb_endpoint::fill, usb_endpoint::halted, list_add_tail, list_del, usb_device::name, usb_endpoint::open, strerror(), usb_endpoint::usb, and usb_endpoint_name().

Referenced by ehci_endpoint_close(), ehci_endpoint_poll(), uhci_endpoint_close(), uhci_endpoint_poll(), usb_complete(), usbio_bulk_in_poll(), usbio_bulk_out_poll(), usbio_control_poll(), usbio_endpoint_close(), xhci_endpoint_close(), and xhci_transfer().

                                 {
        struct usb_device *usb = ep->usb;

        /* Decrement fill level */
        assert ( ep->fill > 0 );
        ep->fill--;

        /* Schedule reset, if applicable */
        if ( ( rc != 0 ) && ep->open ) {
                DBGC ( usb, "USB %s %s completion failed: %s\n",
                       usb->name, usb_endpoint_name ( ep ), strerror ( rc ) );
                list_del ( &ep->halted );
                list_add_tail ( &ep->halted, &usb_halted );
        }

        /* Report completion */
        ep->driver->complete ( ep, iobuf, rc );
}
int usb_prefill ( struct usb_endpoint ep)

Prefill endpoint recycled buffer list.

Parameters:
epUSB endpoint
Return values:
rcReturn status code

Definition at line 602 of file usb.c.

References alloc_iob(), assert, ENOMEM, fill, usb_endpoint::fill, iob_reserve, len, usb_endpoint::len, io_buffer::list, list_add_tail, list_empty, usb_endpoint::max, usb_endpoint::mtu, rc, usb_endpoint::recycled, usb_endpoint::reserve, and usb_flush().

Referenced by efi_usb_async_start(), and ncm_in_prefill().

                                            {
        struct io_buffer *iobuf;
        size_t reserve = ep->reserve;
        size_t len = ( ep->len ? ep->len : ep->mtu );
        unsigned int fill;
        int rc;

        /* Sanity checks */
        assert ( ep->fill == 0 );
        assert ( ep->max > 0 );
        assert ( list_empty ( &ep->recycled ) );

        /* Fill recycled buffer list */
        for ( fill = 0 ; fill < ep->max ; fill++ ) {

                /* Allocate I/O buffer */
                iobuf = alloc_iob ( reserve + len );
                if ( ! iobuf ) {
                        rc = -ENOMEM;
                        goto err_alloc;
                }
                iob_reserve ( iobuf, reserve );

                /* Add to recycled buffer list */
                list_add_tail ( &iobuf->list, &ep->recycled );
        }

        return 0;

 err_alloc:
        usb_flush ( ep );
        return rc;
}
int usb_refill ( struct usb_endpoint ep)

Refill endpoint.

Parameters:
epUSB endpoint
Return values:
rcReturn status code

Definition at line 642 of file usb.c.

References alloc_iob(), assert, ENOMEM, usb_endpoint::fill, iob_len(), iob_put, iob_reserve, len, usb_endpoint::len, io_buffer::list, list_add, list_del, list_empty, list_first_entry, usb_endpoint::max, usb_endpoint::mtu, NULL, usb_endpoint::open, rc, usb_endpoint::recycled, usb_endpoint::reserve, and usb_stream().

Referenced by efi_usb_timer(), hub_refill(), usbhid_open(), usbhid_refill(), usbkbd_iskey(), usbnet_open(), and usbnet_refill().

                                           {
        struct io_buffer *iobuf;
        size_t reserve = ep->reserve;
        size_t len = ( ep->len ? ep->len : ep->mtu );
        int rc;

        /* Sanity checks */
        assert ( ep->open );
        assert ( ep->max > 0 );

        /* Refill endpoint */
        while ( ep->fill < ep->max ) {

                /* Get or allocate buffer */
                if ( list_empty ( &ep->recycled ) ) {
                        /* Recycled buffer list is empty; allocate new buffer */
                        iobuf = alloc_iob ( reserve + len );
                        if ( ! iobuf )
                                return -ENOMEM;
                        iob_reserve ( iobuf, reserve );
                } else {
                        /* Get buffer from recycled buffer list */
                        iobuf = list_first_entry ( &ep->recycled,
                                                   struct io_buffer, list );
                        assert ( iobuf != NULL );
                        list_del ( &iobuf->list );
                }

                /* Reset buffer to maximum size */
                assert ( iob_len ( iobuf ) <= len );
                iob_put ( iobuf, ( len - iob_len ( iobuf ) ) );

                /* Enqueue buffer */
                if ( ( rc = usb_stream ( ep, iobuf, 0 ) ) != 0 ) {
                        list_add ( &iobuf->list, &ep->recycled );
                        return rc;
                }
        }

        return 0;
}
void usb_flush ( struct usb_endpoint ep)

Discard endpoint recycled buffer list.

Parameters:
epUSB endpoint

Definition at line 689 of file usb.c.

References assert, free_iob(), io_buffer::list, list_del, list_for_each_entry_safe, usb_endpoint::max, usb_endpoint::open, and usb_endpoint::recycled.

Referenced by ncm_open(), usb_endpoint_close(), usb_endpoint_open(), and usb_prefill().

                                           {
        struct io_buffer *iobuf;
        struct io_buffer *tmp;

        /* Sanity checks */
        assert ( ! ep->open );
        assert ( ep->max > 0 );

        /* Free all I/O buffers */
        list_for_each_entry_safe ( iobuf, tmp, &ep->recycled, list ) {
                list_del ( &iobuf->list );
                free_iob ( iobuf );
        }
}
static void usb_control_complete ( struct usb_endpoint ep,
struct io_buffer iobuf,
int  rc 
) [static]

Complete USB control transfer.

Parameters:
epUSB endpoint
iobufI/O buffer
rcCompletion status code

Definition at line 724 of file usb.c.

References usb_device::complete, iob_push, io_buffer::list, list_add_tail, rc, usb_control_pseudo_header::rc, and usb_endpoint::usb.

                                                                     {
        struct usb_device *usb = ep->usb;
        struct usb_control_pseudo_header *pshdr;

        /* Record completion status in buffer */
        pshdr = iob_push ( iobuf, sizeof ( *pshdr ) );
        pshdr->rc = rc;

        /* Add to list of completed I/O buffers */
        list_add_tail ( &iobuf->list, &usb->complete );
}
int usb_control ( struct usb_device usb,
unsigned int  request,
unsigned int  value,
unsigned int  index,
void *  data,
size_t  len 
)

Issue USB control transaction.

Parameters:
usbUSB device
requestRequest
valueValue parameter
indexIndex parameter
dataData buffer (if any)
lenLength of data
Return values:
rcReturn status code

Definition at line 753 of file usb.c.

References alloc_iob(), assert, bus, usb_hub::bus, usb_device::complete, usb_device::control, io_buffer::data, DBGC, DBGC_HDA, ENOMEM, ETIMEDOUT, free_iob(), usb_port::hub, iob_len(), iob_pull, iob_put, iob_reserve, io_buffer::list, list_del, list_first_entry, mdelay(), memcpy(), memset(), usb_device::name, usb_device::port, rc, usb_control_pseudo_header::rc, strerror(), USB_CONTROL_MAX_WAIT_MS, USB_DIR_IN, usb_message(), and usb_poll().

Referenced by axge_read_register(), axge_write_register(), cdc_get_encapsulated_response(), cdc_send_encapsulated_command(), dm96xx_read_registers(), dm96xx_write_register(), dm96xx_write_registers(), ecm_open(), efi_usb_control_transfer(), ncm_open(), ncm_probe(), smscusb_raw_readl(), smscusb_raw_writel(), usb_clear_feature(), usb_get_descriptor(), usb_get_status(), usb_hub_clear_tt_buffer(), usb_hub_set_hub_depth(), usb_set_address(), usb_set_configuration(), usb_set_feature(), usb_set_interface(), usbhid_set_idle(), usbhid_set_protocol(), and usbhid_set_report().

                               {
        struct usb_bus *bus = usb->port->hub->bus;
        struct usb_endpoint *ep = &usb->control;
        struct io_buffer *iobuf;
        struct io_buffer *cmplt;
        union {
                struct usb_setup_packet setup;
                struct usb_control_pseudo_header pshdr;
        } *headroom;
        struct usb_control_pseudo_header *pshdr;
        unsigned int i;
        int rc;

        /* Allocate I/O buffer */
        iobuf = alloc_iob ( sizeof ( *headroom ) + len );
        if ( ! iobuf ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        iob_reserve ( iobuf, sizeof ( *headroom ) );
        iob_put ( iobuf, len );
        if ( request & USB_DIR_IN ) {
                memset ( data, 0, len );
        } else {
                memcpy ( iobuf->data, data, len );
        }

        /* Enqueue message */
        if ( ( rc = usb_message ( ep, request, value, index, iobuf ) ) != 0 )
                goto err_message;

        /* Wait for completion */
        for ( i = 0 ; i < USB_CONTROL_MAX_WAIT_MS ; i++ ) {

                /* Poll bus */
                usb_poll ( bus );

                /* Check for completion */
                while ( ( cmplt = list_first_entry ( &usb->complete,
                                                     struct io_buffer,
                                                     list ) ) ) {

                        /* Remove from completion list */
                        list_del ( &cmplt->list );

                        /* Extract and strip completion status */
                        pshdr = cmplt->data;
                        iob_pull ( cmplt, sizeof ( *pshdr ) );
                        rc = pshdr->rc;

                        /* Discard stale completions */
                        if ( cmplt != iobuf ) {
                                DBGC ( usb, "USB %s stale control completion: "
                                       "%s\n", usb->name, strerror ( rc ) );
                                DBGC_HDA ( usb, 0, cmplt->data,
                                           iob_len ( cmplt ) );
                                free_iob ( cmplt );
                                continue;
                        }

                        /* Fail immediately if completion was in error */
                        if ( rc != 0 ) {
                                DBGC ( usb, "USB %s control %04x:%04x:%04x "
                                       "failed: %s\n", usb->name, request,
                                       value, index, strerror ( rc ) );
                                free_iob ( cmplt );
                                return rc;
                        }

                        /* Copy completion to data buffer, if applicable */
                        assert ( iob_len ( cmplt ) <= len );
                        if ( request & USB_DIR_IN )
                                memcpy ( data, cmplt->data, iob_len ( cmplt ) );
                        free_iob ( cmplt );
                        return 0;
                }

                /* Delay */
                mdelay ( 1 );
        }

        DBGC ( usb, "USB %s timed out waiting for control %04x:%04x:%04x\n",
               usb->name, request, value, index );
        return -ETIMEDOUT;

 err_message:
        free_iob ( iobuf );
 err_alloc:
        return rc;
}
static unsigned int usb_get_default_language ( struct usb_device usb) [static]

Get default language ID.

Parameters:
usbUSB device
Return values:
languageLanguage ID

Definition at line 852 of file usb.c.

References __attribute__, DBGC, DBGC2, le16_to_cpu, usb_device::name, rc, strerror(), usb_get_descriptor(), USB_LANG_ENGLISH, and USB_STRING_DESCRIPTOR.

Referenced by usb_get_string_descriptor().

                                                                        {
        struct {
                struct usb_descriptor_header header;
                uint16_t language[1];
        } __attribute__ (( packed )) desc;
        unsigned int language;
        int rc;

        /* Get descriptor */
        if ( ( rc = usb_get_descriptor ( usb, 0, USB_STRING_DESCRIPTOR, 0, 0,
                                         &desc.header, sizeof ( desc ) ) ) !=0){
                DBGC ( usb, "USB %s has no default language: %s\n",
                       usb->name, strerror ( rc ) );
                return USB_LANG_ENGLISH;
        }

        /* Use first language ID */
        language = le16_to_cpu ( desc.language[0] );
        DBGC2 ( usb, "USB %s default language %#04x\n", usb->name, language );
        return language;
}
int usb_get_string_descriptor ( struct usb_device usb,
unsigned int  index,
unsigned int  language,
char *  buf,
size_t  len 
)

Get USB string descriptor.

Parameters:
usbUSB device
indexString index
languageLanguage ID, or 0 to use default
bufData buffer
lenLength of buffer
Return values:
lenString length (excluding NUL), or negative error

Definition at line 884 of file usb.c.

References __attribute__, ENOMEM, free, usb_device::language, le16_to_cpu, malloc(), max, rc, usb_get_default_language(), usb_get_descriptor(), and USB_STRING_DESCRIPTOR.

Referenced by ecm_fetch_mac().

                                                                               {
        size_t max = ( len ? ( len - 1 /* NUL */ ) : 0 );
        struct {
                struct usb_descriptor_header header;
                uint16_t character[max];
        } __attribute__ (( packed )) *desc;
        unsigned int actual;
        unsigned int i;
        int rc;

        /* Use default language ID, if applicable */
        if ( ( language == 0 ) && ( index != 0 ) ) {
                if ( ! usb->language )
                        usb->language = usb_get_default_language ( usb );
                language = usb->language;
        }

        /* Allocate buffer for string */
        desc = malloc ( sizeof ( *desc ) );
        if ( ! desc ) {
                rc = -ENOMEM;
                goto err_alloc;
        }

        /* Get descriptor */
        if ( ( rc = usb_get_descriptor ( usb, 0, USB_STRING_DESCRIPTOR, index,
                                         language, &desc->header,
                                         sizeof ( *desc ) ) ) != 0 )
                goto err_get_descriptor;

        /* Copy to buffer */
        actual = ( ( desc->header.len - sizeof ( desc->header ) ) /
                   sizeof ( desc->character[0] ) );
        for ( i = 0 ; ( ( i < actual ) && ( i < max ) ) ; i++ )
                buf[i] = le16_to_cpu ( desc->character[i] );
        if ( len )
                buf[i] = '\0';

        /* Free buffer */
        free ( desc );

        return actual;

 err_get_descriptor:
        free ( desc );
 err_alloc:
        return rc;
}
static int usb_config_descriptor ( struct usb_device usb,
unsigned int  index,
struct usb_configuration_descriptor **  config 
) [static]

Get USB configuration descriptor.

Parameters:
usbUSB device
indexConfiguration index
Return values:
configConfiguration descriptor
rcReturn status code

The configuration descriptor is dynamically allocated and must eventually be freed by the caller.

Definition at line 953 of file usb.c.

References DBGC, EINVAL, ENOMEM, free, le16_to_cpu, usb_configuration_descriptor::len, len, malloc(), usb_device::name, rc, strerror(), and usb_get_config_descriptor().

Referenced by usb_autoconfigure().

                                                                       {
        struct usb_configuration_descriptor partial;
        size_t len;
        int rc;

        /* Read first part of configuration descriptor to get size */
        if ( ( rc = usb_get_config_descriptor ( usb, index, &partial,
                                                sizeof ( partial ) ) ) != 0 ) {
                DBGC ( usb, "USB %s could not get configuration descriptor %d: "
                       "%s\n", usb->name, index, strerror ( rc ) );
                goto err_get_partial;
        }
        len = le16_to_cpu ( partial.len );
        if ( len < sizeof ( partial ) ) {
                DBGC ( usb, "USB %s underlength configuraton descriptor %d\n",
                       usb->name, index );
                rc = -EINVAL;
                goto err_partial_len;
        }

        /* Allocate buffer for whole configuration descriptor */
        *config = malloc ( len );
        if ( ! *config ) {
                rc = -ENOMEM;
                goto err_alloc_config;
        }

        /* Read whole configuration descriptor */
        if ( ( rc = usb_get_config_descriptor ( usb, index, *config,
                                                len ) ) != 0 ) {
                DBGC ( usb, "USB %s could not get configuration descriptor %d: "
                       "%s\n", usb->name, index, strerror ( rc ) );
                goto err_get_config_descriptor;
        }
        if ( (*config)->len != partial.len ) {
                DBGC ( usb, "USB %s bad configuration descriptor %d length\n",
                       usb->name, index );
                rc = -EINVAL;
                goto err_config_len;
        }

        return 0;

 err_config_len:
 err_get_config_descriptor:
        free ( *config );
 err_alloc_config:
 err_partial_len:
 err_get_partial:
        return rc;
}
static int usb_describe ( struct usb_device usb,
struct usb_configuration_descriptor config,
unsigned int  first,
uint8_t interfaces,
struct usb_function_descriptor desc 
) [static]

Describe USB function.

Parameters:
usbUSB device
configConfiguration descriptor
firstFirst interface number
interfacesInterface list to fill in
descFunction descriptor to fill in
Return values:
rcReturn status code

Definition at line 1016 of file usb.c.

References assert, usb_class::class, usb_interface_descriptor::class, usb_interface_association_descriptor::class, usb_class_descriptor::class, usb_function_descriptor::class, usb_interface_association_descriptor::count, usb_function_descriptor::count, DBGC, usb_device::device, ENOENT, ERANGE, first, usb_interface_association_descriptor::first, cdc_union_descriptor::header, cdc_union_descriptor::interface, usb_interface_descriptor::interface, usb_configuration_descriptor::interfaces, le16_to_cpu, usb_descriptor_header::len, memcpy(), memset(), usb_device::name, offsetof, usb_device_descriptor::product, usb_function_descriptor::product, USB_CLASS_CDC, usb_interface_association_descriptor(), usb_device_descriptor::vendor, and usb_function_descriptor::vendor.

Referenced by usb_probe_all(), and usb_score().

                                                                 {
        struct usb_interface_association_descriptor *association;
        struct usb_interface_descriptor *interface;
        struct cdc_union_descriptor *cdc_union;
        unsigned int i;

        /* Fill in vendor and product ID */
        memset ( desc, 0, sizeof ( *desc ) );
        desc->vendor = le16_to_cpu ( usb->device.vendor );
        desc->product = le16_to_cpu ( usb->device.product );

        /* First, look for an interface association descriptor */
        association = usb_interface_association_descriptor ( config, first );
        if ( association ) {

                /* Sanity check */
                assert ( association->first == first );
                if ( ( first + association->count ) > config->interfaces ) {
                        DBGC ( usb, "USB %s has invalid association [%d-%d)\n",
                               usb->name, first, ( first + association->count));
                        return -ERANGE;
                }

                /* Describe function */
                memcpy ( &desc->class.class, &association->class,
                         sizeof ( desc->class.class ) );
                desc->count = association->count;
                for ( i = 0 ; i < association->count ; i++ )
                        interfaces[i] = ( first + i );
                return 0;
        }

        /* Next, look for an interface descriptor */
        interface = usb_interface_descriptor ( config, first, 0 );
        if ( ! interface ) {
                DBGC ( usb, "USB %s has no descriptor for interface %d\n",
                       usb->name, first );
                return -ENOENT;
        }

        /* Describe function */
        memcpy ( &desc->class.class, &interface->class,
                 sizeof ( desc->class.class ) );
        desc->count = 1;
        interfaces[0] = first;

        /* Look for a CDC union descriptor, if applicable */
        if ( ( desc->class.class.class == USB_CLASS_CDC ) &&
             ( cdc_union = cdc_union_descriptor ( config, interface ) ) ) {

                /* Determine interface count */
                desc->count = ( ( cdc_union->header.len -
                                  offsetof ( typeof ( *cdc_union ),
                                             interface[0] ) ) /
                                sizeof ( cdc_union->interface[0] ) );
                if ( desc->count > config->interfaces ) {
                        DBGC ( usb, "USB %s has invalid union functional "
                               "descriptor with %d interfaces\n",
                               usb->name, desc->count );
                        return -ERANGE;
                }

                /* Describe function */
                for ( i = 0 ; i < desc->count ; i++ ) {
                        if ( cdc_union->interface[i] >= config->interfaces ) {
                                DBGC ( usb, "USB %s has invalid union "
                                       "functional descriptor covering "
                                       "interface %d\n", usb->name,
                                       cdc_union->interface[i] );
                                return -ERANGE;
                        }
                        interfaces[i] = cdc_union->interface[i];
                }

                return 0;
        }

        return 0;
}
static int usb_used ( struct usb_device usb,
unsigned int  count,
uint8_t interface,
uint8_t used 
) [static]

Update list of used interface.

Parameters:
usbUSB device
countNumber of interfaces
interfaceList of interfaces
usedList of already-used interfaces
Return values:
rcReturn status code

Definition at line 1108 of file usb.c.

References count, DBGC, EINVAL, and usb_device::name.

Referenced by usb_probe_all(), and usb_score().

                                                          {
        unsigned int i;

        for ( i = 0 ; i < count ; i++ ) {
                if ( used[interface[i]] ) {
                        DBGC ( usb, "USB %s interface %d already in use\n",
                               usb->name, interface[i] );
                        return -EINVAL;
                }
                used[interface[i]] = 1;
        }
        return 0;
}
struct usb_driver* usb_find_driver ( struct usb_function_descriptor desc,
struct usb_device_id **  id 
) [read]

Find USB device driver.

Parameters:
descFunction descriptor
Return values:
idUSB device ID, or NULL
driverUSB device driver, or NULL

Definition at line 1130 of file usb.c.

References usb_function_descriptor::class, usb_class_id::class, usb_driver::class, driver, for_each_table_entry, usb_driver::id_count, usb_driver::ids, usb_class_id::mask, NULL, usb_function_descriptor::product, usb_class_descriptor::scalar, USB_ANY_ID, USB_DRIVERS, and usb_function_descriptor::vendor.

Referenced by usb_probe(), usb_score(), and usbio_supported().

                                                                  {
        struct usb_driver *driver;
        unsigned int i;

        /* Look for a matching driver */
        for_each_table_entry ( driver, USB_DRIVERS ) {
                for ( i = 0 ; i < driver->id_count ; i++ ) {

                        /* Ignore non-matching driver class */
                        if ( ( driver->class.class.scalar ^ desc->class.scalar )
                             & driver->class.mask.scalar )
                                continue;

                        /* Look for a matching ID */
                        *id = &driver->ids[i];
                        if ( ( ( (*id)->vendor == desc->vendor ) ||
                               ( (*id)->vendor == USB_ANY_ID ) ) &&
                             ( ( (*id)->product == desc->product ) ||
                               ( (*id)->product == USB_ANY_ID ) ) )
                                return driver;
                }
        }

        /* Not found */
        *id = NULL;
        return NULL;
}
static int usb_score ( struct usb_device usb,
struct usb_configuration_descriptor config 
) [static]

Get USB device configuration score.

Parameters:
usbUSB device
configConfiguration descriptor
Return values:
scoreDevice configuration score, or negative error

Definition at line 1166 of file usb.c.

References usb_function_descriptor::count, driver, first, id, usb_configuration_descriptor::interfaces, memset(), rc, usb_driver::score, usb_describe(), usb_find_driver(), and usb_used().

Referenced by usb_autoconfigure().

                                                                     {
        uint8_t used[config->interfaces];
        uint8_t interface[config->interfaces];
        struct usb_function_descriptor desc;
        struct usb_driver *driver;
        struct usb_device_id *id;
        unsigned int first;
        unsigned int score = 0;
        int rc;

        /* Identify each function in turn */
        memset ( used, 0, sizeof ( used ) );
        for ( first = 0 ; first < config->interfaces ; first++ ) {

                /* Skip interfaces already used */
                if ( used[first] )
                        continue;

                /* Describe function */
                if ( ( rc = usb_describe ( usb, config, first, interface,
                                           &desc ) ) != 0 )
                        return rc;

                /* Update used interfaces */
                if ( ( rc = usb_used ( usb, desc.count, interface,
                                       used ) ) != 0 )
                        return rc;

                /* Look for a driver for this function */
                driver = usb_find_driver ( &desc, &id );
                if ( driver )
                        score += driver->score;
        }

        return score;
}
static int usb_probe ( struct usb_function func,
struct usb_configuration_descriptor config 
) [static]

Probe USB device driver.

Parameters:
funcUSB function
configConfiguration descriptor
Return values:
rcReturn status code

Definition at line 1211 of file usb.c.

References usb_class::class, usb_class_descriptor::class, usb_function_descriptor::class, DBGC, usb_function::desc, usb_function::dev, driver, usb_function::driver, device::driver_name, ENOENT, id, usb_function::id, usb_function::name, usb_device_id::name, usb_driver::probe, usb_function_descriptor::product, usb_class::protocol, rc, strerror(), usb_class::subclass, usb_function::usb, usb_find_driver(), and usb_function_descriptor::vendor.

Referenced by usb_probe_all().

                                                                     {
        struct usb_device *usb = func->usb;
        struct usb_driver *driver;
        struct usb_device_id *id;
        int rc;

        /* Identify driver */
        driver = usb_find_driver ( &func->desc, &id );
        if ( ! driver ) {
                DBGC ( usb, "USB %s %04x:%04x class %d:%d:%d has no driver\n",
                       func->name, func->desc.vendor, func->desc.product,
                       func->desc.class.class.class,
                       func->desc.class.class.subclass,
                       func->desc.class.class.protocol );
                return -ENOENT;
        }

        /* Record driver */
        func->driver = driver;
        func->id = id;
        func->dev.driver_name = id->name;

        /* Probe driver */
        if ( ( rc = driver->probe ( func, config ) ) != 0 ) {
                DBGC ( usb, "USB %s failed to probe driver %s: %s\n",
                       func->name, id->name, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static void usb_remove ( struct usb_function func) [static]

Remove USB device driver.

Parameters:
funcUSB function

Definition at line 1249 of file usb.c.

References usb_function::driver, and usb_driver::remove.

Referenced by usb_probe_all(), and usb_remove_all().

                                                     {

        /* Remove driver */
        func->driver->remove ( func );
}
static void usb_probe_all ( struct usb_device usb,
struct usb_configuration_descriptor config 
) [static]

Probe all USB device drivers.

Parameters:
usbUSB device
configConfiguration descriptor

Definition at line 1262 of file usb.c.

References usb_device::address, assert, bus, usb_hub::bus, device_description::bus_type, BUS_TYPE_USB, device::children, usb_class::class, usb_class_descriptor::class, usb_function_descriptor::class, usb_configuration_descriptor::config, usb_function_descriptor::count, DBGC, device::desc, usb_function::desc, usb_function::dev, usb_bus::dev, device_description::device, usb_device::device, device::driver_name, first, free, usb_device::functions, usb_port::hub, INIT_LIST_HEAD, usb_function::interface, usb_configuration_descriptor::interfaces, le16_to_cpu, usb_function::list, list_add_tail, list_del, device_description::location, memset(), device::name, usb_function::name, usb_device::name, device::parent, usb_device::port, usb_device_descriptor::product, usb_function_descriptor::product, usb_class::protocol, rc, device::siblings, snprintf(), usb_class::subclass, usb_function::usb, usb_describe(), usb_probe(), usb_remove(), usb_used(), device_description::vendor, usb_device_descriptor::vendor, usb_function_descriptor::vendor, and zalloc().

Referenced by usb_autoconfigure().

                                                              {
        struct usb_bus *bus = usb->port->hub->bus;
        struct usb_function *func;
        uint8_t used[config->interfaces];
        unsigned int first;
        unsigned int i;
        int rc;

        /* Identify each function in turn */
        memset ( used, 0, sizeof ( used ) );
        for ( first = 0 ; first < config->interfaces ; first++ ) {

                /* Skip interfaces already used */
                if ( used[first] )
                        continue;

                /* Allocate and initialise structure */
                func = zalloc ( sizeof ( *func ) +
                                ( config->interfaces *
                                  sizeof ( func->interface[0] ) ) );
                if ( ! func )
                        goto err_alloc;
                func->name = func->dev.name;
                func->usb = usb;
                func->dev.desc.bus_type = BUS_TYPE_USB;
                func->dev.desc.location = usb->address;
                func->dev.desc.vendor = le16_to_cpu ( usb->device.vendor );
                func->dev.desc.device = le16_to_cpu ( usb->device.product );
                snprintf ( func->dev.name, sizeof ( func->dev.name ),
                           "%s-%d.%d", usb->name, config->config, first );
                INIT_LIST_HEAD ( &func->dev.children );
                func->dev.parent = bus->dev;
                list_add_tail ( &func->list, &usb->functions );

                /* Identify function */
                if ( ( rc = usb_describe ( usb, config, first, func->interface,
                                           &func->desc ) ) != 0 )
                        goto err_describe;
                assert ( func->desc.count <= config->interfaces );

                /* Mark interfaces as used */
                if ( ( rc = usb_used ( usb, func->desc.count, func->interface,
                                       used ) ) != 0 )
                        goto err_used;

                /* Probe device driver */
                if ( ( rc = usb_probe ( func, config ) ) != 0 )
                        goto err_probe;
                DBGC ( usb, "USB %s %04x:%04x class %d:%d:%d interfaces ",
                       func->name, func->desc.vendor, func->desc.product,
                       func->desc.class.class.class,
                       func->desc.class.class.subclass,
                       func->desc.class.class.protocol );
                for ( i = 0 ; i < func->desc.count ; i++ )
                        DBGC ( usb, "%s%d", ( i ? "," : "" ),
                               func->interface[i] );
                DBGC ( usb, " using driver %s\n", func->dev.driver_name );

                /* Add to device hierarchy */
                list_add_tail ( &func->dev.siblings, &bus->dev->children );

                continue;

                list_del ( &func->dev.siblings );
                usb_remove ( func );
        err_probe:
        err_used:
        err_describe:
                list_del ( &func->list );
                free ( func );
        err_alloc:
                /* Continue registering other functions */
                continue;
        }
}
static void usb_remove_all ( struct usb_device usb) [static]

Remove all device drivers.

Parameters:
usbUSB device

Definition at line 1344 of file usb.c.

References assert, device::children, usb_function::dev, free, usb_device::functions, usb_function::list, list_del, list_empty, list_for_each_entry_safe, device::siblings, and usb_remove().

Referenced by usb_autoconfigure(), and usb_deconfigure().

                                                      {
        struct usb_function *func;
        struct usb_function *tmp;

        /* Remove all functions */
        list_for_each_entry_safe ( func, tmp, &usb->functions, list ) {

                /* Remove device driver */
                usb_remove ( func );

                /* Remove from device hierarchy */
                assert ( list_empty ( &func->dev.children ) );
                list_del ( &func->dev.siblings );

                /* Remove from list of functions */
                list_del ( &func->list );

                /* Free function */
                free ( func );
        }
}
static void usb_deconfigure ( struct usb_device usb) [static]

Clear USB device configuration.

Parameters:
usbUSB device

Definition at line 1371 of file usb.c.

References assert, usb_device::ep, NULL, USB_ENDPOINT_IDX, USB_EP0_ADDRESS, usb_remove_all(), and usb_set_configuration().

Referenced by register_usb(), and unregister_usb().

                                                       {
        unsigned int i;

        /* Remove device drivers */
        usb_remove_all ( usb );

        /* Sanity checks */
        for ( i = 0 ; i < ( sizeof ( usb->ep ) / sizeof ( usb->ep[0] ) ) ; i++){
                if ( i != USB_ENDPOINT_IDX ( USB_EP0_ADDRESS ) )
                        assert ( usb->ep[i] == NULL );
        }

        /* Clear device configuration */
        usb_set_configuration ( usb, 0 );
}
static int usb_autoconfigure ( struct usb_device usb) [static]

Choose our preferred USB device configuration.

Parameters:
usbUSB device
Return values:
rcReturn status code

Definition at line 1393 of file usb.c.

References usb_configuration_descriptor::config, usb_device_descriptor::configurations, DBGC, DBGC2, usb_device::device, free, index, usb_device::name, NULL, rc, strerror(), usb_config_descriptor(), usb_probe_all(), usb_remove_all(), usb_score(), and usb_set_configuration().

Referenced by register_usb().

                                                        {
        struct usb_configuration_descriptor *config;
        unsigned int preferred = 0;
        unsigned int index;
        int score;
        int best = 0;
        int rc;

        /* Calculate driver score for each configuration index */
        for ( index = 0 ; index < usb->device.configurations ; index++ ) {

                /* Read configuration descriptor */
                if ( ( rc = usb_config_descriptor ( usb, index,
                                                    &config ) ) != 0 )
                        goto err_config;

                /* Get score for this configuration */
                score = usb_score ( usb, config );
                if ( score < 0 ) {
                        rc = score;
                        goto err_score;
                }
                DBGC2 ( usb, "USB %s configuration %d score %d\n",
                        usb->name, config->config, score );

                /* Record as preferred configuration, if applicable */
                if ( score > best ) {
                        best = score;
                        preferred = index;
                }

                /* Free configuration descriptor */
                free ( config );
                config = NULL;
        }

        /* Read preferred configuration descriptor */
        if ( ( rc = usb_config_descriptor ( usb, preferred, &config ) ) != 0 )
                goto err_preferred;

        /* Set configuration */
        if ( ( rc = usb_set_configuration ( usb, config->config ) ) != 0){
                DBGC ( usb, "USB %s could not set configuration %d: %s\n",
                       usb->name, config->config, strerror ( rc ) );
                goto err_set_configuration;
        }

        /* Probe USB device drivers */
        usb_probe_all ( usb, config );

        /* Free configuration descriptor */
        free ( config );

        return 0;

        usb_remove_all ( usb );
        usb_set_configuration ( usb, 0 );
 err_set_configuration:
        free ( config );
 err_preferred:
        return rc;

 err_score:
        free ( config );
 err_config:
        return rc;
}
static struct usb_device* alloc_usb ( struct usb_port port) [static, read]

Allocate USB device.

Parameters:
portUSB port
Return values:
usbUSB device, or NULL on allocation failure

Definition at line 1474 of file usb.c.

References usb_port::address, bus, usb_hub::bus, usb_device::complete, usb_device::control, usb_host_operations::device, usb_device::functions, usb_device::host, usb_port::hub, INIT_LIST_HEAD, usb_device::name, usb_hub::name, NULL, usb_bus::op, port, usb_device::port, snprintf(), usb_hub::usb, usb_endpoint_init(), and zalloc().

Referenced by usb_attached().

                                                               {
        struct usb_hub *hub = port->hub;
        struct usb_bus *bus = hub->bus;
        struct usb_device *usb;

        /* Allocate and initialise structure */
        usb = zalloc ( sizeof ( *usb ) );
        if ( ! usb )
                return NULL;
        snprintf ( usb->name, sizeof ( usb->name ), "%s%c%d", hub->name,
                   ( hub->usb ? '.' : '-' ), port->address );
        usb->port = port;
        INIT_LIST_HEAD ( &usb->functions );
        usb->host = &bus->op->device;
        usb_endpoint_init ( &usb->control, usb, &usb_control_operations );
        INIT_LIST_HEAD ( &usb->complete );

        return usb;
}
static int register_usb ( struct usb_device usb) [static]

Register USB device.

Parameters:
usbUSB device
Return values:
rcReturn status code

Definition at line 1500 of file usb.c.

References usb_device::address, usb_device_host_operations::address, usb_port::address, assert, bus, usb_hub::bus, usb_class::class, usb_device_descriptor::class, usb_device_host_operations::close, usb_device::control, DBGC, DBGC2, usb_device::device, usb_bus::devices, usb_hub_driver_operations::disable, usb_hub::driver, EALREADY, usb_hub_driver_operations::enable, usb_device::host, usb_port::hub, le16_to_cpu, usb_device::list, list_add_tail, list_del, mdelay(), mtu, usb_device_descriptor::mtu, usb_endpoint::mtu, usb_device::name, usb_hub::name, NULL, usb_device_host_operations::open, port, usb_device::port, usb_device_descriptor::product, protocol, usb_class::protocol, usb_device_descriptor::protocol, rc, usb_device::speed, usb_port::speed, usb_hub_driver_operations::speed, strerror(), usb_class::subclass, usb_port::usb, usb_autoconfigure(), usb_bcd(), usb_deconfigure(), usb_endpoint_close(), usb_endpoint_describe(), usb_endpoint_mtu(), usb_endpoint_open(), USB_EP0_ADDRESS, USB_EP0_ATTRIBUTES, USB_EP0_BURST, USB_EP0_DEFAULT_MTU, USB_EP0_INTERVAL, usb_get_device_descriptor(), usb_get_mtu(), USB_PROTO_3_0, USB_RESET_RECOVER_DELAY_MS, USB_SET_ADDRESS_RECOVER_DELAY_MS, usb_speed_name(), and usb_device_descriptor::vendor.

Referenced by usb_attached().

                                                   {
        struct usb_port *port = usb->port;
        struct usb_hub *hub = port->hub;
        struct usb_bus *bus = hub->bus;
        unsigned int protocol;
        size_t mtu;
        int rc;

        /* Add to port */
        if ( port->usb != NULL ) {
                DBGC ( hub, "USB hub %s port %d is already registered to %s\n",
                       hub->name, port->address, port->usb->name );
                rc = -EALREADY;
                goto err_already;
        }
        port->usb = usb;

        /* Add to bus device list */
        list_add_tail ( &usb->list, &bus->devices );

        /* Enable device */
        if ( ( rc = hub->driver->enable ( hub, port ) ) != 0 ) {
                DBGC ( hub, "USB hub %s port %d could not enable: %s\n",
                       hub->name, port->address, strerror ( rc ) );
                goto err_enable;
        }

        /* Allow recovery interval since port may have been reset */
        mdelay ( USB_RESET_RECOVER_DELAY_MS );

        /* Get device speed */
        if ( ( rc = hub->driver->speed ( hub, port ) ) != 0 ) {
                DBGC ( hub, "USB hub %s port %d could not get speed: %s\n",
                       hub->name, port->address, strerror ( rc ) );
                goto err_speed;
        }
        usb->speed = port->speed;
        DBGC2 ( usb, "USB %s attached as %s-speed device\n",
                usb->name, usb_speed_name ( usb->speed ) );

        /* Open device */
        if ( ( rc = usb->host->open ( usb ) ) != 0 ) {
                DBGC ( usb, "USB %s could not open: %s\n",
                       usb->name, strerror ( rc ) );
                goto err_open;
        }

        /* Describe control endpoint */
        mtu = USB_EP0_DEFAULT_MTU ( usb->speed );
        usb_endpoint_describe ( &usb->control, USB_EP0_ADDRESS,
                                USB_EP0_ATTRIBUTES, mtu, USB_EP0_BURST,
                                USB_EP0_INTERVAL );

        /* Open control endpoint */
        if ( ( rc = usb_endpoint_open ( &usb->control ) ) != 0 )
                goto err_open_control;
        assert ( usb_endpoint ( usb, USB_EP0_ADDRESS ) == &usb->control );

        /* Assign device address */
        if ( ( rc = usb->host->address ( usb ) ) != 0 ) {
                DBGC ( usb, "USB %s could not set address: %s\n",
                       usb->name, strerror ( rc ) );
                goto err_address;
        }
        DBGC2 ( usb, "USB %s assigned address %d\n", usb->name, usb->address );

        /* Allow recovery interval after Set Address command */
        mdelay ( USB_SET_ADDRESS_RECOVER_DELAY_MS );

        /* Read first part of device descriptor to get EP0 MTU */
        if ( ( rc = usb_get_mtu ( usb, &usb->device ) ) != 0 ) {
                DBGC ( usb, "USB %s could not get MTU: %s\n",
                       usb->name, strerror ( rc ) );
                goto err_get_mtu;
        }

        /* Calculate EP0 MTU */
        protocol = le16_to_cpu ( usb->device.protocol );
        mtu = ( ( protocol < USB_PROTO_3_0 ) ?
                usb->device.mtu : ( 1 << usb->device.mtu ) );
        DBGC2 ( usb, "USB %s has control MTU %zd (guessed %zd)\n",
                usb->name, mtu, usb->control.mtu );

        /* Update MTU */
        if ( ( rc = usb_endpoint_mtu ( &usb->control, mtu ) ) != 0 )
                goto err_mtu;

        /* Read whole device descriptor */
        if ( ( rc = usb_get_device_descriptor ( usb, &usb->device ) ) != 0 ) {
                DBGC ( usb, "USB %s could not get device descriptor: %s\n",
                       usb->name, strerror ( rc ) );
                goto err_get_device_descriptor;
        }
        DBGC ( usb, "USB %s addr %d %04x:%04x class %d:%d:%d (v%s, %s-speed, "
               "MTU %zd)\n", usb->name, usb->address,
               le16_to_cpu ( usb->device.vendor ),
               le16_to_cpu ( usb->device.product ), usb->device.class.class,
               usb->device.class.subclass, usb->device.class.protocol,
               usb_bcd ( le16_to_cpu ( usb->device.protocol ) ),
               usb_speed_name ( usb->speed ), usb->control.mtu );

        /* Configure device */
        if ( ( rc = usb_autoconfigure ( usb ) ) != 0 )
                goto err_autoconfigure;

        return 0;

        usb_deconfigure ( usb );
 err_autoconfigure:
 err_get_device_descriptor:
 err_mtu:
 err_get_mtu:
 err_address:
        usb_endpoint_close ( &usb->control );
 err_open_control:
        usb->host->close ( usb );
 err_open:
 err_speed:
        hub->driver->disable ( hub, port );
 err_enable:
        list_del ( &usb->list );
        port->usb = NULL;
 err_already:
        return rc;
}
static void unregister_usb ( struct usb_device usb) [static]

Unregister USB device.

Parameters:
usbUSB device

Definition at line 1631 of file usb.c.

References assert, usb_device_host_operations::close, usb_device::complete, usb_device::control, usb_hub_driver_operations::disable, usb_hub::driver, free_iob(), usb_device::host, usb_port::hub, io_buffer::list, usb_device::list, list_del, list_for_each_entry_safe, NULL, port, usb_device::port, usb_port::usb, usb_deconfigure(), and usb_endpoint_close().

Referenced by usb_attached(), and usb_detached().

                                                      {
        struct usb_port *port = usb->port;
        struct usb_hub *hub = port->hub;
        struct io_buffer *iobuf;
        struct io_buffer *tmp;

        /* Sanity checks */
        assert ( port->usb == usb );

        /* Clear device configuration */
        usb_deconfigure ( usb );

        /* Close control endpoint */
        usb_endpoint_close ( &usb->control );

        /* Discard any stale control completions */
        list_for_each_entry_safe ( iobuf, tmp, &usb->complete, list ) {
                list_del ( &iobuf->list );
                free_iob ( iobuf );
        }

        /* Close device */
        usb->host->close ( usb );

        /* Disable port */
        hub->driver->disable ( hub, port );

        /* Remove from bus device list */
        list_del ( &usb->list );

        /* Remove from port */
        port->usb = NULL;
}
static void free_usb ( struct usb_device usb) [static]

Free USB device.

Parameters:
usbUSB device

Definition at line 1670 of file usb.c.

References assert, usb_device::complete, usb_device::ep, free, usb_device::functions, list_empty, and NULL.

Referenced by usb_attached(), and usb_detached().

                                                {
        unsigned int i;

        /* Sanity checks */
        for ( i = 0 ; i < ( sizeof ( usb->ep ) / sizeof ( usb->ep[0] ) ) ; i++ )
                assert ( usb->ep[i] == NULL );
        assert ( list_empty ( &usb->functions ) );
        assert ( list_empty ( &usb->complete ) );

        /* Free device */
        free ( usb );
}
static int usb_attached ( struct usb_port port) [static]

Handle newly attached USB device.

Parameters:
portUSB port
Return values:
rcReturn status code

Definition at line 1696 of file usb.c.

References alloc_usb(), assert, usb_port::attached, ENOMEM, free_usb(), NULL, rc, register_usb(), unregister_usb(), and usb_port::usb.

Referenced by usb_hotplugged().

                                                  {
        struct usb_device *usb;
        int rc;

        /* Mark port as attached */
        port->attached = 1;

        /* Sanity checks */
        assert ( port->usb == NULL );

        /* Allocate USB device */
        usb = alloc_usb ( port );
        if ( ! usb ) {
                rc = -ENOMEM;
                goto err_alloc;
        }

        /* Register USB device */
        if ( ( rc = register_usb ( usb ) ) != 0 )
                goto err_register;

        return 0;

        unregister_usb ( usb );
 err_register:
        free_usb ( usb );
 err_alloc:
        return rc;
}
static void usb_detached ( struct usb_port port) [static]

Handle newly detached USB device.

Parameters:
portUSB port

Definition at line 1731 of file usb.c.

References usb_port::attached, free_usb(), unregister_usb(), and usb_port::usb.

Referenced by unregister_usb_hub(), and usb_hotplugged().

                                                   {
        struct usb_device *usb = port->usb;

        /* Mark port as detached */
        port->attached = 0;

        /* Do nothing if we have no USB device */
        if ( ! usb )
                return;

        /* Unregister USB device */
        unregister_usb ( usb );

        /* Free USB device */
        free_usb ( usb );
}
static int usb_hotplugged ( struct usb_port port) [static]

Handle newly attached or detached USB device.

Parameters:
portUSB port
Return values:
rcReturn status code

Definition at line 1754 of file usb.c.

References usb_port::address, usb_port::attached, DBGC, usb_port::disconnected, usb_hub::driver, usb_port::hub, usb_hub::name, rc, usb_port::speed, usb_hub_driver_operations::speed, strerror(), usb_attached(), usb_detached(), and USB_SPEED_NONE.

Referenced by usb_hotplug().

                                                    {
        struct usb_hub *hub = port->hub;
        int rc;

        /* Get current port speed */
        if ( ( rc = hub->driver->speed ( hub, port ) ) != 0 ) {
                DBGC ( hub, "USB hub %s port %d could not get speed: %s\n",
                       hub->name, port->address, strerror ( rc ) );
                /* Treat as a disconnection */
                port->disconnected = 1;
                port->speed = USB_SPEED_NONE;
        }

        /* Detach device, if applicable */
        if ( port->attached && ( port->disconnected || ! port->speed ) )
                usb_detached ( port );

        /* Clear any recorded disconnections */
        port->disconnected = 0;

        /* Attach device, if applicable */
        if ( port->speed && ( ! port->attached ) &&
             ( ( rc = usb_attached ( port ) ) != 0 ) )
                return rc;

        return 0;
}
void usb_port_changed ( struct usb_port port)

Report port status change.

Parameters:
portUSB port

Definition at line 1794 of file usb.c.

References usb_port::changed, list_add_tail, and list_del.

Referenced by ehci_root_poll(), hub_complete(), register_usb_hub(), uhci_root_poll(), and xhci_port_status().

                                                {

        /* Record hub port status change */
        list_del ( &port->changed );
        list_add_tail ( &port->changed, &usb_changed );
}
static void usb_hotplug ( void  ) [static]

Handle newly attached or detached USB device.

Definition at line 1805 of file usb.c.

References assert, usb_port::changed, INIT_LIST_HEAD, list_del, list_empty, list_first_entry, NULL, port, and usb_hotplugged().

Referenced by register_usb_bus(), and usb_step().

                                 {
        struct usb_port *port;

        /* Handle any changed ports, allowing for the fact that the
         * port list may change as we perform hotplug actions.
         */
        while ( ! list_empty ( &usb_changed ) ) {

                /* Get first changed port */
                port = list_first_entry ( &usb_changed, struct usb_port,
                                          changed );
                assert ( port != NULL );

                /* Remove from list of changed ports */
                list_del ( &port->changed );
                INIT_LIST_HEAD ( &port->changed );

                /* Perform appropriate hotplug action */
                usb_hotplugged ( port );
        }
}
static void usb_step ( struct process *process  __unused) [static]

USB process.

Parameters:
processUSB process

Definition at line 1832 of file usb.c.

References bus, for_each_usb_bus, usb_endpoint::halted, list_first_entry, NULL, usb_endpoint_reset(), usb_hotplug(), and usb_poll().

                                                          {
        struct usb_bus *bus;
        struct usb_endpoint *ep;

        /* Poll all buses */
        for_each_usb_bus ( bus )
                usb_poll ( bus );

        /* Attempt to reset first halted endpoint in list, if any.  We
         * do not attempt to process the complete list, since this
         * would require extra code to allow for the facts that the
         * halted endpoint list may change as we do so, and that
         * resetting an endpoint may fail.
         */
        if ( ( ep = list_first_entry ( &usb_halted, struct usb_endpoint,
                                       halted ) ) != NULL )
                usb_endpoint_reset ( ep );

        /* Handle any changed ports */
        usb_hotplug();
}
PERMANENT_PROCESS ( usb_process  ,
usb_step   
)

USB process.

struct usb_hub* alloc_usb_hub ( struct usb_bus bus,
struct usb_device usb,
unsigned int  ports,
struct usb_hub_driver_operations driver 
) [read]

Allocate USB hub.

Parameters:
busUSB bus
usbUnderlying USB device, if any
portsNumber of ports
driverHub driver operations
Return values:
hubUSB hub, or NULL on allocation failure

Definition at line 1873 of file usb.c.

References usb_port::address, bus, usb_hub::bus, usb_port::changed, driver, usb_hub::driver, usb_hub::host, usb_port::hub, usb_host_operations::hub, INIT_LIST_HEAD, usb_device::name, usb_hub::name, usb_bus::name, NULL, usb_bus::op, port, usb_device::port, usb_hub::port, usb_hub::ports, usb_port::protocol, usb_hub::protocol, usb_port::usb, usb_hub::usb, usb_port(), and zalloc().

Referenced by alloc_usb_bus(), and hub_probe().

                                                                            {
        struct usb_hub *hub;
        struct usb_port *port;
        unsigned int i;

        /* Allocate and initialise structure */
        hub = zalloc ( sizeof ( *hub ) + ( ports * sizeof ( hub->port[0] ) ) );
        if ( ! hub )
                return NULL;
        hub->name = ( usb ? usb->name : bus->name );
        hub->bus = bus;
        hub->usb = usb;
        if ( usb )
                hub->protocol = usb->port->protocol;
        hub->ports = ports;
        hub->driver = driver;
        hub->host = &bus->op->hub;

        /* Initialise port list */
        for ( i = 1 ; i <= hub->ports ; i++ ) {
                port = usb_port ( hub, i );
                port->hub = hub;
                port->address = i;
                if ( usb )
                        port->protocol = usb->port->protocol;
                INIT_LIST_HEAD ( &port->changed );
        }

        return hub;
}
int register_usb_hub ( struct usb_hub hub)

Register USB hub.

Parameters:
hubUSB hub
Return values:
rcReturn status code

Definition at line 1912 of file usb.c.

References bus, usb_hub::bus, usb_hub_host_operations::close, usb_hub_driver_operations::close, DBGC, usb_hub::driver, usb_hub::host, usb_bus::hubs, usb_hub::list, list_add_tail, list_del, mdelay(), usb_hub::name, usb_hub_host_operations::open, usb_hub_driver_operations::open, port, usb_hub::ports, rc, strerror(), usb_poll(), usb_port(), usb_port_changed(), and USB_PORT_DELAY_MS.

Referenced by hub_probe(), and register_usb_bus().

                                             {
        struct usb_bus *bus = hub->bus;
        struct usb_port *port;
        unsigned int i;
        int rc;

        /* Add to hub list */
        list_add_tail ( &hub->list, &bus->hubs );

        /* Open hub (host controller) */
        if ( ( rc = hub->host->open ( hub ) ) != 0 ) {
                DBGC ( hub, "USB hub %s could not open: %s\n",
                       hub->name, strerror ( rc ) );
                goto err_host_open;
        }

        /* Open hub (driver) */
        if ( ( rc = hub->driver->open ( hub ) ) != 0 ) {
                DBGC ( hub, "USB hub %s could not open: %s\n",
                       hub->name, strerror ( rc ) );
                goto err_driver_open;
        }

        /* Delay to allow ports to stabilise */
        mdelay ( USB_PORT_DELAY_MS );

        /* Mark all ports as changed */
        for ( i = 1 ; i <= hub->ports ; i++ ) {
                port = usb_port ( hub, i );
                usb_port_changed ( port );
        }

        /* Some hubs seem to defer reporting device connections until
         * their interrupt endpoint is polled for the first time.
         * Poll the bus once now in order to pick up any such
         * connections.
         */
        usb_poll ( bus );

        return 0;

        hub->driver->close ( hub );
 err_driver_open:
        hub->host->close ( hub );
 err_host_open:
        list_del ( &hub->list );
        return rc;
}
void unregister_usb_hub ( struct usb_hub hub)

Unregister USB hub.

Parameters:
hubUSB hub

Definition at line 1966 of file usb.c.

References usb_port::attached, usb_port::changed, usb_hub_host_operations::close, usb_hub_driver_operations::close, usb_hub::driver, usb_hub::host, INIT_LIST_HEAD, usb_hub::list, list_del, port, usb_hub::ports, usb_detached(), and usb_port().

Referenced by hub_probe(), hub_remove(), register_usb_bus(), and unregister_usb_bus().

                                                {
        struct usb_port *port;
        unsigned int i;

        /* Detach all devices */
        for ( i = 1 ; i <= hub->ports ; i++ ) {
                port = usb_port ( hub, i );
                if ( port->attached )
                        usb_detached ( port );
        }

        /* Close hub (driver) */
        hub->driver->close ( hub );

        /* Close hub (host controller) */
        hub->host->close ( hub );

        /* Cancel any pending port status changes */
        for ( i = 1 ; i <= hub->ports ; i++ ) {
                port = usb_port ( hub, i );
                list_del ( &port->changed );
                INIT_LIST_HEAD ( &port->changed );
        }

        /* Remove from hub list */
        list_del ( &hub->list );
}
void free_usb_hub ( struct usb_hub hub)

Free USB hub.

Parameters:
hubUSB hub

Definition at line 1999 of file usb.c.

References assert, usb_port::attached, usb_port::changed, free, list_empty, NULL, port, usb_hub::ports, usb_port::usb, and usb_port().

Referenced by alloc_usb_bus(), free_usb_bus(), hub_probe(), and hub_remove().

                                          {
        struct usb_port *port;
        unsigned int i;

        /* Sanity checks */
        for ( i = 1 ; i <= hub->ports ; i++ ) {
                port = usb_port ( hub, i );
                assert ( ! port->attached );
                assert ( port->usb == NULL );
                assert ( list_empty ( &port->changed ) );
        }

        /* Free hub */
        free ( hub );
}
struct usb_bus* alloc_usb_bus ( struct device dev,
unsigned int  ports,
size_t  mtu,
struct usb_host_operations op 
) [read]

Allocate USB bus.

Parameters:
devUnderlying hardware device
portsNumber of root hub ports
mtuLargest transfer allowed on the bus
opHost controller operations
Return values:
busUSB bus, or NULL on allocation failure

Definition at line 2031 of file usb.c.

References alloc_usb_hub(), bus, usb_host_operations::bus, usb_bus::dev, usb_bus::devices, free, free_usb_hub(), usb_bus::host, usb_bus::hub, usb_bus::hubs, INIT_LIST_HEAD, mtu, usb_bus::mtu, device::name, usb_bus::name, NULL, op, usb_bus::op, usb_host_operations::root, and zalloc().

Referenced by ehci_probe(), uhci_probe(), usbio_start(), and xhci_probe().

                                                                              {
        struct usb_bus *bus;

        /* Allocate and initialise structure */
        bus = zalloc ( sizeof ( *bus ) );
        if ( ! bus )
                goto err_alloc_bus;
        bus->name = dev->name;
        bus->dev = dev;
        bus->mtu = mtu;
        bus->op = op;
        INIT_LIST_HEAD ( &bus->devices );
        INIT_LIST_HEAD ( &bus->hubs );
        bus->host = &bus->op->bus;

        /* Allocate root hub */
        bus->hub = alloc_usb_hub ( bus, NULL, ports, &op->root );
        if ( ! bus->hub )
                goto err_alloc_hub;

        return bus;

        free_usb_hub ( bus->hub );
 err_alloc_hub:
        free ( bus );
 err_alloc_bus:
        return NULL;
}
int register_usb_bus ( struct usb_bus bus)

Register USB bus.

Parameters:
busUSB bus
Return values:
rcReturn status code

Definition at line 2067 of file usb.c.

References assert, usb_bus_host_operations::close, usb_bus::host, usb_bus::hub, usb_bus::list, list_add_tail, list_del, NULL, usb_bus_host_operations::open, rc, register_usb_hub(), unregister_usb_hub(), and usb_hotplug().

Referenced by ehci_probe(), uhci_probe(), usbio_start(), and xhci_probe().

                                             {
        int rc;

        /* Sanity checks */
        assert ( bus->hub != NULL );

        /* Open bus */
        if ( ( rc = bus->host->open ( bus ) ) != 0 )
                goto err_open;

        /* Add to list of USB buses */
        list_add_tail ( &bus->list, &usb_buses );

        /* Register root hub */
        if ( ( rc = register_usb_hub ( bus->hub ) ) != 0 )
                goto err_register_hub;

        /* Attach any devices already present */
        usb_hotplug();

        return 0;

        unregister_usb_hub ( bus->hub );
 err_register_hub:
        list_del ( &bus->list );
        bus->host->close ( bus );
 err_open:
        return rc;
}
void unregister_usb_bus ( struct usb_bus bus)

Unregister USB bus.

Parameters:
busUSB bus

Definition at line 2102 of file usb.c.

References assert, usb_bus_host_operations::close, usb_bus::devices, usb_bus::host, usb_bus::hub, usb_bus::hubs, usb_bus::list, list_del, list_empty, NULL, and unregister_usb_hub().

Referenced by ehci_probe(), ehci_remove(), uhci_probe(), uhci_remove(), usbio_start(), usbio_stop(), xhci_probe(), and xhci_remove().

                                                {

        /* Sanity checks */
        assert ( bus->hub != NULL );

        /* Unregister root hub */
        unregister_usb_hub ( bus->hub );

        /* Remove from list of USB buses */
        list_del ( &bus->list );

        /* Close bus */
        bus->host->close ( bus );

        /* Sanity checks */
        assert ( list_empty ( &bus->devices ) );
        assert ( list_empty ( &bus->hubs ) );
}
void free_usb_bus ( struct usb_bus bus)

Free USB bus.

Parameters:
busUSB bus

Definition at line 2126 of file usb.c.

References assert, usb_hub::bus, usb_port::changed, usb_bus::devices, free, free_usb_hub(), usb_port::hub, usb_bus::hub, usb_bus::hubs, list_empty, list_for_each_entry, port, usb_device::port, and usb_endpoint::usb.

Referenced by ehci_probe(), ehci_remove(), uhci_probe(), uhci_remove(), usbio_start(), usbio_stop(), xhci_probe(), and xhci_remove().

                                          {
        struct usb_endpoint *ep;
        struct usb_port *port;

        /* Sanity checks */
        assert ( list_empty ( &bus->devices ) );
        assert ( list_empty ( &bus->hubs ) );
        list_for_each_entry ( ep, &usb_halted, halted )
                assert ( ep->usb->port->hub->bus != bus );
        list_for_each_entry ( port, &usb_changed, changed )
                assert ( port->hub->bus != bus );

        /* Free root hub */
        free_usb_hub ( bus->hub );

        /* Free bus */
        free ( bus );
}
struct usb_bus* find_usb_bus_by_location ( unsigned int  bus_type,
unsigned int  location 
) [read]

Find USB bus by device location.

Parameters:
bus_typeBus type
locationBus location
Return values:
busUSB bus, or NULL

Definition at line 2152 of file usb.c.

References bus, device_description::bus_type, device::desc, usb_bus::dev, for_each_usb_bus, device_description::location, and NULL.

Referenced by uhci_root_speed().

                                                                    {
        struct usb_bus *bus;

        for_each_usb_bus ( bus ) {
                if ( ( bus->dev->desc.bus_type == bus_type ) &&
                     ( bus->dev->desc.location == location ) )
                        return bus;
        }

        return NULL;
}
int usb_alloc_address ( struct usb_bus bus)

Allocate device address.

Parameters:
busUSB bus
Return values:
addressDevice address, or negative error

Definition at line 2178 of file usb.c.

References address, usb_bus::addresses, ENOENT, and ffsll.

Referenced by ehci_device_address(), and uhci_device_address().

                                              {
        unsigned int address;

        /* Find first free device address */
        address = ffsll ( ~bus->addresses );
        if ( ! address )
                return -ENOENT;

        /* Mark address as used */
        bus->addresses |= ( 1ULL << ( address - 1 ) );

        return address;
}
void usb_free_address ( struct usb_bus bus,
unsigned int  address 
)

Free device address.

Parameters:
busUSB bus
addressDevice address

Definition at line 2198 of file usb.c.

References usb_bus::addresses, and assert.

Referenced by ehci_device_address(), ehci_device_close(), uhci_device_address(), and uhci_device_close().

                                                                    {

        /* Sanity check */
        assert ( address > 0 );
        assert ( bus->addresses & ( 1ULL << ( address - 1 ) ) );

        /* Mark address as free */
        bus->addresses &= ~( 1ULL << ( address - 1 ) );
}
unsigned int usb_route_string ( struct usb_device usb)

Get USB route string.

Parameters:
usbUSB device
Return values:
routeUSB route string

Definition at line 2221 of file usb.c.

References usb_port::address, usb_port::hub, usb_device::port, route(), and usb_hub::usb.

Referenced by xhci_device_address().

                                                         {
        struct usb_device *parent;
        unsigned int route;

        /* Navigate up to root hub, constructing route string as we go */
        for ( route = 0 ; ( parent = usb->port->hub->usb ) ; usb = parent ) {
                route <<= 4;
                route |= ( ( usb->port->address > 0xf ) ?
                           0xf : usb->port->address );
        }

        return route;
}
unsigned int usb_depth ( struct usb_device usb)

Get USB depth.

Parameters:
usbUSB device
Return values:
depthHub depth

Definition at line 2241 of file usb.c.

References usb_port::hub, usb_device::port, and usb_hub::usb.

Referenced by efi_usb_install(), and hub_probe().

                                                  {
        struct usb_device *parent;
        unsigned int depth;

        /* Navigate up to root hub, constructing depth as we go */
        for ( depth = 0 ; ( parent = usb->port->hub->usb ) ; usb = parent )
                depth++;

        return depth;
}
struct usb_port* usb_root_hub_port ( struct usb_device usb) [read]

Get USB root hub port.

Parameters:
usbUSB device
Return values:
portRoot hub port

Definition at line 2258 of file usb.c.

References usb_port::hub, usb_device::port, and usb_hub::usb.

Referenced by xhci_device_address().

                                                               {
        struct usb_device *parent;

        /* Navigate up to root hub */
        while ( ( parent = usb->port->hub->usb ) )
                usb = parent;

        return usb->port;
}
struct usb_port* usb_transaction_translator ( struct usb_device usb) [read]

Get USB transaction translator.

Parameters:
usbUSB device
Return values:
portTransaction translator port, or NULL

Definition at line 2274 of file usb.c.

References usb_port::hub, NULL, usb_device::port, usb_device::speed, usb_hub::usb, and USB_SPEED_FULL.

Referenced by ehci_endpoint_capabilities(), usb_endpoint_clear_tt(), and xhci_device_open().

                                                                        {
        struct usb_device *parent;

        /* Navigate up to root hub.  If we find a low-speed or
         * full-speed device with a higher-speed parent hub, then that
         * device's port is the transaction translator.
         */
        for ( ; ( parent = usb->port->hub->usb ) ; usb = parent ) {
                if ( ( usb->speed <= USB_SPEED_FULL ) &&
                     ( parent->speed > USB_SPEED_FULL ) )
                        return usb->port;
        }

        return NULL;
}
REQUIRE_OBJECT ( config_usb  )
REQUIRE_OBJECT ( usbhub  )

Variable Documentation

List of USB buses.

Definition at line 44 of file usb.c.

List of changed ports.

Definition at line 47 of file usb.c.

List of halted endpoints.

Definition at line 50 of file usb.c.

Initial value:
 {
        .complete = usb_control_complete,
}

USB control endpoint driver operations.

Definition at line 738 of file usb.c.