diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2010-10-01 15:39:49 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-21 01:18:25 -0200 |
commit | b5977a58c330ac6afdc64bab9b1dd674f11c0635 (patch) | |
tree | 3bf9956d28f067aca41cc87e4812abfe53eda7af | |
parent | 52c58ad6f95ff60343bf0c517182d5f649ca0403 (diff) | |
download | linux-b5977a58c330ac6afdc64bab9b1dd674f11c0635.tar.bz2 |
[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 <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/uvc/uvc_ctrl.c | 41 |
1 files changed, 41 insertions, 0 deletions
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, |