|
@@ -2013,6 +2013,7 @@ static int uvc_probe(struct usb_interface *intf,
|
|
|
{
|
|
|
struct usb_device *udev = interface_to_usbdev(intf);
|
|
|
struct uvc_device *dev;
|
|
|
+ int function;
|
|
|
int ret;
|
|
|
|
|
|
if (id->idVendor && id->idProduct)
|
|
@@ -2044,9 +2045,27 @@ static int uvc_probe(struct usb_interface *intf,
|
|
|
strlcpy(dev->name, udev->product, sizeof dev->name);
|
|
|
else
|
|
|
snprintf(dev->name, sizeof dev->name,
|
|
|
- "UVC Camera (%04x:%04x)",
|
|
|
- le16_to_cpu(udev->descriptor.idVendor),
|
|
|
- le16_to_cpu(udev->descriptor.idProduct));
|
|
|
+ "UVC Camera (%04x:%04x)",
|
|
|
+ le16_to_cpu(udev->descriptor.idVendor),
|
|
|
+ le16_to_cpu(udev->descriptor.idProduct));
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Add iFunction or iInterface to names when available as additional
|
|
|
+ * distinguishers between interfaces. iFunction is prioritized over
|
|
|
+ * iInterface which matches Windows behavior at the point of writing.
|
|
|
+ */
|
|
|
+ if (intf->intf_assoc && intf->intf_assoc->iFunction != 0)
|
|
|
+ function = intf->intf_assoc->iFunction;
|
|
|
+ else
|
|
|
+ function = intf->cur_altsetting->desc.iInterface;
|
|
|
+ if (function != 0) {
|
|
|
+ size_t len;
|
|
|
+
|
|
|
+ strlcat(dev->name, ": ", sizeof(dev->name));
|
|
|
+ len = strlen(dev->name);
|
|
|
+ usb_string(udev, function, dev->name + len,
|
|
|
+ sizeof(dev->name) - len);
|
|
|
+ }
|
|
|
|
|
|
/* Parse the Video Class control descriptor. */
|
|
|
if (uvc_parse_control(dev) < 0) {
|