Commit 378ca813 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB: Make usb_choose_configuration() a separate subroutine

This patch creates a separate subroutine to encapsulate the work required
in choosing an initial configuration for a device.  In my opinion that
reflects a policy decision that should be kept apart from all the other
work involved in creating a new device structure.  The existing code in
usb_new_device() is simply moved into usb_choose_configuration().
parent ad12579b
...@@ -1066,6 +1066,37 @@ static inline void usb_show_string(struct usb_device *dev, char *id, int index) ...@@ -1066,6 +1066,37 @@ static inline void usb_show_string(struct usb_device *dev, char *id, int index)
kfree(buf); kfree(buf);
} }
static int usb_choose_configuration(struct usb_device *dev)
{
int c, i;
c = dev->config[0].desc.bConfigurationValue;
if (dev->descriptor.bNumConfigurations != 1) {
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
struct usb_interface_descriptor *desc;
/* heuristic: Linux is more likely to have class
* drivers, so avoid vendor-specific interfaces.
*/
desc = &dev->config[i].intf_cache[0]
->altsetting->desc;
if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
continue;
/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */
if (desc->bInterfaceClass == USB_CLASS_COMM
&& desc->bInterfaceSubClass == 2
&& desc->bInterfaceProtocol == 0xff)
continue;
c = dev->config[i].desc.bConfigurationValue;
break;
}
dev_info(&dev->dev,
"configuration #%d chosen from %d choices\n",
c, dev->descriptor.bNumConfigurations);
}
return c;
}
/* /*
* usb_new_device - perform initial device setup (usbcore-internal) * usb_new_device - perform initial device setup (usbcore-internal)
* @dev: newly addressed device (in ADDRESS state) * @dev: newly addressed device (in ADDRESS state)
...@@ -1087,8 +1118,7 @@ static inline void usb_show_string(struct usb_device *dev, char *id, int index) ...@@ -1087,8 +1118,7 @@ static inline void usb_show_string(struct usb_device *dev, char *id, int index)
int usb_new_device(struct usb_device *dev) int usb_new_device(struct usb_device *dev)
{ {
int err; int err;
int i; int c;
int config;
err = usb_get_configuration(dev); err = usb_get_configuration(dev);
if (err < 0) { if (err < 0) {
...@@ -1122,35 +1152,10 @@ int usb_new_device(struct usb_device *dev) ...@@ -1122,35 +1152,10 @@ int usb_new_device(struct usb_device *dev)
* with the driver core, and lets usb device drivers bind to them. * with the driver core, and lets usb device drivers bind to them.
* NOTE: should interact with hub power budgeting. * NOTE: should interact with hub power budgeting.
*/ */
config = dev->config[0].desc.bConfigurationValue; c = usb_choose_configuration(dev);
if (dev->descriptor.bNumConfigurations != 1) { err = usb_set_configuration(dev, c);
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
struct usb_interface_descriptor *desc;
/* heuristic: Linux is more likely to have class
* drivers, so avoid vendor-specific interfaces.
*/
desc = &dev->config[i].intf_cache[0]
->altsetting->desc;
if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
continue;
/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */
if (desc->bInterfaceClass == USB_CLASS_COMM
&& desc->bInterfaceSubClass == 2
&& desc->bInterfaceProtocol == 0xff)
continue;
config = dev->config[i].desc.bConfigurationValue;
break;
}
dev_info(&dev->dev,
"configuration #%d chosen from %d choices\n",
config,
dev->descriptor.bNumConfigurations);
}
err = usb_set_configuration(dev, config);
if (err) { if (err) {
dev_err(&dev->dev, "can't set config #%d, error %d\n", dev_err(&dev->dev, "can't set config #%d, error %d\n", c, err);
config, err);
device_del(&dev->dev); device_del(&dev->dev);
goto fail; goto fail;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment