0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "v4l2-ctrls: " fmt
0009
0010 #include <linux/export.h>
0011 #include <linux/slab.h>
0012 #include <media/v4l2-ctrls.h>
0013 #include <media/v4l2-dev.h>
0014 #include <media/v4l2-ioctl.h>
0015
0016 #include "v4l2-ctrls-priv.h"
0017
0018
0019 void v4l2_ctrl_handler_init_request(struct v4l2_ctrl_handler *hdl)
0020 {
0021 INIT_LIST_HEAD(&hdl->requests);
0022 INIT_LIST_HEAD(&hdl->requests_queued);
0023 hdl->request_is_queued = false;
0024 media_request_object_init(&hdl->req_obj);
0025 }
0026
0027
0028 void v4l2_ctrl_handler_free_request(struct v4l2_ctrl_handler *hdl)
0029 {
0030 struct v4l2_ctrl_handler *req, *next_req;
0031
0032
0033
0034
0035
0036
0037
0038
0039 if (hdl->req_obj.ops || list_empty(&hdl->requests))
0040 return;
0041
0042
0043
0044
0045
0046
0047 list_for_each_entry_safe(req, next_req, &hdl->requests, requests) {
0048 media_request_object_unbind(&req->req_obj);
0049 media_request_object_put(&req->req_obj);
0050 }
0051 }
0052
0053 static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl,
0054 const struct v4l2_ctrl_handler *from)
0055 {
0056 struct v4l2_ctrl_ref *ref;
0057 int err = 0;
0058
0059 if (WARN_ON(!hdl || hdl == from))
0060 return -EINVAL;
0061
0062 if (hdl->error)
0063 return hdl->error;
0064
0065 WARN_ON(hdl->lock != &hdl->_lock);
0066
0067 mutex_lock(from->lock);
0068 list_for_each_entry(ref, &from->ctrl_refs, node) {
0069 struct v4l2_ctrl *ctrl = ref->ctrl;
0070 struct v4l2_ctrl_ref *new_ref;
0071
0072
0073 if (ref->from_other_dev)
0074 continue;
0075 err = handler_new_ref(hdl, ctrl, &new_ref, false, true);
0076 if (err)
0077 break;
0078 }
0079 mutex_unlock(from->lock);
0080 return err;
0081 }
0082
0083 static void v4l2_ctrl_request_queue(struct media_request_object *obj)
0084 {
0085 struct v4l2_ctrl_handler *hdl =
0086 container_of(obj, struct v4l2_ctrl_handler, req_obj);
0087 struct v4l2_ctrl_handler *main_hdl = obj->priv;
0088
0089 mutex_lock(main_hdl->lock);
0090 list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued);
0091 hdl->request_is_queued = true;
0092 mutex_unlock(main_hdl->lock);
0093 }
0094
0095 static void v4l2_ctrl_request_unbind(struct media_request_object *obj)
0096 {
0097 struct v4l2_ctrl_handler *hdl =
0098 container_of(obj, struct v4l2_ctrl_handler, req_obj);
0099 struct v4l2_ctrl_handler *main_hdl = obj->priv;
0100
0101 mutex_lock(main_hdl->lock);
0102 list_del_init(&hdl->requests);
0103 if (hdl->request_is_queued) {
0104 list_del_init(&hdl->requests_queued);
0105 hdl->request_is_queued = false;
0106 }
0107 mutex_unlock(main_hdl->lock);
0108 }
0109
0110 static void v4l2_ctrl_request_release(struct media_request_object *obj)
0111 {
0112 struct v4l2_ctrl_handler *hdl =
0113 container_of(obj, struct v4l2_ctrl_handler, req_obj);
0114
0115 v4l2_ctrl_handler_free(hdl);
0116 kfree(hdl);
0117 }
0118
0119 static const struct media_request_object_ops req_ops = {
0120 .queue = v4l2_ctrl_request_queue,
0121 .unbind = v4l2_ctrl_request_unbind,
0122 .release = v4l2_ctrl_request_release,
0123 };
0124
0125 struct v4l2_ctrl_handler *v4l2_ctrl_request_hdl_find(struct media_request *req,
0126 struct v4l2_ctrl_handler *parent)
0127 {
0128 struct media_request_object *obj;
0129
0130 if (WARN_ON(req->state != MEDIA_REQUEST_STATE_VALIDATING &&
0131 req->state != MEDIA_REQUEST_STATE_QUEUED))
0132 return NULL;
0133
0134 obj = media_request_object_find(req, &req_ops, parent);
0135 if (obj)
0136 return container_of(obj, struct v4l2_ctrl_handler, req_obj);
0137 return NULL;
0138 }
0139 EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_find);
0140
0141 struct v4l2_ctrl *
0142 v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)
0143 {
0144 struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id);
0145
0146 return (ref && ref->p_req_valid) ? ref->ctrl : NULL;
0147 }
0148 EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find);
0149
0150 static int v4l2_ctrl_request_bind(struct media_request *req,
0151 struct v4l2_ctrl_handler *hdl,
0152 struct v4l2_ctrl_handler *from)
0153 {
0154 int ret;
0155
0156 ret = v4l2_ctrl_request_clone(hdl, from);
0157
0158 if (!ret) {
0159 ret = media_request_object_bind(req, &req_ops,
0160 from, false, &hdl->req_obj);
0161 if (!ret) {
0162 mutex_lock(from->lock);
0163 list_add_tail(&hdl->requests, &from->requests);
0164 mutex_unlock(from->lock);
0165 }
0166 }
0167 return ret;
0168 }
0169
0170 static struct media_request_object *
0171 v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl,
0172 struct media_request *req, bool set)
0173 {
0174 struct media_request_object *obj;
0175 struct v4l2_ctrl_handler *new_hdl;
0176 int ret;
0177
0178 if (IS_ERR(req))
0179 return ERR_CAST(req);
0180
0181 if (set && WARN_ON(req->state != MEDIA_REQUEST_STATE_UPDATING))
0182 return ERR_PTR(-EBUSY);
0183
0184 obj = media_request_object_find(req, &req_ops, hdl);
0185 if (obj)
0186 return obj;
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 if (!set)
0199 return ERR_PTR(-ENOMEM);
0200
0201 new_hdl = kzalloc(sizeof(*new_hdl), GFP_KERNEL);
0202 if (!new_hdl)
0203 return ERR_PTR(-ENOMEM);
0204
0205 obj = &new_hdl->req_obj;
0206 ret = v4l2_ctrl_handler_init(new_hdl, (hdl->nr_of_buckets - 1) * 8);
0207 if (!ret)
0208 ret = v4l2_ctrl_request_bind(req, new_hdl, hdl);
0209 if (ret) {
0210 v4l2_ctrl_handler_free(new_hdl);
0211 kfree(new_hdl);
0212 return ERR_PTR(ret);
0213 }
0214
0215 media_request_object_get(obj);
0216 return obj;
0217 }
0218
0219 int v4l2_g_ext_ctrls_request(struct v4l2_ctrl_handler *hdl, struct video_device *vdev,
0220 struct media_device *mdev, struct v4l2_ext_controls *cs)
0221 {
0222 struct media_request_object *obj = NULL;
0223 struct media_request *req = NULL;
0224 int ret;
0225
0226 if (!mdev || cs->request_fd < 0)
0227 return -EINVAL;
0228
0229 req = media_request_get_by_fd(mdev, cs->request_fd);
0230 if (IS_ERR(req))
0231 return PTR_ERR(req);
0232
0233 if (req->state != MEDIA_REQUEST_STATE_COMPLETE) {
0234 media_request_put(req);
0235 return -EACCES;
0236 }
0237
0238 ret = media_request_lock_for_access(req);
0239 if (ret) {
0240 media_request_put(req);
0241 return ret;
0242 }
0243
0244 obj = v4l2_ctrls_find_req_obj(hdl, req, false);
0245 if (IS_ERR(obj)) {
0246 media_request_unlock_for_access(req);
0247 media_request_put(req);
0248 return PTR_ERR(obj);
0249 }
0250
0251 hdl = container_of(obj, struct v4l2_ctrl_handler,
0252 req_obj);
0253 ret = v4l2_g_ext_ctrls_common(hdl, cs, vdev);
0254
0255 media_request_unlock_for_access(req);
0256 media_request_object_put(obj);
0257 media_request_put(req);
0258 return ret;
0259 }
0260
0261 int try_set_ext_ctrls_request(struct v4l2_fh *fh,
0262 struct v4l2_ctrl_handler *hdl,
0263 struct video_device *vdev,
0264 struct media_device *mdev,
0265 struct v4l2_ext_controls *cs, bool set)
0266 {
0267 struct media_request_object *obj = NULL;
0268 struct media_request *req = NULL;
0269 int ret;
0270
0271 if (!mdev) {
0272 dprintk(vdev, "%s: missing media device\n",
0273 video_device_node_name(vdev));
0274 return -EINVAL;
0275 }
0276
0277 if (cs->request_fd < 0) {
0278 dprintk(vdev, "%s: invalid request fd %d\n",
0279 video_device_node_name(vdev), cs->request_fd);
0280 return -EINVAL;
0281 }
0282
0283 req = media_request_get_by_fd(mdev, cs->request_fd);
0284 if (IS_ERR(req)) {
0285 dprintk(vdev, "%s: cannot find request fd %d\n",
0286 video_device_node_name(vdev), cs->request_fd);
0287 return PTR_ERR(req);
0288 }
0289
0290 ret = media_request_lock_for_update(req);
0291 if (ret) {
0292 dprintk(vdev, "%s: cannot lock request fd %d\n",
0293 video_device_node_name(vdev), cs->request_fd);
0294 media_request_put(req);
0295 return ret;
0296 }
0297
0298 obj = v4l2_ctrls_find_req_obj(hdl, req, set);
0299 if (IS_ERR(obj)) {
0300 dprintk(vdev,
0301 "%s: cannot find request object for request fd %d\n",
0302 video_device_node_name(vdev),
0303 cs->request_fd);
0304 media_request_unlock_for_update(req);
0305 media_request_put(req);
0306 return PTR_ERR(obj);
0307 }
0308
0309 hdl = container_of(obj, struct v4l2_ctrl_handler,
0310 req_obj);
0311 ret = try_set_ext_ctrls_common(fh, hdl, cs, vdev, set);
0312 if (ret)
0313 dprintk(vdev,
0314 "%s: try_set_ext_ctrls_common failed (%d)\n",
0315 video_device_node_name(vdev), ret);
0316
0317 media_request_unlock_for_update(req);
0318 media_request_object_put(obj);
0319 media_request_put(req);
0320
0321 return ret;
0322 }
0323
0324 void v4l2_ctrl_request_complete(struct media_request *req,
0325 struct v4l2_ctrl_handler *main_hdl)
0326 {
0327 struct media_request_object *obj;
0328 struct v4l2_ctrl_handler *hdl;
0329 struct v4l2_ctrl_ref *ref;
0330
0331 if (!req || !main_hdl)
0332 return;
0333
0334
0335
0336
0337
0338
0339 obj = media_request_object_find(req, &req_ops, main_hdl);
0340 if (!obj) {
0341 int ret;
0342
0343
0344 hdl = kzalloc(sizeof(*hdl), GFP_KERNEL);
0345 if (!hdl)
0346 return;
0347
0348 ret = v4l2_ctrl_handler_init(hdl, (main_hdl->nr_of_buckets - 1) * 8);
0349 if (!ret)
0350 ret = v4l2_ctrl_request_bind(req, hdl, main_hdl);
0351 if (ret) {
0352 v4l2_ctrl_handler_free(hdl);
0353 kfree(hdl);
0354 return;
0355 }
0356 hdl->request_is_queued = true;
0357 obj = media_request_object_find(req, &req_ops, main_hdl);
0358 }
0359 hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj);
0360
0361 list_for_each_entry(ref, &hdl->ctrl_refs, node) {
0362 struct v4l2_ctrl *ctrl = ref->ctrl;
0363 struct v4l2_ctrl *master = ctrl->cluster[0];
0364 unsigned int i;
0365
0366 if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
0367 v4l2_ctrl_lock(master);
0368
0369 for (i = 0; i < master->ncontrols; i++)
0370 cur_to_new(master->cluster[i]);
0371 call_op(master, g_volatile_ctrl);
0372 new_to_req(ref);
0373 v4l2_ctrl_unlock(master);
0374 continue;
0375 }
0376 if (ref->p_req_valid)
0377 continue;
0378
0379
0380 v4l2_ctrl_lock(ctrl);
0381 cur_to_req(ref);
0382 v4l2_ctrl_unlock(ctrl);
0383 }
0384
0385 mutex_lock(main_hdl->lock);
0386 WARN_ON(!hdl->request_is_queued);
0387 list_del_init(&hdl->requests_queued);
0388 hdl->request_is_queued = false;
0389 mutex_unlock(main_hdl->lock);
0390 media_request_object_complete(obj);
0391 media_request_object_put(obj);
0392 }
0393 EXPORT_SYMBOL(v4l2_ctrl_request_complete);
0394
0395 int v4l2_ctrl_request_setup(struct media_request *req,
0396 struct v4l2_ctrl_handler *main_hdl)
0397 {
0398 struct media_request_object *obj;
0399 struct v4l2_ctrl_handler *hdl;
0400 struct v4l2_ctrl_ref *ref;
0401 int ret = 0;
0402
0403 if (!req || !main_hdl)
0404 return 0;
0405
0406 if (WARN_ON(req->state != MEDIA_REQUEST_STATE_QUEUED))
0407 return -EBUSY;
0408
0409
0410
0411
0412
0413
0414 obj = media_request_object_find(req, &req_ops, main_hdl);
0415 if (!obj)
0416 return 0;
0417 if (obj->completed) {
0418 media_request_object_put(obj);
0419 return -EBUSY;
0420 }
0421 hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj);
0422
0423 list_for_each_entry(ref, &hdl->ctrl_refs, node)
0424 ref->req_done = false;
0425
0426 list_for_each_entry(ref, &hdl->ctrl_refs, node) {
0427 struct v4l2_ctrl *ctrl = ref->ctrl;
0428 struct v4l2_ctrl *master = ctrl->cluster[0];
0429 bool have_new_data = false;
0430 int i;
0431
0432
0433
0434
0435
0436 if (ref->req_done || (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY))
0437 continue;
0438
0439 v4l2_ctrl_lock(master);
0440 for (i = 0; i < master->ncontrols; i++) {
0441 if (master->cluster[i]) {
0442 struct v4l2_ctrl_ref *r =
0443 find_ref(hdl, master->cluster[i]->id);
0444
0445 if (r->p_req_valid) {
0446 have_new_data = true;
0447 break;
0448 }
0449 }
0450 }
0451 if (!have_new_data) {
0452 v4l2_ctrl_unlock(master);
0453 continue;
0454 }
0455
0456 for (i = 0; i < master->ncontrols; i++) {
0457 if (master->cluster[i]) {
0458 struct v4l2_ctrl_ref *r =
0459 find_ref(hdl, master->cluster[i]->id);
0460
0461 ret = req_to_new(r);
0462 if (ret) {
0463 v4l2_ctrl_unlock(master);
0464 goto error;
0465 }
0466 master->cluster[i]->is_new = 1;
0467 r->req_done = true;
0468 }
0469 }
0470
0471
0472
0473
0474
0475
0476
0477
0478 if (master->is_auto && master->has_volatiles &&
0479 !is_cur_manual(master)) {
0480 s32 new_auto_val = *master->p_new.p_s32;
0481
0482
0483
0484
0485
0486 if (new_auto_val == master->manual_mode_value)
0487 update_from_auto_cluster(master);
0488 }
0489
0490 ret = try_or_set_cluster(NULL, master, true, 0);
0491 v4l2_ctrl_unlock(master);
0492
0493 if (ret)
0494 break;
0495 }
0496
0497 error:
0498 media_request_object_put(obj);
0499 return ret;
0500 }
0501 EXPORT_SYMBOL(v4l2_ctrl_request_setup);