Commit eb912d25 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: usbcore, better heuristic for choosing configs

Until now, the Linux-USB core has always chosen the first device
configuration, even when there was a choice.  In 2.4 kernels,
device driver probe() routines were allowed to override that
initial policy decisions.  But 2.6 kernels can't do that from
probe() routines, causing problems with some CDC-ACM modems
where the first config uses MSFT-proprietary protocols.

This patch switches to a smarter heuristic:  Linux now prefers
standard interface classes when there's a choice.  So those
CDC-ACM modems don't need a "write bConfigurationValue in sysfs"
step when they are connected; they act just like on 2.4 kernels.
(And sysfs can still be used to handle any problem cases.)
parent cf1a1e3c
......@@ -991,6 +991,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
int err = -EINVAL;
int i;
int j;
int config;
/*
* Set the driver for the usb device to point to the "generic" driver.
......@@ -1105,18 +1106,30 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
/* choose and set the configuration. that registers the interfaces
* with the driver core, and lets usb device drivers bind to them.
* NOTE: should interact with hub power budgeting.
*/
config = dev->config[0].desc.bConfigurationValue;
if (dev->descriptor.bNumConfigurations != 1) {
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
/* heuristic: Linux is more likely to have class
* drivers, so avoid vendor-specific interfaces.
*/
if (dev->config[i].interface[0]->altsetting
->desc.bInterfaceClass
== USB_CLASS_VENDOR_SPEC)
continue;
config = dev->config[i].desc.bConfigurationValue;
break;
}
dev_info(&dev->dev,
"configuration #%d chosen from %d choices\n",
dev->config[0].desc.bConfigurationValue,
config,
dev->descriptor.bNumConfigurations);
}
err = usb_set_configuration(dev,
dev->config[0].desc.bConfigurationValue);
err = usb_set_configuration(dev, config);
if (err) {
dev_err(&dev->dev, "can't set config #%d, error %d\n",
dev->config[0].desc.bConfigurationValue, err);
config, err);
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