• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * V4L2 controls framework Request API implementation.
4  *
5  * Copyright (C) 2018-2021  Hans Verkuil <hverkuil-cisco@xs4all.nl>
6  */
7 
8 #define pr_fmt(fmt) "v4l2-ctrls: " fmt
9 
10 #include <linux/export.h>
11 #include <linux/slab.h>
12 #include <media/v4l2-ctrls.h>
13 #include <media/v4l2-dev.h>
14 #include <media/v4l2-ioctl.h>
15 
16 #include "v4l2-ctrls-priv.h"
17 
18 /* Initialize the request-related fields in a control handler */
v4l2_ctrl_handler_init_request(struct v4l2_ctrl_handler * hdl)19 void v4l2_ctrl_handler_init_request(struct v4l2_ctrl_handler *hdl)
20 {
21 	INIT_LIST_HEAD(&hdl->requests);
22 	INIT_LIST_HEAD(&hdl->requests_queued);
23 	hdl->request_is_queued = false;
24 	media_request_object_init(&hdl->req_obj);
25 }
26 
27 /* Free the request-related fields in a control handler */
v4l2_ctrl_handler_free_request(struct v4l2_ctrl_handler * hdl)28 void v4l2_ctrl_handler_free_request(struct v4l2_ctrl_handler *hdl)
29 {
30 	struct v4l2_ctrl_handler *req, *next_req;
31 
32 	/*
33 	 * Do nothing if this isn't the main handler or the main
34 	 * handler is not used in any request.
35 	 *
36 	 * The main handler can be identified by having a NULL ops pointer in
37 	 * the request object.
38 	 */
39 	if (hdl->req_obj.ops || list_empty(&hdl->requests))
40 		return;
41 
42 	/*
43 	 * If the main handler is freed and it is used by handler objects in
44 	 * outstanding requests, then unbind and put those objects before
45 	 * freeing the main handler.
46 	 */
47 	list_for_each_entry_safe(req, next_req, &hdl->requests, requests) {
48 		media_request_object_unbind(&req->req_obj);
49 		media_request_object_put(&req->req_obj);
50 	}
51 }
52 
v4l2_ctrl_request_clone(struct v4l2_ctrl_handler * hdl,const struct v4l2_ctrl_handler * from)53 static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl,
54 				   const struct v4l2_ctrl_handler *from)
55 {
56 	struct v4l2_ctrl_ref *ref;
57 	int err = 0;
58 
59 	if (WARN_ON(!hdl || hdl == from))
60 		return -EINVAL;
61 
62 	if (hdl->error)
63 		return hdl->error;
64 
65 	WARN_ON(hdl->lock != &hdl->_lock);
66 
67 	mutex_lock(from->lock);
68 	list_for_each_entry(ref, &from->ctrl_refs, node) {
69 		struct v4l2_ctrl *ctrl = ref->ctrl;
70 		struct v4l2_ctrl_ref *new_ref;
71 
72 		/* Skip refs inherited from other devices */
73 		if (ref->from_other_dev)
74 			continue;
75 		err = handler_new_ref(hdl, ctrl, &new_ref, false, true);
76 		if (err)
77 			break;
78 	}
79 	mutex_unlock(from->lock);
80 	return err;
81 }
82 
v4l2_ctrl_request_queue(struct media_request_object * obj)83 static void v4l2_ctrl_request_queue(struct media_request_object *obj)
84 {
85 	struct v4l2_ctrl_handler *hdl =
86 		container_of(obj, struct v4l2_ctrl_handler, req_obj);
87 	struct v4l2_ctrl_handler *main_hdl = obj->priv;
88 
89 	mutex_lock(main_hdl->lock);
90 	list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued);
91 	hdl->request_is_queued = true;
92 	mutex_unlock(main_hdl->lock);
93 }
94 
v4l2_ctrl_request_unbind(struct media_request_object * obj)95 static void v4l2_ctrl_request_unbind(struct media_request_object *obj)
96 {
97 	struct v4l2_ctrl_handler *hdl =
98 		container_of(obj, struct v4l2_ctrl_handler, req_obj);
99 	struct v4l2_ctrl_handler *main_hdl = obj->priv;
100 
101 	mutex_lock(main_hdl->lock);
102 	list_del_init(&hdl->requests);
103 	if (hdl->request_is_queued) {
104 		list_del_init(&hdl->requests_queued);
105 		hdl->request_is_queued = false;
106 	}
107 	mutex_unlock(main_hdl->lock);
108 }
109 
v4l2_ctrl_request_release(struct media_request_object * obj)110 static void v4l2_ctrl_request_release(struct media_request_object *obj)
111 {
112 	struct v4l2_ctrl_handler *hdl =
113 		container_of(obj, struct v4l2_ctrl_handler, req_obj);
114 
115 	v4l2_ctrl_handler_free(hdl);
116 	kfree(hdl);
117 }
118 
119 static const struct media_request_object_ops req_ops = {
120 	.queue = v4l2_ctrl_request_queue,
121 	.unbind = v4l2_ctrl_request_unbind,
122 	.release = v4l2_ctrl_request_release,
123 };
124 
v4l2_ctrl_request_hdl_find(struct media_request * req,struct v4l2_ctrl_handler * parent)125 struct v4l2_ctrl_handler *v4l2_ctrl_request_hdl_find(struct media_request *req,
126 						     struct v4l2_ctrl_handler *parent)
127 {
128 	struct media_request_object *obj;
129 
130 	if (WARN_ON(req->state != MEDIA_REQUEST_STATE_VALIDATING &&
131 		    req->state != MEDIA_REQUEST_STATE_QUEUED))
132 		return NULL;
133 
134 	obj = media_request_object_find(req, &req_ops, parent);
135 	if (obj)
136 		return container_of(obj, struct v4l2_ctrl_handler, req_obj);
137 	return NULL;
138 }
139 EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_find);
140 
141 struct v4l2_ctrl *
v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler * hdl,u32 id)142 v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)
143 {
144 	struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id);
145 
146 	return (ref && ref->p_req_valid) ? ref->ctrl : NULL;
147 }
148 EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find);
149 
v4l2_ctrl_request_bind(struct media_request * req,struct v4l2_ctrl_handler * hdl,struct v4l2_ctrl_handler * from)150 static int v4l2_ctrl_request_bind(struct media_request *req,
151 				  struct v4l2_ctrl_handler *hdl,
152 				  struct v4l2_ctrl_handler *from)
153 {
154 	int ret;
155 
156 	ret = v4l2_ctrl_request_clone(hdl, from);
157 
158 	if (!ret) {
159 		ret = media_request_object_bind(req, &req_ops,
160 						from, false, &hdl->req_obj);
161 		if (!ret) {
162 			mutex_lock(from->lock);
163 			list_add_tail(&hdl->requests, &from->requests);
164 			mutex_unlock(from->lock);
165 		}
166 	}
167 	return ret;
168 }
169 
170 static struct media_request_object *
v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler * hdl,struct media_request * req,bool set)171 v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl,
172 			struct media_request *req, bool set)
173 {
174 	struct media_request_object *obj;
175 	struct v4l2_ctrl_handler *new_hdl;
176 	int ret;
177 
178 	if (IS_ERR(req))
179 		return ERR_CAST(req);
180 
181 	if (set && WARN_ON(req->state != MEDIA_REQUEST_STATE_UPDATING))
182 		return ERR_PTR(-EBUSY);
183 
184 	obj = media_request_object_find(req, &req_ops, hdl);
185 	if (obj)
186 		return obj;
187 	/*
188 	 * If there are no controls in this completed request,
189 	 * then that can only happen if:
190 	 *
191 	 * 1) no controls were present in the queued request, and
192 	 * 2) v4l2_ctrl_request_complete() could not allocate a
193 	 *    control handler object to store the completed state in.
194 	 *
195 	 * So return ENOMEM to indicate that there was an out-of-memory
196 	 * error.
197 	 */
198 	if (!set)
199 		return ERR_PTR(-ENOMEM);
200 
201 	new_hdl = kzalloc(sizeof(*new_hdl), GFP_KERNEL);
202 	if (!new_hdl)
203 		return ERR_PTR(-ENOMEM);
204 
205 	obj = &new_hdl->req_obj;
206 	ret = v4l2_ctrl_handler_init(new_hdl, (hdl->nr_of_buckets - 1) * 8);
207 	if (!ret)
208 		ret = v4l2_ctrl_request_bind(req, new_hdl, hdl);
209 	if (ret) {
210 		v4l2_ctrl_handler_free(new_hdl);
211 		kfree(new_hdl);
212 		return ERR_PTR(ret);
213 	}
214 
215 	media_request_object_get(obj);
216 	return obj;
217 }
218 
v4l2_g_ext_ctrls_request(struct v4l2_ctrl_handler * hdl,struct video_device * vdev,struct media_device * mdev,struct v4l2_ext_controls * cs)219 int v4l2_g_ext_ctrls_request(struct v4l2_ctrl_handler *hdl, struct video_device *vdev,
220 			     struct media_device *mdev, struct v4l2_ext_controls *cs)
221 {
222 	struct media_request_object *obj = NULL;
223 	struct media_request *req = NULL;
224 	int ret;
225 
226 	if (!mdev || cs->request_fd < 0)
227 		return -EINVAL;
228 
229 	req = media_request_get_by_fd(mdev, cs->request_fd);
230 	if (IS_ERR(req))
231 		return PTR_ERR(req);
232 
233 	if (req->state != MEDIA_REQUEST_STATE_COMPLETE) {
234 		media_request_put(req);
235 		return -EACCES;
236 	}
237 
238 	ret = media_request_lock_for_access(req);
239 	if (ret) {
240 		media_request_put(req);
241 		return ret;
242 	}
243 
244 	obj = v4l2_ctrls_find_req_obj(hdl, req, false);
245 	if (IS_ERR(obj)) {
246 		media_request_unlock_for_access(req);
247 		media_request_put(req);
248 		return PTR_ERR(obj);
249 	}
250 
251 	hdl = container_of(obj, struct v4l2_ctrl_handler,
252 			   req_obj);
253 	ret = v4l2_g_ext_ctrls_common(hdl, cs, vdev);
254 
255 	media_request_unlock_for_access(req);
256 	media_request_object_put(obj);
257 	media_request_put(req);
258 	return ret;
259 }
260 
try_set_ext_ctrls_request(struct v4l2_fh * fh,struct v4l2_ctrl_handler * hdl,struct video_device * vdev,struct media_device * mdev,struct v4l2_ext_controls * cs,bool set)261 int try_set_ext_ctrls_request(struct v4l2_fh *fh,
262 			      struct v4l2_ctrl_handler *hdl,
263 			      struct video_device *vdev,
264 			      struct media_device *mdev,
265 			      struct v4l2_ext_controls *cs, bool set)
266 {
267 	struct media_request_object *obj = NULL;
268 	struct media_request *req = NULL;
269 	int ret;
270 
271 	if (!mdev) {
272 		dprintk(vdev, "%s: missing media device\n",
273 			video_device_node_name(vdev));
274 		return -EINVAL;
275 	}
276 
277 	if (cs->request_fd < 0) {
278 		dprintk(vdev, "%s: invalid request fd %d\n",
279 			video_device_node_name(vdev), cs->request_fd);
280 		return -EINVAL;
281 	}
282 
283 	req = media_request_get_by_fd(mdev, cs->request_fd);
284 	if (IS_ERR(req)) {
285 		dprintk(vdev, "%s: cannot find request fd %d\n",
286 			video_device_node_name(vdev), cs->request_fd);
287 		return PTR_ERR(req);
288 	}
289 
290 	ret = media_request_lock_for_update(req);
291 	if (ret) {
292 		dprintk(vdev, "%s: cannot lock request fd %d\n",
293 			video_device_node_name(vdev), cs->request_fd);
294 		media_request_put(req);
295 		return ret;
296 	}
297 
298 	obj = v4l2_ctrls_find_req_obj(hdl, req, set);
299 	if (IS_ERR(obj)) {
300 		dprintk(vdev,
301 			"%s: cannot find request object for request fd %d\n",
302 			video_device_node_name(vdev),
303 			cs->request_fd);
304 		media_request_unlock_for_update(req);
305 		media_request_put(req);
306 		return PTR_ERR(obj);
307 	}
308 
309 	hdl = container_of(obj, struct v4l2_ctrl_handler,
310 			   req_obj);
311 	ret = try_set_ext_ctrls_common(fh, hdl, cs, vdev, set);
312 	if (ret)
313 		dprintk(vdev,
314 			"%s: try_set_ext_ctrls_common failed (%d)\n",
315 			video_device_node_name(vdev), ret);
316 
317 	media_request_unlock_for_update(req);
318 	media_request_object_put(obj);
319 	media_request_put(req);
320 
321 	return ret;
322 }
323 
v4l2_ctrl_request_complete(struct media_request * req,struct v4l2_ctrl_handler * main_hdl)324 void v4l2_ctrl_request_complete(struct media_request *req,
325 				struct v4l2_ctrl_handler *main_hdl)
326 {
327 	struct media_request_object *obj;
328 	struct v4l2_ctrl_handler *hdl;
329 	struct v4l2_ctrl_ref *ref;
330 
331 	if (!req || !main_hdl)
332 		return;
333 
334 	/*
335 	 * Note that it is valid if nothing was found. It means
336 	 * that this request doesn't have any controls and so just
337 	 * wants to leave the controls unchanged.
338 	 */
339 	obj = media_request_object_find(req, &req_ops, main_hdl);
340 	if (!obj) {
341 		int ret;
342 
343 		/* Create a new request so the driver can return controls */
344 		hdl = kzalloc(sizeof(*hdl), GFP_KERNEL);
345 		if (!hdl)
346 			return;
347 
348 		ret = v4l2_ctrl_handler_init(hdl, (main_hdl->nr_of_buckets - 1) * 8);
349 		if (!ret)
350 			ret = v4l2_ctrl_request_bind(req, hdl, main_hdl);
351 		if (ret) {
352 			v4l2_ctrl_handler_free(hdl);
353 			kfree(hdl);
354 			return;
355 		}
356 		hdl->request_is_queued = true;
357 		obj = media_request_object_find(req, &req_ops, main_hdl);
358 	}
359 	hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj);
360 
361 	list_for_each_entry(ref, &hdl->ctrl_refs, node) {
362 		struct v4l2_ctrl *ctrl = ref->ctrl;
363 		struct v4l2_ctrl *master = ctrl->cluster[0];
364 		unsigned int i;
365 
366 		if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
367 			v4l2_ctrl_lock(master);
368 			/* g_volatile_ctrl will update the current control values */
369 			for (i = 0; i < master->ncontrols; i++)
370 				cur_to_new(master->cluster[i]);
371 			call_op(master, g_volatile_ctrl);
372 			new_to_req(ref);
373 			v4l2_ctrl_unlock(master);
374 			continue;
375 		}
376 		if (ref->p_req_valid)
377 			continue;
378 
379 		/* Copy the current control value into the request */
380 		v4l2_ctrl_lock(ctrl);
381 		cur_to_req(ref);
382 		v4l2_ctrl_unlock(ctrl);
383 	}
384 
385 	mutex_lock(main_hdl->lock);
386 	WARN_ON(!hdl->request_is_queued);
387 	list_del_init(&hdl->requests_queued);
388 	hdl->request_is_queued = false;
389 	mutex_unlock(main_hdl->lock);
390 	media_request_object_complete(obj);
391 	media_request_object_put(obj);
392 }
393 EXPORT_SYMBOL(v4l2_ctrl_request_complete);
394 
v4l2_ctrl_request_setup(struct media_request * req,struct v4l2_ctrl_handler * main_hdl)395 int v4l2_ctrl_request_setup(struct media_request *req,
396 			    struct v4l2_ctrl_handler *main_hdl)
397 {
398 	struct media_request_object *obj;
399 	struct v4l2_ctrl_handler *hdl;
400 	struct v4l2_ctrl_ref *ref;
401 	int ret = 0;
402 
403 	if (!req || !main_hdl)
404 		return 0;
405 
406 	if (WARN_ON(req->state != MEDIA_REQUEST_STATE_QUEUED))
407 		return -EBUSY;
408 
409 	/*
410 	 * Note that it is valid if nothing was found. It means
411 	 * that this request doesn't have any controls and so just
412 	 * wants to leave the controls unchanged.
413 	 */
414 	obj = media_request_object_find(req, &req_ops, main_hdl);
415 	if (!obj)
416 		return 0;
417 	if (obj->completed) {
418 		media_request_object_put(obj);
419 		return -EBUSY;
420 	}
421 	hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj);
422 
423 	list_for_each_entry(ref, &hdl->ctrl_refs, node)
424 		ref->req_done = false;
425 
426 	list_for_each_entry(ref, &hdl->ctrl_refs, node) {
427 		struct v4l2_ctrl *ctrl = ref->ctrl;
428 		struct v4l2_ctrl *master = ctrl->cluster[0];
429 		bool have_new_data = false;
430 		int i;
431 
432 		/*
433 		 * Skip if this control was already handled by a cluster.
434 		 * Skip button controls and read-only controls.
435 		 */
436 		if (ref->req_done || (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY))
437 			continue;
438 
439 		v4l2_ctrl_lock(master);
440 		for (i = 0; i < master->ncontrols; i++) {
441 			if (master->cluster[i]) {
442 				struct v4l2_ctrl_ref *r =
443 					find_ref(hdl, master->cluster[i]->id);
444 
445 				if (r->p_req_valid) {
446 					have_new_data = true;
447 					break;
448 				}
449 			}
450 		}
451 		if (!have_new_data) {
452 			v4l2_ctrl_unlock(master);
453 			continue;
454 		}
455 
456 		for (i = 0; i < master->ncontrols; i++) {
457 			if (master->cluster[i]) {
458 				struct v4l2_ctrl_ref *r =
459 					find_ref(hdl, master->cluster[i]->id);
460 
461 				ret = req_to_new(r);
462 				if (ret) {
463 					v4l2_ctrl_unlock(master);
464 					goto error;
465 				}
466 				master->cluster[i]->is_new = 1;
467 				r->req_done = true;
468 			}
469 		}
470 		/*
471 		 * For volatile autoclusters that are currently in auto mode
472 		 * we need to discover if it will be set to manual mode.
473 		 * If so, then we have to copy the current volatile values
474 		 * first since those will become the new manual values (which
475 		 * may be overwritten by explicit new values from this set
476 		 * of controls).
477 		 */
478 		if (master->is_auto && master->has_volatiles &&
479 		    !is_cur_manual(master)) {
480 			s32 new_auto_val = *master->p_new.p_s32;
481 
482 			/*
483 			 * If the new value == the manual value, then copy
484 			 * the current volatile values.
485 			 */
486 			if (new_auto_val == master->manual_mode_value)
487 				update_from_auto_cluster(master);
488 		}
489 
490 		ret = try_or_set_cluster(NULL, master, true, 0);
491 		v4l2_ctrl_unlock(master);
492 
493 		if (ret)
494 			break;
495 	}
496 
497 error:
498 	media_request_object_put(obj);
499 	return ret;
500 }
501 EXPORT_SYMBOL(v4l2_ctrl_request_setup);
502