diff options
Diffstat (limited to 'drivers/usb/core/usb.c')
-rw-r--r-- | drivers/usb/core/usb.c | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b1b85abb9a2d..4e2c6df8d3cc 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -64,6 +64,43 @@ MODULE_PARM_DESC(autosuspend, "default autosuspend delay"); /** + * usb_find_alt_setting() - Given a configuration, find the alternate setting + * for the given interface. + * @config - the configuration to search (not necessarily the current config). + * @iface_num - interface number to search in + * @alt_num - alternate interface setting number to search for. + * + * Search the configuration's interface cache for the given alt setting. + */ +struct usb_host_interface *usb_find_alt_setting( + struct usb_host_config *config, + unsigned int iface_num, + unsigned int alt_num) +{ + struct usb_interface_cache *intf_cache = NULL; + int i; + + for (i = 0; i < config->desc.bNumInterfaces; i++) { + if (config->intf_cache[i]->altsetting[0].desc.bInterfaceNumber + == iface_num) { + intf_cache = config->intf_cache[i]; + break; + } + } + if (!intf_cache) + return NULL; + for (i = 0; i < intf_cache->num_altsetting; i++) + if (intf_cache->altsetting[i].desc.bAlternateSetting == alt_num) + return &intf_cache->altsetting[i]; + + printk(KERN_DEBUG "Did not find alt setting %u for intf %u, " + "config %u\n", alt_num, iface_num, + config->desc.bConfigurationValue); + return NULL; +} +EXPORT_SYMBOL_GPL(usb_find_alt_setting); + +/** * usb_ifnum_to_if - get the interface object with a given interface number * @dev: the device whose current configuration is considered * @ifnum: the desired interface @@ -130,24 +167,17 @@ struct usb_host_interface *usb_altnum_to_altsetting( } EXPORT_SYMBOL_GPL(usb_altnum_to_altsetting); -struct find_interface_arg { - int minor; - struct usb_interface *interface; -}; - static int __find_interface(struct device *dev, void *data) { - struct find_interface_arg *arg = data; + int *minor = data; struct usb_interface *intf; if (!is_usb_interface(dev)) return 0; intf = to_usb_interface(dev); - if (intf->minor != -1 && intf->minor == arg->minor) { - arg->interface = intf; + if (intf->minor != -1 && intf->minor == *minor) return 1; - } return 0; } @@ -156,21 +186,20 @@ static int __find_interface(struct device *dev, void *data) * @drv: the driver whose current configuration is considered * @minor: the minor number of the desired device * - * This walks the driver device list and returns a pointer to the interface + * This walks the bus device list and returns a pointer to the interface * with the matching minor. Note, this only works for devices that share the * USB major number. */ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) { - struct find_interface_arg argb; - int retval; + struct device *dev; + + dev = bus_find_device(&usb_bus_type, NULL, &minor, __find_interface); + + /* Drop reference count from bus_find_device */ + put_device(dev); - argb.minor = minor; - argb.interface = NULL; - /* eat the error, it will be in argb.interface */ - retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb, - __find_interface); - return argb.interface; + return dev ? to_usb_interface(dev) : NULL; } EXPORT_SYMBOL_GPL(usb_find_interface); @@ -1038,7 +1067,7 @@ static struct notifier_block usb_bus_nb = { struct dentry *usb_debug_root; EXPORT_SYMBOL_GPL(usb_debug_root); -struct dentry *usb_debug_devices; +static struct dentry *usb_debug_devices; static int usb_debugfs_init(void) { |