| 1 | --- a/drivers/usb/core/usb.c |
| 2 | +++ b/drivers/usb/core/usb.c |
| 3 | @@ -653,6 +653,71 @@ int __usb_get_extra_descriptor(char *buf |
| 4 | } |
| 5 | EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor); |
| 6 | |
| 7 | +static struct usb_device *match_device_name(struct usb_device *dev, |
| 8 | + const char *name) |
| 9 | +{ |
| 10 | + struct usb_device *ret_dev = NULL; |
| 11 | + int child; |
| 12 | + |
| 13 | + dev_dbg(&dev->dev, "check for name %s ...\n", name); |
| 14 | + |
| 15 | + /* see if this device matches */ |
| 16 | + if (strcmp(dev_name(&dev->dev), name) == 0 ) { |
| 17 | + dev_dbg(&dev->dev, "matched this device!\n"); |
| 18 | + ret_dev = usb_get_dev(dev); |
| 19 | + goto exit; |
| 20 | + } |
| 21 | + |
| 22 | + /* look through all of the children of this device */ |
| 23 | + for (child = 0; child < dev->maxchild; ++child) { |
| 24 | + if (dev->children[child]) { |
| 25 | + usb_lock_device(dev->children[child]); |
| 26 | + ret_dev = match_device_name(dev->children[child], name); |
| 27 | + usb_unlock_device(dev->children[child]); |
| 28 | + if (ret_dev) |
| 29 | + goto exit; |
| 30 | + } |
| 31 | + } |
| 32 | +exit: |
| 33 | + return ret_dev; |
| 34 | +} |
| 35 | + |
| 36 | +/** |
| 37 | + * usb_find_device_by_name - find a specific usb device in the system |
| 38 | + * @name: the name of the device to find |
| 39 | + * |
| 40 | + * Returns a pointer to a struct usb_device if such a specified usb |
| 41 | + * device is present in the system currently. The usage count of the |
| 42 | + * device will be incremented if a device is found. Make sure to call |
| 43 | + * usb_put_dev() when the caller is finished with the device. |
| 44 | + * |
| 45 | + * If a device with the specified bus id is not found, NULL is returned. |
| 46 | + */ |
| 47 | +struct usb_device *usb_find_device_by_name(const char *name) |
| 48 | +{ |
| 49 | + struct list_head *buslist; |
| 50 | + struct usb_bus *bus; |
| 51 | + struct usb_device *dev = NULL; |
| 52 | + |
| 53 | + mutex_lock(&usb_bus_list_lock); |
| 54 | + for (buslist = usb_bus_list.next; |
| 55 | + buslist != &usb_bus_list; |
| 56 | + buslist = buslist->next) { |
| 57 | + bus = container_of(buslist, struct usb_bus, bus_list); |
| 58 | + if (!bus->root_hub) |
| 59 | + continue; |
| 60 | + usb_lock_device(bus->root_hub); |
| 61 | + dev = match_device_name(bus->root_hub, name); |
| 62 | + usb_unlock_device(bus->root_hub); |
| 63 | + if (dev) |
| 64 | + goto exit; |
| 65 | + } |
| 66 | +exit: |
| 67 | + mutex_unlock(&usb_bus_list_lock); |
| 68 | + return dev; |
| 69 | +} |
| 70 | +EXPORT_SYMBOL_GPL(usb_find_device_by_name); |
| 71 | + |
| 72 | /** |
| 73 | * usb_alloc_coherent - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP |
| 74 | * @dev: device the buffer will be used with |
| 75 | --- a/include/linux/usb.h |
| 76 | +++ b/include/linux/usb.h |
| 77 | @@ -584,6 +584,7 @@ extern int usb_lock_device_for_reset(str |
| 78 | extern int usb_reset_device(struct usb_device *dev); |
| 79 | extern void usb_queue_reset_device(struct usb_interface *dev); |
| 80 | |
| 81 | +extern struct usb_device *usb_find_device_by_name(const char *name); |
| 82 | |
| 83 | /* USB autosuspend and autoresume */ |
| 84 | #ifdef CONFIG_USB_SUSPEND |
| 85 | |