Refactor out the code to find alternate interface settings into usb_find_alt_setting(). Print a debugging message and return null if the alt setting is not found. While we're at it, correct a bug in the refactored code. The interfaces in the configurations' interface cache are not necessarily in numerical order, so we can't just use the interface number as an array index. Loop through the interface caches, looking for the correct interface. Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> --- Alan, I could not find a way to use usb_altnum_to_altsetting(). It takes a struct usb_interface as an argument, but the second for loop is looking through the interface cache, which contains struct usb_host_interfaces. I need to use the interface cache, since this function may be used when installing a new configuration (when usb_host_config->interface[] is not valid). Sarah drivers/usb/core/hcd.c | 12 ++---------- drivers/usb/core/usb.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/usb.h | 4 ++++ 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 34de475..abf3bfb 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1600,7 +1600,6 @@ int usb_hcd_check_bandwidth(struct usb_device *udev, struct usb_interface *new_intf) { int num_intfs, i, j; - struct usb_interface_cache *intf_cache; struct usb_host_interface *alt = 0; int ret = 0; struct usb_hcd *hcd; @@ -1648,15 +1647,8 @@ int usb_hcd_check_bandwidth(struct usb_device *udev, } } for (i = 0; i < num_intfs; ++i) { - - /* Dig the endpoints for alt setting 0 out of the - * interface cache for this interface - */ - intf_cache = new_config->intf_cache[i]; - for (j = 0; j < intf_cache->num_altsetting; j++) { - if (intf_cache->altsetting[j].desc.bAlternateSetting == 0) - alt = &intf_cache->altsetting[j]; - } + /* Set up endpoints for alternate interface setting 0 */ + alt = usb_find_alt_setting(new_config, i, 0); if (!alt) { printk(KERN_DEBUG "Did not find alt setting 0 for intf %d\n", i); continue; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b1b85ab..3fa4d3c 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 diff --git a/include/linux/usb.h b/include/linux/usb.h index a34fa89..e824908 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -626,6 +626,10 @@ extern struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev, unsigned ifnum); extern struct usb_host_interface *usb_altnum_to_altsetting( const struct usb_interface *intf, unsigned int altnum); +extern struct usb_host_interface *usb_find_alt_setting( + struct usb_host_config *config, + unsigned int iface_num, + unsigned int alt_num); /** -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html