summaryrefslogtreecommitdiff
path: root/drivers/media/video/vivi.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2007-12-10 04:38:11 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 19:03:21 -0200
commit55712ff7e06b721fbeebd36499bad4a11b7d8327 (patch)
tree05d943d39d9b87eab483df65b625dbd621ded2ae /drivers/media/video/vivi.c
parentf905c442e5b19f75fe4e8ce96f2acffa565f2392 (diff)
V4L/DVB (6754): Allow vivi to open multiple video devices
Now, it is possible to open multiple vivi devices, by using n_devs parameter. This makes vivi driver closer to a real one. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/vivi.c')
-rw-r--r--drivers/media/video/vivi.c106
1 files changed, 62 insertions, 44 deletions
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 5ddaaa370cbc..fda01f49efdf 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -59,6 +59,7 @@
static unsigned int vid_limit = 16; /* Video memory limit, in Mb */
static struct video_device vivi; /* Video device */
static int video_nr = -1; /* /dev/videoN, -1 for autodetect */
+static int n_devs = 1; /* Number of virtual devices */
/* supported controls */
static struct v4l2_queryctrl vivi_qctrl[] = {
@@ -1079,7 +1080,7 @@ static int vivi_close(struct inode *inode, struct file *file)
videobuf_stop(&fh->vb_vidq);
videobuf_mmap_free(&fh->vb_vidq);
- kfree (fh);
+ kfree(fh);
dev->users--;
@@ -1088,14 +1089,23 @@ static int vivi_close(struct inode *inode, struct file *file)
return 0;
}
-static int vivi_release(struct vivi_dev *dev)
+static int vivi_release(void)
{
- if (-1 != dev->vfd->minor)
- video_unregister_device(dev->vfd);
- else
- video_device_release(dev->vfd);
+ 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);
- dev->vfd = NULL;
+ if (-1 != dev->vfd->minor)
+ video_unregister_device(dev->vfd);
+ else
+ video_device_release(dev->vfd);
+
+ kfree(dev);
+ }
return 0;
}
@@ -1166,55 +1176,60 @@ static struct video_device vivi_template = {
static int __init vivi_init(void)
{
- int ret;
+ int ret = -ENOMEM, i;
struct vivi_dev *dev;
struct video_device *vfd;
- dev = kzalloc(sizeof(*dev),GFP_KERNEL);
- if (NULL == dev)
- return -ENOMEM;
- list_add_tail(&dev->vivi_devlist,&vivi_devlist);
+ for (i = 0; i < n_devs; i++) {
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (NULL == dev)
+ break;
- /* init video dma queues */
- INIT_LIST_HEAD(&dev->vidq.active);
- INIT_LIST_HEAD(&dev->vidq.queued);
- init_waitqueue_head(&dev->vidq.wq);
+ list_add_tail(&dev->vivi_devlist, &vivi_devlist);
- /* initialize locks */
- mutex_init(&dev->lock);
+ /* init video dma queues */
+ INIT_LIST_HEAD(&dev->vidq.active);
+ INIT_LIST_HEAD(&dev->vidq.queued);
+ init_waitqueue_head(&dev->vidq.wq);
- dev->vidq.timeout.function = vivi_vid_timeout;
- dev->vidq.timeout.data = (unsigned long)dev;
- init_timer(&dev->vidq.timeout);
+ /* initialize locks */
+ mutex_init(&dev->lock);
- vfd = video_device_alloc();
- if (NULL == vfd)
- return -ENOMEM;
+ dev->vidq.timeout.function = vivi_vid_timeout;
+ dev->vidq.timeout.data = (unsigned long)dev;
+ init_timer(&dev->vidq.timeout);
- *vfd = vivi_template;
+ vfd = video_device_alloc();
+ if (NULL == vfd)
+ break;
+
+ *vfd = vivi_template;
+
+ ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
+ if (ret < 0)
+ break;
+
+ snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
+ vivi_template.name, vfd->minor);
- ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
- snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
- vivi_template.name, vfd->minor);
+ if (video_nr >= 0)
+ video_nr++;
- dev->vfd = vfd;
+ dev->vfd = vfd;
+ }
- printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret);
+ 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 "
+ "Capture Board successfully loaded.\n");
return ret;
}
static void __exit vivi_exit(void)
{
- struct vivi_dev *h;
- struct list_head *list;
-
- while (!list_empty(&vivi_devlist)) {
- list = vivi_devlist.next;
- list_del(list);
- h = list_entry(list, struct vivi_dev, vivi_devlist);
- vivi_release(h);
- kfree (h);
- }
+ vivi_release();
}
module_init(vivi_init);
@@ -1225,10 +1240,13 @@ MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
MODULE_LICENSE("Dual BSD/GPL");
module_param(video_nr, int, 0);
+MODULE_PARM_DESC(video_nr, "video iminor start number");
-module_param_named(debug,vivi.debug, int, 0644);
-MODULE_PARM_DESC(debug,"activates debug info");
+module_param(n_devs, int, 0);
+MODULE_PARM_DESC(n_devs, "number of video devices to create");
-module_param(vid_limit,int,0644);
-MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
+module_param_named(debug, vivi.debug, int, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");