diff options
Diffstat (limited to 'drivers/media/video/v4l2-event.c')
| -rw-r--r-- | drivers/media/video/v4l2-event.c | 299 |
1 files changed, 0 insertions, 299 deletions
diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c deleted file mode 100644 index 69fd343d477..00000000000 --- a/drivers/media/video/v4l2-event.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * v4l2-event.c - * - * V4L2 events. - * - * Copyright (C) 2009--2010 Nokia Corporation. - * - * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include <media/v4l2-dev.h> -#include <media/v4l2-fh.h> -#include <media/v4l2-event.h> - -#include <linux/sched.h> -#include <linux/slab.h> - -int v4l2_event_init(struct v4l2_fh *fh) -{ - fh->events = kzalloc(sizeof(*fh->events), GFP_KERNEL); - if (fh->events == NULL) - return -ENOMEM; - - init_waitqueue_head(&fh->events->wait); - - INIT_LIST_HEAD(&fh->events->free); - INIT_LIST_HEAD(&fh->events->available); - INIT_LIST_HEAD(&fh->events->subscribed); - - fh->events->sequence = -1; - - return 0; -} -EXPORT_SYMBOL_GPL(v4l2_event_init); - -int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n) -{ - struct v4l2_events *events = fh->events; - unsigned long flags; - - if (!events) { - WARN_ON(1); - return -ENOMEM; - } - - while (events->nallocated < n) { - struct v4l2_kevent *kev; - - kev = kzalloc(sizeof(*kev), GFP_KERNEL); - if (kev == NULL) - return -ENOMEM; - - spin_lock_irqsave(&fh->vdev->fh_lock, flags); - list_add_tail(&kev->list, &events->free); - events->nallocated++; - spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); - } - - return 0; -} -EXPORT_SYMBOL_GPL(v4l2_event_alloc); - -#define list_kfree(list, type, member) \ - while (!list_empty(list)) { \ - type *hi; \ - hi = list_first_entry(list, type, member); \ - list_del(&hi->member); \ - kfree(hi); \ - } - -void v4l2_event_free(struct v4l2_fh *fh) -{ - struct v4l2_events *events = fh->events; - - if (!events) - return; - - list_kfree(&events->free, struct v4l2_kevent, list); - list_kfree(&events->available, struct v4l2_kevent, list); - list_kfree(&events->subscribed, struct v4l2_subscribed_event, list); - - kfree(events); - fh->events = NULL; -} -EXPORT_SYMBOL_GPL(v4l2_event_free); - -static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event) -{ - struct v4l2_events *events = fh->events; - struct v4l2_kevent *kev; - unsigned long flags; - - spin_lock_irqsave(&fh->vdev->fh_lock, flags); - - if (list_empty(&events->available)) { - spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); - return -ENOENT; - } - - WARN_ON(events->navailable == 0); - - kev = list_first_entry(&events->available, struct v4l2_kevent, list); - list_move(&kev->list, &events->free); - events->navailable--; - - kev->event.pending = events->navailable; - *event = kev->event; - - spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); - - return 0; -} - -int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event, - int nonblocking) -{ - struct v4l2_events *events = fh->events; - int ret; - - if (nonblocking) - return __v4l2_event_dequeue(fh, event); - - /* Release the vdev lock while waiting */ - if (fh->vdev->lock) - mutex_unlock(fh->vdev->lock); - - do { - ret = wait_event_interruptible(events->wait, - events->navailable != 0); - if (ret < 0) - break; - - ret = __v4l2_event_dequeue(fh, event); - } while (ret == -ENOENT); - - if (fh->vdev->lock) - mutex_lock(fh->vdev->lock); - - return ret; -} -EXPORT_SYMBOL_GPL(v4l2_event_dequeue); - -/* Caller must hold fh->event->lock! */ -static struct v4l2_subscribed_event *v4l2_event_subscribed( - struct v4l2_fh *fh, u32 type) -{ - struct v4l2_events *events = fh->events; - struct v4l2_subscribed_event *sev; - - assert_spin_locked(&fh->vdev->fh_lock); - - list_for_each_entry(sev, &events->subscribed, list) { - if (sev->type == type) - return sev; - } - - return NULL; -} - -void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev) -{ - struct v4l2_fh *fh; - unsigned long flags; - struct timespec timestamp; - - ktime_get_ts(×tamp); - - spin_lock_irqsave(&vdev->fh_lock, flags); - - list_for_each_entry(fh, &vdev->fh_list, list) { - struct v4l2_events *events = fh->events; - struct v4l2_kevent *kev; - - /* Are we subscribed? */ - if (!v4l2_event_subscribed(fh, ev->type)) - continue; - - /* Increase event sequence number on fh. */ - events->sequence++; - - /* Do we have any free events? */ - if (list_empty(&events->free)) - continue; - - /* Take one and fill it. */ - kev = list_first_entry(&events->free, struct v4l2_kevent, list); - kev->event.type = ev->type; - kev->event.u = ev->u; - kev->event.timestamp = timestamp; - kev->event.sequence = events->sequence; - list_move_tail(&kev->list, &events->available); - - events->navailable++; - - wake_up_all(&events->wait); - } - - spin_unlock_irqrestore(&vdev->fh_lock, flags); -} -EXPORT_SYMBOL_GPL(v4l2_event_queue); - -int v4l2_event_pending(struct v4l2_fh *fh) -{ - return fh->events->navailable; -} -EXPORT_SYMBOL_GPL(v4l2_event_pending); - -int v4l2_event_subscribe(struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) -{ - struct v4l2_events *events = fh->events; - struct v4l2_subscribed_event *sev; - unsigned long flags; - - if (fh->events == NULL) { - WARN_ON(1); - return -ENOMEM; - } - - sev = kmalloc(sizeof(*sev), GFP_KERNEL); - if (!sev) - return -ENOMEM; - - spin_lock_irqsave(&fh->vdev->fh_lock, flags); - - if (v4l2_event_subscribed(fh, sub->type) == NULL) { - INIT_LIST_HEAD(&sev->list); - sev->type = sub->type; - - list_add(&sev->list, &events->subscribed); - sev = NULL; - } - - spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); - - kfree(sev); - - return 0; -} -EXPORT_SYMBOL_GPL(v4l2_event_subscribe); - -static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh) -{ - struct v4l2_events *events = fh->events; - struct v4l2_subscribed_event *sev; - unsigned long flags; - - do { - sev = NULL; - - spin_lock_irqsave(&fh->vdev->fh_lock, flags); - if (!list_empty(&events->subscribed)) { - sev = list_first_entry(&events->subscribed, - struct v4l2_subscribed_event, list); - list_del(&sev->list); - } - spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); - kfree(sev); - } while (sev); -} - -int v4l2_event_unsubscribe(struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) -{ - struct v4l2_subscribed_event *sev; - unsigned long flags; - - if (sub->type == V4L2_EVENT_ALL) { - v4l2_event_unsubscribe_all(fh); - return 0; - } - - spin_lock_irqsave(&fh->vdev->fh_lock, flags); - - sev = v4l2_event_subscribed(fh, sub->type); - if (sev != NULL) - list_del(&sev->list); - - spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); - - kfree(sev); - - return 0; -} -EXPORT_SYMBOL_GPL(v4l2_event_unsubscribe); |
