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:
 
  * 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)
 {
        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;
 
                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);
 {
        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);
 
 
                            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;
 
 };
 
 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);