Skip to contentSkip to conversation

V4L2 file handles and event interface

RFC Superseded Sakari Ailus 1 participant 5 messages Dec 15, 2009 Media (V4L/DVB)

v1 of 8 Superseded Latest is v8 →

lore
Share & tools
lore
#0 lore raw

cover V4L2 file handles and event interface

Hi,

Here's the first version of the V4L2 file handle and event interface patchset. I posted it as RFC since there are a few issues with the contents and I have no assurrances that this even is functional at the moment.

The first patch adds the V4L2 file handle support and the rest are for V4L2 events.

A few notes on the patches:

- I don't like the locking too much. Perhaps the file handle specific lock (events->lock) could be dropped in favour of the lock for v4l2_file_handle in video_device.

- Event queue depth is not controlled at the moment.

- (Un)subscribing all events is not supported.

Comments are very welcome.

Cheers,

Signature · 2 lines
Sakari Ailus
[email protected]
#1 lore raw

RFC 1/4 V4L: File handles

This patch adds a list of v4l2_file_handle structures to every video_device. It allows using file handle related information in V4L2. The event interface is one example of such use.

---
 drivers/media/video/Makefile   |    2 +-
 drivers/media/video/v4l2-dev.c |    7 +++-
 drivers/media/video/v4l2-fh.c  |   95 ++++++++++++++++++++++++++++++++++++++++
 include/media/v4l2-dev.h       |    4 ++
 include/media/v4l2-fh.h        |   45 +++++++++++++++++++
 5 files changed, 151 insertions(+), 2 deletions(-)
 create mode 100644 drivers/media/video/v4l2-fh.c
 create mode 100644 include/media/v4l2-fh.h
drivers/media/video/Makefile +1 -1
index a61e3f3..1947146 100644
@@ -10,7 +10,7 @@ stkwebcam-objs	:=	stk-webcam.o stk-sensor.o
 
 omap2cam-objs	:=	omap24xxcam.o omap24xxcam-dma.o
 
-videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o
+videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o
 
 # V4L2 core modules
 
drivers/media/video/v4l2-dev.c +6 -1
index 7090699..387a302 100644
@@ -283,7 +283,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
 	/* and increase the device refcount */
 	video_get(vdev);
 	mutex_unlock(&videodev_lock);
-	if (vdev->fops->open)
+	ret = v4l2_file_handle_add(vdev, filp);
+	if (!ret && vdev->fops->open)
 		ret = vdev->fops->open(filp);
 
 	/* decrease the refcount in case of an error */
@@ -301,6 +302,8 @@ static int v4l2_release(struct inode *inode, struct file *filp)
 	if (vdev->fops->release)
 		vdev->fops->release(filp);
 
+	v4l2_file_handle_del(vdev, filp);
+
 	/* decrease the refcount unconditionally since the release()
 	   return value is ignored. */
 	video_put(vdev);
@@ -421,6 +424,8 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
 	if (!vdev->release)
 		return -EINVAL;
 
+	v4l2_file_handle_init(vdev);
+
 	/* Part 1: check device type */
 	switch (type) {
 	case VFL_TYPE_GRABBER:
drivers/media/video/v4l2-fh.c new file +95 -0

95 lines not on this page · raw message

include/media/v4l2-dev.h +4 -0
index 2dee938..8eac93d 100644
@@ -16,6 +16,8 @@
 #include <linux/mutex.h>
 #include <linux/videodev2.h>
 
+#include <media/v4l2-fh.h>
+
 #define VIDEO_MAJOR	81
 
 #define VFL_TYPE_GRABBER	0
@@ -77,6 +79,8 @@ struct video_device
 	/* attribute to differentiate multiple indices on one physical device */
 	int index;
 
+	spinlock_t fh_lock;		/* Lock for file handle list */
+	struct list_head fh;		/* File handle list */
 	int debug;			/* Activates debug level*/
 
 	/* Video standard vars */
include/media/v4l2-fh.h new file +45 -0

45 lines not on this page · raw message

Signature · 1 line
1.5.6.5
#2 lore raw

RFC 2/4 V4L: Events: Add new ioctls for events

This patch adds a set of new ioctls to the V4L2 API. The ioctls conform to V4L2 Events RFC version 2.3:

<URL:http://www.spinics.net/lists/linux-media/msg12033.html>

---
 drivers/media/video/v4l2-compat-ioctl32.c |    3 +++
 drivers/media/video/v4l2-ioctl.c          |    3 +++
 include/linux/videodev2.h                 |   24 ++++++++++++++++++++++++
 3 files changed, 30 insertions(+), 0 deletions(-)
drivers/media/video/v4l2-compat-ioctl32.c +3 -0
index 997975d..cba704c 100644
@@ -1077,6 +1077,9 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
 	case VIDIOC_DBG_G_REGISTER:
 	case VIDIOC_DBG_G_CHIP_IDENT:
 	case VIDIOC_S_HW_FREQ_SEEK:
+	case VIDIOC_DQEVENT:
+	case VIDIOC_SUBSCRIBE_EVENT:
+	case VIDIOC_UNSUBSCRIBE_EVENT:
 		ret = do_video_ioctl(file, cmd, arg);
 		break;
 
drivers/media/video/v4l2-ioctl.c +3 -0
index 30cc334..bfc4696 100644
@@ -283,6 +283,9 @@ static const char *v4l2_ioctls[] = {
 
 	[_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
 	[_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)]   = "VIDIOC_S_HW_FREQ_SEEK",
+	[_IOC_NR(VIDIOC_DQEVENT)]	   = "VIDIOC_DQEVENT",
+	[_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)]  = "VIDIOC_SUBSCRIBE_EVENT",
+	[_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
 #endif
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
include/linux/videodev2.h +24 -0
index 54af357..397f8eb 100644
@@ -1536,6 +1536,27 @@ struct v4l2_streamparm {
 };
 
 /*
+ *	E V E N T S
+ */
+
+struct v4l2_event {
+	__u32		count;
+	__u32		type;
+	__u32		sequence;
+	struct timespec	timestamp;
+	__u32		reserved[8];
+	__u8		data[64];
+};
+
+struct v4l2_event_subscription {
+	__u32		type;
+	__u32		reserved[8];
+};
+
+#define V4L2_EVENT_ALL				0
+#define V4L2_EVENT_PRIVATE_START		0x08000000
+
+/*
  *	A D V A N C E D   D E B U G G I N G
  *
  *	NOTE: EXPERIMENTAL API, NEVER RELY ON THIS IN APPLICATIONS!
@@ -1651,6 +1672,9 @@ struct v4l2_dbg_chip_ident {
 #endif
 
 #define VIDIOC_S_HW_FREQ_SEEK	 _IOW('V', 82, struct v4l2_hw_freq_seek)
+#define VIDIOC_DQEVENT		 _IOR('V', 83, struct v4l2_event)
+#define VIDIOC_SUBSCRIBE_EVENT	 _IOW('V', 84, struct v4l2_event_subscription)
+#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 85, struct v4l2_event_subscription)
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/video/v4l2-compat-ioctl32.c as well! */
 
Signature · 1 line
1.5.6.5
#3 lore raw

RFC 3/4 V4L: Events: Support event handling in do_ioctl

Add support for event handling to do_ioctl.

---
 drivers/media/video/v4l2-ioctl.c |   48 ++++++++++++++++++++++++++++++++++++++
 include/media/v4l2-ioctl.h       |    7 +++++
 2 files changed, 55 insertions(+), 0 deletions(-)
drivers/media/video/v4l2-ioctl.c +48 -0
index bfc4696..067ab3a 100644
@@ -1797,7 +1797,55 @@ static long __video_do_ioctl(struct file *file,
 		}
 		break;
 	}
+	case VIDIOC_DQEVENT:
+	{
+		struct v4l2_event *ev = arg;
+
+		if (!ops->vidioc_dqevent)
+			break;
+
+		ret = ops->vidioc_dqevent(file, ev);
+		if (ret < 0) {
+			dbgarg(cmd, "no pending events?");
+			break;
+		}
+		dbgarg(cmd,
+		       "count=%d, type=0x%8.8x, sequence=%d, "
+		       "timestamp=%d.%9.9lu ",
+		       ev->count, ev->type, ev->sequence,
+		       (int)ev->timestamp.tv_sec, ev->timestamp.tv_nsec);
+		break;
+	}
+	case VIDIOC_SUBSCRIBE_EVENT:
+	{
+		struct v4l2_event_subscription *sub = arg;
 
+		if (!ops->vidioc_subscribe_event)
+			break;
+
+		ret = ops->vidioc_subscribe_event(file, sub);
+		if (ret < 0) {
+			dbgarg(cmd, "failed, ret=%ld", ret);
+			break;
+		}
+		dbgarg(cmd, "type=0x%8.8x", sub->type);
+		break;
+	}
+	case VIDIOC_UNSUBSCRIBE_EVENT:
+	{
+		struct v4l2_event_subscription *sub = arg;
+
+		if (!ops->vidioc_unsubscribe_event)
+			break;
+
+		ret = ops->vidioc_unsubscribe_event(file, sub);
+		if (ret < 0) {
+			dbgarg(cmd, "failed, ret=%ld", ret);
+			break;
+		}
+		dbgarg(cmd, "type=0x%8.8x", sub->type);
+		break;
+	}
 	default:
 	{
 		if (!ops->vidioc_default)
include/media/v4l2-ioctl.h +7 -0
index 7a4529d..77a71cc 100644
@@ -239,6 +239,13 @@ struct v4l2_ioctl_ops {
 	int (*vidioc_enum_frameintervals) (struct file *file, void *fh,
 					   struct v4l2_frmivalenum *fival);
 
+	int (*vidioc_dqevent)	       (struct file *file,
+					struct v4l2_event *ev);
+	int (*vidioc_subscribe_event)  (struct file *file,
+					struct v4l2_event_subscription *sub);
+	int (*vidioc_unsubscribe_event) (struct file *file,
+					 struct v4l2_event_subscription *sub);
+
 	/* For other private ioctls */
 	long (*vidioc_default)	       (struct file *file, void *fh,
 					int cmd, void *arg);
Signature · 1 line
1.5.6.5
#4 lore raw

RFC 4/4 V4L: Events: Add backend

Add event handling backend to V4L2. The backend handles event subscription and delivery to file handles. Event subscriptions are based on file handle. Events may be delivered to all subscribed file handles on a device independent of where they originate from.

---
 drivers/media/video/Makefile     |    3 +-
 drivers/media/video/v4l2-event.c |  254 ++++++++++++++++++++++++++++++++++++++
 drivers/media/video/v4l2-fh.c    |    9 ++
 include/media/v4l2-event.h       |   73 +++++++++++
 include/media/v4l2-fh.h          |    3 +
 5 files changed, 341 insertions(+), 1 deletions(-)
 create mode 100644 drivers/media/video/v4l2-event.c
 create mode 100644 include/media/v4l2-event.h
drivers/media/video/Makefile +2 -1
index 1947146..dd6a853 100644
@@ -10,7 +10,8 @@ stkwebcam-objs	:=	stk-webcam.o stk-sensor.o
 
 omap2cam-objs	:=	omap24xxcam.o omap24xxcam-dma.o
 
-videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o
+videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
+			v4l2-event.o
 
 # V4L2 core modules
 
drivers/media/video/v4l2-event.c new file +254 -0

254 lines not on this page · raw message

drivers/media/video/v4l2-fh.c +9 -0
index 52cb3b3..a8d4318 100644
@@ -59,6 +59,7 @@ int v4l2_file_handle_add(struct video_device *vdev, struct file *filp)
 {
 	struct v4l2_file_handle *fh;
 	unsigned long flags;
+	int ret;
 
 	fh = kmalloc(sizeof(*fh), GFP_KERNEL);
 	if (!fh)
@@ -66,6 +67,12 @@ int v4l2_file_handle_add(struct video_device *vdev, struct file *filp)
 
 	fh->filp = filp;
 
+	ret = v4l2_event_init(&fh->events);
+	if (ret) {
+		kfree(fh);
+		return ret;
+	}
+
 	spin_lock_irqsave(&vdev->fh_lock, flags);
 	list_add(&fh->list, &vdev->fh);
 	spin_unlock_irqrestore(&vdev->fh_lock, flags);
@@ -79,6 +86,8 @@ void v4l2_file_handle_del(struct video_device *vdev, struct file *filp)
 	struct v4l2_file_handle *fh = v4l2_file_handle_get(vdev, filp);
 	unsigned long flags;
 
+	v4l2_event_exit(&fh->events);
+
 	spin_lock_irqsave(&vdev->fh_lock, flags);
 	list_del(&fh->list);
 	spin_unlock_irqrestore(&vdev->fh_lock, flags);
include/media/v4l2-event.h new file +73 -0

73 lines not on this page · raw message

include/media/v4l2-fh.h +3 -0
index 5c9d08b..6e92014 100644
@@ -28,9 +28,12 @@
 #include <linux/types.h>
 #include <linux/list.h>
 
+#include <media/v4l2-event.h>
+
 struct v4l2_file_handle {
 	struct list_head	list;
 	struct file		*filp;
+	struct v4l2_events	events;	/* events, pending and subscribed */
 };
 
 struct video_device;
Signature · 1 line
1.5.6.5