Henrik Ingo
2015-12-10 12:50:17 UTC
Acer Integrated Camera 5986:055a (as found on many Lenovo E... laptops)
fails uvc_scan_chain(), but it was found that if the error is ignored
the camera works just fine. The problem is that the output terminal
baSourceID refers to an entity 6, while the entities list only contains
entities 1 to 4. This patch adds a new quirk to simply link the observed
entities as a chain 1->2->4->3.
Signed-off-by: Henrik Ingo <***@avoinelama.fi>
---
drivers/media/usb/uvc/uvc_driver.c | 30 ++++++++++++++++++++++++++++++
drivers/media/usb/uvc/uvcvideo.h | 1 +
2 files changed, 31 insertions(+)
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index fae81ef0e0d2..9d6a3a020f25 100644
--- 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) },
{}
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 816dd1a0fd81..fa2c397e6326 100644
--- 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
--
2.5.0
------------------------------------------------------------------------------
fails uvc_scan_chain(), but it was found that if the error is ignored
the camera works just fine. The problem is that the output terminal
baSourceID refers to an entity 6, while the entities list only contains
entities 1 to 4. This patch adds a new quirk to simply link the observed
entities as a chain 1->2->4->3.
Signed-off-by: Henrik Ingo <***@avoinelama.fi>
---
drivers/media/usb/uvc/uvc_driver.c | 30 ++++++++++++++++++++++++++++++
drivers/media/usb/uvc/uvcvideo.h | 1 +
2 files changed, 31 insertions(+)
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index fae81ef0e0d2..9d6a3a020f25 100644
--- 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) },
{}
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 816dd1a0fd81..fa2c397e6326 100644
--- 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
--
2.5.0
------------------------------------------------------------------------------