From b5977a58c330ac6afdc64bab9b1dd674f11c0635 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 1 Oct 2010 15:39:49 -0300 Subject: [PATCH] [media] uvcvideo: Fix bogus XU controls information XU control information is supposed to be entirely discoverable using standard UVC queries. As some devices report bogus information (such as reporting a read-only control as being read-write), add a fixup table for XU controls. This table can also be used to selectively disable requests supposed to be supported by all XU controls (GET_MIN, GET_MAX, GET_DEF, GET_RES) but not correctly (or at all) supported by the device. The table currently disables GET_CUR on the Logitech motor control XU pan/tilt controls. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index a0c9d580ca9d..0d310c422412 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -1164,6 +1164,45 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, * Dynamic controls */ +static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev, + const struct uvc_control *ctrl, struct uvc_control_info *info) +{ + struct uvc_ctrl_fixup { + struct usb_device_id id; + u8 entity; + u8 selector; + u8 flags; + }; + + static const struct uvc_ctrl_fixup fixups[] = { + { { USB_DEVICE(0x046d, 0x08c2) }, 9, 1, + UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | + UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR | + UVC_CONTROL_AUTO_UPDATE }, + { { USB_DEVICE(0x046d, 0x08cc) }, 9, 1, + UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | + UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR | + UVC_CONTROL_AUTO_UPDATE }, + { { USB_DEVICE(0x046d, 0x0994) }, 9, 1, + UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | + UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR | + UVC_CONTROL_AUTO_UPDATE }, + }; + + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(fixups); ++i) { + if (!usb_match_one_id(dev->intf, &fixups[i].id)) + continue; + + if (fixups[i].entity == ctrl->entity->id && + fixups[i].selector == info->selector) { + info->flags = fixups[i].flags; + return; + } + } +} + /* * Query control information (size and flags) for XU controls. */ @@ -1211,6 +1250,8 @@ static int uvc_ctrl_fill_xu_info(struct uvc_device *dev, | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? UVC_CONTROL_AUTO_UPDATE : 0); + uvc_ctrl_fixup_xu_info(dev, ctrl, info); + uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, " "flags { get %u set %u auto %u }.\n", info->entity, info->selector, info->size, -- 2.39.5