A number of USB drivers are unable to successfully probe a new device without some driver specific information in the driver_info field. By copying the driver_info from the first device in the static device id list, we can enable dynamic device IDs for such drivers as well. This will make the first device a generic template for dynamic IDs, with no way to specify another template device. Signed-off-by: Bjørn Mork <bjorn@xxxxxxx> --- I'd really like to see some way to make dynamic device IDs work for e.g. usbnet based minidrivers. This patch is one way to do that. Another possibility would be to let the user provide a "template device" from the driver built-in list along with the new device ID. Something like # echo "8086 10f5 8086 10f4" > /sys/bus/usb/drivers/foo/new_id where the two last numbers would specify a device already supported by the driver. This might be better for drivers with a number of different driver_info options, and would also provide support for complex class and protocol matching, as long as an existing entry has the wanted configuration. But it would make it necessary to extend the new_id interface yet again, and in a way which cannot easily be combined with the recently added interface class match. Which makes me hesitate... Therefore this patch, which is sufficient for most of the drivers. What do you think? BTW, another wishlist item is the ability to view the dynamic device list. Any objections against providing a read method for the new_id (and maybe also remove_id) file? Bjørn drivers/usb/core/driver.c | 8 +++++++- drivers/usb/serial/bus.c | 10 ++++++++-- include/linux/usb.h | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 112a7ae..c3d0924 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -40,6 +40,7 @@ */ ssize_t usb_store_new_id(struct usb_dynids *dynids, struct device_driver *driver, + kernel_ulong_t driver_info, const char *buf, size_t count) { struct usb_dynid *dynid; @@ -66,6 +67,7 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, dynid->id.bInterfaceClass = (u8)bInterfaceClass; dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS; } + dynid->id.driver_info = driver_info; spin_lock(&dynids->lock); list_add_tail(&dynid->node, &dynids->list); @@ -83,8 +85,12 @@ static ssize_t store_new_id(struct device_driver *driver, const char *buf, size_t count) { struct usb_driver *usb_drv = to_usb_driver(driver); + kernel_ulong_t driver_info = 0; - return usb_store_new_id(&usb_drv->dynids, driver, buf, count); + if (usb_drv->id_table) + driver_info = usb_drv->id_table[0].driver_info; + return usb_store_new_id(&usb_drv->dynids, driver, driver_info, + buf, count); } static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index ed8adb0..cde24cc 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -115,12 +115,18 @@ static ssize_t store_new_id(struct device_driver *driver, const char *buf, size_t count) { struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver); - ssize_t retval = usb_store_new_id(&usb_drv->dynids, driver, buf, count); + kernel_ulong_t driver_info = 0; + ssize_t retval; + + if (usb_drv->id_table) + driver_info = usb_drv->id_table[0].driver_info; + retval = usb_store_new_id(&usb_drv->dynids, driver, driver_info, + buf, count); if (retval >= 0 && usb_drv->usb_driver != NULL) retval = usb_store_new_id(&usb_drv->usb_driver->dynids, &usb_drv->usb_driver->drvwrap.driver, - buf, count); + driver_info, buf, count); return retval; } diff --git a/include/linux/usb.h b/include/linux/usb.h index 5483cd7..828062c 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -788,6 +788,7 @@ struct usb_dynid { extern ssize_t usb_store_new_id(struct usb_dynids *dynids, struct device_driver *driver, + kernel_ulong_t driver_info, const char *buf, size_t count); /** -- 1.7.10 -- 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