Drivers that supported events used to be rare, but now that controls can also
raise events this will become much more common since almost all drivers have
controls.
This means that keeping struct v4l2_events as a separate struct make no more
sense. Merging it into struct v4l2_fh simplifies things substantially as it
is now an integral part of the filehandle struct.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
/* If there are subscribed events, then only use the new event
API instead of the old video.h based API. */
/* If there are subscribed events, then only use the new event
API instead of the old video.h based API. */
- if (!list_empty(&id->fh.events->subscribed)) {
- poll_wait(filp, &id->fh.events->wait, wait);
+ if (!list_empty(&id->fh.subscribed)) {
+ poll_wait(filp, &id->fh.wait, wait);
/* Turn off the old-style vsync events */
clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
if (v4l2_event_pending(&id->fh))
/* Turn off the old-style vsync events */
clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
if (v4l2_event_pending(&id->fh))
if (v4l2_event_pending(&id->fh))
res |= POLLPRI;
else
if (v4l2_event_pending(&id->fh))
res |= POLLPRI;
else
- poll_wait(filp, &id->fh.events->wait, wait);
+ poll_wait(filp, &id->fh.wait, wait);
if (s->q_full.length || s->q_io.length)
return res | POLLIN | POLLRDNORM;
if (s->q_full.length || s->q_io.length)
return res | POLLIN | POLLRDNORM;
struct v4l2_ctrl_handler *hdl = fh->ctrl_handler;
int ret = 0;
struct v4l2_ctrl_handler *hdl = fh->ctrl_handler;
int ret = 0;
- if (!fh->events)
- ret = v4l2_event_init(fh);
if (!ret) {
if (hdl->nr_of_refs * 2 > n)
n = hdl->nr_of_refs * 2;
if (!ret) {
if (hdl->nr_of_refs * 2 > n)
n = hdl->nr_of_refs * 2;
static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh);
static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh);
-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)
{
int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n)
{
- struct v4l2_events *events = fh->events;
- if (!events) {
- WARN_ON(1);
- return -ENOMEM;
- }
-
- while (events->nallocated < n) {
+ while (fh->nallocated < n) {
struct v4l2_kevent *kev;
kev = kzalloc(sizeof(*kev), GFP_KERNEL);
struct v4l2_kevent *kev;
kev = kzalloc(sizeof(*kev), GFP_KERNEL);
return -ENOMEM;
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
return -ENOMEM;
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
- list_add_tail(&kev->list, &events->free);
- events->nallocated++;
+ list_add_tail(&kev->list, &fh->free);
+ fh->nallocated++;
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
}
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
}
void v4l2_event_free(struct v4l2_fh *fh)
{
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(&fh->free, struct v4l2_kevent, list);
+ list_kfree(&fh->available, struct v4l2_kevent, list);
v4l2_event_unsubscribe_all(fh);
v4l2_event_unsubscribe_all(fh);
-
- kfree(events);
- fh->events = NULL;
}
EXPORT_SYMBOL_GPL(v4l2_event_free);
static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
{
}
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);
struct v4l2_kevent *kev;
unsigned long flags;
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
- if (list_empty(&events->available)) {
+ if (list_empty(&fh->available)) {
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
return -ENOENT;
}
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
return -ENOENT;
}
- WARN_ON(events->navailable == 0);
+ WARN_ON(fh->navailable == 0);
- kev = list_first_entry(&events->available, struct v4l2_kevent, list);
- list_move(&kev->list, &events->free);
- events->navailable--;
+ kev = list_first_entry(&fh->available, struct v4l2_kevent, list);
+ list_move(&kev->list, &fh->free);
+ fh->navailable--;
- kev->event.pending = events->navailable;
+ kev->event.pending = fh->navailable;
*event = kev->event;
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
*event = kev->event;
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
int nonblocking)
{
int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
int nonblocking)
{
- struct v4l2_events *events = fh->events;
int ret;
if (nonblocking)
int ret;
if (nonblocking)
mutex_unlock(fh->vdev->lock);
do {
mutex_unlock(fh->vdev->lock);
do {
- ret = wait_event_interruptible(events->wait,
- events->navailable != 0);
+ ret = wait_event_interruptible(fh->wait,
+ fh->navailable != 0);
static struct v4l2_subscribed_event *v4l2_event_subscribed(
struct v4l2_fh *fh, u32 type, u32 id)
{
static struct v4l2_subscribed_event *v4l2_event_subscribed(
struct v4l2_fh *fh, u32 type, u32 id)
{
- struct v4l2_events *events = fh->events;
struct v4l2_subscribed_event *sev;
assert_spin_locked(&fh->vdev->fh_lock);
struct v4l2_subscribed_event *sev;
assert_spin_locked(&fh->vdev->fh_lock);
- list_for_each_entry(sev, &events->subscribed, list) {
+ list_for_each_entry(sev, &fh->subscribed, list) {
if (sev->type == type && sev->id == id)
return sev;
}
if (sev->type == type && sev->id == id)
return sev;
}
static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev,
const struct timespec *ts)
{
static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev,
const struct timespec *ts)
{
- struct v4l2_events *events = fh->events;
struct v4l2_subscribed_event *sev;
struct v4l2_kevent *kev;
struct v4l2_subscribed_event *sev;
struct v4l2_kevent *kev;
return;
/* Increase event sequence number on fh. */
return;
/* Increase event sequence number on fh. */
/* Do we have any free events? */
/* Do we have any free events? */
- if (list_empty(&events->free))
+ if (list_empty(&fh->free))
return;
/* Take one and fill it. */
return;
/* Take one and fill it. */
- kev = list_first_entry(&events->free, struct v4l2_kevent, list);
+ kev = list_first_entry(&fh->free, struct v4l2_kevent, list);
kev->event.type = ev->type;
kev->event.u = ev->u;
kev->event.id = ev->id;
kev->event.timestamp = *ts;
kev->event.type = ev->type;
kev->event.u = ev->u;
kev->event.id = ev->id;
kev->event.timestamp = *ts;
- kev->event.sequence = events->sequence;
- list_move_tail(&kev->list, &events->available);
+ kev->event.sequence = fh->sequence;
+ list_move_tail(&kev->list, &fh->available);
- wake_up_all(&events->wait);
+ wake_up_all(&fh->wait);
}
void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev)
}
void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev)
int v4l2_event_pending(struct v4l2_fh *fh)
{
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)
{
}
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, *found_ev;
struct v4l2_ctrl *ctrl = NULL;
struct v4l2_ctrl_fh *ctrl_fh = NULL;
unsigned long flags;
struct v4l2_subscribed_event *sev, *found_ev;
struct v4l2_ctrl *ctrl = NULL;
struct v4l2_ctrl_fh *ctrl_fh = NULL;
unsigned long flags;
- if (fh->events == NULL) {
- WARN_ON(1);
- return -ENOMEM;
- }
-
if (sub->type == V4L2_EVENT_CTRL) {
ctrl = v4l2_ctrl_find(fh->ctrl_handler, sub->id);
if (ctrl == NULL)
if (sub->type == V4L2_EVENT_CTRL) {
ctrl = v4l2_ctrl_find(fh->ctrl_handler, sub->id);
if (ctrl == NULL)
sev->type = sub->type;
sev->id = sub->id;
sev->type = sub->type;
sev->id = sub->id;
- list_add(&sev->list, &events->subscribed);
+ list_add(&sev->list, &fh->subscribed);
static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
{
static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
{
- struct v4l2_events *events = fh->events;
struct v4l2_event_subscription sub;
struct v4l2_subscribed_event *sev;
unsigned long flags;
struct v4l2_event_subscription sub;
struct v4l2_subscribed_event *sev;
unsigned long flags;
sev = NULL;
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
sev = NULL;
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
- if (!list_empty(&events->subscribed)) {
- sev = list_first_entry(&events->subscribed,
+ if (!list_empty(&fh->subscribed)) {
+ sev = list_first_entry(&fh->subscribed,
struct v4l2_subscribed_event, list);
sub.type = sev->type;
sub.id = sev->id;
struct v4l2_subscribed_event, list);
sub.type = sev->type;
sub.id = sev->id;
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
-int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
+void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
{
fh->vdev = vdev;
/* Inherit from video_device. May be overridden by the driver. */
{
fh->vdev = vdev;
/* Inherit from video_device. May be overridden by the driver. */
set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags);
fh->prio = V4L2_PRIORITY_UNSET;
set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags);
fh->prio = V4L2_PRIORITY_UNSET;
- /*
- * fh->events only needs to be initialized if the driver
- * supports the VIDIOC_SUBSCRIBE_EVENT ioctl.
- */
- if (vdev->ioctl_ops && vdev->ioctl_ops->vidioc_subscribe_event)
- return v4l2_event_init(fh);
-
- fh->events = NULL;
-
- return 0;
+ init_waitqueue_head(&fh->wait);
+ INIT_LIST_HEAD(&fh->free);
+ INIT_LIST_HEAD(&fh->available);
+ INIT_LIST_HEAD(&fh->subscribed);
+ fh->sequence = -1;
}
EXPORT_SYMBOL_GPL(v4l2_fh_init);
}
EXPORT_SYMBOL_GPL(v4l2_fh_init);
- ret = v4l2_fh_init(&subdev_fh->vfh, vdev);
- if (ret)
- goto err;
+ v4l2_fh_init(&subdev_fh->vfh, vdev);
if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
- ret = v4l2_event_init(&subdev_fh->vfh);
- if (ret)
- goto err;
-
ret = v4l2_event_alloc(&subdev_fh->vfh, sd->nevents);
if (ret)
goto err;
ret = v4l2_event_alloc(&subdev_fh->vfh, sd->nevents);
if (ret)
goto err;
if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
return POLLERR;
if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
return POLLERR;
- poll_wait(file, &fh->events->wait, wait);
+ poll_wait(file, &fh->wait, wait);
if (v4l2_event_pending(fh))
return POLLPRI;
if (v4l2_event_pending(fh))
return POLLPRI;
if (v4l2_event_pending(fh))
res |= POLLPRI;
else
if (v4l2_event_pending(fh))
res |= POLLPRI;
else
- poll_wait(file, &fh->events->wait, wait);
+ poll_wait(file, &fh->wait, wait);
if (handle == NULL)
return -ENOMEM;
if (handle == NULL)
return -ENOMEM;
- ret = v4l2_fh_init(&handle->vfh, vdev);
- if (ret < 0)
- goto error;
-
- ret = v4l2_event_init(&handle->vfh);
- if (ret < 0)
- goto error;
+ v4l2_fh_init(&handle->vfh, vdev);
ret = v4l2_event_alloc(&handle->vfh, 8);
if (ret < 0)
ret = v4l2_event_alloc(&handle->vfh, 8);
if (ret < 0)
struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
unsigned int mask = 0;
struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
unsigned int mask = 0;
- poll_wait(file, &handle->vfh.events->wait, wait);
+ poll_wait(file, &handle->vfh.wait, wait);
if (v4l2_event_pending(&handle->vfh))
mask |= POLLPRI;
if (v4l2_event_pending(&handle->vfh))
mask |= POLLPRI;
-struct v4l2_events {
- wait_queue_head_t wait;
- struct list_head subscribed; /* Subscribed events */
- struct list_head free; /* Events ready for use */
- struct list_head available; /* Dequeueable event */
- unsigned int navailable;
- unsigned int nallocated; /* Number of allocated events */
- u32 sequence;
-};
-
-int v4l2_event_init(struct v4l2_fh *fh);
int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n);
void v4l2_event_free(struct v4l2_fh *fh);
int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n);
void v4l2_event_free(struct v4l2_fh *fh);
int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
#include <linux/list.h>
struct video_device;
#include <linux/list.h>
struct video_device;
struct v4l2_ctrl_handler;
struct v4l2_fh {
struct list_head list;
struct video_device *vdev;
struct v4l2_ctrl_handler;
struct v4l2_fh {
struct list_head list;
struct video_device *vdev;
- struct v4l2_events *events; /* events, pending and subscribed */
struct v4l2_ctrl_handler *ctrl_handler;
enum v4l2_priority prio;
struct v4l2_ctrl_handler *ctrl_handler;
enum v4l2_priority prio;
+
+ /* Events */
+ wait_queue_head_t wait;
+ struct list_head subscribed; /* Subscribed events */
+ struct list_head free; /* Events ready for use */
+ struct list_head available; /* Dequeueable event */
+ unsigned int navailable;
+ unsigned int nallocated; /* Number of allocated events */
+ u32 sequence;
* from driver's v4l2_file_operations->open() handler if the driver
* uses v4l2_fh.
*/
* from driver's v4l2_file_operations->open() handler if the driver
* uses v4l2_fh.
*/
-int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev);
+void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev);
/*
* Add the fh to the list of file handles on a video_device. The file
* handle must be initialised first.
/*
* Add the fh to the list of file handles on a video_device. The file
* handle must be initialised first.