Commit 77068d36 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] v4l2-ctrls/event: remove struct v4l2_ctrl_fh, instead use v4l2_subscribed_event

The v4l2_ctrl_fh struct connected v4l2_ctrl with v4l2_fh so the control
would know which filehandles subscribed to it. However, it is much easier
to use struct v4l2_subscribed_event directly for that and get rid of that
intermediate struct.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 523f46d6
...@@ -581,15 +581,15 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change ...@@ -581,15 +581,15 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change
static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes) static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
{ {
struct v4l2_event ev; struct v4l2_event ev;
struct v4l2_ctrl_fh *pos; struct v4l2_subscribed_event *sev;
if (list_empty(&ctrl->fhs)) if (list_empty(&ctrl->ev_subs))
return; return;
fill_event(&ev, ctrl, changes); fill_event(&ev, ctrl, changes);
list_for_each_entry(pos, &ctrl->fhs, node) list_for_each_entry(sev, &ctrl->ev_subs, node)
if (pos->fh != fh) if (sev->fh && sev->fh != fh)
v4l2_event_queue_fh(pos->fh, &ev); v4l2_event_queue_fh(sev->fh, &ev);
} }
/* Helper function: copy the current control value back to the caller */ /* Helper function: copy the current control value back to the caller */
...@@ -867,7 +867,7 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl) ...@@ -867,7 +867,7 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
{ {
struct v4l2_ctrl_ref *ref, *next_ref; struct v4l2_ctrl_ref *ref, *next_ref;
struct v4l2_ctrl *ctrl, *next_ctrl; struct v4l2_ctrl *ctrl, *next_ctrl;
struct v4l2_ctrl_fh *ctrl_fh, *next_ctrl_fh; struct v4l2_subscribed_event *sev, *next_sev;
if (hdl == NULL || hdl->buckets == NULL) if (hdl == NULL || hdl->buckets == NULL)
return; return;
...@@ -881,10 +881,8 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl) ...@@ -881,10 +881,8 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
/* Free all controls owned by the handler */ /* Free all controls owned by the handler */
list_for_each_entry_safe(ctrl, next_ctrl, &hdl->ctrls, node) { list_for_each_entry_safe(ctrl, next_ctrl, &hdl->ctrls, node) {
list_del(&ctrl->node); list_del(&ctrl->node);
list_for_each_entry_safe(ctrl_fh, next_ctrl_fh, &ctrl->fhs, node) { list_for_each_entry_safe(sev, next_sev, &ctrl->ev_subs, node)
list_del(&ctrl_fh->node); list_del(&sev->node);
kfree(ctrl_fh);
}
kfree(ctrl); kfree(ctrl);
} }
kfree(hdl->buckets); kfree(hdl->buckets);
...@@ -1084,7 +1082,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, ...@@ -1084,7 +1082,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
} }
INIT_LIST_HEAD(&ctrl->node); INIT_LIST_HEAD(&ctrl->node);
INIT_LIST_HEAD(&ctrl->fhs); INIT_LIST_HEAD(&ctrl->ev_subs);
ctrl->handler = hdl; ctrl->handler = hdl;
ctrl->ops = ops; ctrl->ops = ops;
ctrl->id = id; ctrl->id = id;
...@@ -2028,41 +2026,31 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) ...@@ -2028,41 +2026,31 @@ 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_fh(struct v4l2_ctrl_handler *hdl, void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
struct v4l2_ctrl_fh *ctrl_fh, struct v4l2_subscribed_event *sev)
struct v4l2_event_subscription *sub)
{ {
struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, sub->id);
v4l2_ctrl_lock(ctrl); v4l2_ctrl_lock(ctrl);
list_add_tail(&ctrl_fh->node, &ctrl->fhs); list_add_tail(&sev->node, &ctrl->ev_subs);
if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS && if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS &&
(sub->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL)) { (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL)) {
struct v4l2_event ev; struct v4l2_event ev;
fill_event(&ev, ctrl, V4L2_EVENT_CTRL_CH_VALUE | fill_event(&ev, ctrl, V4L2_EVENT_CTRL_CH_VALUE |
V4L2_EVENT_CTRL_CH_FLAGS); V4L2_EVENT_CTRL_CH_FLAGS);
v4l2_event_queue_fh(ctrl_fh->fh, &ev); v4l2_event_queue_fh(sev->fh, &ev);
} }
v4l2_ctrl_unlock(ctrl); v4l2_ctrl_unlock(ctrl);
} }
EXPORT_SYMBOL(v4l2_ctrl_add_fh); EXPORT_SYMBOL(v4l2_ctrl_add_event);
void v4l2_ctrl_del_fh(struct v4l2_ctrl *ctrl, struct v4l2_fh *fh) void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
struct v4l2_subscribed_event *sev)
{ {
struct v4l2_ctrl_fh *pos;
v4l2_ctrl_lock(ctrl); v4l2_ctrl_lock(ctrl);
list_for_each_entry(pos, &ctrl->fhs, node) { list_del(&sev->node);
if (pos->fh == fh) {
list_del(&pos->node);
kfree(pos);
break;
}
}
v4l2_ctrl_unlock(ctrl); v4l2_ctrl_unlock(ctrl);
} }
EXPORT_SYMBOL(v4l2_ctrl_del_fh); EXPORT_SYMBOL(v4l2_ctrl_del_event);
int v4l2_ctrl_subscribe_fh(struct v4l2_fh *fh, int v4l2_ctrl_subscribe_fh(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub, unsigned n) struct v4l2_event_subscription *sub, unsigned n)
......
...@@ -213,7 +213,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, ...@@ -213,7 +213,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
{ {
struct v4l2_subscribed_event *sev, *found_ev; struct v4l2_subscribed_event *sev, *found_ev;
struct v4l2_ctrl *ctrl = NULL; struct v4l2_ctrl *ctrl = NULL;
struct v4l2_ctrl_fh *ctrl_fh = NULL;
unsigned long flags; unsigned long flags;
if (sub->type == V4L2_EVENT_CTRL) { if (sub->type == V4L2_EVENT_CTRL) {
...@@ -222,17 +221,9 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, ...@@ -222,17 +221,9 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
return -EINVAL; return -EINVAL;
} }
sev = kmalloc(sizeof(*sev), GFP_KERNEL); sev = kzalloc(sizeof(*sev), GFP_KERNEL);
if (!sev) if (!sev)
return -ENOMEM; return -ENOMEM;
if (ctrl) {
ctrl_fh = kzalloc(sizeof(*ctrl_fh), GFP_KERNEL);
if (!ctrl_fh) {
kfree(sev);
return -ENOMEM;
}
ctrl_fh->fh = fh;
}
spin_lock_irqsave(&fh->vdev->fh_lock, flags); spin_lock_irqsave(&fh->vdev->fh_lock, flags);
...@@ -241,22 +232,19 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, ...@@ -241,22 +232,19 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
INIT_LIST_HEAD(&sev->list); INIT_LIST_HEAD(&sev->list);
sev->type = sub->type; sev->type = sub->type;
sev->id = sub->id; sev->id = sub->id;
sev->fh = fh;
sev->flags = sub->flags;
list_add(&sev->list, &fh->subscribed); list_add(&sev->list, &fh->subscribed);
sev = NULL;
} }
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
/* v4l2_ctrl_add_fh uses a mutex, so do this outside the spin lock */ /* v4l2_ctrl_add_fh uses a mutex, so do this outside the spin lock */
if (ctrl) { if (found_ev)
if (found_ev) kfree(sev);
kfree(ctrl_fh); else if (ctrl)
else v4l2_ctrl_add_event(ctrl, sev);
v4l2_ctrl_add_fh(fh->ctrl_handler, ctrl_fh, sub);
}
kfree(sev);
return 0; return 0;
} }
...@@ -298,15 +286,17 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh, ...@@ -298,15 +286,17 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
spin_lock_irqsave(&fh->vdev->fh_lock, flags); spin_lock_irqsave(&fh->vdev->fh_lock, flags);
sev = v4l2_event_subscribed(fh, sub->type, sub->id); sev = v4l2_event_subscribed(fh, sub->type, sub->id);
if (sev != NULL) if (sev != NULL) {
list_del(&sev->list); list_del(&sev->list);
sev->fh = NULL;
}
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
if (sev->type == V4L2_EVENT_CTRL) { if (sev && sev->type == V4L2_EVENT_CTRL) {
struct v4l2_ctrl *ctrl = v4l2_ctrl_find(fh->ctrl_handler, sev->id); struct v4l2_ctrl *ctrl = v4l2_ctrl_find(fh->ctrl_handler, sev->id);
if (ctrl) if (ctrl)
v4l2_ctrl_del_fh(ctrl, fh); v4l2_ctrl_del_event(ctrl, sev);
} }
kfree(sev); kfree(sev);
......
...@@ -31,6 +31,7 @@ struct v4l2_ctrl; ...@@ -31,6 +31,7 @@ struct v4l2_ctrl;
struct video_device; struct video_device;
struct v4l2_subdev; struct v4l2_subdev;
struct v4l2_event_subscription; struct v4l2_event_subscription;
struct v4l2_subscribed_event;
struct v4l2_fh; struct v4l2_fh;
/** struct v4l2_ctrl_ops - The control operations that the driver has to provide. /** struct v4l2_ctrl_ops - The control operations that the driver has to provide.
...@@ -53,6 +54,7 @@ struct v4l2_ctrl_ops { ...@@ -53,6 +54,7 @@ struct v4l2_ctrl_ops {
/** struct v4l2_ctrl - The control structure. /** struct v4l2_ctrl - The control structure.
* @node: The list node. * @node: The list node.
* @ev_subs: The list of control event subscriptions.
* @handler: The handler that owns the control. * @handler: The handler that owns the control.
* @cluster: Point to start of cluster array. * @cluster: Point to start of cluster array.
* @ncontrols: Number of controls in cluster array. * @ncontrols: Number of controls in cluster array.
...@@ -108,7 +110,7 @@ struct v4l2_ctrl_ops { ...@@ -108,7 +110,7 @@ struct v4l2_ctrl_ops {
struct v4l2_ctrl { struct v4l2_ctrl {
/* Administrative fields */ /* Administrative fields */
struct list_head node; struct list_head node;
struct list_head fhs; struct list_head ev_subs;
struct v4l2_ctrl_handler *handler; struct v4l2_ctrl_handler *handler;
struct v4l2_ctrl **cluster; struct v4l2_ctrl **cluster;
unsigned ncontrols; unsigned ncontrols;
...@@ -184,11 +186,6 @@ struct v4l2_ctrl_handler { ...@@ -184,11 +186,6 @@ struct v4l2_ctrl_handler {
int error; int error;
}; };
struct v4l2_ctrl_fh {
struct list_head node;
struct v4l2_fh *fh;
};
/** struct v4l2_ctrl_config - Control configuration structure. /** struct v4l2_ctrl_config - Control configuration structure.
* @ops: The control ops. * @ops: The control ops.
* @id: The control ID. * @id: The control ID.
...@@ -497,10 +494,10 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl); ...@@ -497,10 +494,10 @@ 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_fh(struct v4l2_ctrl_handler *hdl, void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
struct v4l2_ctrl_fh *ctrl_fh, struct v4l2_subscribed_event *sev);
struct v4l2_event_subscription *sub); void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
void v4l2_ctrl_del_fh(struct v4l2_ctrl *ctrl, struct v4l2_fh *fh); struct v4l2_subscribed_event *sev);
/** v4l2_ctrl_subscribe_fh() - Helper function that subscribes a control event. /** v4l2_ctrl_subscribe_fh() - Helper function that subscribes a control event.
* @fh: The file handler that subscribed the control event. * @fh: The file handler that subscribed the control event.
......
...@@ -38,9 +38,18 @@ struct v4l2_kevent { ...@@ -38,9 +38,18 @@ struct v4l2_kevent {
}; };
struct v4l2_subscribed_event { struct v4l2_subscribed_event {
/* list node for the v4l2_fh->subscribed list */
struct list_head list; struct list_head list;
/* event type */
u32 type; u32 type;
/* associated object ID (e.g. control ID) */
u32 id; u32 id;
/* copy of v4l2_event_subscription->flags */
u32 flags;
/* filehandle that subscribed to this event */
struct v4l2_fh *fh;
/* list node that hooks into the object's event list (if there is one) */
struct list_head node;
}; };
int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n); int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment