V4L/DVB (10645): vivi: introduce v4l2_device and do several cleanups

- add v4l2_device
- remove BKL
- make the debug parameter settable on the fly
- set bus_info in querycap

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Hans Verkuil 2009-02-14 13:23:12 -03:00 committed by Mauro Carvalho Chehab
parent b016760054
commit 5ab6c9af37

View File

@ -33,12 +33,13 @@
#include <linux/videodev.h>
#endif
#include <linux/interrupt.h>
#include <media/videobuf-vmalloc.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <linux/kthread.h>
#include <linux/highmem.h>
#include <linux/freezer.h>
#include <media/videobuf-vmalloc.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include "font.h"
#define VIVI_MODULE_NAME "vivi"
@ -47,18 +48,32 @@
#define WAKE_DENOMINATOR 1001
#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
#include "font.h"
#define VIVI_MAJOR_VERSION 0
#define VIVI_MINOR_VERSION 5
#define VIVI_MINOR_VERSION 6
#define VIVI_RELEASE 0
#define VIVI_VERSION \
KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
/* Declare static vars that will be used as parameters */
static unsigned int vid_limit = 16; /* Video memory limit, in Mb */
static int video_nr = -1; /* /dev/videoN, -1 for autodetect */
static int n_devs = 1; /* Number of virtual devices */
MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
MODULE_LICENSE("Dual BSD/GPL");
static unsigned video_nr = -1;
module_param(video_nr, uint, 0644);
MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
static unsigned n_devs = 1;
module_param(n_devs, uint, 0644);
MODULE_PARM_DESC(n_devs, "number of video devices to create");
static unsigned debug;
module_param(debug, uint, 0644);
MODULE_PARM_DESC(debug, "activates debug info");
static unsigned int vid_limit = 16;
module_param(vid_limit, uint, 0644);
MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
/* supported controls */
static struct v4l2_queryctrl vivi_qctrl[] = {
@ -112,11 +127,8 @@ static struct v4l2_queryctrl vivi_qctrl[] = {
static int qctl_regs[ARRAY_SIZE(vivi_qctrl)];
#define dprintk(dev, level, fmt, arg...) \
do { \
if (dev->vfd->debug >= (level)) \
printk(KERN_DEBUG "vivi: " fmt , ## arg); \
} while (0)
#define dprintk(dev, level, fmt, arg...) \
v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
/* ------------------------------------------------------------------
Basic structures
@ -206,6 +218,7 @@ static LIST_HEAD(vivi_devlist);
struct vivi_dev {
struct list_head vivi_devlist;
struct v4l2_device v4l2_dev;
spinlock_t slock;
struct mutex mutex;
@ -656,7 +669,7 @@ static int vivi_start_thread(struct vivi_fh *fh)
dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
if (IS_ERR(dma_q->kthread)) {
printk(KERN_ERR "vivi: kernel_thread() failed\n");
v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
return PTR_ERR(dma_q->kthread);
}
/* Wakes thread */
@ -799,8 +812,12 @@ static struct videobuf_queue_ops vivi_video_qops = {
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
struct vivi_fh *fh = priv;
struct vivi_dev *dev = fh->dev;
strcpy(cap->driver, "vivi");
strcpy(cap->card, "vivi");
strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
cap->version = VIVI_VERSION;
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_STREAMING |
@ -1124,32 +1141,21 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
static int vivi_open(struct file *file)
{
int minor = video_devdata(file)->minor;
struct vivi_dev *dev;
struct vivi_dev *dev = video_drvdata(file);
struct vivi_fh *fh = NULL;
int i;
int retval = 0;
printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
lock_kernel();
list_for_each_entry(dev, &vivi_devlist, vivi_devlist)
if (dev->vfd->minor == minor)
goto found;
unlock_kernel();
return -ENODEV;
found:
mutex_lock(&dev->mutex);
dev->users++;
if (dev->users > 1) {
dev->users--;
retval = -EBUSY;
goto unlock;
mutex_unlock(&dev->mutex);
return -EBUSY;
}
dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor,
dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num,
v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
/* allocate + initialize per filehandle data */
@ -1157,14 +1163,11 @@ found:
if (NULL == fh) {
dev->users--;
retval = -ENOMEM;
goto unlock;
}
unlock:
mutex_unlock(&dev->mutex);
if (retval) {
unlock_kernel();
if (retval)
return retval;
}
file->private_data = fh;
fh->dev = dev;
@ -1193,7 +1196,6 @@ unlock:
sizeof(struct vivi_buffer), fh);
vivi_start_thread(fh);
unlock_kernel();
return 0;
}
@ -1249,32 +1251,6 @@ static int vivi_close(struct file *file)
return 0;
}
static int vivi_release(void)
{
struct vivi_dev *dev;
struct list_head *list;
while (!list_empty(&vivi_devlist)) {
list = vivi_devlist.next;
list_del(list);
dev = list_entry(list, struct vivi_dev, vivi_devlist);
if (-1 != dev->vfd->minor) {
printk(KERN_INFO "%s: unregistering /dev/video%d\n",
VIVI_MODULE_NAME, dev->vfd->num);
video_unregister_device(dev->vfd);
} else {
printk(KERN_INFO "%s: releasing /dev/video%d\n",
VIVI_MODULE_NAME, dev->vfd->num);
video_device_release(dev->vfd);
}
kfree(dev);
}
return 0;
}
static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
{
struct vivi_fh *fh = file->private_data;
@ -1337,10 +1313,91 @@ static struct video_device vivi_template = {
.tvnorms = V4L2_STD_525_60,
.current_norm = V4L2_STD_NTSC_M,
};
/* -----------------------------------------------------------------
Initialization and module stuff
------------------------------------------------------------------*/
static int vivi_release(void)
{
struct vivi_dev *dev;
struct list_head *list;
while (!list_empty(&vivi_devlist)) {
list = vivi_devlist.next;
list_del(list);
dev = list_entry(list, struct vivi_dev, vivi_devlist);
v4l2_info(&dev->v4l2_dev, "unregistering /dev/video%d\n",
dev->vfd->num);
video_unregister_device(dev->vfd);
v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev);
}
return 0;
}
static int __init vivi_create_instance(int i)
{
struct vivi_dev *dev;
struct video_device *vfd;
int ret;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
"%s-%03d", VIVI_MODULE_NAME, i);
ret = v4l2_device_register(NULL, &dev->v4l2_dev);
if (ret)
goto free_dev;
/* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active);
init_waitqueue_head(&dev->vidq.wq);
/* initialize locks */
spin_lock_init(&dev->slock);
mutex_init(&dev->mutex);
ret = -ENOMEM;
vfd = video_device_alloc();
if (!vfd)
goto unreg_dev;
*vfd = vivi_template;
ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
if (ret < 0)
goto rel_vdev;
video_set_drvdata(vfd, dev);
/* Now that everything is fine, let's add it to device list */
list_add_tail(&dev->vivi_devlist, &vivi_devlist);
snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
vivi_template.name, vfd->num);
if (video_nr >= 0)
video_nr++;
dev->vfd = vfd;
v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n",
vfd->num);
return 0;
rel_vdev:
video_device_release(vfd);
unreg_dev:
v4l2_device_unregister(&dev->v4l2_dev);
free_dev:
kfree(dev);
return ret;
}
/* This routine allocates from 1 to n_devs virtual drivers.
The real maximum number of virtual drivers will depend on how many drivers
@ -1349,72 +1406,33 @@ static struct video_device vivi_template = {
*/
static int __init vivi_init(void)
{
int ret = -ENOMEM, i;
struct vivi_dev *dev;
struct video_device *vfd;
int ret, i;
if (n_devs <= 0)
n_devs = 1;
for (i = 0; i < n_devs; i++) {
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
break;
/* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active);
init_waitqueue_head(&dev->vidq.wq);
/* initialize locks */
spin_lock_init(&dev->slock);
mutex_init(&dev->mutex);
vfd = video_device_alloc();
if (!vfd) {
kfree(dev);
break;
}
*vfd = vivi_template;
ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
if (ret < 0) {
video_device_release(vfd);
kfree(dev);
/* If some registers succeeded, keep driver */
ret = vivi_create_instance(i);
if (ret) {
/* If some instantiations succeeded, keep driver */
if (i)
ret = 0;
break;
}
/* Now that everything is fine, let's add it to device list */
list_add_tail(&dev->vivi_devlist, &vivi_devlist);
snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
vivi_template.name, vfd->minor);
if (video_nr >= 0)
video_nr++;
dev->vfd = vfd;
printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n",
VIVI_MODULE_NAME, vfd->num);
}
if (ret < 0) {
vivi_release();
printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
} else {
printk(KERN_INFO "Video Technology Magazine Virtual Video "
return ret;
}
printk(KERN_INFO "Video Technology Magazine Virtual Video "
"Capture Board ver %u.%u.%u successfully loaded.\n",
(VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
VIVI_VERSION & 0xFF);
/* n_devs will reflect the actual number of allocated devices */
n_devs = i;
}
/* n_devs will reflect the actual number of allocated devices */
n_devs = i;
return ret;
}
@ -1426,19 +1444,3 @@ static void __exit vivi_exit(void)
module_init(vivi_init);
module_exit(vivi_exit);
MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
MODULE_LICENSE("Dual BSD/GPL");
module_param(video_nr, uint, 0444);
MODULE_PARM_DESC(video_nr, "video iminor start number");
module_param(n_devs, uint, 0444);
MODULE_PARM_DESC(n_devs, "number of video devices to create");
module_param_named(debug, vivi_template.debug, int, 0444);
MODULE_PARM_DESC(debug, "activates debug info");
module_param(vid_limit, int, 0644);
MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");