[media] v4l2-ctrls: Use v4l2_subscribed_event_ops

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
[hans.verkuil@cisco.com: Fix a locking bug]
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Hans de Goede 2012-04-08 12:59:47 -03:00 committed by Mauro Carvalho Chehab
parent c53c254933
commit 3e366149b8
4 changed files with 39 additions and 51 deletions

View File

@ -1468,8 +1468,9 @@ static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscripti
switch (sub->type) { switch (sub->type) {
case V4L2_EVENT_VSYNC: case V4L2_EVENT_VSYNC:
case V4L2_EVENT_EOS: case V4L2_EVENT_EOS:
case V4L2_EVENT_CTRL:
return v4l2_event_subscribe(fh, sub, 0, NULL); return v4l2_event_subscribe(fh, sub, 0, NULL);
case V4L2_EVENT_CTRL:
return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
default: default:
return -EINVAL; return -EINVAL;
} }

View File

@ -2424,9 +2424,13 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
} }
EXPORT_SYMBOL(v4l2_ctrl_s_ctrl); EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl, static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev)
struct v4l2_subscribed_event *sev)
{ {
struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
if (ctrl == NULL)
return -EINVAL;
v4l2_ctrl_lock(ctrl); v4l2_ctrl_lock(ctrl);
list_add_tail(&sev->node, &ctrl->ev_subs); list_add_tail(&sev->node, &ctrl->ev_subs);
if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS && if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS &&
@ -2440,17 +2444,40 @@ void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
v4l2_event_queue_fh(sev->fh, &ev); v4l2_event_queue_fh(sev->fh, &ev);
} }
v4l2_ctrl_unlock(ctrl); v4l2_ctrl_unlock(ctrl);
return 0;
} }
EXPORT_SYMBOL(v4l2_ctrl_add_event);
void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl, static void v4l2_ctrl_del_event(struct v4l2_subscribed_event *sev)
struct v4l2_subscribed_event *sev)
{ {
struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
v4l2_ctrl_lock(ctrl); v4l2_ctrl_lock(ctrl);
list_del(&sev->node); list_del(&sev->node);
v4l2_ctrl_unlock(ctrl); v4l2_ctrl_unlock(ctrl);
} }
EXPORT_SYMBOL(v4l2_ctrl_del_event);
void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new)
{
u32 old_changes = old->u.ctrl.changes;
old->u.ctrl = new->u.ctrl;
old->u.ctrl.changes |= old_changes;
}
EXPORT_SYMBOL(v4l2_ctrl_replace);
void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new)
{
new->u.ctrl.changes |= old->u.ctrl.changes;
}
EXPORT_SYMBOL(v4l2_ctrl_merge);
const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops = {
.add = v4l2_ctrl_add_event,
.del = v4l2_ctrl_del_event,
.replace = v4l2_ctrl_replace,
.merge = v4l2_ctrl_merge,
};
EXPORT_SYMBOL(v4l2_ctrl_sub_ev_ops);
int v4l2_ctrl_log_status(struct file *file, void *fh) int v4l2_ctrl_log_status(struct file *file, void *fh)
{ {
@ -2468,7 +2495,7 @@ int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub) struct v4l2_event_subscription *sub)
{ {
if (sub->type == V4L2_EVENT_CTRL) if (sub->type == V4L2_EVENT_CTRL)
return v4l2_event_subscribe(fh, sub, 0, NULL); return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
return -EINVAL; return -EINVAL;
} }
EXPORT_SYMBOL(v4l2_ctrl_subscribe_event); EXPORT_SYMBOL(v4l2_ctrl_subscribe_event);

View File

@ -25,7 +25,6 @@
#include <media/v4l2-dev.h> #include <media/v4l2-dev.h>
#include <media/v4l2-fh.h> #include <media/v4l2-fh.h>
#include <media/v4l2-event.h> #include <media/v4l2-event.h>
#include <media/v4l2-ctrls.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -203,30 +202,11 @@ int v4l2_event_pending(struct v4l2_fh *fh)
} }
EXPORT_SYMBOL_GPL(v4l2_event_pending); EXPORT_SYMBOL_GPL(v4l2_event_pending);
static void ctrls_replace(struct v4l2_event *old, const struct v4l2_event *new)
{
u32 old_changes = old->u.ctrl.changes;
old->u.ctrl = new->u.ctrl;
old->u.ctrl.changes |= old_changes;
}
static void ctrls_merge(const struct v4l2_event *old, struct v4l2_event *new)
{
new->u.ctrl.changes |= old->u.ctrl.changes;
}
static const struct v4l2_subscribed_event_ops ctrl_ops = {
.replace = ctrls_replace,
.merge = ctrls_merge,
};
int v4l2_event_subscribe(struct v4l2_fh *fh, int v4l2_event_subscribe(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub, unsigned elems, struct v4l2_event_subscription *sub, unsigned elems,
const struct v4l2_subscribed_event_ops *ops) const struct v4l2_subscribed_event_ops *ops)
{ {
struct v4l2_subscribed_event *sev, *found_ev; struct v4l2_subscribed_event *sev, *found_ev;
struct v4l2_ctrl *ctrl = NULL;
unsigned long flags; unsigned long flags;
unsigned i; unsigned i;
@ -235,11 +215,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
if (elems < 1) if (elems < 1)
elems = 1; elems = 1;
if (sub->type == V4L2_EVENT_CTRL) {
ctrl = v4l2_ctrl_find(fh->ctrl_handler, sub->id);
if (ctrl == NULL)
return -EINVAL;
}
sev = kzalloc(sizeof(*sev) + sizeof(struct v4l2_kevent) * elems, GFP_KERNEL); sev = kzalloc(sizeof(*sev) + sizeof(struct v4l2_kevent) * elems, GFP_KERNEL);
if (!sev) if (!sev)
@ -251,9 +226,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
sev->flags = sub->flags; sev->flags = sub->flags;
sev->fh = fh; sev->fh = fh;
sev->ops = ops; sev->ops = ops;
if (ctrl) {
sev->ops = &ctrl_ops;
}
spin_lock_irqsave(&fh->vdev->fh_lock, flags); spin_lock_irqsave(&fh->vdev->fh_lock, flags);
found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); found_ev = v4l2_event_subscribed(fh, sub->type, sub->id);
@ -275,10 +247,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
} }
} }
/* v4l2_ctrl_add_event uses a mutex, so do this outside the spin lock */
if (ctrl)
v4l2_ctrl_add_event(ctrl, sev);
/* Mark as ready for use */ /* Mark as ready for use */
sev->elems = elems; sev->elems = elems;
@ -338,13 +306,6 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
if (sev && sev->ops && sev->ops->del) if (sev && sev->ops && sev->ops->del)
sev->ops->del(sev); sev->ops->del(sev);
if (sev && sev->type == V4L2_EVENT_CTRL) {
struct v4l2_ctrl *ctrl = v4l2_ctrl_find(fh->ctrl_handler, sev->id);
if (ctrl)
v4l2_ctrl_del_event(ctrl, sev);
}
kfree(sev); kfree(sev);
return 0; return 0;

View File

@ -491,10 +491,9 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val); int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
/* Internal helper functions that deal with control events. */ /* Internal helper functions that deal with control events. */
void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl, extern const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops;
struct v4l2_subscribed_event *sev); void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new);
void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl, void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new);
struct v4l2_subscribed_event *sev);
struct file; struct file;
/* Can be used as a vidioc_log_status function that just dumps all controls /* Can be used as a vidioc_log_status function that just dumps all controls