aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2011-06-18 06:02:20 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-07-27 16:53:31 -0400
commit2151bdc887acfd6dc2c931b4d3c01f95e30b7df8 (patch)
tree429683c0f6de68971d74fa379cf1dcfe4540c5a3 /drivers
parentf1e393de382af9b9bd2462a42bfa16b8c501d81b (diff)
[media] v4l2-event: add optional merge and replace callbacks
When the event queue for a subscribed event is full, then the oldest event is dropped. It would be nice if the contents of that oldest event could be merged with the next-oldest. That way no information is lost, only intermediate steps are lost. This patch adds optional replace() (called when only one kevent was allocated) and merge() (called when more than one kevent was allocated) callbacks that will be called to do this job. These two callbacks are implemented for the V4L2_EVENT_CTRL event. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/v4l2-event.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c
index 9e325dd3ce27..b1c19fc2f08c 100644
--- a/drivers/media/video/v4l2-event.c
+++ b/drivers/media/video/v4l2-event.c
@@ -113,6 +113,7 @@ static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *e
113{ 113{
114 struct v4l2_subscribed_event *sev; 114 struct v4l2_subscribed_event *sev;
115 struct v4l2_kevent *kev; 115 struct v4l2_kevent *kev;
116 bool copy_payload = true;
116 117
117 /* Are we subscribed? */ 118 /* Are we subscribed? */
118 sev = v4l2_event_subscribed(fh, ev->type, ev->id); 119 sev = v4l2_event_subscribed(fh, ev->type, ev->id);
@@ -130,12 +131,23 @@ static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *e
130 sev->in_use--; 131 sev->in_use--;
131 sev->first = sev_pos(sev, 1); 132 sev->first = sev_pos(sev, 1);
132 fh->navailable--; 133 fh->navailable--;
134 if (sev->elems == 1) {
135 if (sev->replace) {
136 sev->replace(&kev->event, ev);
137 copy_payload = false;
138 }
139 } else if (sev->merge) {
140 struct v4l2_kevent *second_oldest =
141 sev->events + sev_pos(sev, 0);
142 sev->merge(&kev->event, &second_oldest->event);
143 }
133 } 144 }
134 145
135 /* Take one and fill it. */ 146 /* Take one and fill it. */
136 kev = sev->events + sev_pos(sev, sev->in_use); 147 kev = sev->events + sev_pos(sev, sev->in_use);
137 kev->event.type = ev->type; 148 kev->event.type = ev->type;
138 kev->event.u = ev->u; 149 if (copy_payload)
150 kev->event.u = ev->u;
139 kev->event.id = ev->id; 151 kev->event.id = ev->id;
140 kev->event.timestamp = *ts; 152 kev->event.timestamp = *ts;
141 kev->event.sequence = fh->sequence; 153 kev->event.sequence = fh->sequence;
@@ -184,6 +196,19 @@ int v4l2_event_pending(struct v4l2_fh *fh)
184} 196}
185EXPORT_SYMBOL_GPL(v4l2_event_pending); 197EXPORT_SYMBOL_GPL(v4l2_event_pending);
186 198
199static void ctrls_replace(struct v4l2_event *old, const struct v4l2_event *new)
200{
201 u32 old_changes = old->u.ctrl.changes;
202
203 old->u.ctrl = new->u.ctrl;
204 old->u.ctrl.changes |= old_changes;
205}
206
207static void ctrls_merge(const struct v4l2_event *old, struct v4l2_event *new)
208{
209 new->u.ctrl.changes |= old->u.ctrl.changes;
210}
211
187int v4l2_event_subscribe(struct v4l2_fh *fh, 212int v4l2_event_subscribe(struct v4l2_fh *fh,
188 struct v4l2_event_subscription *sub, unsigned elems) 213 struct v4l2_event_subscription *sub, unsigned elems)
189{ 214{
@@ -210,6 +235,10 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
210 sev->flags = sub->flags; 235 sev->flags = sub->flags;
211 sev->fh = fh; 236 sev->fh = fh;
212 sev->elems = elems; 237 sev->elems = elems;
238 if (ctrl) {
239 sev->replace = ctrls_replace;
240 sev->merge = ctrls_merge;
241 }
213 242
214 spin_lock_irqsave(&fh->vdev->fh_lock, flags); 243 spin_lock_irqsave(&fh->vdev->fh_lock, flags);
215 found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); 244 found_ev = v4l2_event_subscribed(fh, sub->type, sub->id);