|
@@ -35,10 +35,6 @@
|
|
|
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);
|