Hi Juho,

On Monday 17 November 2008, Juho Vähä-Herttua wrote:
> Hi,
>
> Now that I'm back in business with the latest repository, let's get
> back to the reason why I need to be able to keep up to date... My
> SiGma Micro camera still doesn't work with gstreamer or mplayer. The
> issue is pretty well described in the earlier post:
>
> http://lists.berlios.de/pipermail/linux-uvc-devel/2008-June/003587.html
>
> Also there is the earlier mail by Laurent that suggest a fix to the
> problem:
>
> http://lists.berlios.de/pipermail/linux-uvc-devel/2008-June/003617.html
>
> However up until today there's still no fix and my camera is still
> not fully working. Therefore I took the time to write and test a
> patch that is attached in this email. The problem of course is that
> the order of the control units is not known, so I have to do two
> scans through the list, it makes it look a bit messy.

This is not completely true. Controls are added to the entity controls list in 
ascending index order, so manual controls will always come before auto 
controls (at least for the processing unit).

> However it works again for me and that's what matters now. I hope to get
> this thing resolved some day in the official version too though. :)

Let's work on this then :-)

The patch indeed looked a bit messy at first. I've been trying to rework it 
for the past hour but ran into various issues and I now understand 
implementing a clean solution is not as easy as it might seem.

There are several places where control blacklisting can be implemented. If we 
want to use information taken from uvc_control_info (such as the control 
selector) the location you picked is the right one. However, the driver then 
needs to walk the entities and controls lists over again and free data 
allocated during the initialisation process.

Another solution would be to blacklist controls before they are allocated. We 
would then process the bmControls bitmask instead of the controls list. This 
approach is more efficient, but probably less generic as it won't allow the 
driver to blacklist controls based on advanced information taken from 
uvc_control_info.

As both solutions have advantages and drawbacks let's remember Linus Torvald 
and his famous quote about overdesign. Here's a simplified version of the 
patch that optionally (based on a device quirk) removes processing unit auto 
controls when no corresponding manual control is available.

Could you please test the patch and report the results ?

Best regards,

Laurent Pinchart
diff -r 283b73ee3b3a linux/drivers/media/video/uvc/uvc_ctrl.c
--- a/linux/drivers/media/video/uvc/uvc_ctrl.c	Mon Nov 17 22:32:11 2008 +0100
+++ b/linux/drivers/media/video/uvc/uvc_ctrl.c	Tue Nov 25 22:20:51 2008 +0100
@@ -545,9 +545,14 @@
 	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
@@ -1308,6 +1313,51 @@
 }
 
 /*
+ * Prune an entity of its bogus controls. This currently include 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->extension.bmControls;
+	size = entity->extension.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.
  */
 int uvc_ctrl_init_device(struct uvc_device *dev)
@@ -1333,6 +1383,9 @@
 			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]);
 
@@ -1347,7 +1400,7 @@
 
 		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 -r 283b73ee3b3a linux/drivers/media/video/uvc/uvc_driver.c
--- a/linux/drivers/media/video/uvc/uvc_driver.c	Mon Nov 17 22:32:11 2008 +0100
+++ b/linux/drivers/media/video/uvc/uvc_driver.c	Tue Nov 25 22:20:51 2008 +0100
@@ -1895,7 +1895,8 @@
 	  .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 -r 283b73ee3b3a linux/drivers/media/video/uvc/uvcvideo.h
--- a/linux/drivers/media/video/uvc/uvcvideo.h	Mon Nov 17 22:32:11 2008 +0100
+++ b/linux/drivers/media/video/uvc/uvcvideo.h	Tue Nov 25 22:20:51 2008 +0100
@@ -317,6 +317,7 @@
 #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
_______________________________________________
Linux-uvc-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/linux-uvc-devel

Reply via email to