The patch number 9903 was added via Laurent Pinchart 
<laurent.pinch...@skynet.be>
to http://linuxtv.org/hg/v4l-dvb master development tree.

Kernel patches in this development tree may be modified to be backward
compatible with older kernels. Compatibility modifications will be
removed before inclusion into the mainstream Kernel

If anyone has any objections, please let us know by sending a message to:
        v4l-dvb-maintai...@linuxtv.org

------

From: Laurent Pinchart  <laurent.pinch...@skynet.be>
uvcvideo: V4L2 zoom controls support


Add support for absolute and continuous zoom controls (mapped to absolute
and relative UVC zoom controls).

Priority: normal

Signed-off-by: Laurent Pinchart <laurent.pinch...@skynet.be>


---

 linux/drivers/media/video/uvc/uvc_ctrl.c |   76 +++++++++++++++++++----
 linux/drivers/media/video/uvc/uvc_v4l2.c |    4 -
 linux/drivers/media/video/uvc/uvcvideo.h |    5 +
 3 files changed, 71 insertions(+), 14 deletions(-)

diff -r 7c2434c2e1a6 -r 086c580cf0e7 linux/drivers/media/video/uvc/uvc_ctrl.c
--- a/linux/drivers/media/video/uvc/uvc_ctrl.c  Tue Dec 16 10:44:11 2008 +0100
+++ b/linux/drivers/media/video/uvc/uvc_ctrl.c  Tue Dec 16 10:46:32 2008 +0100
@@ -329,6 +329,31 @@ static struct uvc_menu_info exposure_aut
        { 8, "Aperture Priority Mode" },
 };
 
+static __s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping,
+       __u8 query, const __u8 *data)
+{
+       __s8 zoom = (__s8)data[0];
+
+       switch (query) {
+       case GET_CUR:
+               return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]);
+
+       case GET_MIN:
+       case GET_MAX:
+       case GET_RES:
+       case GET_DEF:
+       default:
+               return data[2];
+       }
+}
+
+static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping,
+       __s32 value, __u8 *data)
+{
+       data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff;
+       data[2] = min(abs(value), 0xff);
+}
+
 static struct uvc_control_mapping uvc_ctrl_mappings[] = {
        {
                .id             = V4L2_CID_BRIGHTNESS,
@@ -535,6 +560,28 @@ static struct uvc_control_mapping uvc_ct
                .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
        },
        {
+               .id             = V4L2_CID_ZOOM_ABSOLUTE,
+               .name           = "Zoom, Absolute",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_ZOOM_ABSOLUTE_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_ZOOM_CONTINUOUS,
+               .name           = "Zoom, Continuous",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_ZOOM_RELATIVE_CONTROL,
+               .size           = 0,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
+               .get            = uvc_ctrl_get_zoom,
+               .set            = uvc_ctrl_set_zoom,
+       },
+       {
                .id             = V4L2_CID_PRIVACY,
                .name           = "Privacy",
                .entity         = UVC_GUID_UVC_CAMERA,
@@ -570,8 +617,8 @@ static inline void uvc_clear_bit(__u8 *d
  * a signed 32bit integer. Sign extension will be performed if the mapping
  * references a signed data type.
  */
-static __s32 uvc_get_le_value(const __u8 *data,
-       struct uvc_control_mapping *mapping)
+static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
+       __u8 query, const __u8 *data)
 {
        int bits = mapping->size;
        int offset = mapping->offset;
@@ -600,8 +647,8 @@ static __s32 uvc_get_le_value(const __u8
 /* Set the bit string specified by mapping->offset and mapping->size
  * in the little-endian data stored at 'data' to the value 'value'.
  */
-static void uvc_set_le_value(__s32 value, __u8 *data,
-       struct uvc_control_mapping *mapping)
+static void uvc_set_le_value(struct uvc_control_mapping *mapping,
+       __s32 value, __u8 *data)
 {
        int bits = mapping->size;
        int offset = mapping->offset;
@@ -753,7 +800,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video
                                video->dev->intfnum, ctrl->info->selector,
                                data, ctrl->info->size)) < 0)
                        goto out;
-               v4l2_ctrl->default_value = uvc_get_le_value(data, mapping);
+               v4l2_ctrl->default_value = mapping->get(mapping, GET_DEF, data);
        }
 
        switch (mapping->v4l2_type) {
@@ -789,21 +836,21 @@ int uvc_query_v4l2_ctrl(struct uvc_video
                                video->dev->intfnum, ctrl->info->selector,
                                data, ctrl->info->size)) < 0)
                        goto out;
-               v4l2_ctrl->minimum = uvc_get_le_value(data, mapping);
+               v4l2_ctrl->minimum = mapping->get(mapping, GET_MIN, data);
        }
        if (ctrl->info->flags & UVC_CONTROL_GET_MAX) {
                if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id,
                                video->dev->intfnum, ctrl->info->selector,
                                data, ctrl->info->size)) < 0)
                        goto out;
-               v4l2_ctrl->maximum = uvc_get_le_value(data, mapping);
+               v4l2_ctrl->maximum = mapping->get(mapping, GET_MAX, data);
        }
        if (ctrl->info->flags & UVC_CONTROL_GET_RES) {
                if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id,
                                video->dev->intfnum, ctrl->info->selector,
                                data, ctrl->info->size)) < 0)
                        goto out;
-               v4l2_ctrl->step = uvc_get_le_value(data, mapping);
+               v4l2_ctrl->step = mapping->get(mapping, GET_RES, data);
        }
 
        ret = 0;
@@ -940,8 +987,8 @@ int uvc_ctrl_get(struct uvc_video_device
                ctrl->loaded = 1;
        }
 
-       xctrl->value = uvc_get_le_value(
-               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping);
+       xctrl->value = mapping->get(mapping, GET_CUR,
+               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
 
        if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
                menu = mapping->menu_info;
@@ -997,8 +1044,8 @@ int uvc_ctrl_set(struct uvc_video_device
                       ctrl->info->size);
        }
 
-       uvc_set_le_value(value,
-               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping);
+       mapping->set(mapping, value,
+               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
 
        ctrl->dirty = 1;
        ctrl->modified = 1;
@@ -1273,6 +1320,11 @@ int uvc_ctrl_add_mapping(struct uvc_cont
        struct uvc_control_info *info;
        struct uvc_control_mapping *map;
        int ret = -EINVAL;
+
+       if (mapping->get == NULL)
+               mapping->get = uvc_get_le_value;
+       if (mapping->set == NULL)
+               mapping->set = uvc_set_le_value;
 
        if (mapping->id & ~V4L2_CTRL_ID_MASK) {
                uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s' with "
diff -r 7c2434c2e1a6 -r 086c580cf0e7 linux/drivers/media/video/uvc/uvc_v4l2.c
--- a/linux/drivers/media/video/uvc/uvc_v4l2.c  Tue Dec 16 10:44:11 2008 +0100
+++ b/linux/drivers/media/video/uvc/uvc_v4l2.c  Tue Dec 16 10:46:32 2008 +0100
@@ -920,7 +920,7 @@ static int uvc_v4l2_do_ioctl(struct file
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
 
-               info = kmalloc(sizeof *info, GFP_KERNEL);
+               info = kzalloc(sizeof *info, GFP_KERNEL);
                if (info == NULL)
                        return -ENOMEM;
 
@@ -947,7 +947,7 @@ static int uvc_v4l2_do_ioctl(struct file
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
 
-               map = kmalloc(sizeof *map, GFP_KERNEL);
+               map = kzalloc(sizeof *map, GFP_KERNEL);
                if (map == NULL)
                        return -ENOMEM;
 
diff -r 7c2434c2e1a6 -r 086c580cf0e7 linux/drivers/media/video/uvc/uvcvideo.h
--- a/linux/drivers/media/video/uvc/uvcvideo.h  Tue Dec 16 10:44:11 2008 +0100
+++ b/linux/drivers/media/video/uvc/uvcvideo.h  Tue Dec 16 10:46:32 2008 +0100
@@ -384,6 +384,11 @@ struct uvc_control_mapping {
 
        struct uvc_menu_info *menu_info;
        __u32 menu_count;
+
+       __s32 (*get) (struct uvc_control_mapping *mapping, __u8 query,
+                     const __u8 *data);
+       void (*set) (struct uvc_control_mapping *mapping, __s32 value,
+                    __u8 *data);
 };
 
 struct uvc_control {


---

Patch is available at: 
http://linuxtv.org/hg/v4l-dvb/rev/086c580cf0e7e3e437c308081430a289aaeeb681

_______________________________________________
linuxtv-commits mailing list
linuxtv-commits@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to