[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:
parent
c53c254933
commit
3e366149b8
4 changed files with 39 additions and 51 deletions
|
@ -1468,8 +1468,9 @@ static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscripti
|
|||
switch (sub->type) {
|
||||
case V4L2_EVENT_VSYNC:
|
||||
case V4L2_EVENT_EOS:
|
||||
case V4L2_EVENT_CTRL:
|
||||
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:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -2424,9 +2424,13 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
|
|||
}
|
||||
EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
|
||||
|
||||
void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
|
||||
struct v4l2_subscribed_event *sev)
|
||||
static int v4l2_ctrl_add_event(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);
|
||||
list_add_tail(&sev->node, &ctrl->ev_subs);
|
||||
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_ctrl_unlock(ctrl);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(v4l2_ctrl_add_event);
|
||||
|
||||
void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
|
||||
struct v4l2_subscribed_event *sev)
|
||||
static void v4l2_ctrl_del_event(struct v4l2_subscribed_event *sev)
|
||||
{
|
||||
struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
|
||||
|
||||
v4l2_ctrl_lock(ctrl);
|
||||
list_del(&sev->node);
|
||||
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)
|
||||
{
|
||||
|
@ -2468,7 +2495,7 @@ int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
|
|||
struct v4l2_event_subscription *sub)
|
||||
{
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL(v4l2_ctrl_subscribe_event);
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <media/v4l2-dev.h>
|
||||
#include <media/v4l2-fh.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -203,30 +202,11 @@ int v4l2_event_pending(struct v4l2_fh *fh)
|
|||
}
|
||||
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,
|
||||
struct v4l2_event_subscription *sub, unsigned elems,
|
||||
const struct v4l2_subscribed_event_ops *ops)
|
||||
{
|
||||
struct v4l2_subscribed_event *sev, *found_ev;
|
||||
struct v4l2_ctrl *ctrl = NULL;
|
||||
unsigned long flags;
|
||||
unsigned i;
|
||||
|
||||
|
@ -235,11 +215,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
|
|||
|
||||
if (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);
|
||||
if (!sev)
|
||||
|
@ -251,9 +226,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
|
|||
sev->flags = sub->flags;
|
||||
sev->fh = fh;
|
||||
sev->ops = ops;
|
||||
if (ctrl) {
|
||||
sev->ops = &ctrl_ops;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
|
||||
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 */
|
||||
sev->elems = elems;
|
||||
|
||||
|
@ -338,13 +306,6 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
|
|||
if (sev && sev->ops && sev->ops->del)
|
||||
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);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -491,10 +491,9 @@ 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_event(struct v4l2_ctrl *ctrl,
|
||||
struct v4l2_subscribed_event *sev);
|
||||
void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
|
||||
struct v4l2_subscribed_event *sev);
|
||||
extern const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops;
|
||||
void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new);
|
||||
void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new);
|
||||
|
||||
struct file;
|
||||
/* Can be used as a vidioc_log_status function that just dumps all controls
|
||||
|
|
Loading…
Reference in a new issue