[media] hdpvr: remove hdpvr_fh and just use v4l2_fh
authorHans Verkuil <hans.verkuil@cisco.com>
Sat, 6 Apr 2013 09:00:17 +0000 (06:00 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sun, 14 Apr 2013 22:57:32 +0000 (19:57 -0300)
This prepares the driver for priority and control event handling.
This patch also checks for correct streaming ownership and it makes a
small improvement to the encoder_cmd ioctls: always zero 'flags' and
drop the memset of 'raw' as that is already done by the v4l2 core.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/usb/hdpvr/hdpvr-video.c
drivers/media/usb/hdpvr/hdpvr.h

index a890127..4bbcf48 100644 (file)
                         list_size(&dev->free_buff_list),               \
                         list_size(&dev->rec_buff_list)); }
 
-struct hdpvr_fh {
-       struct hdpvr_device     *dev;
-};
-
 static uint list_size(struct list_head *list)
 {
        struct list_head *tmp;
@@ -358,55 +354,21 @@ static int hdpvr_stop_streaming(struct hdpvr_device *dev)
  * video 4 linux 2 file operations
  */
 
-static int hdpvr_open(struct file *file)
-{
-       struct hdpvr_device *dev;
-       struct hdpvr_fh *fh;
-       int retval = -ENOMEM;
-
-       dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file));
-       if (!dev) {
-               pr_err("open failing with with ENODEV\n");
-               retval = -ENODEV;
-               goto err;
-       }
-
-       fh = kzalloc(sizeof(struct hdpvr_fh), GFP_KERNEL);
-       if (!fh) {
-               v4l2_err(&dev->v4l2_dev, "Out of memory\n");
-               goto err;
-       }
-       /* lock the device to allow correctly handling errors
-        * in resumption */
-       mutex_lock(&dev->io_mutex);
-       dev->open_count++;
-       mutex_unlock(&dev->io_mutex);
-
-       fh->dev = dev;
-
-       /* save our object in the file's private structure */
-       file->private_data = fh;
-
-       retval = 0;
-err:
-       return retval;
-}
-
 static int hdpvr_release(struct file *file)
 {
-       struct hdpvr_fh         *fh  = file->private_data;
-       struct hdpvr_device     *dev = fh->dev;
+       struct hdpvr_device *dev = video_drvdata(file);
 
        if (!dev)
                return -ENODEV;
 
        mutex_lock(&dev->io_mutex);
-       if (!(--dev->open_count) && dev->status == STATUS_STREAMING)
+       if (file->private_data == dev->owner) {
                hdpvr_stop_streaming(dev);
-
+               dev->owner = NULL;
+       }
        mutex_unlock(&dev->io_mutex);
 
-       return 0;
+       return v4l2_fh_release(file);
 }
 
 /*
@@ -416,8 +378,7 @@ static int hdpvr_release(struct file *file)
 static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
                          loff_t *pos)
 {
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
+       struct hdpvr_device *dev = video_drvdata(file);
        struct hdpvr_buffer *buf = NULL;
        struct urb *urb;
        unsigned int ret = 0;
@@ -440,6 +401,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
                        mutex_unlock(&dev->io_mutex);
                        goto err;
                }
+               dev->owner = file->private_data;
                print_buffer_status();
        }
        mutex_unlock(&dev->io_mutex);
@@ -518,8 +480,7 @@ err:
 static unsigned int hdpvr_poll(struct file *filp, poll_table *wait)
 {
        struct hdpvr_buffer *buf = NULL;
-       struct hdpvr_fh *fh = filp->private_data;
-       struct hdpvr_device *dev = fh->dev;
+       struct hdpvr_device *dev = video_drvdata(filp);
        unsigned int mask = 0;
 
        mutex_lock(&dev->io_mutex);
@@ -534,6 +495,8 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait)
                        v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
                                 "start_streaming failed\n");
                        dev->status = STATUS_IDLE;
+               } else {
+                       dev->owner = filp->private_data;
                }
 
                print_buffer_status();
@@ -555,7 +518,7 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait)
 
 static const struct v4l2_file_operations hdpvr_fops = {
        .owner          = THIS_MODULE,
-       .open           = hdpvr_open,
+       .open           = v4l2_fh_open,
        .release        = hdpvr_release,
        .read           = hdpvr_read,
        .poll           = hdpvr_poll,
@@ -584,8 +547,7 @@ static int vidioc_querycap(struct file *file, void  *priv,
 static int vidioc_s_std(struct file *file, void *private_data,
                        v4l2_std_id std)
 {
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
+       struct hdpvr_device *dev = video_drvdata(file);
        u8 std_type = 1;
 
        if (std & (V4L2_STD_NTSC | V4L2_STD_PAL_60))
@@ -603,8 +565,7 @@ static const char *iname[] = {
 static int vidioc_enum_input(struct file *file, void *priv,
                                struct v4l2_input *i)
 {
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
+       struct hdpvr_device *dev = video_drvdata(file);
        unsigned int n;
 
        n = i->index;
@@ -626,8 +587,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
 static int vidioc_s_input(struct file *file, void *private_data,
                          unsigned int index)
 {
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
+       struct hdpvr_device *dev = video_drvdata(file);
        int retval;
 
        if (index >= HDPVR_VIDEO_INPUTS)
@@ -646,8 +606,7 @@ static int vidioc_s_input(struct file *file, void *private_data,
 static int vidioc_g_input(struct file *file, void *private_data,
                          unsigned int *index)
 {
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
+       struct hdpvr_device *dev = video_drvdata(file);
 
        *index = dev->options.video_input;
        return 0;
@@ -680,8 +639,7 @@ static int vidioc_enumaudio(struct file *file, void *priv,
 static int vidioc_s_audio(struct file *file, void *private_data,
                          const struct v4l2_audio *audio)
 {
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
+       struct hdpvr_device *dev = video_drvdata(file);
        int retval;
 
        if (audio->index >= HDPVR_AUDIO_INPUTS)
@@ -700,8 +658,7 @@ static int vidioc_s_audio(struct file *file, void *private_data,
 static int vidioc_g_audio(struct file *file, void *private_data,
                          struct v4l2_audio *audio)
 {
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
+       struct hdpvr_device *dev = video_drvdata(file);
 
        audio->index = dev->options.audio_input;
        audio->capability = V4L2_AUDCAP_STEREO;
@@ -833,8 +790,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data,
 static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data,
                                struct v4l2_format *f)
 {
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
+       struct hdpvr_device *dev = video_drvdata(file);
        struct hdpvr_video_info *vid_info;
 
        if (!dev)
@@ -860,26 +816,44 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data,
 static int vidioc_encoder_cmd(struct file *filp, void *priv,
                               struct v4l2_encoder_cmd *a)
 {
-       struct hdpvr_fh *fh = filp->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       int res;
+       struct hdpvr_device *dev = video_drvdata(filp);
+       int res = 0;
 
        mutex_lock(&dev->io_mutex);
+       a->flags = 0;
 
-       memset(&a->raw, 0, sizeof(a->raw));
        switch (a->cmd) {
        case V4L2_ENC_CMD_START:
-               a->flags = 0;
+               if (dev->owner && filp->private_data != dev->owner) {
+                       res = -EBUSY;
+                       break;
+               }
+               if (dev->status == STATUS_STREAMING)
+                       break;
                res = hdpvr_start_streaming(dev);
+               if (!res)
+                       dev->owner = filp->private_data;
+               else
+                       dev->status = STATUS_IDLE;
                break;
        case V4L2_ENC_CMD_STOP:
+               if (dev->owner && filp->private_data != dev->owner) {
+                       res = -EBUSY;
+                       break;
+               }
+               if (dev->status == STATUS_IDLE)
+                       break;
                res = hdpvr_stop_streaming(dev);
+               if (!res)
+                       dev->owner = NULL;
                break;
        default:
                v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
                         "Unsupported encoder cmd %d\n", a->cmd);
                res = -EINVAL;
+               break;
        }
+
        mutex_unlock(&dev->io_mutex);
        return res;
 }
@@ -887,6 +861,7 @@ static int vidioc_encoder_cmd(struct file *filp, void *priv,
 static int vidioc_try_encoder_cmd(struct file *filp, void *priv,
                                        struct v4l2_encoder_cmd *a)
 {
+       a->flags = 0;
        switch (a->cmd) {
        case V4L2_ENC_CMD_START:
        case V4L2_ENC_CMD_STOP:
@@ -935,8 +910,6 @@ static void hdpvr_device_release(struct video_device *vdev)
 }
 
 static const struct video_device hdpvr_video_template = {
-/*     .type                   = VFL_TYPE_GRABBER, */
-/*     .type2                  = VID_TYPE_CAPTURE | VID_TYPE_MPEG_ENCODER, */
        .fops                   = &hdpvr_fops,
        .release                = hdpvr_device_release,
        .ioctl_ops              = &hdpvr_ioctl_ops,
@@ -1031,9 +1004,9 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
                goto error;
        }
 
-       *(dev->video_dev) = hdpvr_video_template;
+       *dev->video_dev = hdpvr_video_template;
        strcpy(dev->video_dev->name, "Hauppauge HD PVR");
-       dev->video_dev->parent = parent;
+       dev->video_dev->v4l2_dev = &dev->v4l2_dev;
        video_set_drvdata(dev->video_dev, dev);
 
        res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum);
index 2a4deab..9450093 100644 (file)
@@ -85,8 +85,6 @@ struct hdpvr_device {
 
        /* holds the current device status */
        __u8                    status;
-       /* count the number of openers */
-       uint                    open_count;
 
        /* holds the cureent set options */
        struct hdpvr_options    options;
@@ -107,6 +105,8 @@ struct hdpvr_device {
        struct workqueue_struct *workqueue;
        /**/
        struct work_struct      worker;
+       /* current stream owner */
+       struct v4l2_fh          *owner;
 
        /* I2C adapter */
        struct i2c_adapter      i2c_adapter;