diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-12-10 04:38:11 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 19:03:21 -0200 |
commit | 55712ff7e06b721fbeebd36499bad4a11b7d8327 (patch) | |
tree | 05d943d39d9b87eab483df65b625dbd621ded2ae /drivers/media/video/vivi.c | |
parent | f905c442e5b19f75fe4e8ce96f2acffa565f2392 (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.c | 106 |
1 files changed, 62 insertions, 44 deletions
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 5ddaaa370cb..fda01f49efd 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"); |