--- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1841,6 +1841,19 @@ static int uvc_register_chains(struct uvc_device *dev) return 0; } +static int uvc_quirk_fix_broken_chain(struct uvc_device *dev) +{ + struct uvc_entity *entity; + __u8 broken_id = 3; + + entity = uvc_entity_by_id(dev, broken_id); + if (entity == NULL) + return -EINVAL; + *(entity->baSourceID) = 4; + return 0; +} + + /* ------------------------------------------------------------------------ * USB probe, disconnect, suspend and resume */ @@ -1927,6 +1940,14 @@ static int uvc_probe(struct usb_interface *intf, if (uvc_ctrl_init_device(dev) < 0) goto error; + if (dev->quirks & UVC_QUIRK_FIX_BROKEN_CHAIN) { + if (uvc_quirk_fix_broken_chain(dev) < 0) + uvc_trace(UVC_TRACE_PROBE, + "Warning: tried to fix a broken uvc chain " + "(UVC_QUIRK_FIX_BROKEN_CHAIN), but failed. " + "Will continue probing the device, " + "but it may fail later.\n"); + } /* Scan the device for video chains. */ if (uvc_scan_device(dev) < 0) goto error; @@ -2545,6 +2566,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_FORCE_Y8 }, + /* Acer Integrated Camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x5986, + .idProduct = 0x055a, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_FIX_BROKEN_CHAIN }, /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, {} --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -152,6 +152,7 @@ #define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200 #define UVC_QUIRK_RESTORE_CTRLS_ON_INIT 0x00000400 #define UVC_QUIRK_FORCE_Y8 0x00000800 +#define UVC_QUIRK_FIX_BROKEN_CHAIN 0x00001000 /* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001