aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSakari Ailus <sakari.ailus@iki.fi>2010-03-03 10:49:38 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-21 19:32:42 -0400
commit02adb1cc765b8c29dc83c6602bda19003cce62f1 (patch)
tree067fd5a73251f6dc33567926c409a0b1070710ab
parentea8aa4349e11c62242a8908fc172de27d7a151d7 (diff)
[media] v4l: subdev: Events support
Provide v4l2_subdevs with v4l2_event support. Subdev drivers only need very little to support events. Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi> Signed-off-by: David Cohen <dacohen@gmail.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--Documentation/video4linux/v4l2-framework.txt18
-rw-r--r--drivers/media/video/v4l2-subdev.c78
-rw-r--r--include/media/v4l2-subdev.h10
3 files changed, 105 insertions, 1 deletions
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index 1feecfc59c3d..eb8479565dc4 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -350,6 +350,24 @@ VIDIOC_TRY_EXT_CTRLS
350 controls can be also be accessed through one (or several) V4L2 device 350 controls can be also be accessed through one (or several) V4L2 device
351 nodes. 351 nodes.
352 352
353VIDIOC_DQEVENT
354VIDIOC_SUBSCRIBE_EVENT
355VIDIOC_UNSUBSCRIBE_EVENT
356
357 The events ioctls are identical to the ones defined in V4L2. They
358 behave identically, with the only exception that they deal only with
359 events generated by the sub-device. Depending on the driver, those
360 events can also be reported by one (or several) V4L2 device nodes.
361
362 Sub-device drivers that want to use events need to set the
363 V4L2_SUBDEV_USES_EVENTS v4l2_subdev::flags and initialize
364 v4l2_subdev::nevents to events queue depth before registering the
365 sub-device. After registration events can be queued as usual on the
366 v4l2_subdev::devnode device node.
367
368 To properly support events, the poll() file operation is also
369 implemented.
370
353 371
354I2C sub-device drivers 372I2C sub-device drivers
355---------------------- 373----------------------
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
index da10430051c0..0c67f5a278fb 100644
--- a/drivers/media/video/v4l2-subdev.c
+++ b/drivers/media/video/v4l2-subdev.c
@@ -20,21 +20,66 @@
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */ 21 */
22 22
23#include <linux/types.h>
24#include <linux/ioctl.h> 23#include <linux/ioctl.h>
24#include <linux/slab.h>
25#include <linux/types.h>
25#include <linux/videodev2.h> 26#include <linux/videodev2.h>
26 27
27#include <media/v4l2-ctrls.h> 28#include <media/v4l2-ctrls.h>
28#include <media/v4l2-device.h> 29#include <media/v4l2-device.h>
29#include <media/v4l2-ioctl.h> 30#include <media/v4l2-ioctl.h>
31#include <media/v4l2-fh.h>
32#include <media/v4l2-event.h>
30 33
31static int subdev_open(struct file *file) 34static int subdev_open(struct file *file)
32{ 35{
36 struct video_device *vdev = video_devdata(file);
37 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
38 struct v4l2_fh *vfh;
39 int ret;
40
41 if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
42 vfh = kzalloc(sizeof(*vfh), GFP_KERNEL);
43 if (vfh == NULL)
44 return -ENOMEM;
45
46 ret = v4l2_fh_init(vfh, vdev);
47 if (ret)
48 goto err;
49
50 ret = v4l2_event_init(vfh);
51 if (ret)
52 goto err;
53
54 ret = v4l2_event_alloc(vfh, sd->nevents);
55 if (ret)
56 goto err;
57
58 v4l2_fh_add(vfh);
59 file->private_data = vfh;
60 }
61
33 return 0; 62 return 0;
63
64err:
65 if (vfh != NULL) {
66 v4l2_fh_exit(vfh);
67 kfree(vfh);
68 }
69
70 return ret;
34} 71}
35 72
36static int subdev_close(struct file *file) 73static int subdev_close(struct file *file)
37{ 74{
75 struct v4l2_fh *vfh = file->private_data;
76
77 if (vfh != NULL) {
78 v4l2_fh_del(vfh);
79 v4l2_fh_exit(vfh);
80 kfree(vfh);
81 }
82
38 return 0; 83 return 0;
39} 84}
40 85
@@ -42,6 +87,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
42{ 87{
43 struct video_device *vdev = video_devdata(file); 88 struct video_device *vdev = video_devdata(file);
44 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); 89 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
90 struct v4l2_fh *fh = file->private_data;
45 91
46 switch (cmd) { 92 switch (cmd) {
47 case VIDIOC_QUERYCTRL: 93 case VIDIOC_QUERYCTRL:
@@ -65,6 +111,18 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
65 case VIDIOC_TRY_EXT_CTRLS: 111 case VIDIOC_TRY_EXT_CTRLS:
66 return v4l2_subdev_try_ext_ctrls(sd, arg); 112 return v4l2_subdev_try_ext_ctrls(sd, arg);
67 113
114 case VIDIOC_DQEVENT:
115 if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
116 return -ENOIOCTLCMD;
117
118 return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK);
119
120 case VIDIOC_SUBSCRIBE_EVENT:
121 return v4l2_subdev_call(sd, core, subscribe_event, fh, arg);
122
123 case VIDIOC_UNSUBSCRIBE_EVENT:
124 return v4l2_subdev_call(sd, core, unsubscribe_event, fh, arg);
125
68 default: 126 default:
69 return -ENOIOCTLCMD; 127 return -ENOIOCTLCMD;
70 } 128 }
@@ -78,11 +136,29 @@ static long subdev_ioctl(struct file *file, unsigned int cmd,
78 return video_usercopy(file, cmd, arg, subdev_do_ioctl); 136 return video_usercopy(file, cmd, arg, subdev_do_ioctl);
79} 137}
80 138
139static unsigned int subdev_poll(struct file *file, poll_table *wait)
140{
141 struct video_device *vdev = video_devdata(file);
142 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
143 struct v4l2_fh *fh = file->private_data;
144
145 if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
146 return POLLERR;
147
148 poll_wait(file, &fh->events->wait, wait);
149
150 if (v4l2_event_pending(fh))
151 return POLLPRI;
152
153 return 0;
154}
155
81const struct v4l2_file_operations v4l2_subdev_fops = { 156const struct v4l2_file_operations v4l2_subdev_fops = {
82 .owner = THIS_MODULE, 157 .owner = THIS_MODULE,
83 .open = subdev_open, 158 .open = subdev_open,
84 .unlocked_ioctl = subdev_ioctl, 159 .unlocked_ioctl = subdev_ioctl,
85 .release = subdev_close, 160 .release = subdev_close,
161 .poll = subdev_poll,
86}; 162};
87 163
88void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) 164void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 3276065022ef..0f9937be53d2 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -37,6 +37,8 @@
37 37
38struct v4l2_device; 38struct v4l2_device;
39struct v4l2_ctrl_handler; 39struct v4l2_ctrl_handler;
40struct v4l2_event_subscription;
41struct v4l2_fh;
40struct v4l2_subdev; 42struct v4l2_subdev;
41struct tuner_setup; 43struct tuner_setup;
42 44
@@ -161,6 +163,10 @@ struct v4l2_subdev_core_ops {
161 int (*s_power)(struct v4l2_subdev *sd, int on); 163 int (*s_power)(struct v4l2_subdev *sd, int on);
162 int (*interrupt_service_routine)(struct v4l2_subdev *sd, 164 int (*interrupt_service_routine)(struct v4l2_subdev *sd,
163 u32 status, bool *handled); 165 u32 status, bool *handled);
166 int (*subscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
167 struct v4l2_event_subscription *sub);
168 int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
169 struct v4l2_event_subscription *sub);
164}; 170};
165 171
166/* s_mode: switch the tuner to a specific tuner mode. Replacement of s_radio. 172/* s_mode: switch the tuner to a specific tuner mode. Replacement of s_radio.
@@ -437,6 +443,8 @@ struct v4l2_subdev_internal_ops {
437#define V4L2_SUBDEV_FL_IS_SPI (1U << 1) 443#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
438/* Set this flag if this subdev needs a device node. */ 444/* Set this flag if this subdev needs a device node. */
439#define V4L2_SUBDEV_FL_HAS_DEVNODE (1U << 2) 445#define V4L2_SUBDEV_FL_HAS_DEVNODE (1U << 2)
446/* Set this flag if this subdev generates events. */
447#define V4L2_SUBDEV_FL_HAS_EVENTS (1U << 3)
440 448
441/* Each instance of a subdev driver should create this struct, either 449/* Each instance of a subdev driver should create this struct, either
442 stand-alone or embedded in a larger struct. 450 stand-alone or embedded in a larger struct.
@@ -460,6 +468,8 @@ struct v4l2_subdev {
460 void *host_priv; 468 void *host_priv;
461 /* subdev device node */ 469 /* subdev device node */
462 struct video_device devnode; 470 struct video_device devnode;
471 /* number of events to be allocated on open */
472 unsigned int nevents;
463}; 473};
464 474
465#define vdev_to_v4l2_subdev(vdev) \ 475#define vdev_to_v4l2_subdev(vdev) \