[media] v4l2-ctrls: simplify event subscription
Hans Verkuil [Fri, 10 Jun 2011 08:56:39 +0000 (05:56 -0300)]
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

drivers/media/video/v4l2-ctrls.c
include/media/v4l2-ctrls.h

index 5f31666..d084cea 100644 (file)
@@ -1013,6 +1013,7 @@ static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
           insertion is an O(1) operation. */
        if (list_empty(&hdl->ctrl_refs) || id > node2id(hdl->ctrl_refs.prev)) {
                list_add_tail(&new_ref->node, &hdl->ctrl_refs);
+               hdl->nr_of_refs++;
                goto insert_in_hash;
        }
 
@@ -2061,3 +2062,22 @@ void v4l2_ctrl_del_fh(struct v4l2_ctrl *ctrl, struct v4l2_fh *fh)
        v4l2_ctrl_unlock(ctrl);
 }
 EXPORT_SYMBOL(v4l2_ctrl_del_fh);
+
+int v4l2_ctrl_subscribe_fh(struct v4l2_fh *fh,
+                       struct v4l2_event_subscription *sub, unsigned n)
+{
+       struct v4l2_ctrl_handler *hdl = fh->ctrl_handler;
+       int ret = 0;
+
+       if (!fh->events)
+               ret = v4l2_event_init(fh);
+       if (!ret) {
+               if (hdl->nr_of_refs * 2 > n)
+                       n = hdl->nr_of_refs * 2;
+               ret = v4l2_event_alloc(fh, n);
+       }
+       if (!ret)
+               ret = v4l2_event_subscribe(fh, sub);
+       return ret;
+}
+EXPORT_SYMBOL(v4l2_ctrl_subscribe_fh);
index c45bf40..de68a59 100644 (file)
@@ -169,6 +169,7 @@ struct v4l2_ctrl_ref {
   *            control is needed multiple times, so this is a simple
   *            optimization.
   * @buckets:  Buckets for the hashing. Allows for quick control lookup.
+  * @nr_of_refs: Total number of control references in the list.
   * @nr_of_buckets: Total number of buckets in the array.
   * @error:    The error code of the first failed control addition.
   */
@@ -178,6 +179,7 @@ struct v4l2_ctrl_handler {
        struct list_head ctrl_refs;
        struct v4l2_ctrl_ref *cached;
        struct v4l2_ctrl_ref **buckets;
+       u16 nr_of_refs;
        u16 nr_of_buckets;
        int error;
 };
@@ -494,11 +496,29 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
   */
 int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
 
+/* Internal helper functions that deal with control events. */
 void v4l2_ctrl_add_fh(struct v4l2_ctrl_handler *hdl,
                struct v4l2_ctrl_fh *ctrl_fh,
                struct v4l2_event_subscription *sub);
 void v4l2_ctrl_del_fh(struct v4l2_ctrl *ctrl, struct v4l2_fh *fh);
 
+/** v4l2_ctrl_subscribe_fh() - Helper function that subscribes a control event.
+  * @fh:       The file handler that subscribed the control event.
+  * @sub:      The event to subscribe (type must be V4L2_EVENT_CTRL).
+  * @n:                How many events should be allocated? (Passed to v4l2_event_alloc).
+  *            Recommended to set to twice the number of controls plus whatever
+  *            is needed for other events. This function will set n to
+  *            max(n, 2 * fh->ctrl_handler->nr_of_refs).
+  *
+  * A helper function that initializes the fh for events, allocates the
+  * list of events and subscribes the control event.
+  *
+  * Typically called in the handler of VIDIOC_SUBSCRIBE_EVENT in the
+  * V4L2_EVENT_CTRL case.
+  */
+int v4l2_ctrl_subscribe_fh(struct v4l2_fh *fh,
+                       struct v4l2_event_subscription *sub, unsigned n);
+
 /* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */
 int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc);
 int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm);