{
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);
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;
}
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)
{
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);
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 */