diff options
Diffstat (limited to 'src/drivers/bus/usb.c')
| -rw-r--r-- | src/drivers/bus/usb.c | 84 |
1 files changed, 77 insertions, 7 deletions
diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c index 428ae26c1..30c288df9 100644 --- a/src/drivers/bus/usb.c +++ b/src/drivers/bus/usb.c @@ -22,6 +22,7 @@ */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +FILE_SECBOOT ( PERMITTED ); #include <stdlib.h> #include <stdio.h> @@ -914,10 +915,9 @@ static unsigned int usb_get_default_language ( struct usb_device *usb ) { */ int usb_get_string_descriptor ( struct usb_device *usb, unsigned int index, unsigned int language, char *buf, size_t len ) { - size_t max = ( len ? ( len - 1 /* NUL */ ) : 0 ); struct { struct usb_descriptor_header header; - uint16_t character[max]; + uint16_t character[len]; } __attribute__ (( packed )) *desc; unsigned int actual; unsigned int i; @@ -952,10 +952,9 @@ int usb_get_string_descriptor ( struct usb_device *usb, unsigned int index, sizeof ( desc->character[0] ) ); /* Copy to buffer */ - for ( i = 0 ; ( ( i < actual ) && ( i < max ) ) ; i++ ) + memset ( buf, 0, len ); + for ( i = 0 ; ( ( i < actual ) && ( i < len ) ) ; i++ ) buf[i] = le16_to_cpu ( desc->character[i] ); - if ( len ) - buf[i] = '\0'; /* Free buffer */ free ( desc ); @@ -1323,7 +1322,8 @@ usb_probe_all ( struct usb_device *usb, 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.location = + USB_BUSDEV ( bus->address, 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 ), @@ -1725,6 +1725,25 @@ static void free_usb ( struct usb_device *usb ) { free ( usb ); } +/** + * Find USB device by address + * + * @v bus USB bus + * @v address Device address + * @ret usb USB device, or NULL if not found + */ +struct usb_device * find_usb ( struct usb_bus *bus, unsigned int address ) { + struct usb_device *usb; + + /* Search for a matching non-zero address */ + list_for_each_entry ( usb, &bus->devices, list ) { + if ( address && ( usb->address == address ) ) + return usb; + } + + return NULL; +} + /****************************************************************************** * * USB device hotplug event handling @@ -2115,6 +2134,11 @@ int register_usb_bus ( struct usb_bus *bus ) { /* Sanity checks */ assert ( bus->hub != NULL ); + /* Assign the first available bus address */ + bus->address = 0; + while ( find_usb_bus ( bus->address ) != NULL ) + bus->address++; + /* Open bus */ if ( ( rc = bus->host->open ( bus ) ) != 0 ) goto err_open; @@ -2188,6 +2212,23 @@ void free_usb_bus ( struct usb_bus *bus ) { } /** + * Find USB bus by address + * + * @v address Bus address + * @ret bus USB bus, or NULL + */ +struct usb_bus * find_usb_bus ( unsigned int address ) { + struct usb_bus *bus; + + for_each_usb_bus ( bus ) { + if ( bus->address == address ) + return bus; + } + + return NULL; +} + +/** * Find USB bus by device location * * @v bus_type Bus type @@ -2209,7 +2250,7 @@ struct usb_bus * find_usb_bus_by_location ( unsigned int bus_type, /****************************************************************************** * - * USB address assignment + * USB device addressing * ****************************************************************************** */ @@ -2250,6 +2291,35 @@ void usb_free_address ( struct usb_bus *bus, unsigned int address ) { bus->addresses &= ~( 1ULL << ( address - 1 ) ); } +/** + * Find next USB device + * + * @v usb USB device to fill in + * @v busdev Starting bus:dev address + * @ret busdev Bus:dev address of next USB device + * @ret rc Return status code + */ +int usb_find_next ( struct usb_device **usb, uint16_t *busdev ) { + struct usb_bus *bus; + + do { + /* Find USB bus, if any */ + bus = find_usb_bus ( USB_BUS ( *busdev ) ); + if ( ! bus ) { + *busdev |= ( USB_BUS ( 1 ) - 1 ); + continue; + } + + /* Find USB device, if any */ + *usb = find_usb ( bus, USB_DEV ( *busdev ) ); + if ( *usb ) + return 0; + + } while ( ++(*busdev) ); + + return -ENODEV; +} + /****************************************************************************** * * USB bus topology |
