Browse Source

V4L/DVB (11944): uvcvideo: Add generic control blacklist.

Another device (5986:0241) has been reported to advertise a UVC control it
does not support. Rework the control blacklist to match devices by their
VID:PID instead of trying to be clever about which controls might not be
supported properly.

Signed-off-by: Laurent Pinchart <laurent.pinchart@skynet.be>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Laurent Pinchart 16 years ago
parent
commit
d732c44c1a

+ 15 - 20
drivers/media/video/uvc/uvc_ctrl.c

@@ -1372,21 +1372,19 @@ end:
 }
 
 /*
- * 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.
+ * Prune an entity of its bogus controls using a blacklist. Bogus controls
+ * are currently the ones that crash the camera or unconditionally return an
+ * error when queried.
  */
 static void
-uvc_ctrl_prune_entity(struct uvc_entity *entity)
+uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity)
 {
 	static const struct {
-		u8 idx_manual;
-		u8 idx_auto;
+		struct usb_device_id id;
+		u8 index;
 	} blacklist[] = {
-		{ 2, 11 }, /* Hue */
-		{ 6, 12 }, /* White Balance Temperature */
-		{ 7, 13 }, /* White Balance Component */
+		{ { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */
+		{ { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */
 	};
 
 	u8 *controls;
@@ -1400,19 +1398,17 @@ uvc_ctrl_prune_entity(struct uvc_entity *entity)
 	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)
+		if (!usb_match_id(dev->intf, &blacklist[i].id))
 			continue;
 
-		if (!uvc_test_bit(controls, blacklist[i].idx_auto) ||
-		     uvc_test_bit(controls, blacklist[i].idx_manual))
+		if (blacklist[i].index >= 8 * size ||
+		    !uvc_test_bit(controls, blacklist[i].index))
 			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_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, "
+			"removing it.\n", entity->id, blacklist[i].index);
 
-		uvc_clear_bit(controls, blacklist[i].idx_auto);
+		uvc_clear_bit(controls, blacklist[i].index);
 	}
 }
 
@@ -1442,8 +1438,7 @@ 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);
+		uvc_ctrl_prune_entity(dev, entity);
 
 		for (i = 0; i < bControlSize; ++i)
 			ncontrols += hweight8(bmControls[i]);

+ 1 - 2
drivers/media/video/uvc/uvc_driver.c

@@ -1946,8 +1946,7 @@ static struct usb_device_id uvc_ids[] = {
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
-				| UVC_QUIRK_IGNORE_SELECTOR_UNIT
-				| UVC_QUIRK_PRUNE_CONTROLS },
+				| UVC_QUIRK_IGNORE_SELECTOR_UNIT },
 	/* Generic USB Video Class */
 	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
 	{}

+ 0 - 1
drivers/media/video/uvc/uvcvideo.h

@@ -313,7 +313,6 @@ 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
 #define UVC_QUIRK_FIX_BANDWIDTH		0x00000080
 
 /* Format flags */