forked from Minki/linux
usb: core: allow a reference device for new_id
Often, usb drivers need some driver_info to get a device to work. To have access to driver_info when using new_id, allow to pass a reference vendor:product tuple from which new_id will inherit driver_info. Signed-off-by: Wolfram Sang <wsa@the-dreams.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
c63fe8f6ca
commit
2fc82c2de6
@ -50,13 +50,19 @@ Description:
|
||||
This may allow the driver to support more hardware than
|
||||
was included in the driver's static device ID support
|
||||
table at compile time. The format for the device ID is:
|
||||
idVendor idProduct bInterfaceClass.
|
||||
idVendor idProduct bInterfaceClass RefIdVendor RefIdProduct
|
||||
The vendor ID and device ID fields are required, the
|
||||
interface class is optional.
|
||||
rest is optional. The Ref* tuple can be used to tell the
|
||||
driver to use the same driver_data for the new device as
|
||||
it is used for the reference device.
|
||||
Upon successfully adding an ID, the driver will probe
|
||||
for the device and attempt to bind to it. For example:
|
||||
# echo "8086 10f5" > /sys/bus/usb/drivers/foo/new_id
|
||||
|
||||
Here add a new device (0458:7045) using driver_data from
|
||||
an already supported device (0458:704c):
|
||||
# echo "0458 7045 0 0458 704c" > /sys/bus/usb/drivers/foo/new_id
|
||||
|
||||
Reading from this file will list all dynamically added
|
||||
device IDs in the same format, with one entry per
|
||||
line. For example:
|
||||
|
@ -37,6 +37,7 @@
|
||||
* and cause the driver to probe for all devices again.
|
||||
*/
|
||||
ssize_t usb_store_new_id(struct usb_dynids *dynids,
|
||||
const struct usb_device_id *id_table,
|
||||
struct device_driver *driver,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
@ -44,11 +45,12 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
|
||||
u32 idVendor = 0;
|
||||
u32 idProduct = 0;
|
||||
unsigned int bInterfaceClass = 0;
|
||||
u32 refVendor, refProduct;
|
||||
int fields = 0;
|
||||
int retval = 0;
|
||||
|
||||
fields = sscanf(buf, "%x %x %x", &idVendor, &idProduct,
|
||||
&bInterfaceClass);
|
||||
fields = sscanf(buf, "%x %x %x %x %x", &idVendor, &idProduct,
|
||||
&bInterfaceClass, &refVendor, &refProduct);
|
||||
if (fields < 2)
|
||||
return -EINVAL;
|
||||
|
||||
@ -68,6 +70,16 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
|
||||
dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
|
||||
}
|
||||
|
||||
if (fields > 4) {
|
||||
const struct usb_device_id *id = id_table;
|
||||
|
||||
for (; id->match_flags; id++)
|
||||
if (id->idVendor == refVendor && id->idProduct == refProduct) {
|
||||
dynid->id.driver_info = id->driver_info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock(&dynids->lock);
|
||||
list_add_tail(&dynid->node, &dynids->list);
|
||||
spin_unlock(&dynids->lock);
|
||||
@ -109,7 +121,7 @@ static ssize_t new_id_store(struct device_driver *driver,
|
||||
{
|
||||
struct usb_driver *usb_drv = to_usb_driver(driver);
|
||||
|
||||
return usb_store_new_id(&usb_drv->dynids, driver, buf, count);
|
||||
return usb_store_new_id(&usb_drv->dynids, usb_drv->id_table, driver, buf, count);
|
||||
}
|
||||
static DRIVER_ATTR_RW(new_id);
|
||||
|
||||
|
@ -125,10 +125,12 @@ static ssize_t new_id_store(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);
|
||||
ssize_t retval = usb_store_new_id(&usb_drv->dynids, usb_drv->id_table,
|
||||
driver, buf, count);
|
||||
|
||||
if (retval >= 0 && usb_drv->usb_driver != NULL)
|
||||
retval = usb_store_new_id(&usb_drv->usb_driver->dynids,
|
||||
usb_drv->usb_driver->id_table,
|
||||
&usb_drv->usb_driver->drvwrap.driver,
|
||||
buf, count);
|
||||
return retval;
|
||||
|
@ -965,6 +965,7 @@ struct usb_dynid {
|
||||
};
|
||||
|
||||
extern ssize_t usb_store_new_id(struct usb_dynids *dynids,
|
||||
const struct usb_device_id *id_table,
|
||||
struct device_driver *driver,
|
||||
const char *buf, size_t count);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user