diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2010-10-01 14:39:49 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-20 23:18:25 -0400 |
commit | b5977a58c330ac6afdc64bab9b1dd674f11c0635 (patch) | |
tree | 3bf9956d28f067aca41cc87e4812abfe53eda7af /drivers/media/video/uvc/uvc_ctrl.c | |
parent | 52c58ad6f95ff60343bf0c517182d5f649ca0403 (diff) |
[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>
Diffstat (limited to 'drivers/media/video/uvc/uvc_ctrl.c')
-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, | |||
1164 | * Dynamic controls | 1164 | * Dynamic controls |
1165 | */ | 1165 | */ |
1166 | 1166 | ||
1167 | static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev, | ||
1168 | const struct uvc_control *ctrl, struct uvc_control_info *info) | ||
1169 | { | ||
1170 | struct uvc_ctrl_fixup { | ||
1171 | struct usb_device_id id; | ||
1172 | u8 entity; | ||
1173 | u8 selector; | ||
1174 | u8 flags; | ||
1175 | }; | ||
1176 | |||
1177 | static const struct uvc_ctrl_fixup fixups[] = { | ||
1178 | { { USB_DEVICE(0x046d, 0x08c2) }, 9, 1, | ||
1179 | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | | ||
1180 | UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR | | ||
1181 | UVC_CONTROL_AUTO_UPDATE }, | ||
1182 | { { USB_DEVICE(0x046d, 0x08cc) }, 9, 1, | ||
1183 | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | | ||
1184 | UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR | | ||
1185 | UVC_CONTROL_AUTO_UPDATE }, | ||
1186 | { { USB_DEVICE(0x046d, 0x0994) }, 9, 1, | ||
1187 | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | | ||
1188 | UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR | | ||
1189 | UVC_CONTROL_AUTO_UPDATE }, | ||
1190 | }; | ||
1191 | |||
1192 | unsigned int i; | ||
1193 | |||
1194 | for (i = 0; i < ARRAY_SIZE(fixups); ++i) { | ||
1195 | if (!usb_match_one_id(dev->intf, &fixups[i].id)) | ||
1196 | continue; | ||
1197 | |||
1198 | if (fixups[i].entity == ctrl->entity->id && | ||
1199 | fixups[i].selector == info->selector) { | ||
1200 | info->flags = fixups[i].flags; | ||
1201 | return; | ||
1202 | } | ||
1203 | } | ||
1204 | } | ||
1205 | |||
1167 | /* | 1206 | /* |
1168 | * Query control information (size and flags) for XU controls. | 1207 | * Query control information (size and flags) for XU controls. |
1169 | */ | 1208 | */ |
@@ -1211,6 +1250,8 @@ static int uvc_ctrl_fill_xu_info(struct uvc_device *dev, | |||
1211 | | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? | 1250 | | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? |
1212 | UVC_CONTROL_AUTO_UPDATE : 0); | 1251 | UVC_CONTROL_AUTO_UPDATE : 0); |
1213 | 1252 | ||
1253 | uvc_ctrl_fixup_xu_info(dev, ctrl, info); | ||
1254 | |||
1214 | uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, " | 1255 | uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, " |
1215 | "flags { get %u set %u auto %u }.\n", | 1256 | "flags { get %u set %u auto %u }.\n", |
1216 | info->entity, info->selector, info->size, | 1257 | info->entity, info->selector, info->size, |