aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers/bus
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2024-10-17 14:05:25 +0100
committerMichael Brown <mcb30@ipxe.org>2024-10-17 14:18:22 +0100
commitc219b5d8a9536cc87e9c53e8389e59c706ba3f8e (patch)
tree52d62d6941b071396ecc2d65de9c5cb5199d395f /src/drivers/bus
parent2bf16c6ffca1e294bb8233d19c9c36e43b31f041 (diff)
downloadipxe-c219b5d8a9536cc87e9c53e8389e59c706ba3f8e.tar.gz
[usb] Add "usbscan" command for iterating over USB devices
Implement a "usbscan" command as a direct analogy of the existing "pciscan" command, allowing scripts to iterate over all detected USB devices. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/bus')
-rw-r--r--src/drivers/bus/usb.c75
1 files changed, 73 insertions, 2 deletions
diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c
index 428ae26c1..e1e7d51f7 100644
--- a/src/drivers/bus/usb.c
+++ b/src/drivers/bus/usb.c
@@ -1323,7 +1323,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 +1726,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 +2135,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 +2213,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 +2251,7 @@ struct usb_bus * find_usb_bus_by_location ( unsigned int bus_type,
/******************************************************************************
*
- * USB address assignment
+ * USB device addressing
*
******************************************************************************
*/
@@ -2250,6 +2292,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