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