Commit ede197aa authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] hdpvr: remove hdpvr_fh and just use v4l2_fh

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: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 99c77aa4
...@@ -35,10 +35,6 @@ ...@@ -35,10 +35,6 @@
list_size(&dev->free_buff_list), \ list_size(&dev->free_buff_list), \
list_size(&dev->rec_buff_list)); } list_size(&dev->rec_buff_list)); }
struct hdpvr_fh {
struct hdpvr_device *dev;
};
static uint list_size(struct list_head *list) static uint list_size(struct list_head *list)
{ {
struct list_head *tmp; struct list_head *tmp;
...@@ -358,55 +354,21 @@ static int hdpvr_stop_streaming(struct hdpvr_device *dev) ...@@ -358,55 +354,21 @@ static int hdpvr_stop_streaming(struct hdpvr_device *dev)
* video 4 linux 2 file operations * 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) static int hdpvr_release(struct file *file)
{ {
struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = video_drvdata(file);
struct hdpvr_device *dev = fh->dev;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
mutex_lock(&dev->io_mutex); mutex_lock(&dev->io_mutex);
if (!(--dev->open_count) && dev->status == STATUS_STREAMING) if (file->private_data == dev->owner) {
hdpvr_stop_streaming(dev); hdpvr_stop_streaming(dev);
dev->owner = NULL;
}
mutex_unlock(&dev->io_mutex); mutex_unlock(&dev->io_mutex);
return 0; return v4l2_fh_release(file);
} }
/* /*
...@@ -416,8 +378,7 @@ static int hdpvr_release(struct file *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, static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
loff_t *pos) loff_t *pos)
{ {
struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = video_drvdata(file);
struct hdpvr_device *dev = fh->dev;
struct hdpvr_buffer *buf = NULL; struct hdpvr_buffer *buf = NULL;
struct urb *urb; struct urb *urb;
unsigned int ret = 0; unsigned int ret = 0;
...@@ -440,6 +401,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, ...@@ -440,6 +401,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
mutex_unlock(&dev->io_mutex); mutex_unlock(&dev->io_mutex);
goto err; goto err;
} }
dev->owner = file->private_data;
print_buffer_status(); print_buffer_status();
} }
mutex_unlock(&dev->io_mutex); mutex_unlock(&dev->io_mutex);
...@@ -518,8 +480,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, ...@@ -518,8 +480,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) static unsigned int hdpvr_poll(struct file *filp, poll_table *wait)
{ {
struct hdpvr_buffer *buf = NULL; struct hdpvr_buffer *buf = NULL;
struct hdpvr_fh *fh = filp->private_data; struct hdpvr_device *dev = video_drvdata(filp);
struct hdpvr_device *dev = fh->dev;
unsigned int mask = 0; unsigned int mask = 0;
mutex_lock(&dev->io_mutex); mutex_lock(&dev->io_mutex);
...@@ -534,6 +495,8 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) ...@@ -534,6 +495,8 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait)
v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
"start_streaming failed\n"); "start_streaming failed\n");
dev->status = STATUS_IDLE; dev->status = STATUS_IDLE;
} else {
dev->owner = filp->private_data;
} }
print_buffer_status(); print_buffer_status();
...@@ -555,7 +518,7 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) ...@@ -555,7 +518,7 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait)
static const struct v4l2_file_operations hdpvr_fops = { static const struct v4l2_file_operations hdpvr_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = hdpvr_open, .open = v4l2_fh_open,
.release = hdpvr_release, .release = hdpvr_release,
.read = hdpvr_read, .read = hdpvr_read,
.poll = hdpvr_poll, .poll = hdpvr_poll,
...@@ -584,8 +547,7 @@ static int vidioc_querycap(struct file *file, void *priv, ...@@ -584,8 +547,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_s_std(struct file *file, void *private_data, static int vidioc_s_std(struct file *file, void *private_data,
v4l2_std_id std) v4l2_std_id std)
{ {
struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = video_drvdata(file);
struct hdpvr_device *dev = fh->dev;
u8 std_type = 1; u8 std_type = 1;
if (std & (V4L2_STD_NTSC | V4L2_STD_PAL_60)) if (std & (V4L2_STD_NTSC | V4L2_STD_PAL_60))
...@@ -603,8 +565,7 @@ static const char *iname[] = { ...@@ -603,8 +565,7 @@ static const char *iname[] = {
static int vidioc_enum_input(struct file *file, void *priv, static int vidioc_enum_input(struct file *file, void *priv,
struct v4l2_input *i) struct v4l2_input *i)
{ {
struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = video_drvdata(file);
struct hdpvr_device *dev = fh->dev;
unsigned int n; unsigned int n;
n = i->index; n = i->index;
...@@ -626,8 +587,7 @@ static int vidioc_enum_input(struct file *file, void *priv, ...@@ -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, static int vidioc_s_input(struct file *file, void *private_data,
unsigned int index) unsigned int index)
{ {
struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = video_drvdata(file);
struct hdpvr_device *dev = fh->dev;
int retval; int retval;
if (index >= HDPVR_VIDEO_INPUTS) if (index >= HDPVR_VIDEO_INPUTS)
...@@ -646,8 +606,7 @@ static int vidioc_s_input(struct file *file, void *private_data, ...@@ -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, static int vidioc_g_input(struct file *file, void *private_data,
unsigned int *index) unsigned int *index)
{ {
struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = video_drvdata(file);
struct hdpvr_device *dev = fh->dev;
*index = dev->options.video_input; *index = dev->options.video_input;
return 0; return 0;
...@@ -680,8 +639,7 @@ static int vidioc_enumaudio(struct file *file, void *priv, ...@@ -680,8 +639,7 @@ static int vidioc_enumaudio(struct file *file, void *priv,
static int vidioc_s_audio(struct file *file, void *private_data, static int vidioc_s_audio(struct file *file, void *private_data,
const struct v4l2_audio *audio) const struct v4l2_audio *audio)
{ {
struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = video_drvdata(file);
struct hdpvr_device *dev = fh->dev;
int retval; int retval;
if (audio->index >= HDPVR_AUDIO_INPUTS) if (audio->index >= HDPVR_AUDIO_INPUTS)
...@@ -700,8 +658,7 @@ static int vidioc_s_audio(struct file *file, void *private_data, ...@@ -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, static int vidioc_g_audio(struct file *file, void *private_data,
struct v4l2_audio *audio) struct v4l2_audio *audio)
{ {
struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = video_drvdata(file);
struct hdpvr_device *dev = fh->dev;
audio->index = dev->options.audio_input; audio->index = dev->options.audio_input;
audio->capability = V4L2_AUDCAP_STEREO; audio->capability = V4L2_AUDCAP_STEREO;
...@@ -833,8 +790,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, ...@@ -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, static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = video_drvdata(file);
struct hdpvr_device *dev = fh->dev;
struct hdpvr_video_info *vid_info; struct hdpvr_video_info *vid_info;
if (!dev) if (!dev)
...@@ -860,26 +816,44 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data, ...@@ -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, static int vidioc_encoder_cmd(struct file *filp, void *priv,
struct v4l2_encoder_cmd *a) struct v4l2_encoder_cmd *a)
{ {
struct hdpvr_fh *fh = filp->private_data; struct hdpvr_device *dev = video_drvdata(filp);
struct hdpvr_device *dev = fh->dev; int res = 0;
int res;
mutex_lock(&dev->io_mutex); mutex_lock(&dev->io_mutex);
a->flags = 0;
memset(&a->raw, 0, sizeof(a->raw));
switch (a->cmd) { switch (a->cmd) {
case V4L2_ENC_CMD_START: 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); res = hdpvr_start_streaming(dev);
if (!res)
dev->owner = filp->private_data;
else
dev->status = STATUS_IDLE;
break; break;
case V4L2_ENC_CMD_STOP: 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); res = hdpvr_stop_streaming(dev);
if (!res)
dev->owner = NULL;
break; break;
default: default:
v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
"Unsupported encoder cmd %d\n", a->cmd); "Unsupported encoder cmd %d\n", a->cmd);
res = -EINVAL; res = -EINVAL;
break;
} }
mutex_unlock(&dev->io_mutex); mutex_unlock(&dev->io_mutex);
return res; return res;
} }
...@@ -887,6 +861,7 @@ static int vidioc_encoder_cmd(struct file *filp, void *priv, ...@@ -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, static int vidioc_try_encoder_cmd(struct file *filp, void *priv,
struct v4l2_encoder_cmd *a) struct v4l2_encoder_cmd *a)
{ {
a->flags = 0;
switch (a->cmd) { switch (a->cmd) {
case V4L2_ENC_CMD_START: case V4L2_ENC_CMD_START:
case V4L2_ENC_CMD_STOP: case V4L2_ENC_CMD_STOP:
...@@ -935,8 +910,6 @@ static void hdpvr_device_release(struct video_device *vdev) ...@@ -935,8 +910,6 @@ static void hdpvr_device_release(struct video_device *vdev)
} }
static const struct video_device hdpvr_video_template = { static const struct video_device hdpvr_video_template = {
/* .type = VFL_TYPE_GRABBER, */
/* .type2 = VID_TYPE_CAPTURE | VID_TYPE_MPEG_ENCODER, */
.fops = &hdpvr_fops, .fops = &hdpvr_fops,
.release = hdpvr_device_release, .release = hdpvr_device_release,
.ioctl_ops = &hdpvr_ioctl_ops, .ioctl_ops = &hdpvr_ioctl_ops,
...@@ -1031,9 +1004,9 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, ...@@ -1031,9 +1004,9 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
goto error; goto error;
} }
*(dev->video_dev) = hdpvr_video_template; *dev->video_dev = hdpvr_video_template;
strcpy(dev->video_dev->name, "Hauppauge HD PVR"); 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); video_set_drvdata(dev->video_dev, dev);
res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum); res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum);
......
...@@ -85,8 +85,6 @@ struct hdpvr_device { ...@@ -85,8 +85,6 @@ struct hdpvr_device {
/* holds the current device status */ /* holds the current device status */
__u8 status; __u8 status;
/* count the number of openers */
uint open_count;
/* holds the cureent set options */ /* holds the cureent set options */
struct hdpvr_options options; struct hdpvr_options options;
...@@ -107,6 +105,8 @@ struct hdpvr_device { ...@@ -107,6 +105,8 @@ struct hdpvr_device {
struct workqueue_struct *workqueue; struct workqueue_struct *workqueue;
/**/ /**/
struct work_struct worker; struct work_struct worker;
/* current stream owner */
struct v4l2_fh *owner;
/* I2C adapter */ /* I2C adapter */
struct i2c_adapter i2c_adapter; struct i2c_adapter i2c_adapter;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment