[media] tm6000: add support for control events and prio handling
authorHans Verkuil <hans.verkuil@cisco.com>
Tue, 11 Sep 2012 14:50:37 +0000 (11:50 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 5 Feb 2013 20:31:33 +0000 (18:31 -0200)
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/usb/tm6000/tm6000-video.c
drivers/media/usb/tm6000/tm6000.h

index 4329fbcf2de2c8c3f54c3cfc220c1f3842c7a5ac..25202a71d65eb478bde7b48f35b5b2428d4e5c1e 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/usb.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
 #include <media/tuner.h>
 #include <linux/interrupt.h>
 #include <linux/kthread.h>
@@ -1350,6 +1351,7 @@ static int __tm6000_open(struct file *file)
                return -ENOMEM;
        }
 
+       v4l2_fh_init(&fh->fh, vdev);
        file->private_data = fh;
        fh->dev      = dev;
        fh->radio    = radio;
@@ -1393,6 +1395,7 @@ static int __tm6000_open(struct file *file)
                tm6000_prepare_isoc(dev);
                tm6000_start_thread(dev);
        }
+       v4l2_fh_add(&fh->fh);
 
        return 0;
 }
@@ -1433,29 +1436,35 @@ tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos)
 static unsigned int
 __tm6000_poll(struct file *file, struct poll_table_struct *wait)
 {
+       unsigned long req_events = poll_requested_events(wait);
        struct tm6000_fh        *fh = file->private_data;
        struct tm6000_buffer    *buf;
+       int res = 0;
 
+       if (v4l2_event_pending(&fh->fh))
+               res = POLLPRI;
+       else if (req_events & POLLPRI)
+               poll_wait(file, &fh->fh.wait, wait);
        if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
-               return POLLERR;
+               return res | POLLERR;
 
        if (!!is_res_streaming(fh->dev, fh))
-               return POLLERR;
+               return res | POLLERR;
 
        if (!is_res_read(fh->dev, fh)) {
                /* streaming capture */
                if (list_empty(&fh->vb_vidq.stream))
-                       return POLLERR;
+                       return res | POLLERR;
                buf = list_entry(fh->vb_vidq.stream.next, struct tm6000_buffer, vb.stream);
-       } else {
+       } else if (req_events & (POLLIN | POLLRDNORM)) {
                /* read() capture */
-               return videobuf_poll_stream(file, &fh->vb_vidq, wait);
+               return res | videobuf_poll_stream(file, &fh->vb_vidq, wait);
        }
        poll_wait(file, &buf->vb.done, wait);
        if (buf->vb.state == VIDEOBUF_DONE ||
            buf->vb.state == VIDEOBUF_ERROR)
-               return POLLIN | POLLRDNORM;
-       return 0;
+               return res | POLLIN | POLLRDNORM;
+       return res;
 }
 
 static unsigned int tm6000_poll(struct file *file, struct poll_table_struct *wait)
@@ -1505,7 +1514,8 @@ static int tm6000_release(struct file *file)
                if (!fh->radio)
                        videobuf_mmap_free(&fh->vb_vidq);
        }
-
+       v4l2_fh_del(&fh->fh);
+       v4l2_fh_exit(&fh->fh);
        kfree(fh);
        mutex_unlock(&dev->lock);
 
@@ -1555,6 +1565,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_querybuf          = vidioc_querybuf,
        .vidioc_qbuf              = vidioc_qbuf,
        .vidioc_dqbuf             = vidioc_dqbuf,
+       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device tm6000_template = {
@@ -1579,6 +1591,8 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
        .vidioc_s_tuner         = radio_s_tuner,
        .vidioc_g_frequency     = vidioc_g_frequency,
        .vidioc_s_frequency     = vidioc_s_frequency,
+       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device tm6000_radio_template = {
@@ -1607,6 +1621,7 @@ static struct video_device *vdev_init(struct tm6000_core *dev,
        vfd->release = video_device_release;
        vfd->debug = tm6000_debug;
        vfd->lock = &dev->lock;
+       set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 
        snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
 
index a9ac262fcc9379389dd694eba5b986d16bb10079..08bd0740dd2368ddaaa23dcaea687f8de57e086c 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mutex.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
 
 #include <linux/dvb/frontend.h>
 #include "dvb_demux.h"
@@ -290,6 +291,7 @@ struct tm6000_ops {
 };
 
 struct tm6000_fh {
+       struct v4l2_fh               fh;
        struct tm6000_core           *dev;
        unsigned int                 radio;