From 3cc506274a2f7c27fbd6a51d1177ea55bcccd980 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 18 Jun 2011 07:02:20 -0300 Subject: [PATCH] --- yaml --- r: 261403 b: refs/heads/master c: 2151bdc887acfd6dc2c931b4d3c01f95e30b7df8 h: refs/heads/master i: 261401: dd821b849c10f34742e06f6878b1e61a418da68f 261399: 235d8efe24398566d875b6412a11c78e1f281e0d v: v3 --- [refs] | 2 +- trunk/drivers/media/video/v4l2-event.c | 31 +++++++++++++++++++++++++- trunk/include/media/v4l2-event.h | 6 +++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 06e9c2e9ec84..7e581453b1bf 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f1e393de382af9b9bd2462a42bfa16b8c501d81b +refs/heads/master: 2151bdc887acfd6dc2c931b4d3c01f95e30b7df8 diff --git a/trunk/drivers/media/video/v4l2-event.c b/trunk/drivers/media/video/v4l2-event.c index 9e325dd3ce27..b1c19fc2f08c 100644 --- a/trunk/drivers/media/video/v4l2-event.c +++ b/trunk/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 { struct v4l2_subscribed_event *sev; struct v4l2_kevent *kev; + bool copy_payload = true; /* Are we subscribed? */ 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 sev->in_use--; sev->first = sev_pos(sev, 1); fh->navailable--; + if (sev->elems == 1) { + if (sev->replace) { + sev->replace(&kev->event, ev); + copy_payload = false; + } + } else if (sev->merge) { + struct v4l2_kevent *second_oldest = + sev->events + sev_pos(sev, 0); + sev->merge(&kev->event, &second_oldest->event); + } } /* Take one and fill it. */ kev = sev->events + sev_pos(sev, sev->in_use); kev->event.type = ev->type; - kev->event.u = ev->u; + if (copy_payload) + kev->event.u = ev->u; kev->event.id = ev->id; kev->event.timestamp = *ts; kev->event.sequence = fh->sequence; @@ -184,6 +196,19 @@ 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; +} + int v4l2_event_subscribe(struct v4l2_fh *fh, struct v4l2_event_subscription *sub, unsigned elems) { @@ -210,6 +235,10 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, sev->flags = sub->flags; sev->fh = fh; sev->elems = elems; + if (ctrl) { + sev->replace = ctrls_replace; + sev->merge = ctrls_merge; + } spin_lock_irqsave(&fh->vdev->fh_lock, flags); found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); diff --git a/trunk/include/media/v4l2-event.h b/trunk/include/media/v4l2-event.h index 8d681e5ca552..6da793fa4d34 100644 --- a/trunk/include/media/v4l2-event.h +++ b/trunk/include/media/v4l2-event.h @@ -55,6 +55,12 @@ struct v4l2_subscribed_event { struct v4l2_fh *fh; /* list node that hooks into the object's event list (if there is one) */ struct list_head node; + /* Optional callback that can replace event 'old' with event 'new'. */ + void (*replace)(struct v4l2_event *old, + const struct v4l2_event *new); + /* Optional callback that can merge event 'old' into event 'new'. */ + void (*merge)(const struct v4l2_event *old, + struct v4l2_event *new); /* the number of elements in the events array */ unsigned elems; /* the index of the events containing the oldest available event */