This is an automatic generated email to let you know that the following patch 
were queued at the 
http://git.linuxtv.org/v4l-dvb.git tree:

Subject: V4L/DVB: uvcvideo: Support menu controls in the control mapping API
Author:  Laurent Pinchart <[email protected]>
Date:    Thu Feb 18 16:38:52 2010 -0300

The UVCIOC_CTRL_MAP ioctl doesn't support menu entries for menu
controls. As the uvc_xu_control_mapping structure has no reserved
fields, this can't be fixed while keeping ABI compatibility.

Modify the UVCIOC_CTRL_MAP ioctl to add menu entries support, and define
UVCIOC_CTRL_MAP_OLD that supports the old ABI without any ability to add
menu controls.

Signed-off-by: Laurent Pinchart <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>

 drivers/media/video/uvc/uvc_ctrl.c   |   22 ++++++++
 drivers/media/video/uvc/uvc_driver.c |    1 +
 drivers/media/video/uvc/uvc_v4l2.c   |   92 +++++++++++++++++++++++++--------
 drivers/media/video/uvc/uvcvideo.h   |   23 +++++++--
 4 files changed, 110 insertions(+), 28 deletions(-)

---

http://git.linuxtv.org/v4l-dvb.git?a=commitdiff;h=c3810b43416155d040a200e7a7301f379c8ae8a0

diff --git a/drivers/media/video/uvc/uvc_ctrl.c 
b/drivers/media/video/uvc/uvc_ctrl.c
index 8bb825d..c88d72e 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -1606,6 +1606,28 @@ void uvc_ctrl_cleanup_device(struct uvc_device *dev)
        }
 }
 
+void uvc_ctrl_cleanup(void)
+{
+       struct uvc_control_info *info;
+       struct uvc_control_info *ni;
+       struct uvc_control_mapping *mapping;
+       struct uvc_control_mapping *nm;
+
+       list_for_each_entry_safe(info, ni, &uvc_driver.controls, list) {
+               if (!(info->flags & UVC_CONTROL_EXTENSION))
+                       continue;
+
+               list_for_each_entry_safe(mapping, nm, &info->mappings, list) {
+                       list_del(&mapping->list);
+                       kfree(mapping->menu_info);
+                       kfree(mapping);
+               }
+
+               list_del(&info->list);
+               kfree(info);
+       }
+}
+
 void uvc_ctrl_init(void)
 {
        struct uvc_control_info *ctrl = uvc_ctrls;
diff --git a/drivers/media/video/uvc/uvc_driver.c 
b/drivers/media/video/uvc/uvc_driver.c
index 45aac10..c5258b3 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -2260,6 +2260,7 @@ static int __init uvc_init(void)
 static void __exit uvc_cleanup(void)
 {
        usb_deregister(&uvc_driver.driver);
+       uvc_ctrl_cleanup();
 }
 
 module_init(uvc_init);
diff --git a/drivers/media/video/uvc/uvc_v4l2.c 
b/drivers/media/video/uvc/uvc_v4l2.c
index 7c9ab29..485a899 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -29,6 +29,71 @@
 #include "uvcvideo.h"
 
 /* ------------------------------------------------------------------------
+ * UVC ioctls
+ */
+static int uvc_ioctl_ctrl_map(struct uvc_xu_control_mapping *xmap, int old)
+{
+       struct uvc_control_mapping *map;
+       unsigned int size;
+       int ret;
+
+       map = kzalloc(sizeof *map, GFP_KERNEL);
+       if (map == NULL)
+               return -ENOMEM;
+
+       map->id = xmap->id;
+       memcpy(map->name, xmap->name, sizeof map->name);
+       memcpy(map->entity, xmap->entity, sizeof map->entity);
+       map->selector = xmap->selector;
+       map->size = xmap->size;
+       map->offset = xmap->offset;
+       map->v4l2_type = xmap->v4l2_type;
+       map->data_type = xmap->data_type;
+
+       switch (xmap->v4l2_type) {
+       case V4L2_CTRL_TYPE_INTEGER:
+       case V4L2_CTRL_TYPE_BOOLEAN:
+       case V4L2_CTRL_TYPE_BUTTON:
+               break;
+
+       case V4L2_CTRL_TYPE_MENU:
+               if (old) {
+                       ret = -EINVAL;
+                       goto done;
+               }
+
+               size = xmap->menu_count * sizeof(*map->menu_info);
+               map->menu_info = kmalloc(size, GFP_KERNEL);
+               if (map->menu_info == NULL) {
+                       ret = -ENOMEM;
+                       goto done;
+               }
+
+               if (copy_from_user(map->menu_info, xmap->menu_info, size)) {
+                       ret = -EFAULT;
+                       goto done;
+               }
+
+               map->menu_count = xmap->menu_count;
+               break;
+
+       default:
+               ret = -EINVAL;
+               goto done;
+       }
+
+       ret = uvc_ctrl_add_mapping(map);
+
+done:
+       if (ret < 0) {
+               kfree(map->menu_info);
+               kfree(map);
+       }
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------
  * V4L2 interface
  */
 
@@ -974,7 +1039,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned 
int cmd, void *arg)
                info->flags = xinfo->flags;
 
                info->flags |= UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX |
-                               UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF;
+                              UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF |
+                              UVC_CONTROL_EXTENSION;
 
                ret = uvc_ctrl_add_info(info);
                if (ret < 0)
@@ -982,32 +1048,12 @@ static long uvc_v4l2_do_ioctl(struct file *file, 
unsigned int cmd, void *arg)
                break;
        }
 
+       case UVCIOC_CTRL_MAP_OLD:
        case UVCIOC_CTRL_MAP:
-       {
-               struct uvc_xu_control_mapping *xmap = arg;
-               struct uvc_control_mapping *map;
-
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
 
-               map = kzalloc(sizeof *map, GFP_KERNEL);
-               if (map == NULL)
-                       return -ENOMEM;
-
-               map->id = xmap->id;
-               memcpy(map->name, xmap->name, sizeof map->name);
-               memcpy(map->entity, xmap->entity, sizeof map->entity);
-               map->selector = xmap->selector;
-               map->size = xmap->size;
-               map->offset = xmap->offset;
-               map->v4l2_type = xmap->v4l2_type;
-               map->data_type = xmap->data_type;
-
-               ret = uvc_ctrl_add_mapping(map);
-               if (ret < 0)
-                       kfree(map);
-               break;
-       }
+               return uvc_ioctl_ctrl_map(arg, cmd == UVCIOC_CTRL_MAP_OLD);
 
        case UVCIOC_CTRL_GET:
                return uvc_xu_ctrl_query(chain, arg, 0);
diff --git a/drivers/media/video/uvc/uvcvideo.h 
b/drivers/media/video/uvc/uvcvideo.h
index d1f8840..14f77e4 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -27,6 +27,8 @@
 #define UVC_CONTROL_RESTORE    (1 << 6)
 /* Control can be updated by the camera. */
 #define UVC_CONTROL_AUTO_UPDATE        (1 << 7)
+/* Control is an extension unit control. */
+#define UVC_CONTROL_EXTENSION  (1 << 8)
 
 #define UVC_CONTROL_GET_RANGE  (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \
                                 UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \
@@ -40,6 +42,15 @@ struct uvc_xu_control_info {
        __u32 flags;
 };
 
+struct uvc_menu_info {
+       __u32 value;
+       __u8 name[32];
+};
+
+struct uvc_xu_control_mapping_old {
+       __u8 reserved[64];
+};
+
 struct uvc_xu_control_mapping {
        __u32 id;
        __u8 name[32];
@@ -50,6 +61,11 @@ struct uvc_xu_control_mapping {
        __u8 offset;
        enum v4l2_ctrl_type v4l2_type;
        __u32 data_type;
+
+       struct uvc_menu_info __user *menu_info;
+       __u32 menu_count;
+
+       __u32 reserved[4];
 };
 
 struct uvc_xu_control {
@@ -60,6 +76,7 @@ struct uvc_xu_control {
 };
 
 #define UVCIOC_CTRL_ADD                _IOW('U', 1, struct uvc_xu_control_info)
+#define UVCIOC_CTRL_MAP_OLD    _IOWR('U', 2, struct uvc_xu_control_mapping_old)
 #define UVCIOC_CTRL_MAP                _IOWR('U', 2, struct 
uvc_xu_control_mapping)
 #define UVCIOC_CTRL_GET                _IOWR('U', 3, struct uvc_xu_control)
 #define UVCIOC_CTRL_SET                _IOW('U', 4, struct uvc_xu_control)
@@ -198,11 +215,6 @@ struct uvc_streaming_control {
        __u8  bMaxVersion;
 };
 
-struct uvc_menu_info {
-       __u32 value;
-       __u8 name[32];
-};
-
 struct uvc_control_info {
        struct list_head list;
        struct list_head mappings;
@@ -625,6 +637,7 @@ extern int uvc_ctrl_init_device(struct uvc_device *dev);
 extern void uvc_ctrl_cleanup_device(struct uvc_device *dev);
 extern int uvc_ctrl_resume_device(struct uvc_device *dev);
 extern void uvc_ctrl_init(void);
+extern void uvc_ctrl_cleanup(void);
 
 extern int uvc_ctrl_begin(struct uvc_video_chain *chain);
 extern int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback);

_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to