From c4d99f89e20c87c8e2a992ce4cf9aa4325dc7fa7 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: Thu, 30 Sep 2010 09:04:03 -0300
Subject: [PATCH] [media] uvcvideo: Ignore GET_RES error for XU controls

GET_RES request support is mandatory for extension units, but some
cameras still choke on it (one example is the Logitech QuickCam PTZ that
returns a single byte for the PTZ relative control instead of four).

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/video/uvc/uvc_ctrl.c | 17 +++++++++++++++--
 drivers/media/video/uvc/uvcvideo.h |  1 +
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 254d32688843..3e849d977bd4 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -878,8 +878,21 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
 				     chain->dev->intfnum, ctrl->info.selector,
 				     uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES),
 				     ctrl->info.size);
-		if (ret < 0)
-			return ret;
+		if (ret < 0) {
+			if (UVC_ENTITY_TYPE(ctrl->entity) !=
+			    UVC_VC_EXTENSION_UNIT)
+				return ret;
+
+			/* GET_RES is mandatory for XU controls, but some
+			 * cameras still choke on it. Ignore errors and set the
+			 * resolution value to zero.
+			 */
+			uvc_warn_once(chain->dev, UVC_WARN_XU_GET_RES,
+				      "UVC non compliance - GET_RES failed on "
+				      "an XU control. Enabling workaround.\n");
+			memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), 0,
+			       ctrl->info.size);
+		}
 	}
 
 	ctrl->cached = 1;
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 882159aab610..2b84cbb49665 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -477,6 +477,7 @@ struct uvc_driver {
 
 #define UVC_WARN_MINMAX		0
 #define UVC_WARN_PROBE_DEF	1
+#define UVC_WARN_XU_GET_RES	2
 
 extern unsigned int uvc_clock_param;
 extern unsigned int uvc_no_drop_param;