*/
 
+#define pr_fmt(fmt) "v4l2-ctrls: " fmt
+
 #include <linux/ctype.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-dev.h>
 
+#define dprintk(vdev, fmt, arg...) do {                                        \
+       if (!WARN_ON(!(vdev)) && ((vdev)->dev_debug & V4L2_DEV_DEBUG_CTRL)) \
+               printk(KERN_DEBUG pr_fmt("%s: %s: " fmt),               \
+                      __func__, video_device_node_name(vdev), ##arg);  \
+} while (0)
+
 #define has_op(master, op) \
        (master->ops && master->ops->op)
 #define call_op(master, op) \
 static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
                             struct v4l2_ext_controls *cs,
                             struct v4l2_ctrl_helper *helpers,
+                            struct video_device *vdev,
                             bool get)
 {
        struct v4l2_ctrl_helper *h;
                if (cs->which &&
                    cs->which != V4L2_CTRL_WHICH_DEF_VAL &&
                    cs->which != V4L2_CTRL_WHICH_REQUEST_VAL &&
-                   V4L2_CTRL_ID2WHICH(id) != cs->which)
+                   V4L2_CTRL_ID2WHICH(id) != cs->which) {
+                       dprintk(vdev,
+                               "invalid which 0x%x or control id 0x%x\n",
+                               cs->which, id);
                        return -EINVAL;
+               }
 
                /* Old-style private controls are not allowed for
                   extended controls */
-               if (id >= V4L2_CID_PRIVATE_BASE)
+               if (id >= V4L2_CID_PRIVATE_BASE) {
+                       dprintk(vdev,
+                               "old-style private controls not allowed\n");
                        return -EINVAL;
+               }
                ref = find_ref_lock(hdl, id);
-               if (ref == NULL)
+               if (ref == NULL) {
+                       dprintk(vdev, "cannot find control id 0x%x\n", id);
                        return -EINVAL;
+               }
                h->ref = ref;
                ctrl = ref->ctrl;
-               if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED)
+               if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) {
+                       dprintk(vdev, "control id 0x%x is disabled\n", id);
                        return -EINVAL;
+               }
 
                if (ctrl->cluster[0]->ncontrols > 1)
                        have_clusters = true;
                        unsigned tot_size = ctrl->elems * ctrl->elem_size;
 
                        if (c->size < tot_size) {
+                               /*
+                                * In the get case the application first
+                                * queries to obtain the size of the control.
+                                */
                                if (get) {
                                        c->size = tot_size;
                                        return -ENOSPC;
                                }
+                               dprintk(vdev,
+                                       "pointer control id 0x%x size too small, %d bytes but %d bytes needed\n",
+                                       id, c->size, tot_size);
                                return -EFAULT;
                        }
                        c->size = tot_size;
 
 /* Get extended controls. Allocates the helpers array if needed. */
 static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
-                                  struct v4l2_ext_controls *cs)
+                                  struct v4l2_ext_controls *cs,
+                                  struct video_device *vdev)
 {
        struct v4l2_ctrl_helper helper[4];
        struct v4l2_ctrl_helper *helpers = helper;
                        return -ENOMEM;
        }
 
-       ret = prepare_ext_ctrls(hdl, cs, helpers, true);
+       ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, true);
        cs->error_idx = cs->count;
 
        for (i = 0; !ret && i < cs->count; i++)
        return obj;
 }
 
-int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct media_device *mdev,
-                    struct v4l2_ext_controls *cs)
+int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev,
+                    struct media_device *mdev, struct v4l2_ext_controls *cs)
 {
        struct media_request_object *obj = NULL;
        struct media_request *req = NULL;
                                   req_obj);
        }
 
-       ret = v4l2_g_ext_ctrls_common(hdl, cs);
+       ret = v4l2_g_ext_ctrls_common(hdl, cs, vdev);
 
        if (obj) {
                media_request_unlock_for_access(req);
 
 /* Validate controls. */
 static int validate_ctrls(struct v4l2_ext_controls *cs,
-                         struct v4l2_ctrl_helper *helpers, bool set)
+                         struct v4l2_ctrl_helper *helpers,
+                         struct video_device *vdev,
+                         bool set)
 {
        unsigned i;
        int ret = 0;
 
                cs->error_idx = i;
 
-               if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
+               if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) {
+                       dprintk(vdev,
+                               "control id 0x%x is read-only\n",
+                               ctrl->id);
                        return -EACCES;
+               }
                /* This test is also done in try_set_control_cluster() which
                   is called in atomic context, so that has the final say,
                   but it makes sense to do an up-front check as well. Once
                   an error occurs in try_set_control_cluster() some other
                   controls may have been set already and we want to do a
                   best-effort to avoid that. */
-               if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
+               if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) {
+                       dprintk(vdev,
+                               "control id 0x%x is grabbed, cannot set\n",
+                               ctrl->id);
                        return -EBUSY;
+               }
                /*
                 * Skip validation for now if the payload needs to be copied
                 * from userspace into kernelspace. We'll validate those later.
 /* Try or try-and-set controls */
 static int try_set_ext_ctrls_common(struct v4l2_fh *fh,
                                    struct v4l2_ctrl_handler *hdl,
-                                   struct v4l2_ext_controls *cs, bool set)
+                                   struct v4l2_ext_controls *cs,
+                                   struct video_device *vdev, bool set)
 {
        struct v4l2_ctrl_helper helper[4];
        struct v4l2_ctrl_helper *helpers = helper;
        cs->error_idx = cs->count;
 
        /* Default value cannot be changed */
-       if (cs->which == V4L2_CTRL_WHICH_DEF_VAL)
+       if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) {
+               dprintk(vdev, "%s: cannot change default value\n",
+                       video_device_node_name(vdev));
                return -EINVAL;
+       }
 
        cs->which = V4L2_CTRL_ID2WHICH(cs->which);
 
-       if (hdl == NULL)
+       if (hdl == NULL) {
+               dprintk(vdev, "%s: invalid null control handler\n",
+                       video_device_node_name(vdev));
                return -EINVAL;
+       }
 
        if (cs->count == 0)
                return class_check(hdl, cs->which);
                if (!helpers)
                        return -ENOMEM;
        }
-       ret = prepare_ext_ctrls(hdl, cs, helpers, false);
+       ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, false);
        if (!ret)
-               ret = validate_ctrls(cs, helpers, set);
+               ret = validate_ctrls(cs, helpers, vdev, set);
        if (ret && set)
                cs->error_idx = cs->count;
        for (i = 0; !ret && i < cs->count; i++) {
 }
 
 static int try_set_ext_ctrls(struct v4l2_fh *fh,
-                            struct v4l2_ctrl_handler *hdl, struct media_device *mdev,
+                            struct v4l2_ctrl_handler *hdl,
+                            struct video_device *vdev,
+                            struct media_device *mdev,
                             struct v4l2_ext_controls *cs, bool set)
 {
        struct media_request_object *obj = NULL;
        int ret;
 
        if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) {
-               if (!mdev || cs->request_fd < 0)
+               if (!mdev) {
+                       dprintk(vdev, "%s: missing media device\n",
+                               video_device_node_name(vdev));
+                       return -EINVAL;
+               }
+
+               if (cs->request_fd < 0) {
+                       dprintk(vdev, "%s: invalid request fd %d\n",
+                               video_device_node_name(vdev), cs->request_fd);
                        return -EINVAL;
+               }
 
                req = media_request_get_by_fd(mdev, cs->request_fd);
-               if (IS_ERR(req))
+               if (IS_ERR(req)) {
+                       dprintk(vdev, "%s: cannot find request fd %d\n",
+                               video_device_node_name(vdev), cs->request_fd);
                        return PTR_ERR(req);
+               }
 
                ret = media_request_lock_for_update(req);
                if (ret) {
+                       dprintk(vdev, "%s: cannot lock request fd %d\n",
+                               video_device_node_name(vdev), cs->request_fd);
                        media_request_put(req);
                        return ret;
                }
 
                obj = v4l2_ctrls_find_req_obj(hdl, req, set);
                if (IS_ERR(obj)) {
+                       dprintk(vdev,
+                               "%s: cannot find request object for request fd %d\n",
+                               video_device_node_name(vdev),
+                               cs->request_fd);
                        media_request_unlock_for_update(req);
                        media_request_put(req);
                        return PTR_ERR(obj);
                                   req_obj);
        }
 
-       ret = try_set_ext_ctrls_common(fh, hdl, cs, set);
+       ret = try_set_ext_ctrls_common(fh, hdl, cs, vdev, set);
+       if (ret)
+               dprintk(vdev,
+                       "%s: try_set_ext_ctrls_common failed (%d)\n",
+                       video_device_node_name(vdev), ret);
 
        if (obj) {
                media_request_unlock_for_update(req);
        return ret;
 }
 
-int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct media_device *mdev,
+int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl,
+                      struct video_device *vdev,
+                      struct media_device *mdev,
                       struct v4l2_ext_controls *cs)
 {
-       return try_set_ext_ctrls(NULL, hdl, mdev, cs, false);
+       return try_set_ext_ctrls(NULL, hdl, vdev, mdev, cs, false);
 }
 EXPORT_SYMBOL(v4l2_try_ext_ctrls);
 
-int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
-                    struct media_device *mdev, struct v4l2_ext_controls *cs)
+int v4l2_s_ext_ctrls(struct v4l2_fh *fh,
+                    struct v4l2_ctrl_handler *hdl,
+                    struct video_device *vdev,
+                    struct media_device *mdev,
+                    struct v4l2_ext_controls *cs)
 {
-       return try_set_ext_ctrls(fh, hdl, mdev, cs, true);
+       return try_set_ext_ctrls(fh, hdl, vdev, mdev, cs, true);
 }
 EXPORT_SYMBOL(v4l2_s_ext_ctrls);
 
 
 
        p->error_idx = p->count;
        if (vfh && vfh->ctrl_handler)
-               return v4l2_g_ext_ctrls(vfh->ctrl_handler, vfd->v4l2_dev->mdev, p);
+               return v4l2_g_ext_ctrls(vfh->ctrl_handler,
+                                       vfd, vfd->v4l2_dev->mdev, p);
        if (vfd->ctrl_handler)
-               return v4l2_g_ext_ctrls(vfd->ctrl_handler, vfd->v4l2_dev->mdev, p);
+               return v4l2_g_ext_ctrls(vfd->ctrl_handler,
+                                       vfd, vfd->v4l2_dev->mdev, p);
        if (ops->vidioc_g_ext_ctrls == NULL)
                return -ENOTTY;
        return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) :
 
        p->error_idx = p->count;
        if (vfh && vfh->ctrl_handler)
-               return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, vfd->v4l2_dev->mdev, p);
+               return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler,
+                                       vfd, vfd->v4l2_dev->mdev, p);
        if (vfd->ctrl_handler)
-               return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, vfd->v4l2_dev->mdev, p);
+               return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler,
+                                       vfd, vfd->v4l2_dev->mdev, p);
        if (ops->vidioc_s_ext_ctrls == NULL)
                return -ENOTTY;
        return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) :
 
        p->error_idx = p->count;
        if (vfh && vfh->ctrl_handler)
-               return v4l2_try_ext_ctrls(vfh->ctrl_handler, vfd->v4l2_dev->mdev, p);
+               return v4l2_try_ext_ctrls(vfh->ctrl_handler,
+                                         vfd, vfd->v4l2_dev->mdev, p);
        if (vfd->ctrl_handler)
-               return v4l2_try_ext_ctrls(vfd->ctrl_handler, vfd->v4l2_dev->mdev, p);
+               return v4l2_try_ext_ctrls(vfd->ctrl_handler,
+                                         vfd, vfd->v4l2_dev->mdev, p);
        if (ops->vidioc_try_ext_ctrls == NULL)
                return -ENOTTY;
        return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) :