GWater schrieb:
I already told you that I asked scott bertin to help me with our auto-exposure problem. (Currently auto-exposure doesn't show up in v4l2ucp because it has an id which isn't queried.)

Scott Bertin answered me with a nice patch (v4l2ucp-extcontrols.patch) which led me to conlude that our code contains the problem. I found it and fixed it in the attached patch 0006. However I still face some difficulties with V4L2_CTRL_FLAG_NEXT_CTRL.

V4L2_CTRL_FLAG_NEXT_CTRL can be used by an app to automagically get the next available CID. That works fine as long as all CIDs are in a nice order like:
1,2,3,4

However in our code they are a bit mixed:
1,3,2,4

This leads to CID number 2 being missed because my algorithm can't process the fact that before CID 3 CID 2 should be sent. However CID 1 should not be sent twice.

Help me, Obi-Wan.

GWater

PS:The other patches are just there to provide a nice line from origin to patch 0006. But please free to discuss them, too.


And he's talking while he could fix it himself, ...

So here's a patch with full V4L2_CTRL_FLAG_NEXT_CTRL as described in the V4L2 spec. It is fully operational now, no more missing controls.

Have fun with auto-exposure.

I'll ask Scott Bertin to commit his own patch to v4l2ucp now with a screenshot to proof that it fixes our problems.

GWater
From d44c858d3d857506fb774805ee1694e62346827c Mon Sep 17 00:00:00 2001
From: GWater <[email protected]>
Date: Wed, 17 Dec 2008 23:07:56 +0100
Subject: [PATCH] Add support for hv7131r sensors

        devices 627c and 62bc should now work

Signed-off-by: GWater <[email protected]>
---
 Makefile       |    2 +-
 hv7131r.c      |  128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 microdia-dev.c |   14 ++++++
 microdia.h     |    7 +++
 sn9c20x.c      |   14 +-----
 5 files changed, 152 insertions(+), 13 deletions(-)
 create mode 100644 hv7131r.c

diff --git a/Makefile b/Makefile
index 379ae58..59d10ba 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ include $(src)/.config
 
 microdia-objs := microdia-usb.o microdia-v4l.o microdia-sysfs.o
 microdia-objs += microdia-dev.o microdia-queue.o
-microdia-objs += sn9c20x.o omnivision.o micron.o
+microdia-objs += sn9c20x.o omnivision.o micron.o hv7131r.o
 
 ifeq ($(CONFIG_MICRODIA_DEBUGFS),y)
 microdia-objs += microdia-debugfs.o
diff --git a/hv7131r.c b/hv7131r.c
new file mode 100644
index 0000000..ea44300
--- /dev/null
+++ b/hv7131r.c
@@ -0,0 +1,128 @@
+/**
+ * @file hv7131r.c
+ * @author GWater
+ * @date 2008-12-17
+ *
+ * @brief Common control functions the HV7131R Image Sensor
+ *
+ * @note Copyright (C) GWater
+ *
+ * @par Licences
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "microdia.h"
+#include "sn9c20x.h"
+
+static __u8 hv7131r_init[][2] = {
+       {0x02, 0x08},
+       {0x02, 0x00},
+       {0x01, 0x08},
+       {0x02, 0x00},
+       {0x20, 0x00},
+       {0x21, 0xd0},
+       {0x22, 0x00},
+       {0x23, 0x09},
+       {0x01, 0x08},
+       {0x01, 0x08},
+       {0x01, 0x08},
+       {0x25, 0x07},
+       {0x26, 0xc3},
+       {0x27, 0x50},
+       {0x30, 0x62},
+       {0x31, 0x10},
+       {0x32, 0x06},
+       {0x33, 0x10},
+       {0x20, 0x00},
+       {0x21, 0xd0},
+       {0x22, 0x00},
+       {0x23, 0x09},
+       {0x01, 0x08},
+};
+
+int hv7131r_initialize(struct usb_microdia *dev)
+{
+       int i;
+       int ret = 0;
+
+       dev->camera.i2c_flags |= SN9C20X_I2C_400KHZ;
+
+       for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
+               ret = sn9c20x_write_i2c_data(dev, 1, hv7131r_init[i][0],
+                       &hv7131r_init[i][1]);
+               if (ret < 0)
+                       goto err;
+       }
+
+       return ret;
+
+err:
+       UDIA_ERROR("Sensor Init failed (%d)! - line %d\n", ret, i);
+       return ret;
+}
+
+int hv7131r_set_exposure(struct usb_microdia *dev)
+{
+       __u8 buf[3];
+       int ret;
+       __u32 val;
+
+       val = (dev->vsettings.exposure * 0xffffff) / 0xffff;
+
+       buf[0] = (val >> 16) & 0xff;
+       buf[1] = (val >> 8) & 0xff;
+       buf[2] = val & 0xff;
+
+       ret = sn9c20x_write_i2c_data_ext(dev, 3, 0x25, buf, 0x1e);
+
+       return ret;
+}
+
+/* int hv7131r_set_gain(struct usb_microdia *dev)
+{
+       __u8 buf;
+       int ret;
+
+       buf = (dev->vsettings.gain >> 8) & 0xff;
+
+       ret = sn9c20x_write_i2c_data_ext(dev, 1, 0x30, &buf, 0x1d);
+
+       return ret;
+} */
+
+int hv7131r_set_hvflip(struct usb_microdia *dev)
+{
+       __u8 buf;
+       int ret;
+
+       ret = sn9c20x_read_i2c_data(dev, 1, 0x01, &buf);
+       if (ret < 0)
+               return ret;
+
+       if (dev->vsettings.hflip)
+               buf |= 0x02;
+       else
+               buf &= ~0x02;
+
+       if (dev->vsettings.vflip)
+               buf |= 0x01;
+       else
+               buf &= ~0x01;
+
+       ret = sn9c20x_write_i2c_data(dev, 1, 0x01, &buf);
+
+       return ret;
+}
diff --git a/microdia-dev.c b/microdia-dev.c
index 2f684ce..d16481b 100644
--- a/microdia-dev.c
+++ b/microdia-dev.c
@@ -139,6 +139,18 @@ static struct sensor_info sensors[] = {
                .hstart = 2,
                .vstart = 2,
        },
+       {
+               .id = HV7131R_SENSOR,
+               .name = "HV7131R",
+               .address = 0x11,
+               .initialize = hv7131r_initialize,
+               /* not yet available via V4L2:
+               .set_gain = hv7131r_set_gain, */
+               .set_exposure = hv7131r_set_exposure,
+               .set_hvflip = hv7131r_set_hvflip,
+               .hstart = 0,
+               .vstart = 1,
+       },
 };
 
 static __u16 known_cams[][2] = {
@@ -151,6 +163,7 @@ static __u16 known_cams[][2] = {
        {0x6253, OV9650_SENSOR},
        {0x6260, OV7670_SENSOR},
        {0x627b, OV7660_SENSOR},
+       {0x627c, HV7131R_SENSOR},
        {0x627f, OV9650_SENSOR},
        {0x6280, MT9M001_SENSOR},
        {0x6282, MT9M111_SENSOR},
@@ -160,6 +173,7 @@ static __u16 known_cams[][2] = {
        {0x62a0, OV7670_SENSOR},
        {0x62b3, OV9655_SENSOR},
        {0x62bb, OV7660_SENSOR},
+       {0x62bc, HV7131R_SENSOR},
        /* The following PIDs have VIDs different from 0x0c45. */
        {0x00f4, OV9650_SENSOR},
        {0x013d, OV7660_SENSOR},
diff --git a/microdia.h b/microdia.h
index 1134542..3f5dd7c 100644
--- a/microdia.h
+++ b/microdia.h
@@ -324,6 +324,7 @@ enum microdia_sensors {
        MT9V111_SENSOR          = 7,
        MT9V011_SENSOR          = 8,
        MT9M001_SENSOR          = 9,
+       HV7131R_SENSOR          = 10,
 };
 
 
@@ -522,4 +523,10 @@ static inline int microdia_queue_streaming(struct 
microdia_video_queue *queue)
        return queue->flags & MICRODIA_QUEUE_STREAMING;
 }
 
+/* sensor hv7131r has no header-file of its own: */
+int hv7131r_initialize(struct usb_microdia *dev);
+int hv7131r_set_exposure(struct usb_microdia *dev);
+/* int hv7131r_set_gain(struct usb_microdia *dev); */
+int hv7131r_set_hvflip(struct usb_microdia *dev);
+
 #endif
diff --git a/sn9c20x.c b/sn9c20x.c
index 328dad2..b66c1e1 100644
--- a/sn9c20x.c
+++ b/sn9c20x.c
@@ -227,17 +227,12 @@ int sn9c20x_set_LEDs(struct usb_microdia *dev, int enable)
        if (enable) {
                switch (sensor) {
                case MT9M001_SENSOR:
-                       led[0] = 0x80;
-                       led[1] = 0xa0;
-               break;
+               case HV7131R_SENSOR:
                case SOI968_SENSOR:
                        led[0] = 0x80;
                        led[1] = 0xa0;
                break;
                case MT9V011_SENSOR:
-                       led[0] = 0x40;
-                       led[1] = 0x60;
-               break;
                case OV7660_SENSOR:
                        led[0] = 0x40;
                        led[1] = 0x60;
@@ -252,18 +247,13 @@ int sn9c20x_set_LEDs(struct usb_microdia *dev, int enable)
                }
        } else {
                switch (sensor) {
+               case HV7131R_SENSOR:
                case MT9M001_SENSOR:
-                       led[0] = 0xa0;
-                       led[1] = 0xa0;
-               break;
                case MT9V011_SENSOR:
                        led[0] = 0xa0;
                        led[1] = 0xa0;
                break;
                case MT9M111_SENSOR:
-                       led[0] = 0x20;
-                       led[1] = 0x60;
-               break;
                case OV7660_SENSOR:
                        led[0] = 0x20;
                        led[1] = 0x60;
-- 
1.6.0.4

From 33746012cc98aeecd489659bb9e5422038cd7906 Mon Sep 17 00:00:00 2001
From: GWater <[email protected]>
Date: Fri, 19 Dec 2008 20:45:34 +0100
Subject: [PATCH] Add module parameter gain/V4L2_CID_GAIN

Signed-off-by: GWater <[email protected]>
---
 hv7131r.c      |    4 ++--
 microdia-dev.c |   19 +++++++++++++++++--
 microdia-usb.c |    8 ++++++++
 microdia-v4l.c |   18 ++++++++++++++++++
 microdia.h     |    5 ++++-
 5 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/hv7131r.c b/hv7131r.c
index ea44300..291fbec 100644
--- a/hv7131r.c
+++ b/hv7131r.c
@@ -91,7 +91,7 @@ int hv7131r_set_exposure(struct usb_microdia *dev)
        return ret;
 }
 
-/* int hv7131r_set_gain(struct usb_microdia *dev)
+int hv7131r_set_gain(struct usb_microdia *dev)
 {
        __u8 buf;
        int ret;
@@ -101,7 +101,7 @@ int hv7131r_set_exposure(struct usb_microdia *dev)
        ret = sn9c20x_write_i2c_data_ext(dev, 1, 0x30, &buf, 0x1d);
 
        return ret;
-} */
+}
 
 int hv7131r_set_hvflip(struct usb_microdia *dev)
 {
diff --git a/microdia-dev.c b/microdia-dev.c
index d16481b..a6070f5 100644
--- a/microdia-dev.c
+++ b/microdia-dev.c
@@ -144,8 +144,7 @@ static struct sensor_info sensors[] = {
                .name = "HV7131R",
                .address = 0x11,
                .initialize = hv7131r_initialize,
-               /* not yet available via V4L2:
-               .set_gain = hv7131r_set_gain, */
+               .set_gain = hv7131r_set_gain,
                .set_exposure = hv7131r_set_exposure,
                .set_hvflip = hv7131r_set_hvflip,
                .hstart = 0,
@@ -441,6 +440,22 @@ int dev_microdia_camera_set_exposure(struct usb_microdia 
*dev)
 }
 
 /**
+ * @brief Wrapper function for device-specific gain functions
+ *
+ * @param dev Pointer to device structure
+ *
+ * @returns 0 or negative error value
+ *
+ */
+int dev_microdia_camera_set_gain(struct usb_microdia *dev)
+{
+       if (dev && dev->camera.sensor->set_gain != NULL)
+               return dev->camera.sensor->set_gain(dev);
+
+       return 0;
+}
+
+/**
  * @brief Wrapper function for device-specific hvflip functions
  *
  * @param dev Pointer to device structure
diff --git a/microdia-usb.c b/microdia-usb.c
index e9b405b..a06bdeb 100644
--- a/microdia-usb.c
+++ b/microdia-usb.c
@@ -96,6 +96,12 @@ static int contrast = MICRODIA_PERCENT(50, 0xFFFF);
 static int exposure = MICRODIA_PERCENT(20, 0xFFFF);
 
 /**
+ * @var gain
+ *   Module parameter to set the gain
+ */
+static int gain = MICRODIA_PERCENT(20, 0xFFFF);
+
+/**
  * @var sharpness
  *   Module parameter to set the sharpness
  */
@@ -705,6 +711,7 @@ static int usb_microdia_default_settings(struct 
usb_microdia *dev)
        dev->vsettings.contrast = contrast & 0xffff;
        dev->vsettings.whiteness = whiteness & 0xffff;
        dev->vsettings.exposure = exposure & 0xffff;
+       dev->vsettings.gain = gain & 0xffff;
        dev->vsettings.sharpness = sharpness & 0x3f;
        dev->vsettings.rgb_gain[0] = (rgb_gain >> 16) & 0x7f;
        dev->vsettings.rgb_gain[1] = (rgb_gain >> 8) & 0x7f;
@@ -1023,6 +1030,7 @@ MODULE_PARM_DESC(auto_whitebalance, "Automatic 
whitebalance");    /**< @brief Descr
 MODULE_PARM_DESC(brightness, "Brightness setting");    /**< @brief Description 
of 'brightness' parameter */
 MODULE_PARM_DESC(whiteness, "Whiteness setting");      /**< @brief Description 
of 'whiteness' parameter */
 MODULE_PARM_DESC(exposure, "Exposure setting");                /**< @brief 
Description of 'exposure' parameter */
+MODULE_PARM_DESC(gain, "Gain setting");                        /**< @brief 
Description of 'gain' parameter */
 MODULE_PARM_DESC(contrast, "Contrast setting");                /**< @brief 
Description of 'contrast' parameter */
 MODULE_PARM_DESC(sharpness, "Sharpness setting");      /**< @brief Description 
of 'sharpness' parameter */
 MODULE_PARM_DESC(rgb_gain, "Red/Green/Blue Gain setting"); /**< @brief 
Description of 'RGB Gain' parameter */
diff --git a/microdia-v4l.c b/microdia-v4l.c
index 4f6f11d..7be3909 100644
--- a/microdia-v4l.c
+++ b/microdia-v4l.c
@@ -96,6 +96,15 @@ static struct v4l2_queryctrl microdia_controls[] = {
                .default_value = 0x1000,
        },
        {
+               .id      = V4L2_CID_GAIN,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Gain",
+               .minimum = 0,
+               .maximum = 0xff00,
+               .step    = 1,
+               .default_value = 0x1000,
+       },
+       {
                .id      = V4L2_CID_HFLIP,
                .type    = V4L2_CTRL_TYPE_BOOLEAN,
                .name    = "Horizontal flip",
@@ -777,6 +786,10 @@ int microdia_vidioc_g_ctrl(struct file *file, void *priv,
                ctrl->value = dev->vsettings.exposure;
                break;
 
+       case V4L2_CID_GAIN:
+               ctrl->value = dev->vsettings.gain;
+               break;
+
        case V4L2_CID_WHITENESS:
                ctrl->value = dev->vsettings.whiteness;
                break;
@@ -857,6 +870,11 @@ int microdia_vidioc_s_ctrl(struct file *file, void *priv,
                dev_microdia_camera_set_exposure(dev);
                break;
 
+       case V4L2_CID_GAIN:
+               dev->vsettings.gain = (0xff00 & ctrl->value);
+               dev_microdia_camera_set_gain(dev);
+               break;
+
        case V4L2_CID_WHITENESS:
                dev->vsettings.whiteness = (0xff00 & ctrl->value);
                dev_microdia_camera_set_gamma(dev);
diff --git a/microdia.h b/microdia.h
index 3f5dd7c..5a474b6 100644
--- a/microdia.h
+++ b/microdia.h
@@ -282,6 +282,7 @@ struct microdia_video {
        int hflip;                              /**< Horizontal flip */
        int vflip;                              /**< Vertical flip */
        int exposure;                           /**< Exposure */
+       int gain;                               /**< Gain */
        int sharpness;                          /**< Sharpness */
        __u8 rgb_gain[4];                       /**< RGB Gain (RGGB) */
        int auto_exposure;                      /**< Automatic exposure */
@@ -362,6 +363,7 @@ struct sensor_info {
 /* sensor specific functions */
        int (*initialize) (struct usb_microdia *dev);
        int (*set_exposure) (struct usb_microdia *dev);
+       int (*set_gain) (struct usb_microdia *dev);
        int (*set_auto_exposure) (struct usb_microdia *dev);
        int (*set_auto_gain) (struct usb_microdia *dev);
        int (*set_auto_whitebalance) (struct usb_microdia *dev);
@@ -467,6 +469,7 @@ int dev_microdia_camera_set_contrast(struct usb_microdia *);
 int dev_microdia_camera_set_brightness(struct usb_microdia *);
 int dev_microdia_camera_set_gamma(struct usb_microdia *);
 int dev_microdia_camera_set_exposure(struct usb_microdia *);
+int dev_microdia_camera_set_gain(struct usb_microdia *);
 int dev_microdia_camera_set_hvflip(struct usb_microdia *);
 int dev_microdia_camera_set_sharpness(struct usb_microdia *dev);
 int dev_microdia_camera_set_rgb_gain(struct usb_microdia *dev);
@@ -526,7 +529,7 @@ static inline int microdia_queue_streaming(struct 
microdia_video_queue *queue)
 /* sensor hv7131r has no header-file of its own: */
 int hv7131r_initialize(struct usb_microdia *dev);
 int hv7131r_set_exposure(struct usb_microdia *dev);
-/* int hv7131r_set_gain(struct usb_microdia *dev); */
+int hv7131r_set_gain(struct usb_microdia *dev);
 int hv7131r_set_hvflip(struct usb_microdia *dev);
 
 #endif
-- 
1.6.0.4

From 1b85a720869456c9180e12109254f330a41ef0e4 Mon Sep 17 00:00:00 2001
From: GWater <[email protected]>
Date: Fri, 19 Dec 2008 21:14:18 +0100
Subject: [PATCH] Add gain control for omnivision sensors

Signed-off-by: GWater <[email protected]>
---
 microdia-dev.c |    5 +++++
 omnivision.c   |   32 ++++++++++++++++++++++++++++++++
 omnivision.h   |    1 +
 3 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/microdia-dev.c b/microdia-dev.c
index a6070f5..c0b7cb3 100644
--- a/microdia-dev.c
+++ b/microdia-dev.c
@@ -44,6 +44,7 @@ static struct sensor_info sensors[] = {
                .set_hvflip = ov965x_set_hvflip,
                .set_exposure = ov965x_set_exposure,
                .set_auto_gain = ov_set_autogain,
+               .set_gain = ov_set_gain,
                .flip_detect = ov965x_flip_detect,
                .get_yavg = ov965x_get_yavg,
                .min_yavg = 30,
@@ -58,6 +59,7 @@ static struct sensor_info sensors[] = {
                .initialize = ov_initialize,
                .set_auto_exposure = ov_set_autoexposure,
                .set_auto_gain = ov_set_autogain,
+               .set_gain = ov_set_gain,
                .hstart = 0,
                .vstart = 7,
        },
@@ -69,6 +71,7 @@ static struct sensor_info sensors[] = {
                .set_exposure = soi968_set_exposure,
                .set_auto_exposure = ov_set_autoexposure,
                .set_auto_gain = ov_set_autogain,
+               .set_gain = ov_set_gain,
                .button_detect = soi968_button_detect,
                .hstart = 60,
                .vstart = 11,
@@ -80,6 +83,7 @@ static struct sensor_info sensors[] = {
                .initialize = ov_initialize,
                .set_exposure = ov7660_set_exposure,
                .set_auto_gain = ov_set_autogain,
+               .set_gain = ov_set_gain,
                .hstart = 1,
                .vstart = 1,
                .get_yavg = ov965x_get_yavg,
@@ -96,6 +100,7 @@ static struct sensor_info sensors[] = {
                .set_auto_exposure = ov_set_autoexposure,
                .set_exposure = ov7660_set_exposure,
                .set_auto_gain = ov_set_autogain,
+               .set_gain = ov_set_gain,
                .flip_detect = ov7670_flip_detect,
                .hstart = 0,
                .vstart = 1,
diff --git a/omnivision.c b/omnivision.c
index 7cfc230..b67742f 100644
--- a/omnivision.c
+++ b/omnivision.c
@@ -892,6 +892,38 @@ int soi968_set_exposure(struct usb_microdia *dev)
        return 0;
 }
 
+int ov_set_gain(struct usb_microdia *dev)
+{
+       __u8 buf, buf2;
+       int ret;
+       __u16 val = dev->vsettings.gain;
+
+       switch (dev->camera.sensor->id) {
+       case SOI968_SENSOR:
+               buf = (val >> 10) & 0x3f;
+       break;
+       case OV7660_SENSOR:
+               buf = (val >> 9) & 0x7f;
+       break;
+       case OV7670_SENSOR:
+               buf = (val >> 6) & 0xff;
+               ret = sn9c20x_read_i2c_data(dev, 1, 0x03, &buf2);
+               if (ret < 0)
+                       return ret;
+               buf2 |= ((val >> 8) & 0xc0);
+               ret = sn9c20x_write_i2c_data(dev, 1, 0x03, &buf2);
+               if (ret < 0)
+                       return ret;
+       break;
+       default:
+               buf = (val >> 8) & 0xff;
+       }
+
+       ret = sn9c20x_write_i2c_data(dev, 1, 0x00, &buf);
+
+       return ret;
+}
+
 /**
  * @brief Detect whether the image for 6260 has to be flipped
  *
diff --git a/omnivision.h b/omnivision.h
index 391fbf1..5840fb7 100644
--- a/omnivision.h
+++ b/omnivision.h
@@ -550,4 +550,5 @@ int ov965x_get_yavg(struct usb_microdia *dev);
 int ov_initialize(struct usb_microdia *dev);
 int ov_set_autogain(struct usb_microdia *dev);
 int ov_set_autoexposure(struct usb_microdia *dev);
+int ov_set_gain(struct usb_microdia *dev);
 #endif
-- 
1.6.0.4

From 1357d1e426eb80f5de9a6fb40092fa2828a25a86 Mon Sep 17 00:00:00 2001
From: GWater <[email protected]>
Date: Fri, 19 Dec 2008 21:58:36 +0100
Subject: [PATCH] YUV422 omnivision sensors

        This patch is based on an older version by
        Brian Johnson <[email protected]> .

Signed-off-by: GWater <[email protected]>
---
 microdia-dev.c |    2 ++
 microdia-v4l.c |    9 +++++++--
 omnivision.c   |   23 +++++++++++++++++++++--
 omnivision.h   |    3 +++
 4 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/microdia-dev.c b/microdia-dev.c
index c0b7cb3..b17e921 100644
--- a/microdia-dev.c
+++ b/microdia-dev.c
@@ -51,6 +51,8 @@ static struct sensor_info sensors[] = {
                .max_yavg = 60,
                .min_stable_yavg = 32,
                .max_stable_yavg = 58,
+               .set_yuv422 = ov965x_set_yuv422,
+               .set_bayer = ov965x_set_bayer,
        },
        {
                .id = OV9655_SENSOR,
diff --git a/microdia-v4l.c b/microdia-v4l.c
index 7be3909..1985fa3 100644
--- a/microdia-v4l.c
+++ b/microdia-v4l.c
@@ -374,9 +374,13 @@ int v4l2_enable_video(struct usb_microdia *dev, int mode)
 
        dev_microdia_enable_video(dev, 1);
        dev_microdia_camera_settings(dev);
-       dev->queue.flags &= ~MICRODIA_QUEUE_DROP_INCOMPLETE;
        dev->mode = mode;
 
+       if(dev->vsettings.format.pixelformat == V4L2_PIX_FMT_JPEG)
+               dev->queue.flags &= ~MICRODIA_QUEUE_DROP_INCOMPLETE;
+       else
+               dev->queue.flags |= MICRODIA_QUEUE_DROP_INCOMPLETE;
+
        return 0;
 }
 
@@ -1061,9 +1065,10 @@ int microdia_vidioc_s_fmt_cap(struct file *file, void 
*priv,
        if (ret)
                return -EINVAL;
 
+       memcpy(&(dev->vsettings.format), &(fmt->fmt.pix), sizeof(fmt->fmt.pix));
+
        sn9c20x_set_resolution(dev, fmt->fmt.pix.width, fmt->fmt.pix.height);
        dev->camera.fmts[fmt->fmt.pix.priv].set_format(dev);
-       memcpy(&(dev->vsettings.format), &(fmt->fmt.pix), sizeof(fmt->fmt.pix));
 
        return 0;
 }
diff --git a/omnivision.c b/omnivision.c
index b67742f..eb6bd5c 100644
--- a/omnivision.c
+++ b/omnivision.c
@@ -352,8 +352,7 @@ static __u8 ov9650_init[][2] = {
        {OV965X_CTL_ADC, 0x00}, /* reserved */
        {OV965X_CTL_ACOM, 0x93}, /* reserved */
        {OV965X_CTL_OFON, 0x50},
-       {OV965X_CTL_TSLB, OV965X_TSLB_OUTPUT_SEQ_UYVY |
-                         OV965X_TSLB_DIGITAL_BLC_ENABLE},
+       {OV965X_CTL_TSLB, OV965X_TSLB_DIGITAL_BLC_ENABLE},
        {OV965X_CTL_COM11, OV965X_COM11_MANUAL_BANDING_FILTER},
        {OV965X_CTL_COM12, 0x73},
        {OV965X_CTL_COM13, OV965X_COM13_ENABLE_COLOR_MATRIX |
@@ -810,6 +809,26 @@ int ov_set_autoexposure(struct usb_microdia *dev)
        return ret;
 }
 
+int ov965x_set_yuv422(struct usb_microdia *dev)
+{
+       __u8 buf = OV965X_COM7_OUTPUT_VGA;
+       sn9c20x_write_i2c_data(dev, 1, 0x12, &buf);
+
+       sn9c20x_set_raw(dev);
+
+       return 0;
+}
+
+int ov965x_set_bayer(struct usb_microdia *dev)
+{
+       __u8 buf = OV965X_COM7_OUTPUT_RAW_RGB;
+       sn9c20x_write_i2c_data(dev, 1, 0x12, &buf);
+
+       sn9c20x_set_raw(dev);
+
+       return 0;
+}
+
 /**
  * @brief Set autogain for omnivision sensors
  *
diff --git a/omnivision.h b/omnivision.h
index 5840fb7..5246275 100644
--- a/omnivision.h
+++ b/omnivision.h
@@ -546,6 +546,9 @@ int ov965x_set_hvflip(struct usb_microdia *);
 int ov965x_set_exposure(struct usb_microdia *);
 int ov965x_flip_detect(struct usb_microdia *dev);
 int ov965x_get_yavg(struct usb_microdia *dev);
+int ov965x_set_yuv422(struct usb_microdia *dev);
+int ov965x_set_bayer(struct usb_microdia *dev);
+
 
 int ov_initialize(struct usb_microdia *dev);
 int ov_set_autogain(struct usb_microdia *dev);
-- 
1.6.0.4

From b94ab6a234cbb32d684f4fce8e7371bda8169f65 Mon Sep 17 00:00:00 2001
From: GWater <[email protected]>
Date: Fri, 19 Dec 2008 22:21:59 +0100
Subject: [PATCH] Copy default_fmts for every microdia device to avoid problems 
with multiple webcams on one host

Signed-off-by: GWater <[email protected]>
---
 microdia-dev.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/microdia-dev.c b/microdia-dev.c
index b17e921..056b83f 100644
--- a/microdia-dev.c
+++ b/microdia-dev.c
@@ -279,12 +279,17 @@ static struct microdia_video_format default_fmts[] = {
        },
 };
 
+static struct microdia_video_format sensor_fmts[ARRAY_SIZE(default_fmts)];
+
 int dev_microdia_assign_fmts(struct usb_microdia *dev)
 {
        int i, j;
 
-       dev->camera.fmts = default_fmts;
-       dev->camera.nfmts = ARRAY_SIZE(default_fmts);
+       for (i = 0; i < ARRAY_SIZE(sensor_fmts); i++)
+               sensor_fmts[i] = default_fmts[i];
+
+       dev->camera.fmts = sensor_fmts;
+       dev->camera.nfmts = ARRAY_SIZE(sensor_fmts);
 
        for (i = 0; i < ARRAY_SIZE(default_fmts); i++) {
                if ((dev->camera.sensor->set_yuv422 != NULL) &&
-- 
1.6.0.4

From f8ed8f236af8ecc8dd50d32d55145c10fe1fe746 Mon Sep 17 00:00:00 2001
From: GWater <[email protected]>
Date: Sat, 20 Dec 2008 00:36:32 +0100
Subject: [PATCH] Implement V4L2_CTRL_FLAG_NEXT_CTRL

        This fixes the problem with V4L2_CID_EXPOSURE_AUTO

Signed-off-by: GWater <[email protected]>
---
 microdia-v4l.c |   50 +++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/microdia-v4l.c b/microdia-v4l.c
index 1985fa3..e67056a 100644
--- a/microdia-v4l.c
+++ b/microdia-v4l.c
@@ -743,18 +743,42 @@ int microdia_vidioc_queryctrl(struct file *file, void 
*priv,
        struct v4l2_queryctrl *ctrl)
 {
        int i;
-       int nbr;
-
-       UDIA_DEBUG("VIDIOC_QUERYCTRL id = %d\n", ctrl->id);
-
-       nbr = sizeof(microdia_controls)/sizeof(struct v4l2_queryctrl);
-
-       for (i = 0; i < nbr; i++) {
-               if (microdia_controls[i].id == ctrl->id) {
+       int nbr = ARRAY_SIZE(microdia_controls);
+#ifdef V4L2_CTRL_FLAG_NEXT_CTRL
+       int min;
+       __u32 idnew, idlast;
+#endif
+       UDIA_DEBUG("VIDIOC_QUERYCTRL id = 0x%x\n", ctrl->id);
+
+#ifdef V4L2_CTRL_FLAG_NEXT_CTRL
+       if (ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
+               min = 0;
+               idnew = V4L2_CTRL_FLAG_NEXT_CTRL;
+               idlast = ctrl->id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
+               for (i = 0; i < nbr; i++) {
+                       if ((microdia_controls[i].id < idnew) &&
+                               (microdia_controls[i].id > idlast)) {
+                                       idnew = microdia_controls[i].id;
+                                       min = i;
+                       }
+               }
+               if (microdia_controls[min].id > idlast) {
                        UDIA_DEBUG("VIDIOC_QUERYCTRL found\n");
-                       memcpy(ctrl, &microdia_controls[i],
-                              sizeof(struct v4l2_queryctrl));
-                       break;
+                       memcpy(ctrl, &microdia_controls[min],
+                               sizeof(struct v4l2_queryctrl));
+                       return 0;
+               } else
+                       return -EINVAL;
+       } else
+#endif
+       {
+               for (i = 0; i < nbr; i++) {
+                       if (microdia_controls[i].id == ctrl->id) {
+                               UDIA_DEBUG("VIDIOC_QUERYCTRL found\n");
+                               memcpy(ctrl, &microdia_controls[i],
+                                       sizeof(struct v4l2_queryctrl));
+                               break;
+                       }
                }
        }
 
@@ -779,7 +803,7 @@ int microdia_vidioc_g_ctrl(struct file *file, void *priv,
 
        dev = video_get_drvdata(priv);
 
-       UDIA_DEBUG("GET CTRL id=%d\n", ctrl->id);
+       UDIA_DEBUG("GET CTRL id=0x%x\n", ctrl->id);
 
        switch (ctrl->id) {
        case V4L2_CID_BRIGHTNESS:
@@ -861,7 +885,7 @@ int microdia_vidioc_s_ctrl(struct file *file, void *priv,
 
        dev = video_get_drvdata(priv);
 
-       UDIA_DEBUG("SET CTRL id=%d value=%d\n", ctrl->id, ctrl->value);
+       UDIA_DEBUG("SET CTRL id=0x%x value=%d\n", ctrl->id, ctrl->value);
 
        switch (ctrl->id) {
        case V4L2_CID_BRIGHTNESS:
-- 
1.6.0.4

Index: mainWindow.cpp
===================================================================
RCS file: /cvsroot/v4l2ucp/v4l2ucp/mainWindow.cpp,v
retrieving revision 1.8
diff -u -r1.8 mainWindow.cpp
--- mainWindow.cpp      5 Mar 2006 06:06:06 -0000       1.8
+++ mainWindow.cpp      4 Dec 2008 02:44:07 -0000
@@ -155,24 +155,37 @@
     new QLabel(grid);
     new QLabel(grid);
 
-    /* Check all the standard controls */
-    for(int i=V4L2_CID_BASE; i<V4L2_CID_LASTP1; i++) {
-        struct v4l2_queryctrl ctrl;
-        ctrl.id = i;
-        if(ioctl(fd, VIDIOC_QUERYCTRL, &ctrl) == 0) {
-            mw->add_control(ctrl, fd, grid);
-        }
-    }
     
-    /* Check any custom controls */
-    for(int i=V4L2_CID_PRIVATE_BASE; ; i++) {
-        struct v4l2_queryctrl ctrl;
-        ctrl.id = i;
-        if(ioctl(fd, VIDIOC_QUERYCTRL, &ctrl) == 0) {
-            mw->add_control(ctrl, fd, grid);
-        } else {
-            break;
-        }
+    struct v4l2_queryctrl ctrl;
+#ifdef V4L2_CTRL_FLAG_NEXT_CTRL
+    /* Try the extended control API first */
+    ctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
+    if(0 == ioctl (fd, VIDIOC_QUERYCTRL, &ctrl)) {
+       do {
+               mw->add_control(ctrl, fd, grid);
+               ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+       } while(0 == ioctl (fd, VIDIOC_QUERYCTRL, &ctrl));
+    } else
+#endif
+    {
+       /* Fall back on the standard API */
+       /* Check all the standard controls */
+       for(int i=V4L2_CID_BASE; i<V4L2_CID_LASTP1; i++) {
+            ctrl.id = i;
+            if(ioctl(fd, VIDIOC_QUERYCTRL, &ctrl) == 0) {
+               mw->add_control(ctrl, fd, grid);
+            }
+       }
+
+       /* Check any custom controls */
+       for(int i=V4L2_CID_PRIVATE_BASE; ; i++) {
+            ctrl.id = i;
+            if(ioctl(fd, VIDIOC_QUERYCTRL, &ctrl) == 0) {
+               mw->add_control(ctrl, fd, grid);
+            } else {
+               break;
+            }
+       }
     }
     
     mw->setCentralWidget(sv);

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to