From dba03915b35d3de6a9114ca7a8921e78e314a2f2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 6 Dec 2008 17:43:40 -0300 Subject: [PATCH] --- yaml --- r: 124335 b: refs/heads/master c: 2bdd29cf3d4d32e4371fbd6b27ea171f2c1f0836 h: refs/heads/master i: 124333: 4fe96226590da56b0a279918263c9ab0d9f27bc8 124331: b83c37bcff573e1601e8cba3d0645b55ad24524f 124327: 50d7c6d0109b9c4f91fb0765a8fdde888b171b36 124319: 5e14457705a36d28b14a76261f89918ca806003d v: v3 --- [refs] | 2 +- trunk/drivers/media/video/uvc/uvc_ctrl.c | 57 +++++++++++++++++++++- trunk/drivers/media/video/uvc/uvc_driver.c | 3 +- trunk/drivers/media/video/uvc/uvcvideo.h | 1 + 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 9acba4f39736..44c68b012b5f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0fbd8ee6de6ac3d0b93c96da848c5bc3ccc1dc83 +refs/heads/master: 2bdd29cf3d4d32e4371fbd6b27ea171f2c1f0836 diff --git a/trunk/drivers/media/video/uvc/uvc_ctrl.c b/trunk/drivers/media/video/uvc/uvc_ctrl.c index f16aafe9cf14..77b92e67953d 100644 --- a/trunk/drivers/media/video/uvc/uvc_ctrl.c +++ b/trunk/drivers/media/video/uvc/uvc_ctrl.c @@ -543,11 +543,16 @@ static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id) return ctrl->data + id * ctrl->info->size; } -static inline int uvc_get_bit(const __u8 *data, int bit) +static inline int uvc_test_bit(const __u8 *data, int bit) { return (data[bit >> 3] >> (bit & 7)) & 1; } +static inline void uvc_clear_bit(__u8 *data, int bit) +{ + data[bit >> 3] &= ~(1 << (bit & 7)); +} + /* Extract the bit string specified by mapping->offset and mapping->size * from the little-endian data stored at 'data' and return the result as * a signed 32bit integer. Sign extension will be performed if the mapping @@ -1305,6 +1310,51 @@ int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping) return ret; } +/* + * Prune an entity of its bogus controls. This currently includes processing + * unit auto controls for which no corresponding manual control is available. + * Such auto controls make little sense if any, and are known to crash at + * least the SiGma Micro webcam. + */ +static void +uvc_ctrl_prune_entity(struct uvc_entity *entity) +{ + static const struct { + u8 idx_manual; + u8 idx_auto; + } blacklist[] = { + { 2, 11 }, /* Hue */ + { 6, 12 }, /* White Balance Temperature */ + { 7, 13 }, /* White Balance Component */ + }; + + u8 *controls; + unsigned int size; + unsigned int i; + + if (UVC_ENTITY_TYPE(entity) != VC_PROCESSING_UNIT) + return; + + controls = entity->processing.bmControls; + size = entity->processing.bControlSize; + + for (i = 0; i < ARRAY_SIZE(blacklist); ++i) { + if (blacklist[i].idx_auto >= 8 * size || + blacklist[i].idx_manual >= 8 * size) + continue; + + if (!uvc_test_bit(controls, blacklist[i].idx_auto) || + uvc_test_bit(controls, blacklist[i].idx_manual)) + continue; + + uvc_trace(UVC_TRACE_CONTROL, "Auto control %u/%u has no " + "matching manual control, removing it.\n", entity->id, + blacklist[i].idx_auto); + + uvc_clear_bit(controls, blacklist[i].idx_auto); + } +} + /* * Initialize device controls. */ @@ -1331,6 +1381,9 @@ int uvc_ctrl_init_device(struct uvc_device *dev) bControlSize = entity->camera.bControlSize; } + if (dev->quirks & UVC_QUIRK_PRUNE_CONTROLS) + uvc_ctrl_prune_entity(entity); + for (i = 0; i < bControlSize; ++i) ncontrols += hweight8(bmControls[i]); @@ -1345,7 +1398,7 @@ int uvc_ctrl_init_device(struct uvc_device *dev) ctrl = entity->controls; for (i = 0; i < bControlSize * 8; ++i) { - if (uvc_get_bit(bmControls, i) == 0) + if (uvc_test_bit(bmControls, i) == 0) continue; ctrl->entity = entity; diff --git a/trunk/drivers/media/video/uvc/uvc_driver.c b/trunk/drivers/media/video/uvc/uvc_driver.c index a67533f11f2e..1054c7656aef 100644 --- a/trunk/drivers/media/video/uvc/uvc_driver.c +++ b/trunk/drivers/media/video/uvc/uvc_driver.c @@ -1894,7 +1894,8 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX - | UVC_QUIRK_IGNORE_SELECTOR_UNIT}, + | UVC_QUIRK_IGNORE_SELECTOR_UNIT + | UVC_QUIRK_PRUNE_CONTROLS }, /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, {} diff --git a/trunk/drivers/media/video/uvc/uvcvideo.h b/trunk/drivers/media/video/uvc/uvcvideo.h index 437df60e0dae..00d593776b86 100644 --- a/trunk/drivers/media/video/uvc/uvcvideo.h +++ b/trunk/drivers/media/video/uvc/uvcvideo.h @@ -316,6 +316,7 @@ struct uvc_xu_control { #define UVC_QUIRK_BUILTIN_ISIGHT 0x00000008 #define UVC_QUIRK_STREAM_NO_FID 0x00000010 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 +#define UVC_QUIRK_PRUNE_CONTROLS 0x00000040 /* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001