linux/drivers/media/v4l2-core/v4l2-ctrls-request.c
<<
>>
Prefs
   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 */
  19void 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 */
  28void 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
  53static 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
  83static 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
  95static 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
 110static 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
 119static 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
 125struct 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}
 139EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_find);
 140
 141struct v4l2_ctrl *
 142v4l2_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->valid_p_req) ? ref->ctrl : NULL;
 147}
 148EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find);
 149
 150static 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
 170static struct media_request_object *
 171v4l2_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
 219int 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
 261int 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
 324void 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->valid_p_req)
 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}
 393EXPORT_SYMBOL(v4l2_ctrl_request_complete);
 394
 395int 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->valid_p_req) {
 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                                req_to_new(r);
 462                                master->cluster[i]->is_new = 1;
 463                                r->req_done = true;
 464                        }
 465                }
 466                /*
 467                 * For volatile autoclusters that are currently in auto mode
 468                 * we need to discover if it will be set to manual mode.
 469                 * If so, then we have to copy the current volatile values
 470                 * first since those will become the new manual values (which
 471                 * may be overwritten by explicit new values from this set
 472                 * of controls).
 473                 */
 474                if (master->is_auto && master->has_volatiles &&
 475                    !is_cur_manual(master)) {
 476                        s32 new_auto_val = *master->p_new.p_s32;
 477
 478                        /*
 479                         * If the new value == the manual value, then copy
 480                         * the current volatile values.
 481                         */
 482                        if (new_auto_val == master->manual_mode_value)
 483                                update_from_auto_cluster(master);
 484                }
 485
 486                ret = try_or_set_cluster(NULL, master, true, 0);
 487                v4l2_ctrl_unlock(master);
 488
 489                if (ret)
 490                        break;
 491        }
 492
 493        media_request_object_put(obj);
 494        return ret;
 495}
 496EXPORT_SYMBOL(v4l2_ctrl_request_setup);
 497