xref: /openbmc/linux/drivers/media/v4l2-core/v4l2-ctrls-api.c (revision 24f68eb5bf14a74027946970a18bc902e19d986a)
171c689dcSHans Verkuil // SPDX-License-Identifier: GPL-2.0-or-later
271c689dcSHans Verkuil /*
371c689dcSHans Verkuil  * V4L2 controls framework uAPI implementation:
471c689dcSHans Verkuil  *
571c689dcSHans Verkuil  * Copyright (C) 2010-2021  Hans Verkuil <hverkuil-cisco@xs4all.nl>
671c689dcSHans Verkuil  */
771c689dcSHans Verkuil 
871c689dcSHans Verkuil #define pr_fmt(fmt) "v4l2-ctrls: " fmt
971c689dcSHans Verkuil 
1071c689dcSHans Verkuil #include <linux/export.h>
1171c689dcSHans Verkuil #include <linux/mm.h>
1271c689dcSHans Verkuil #include <linux/slab.h>
1371c689dcSHans Verkuil #include <media/v4l2-ctrls.h>
1471c689dcSHans Verkuil #include <media/v4l2-dev.h>
1571c689dcSHans Verkuil #include <media/v4l2-device.h>
1671c689dcSHans Verkuil #include <media/v4l2-event.h>
1771c689dcSHans Verkuil #include <media/v4l2-ioctl.h>
1871c689dcSHans Verkuil 
1971c689dcSHans Verkuil #include "v4l2-ctrls-priv.h"
2071c689dcSHans Verkuil 
2171c689dcSHans Verkuil /* Internal temporary helper struct, one for each v4l2_ext_control */
2271c689dcSHans Verkuil struct v4l2_ctrl_helper {
2371c689dcSHans Verkuil 	/* Pointer to the control reference of the master control */
2471c689dcSHans Verkuil 	struct v4l2_ctrl_ref *mref;
2571c689dcSHans Verkuil 	/* The control ref corresponding to the v4l2_ext_control ID field. */
2671c689dcSHans Verkuil 	struct v4l2_ctrl_ref *ref;
2771c689dcSHans Verkuil 	/*
2871c689dcSHans Verkuil 	 * v4l2_ext_control index of the next control belonging to the
2971c689dcSHans Verkuil 	 * same cluster, or 0 if there isn't any.
3071c689dcSHans Verkuil 	 */
3171c689dcSHans Verkuil 	u32 next;
3271c689dcSHans Verkuil };
3371c689dcSHans Verkuil 
3471c689dcSHans Verkuil /*
3571c689dcSHans Verkuil  * Helper functions to copy control payload data from kernel space to
3671c689dcSHans Verkuil  * user space and vice versa.
3771c689dcSHans Verkuil  */
3871c689dcSHans Verkuil 
3971c689dcSHans Verkuil /* Helper function: copy the given control value back to the caller */
ptr_to_user(struct v4l2_ext_control * c,struct v4l2_ctrl * ctrl,union v4l2_ctrl_ptr ptr)4071c689dcSHans Verkuil static int ptr_to_user(struct v4l2_ext_control *c,
4171c689dcSHans Verkuil 		       struct v4l2_ctrl *ctrl,
4271c689dcSHans Verkuil 		       union v4l2_ctrl_ptr ptr)
4371c689dcSHans Verkuil {
4471c689dcSHans Verkuil 	u32 len;
4571c689dcSHans Verkuil 
4671c689dcSHans Verkuil 	if (ctrl->is_ptr && !ctrl->is_string)
4771c689dcSHans Verkuil 		return copy_to_user(c->ptr, ptr.p_const, c->size) ?
4871c689dcSHans Verkuil 		       -EFAULT : 0;
4971c689dcSHans Verkuil 
5071c689dcSHans Verkuil 	switch (ctrl->type) {
5171c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_STRING:
5271c689dcSHans Verkuil 		len = strlen(ptr.p_char);
5371c689dcSHans Verkuil 		if (c->size < len + 1) {
5471c689dcSHans Verkuil 			c->size = ctrl->elem_size;
5571c689dcSHans Verkuil 			return -ENOSPC;
5671c689dcSHans Verkuil 		}
5771c689dcSHans Verkuil 		return copy_to_user(c->string, ptr.p_char, len + 1) ?
5871c689dcSHans Verkuil 		       -EFAULT : 0;
5971c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_INTEGER64:
6071c689dcSHans Verkuil 		c->value64 = *ptr.p_s64;
6171c689dcSHans Verkuil 		break;
6271c689dcSHans Verkuil 	default:
6371c689dcSHans Verkuil 		c->value = *ptr.p_s32;
6471c689dcSHans Verkuil 		break;
6571c689dcSHans Verkuil 	}
6671c689dcSHans Verkuil 	return 0;
6771c689dcSHans Verkuil }
6871c689dcSHans Verkuil 
6971c689dcSHans Verkuil /* Helper function: copy the current control value back to the caller */
cur_to_user(struct v4l2_ext_control * c,struct v4l2_ctrl * ctrl)7071c689dcSHans Verkuil static int cur_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
7171c689dcSHans Verkuil {
7271c689dcSHans Verkuil 	return ptr_to_user(c, ctrl, ctrl->p_cur);
7371c689dcSHans Verkuil }
7471c689dcSHans Verkuil 
7571c689dcSHans Verkuil /* Helper function: copy the new control value back to the caller */
new_to_user(struct v4l2_ext_control * c,struct v4l2_ctrl * ctrl)7671c689dcSHans Verkuil static int new_to_user(struct v4l2_ext_control *c,
7771c689dcSHans Verkuil 		       struct v4l2_ctrl *ctrl)
7871c689dcSHans Verkuil {
7971c689dcSHans Verkuil 	return ptr_to_user(c, ctrl, ctrl->p_new);
8071c689dcSHans Verkuil }
8171c689dcSHans Verkuil 
8271c689dcSHans Verkuil /* Helper function: copy the request value back to the caller */
req_to_user(struct v4l2_ext_control * c,struct v4l2_ctrl_ref * ref)8371c689dcSHans Verkuil static int req_to_user(struct v4l2_ext_control *c,
8471c689dcSHans Verkuil 		       struct v4l2_ctrl_ref *ref)
8571c689dcSHans Verkuil {
8671c689dcSHans Verkuil 	return ptr_to_user(c, ref->ctrl, ref->p_req);
8771c689dcSHans Verkuil }
8871c689dcSHans Verkuil 
8971c689dcSHans Verkuil /* Helper function: copy the initial control value back to the caller */
def_to_user(struct v4l2_ext_control * c,struct v4l2_ctrl * ctrl)9071c689dcSHans Verkuil static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
9171c689dcSHans Verkuil {
92cd75981eSHans Verkuil 	ctrl->type_ops->init(ctrl, 0, ctrl->p_new);
9371c689dcSHans Verkuil 
9471c689dcSHans Verkuil 	return ptr_to_user(c, ctrl, ctrl->p_new);
9571c689dcSHans Verkuil }
9671c689dcSHans Verkuil 
97fb582cbaSHans Verkuil /* Helper function: copy the caller-provider value as the new control value */
user_to_new(struct v4l2_ext_control * c,struct v4l2_ctrl * ctrl)98fb582cbaSHans Verkuil static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
9971c689dcSHans Verkuil {
10071c689dcSHans Verkuil 	int ret;
10171c689dcSHans Verkuil 	u32 size;
10271c689dcSHans Verkuil 
103fb582cbaSHans Verkuil 	ctrl->is_new = 0;
104fb582cbaSHans Verkuil 	if (ctrl->is_dyn_array &&
1055f2c5c69SHans Verkuil 	    c->size > ctrl->p_array_alloc_elems * ctrl->elem_size) {
1065f2c5c69SHans Verkuil 		void *old = ctrl->p_array;
107fb582cbaSHans Verkuil 		void *tmp = kvzalloc(2 * c->size, GFP_KERNEL);
108fb582cbaSHans Verkuil 
109fb582cbaSHans Verkuil 		if (!tmp)
110fb582cbaSHans Verkuil 			return -ENOMEM;
111fb582cbaSHans Verkuil 		memcpy(tmp, ctrl->p_new.p, ctrl->elems * ctrl->elem_size);
112fb582cbaSHans Verkuil 		memcpy(tmp + c->size, ctrl->p_cur.p, ctrl->elems * ctrl->elem_size);
113fb582cbaSHans Verkuil 		ctrl->p_new.p = tmp;
114fb582cbaSHans Verkuil 		ctrl->p_cur.p = tmp + c->size;
1155f2c5c69SHans Verkuil 		ctrl->p_array = tmp;
1165f2c5c69SHans Verkuil 		ctrl->p_array_alloc_elems = c->size / ctrl->elem_size;
117fb582cbaSHans Verkuil 		kvfree(old);
118fb582cbaSHans Verkuil 	}
119fb582cbaSHans Verkuil 
12071c689dcSHans Verkuil 	if (ctrl->is_ptr && !ctrl->is_string) {
121fb582cbaSHans Verkuil 		unsigned int elems = c->size / ctrl->elem_size;
12271c689dcSHans Verkuil 
123fb582cbaSHans Verkuil 		if (copy_from_user(ctrl->p_new.p, c->ptr, c->size))
124fb582cbaSHans Verkuil 			return -EFAULT;
125fb582cbaSHans Verkuil 		ctrl->is_new = 1;
126fb582cbaSHans Verkuil 		if (ctrl->is_dyn_array)
127fb582cbaSHans Verkuil 			ctrl->new_elems = elems;
128fb582cbaSHans Verkuil 		else if (ctrl->is_array)
129cd75981eSHans Verkuil 			ctrl->type_ops->init(ctrl, elems, ctrl->p_new);
13071c689dcSHans Verkuil 		return 0;
13171c689dcSHans Verkuil 	}
13271c689dcSHans Verkuil 
13371c689dcSHans Verkuil 	switch (ctrl->type) {
13471c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_INTEGER64:
135fb582cbaSHans Verkuil 		*ctrl->p_new.p_s64 = c->value64;
13671c689dcSHans Verkuil 		break;
13771c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_STRING:
13871c689dcSHans Verkuil 		size = c->size;
13971c689dcSHans Verkuil 		if (size == 0)
14071c689dcSHans Verkuil 			return -ERANGE;
14171c689dcSHans Verkuil 		if (size > ctrl->maximum + 1)
14271c689dcSHans Verkuil 			size = ctrl->maximum + 1;
143fb582cbaSHans Verkuil 		ret = copy_from_user(ctrl->p_new.p_char, c->string, size) ? -EFAULT : 0;
14471c689dcSHans Verkuil 		if (!ret) {
145fb582cbaSHans Verkuil 			char last = ctrl->p_new.p_char[size - 1];
14671c689dcSHans Verkuil 
147fb582cbaSHans Verkuil 			ctrl->p_new.p_char[size - 1] = 0;
14871c689dcSHans Verkuil 			/*
14971c689dcSHans Verkuil 			 * If the string was longer than ctrl->maximum,
15071c689dcSHans Verkuil 			 * then return an error.
15171c689dcSHans Verkuil 			 */
152fb582cbaSHans Verkuil 			if (strlen(ctrl->p_new.p_char) == ctrl->maximum && last)
15371c689dcSHans Verkuil 				return -ERANGE;
154a1550700SHans Verkuil 			ctrl->is_new = 1;
15571c689dcSHans Verkuil 		}
15671c689dcSHans Verkuil 		return ret;
15771c689dcSHans Verkuil 	default:
158fb582cbaSHans Verkuil 		*ctrl->p_new.p_s32 = c->value;
15971c689dcSHans Verkuil 		break;
16071c689dcSHans Verkuil 	}
161fb582cbaSHans Verkuil 	ctrl->is_new = 1;
16271c689dcSHans Verkuil 	return 0;
16371c689dcSHans Verkuil }
16471c689dcSHans Verkuil 
16571c689dcSHans Verkuil /*
16671c689dcSHans Verkuil  * VIDIOC_G/TRY/S_EXT_CTRLS implementation
16771c689dcSHans Verkuil  */
16871c689dcSHans Verkuil 
16971c689dcSHans Verkuil /*
17071c689dcSHans Verkuil  * Some general notes on the atomic requirements of VIDIOC_G/TRY/S_EXT_CTRLS:
17171c689dcSHans Verkuil  *
17271c689dcSHans Verkuil  * It is not a fully atomic operation, just best-effort only. After all, if
17371c689dcSHans Verkuil  * multiple controls have to be set through multiple i2c writes (for example)
17471c689dcSHans Verkuil  * then some initial writes may succeed while others fail. Thus leaving the
17571c689dcSHans Verkuil  * system in an inconsistent state. The question is how much effort you are
17671c689dcSHans Verkuil  * willing to spend on trying to make something atomic that really isn't.
17771c689dcSHans Verkuil  *
17871c689dcSHans Verkuil  * From the point of view of an application the main requirement is that
17971c689dcSHans Verkuil  * when you call VIDIOC_S_EXT_CTRLS and some values are invalid then an
18071c689dcSHans Verkuil  * error should be returned without actually affecting any controls.
18171c689dcSHans Verkuil  *
18271c689dcSHans Verkuil  * If all the values are correct, then it is acceptable to just give up
18371c689dcSHans Verkuil  * in case of low-level errors.
18471c689dcSHans Verkuil  *
18571c689dcSHans Verkuil  * It is important though that the application can tell when only a partial
18671c689dcSHans Verkuil  * configuration was done. The way we do that is through the error_idx field
18771c689dcSHans Verkuil  * of struct v4l2_ext_controls: if that is equal to the count field then no
18871c689dcSHans Verkuil  * controls were affected. Otherwise all controls before that index were
18971c689dcSHans Verkuil  * successful in performing their 'get' or 'set' operation, the control at
19071c689dcSHans Verkuil  * the given index failed, and you don't know what happened with the controls
19171c689dcSHans Verkuil  * after the failed one. Since if they were part of a control cluster they
19271c689dcSHans Verkuil  * could have been successfully processed (if a cluster member was encountered
19371c689dcSHans Verkuil  * at index < error_idx), they could have failed (if a cluster member was at
19471c689dcSHans Verkuil  * error_idx), or they may not have been processed yet (if the first cluster
19571c689dcSHans Verkuil  * member appeared after error_idx).
19671c689dcSHans Verkuil  *
19771c689dcSHans Verkuil  * It is all fairly theoretical, though. In practice all you can do is to
19871c689dcSHans Verkuil  * bail out. If error_idx == count, then it is an application bug. If
19971c689dcSHans Verkuil  * error_idx < count then it is only an application bug if the error code was
20071c689dcSHans Verkuil  * EBUSY. That usually means that something started streaming just when you
20171c689dcSHans Verkuil  * tried to set the controls. In all other cases it is a driver/hardware
20271c689dcSHans Verkuil  * problem and all you can do is to retry or bail out.
20371c689dcSHans Verkuil  *
20471c689dcSHans Verkuil  * Note that these rules do not apply to VIDIOC_TRY_EXT_CTRLS: since that
20571c689dcSHans Verkuil  * never modifies controls the error_idx is just set to whatever control
20671c689dcSHans Verkuil  * has an invalid value.
20771c689dcSHans Verkuil  */
20871c689dcSHans Verkuil 
20971c689dcSHans Verkuil /*
21071c689dcSHans Verkuil  * Prepare for the extended g/s/try functions.
21171c689dcSHans Verkuil  * Find the controls in the control array and do some basic checks.
21271c689dcSHans Verkuil  */
prepare_ext_ctrls(struct v4l2_ctrl_handler * hdl,struct v4l2_ext_controls * cs,struct v4l2_ctrl_helper * helpers,struct video_device * vdev,bool get)21371c689dcSHans Verkuil static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
21471c689dcSHans Verkuil 			     struct v4l2_ext_controls *cs,
21571c689dcSHans Verkuil 			     struct v4l2_ctrl_helper *helpers,
21671c689dcSHans Verkuil 			     struct video_device *vdev,
21771c689dcSHans Verkuil 			     bool get)
21871c689dcSHans Verkuil {
21971c689dcSHans Verkuil 	struct v4l2_ctrl_helper *h;
22071c689dcSHans Verkuil 	bool have_clusters = false;
22171c689dcSHans Verkuil 	u32 i;
22271c689dcSHans Verkuil 
22371c689dcSHans Verkuil 	for (i = 0, h = helpers; i < cs->count; i++, h++) {
22471c689dcSHans Verkuil 		struct v4l2_ext_control *c = &cs->controls[i];
22571c689dcSHans Verkuil 		struct v4l2_ctrl_ref *ref;
22671c689dcSHans Verkuil 		struct v4l2_ctrl *ctrl;
22771c689dcSHans Verkuil 		u32 id = c->id & V4L2_CTRL_ID_MASK;
22871c689dcSHans Verkuil 
22971c689dcSHans Verkuil 		cs->error_idx = i;
23071c689dcSHans Verkuil 
23171c689dcSHans Verkuil 		if (cs->which &&
23271c689dcSHans Verkuil 		    cs->which != V4L2_CTRL_WHICH_DEF_VAL &&
23371c689dcSHans Verkuil 		    cs->which != V4L2_CTRL_WHICH_REQUEST_VAL &&
23471c689dcSHans Verkuil 		    V4L2_CTRL_ID2WHICH(id) != cs->which) {
23571c689dcSHans Verkuil 			dprintk(vdev,
23671c689dcSHans Verkuil 				"invalid which 0x%x or control id 0x%x\n",
23771c689dcSHans Verkuil 				cs->which, id);
23871c689dcSHans Verkuil 			return -EINVAL;
23971c689dcSHans Verkuil 		}
24071c689dcSHans Verkuil 
24171c689dcSHans Verkuil 		/*
24271c689dcSHans Verkuil 		 * Old-style private controls are not allowed for
24371c689dcSHans Verkuil 		 * extended controls.
24471c689dcSHans Verkuil 		 */
24571c689dcSHans Verkuil 		if (id >= V4L2_CID_PRIVATE_BASE) {
24671c689dcSHans Verkuil 			dprintk(vdev,
24771c689dcSHans Verkuil 				"old-style private controls not allowed\n");
24871c689dcSHans Verkuil 			return -EINVAL;
24971c689dcSHans Verkuil 		}
25071c689dcSHans Verkuil 		ref = find_ref_lock(hdl, id);
25171c689dcSHans Verkuil 		if (!ref) {
25271c689dcSHans Verkuil 			dprintk(vdev, "cannot find control id 0x%x\n", id);
25371c689dcSHans Verkuil 			return -EINVAL;
25471c689dcSHans Verkuil 		}
25571c689dcSHans Verkuil 		h->ref = ref;
25671c689dcSHans Verkuil 		ctrl = ref->ctrl;
25771c689dcSHans Verkuil 		if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) {
25871c689dcSHans Verkuil 			dprintk(vdev, "control id 0x%x is disabled\n", id);
25971c689dcSHans Verkuil 			return -EINVAL;
26071c689dcSHans Verkuil 		}
26171c689dcSHans Verkuil 
26271c689dcSHans Verkuil 		if (ctrl->cluster[0]->ncontrols > 1)
26371c689dcSHans Verkuil 			have_clusters = true;
26471c689dcSHans Verkuil 		if (ctrl->cluster[0] != ctrl)
26571c689dcSHans Verkuil 			ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
266fb582cbaSHans Verkuil 		if (ctrl->is_dyn_array) {
267fb582cbaSHans Verkuil 			unsigned int max_size = ctrl->dims[0] * ctrl->elem_size;
268fb582cbaSHans Verkuil 			unsigned int tot_size = ctrl->elem_size;
269fb582cbaSHans Verkuil 
270fb582cbaSHans Verkuil 			if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL)
271fb582cbaSHans Verkuil 				tot_size *= ref->p_req_elems;
272fb582cbaSHans Verkuil 			else
273fb582cbaSHans Verkuil 				tot_size *= ctrl->elems;
274fb582cbaSHans Verkuil 
275fb582cbaSHans Verkuil 			c->size = ctrl->elem_size * (c->size / ctrl->elem_size);
276fb582cbaSHans Verkuil 			if (get) {
277fb582cbaSHans Verkuil 				if (c->size < tot_size) {
278fb582cbaSHans Verkuil 					c->size = tot_size;
279fb582cbaSHans Verkuil 					return -ENOSPC;
280fb582cbaSHans Verkuil 				}
281fb582cbaSHans Verkuil 				c->size = tot_size;
282fb582cbaSHans Verkuil 			} else {
283fb582cbaSHans Verkuil 				if (c->size > max_size) {
284fb582cbaSHans Verkuil 					c->size = max_size;
285fb582cbaSHans Verkuil 					return -ENOSPC;
286fb582cbaSHans Verkuil 				}
287fb582cbaSHans Verkuil 				if (!c->size)
288fb582cbaSHans Verkuil 					return -EFAULT;
289fb582cbaSHans Verkuil 			}
290fb582cbaSHans Verkuil 		} else if (ctrl->is_ptr && !ctrl->is_string) {
29171c689dcSHans Verkuil 			unsigned int tot_size = ctrl->elems * ctrl->elem_size;
29271c689dcSHans Verkuil 
29371c689dcSHans Verkuil 			if (c->size < tot_size) {
29471c689dcSHans Verkuil 				/*
29571c689dcSHans Verkuil 				 * In the get case the application first
29671c689dcSHans Verkuil 				 * queries to obtain the size of the control.
29771c689dcSHans Verkuil 				 */
29871c689dcSHans Verkuil 				if (get) {
29971c689dcSHans Verkuil 					c->size = tot_size;
30071c689dcSHans Verkuil 					return -ENOSPC;
30171c689dcSHans Verkuil 				}
30271c689dcSHans Verkuil 				dprintk(vdev,
30371c689dcSHans Verkuil 					"pointer control id 0x%x size too small, %d bytes but %d bytes needed\n",
30471c689dcSHans Verkuil 					id, c->size, tot_size);
30571c689dcSHans Verkuil 				return -EFAULT;
30671c689dcSHans Verkuil 			}
30771c689dcSHans Verkuil 			c->size = tot_size;
30871c689dcSHans Verkuil 		}
30971c689dcSHans Verkuil 		/* Store the ref to the master control of the cluster */
31071c689dcSHans Verkuil 		h->mref = ref;
31171c689dcSHans Verkuil 		/*
31271c689dcSHans Verkuil 		 * Initially set next to 0, meaning that there is no other
31371c689dcSHans Verkuil 		 * control in this helper array belonging to the same
31471c689dcSHans Verkuil 		 * cluster.
31571c689dcSHans Verkuil 		 */
31671c689dcSHans Verkuil 		h->next = 0;
31771c689dcSHans Verkuil 	}
31871c689dcSHans Verkuil 
31971c689dcSHans Verkuil 	/*
32071c689dcSHans Verkuil 	 * We are done if there were no controls that belong to a multi-
32171c689dcSHans Verkuil 	 * control cluster.
32271c689dcSHans Verkuil 	 */
32371c689dcSHans Verkuil 	if (!have_clusters)
32471c689dcSHans Verkuil 		return 0;
32571c689dcSHans Verkuil 
32671c689dcSHans Verkuil 	/*
32771c689dcSHans Verkuil 	 * The code below figures out in O(n) time which controls in the list
32871c689dcSHans Verkuil 	 * belong to the same cluster.
32971c689dcSHans Verkuil 	 */
33071c689dcSHans Verkuil 
33171c689dcSHans Verkuil 	/* This has to be done with the handler lock taken. */
33271c689dcSHans Verkuil 	mutex_lock(hdl->lock);
33371c689dcSHans Verkuil 
33471c689dcSHans Verkuil 	/* First zero the helper field in the master control references */
33571c689dcSHans Verkuil 	for (i = 0; i < cs->count; i++)
33671c689dcSHans Verkuil 		helpers[i].mref->helper = NULL;
33771c689dcSHans Verkuil 	for (i = 0, h = helpers; i < cs->count; i++, h++) {
33871c689dcSHans Verkuil 		struct v4l2_ctrl_ref *mref = h->mref;
33971c689dcSHans Verkuil 
34071c689dcSHans Verkuil 		/*
34171c689dcSHans Verkuil 		 * If the mref->helper is set, then it points to an earlier
34271c689dcSHans Verkuil 		 * helper that belongs to the same cluster.
34371c689dcSHans Verkuil 		 */
34471c689dcSHans Verkuil 		if (mref->helper) {
34571c689dcSHans Verkuil 			/*
34671c689dcSHans Verkuil 			 * Set the next field of mref->helper to the current
34771c689dcSHans Verkuil 			 * index: this means that the earlier helper now
34871c689dcSHans Verkuil 			 * points to the next helper in the same cluster.
34971c689dcSHans Verkuil 			 */
35071c689dcSHans Verkuil 			mref->helper->next = i;
35171c689dcSHans Verkuil 			/*
35271c689dcSHans Verkuil 			 * mref should be set only for the first helper in the
35371c689dcSHans Verkuil 			 * cluster, clear the others.
35471c689dcSHans Verkuil 			 */
35571c689dcSHans Verkuil 			h->mref = NULL;
35671c689dcSHans Verkuil 		}
35771c689dcSHans Verkuil 		/* Point the mref helper to the current helper struct. */
35871c689dcSHans Verkuil 		mref->helper = h;
35971c689dcSHans Verkuil 	}
36071c689dcSHans Verkuil 	mutex_unlock(hdl->lock);
36171c689dcSHans Verkuil 	return 0;
36271c689dcSHans Verkuil }
36371c689dcSHans Verkuil 
36471c689dcSHans Verkuil /*
36571c689dcSHans Verkuil  * Handles the corner case where cs->count == 0. It checks whether the
36671c689dcSHans Verkuil  * specified control class exists. If that class ID is 0, then it checks
36771c689dcSHans Verkuil  * whether there are any controls at all.
36871c689dcSHans Verkuil  */
class_check(struct v4l2_ctrl_handler * hdl,u32 which)36971c689dcSHans Verkuil static int class_check(struct v4l2_ctrl_handler *hdl, u32 which)
37071c689dcSHans Verkuil {
37171c689dcSHans Verkuil 	if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL ||
37271c689dcSHans Verkuil 	    which == V4L2_CTRL_WHICH_REQUEST_VAL)
37371c689dcSHans Verkuil 		return 0;
37471c689dcSHans Verkuil 	return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL;
37571c689dcSHans Verkuil }
37671c689dcSHans Verkuil 
37771c689dcSHans Verkuil /*
37871c689dcSHans Verkuil  * Get extended controls. Allocates the helpers array if needed.
37971c689dcSHans Verkuil  *
38071c689dcSHans Verkuil  * Note that v4l2_g_ext_ctrls_common() with 'which' set to
38171c689dcSHans Verkuil  * V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was
382fb582cbaSHans Verkuil  * completed, and in that case p_req_valid is true for all controls.
38371c689dcSHans Verkuil  */
v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler * hdl,struct v4l2_ext_controls * cs,struct video_device * vdev)38471c689dcSHans Verkuil int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
38571c689dcSHans Verkuil 			    struct v4l2_ext_controls *cs,
38671c689dcSHans Verkuil 			    struct video_device *vdev)
38771c689dcSHans Verkuil {
38871c689dcSHans Verkuil 	struct v4l2_ctrl_helper helper[4];
38971c689dcSHans Verkuil 	struct v4l2_ctrl_helper *helpers = helper;
39071c689dcSHans Verkuil 	int ret;
39171c689dcSHans Verkuil 	int i, j;
39271c689dcSHans Verkuil 	bool is_default, is_request;
39371c689dcSHans Verkuil 
39471c689dcSHans Verkuil 	is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL);
39571c689dcSHans Verkuil 	is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL);
39671c689dcSHans Verkuil 
39771c689dcSHans Verkuil 	cs->error_idx = cs->count;
39871c689dcSHans Verkuil 	cs->which = V4L2_CTRL_ID2WHICH(cs->which);
39971c689dcSHans Verkuil 
40071c689dcSHans Verkuil 	if (!hdl)
40171c689dcSHans Verkuil 		return -EINVAL;
40271c689dcSHans Verkuil 
40371c689dcSHans Verkuil 	if (cs->count == 0)
40471c689dcSHans Verkuil 		return class_check(hdl, cs->which);
40571c689dcSHans Verkuil 
40671c689dcSHans Verkuil 	if (cs->count > ARRAY_SIZE(helper)) {
40771c689dcSHans Verkuil 		helpers = kvmalloc_array(cs->count, sizeof(helper[0]),
40871c689dcSHans Verkuil 					 GFP_KERNEL);
40971c689dcSHans Verkuil 		if (!helpers)
41071c689dcSHans Verkuil 			return -ENOMEM;
41171c689dcSHans Verkuil 	}
41271c689dcSHans Verkuil 
41371c689dcSHans Verkuil 	ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, true);
41471c689dcSHans Verkuil 	cs->error_idx = cs->count;
41571c689dcSHans Verkuil 
41671c689dcSHans Verkuil 	for (i = 0; !ret && i < cs->count; i++)
41771c689dcSHans Verkuil 		if (helpers[i].ref->ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
41871c689dcSHans Verkuil 			ret = -EACCES;
41971c689dcSHans Verkuil 
42071c689dcSHans Verkuil 	for (i = 0; !ret && i < cs->count; i++) {
42171c689dcSHans Verkuil 		struct v4l2_ctrl *master;
42271c689dcSHans Verkuil 		bool is_volatile = false;
42371c689dcSHans Verkuil 		u32 idx = i;
42471c689dcSHans Verkuil 
42571c689dcSHans Verkuil 		if (!helpers[i].mref)
42671c689dcSHans Verkuil 			continue;
42771c689dcSHans Verkuil 
42871c689dcSHans Verkuil 		master = helpers[i].mref->ctrl;
42971c689dcSHans Verkuil 		cs->error_idx = i;
43071c689dcSHans Verkuil 
43171c689dcSHans Verkuil 		v4l2_ctrl_lock(master);
43271c689dcSHans Verkuil 
43371c689dcSHans Verkuil 		/*
43471c689dcSHans Verkuil 		 * g_volatile_ctrl will update the new control values.
43571c689dcSHans Verkuil 		 * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and
43671c689dcSHans Verkuil 		 * V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests
43771c689dcSHans Verkuil 		 * it is v4l2_ctrl_request_complete() that copies the
43871c689dcSHans Verkuil 		 * volatile controls at the time of request completion
43971c689dcSHans Verkuil 		 * to the request, so you don't want to do that again.
44071c689dcSHans Verkuil 		 */
44171c689dcSHans Verkuil 		if (!is_default && !is_request &&
44271c689dcSHans Verkuil 		    ((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||
44371c689dcSHans Verkuil 		    (master->has_volatiles && !is_cur_manual(master)))) {
44471c689dcSHans Verkuil 			for (j = 0; j < master->ncontrols; j++)
44571c689dcSHans Verkuil 				cur_to_new(master->cluster[j]);
44671c689dcSHans Verkuil 			ret = call_op(master, g_volatile_ctrl);
44771c689dcSHans Verkuil 			is_volatile = true;
44871c689dcSHans Verkuil 		}
44971c689dcSHans Verkuil 
45071c689dcSHans Verkuil 		if (ret) {
45171c689dcSHans Verkuil 			v4l2_ctrl_unlock(master);
45271c689dcSHans Verkuil 			break;
45371c689dcSHans Verkuil 		}
45471c689dcSHans Verkuil 
45571c689dcSHans Verkuil 		/*
45671c689dcSHans Verkuil 		 * Copy the default value (if is_default is true), the
45771c689dcSHans Verkuil 		 * request value (if is_request is true and p_req is valid),
45871c689dcSHans Verkuil 		 * the new volatile value (if is_volatile is true) or the
45971c689dcSHans Verkuil 		 * current value.
46071c689dcSHans Verkuil 		 */
46171c689dcSHans Verkuil 		do {
46271c689dcSHans Verkuil 			struct v4l2_ctrl_ref *ref = helpers[idx].ref;
46371c689dcSHans Verkuil 
46471c689dcSHans Verkuil 			if (is_default)
46571c689dcSHans Verkuil 				ret = def_to_user(cs->controls + idx, ref->ctrl);
4667392d87aSHans Verkuil 			else if (is_request && ref->p_req_array_enomem)
467fb582cbaSHans Verkuil 				ret = -ENOMEM;
468fb582cbaSHans Verkuil 			else if (is_request && ref->p_req_valid)
46971c689dcSHans Verkuil 				ret = req_to_user(cs->controls + idx, ref);
47071c689dcSHans Verkuil 			else if (is_volatile)
47171c689dcSHans Verkuil 				ret = new_to_user(cs->controls + idx, ref->ctrl);
47271c689dcSHans Verkuil 			else
47371c689dcSHans Verkuil 				ret = cur_to_user(cs->controls + idx, ref->ctrl);
47471c689dcSHans Verkuil 			idx = helpers[idx].next;
47571c689dcSHans Verkuil 		} while (!ret && idx);
47671c689dcSHans Verkuil 
47771c689dcSHans Verkuil 		v4l2_ctrl_unlock(master);
47871c689dcSHans Verkuil 	}
47971c689dcSHans Verkuil 
48071c689dcSHans Verkuil 	if (cs->count > ARRAY_SIZE(helper))
48171c689dcSHans Verkuil 		kvfree(helpers);
48271c689dcSHans Verkuil 	return ret;
48371c689dcSHans Verkuil }
48471c689dcSHans Verkuil 
v4l2_g_ext_ctrls(struct v4l2_ctrl_handler * hdl,struct video_device * vdev,struct media_device * mdev,struct v4l2_ext_controls * cs)48571c689dcSHans Verkuil int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev,
48671c689dcSHans Verkuil 		     struct media_device *mdev, struct v4l2_ext_controls *cs)
48771c689dcSHans Verkuil {
48871c689dcSHans Verkuil 	if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL)
48971c689dcSHans Verkuil 		return v4l2_g_ext_ctrls_request(hdl, vdev, mdev, cs);
49071c689dcSHans Verkuil 
49171c689dcSHans Verkuil 	return v4l2_g_ext_ctrls_common(hdl, cs, vdev);
49271c689dcSHans Verkuil }
49371c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_g_ext_ctrls);
49471c689dcSHans Verkuil 
495fb582cbaSHans Verkuil /* Validate a new control */
validate_new(const struct v4l2_ctrl * ctrl,union v4l2_ctrl_ptr p_new)496fb582cbaSHans Verkuil static int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new)
497fb582cbaSHans Verkuil {
498cd75981eSHans Verkuil 	return ctrl->type_ops->validate(ctrl, p_new);
499fb582cbaSHans Verkuil }
500fb582cbaSHans Verkuil 
50171c689dcSHans Verkuil /* Validate controls. */
validate_ctrls(struct v4l2_ext_controls * cs,struct v4l2_ctrl_helper * helpers,struct video_device * vdev,bool set)50271c689dcSHans Verkuil static int validate_ctrls(struct v4l2_ext_controls *cs,
50371c689dcSHans Verkuil 			  struct v4l2_ctrl_helper *helpers,
50471c689dcSHans Verkuil 			  struct video_device *vdev,
50571c689dcSHans Verkuil 			  bool set)
50671c689dcSHans Verkuil {
50771c689dcSHans Verkuil 	unsigned int i;
50871c689dcSHans Verkuil 	int ret = 0;
50971c689dcSHans Verkuil 
51071c689dcSHans Verkuil 	cs->error_idx = cs->count;
51171c689dcSHans Verkuil 	for (i = 0; i < cs->count; i++) {
51271c689dcSHans Verkuil 		struct v4l2_ctrl *ctrl = helpers[i].ref->ctrl;
51371c689dcSHans Verkuil 		union v4l2_ctrl_ptr p_new;
51471c689dcSHans Verkuil 
51571c689dcSHans Verkuil 		cs->error_idx = i;
51671c689dcSHans Verkuil 
51771c689dcSHans Verkuil 		if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) {
51871c689dcSHans Verkuil 			dprintk(vdev,
51971c689dcSHans Verkuil 				"control id 0x%x is read-only\n",
52071c689dcSHans Verkuil 				ctrl->id);
52171c689dcSHans Verkuil 			return -EACCES;
52271c689dcSHans Verkuil 		}
52371c689dcSHans Verkuil 		/*
52471c689dcSHans Verkuil 		 * This test is also done in try_set_control_cluster() which
52571c689dcSHans Verkuil 		 * is called in atomic context, so that has the final say,
52671c689dcSHans Verkuil 		 * but it makes sense to do an up-front check as well. Once
52771c689dcSHans Verkuil 		 * an error occurs in try_set_control_cluster() some other
52871c689dcSHans Verkuil 		 * controls may have been set already and we want to do a
52971c689dcSHans Verkuil 		 * best-effort to avoid that.
53071c689dcSHans Verkuil 		 */
53171c689dcSHans Verkuil 		if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) {
53271c689dcSHans Verkuil 			dprintk(vdev,
53371c689dcSHans Verkuil 				"control id 0x%x is grabbed, cannot set\n",
53471c689dcSHans Verkuil 				ctrl->id);
53571c689dcSHans Verkuil 			return -EBUSY;
53671c689dcSHans Verkuil 		}
53771c689dcSHans Verkuil 		/*
53871c689dcSHans Verkuil 		 * Skip validation for now if the payload needs to be copied
53971c689dcSHans Verkuil 		 * from userspace into kernelspace. We'll validate those later.
54071c689dcSHans Verkuil 		 */
54171c689dcSHans Verkuil 		if (ctrl->is_ptr)
54271c689dcSHans Verkuil 			continue;
54371c689dcSHans Verkuil 		if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
54471c689dcSHans Verkuil 			p_new.p_s64 = &cs->controls[i].value64;
54571c689dcSHans Verkuil 		else
54671c689dcSHans Verkuil 			p_new.p_s32 = &cs->controls[i].value;
54771c689dcSHans Verkuil 		ret = validate_new(ctrl, p_new);
54871c689dcSHans Verkuil 		if (ret)
54971c689dcSHans Verkuil 			return ret;
55071c689dcSHans Verkuil 	}
55171c689dcSHans Verkuil 	return 0;
55271c689dcSHans Verkuil }
55371c689dcSHans Verkuil 
55471c689dcSHans Verkuil /* Try or try-and-set controls */
try_set_ext_ctrls_common(struct v4l2_fh * fh,struct v4l2_ctrl_handler * hdl,struct v4l2_ext_controls * cs,struct video_device * vdev,bool set)55571c689dcSHans Verkuil int try_set_ext_ctrls_common(struct v4l2_fh *fh,
55671c689dcSHans Verkuil 			     struct v4l2_ctrl_handler *hdl,
55771c689dcSHans Verkuil 			     struct v4l2_ext_controls *cs,
55871c689dcSHans Verkuil 			     struct video_device *vdev, bool set)
55971c689dcSHans Verkuil {
56071c689dcSHans Verkuil 	struct v4l2_ctrl_helper helper[4];
56171c689dcSHans Verkuil 	struct v4l2_ctrl_helper *helpers = helper;
56271c689dcSHans Verkuil 	unsigned int i, j;
56371c689dcSHans Verkuil 	int ret;
56471c689dcSHans Verkuil 
56571c689dcSHans Verkuil 	cs->error_idx = cs->count;
56671c689dcSHans Verkuil 
56771c689dcSHans Verkuil 	/* Default value cannot be changed */
56871c689dcSHans Verkuil 	if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) {
56971c689dcSHans Verkuil 		dprintk(vdev, "%s: cannot change default value\n",
57071c689dcSHans Verkuil 			video_device_node_name(vdev));
57171c689dcSHans Verkuil 		return -EINVAL;
57271c689dcSHans Verkuil 	}
57371c689dcSHans Verkuil 
57471c689dcSHans Verkuil 	cs->which = V4L2_CTRL_ID2WHICH(cs->which);
57571c689dcSHans Verkuil 
57671c689dcSHans Verkuil 	if (!hdl) {
57771c689dcSHans Verkuil 		dprintk(vdev, "%s: invalid null control handler\n",
57871c689dcSHans Verkuil 			video_device_node_name(vdev));
57971c689dcSHans Verkuil 		return -EINVAL;
58071c689dcSHans Verkuil 	}
58171c689dcSHans Verkuil 
58271c689dcSHans Verkuil 	if (cs->count == 0)
58371c689dcSHans Verkuil 		return class_check(hdl, cs->which);
58471c689dcSHans Verkuil 
58571c689dcSHans Verkuil 	if (cs->count > ARRAY_SIZE(helper)) {
58671c689dcSHans Verkuil 		helpers = kvmalloc_array(cs->count, sizeof(helper[0]),
58771c689dcSHans Verkuil 					 GFP_KERNEL);
58871c689dcSHans Verkuil 		if (!helpers)
58971c689dcSHans Verkuil 			return -ENOMEM;
59071c689dcSHans Verkuil 	}
59171c689dcSHans Verkuil 	ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, false);
59271c689dcSHans Verkuil 	if (!ret)
59371c689dcSHans Verkuil 		ret = validate_ctrls(cs, helpers, vdev, set);
59471c689dcSHans Verkuil 	if (ret && set)
59571c689dcSHans Verkuil 		cs->error_idx = cs->count;
59671c689dcSHans Verkuil 	for (i = 0; !ret && i < cs->count; i++) {
59771c689dcSHans Verkuil 		struct v4l2_ctrl *master;
59871c689dcSHans Verkuil 		u32 idx = i;
59971c689dcSHans Verkuil 
60071c689dcSHans Verkuil 		if (!helpers[i].mref)
60171c689dcSHans Verkuil 			continue;
60271c689dcSHans Verkuil 
60371c689dcSHans Verkuil 		cs->error_idx = i;
60471c689dcSHans Verkuil 		master = helpers[i].mref->ctrl;
60571c689dcSHans Verkuil 		v4l2_ctrl_lock(master);
60671c689dcSHans Verkuil 
60771c689dcSHans Verkuil 		/* Reset the 'is_new' flags of the cluster */
60871c689dcSHans Verkuil 		for (j = 0; j < master->ncontrols; j++)
60971c689dcSHans Verkuil 			if (master->cluster[j])
61071c689dcSHans Verkuil 				master->cluster[j]->is_new = 0;
61171c689dcSHans Verkuil 
61271c689dcSHans Verkuil 		/*
61371c689dcSHans Verkuil 		 * For volatile autoclusters that are currently in auto mode
61471c689dcSHans Verkuil 		 * we need to discover if it will be set to manual mode.
61571c689dcSHans Verkuil 		 * If so, then we have to copy the current volatile values
61671c689dcSHans Verkuil 		 * first since those will become the new manual values (which
61771c689dcSHans Verkuil 		 * may be overwritten by explicit new values from this set
61871c689dcSHans Verkuil 		 * of controls).
61971c689dcSHans Verkuil 		 */
62071c689dcSHans Verkuil 		if (master->is_auto && master->has_volatiles &&
62171c689dcSHans Verkuil 		    !is_cur_manual(master)) {
62271c689dcSHans Verkuil 			/* Pick an initial non-manual value */
62371c689dcSHans Verkuil 			s32 new_auto_val = master->manual_mode_value + 1;
62471c689dcSHans Verkuil 			u32 tmp_idx = idx;
62571c689dcSHans Verkuil 
62671c689dcSHans Verkuil 			do {
62771c689dcSHans Verkuil 				/*
62871c689dcSHans Verkuil 				 * Check if the auto control is part of the
62971c689dcSHans Verkuil 				 * list, and remember the new value.
63071c689dcSHans Verkuil 				 */
63171c689dcSHans Verkuil 				if (helpers[tmp_idx].ref->ctrl == master)
63271c689dcSHans Verkuil 					new_auto_val = cs->controls[tmp_idx].value;
63371c689dcSHans Verkuil 				tmp_idx = helpers[tmp_idx].next;
63471c689dcSHans Verkuil 			} while (tmp_idx);
63571c689dcSHans Verkuil 			/*
63671c689dcSHans Verkuil 			 * If the new value == the manual value, then copy
63771c689dcSHans Verkuil 			 * the current volatile values.
63871c689dcSHans Verkuil 			 */
63971c689dcSHans Verkuil 			if (new_auto_val == master->manual_mode_value)
64071c689dcSHans Verkuil 				update_from_auto_cluster(master);
64171c689dcSHans Verkuil 		}
64271c689dcSHans Verkuil 
64371c689dcSHans Verkuil 		/*
64471c689dcSHans Verkuil 		 * Copy the new caller-supplied control values.
64571c689dcSHans Verkuil 		 * user_to_new() sets 'is_new' to 1.
64671c689dcSHans Verkuil 		 */
64771c689dcSHans Verkuil 		do {
64871c689dcSHans Verkuil 			struct v4l2_ctrl *ctrl = helpers[idx].ref->ctrl;
64971c689dcSHans Verkuil 
65071c689dcSHans Verkuil 			ret = user_to_new(cs->controls + idx, ctrl);
65171c689dcSHans Verkuil 			if (!ret && ctrl->is_ptr) {
65271c689dcSHans Verkuil 				ret = validate_new(ctrl, ctrl->p_new);
65371c689dcSHans Verkuil 				if (ret)
65471c689dcSHans Verkuil 					dprintk(vdev,
65571c689dcSHans Verkuil 						"failed to validate control %s (%d)\n",
65671c689dcSHans Verkuil 						v4l2_ctrl_get_name(ctrl->id), ret);
65771c689dcSHans Verkuil 			}
65871c689dcSHans Verkuil 			idx = helpers[idx].next;
65971c689dcSHans Verkuil 		} while (!ret && idx);
66071c689dcSHans Verkuil 
66171c689dcSHans Verkuil 		if (!ret)
66271c689dcSHans Verkuil 			ret = try_or_set_cluster(fh, master,
66371c689dcSHans Verkuil 						 !hdl->req_obj.req && set, 0);
66471c689dcSHans Verkuil 		if (!ret && hdl->req_obj.req && set) {
66571c689dcSHans Verkuil 			for (j = 0; j < master->ncontrols; j++) {
66671c689dcSHans Verkuil 				struct v4l2_ctrl_ref *ref =
66771c689dcSHans Verkuil 					find_ref(hdl, master->cluster[j]->id);
66871c689dcSHans Verkuil 
66971c689dcSHans Verkuil 				new_to_req(ref);
67071c689dcSHans Verkuil 			}
67171c689dcSHans Verkuil 		}
67271c689dcSHans Verkuil 
67371c689dcSHans Verkuil 		/* Copy the new values back to userspace. */
67471c689dcSHans Verkuil 		if (!ret) {
67571c689dcSHans Verkuil 			idx = i;
67671c689dcSHans Verkuil 			do {
67771c689dcSHans Verkuil 				ret = new_to_user(cs->controls + idx,
67871c689dcSHans Verkuil 						  helpers[idx].ref->ctrl);
67971c689dcSHans Verkuil 				idx = helpers[idx].next;
68071c689dcSHans Verkuil 			} while (!ret && idx);
68171c689dcSHans Verkuil 		}
68271c689dcSHans Verkuil 		v4l2_ctrl_unlock(master);
68371c689dcSHans Verkuil 	}
68471c689dcSHans Verkuil 
68571c689dcSHans Verkuil 	if (cs->count > ARRAY_SIZE(helper))
68671c689dcSHans Verkuil 		kvfree(helpers);
68771c689dcSHans Verkuil 	return ret;
68871c689dcSHans Verkuil }
68971c689dcSHans Verkuil 
try_set_ext_ctrls(struct v4l2_fh * fh,struct v4l2_ctrl_handler * hdl,struct video_device * vdev,struct media_device * mdev,struct v4l2_ext_controls * cs,bool set)69071c689dcSHans Verkuil static int try_set_ext_ctrls(struct v4l2_fh *fh,
69171c689dcSHans Verkuil 			     struct v4l2_ctrl_handler *hdl,
69271c689dcSHans Verkuil 			     struct video_device *vdev,
69371c689dcSHans Verkuil 			     struct media_device *mdev,
69471c689dcSHans Verkuil 			     struct v4l2_ext_controls *cs, bool set)
69571c689dcSHans Verkuil {
69671c689dcSHans Verkuil 	int ret;
69771c689dcSHans Verkuil 
69871c689dcSHans Verkuil 	if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL)
69971c689dcSHans Verkuil 		return try_set_ext_ctrls_request(fh, hdl, vdev, mdev, cs, set);
70071c689dcSHans Verkuil 
70171c689dcSHans Verkuil 	ret = try_set_ext_ctrls_common(fh, hdl, cs, vdev, set);
70271c689dcSHans Verkuil 	if (ret)
70371c689dcSHans Verkuil 		dprintk(vdev,
70471c689dcSHans Verkuil 			"%s: try_set_ext_ctrls_common failed (%d)\n",
70571c689dcSHans Verkuil 			video_device_node_name(vdev), ret);
70671c689dcSHans Verkuil 
70771c689dcSHans Verkuil 	return ret;
70871c689dcSHans Verkuil }
70971c689dcSHans Verkuil 
v4l2_try_ext_ctrls(struct v4l2_ctrl_handler * hdl,struct video_device * vdev,struct media_device * mdev,struct v4l2_ext_controls * cs)71071c689dcSHans Verkuil int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl,
71171c689dcSHans Verkuil 		       struct video_device *vdev,
71271c689dcSHans Verkuil 		       struct media_device *mdev,
71371c689dcSHans Verkuil 		       struct v4l2_ext_controls *cs)
71471c689dcSHans Verkuil {
71571c689dcSHans Verkuil 	return try_set_ext_ctrls(NULL, hdl, vdev, mdev, cs, false);
71671c689dcSHans Verkuil }
71771c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_try_ext_ctrls);
71871c689dcSHans Verkuil 
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)71971c689dcSHans Verkuil int v4l2_s_ext_ctrls(struct v4l2_fh *fh,
72071c689dcSHans Verkuil 		     struct v4l2_ctrl_handler *hdl,
72171c689dcSHans Verkuil 		     struct video_device *vdev,
72271c689dcSHans Verkuil 		     struct media_device *mdev,
72371c689dcSHans Verkuil 		     struct v4l2_ext_controls *cs)
72471c689dcSHans Verkuil {
72571c689dcSHans Verkuil 	return try_set_ext_ctrls(fh, hdl, vdev, mdev, cs, true);
72671c689dcSHans Verkuil }
72771c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_s_ext_ctrls);
72871c689dcSHans Verkuil 
72971c689dcSHans Verkuil /*
73071c689dcSHans Verkuil  * VIDIOC_G/S_CTRL implementation
73171c689dcSHans Verkuil  */
73271c689dcSHans Verkuil 
73371c689dcSHans Verkuil /* Helper function to get a single control */
get_ctrl(struct v4l2_ctrl * ctrl,struct v4l2_ext_control * c)73471c689dcSHans Verkuil static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
73571c689dcSHans Verkuil {
73671c689dcSHans Verkuil 	struct v4l2_ctrl *master = ctrl->cluster[0];
73771c689dcSHans Verkuil 	int ret = 0;
73871c689dcSHans Verkuil 	int i;
73971c689dcSHans Verkuil 
74071c689dcSHans Verkuil 	/* Compound controls are not supported. The new_to_user() and
74171c689dcSHans Verkuil 	 * cur_to_user() calls below would need to be modified not to access
74271c689dcSHans Verkuil 	 * userspace memory when called from get_ctrl().
74371c689dcSHans Verkuil 	 */
74471c689dcSHans Verkuil 	if (!ctrl->is_int && ctrl->type != V4L2_CTRL_TYPE_INTEGER64)
74571c689dcSHans Verkuil 		return -EINVAL;
74671c689dcSHans Verkuil 
74771c689dcSHans Verkuil 	if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
74871c689dcSHans Verkuil 		return -EACCES;
74971c689dcSHans Verkuil 
75071c689dcSHans Verkuil 	v4l2_ctrl_lock(master);
75171c689dcSHans Verkuil 	/* g_volatile_ctrl will update the current control values */
75271c689dcSHans Verkuil 	if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
75371c689dcSHans Verkuil 		for (i = 0; i < master->ncontrols; i++)
75471c689dcSHans Verkuil 			cur_to_new(master->cluster[i]);
75571c689dcSHans Verkuil 		ret = call_op(master, g_volatile_ctrl);
756*32adcb83SMauro Carvalho Chehab 		if (!ret)
757*32adcb83SMauro Carvalho Chehab 			ret = new_to_user(c, ctrl);
75871c689dcSHans Verkuil 	} else {
759*32adcb83SMauro Carvalho Chehab 		ret = cur_to_user(c, ctrl);
76071c689dcSHans Verkuil 	}
76171c689dcSHans Verkuil 	v4l2_ctrl_unlock(master);
76271c689dcSHans Verkuil 	return ret;
76371c689dcSHans Verkuil }
76471c689dcSHans Verkuil 
v4l2_g_ctrl(struct v4l2_ctrl_handler * hdl,struct v4l2_control * control)76571c689dcSHans Verkuil int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
76671c689dcSHans Verkuil {
76771c689dcSHans Verkuil 	struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
76871c689dcSHans Verkuil 	struct v4l2_ext_control c;
76971c689dcSHans Verkuil 	int ret;
77071c689dcSHans Verkuil 
77171c689dcSHans Verkuil 	if (!ctrl || !ctrl->is_int)
77271c689dcSHans Verkuil 		return -EINVAL;
77371c689dcSHans Verkuil 	ret = get_ctrl(ctrl, &c);
774*32adcb83SMauro Carvalho Chehab 
775*32adcb83SMauro Carvalho Chehab 	if (!ret)
77671c689dcSHans Verkuil 		control->value = c.value;
777*32adcb83SMauro Carvalho Chehab 
77871c689dcSHans Verkuil 	return ret;
77971c689dcSHans Verkuil }
78071c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_g_ctrl);
78171c689dcSHans Verkuil 
78271c689dcSHans Verkuil /* Helper function for VIDIOC_S_CTRL compatibility */
set_ctrl(struct v4l2_fh * fh,struct v4l2_ctrl * ctrl,u32 ch_flags)78371c689dcSHans Verkuil static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
78471c689dcSHans Verkuil {
78571c689dcSHans Verkuil 	struct v4l2_ctrl *master = ctrl->cluster[0];
78671c689dcSHans Verkuil 	int ret;
78771c689dcSHans Verkuil 	int i;
78871c689dcSHans Verkuil 
78971c689dcSHans Verkuil 	/* Reset the 'is_new' flags of the cluster */
79071c689dcSHans Verkuil 	for (i = 0; i < master->ncontrols; i++)
79171c689dcSHans Verkuil 		if (master->cluster[i])
79271c689dcSHans Verkuil 			master->cluster[i]->is_new = 0;
79371c689dcSHans Verkuil 
79471c689dcSHans Verkuil 	ret = validate_new(ctrl, ctrl->p_new);
79571c689dcSHans Verkuil 	if (ret)
79671c689dcSHans Verkuil 		return ret;
79771c689dcSHans Verkuil 
79871c689dcSHans Verkuil 	/*
79971c689dcSHans Verkuil 	 * For autoclusters with volatiles that are switched from auto to
80071c689dcSHans Verkuil 	 * manual mode we have to update the current volatile values since
80171c689dcSHans Verkuil 	 * those will become the initial manual values after such a switch.
80271c689dcSHans Verkuil 	 */
80371c689dcSHans Verkuil 	if (master->is_auto && master->has_volatiles && ctrl == master &&
80471c689dcSHans Verkuil 	    !is_cur_manual(master) && ctrl->val == master->manual_mode_value)
80571c689dcSHans Verkuil 		update_from_auto_cluster(master);
80671c689dcSHans Verkuil 
80771c689dcSHans Verkuil 	ctrl->is_new = 1;
80871c689dcSHans Verkuil 	return try_or_set_cluster(fh, master, true, ch_flags);
80971c689dcSHans Verkuil }
81071c689dcSHans Verkuil 
81171c689dcSHans Verkuil /* Helper function for VIDIOC_S_CTRL compatibility */
set_ctrl_lock(struct v4l2_fh * fh,struct v4l2_ctrl * ctrl,struct v4l2_ext_control * c)81271c689dcSHans Verkuil static int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
81371c689dcSHans Verkuil 			 struct v4l2_ext_control *c)
81471c689dcSHans Verkuil {
81571c689dcSHans Verkuil 	int ret;
81671c689dcSHans Verkuil 
81771c689dcSHans Verkuil 	v4l2_ctrl_lock(ctrl);
818*32adcb83SMauro Carvalho Chehab 	ret = user_to_new(c, ctrl);
819*32adcb83SMauro Carvalho Chehab 	if (!ret)
82071c689dcSHans Verkuil 		ret = set_ctrl(fh, ctrl, 0);
82171c689dcSHans Verkuil 	if (!ret)
822*32adcb83SMauro Carvalho Chehab 		ret = cur_to_user(c, ctrl);
82371c689dcSHans Verkuil 	v4l2_ctrl_unlock(ctrl);
82471c689dcSHans Verkuil 	return ret;
82571c689dcSHans Verkuil }
82671c689dcSHans Verkuil 
v4l2_s_ctrl(struct v4l2_fh * fh,struct v4l2_ctrl_handler * hdl,struct v4l2_control * control)82771c689dcSHans Verkuil int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
82871c689dcSHans Verkuil 		struct v4l2_control *control)
82971c689dcSHans Verkuil {
83071c689dcSHans Verkuil 	struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
83171c689dcSHans Verkuil 	struct v4l2_ext_control c = { control->id };
83271c689dcSHans Verkuil 	int ret;
83371c689dcSHans Verkuil 
83471c689dcSHans Verkuil 	if (!ctrl || !ctrl->is_int)
83571c689dcSHans Verkuil 		return -EINVAL;
83671c689dcSHans Verkuil 
83771c689dcSHans Verkuil 	if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
83871c689dcSHans Verkuil 		return -EACCES;
83971c689dcSHans Verkuil 
84071c689dcSHans Verkuil 	c.value = control->value;
84171c689dcSHans Verkuil 	ret = set_ctrl_lock(fh, ctrl, &c);
84271c689dcSHans Verkuil 	control->value = c.value;
84371c689dcSHans Verkuil 	return ret;
84471c689dcSHans Verkuil }
84571c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_s_ctrl);
84671c689dcSHans Verkuil 
84771c689dcSHans Verkuil /*
84871c689dcSHans Verkuil  * Helper functions for drivers to get/set controls.
84971c689dcSHans Verkuil  */
85071c689dcSHans Verkuil 
v4l2_ctrl_g_ctrl(struct v4l2_ctrl * ctrl)85171c689dcSHans Verkuil s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl)
85271c689dcSHans Verkuil {
85371c689dcSHans Verkuil 	struct v4l2_ext_control c;
85471c689dcSHans Verkuil 
85571c689dcSHans Verkuil 	/* It's a driver bug if this happens. */
85671c689dcSHans Verkuil 	if (WARN_ON(!ctrl->is_int))
85771c689dcSHans Verkuil 		return 0;
85871c689dcSHans Verkuil 	c.value = 0;
85971c689dcSHans Verkuil 	get_ctrl(ctrl, &c);
86071c689dcSHans Verkuil 	return c.value;
86171c689dcSHans Verkuil }
86271c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_ctrl_g_ctrl);
86371c689dcSHans Verkuil 
v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl * ctrl)86471c689dcSHans Verkuil s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl)
86571c689dcSHans Verkuil {
86671c689dcSHans Verkuil 	struct v4l2_ext_control c;
86771c689dcSHans Verkuil 
86871c689dcSHans Verkuil 	/* It's a driver bug if this happens. */
86971c689dcSHans Verkuil 	if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64))
87071c689dcSHans Verkuil 		return 0;
87171c689dcSHans Verkuil 	c.value64 = 0;
87271c689dcSHans Verkuil 	get_ctrl(ctrl, &c);
87371c689dcSHans Verkuil 	return c.value64;
87471c689dcSHans Verkuil }
87571c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64);
87671c689dcSHans Verkuil 
__v4l2_ctrl_s_ctrl(struct v4l2_ctrl * ctrl,s32 val)87771c689dcSHans Verkuil int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
87871c689dcSHans Verkuil {
87971c689dcSHans Verkuil 	lockdep_assert_held(ctrl->handler->lock);
88071c689dcSHans Verkuil 
88171c689dcSHans Verkuil 	/* It's a driver bug if this happens. */
88271c689dcSHans Verkuil 	if (WARN_ON(!ctrl->is_int))
88371c689dcSHans Verkuil 		return -EINVAL;
88471c689dcSHans Verkuil 	ctrl->val = val;
88571c689dcSHans Verkuil 	return set_ctrl(NULL, ctrl, 0);
88671c689dcSHans Verkuil }
88771c689dcSHans Verkuil EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl);
88871c689dcSHans Verkuil 
__v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl * ctrl,s64 val)88971c689dcSHans Verkuil int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
89071c689dcSHans Verkuil {
89171c689dcSHans Verkuil 	lockdep_assert_held(ctrl->handler->lock);
89271c689dcSHans Verkuil 
89371c689dcSHans Verkuil 	/* It's a driver bug if this happens. */
89471c689dcSHans Verkuil 	if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64))
89571c689dcSHans Verkuil 		return -EINVAL;
89671c689dcSHans Verkuil 	*ctrl->p_new.p_s64 = val;
89771c689dcSHans Verkuil 	return set_ctrl(NULL, ctrl, 0);
89871c689dcSHans Verkuil }
89971c689dcSHans Verkuil EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64);
90071c689dcSHans Verkuil 
__v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl * ctrl,const char * s)90171c689dcSHans Verkuil int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)
90271c689dcSHans Verkuil {
90371c689dcSHans Verkuil 	lockdep_assert_held(ctrl->handler->lock);
90471c689dcSHans Verkuil 
90571c689dcSHans Verkuil 	/* It's a driver bug if this happens. */
90671c689dcSHans Verkuil 	if (WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING))
90771c689dcSHans Verkuil 		return -EINVAL;
90871c689dcSHans Verkuil 	strscpy(ctrl->p_new.p_char, s, ctrl->maximum + 1);
90971c689dcSHans Verkuil 	return set_ctrl(NULL, ctrl, 0);
91071c689dcSHans Verkuil }
91171c689dcSHans Verkuil EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string);
91271c689dcSHans Verkuil 
__v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl * ctrl,enum v4l2_ctrl_type type,const void * p)91371c689dcSHans Verkuil int __v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl,
91471c689dcSHans Verkuil 				enum v4l2_ctrl_type type, const void *p)
91571c689dcSHans Verkuil {
91671c689dcSHans Verkuil 	lockdep_assert_held(ctrl->handler->lock);
91771c689dcSHans Verkuil 
91871c689dcSHans Verkuil 	/* It's a driver bug if this happens. */
91971c689dcSHans Verkuil 	if (WARN_ON(ctrl->type != type))
92071c689dcSHans Verkuil 		return -EINVAL;
921fb582cbaSHans Verkuil 	/* Setting dynamic arrays is not (yet?) supported. */
922fb582cbaSHans Verkuil 	if (WARN_ON(ctrl->is_dyn_array))
923fb582cbaSHans Verkuil 		return -EINVAL;
92471c689dcSHans Verkuil 	memcpy(ctrl->p_new.p, p, ctrl->elems * ctrl->elem_size);
92571c689dcSHans Verkuil 	return set_ctrl(NULL, ctrl, 0);
92671c689dcSHans Verkuil }
92771c689dcSHans Verkuil EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_compound);
92871c689dcSHans Verkuil 
92971c689dcSHans Verkuil /*
93071c689dcSHans Verkuil  * Modify the range of a control.
93171c689dcSHans Verkuil  */
__v4l2_ctrl_modify_range(struct v4l2_ctrl * ctrl,s64 min,s64 max,u64 step,s64 def)93271c689dcSHans Verkuil int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
93371c689dcSHans Verkuil 			     s64 min, s64 max, u64 step, s64 def)
93471c689dcSHans Verkuil {
93571c689dcSHans Verkuil 	bool value_changed;
93671c689dcSHans Verkuil 	bool range_changed = false;
93771c689dcSHans Verkuil 	int ret;
93871c689dcSHans Verkuil 
93971c689dcSHans Verkuil 	lockdep_assert_held(ctrl->handler->lock);
94071c689dcSHans Verkuil 
94171c689dcSHans Verkuil 	switch (ctrl->type) {
94271c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_INTEGER:
94371c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_INTEGER64:
94471c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_BOOLEAN:
94571c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_MENU:
94671c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_INTEGER_MENU:
94771c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_BITMASK:
94871c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_U8:
94971c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_U16:
95071c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_U32:
95171c689dcSHans Verkuil 		if (ctrl->is_array)
95271c689dcSHans Verkuil 			return -EINVAL;
95371c689dcSHans Verkuil 		ret = check_range(ctrl->type, min, max, step, def);
95471c689dcSHans Verkuil 		if (ret)
95571c689dcSHans Verkuil 			return ret;
95671c689dcSHans Verkuil 		break;
95771c689dcSHans Verkuil 	default:
95871c689dcSHans Verkuil 		return -EINVAL;
95971c689dcSHans Verkuil 	}
96071c689dcSHans Verkuil 	if (ctrl->minimum != min || ctrl->maximum != max ||
96171c689dcSHans Verkuil 	    ctrl->step != step || ctrl->default_value != def) {
96271c689dcSHans Verkuil 		range_changed = true;
96371c689dcSHans Verkuil 		ctrl->minimum = min;
96471c689dcSHans Verkuil 		ctrl->maximum = max;
96571c689dcSHans Verkuil 		ctrl->step = step;
96671c689dcSHans Verkuil 		ctrl->default_value = def;
96771c689dcSHans Verkuil 	}
96871c689dcSHans Verkuil 	cur_to_new(ctrl);
96971c689dcSHans Verkuil 	if (validate_new(ctrl, ctrl->p_new)) {
97071c689dcSHans Verkuil 		if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
97171c689dcSHans Verkuil 			*ctrl->p_new.p_s64 = def;
97271c689dcSHans Verkuil 		else
97371c689dcSHans Verkuil 			*ctrl->p_new.p_s32 = def;
97471c689dcSHans Verkuil 	}
97571c689dcSHans Verkuil 
97671c689dcSHans Verkuil 	if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
97771c689dcSHans Verkuil 		value_changed = *ctrl->p_new.p_s64 != *ctrl->p_cur.p_s64;
97871c689dcSHans Verkuil 	else
97971c689dcSHans Verkuil 		value_changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32;
98071c689dcSHans Verkuil 	if (value_changed)
98171c689dcSHans Verkuil 		ret = set_ctrl(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
98271c689dcSHans Verkuil 	else if (range_changed)
98371c689dcSHans Verkuil 		send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
98471c689dcSHans Verkuil 	return ret;
98571c689dcSHans Verkuil }
98671c689dcSHans Verkuil EXPORT_SYMBOL(__v4l2_ctrl_modify_range);
98771c689dcSHans Verkuil 
__v4l2_ctrl_modify_dimensions(struct v4l2_ctrl * ctrl,u32 dims[V4L2_CTRL_MAX_DIMS])98809752745SHans Verkuil int __v4l2_ctrl_modify_dimensions(struct v4l2_ctrl *ctrl,
98909752745SHans Verkuil 				  u32 dims[V4L2_CTRL_MAX_DIMS])
99009752745SHans Verkuil {
99109752745SHans Verkuil 	unsigned int elems = 1;
99209752745SHans Verkuil 	unsigned int i;
99309752745SHans Verkuil 	void *p_array;
99409752745SHans Verkuil 
99509752745SHans Verkuil 	lockdep_assert_held(ctrl->handler->lock);
99609752745SHans Verkuil 
99709752745SHans Verkuil 	if (!ctrl->is_array || ctrl->is_dyn_array)
99809752745SHans Verkuil 		return -EINVAL;
99909752745SHans Verkuil 
100009752745SHans Verkuil 	for (i = 0; i < ctrl->nr_of_dims; i++)
100109752745SHans Verkuil 		elems *= dims[i];
100209752745SHans Verkuil 	if (elems == 0)
100309752745SHans Verkuil 		return -EINVAL;
100409752745SHans Verkuil 	p_array = kvzalloc(2 * elems * ctrl->elem_size, GFP_KERNEL);
100509752745SHans Verkuil 	if (!p_array)
100609752745SHans Verkuil 		return -ENOMEM;
100709752745SHans Verkuil 	kvfree(ctrl->p_array);
100809752745SHans Verkuil 	ctrl->p_array_alloc_elems = elems;
100909752745SHans Verkuil 	ctrl->elems = elems;
101009752745SHans Verkuil 	ctrl->new_elems = elems;
101109752745SHans Verkuil 	ctrl->p_array = p_array;
101209752745SHans Verkuil 	ctrl->p_new.p = p_array;
101309752745SHans Verkuil 	ctrl->p_cur.p = p_array + elems * ctrl->elem_size;
101409752745SHans Verkuil 	for (i = 0; i < ctrl->nr_of_dims; i++)
101509752745SHans Verkuil 		ctrl->dims[i] = dims[i];
1016cd75981eSHans Verkuil 	ctrl->type_ops->init(ctrl, 0, ctrl->p_cur);
101709752745SHans Verkuil 	cur_to_new(ctrl);
101843cc0ec3SHans Verkuil 	send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_VALUE |
101943cc0ec3SHans Verkuil 			       V4L2_EVENT_CTRL_CH_DIMENSIONS);
102009752745SHans Verkuil 	return 0;
102109752745SHans Verkuil }
102209752745SHans Verkuil EXPORT_SYMBOL(__v4l2_ctrl_modify_dimensions);
102309752745SHans Verkuil 
102471c689dcSHans Verkuil /* Implement VIDIOC_QUERY_EXT_CTRL */
v4l2_query_ext_ctrl(struct v4l2_ctrl_handler * hdl,struct v4l2_query_ext_ctrl * qc)102571c689dcSHans Verkuil int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc)
102671c689dcSHans Verkuil {
102771c689dcSHans Verkuil 	const unsigned int next_flags = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
102871c689dcSHans Verkuil 	u32 id = qc->id & V4L2_CTRL_ID_MASK;
102971c689dcSHans Verkuil 	struct v4l2_ctrl_ref *ref;
103071c689dcSHans Verkuil 	struct v4l2_ctrl *ctrl;
103171c689dcSHans Verkuil 
103271c689dcSHans Verkuil 	if (!hdl)
103371c689dcSHans Verkuil 		return -EINVAL;
103471c689dcSHans Verkuil 
103571c689dcSHans Verkuil 	mutex_lock(hdl->lock);
103671c689dcSHans Verkuil 
103771c689dcSHans Verkuil 	/* Try to find it */
103871c689dcSHans Verkuil 	ref = find_ref(hdl, id);
103971c689dcSHans Verkuil 
104071c689dcSHans Verkuil 	if ((qc->id & next_flags) && !list_empty(&hdl->ctrl_refs)) {
104171c689dcSHans Verkuil 		bool is_compound;
104271c689dcSHans Verkuil 		/* Match any control that is not hidden */
104371c689dcSHans Verkuil 		unsigned int mask = 1;
104471c689dcSHans Verkuil 		bool match = false;
104571c689dcSHans Verkuil 
104671c689dcSHans Verkuil 		if ((qc->id & next_flags) == V4L2_CTRL_FLAG_NEXT_COMPOUND) {
104771c689dcSHans Verkuil 			/* Match any hidden control */
104871c689dcSHans Verkuil 			match = true;
104971c689dcSHans Verkuil 		} else if ((qc->id & next_flags) == next_flags) {
105071c689dcSHans Verkuil 			/* Match any control, compound or not */
105171c689dcSHans Verkuil 			mask = 0;
105271c689dcSHans Verkuil 		}
105371c689dcSHans Verkuil 
105471c689dcSHans Verkuil 		/* Find the next control with ID > qc->id */
105571c689dcSHans Verkuil 
105671c689dcSHans Verkuil 		/* Did we reach the end of the control list? */
105771c689dcSHans Verkuil 		if (id >= node2id(hdl->ctrl_refs.prev)) {
105871c689dcSHans Verkuil 			ref = NULL; /* Yes, so there is no next control */
105971c689dcSHans Verkuil 		} else if (ref) {
106071c689dcSHans Verkuil 			/*
106171c689dcSHans Verkuil 			 * We found a control with the given ID, so just get
106271c689dcSHans Verkuil 			 * the next valid one in the list.
106371c689dcSHans Verkuil 			 */
106471c689dcSHans Verkuil 			list_for_each_entry_continue(ref, &hdl->ctrl_refs, node) {
106571c689dcSHans Verkuil 				is_compound = ref->ctrl->is_array ||
106671c689dcSHans Verkuil 					ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
106771c689dcSHans Verkuil 				if (id < ref->ctrl->id &&
106871c689dcSHans Verkuil 				    (is_compound & mask) == match)
106971c689dcSHans Verkuil 					break;
107071c689dcSHans Verkuil 			}
107171c689dcSHans Verkuil 			if (&ref->node == &hdl->ctrl_refs)
107271c689dcSHans Verkuil 				ref = NULL;
107371c689dcSHans Verkuil 		} else {
107471c689dcSHans Verkuil 			/*
107571c689dcSHans Verkuil 			 * No control with the given ID exists, so start
107671c689dcSHans Verkuil 			 * searching for the next largest ID. We know there
107771c689dcSHans Verkuil 			 * is one, otherwise the first 'if' above would have
107871c689dcSHans Verkuil 			 * been true.
107971c689dcSHans Verkuil 			 */
108071c689dcSHans Verkuil 			list_for_each_entry(ref, &hdl->ctrl_refs, node) {
108171c689dcSHans Verkuil 				is_compound = ref->ctrl->is_array ||
108271c689dcSHans Verkuil 					ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
108371c689dcSHans Verkuil 				if (id < ref->ctrl->id &&
108471c689dcSHans Verkuil 				    (is_compound & mask) == match)
108571c689dcSHans Verkuil 					break;
108671c689dcSHans Verkuil 			}
108771c689dcSHans Verkuil 			if (&ref->node == &hdl->ctrl_refs)
108871c689dcSHans Verkuil 				ref = NULL;
108971c689dcSHans Verkuil 		}
109071c689dcSHans Verkuil 	}
109171c689dcSHans Verkuil 	mutex_unlock(hdl->lock);
109271c689dcSHans Verkuil 
109371c689dcSHans Verkuil 	if (!ref)
109471c689dcSHans Verkuil 		return -EINVAL;
109571c689dcSHans Verkuil 
109671c689dcSHans Verkuil 	ctrl = ref->ctrl;
109771c689dcSHans Verkuil 	memset(qc, 0, sizeof(*qc));
109871c689dcSHans Verkuil 	if (id >= V4L2_CID_PRIVATE_BASE)
109971c689dcSHans Verkuil 		qc->id = id;
110071c689dcSHans Verkuil 	else
110171c689dcSHans Verkuil 		qc->id = ctrl->id;
110271c689dcSHans Verkuil 	strscpy(qc->name, ctrl->name, sizeof(qc->name));
110371c689dcSHans Verkuil 	qc->flags = user_flags(ctrl);
110471c689dcSHans Verkuil 	qc->type = ctrl->type;
110571c689dcSHans Verkuil 	qc->elem_size = ctrl->elem_size;
110671c689dcSHans Verkuil 	qc->elems = ctrl->elems;
110771c689dcSHans Verkuil 	qc->nr_of_dims = ctrl->nr_of_dims;
110871c689dcSHans Verkuil 	memcpy(qc->dims, ctrl->dims, qc->nr_of_dims * sizeof(qc->dims[0]));
110971c689dcSHans Verkuil 	qc->minimum = ctrl->minimum;
111071c689dcSHans Verkuil 	qc->maximum = ctrl->maximum;
111171c689dcSHans Verkuil 	qc->default_value = ctrl->default_value;
111271c689dcSHans Verkuil 	if (ctrl->type == V4L2_CTRL_TYPE_MENU ||
111371c689dcSHans Verkuil 	    ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU)
111471c689dcSHans Verkuil 		qc->step = 1;
111571c689dcSHans Verkuil 	else
111671c689dcSHans Verkuil 		qc->step = ctrl->step;
111771c689dcSHans Verkuil 	return 0;
111871c689dcSHans Verkuil }
111971c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_query_ext_ctrl);
112071c689dcSHans Verkuil 
112171c689dcSHans Verkuil /* Implement VIDIOC_QUERYCTRL */
v4l2_queryctrl(struct v4l2_ctrl_handler * hdl,struct v4l2_queryctrl * qc)112271c689dcSHans Verkuil int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
112371c689dcSHans Verkuil {
112471c689dcSHans Verkuil 	struct v4l2_query_ext_ctrl qec = { qc->id };
112571c689dcSHans Verkuil 	int rc;
112671c689dcSHans Verkuil 
112771c689dcSHans Verkuil 	rc = v4l2_query_ext_ctrl(hdl, &qec);
112871c689dcSHans Verkuil 	if (rc)
112971c689dcSHans Verkuil 		return rc;
113071c689dcSHans Verkuil 
113171c689dcSHans Verkuil 	qc->id = qec.id;
113271c689dcSHans Verkuil 	qc->type = qec.type;
113371c689dcSHans Verkuil 	qc->flags = qec.flags;
113471c689dcSHans Verkuil 	strscpy(qc->name, qec.name, sizeof(qc->name));
113571c689dcSHans Verkuil 	switch (qc->type) {
113671c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_INTEGER:
113771c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_BOOLEAN:
113871c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_MENU:
113971c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_INTEGER_MENU:
114071c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_STRING:
114171c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_BITMASK:
114271c689dcSHans Verkuil 		qc->minimum = qec.minimum;
114371c689dcSHans Verkuil 		qc->maximum = qec.maximum;
114471c689dcSHans Verkuil 		qc->step = qec.step;
114571c689dcSHans Verkuil 		qc->default_value = qec.default_value;
114671c689dcSHans Verkuil 		break;
114771c689dcSHans Verkuil 	default:
114871c689dcSHans Verkuil 		qc->minimum = 0;
114971c689dcSHans Verkuil 		qc->maximum = 0;
115071c689dcSHans Verkuil 		qc->step = 0;
115171c689dcSHans Verkuil 		qc->default_value = 0;
115271c689dcSHans Verkuil 		break;
115371c689dcSHans Verkuil 	}
115471c689dcSHans Verkuil 	return 0;
115571c689dcSHans Verkuil }
115671c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_queryctrl);
115771c689dcSHans Verkuil 
115871c689dcSHans Verkuil /* Implement VIDIOC_QUERYMENU */
v4l2_querymenu(struct v4l2_ctrl_handler * hdl,struct v4l2_querymenu * qm)115971c689dcSHans Verkuil int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm)
116071c689dcSHans Verkuil {
116171c689dcSHans Verkuil 	struct v4l2_ctrl *ctrl;
116271c689dcSHans Verkuil 	u32 i = qm->index;
116371c689dcSHans Verkuil 
116471c689dcSHans Verkuil 	ctrl = v4l2_ctrl_find(hdl, qm->id);
116571c689dcSHans Verkuil 	if (!ctrl)
116671c689dcSHans Verkuil 		return -EINVAL;
116771c689dcSHans Verkuil 
116871c689dcSHans Verkuil 	qm->reserved = 0;
116971c689dcSHans Verkuil 	/* Sanity checks */
117071c689dcSHans Verkuil 	switch (ctrl->type) {
117171c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_MENU:
117271c689dcSHans Verkuil 		if (!ctrl->qmenu)
117371c689dcSHans Verkuil 			return -EINVAL;
117471c689dcSHans Verkuil 		break;
117571c689dcSHans Verkuil 	case V4L2_CTRL_TYPE_INTEGER_MENU:
117671c689dcSHans Verkuil 		if (!ctrl->qmenu_int)
117771c689dcSHans Verkuil 			return -EINVAL;
117871c689dcSHans Verkuil 		break;
117971c689dcSHans Verkuil 	default:
118071c689dcSHans Verkuil 		return -EINVAL;
118171c689dcSHans Verkuil 	}
118271c689dcSHans Verkuil 
118371c689dcSHans Verkuil 	if (i < ctrl->minimum || i > ctrl->maximum)
118471c689dcSHans Verkuil 		return -EINVAL;
118571c689dcSHans Verkuil 
118671c689dcSHans Verkuil 	/* Use mask to see if this menu item should be skipped */
118771c689dcSHans Verkuil 	if (ctrl->menu_skip_mask & (1ULL << i))
118871c689dcSHans Verkuil 		return -EINVAL;
118971c689dcSHans Verkuil 	/* Empty menu items should also be skipped */
119071c689dcSHans Verkuil 	if (ctrl->type == V4L2_CTRL_TYPE_MENU) {
119171c689dcSHans Verkuil 		if (!ctrl->qmenu[i] || ctrl->qmenu[i][0] == '\0')
119271c689dcSHans Verkuil 			return -EINVAL;
119371c689dcSHans Verkuil 		strscpy(qm->name, ctrl->qmenu[i], sizeof(qm->name));
119471c689dcSHans Verkuil 	} else {
119571c689dcSHans Verkuil 		qm->value = ctrl->qmenu_int[i];
119671c689dcSHans Verkuil 	}
119771c689dcSHans Verkuil 	return 0;
119871c689dcSHans Verkuil }
119971c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_querymenu);
120071c689dcSHans Verkuil 
120171c689dcSHans Verkuil /*
120271c689dcSHans Verkuil  * VIDIOC_LOG_STATUS helpers
120371c689dcSHans Verkuil  */
120471c689dcSHans Verkuil 
v4l2_ctrl_log_status(struct file * file,void * fh)120571c689dcSHans Verkuil int v4l2_ctrl_log_status(struct file *file, void *fh)
120671c689dcSHans Verkuil {
120771c689dcSHans Verkuil 	struct video_device *vfd = video_devdata(file);
120871c689dcSHans Verkuil 	struct v4l2_fh *vfh = file->private_data;
120971c689dcSHans Verkuil 
121071c689dcSHans Verkuil 	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev)
121171c689dcSHans Verkuil 		v4l2_ctrl_handler_log_status(vfh->ctrl_handler,
121271c689dcSHans Verkuil 					     vfd->v4l2_dev->name);
121371c689dcSHans Verkuil 	return 0;
121471c689dcSHans Verkuil }
121571c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_ctrl_log_status);
121671c689dcSHans Verkuil 
v4l2_ctrl_subdev_log_status(struct v4l2_subdev * sd)121771c689dcSHans Verkuil int v4l2_ctrl_subdev_log_status(struct v4l2_subdev *sd)
121871c689dcSHans Verkuil {
121971c689dcSHans Verkuil 	v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
122071c689dcSHans Verkuil 	return 0;
122171c689dcSHans Verkuil }
122271c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_ctrl_subdev_log_status);
122371c689dcSHans Verkuil 
122471c689dcSHans Verkuil /*
122571c689dcSHans Verkuil  * VIDIOC_(UN)SUBSCRIBE_EVENT implementation
122671c689dcSHans Verkuil  */
122771c689dcSHans Verkuil 
v4l2_ctrl_add_event(struct v4l2_subscribed_event * sev,unsigned int elems)122871c689dcSHans Verkuil static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev,
122971c689dcSHans Verkuil 			       unsigned int elems)
123071c689dcSHans Verkuil {
123171c689dcSHans Verkuil 	struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
123271c689dcSHans Verkuil 
123371c689dcSHans Verkuil 	if (!ctrl)
123471c689dcSHans Verkuil 		return -EINVAL;
123571c689dcSHans Verkuil 
123671c689dcSHans Verkuil 	v4l2_ctrl_lock(ctrl);
123771c689dcSHans Verkuil 	list_add_tail(&sev->node, &ctrl->ev_subs);
123871c689dcSHans Verkuil 	if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS &&
123971c689dcSHans Verkuil 	    (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL))
124071c689dcSHans Verkuil 		send_initial_event(sev->fh, ctrl);
124171c689dcSHans Verkuil 	v4l2_ctrl_unlock(ctrl);
124271c689dcSHans Verkuil 	return 0;
124371c689dcSHans Verkuil }
124471c689dcSHans Verkuil 
v4l2_ctrl_del_event(struct v4l2_subscribed_event * sev)124571c689dcSHans Verkuil static void v4l2_ctrl_del_event(struct v4l2_subscribed_event *sev)
124671c689dcSHans Verkuil {
124771c689dcSHans Verkuil 	struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
124871c689dcSHans Verkuil 
124971c689dcSHans Verkuil 	if (!ctrl)
125071c689dcSHans Verkuil 		return;
125171c689dcSHans Verkuil 
125271c689dcSHans Verkuil 	v4l2_ctrl_lock(ctrl);
125371c689dcSHans Verkuil 	list_del(&sev->node);
125471c689dcSHans Verkuil 	v4l2_ctrl_unlock(ctrl);
125571c689dcSHans Verkuil }
125671c689dcSHans Verkuil 
v4l2_ctrl_replace(struct v4l2_event * old,const struct v4l2_event * new)125771c689dcSHans Verkuil void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new)
125871c689dcSHans Verkuil {
125971c689dcSHans Verkuil 	u32 old_changes = old->u.ctrl.changes;
126071c689dcSHans Verkuil 
126171c689dcSHans Verkuil 	old->u.ctrl = new->u.ctrl;
126271c689dcSHans Verkuil 	old->u.ctrl.changes |= old_changes;
126371c689dcSHans Verkuil }
126471c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_ctrl_replace);
126571c689dcSHans Verkuil 
v4l2_ctrl_merge(const struct v4l2_event * old,struct v4l2_event * new)126671c689dcSHans Verkuil void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new)
126771c689dcSHans Verkuil {
126871c689dcSHans Verkuil 	new->u.ctrl.changes |= old->u.ctrl.changes;
126971c689dcSHans Verkuil }
127071c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_ctrl_merge);
127171c689dcSHans Verkuil 
127271c689dcSHans Verkuil const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops = {
127371c689dcSHans Verkuil 	.add = v4l2_ctrl_add_event,
127471c689dcSHans Verkuil 	.del = v4l2_ctrl_del_event,
127571c689dcSHans Verkuil 	.replace = v4l2_ctrl_replace,
127671c689dcSHans Verkuil 	.merge = v4l2_ctrl_merge,
127771c689dcSHans Verkuil };
127871c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_ctrl_sub_ev_ops);
127971c689dcSHans Verkuil 
v4l2_ctrl_subscribe_event(struct v4l2_fh * fh,const struct v4l2_event_subscription * sub)128071c689dcSHans Verkuil int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
128171c689dcSHans Verkuil 			      const struct v4l2_event_subscription *sub)
128271c689dcSHans Verkuil {
128371c689dcSHans Verkuil 	if (sub->type == V4L2_EVENT_CTRL)
128471c689dcSHans Verkuil 		return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
128571c689dcSHans Verkuil 	return -EINVAL;
128671c689dcSHans Verkuil }
128771c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_ctrl_subscribe_event);
128871c689dcSHans Verkuil 
v4l2_ctrl_subdev_subscribe_event(struct v4l2_subdev * sd,struct v4l2_fh * fh,struct v4l2_event_subscription * sub)128971c689dcSHans Verkuil int v4l2_ctrl_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
129071c689dcSHans Verkuil 				     struct v4l2_event_subscription *sub)
129171c689dcSHans Verkuil {
129271c689dcSHans Verkuil 	if (!sd->ctrl_handler)
129371c689dcSHans Verkuil 		return -EINVAL;
129471c689dcSHans Verkuil 	return v4l2_ctrl_subscribe_event(fh, sub);
129571c689dcSHans Verkuil }
129671c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_ctrl_subdev_subscribe_event);
129771c689dcSHans Verkuil 
129871c689dcSHans Verkuil /*
129971c689dcSHans Verkuil  * poll helper
130071c689dcSHans Verkuil  */
v4l2_ctrl_poll(struct file * file,struct poll_table_struct * wait)130171c689dcSHans Verkuil __poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait)
130271c689dcSHans Verkuil {
130371c689dcSHans Verkuil 	struct v4l2_fh *fh = file->private_data;
130471c689dcSHans Verkuil 
130571c689dcSHans Verkuil 	poll_wait(file, &fh->wait, wait);
130671c689dcSHans Verkuil 	if (v4l2_event_pending(fh))
130771c689dcSHans Verkuil 		return EPOLLPRI;
130871c689dcSHans Verkuil 	return 0;
130971c689dcSHans Verkuil }
131071c689dcSHans Verkuil EXPORT_SYMBOL(v4l2_ctrl_poll);
1311