2 * Video capture interface for Linux
4 * A generic video device interface for the LINUX operating system
5 * using a set of device structures/vectors for low level operations.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
12 * Author: Alan Cox, <alan@redhat.com>
14 * Fixes: 20000516 Claudio Matsuoka <claudio@conectiva.com>
15 * - Added procfs support
18 #include <linux/config.h>
19 #include <linux/version.h>
20 #include <linux/module.h>
21 #include <linux/types.h>
22 #include <linux/kernel.h>
23 #include <linux/sched.h>
24 #include <linux/smp_lock.h>
26 #include <linux/string.h>
27 #include <linux/errno.h>
28 #include <linux/init.h>
29 #include <linux/kmod.h>
30 #include <linux/slab.h>
31 #include <asm/uaccess.h>
32 #include <asm/system.h>
33 #include <asm/semaphore.h>
35 #include <linux/videodev.h>
37 #define VIDEO_NUM_DEVICES 256
43 static struct video_device *video_device[VIDEO_NUM_DEVICES];
44 static DECLARE_MUTEX(videodev_lock);
47 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
49 #include <linux/proc_fs.h>
51 struct videodev_proc_data {
52 struct list_head proc_list;
54 struct video_device *vdev;
55 struct proc_dir_entry *proc_entry;
58 static struct proc_dir_entry *video_dev_proc_entry = NULL;
59 struct proc_dir_entry *video_proc_entry = NULL;
60 EXPORT_SYMBOL(video_proc_entry);
61 LIST_HEAD(videodev_proc_list);
63 #endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
65 struct video_device *video_device_alloc(void)
67 struct video_device *vfd;
68 vfd = kmalloc(sizeof(*vfd),GFP_KERNEL);
71 memset(vfd,0,sizeof(*vfd));
75 void video_device_release(struct video_device *vfd)
81 * Read will do some smarts later on. Buffer pin etc.
84 static ssize_t video_read(struct file *file,
85 char *buf, size_t count, loff_t *ppos)
87 struct video_device *vfl = video_devdata(file);
89 return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
96 * Write for now does nothing. No reason it shouldnt do overlay setting
97 * for some boards I guess..
100 static ssize_t video_write(struct file *file, const char *buf,
101 size_t count, loff_t *ppos)
103 struct video_device *vfl = video_devdata(file);
105 return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK);
110 struct video_device* video_devdata(struct file *file)
112 return video_device[minor(file->f_dentry->d_inode->i_rdev)];
116 * Poll to see if we're readable, can probably be used for timing on incoming
120 static unsigned int video_poll(struct file *file, poll_table * wait)
122 struct video_device *vfl = video_devdata(file);
124 return vfl->poll(vfl, file, wait);
131 * Open a video device.
134 static int video_open(struct inode *inode, struct file *file)
136 unsigned int minor = minor(inode->i_rdev);
138 struct video_device *vfl;
140 if(minor>=VIDEO_NUM_DEVICES)
142 down(&videodev_lock);
143 vfl=video_device[minor];
148 sprintf (modname, "char-major-%d-%d", VIDEO_MAJOR, minor);
149 request_module(modname);
150 down(&videodev_lock);
151 vfl=video_device[minor];
158 struct file_operations *old_fops;
160 old_fops = file->f_op;
161 file->f_op = fops_get(vfl->fops);
163 err = file->f_op->open(inode,file);
165 fops_put(file->f_op);
166 file->f_op = fops_get(old_fops);
175 vfl->users++; /* In case vfl->open sleeps */
178 __MOD_INC_USE_COUNT(vfl->owner);
181 err=vfl->open(vfl,0); /* Tell the device it is open */
185 __MOD_DEC_USE_COUNT(vfl->owner);
197 * Last close of a video for Linux device
200 static int video_release(struct inode *inode, struct file *file)
202 struct video_device *vfl;
203 struct module *owner;
205 vfl = video_devdata(file);
210 down(&videodev_lock);
211 /* ->close() might have called video_device_unregister()
212 in case of a hot unplug, thus we have to get vfl again */
213 vfl = video_devdata(file);
217 __MOD_DEC_USE_COUNT(owner);
222 static int video_ioctl(struct inode *inode, struct file *file,
223 unsigned int cmd, unsigned long arg)
225 struct video_device *vfl = video_devdata(file);
226 int err=vfl->ioctl(vfl, cmd, (void *)arg);
228 if(err!=-ENOIOCTLCMD)
239 * We need to do MMAP support
242 int video_mmap(struct file *file, struct vm_area_struct *vma)
245 struct video_device *vfl = video_devdata(file);
248 ret = vfl->mmap(vfl, (char *)vma->vm_start,
249 (unsigned long)(vma->vm_end-vma->vm_start));
256 * helper function -- handles userspace copying for ioctl arguments
259 video_usercopy(struct inode *inode, struct file *file,
260 unsigned int cmd, unsigned long arg,
261 int (*func)(struct inode *inode, struct file *file,
262 unsigned int cmd, void *arg))
269 /* Copy arguments into temp kernel buffer */
270 switch (_IOC_DIR(cmd)) {
274 case _IOC_READ: /* some v4l ioctls are marked wrong ... */
276 case (_IOC_WRITE | _IOC_READ):
277 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
280 /* too big to allocate from stack */
281 mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
288 if (copy_from_user(parg, (void *)arg, _IOC_SIZE(cmd)))
294 err = func(inode, file, cmd, parg);
295 if (err == -ENOIOCTLCMD)
300 /* Copy results into user buffer */
301 switch (_IOC_DIR(cmd))
304 case (_IOC_WRITE | _IOC_READ):
305 if (copy_to_user((void *)arg, parg, _IOC_SIZE(cmd)))
317 * open/release helper functions -- handle exclusive opens
319 extern int video_exclusive_open(struct inode *inode, struct file *file)
321 struct video_device *vfl = video_devdata(file);
334 extern int video_exclusive_release(struct inode *inode, struct file *file)
336 struct video_device *vfl = video_devdata(file);
346 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
348 /* Hmm... i'd like to see video_capability information here, but
349 * how can I access it (without changing the other drivers? -claudio
351 static int videodev_proc_read(char *page, char **start, off_t off,
352 int count, int *eof, void *data)
355 struct video_device *vfd = data;
356 struct videodev_proc_data *d;
357 struct list_head *tmp;
361 list_for_each (tmp, &videodev_proc_list) {
362 d = list_entry(tmp, struct videodev_proc_data, proc_list);
368 if (tmp == &videodev_proc_list)
371 #define PRINT_VID_TYPE(x) do { if (vfd->type & x) \
372 out += sprintf (out, "%c%s", c, #x); c='|';} while (0)
374 out += sprintf (out, "name : %s\n", vfd->name);
375 out += sprintf (out, "type :");
376 PRINT_VID_TYPE(VID_TYPE_CAPTURE);
377 PRINT_VID_TYPE(VID_TYPE_TUNER);
378 PRINT_VID_TYPE(VID_TYPE_TELETEXT);
379 PRINT_VID_TYPE(VID_TYPE_OVERLAY);
380 PRINT_VID_TYPE(VID_TYPE_CHROMAKEY);
381 PRINT_VID_TYPE(VID_TYPE_CLIPPING);
382 PRINT_VID_TYPE(VID_TYPE_FRAMERAM);
383 PRINT_VID_TYPE(VID_TYPE_SCALES);
384 PRINT_VID_TYPE(VID_TYPE_MONOCHROME);
385 PRINT_VID_TYPE(VID_TYPE_SUBCAPTURE);
386 PRINT_VID_TYPE(VID_TYPE_MPEG_DECODER);
387 PRINT_VID_TYPE(VID_TYPE_MPEG_ENCODER);
388 PRINT_VID_TYPE(VID_TYPE_MJPEG_DECODER);
389 PRINT_VID_TYPE(VID_TYPE_MJPEG_ENCODER);
390 out += sprintf (out, "\n");
391 out += sprintf (out, "hardware : 0x%x\n", vfd->hardware);
393 out += sprintf (out, "channels : %d\n", d->vcap.channels);
394 out += sprintf (out, "audios : %d\n", d->vcap.audios);
395 out += sprintf (out, "maxwidth : %d\n", d->vcap.maxwidth);
396 out += sprintf (out, "maxheight : %d\n", d->vcap.maxheight);
397 out += sprintf (out, "minwidth : %d\n", d->vcap.minwidth);
398 out += sprintf (out, "minheight : %d\n", d->vcap.minheight);
416 static void videodev_proc_create(void)
418 video_proc_entry = create_proc_entry("video", S_IFDIR, &proc_root);
420 if (video_proc_entry == NULL) {
421 printk("video_dev: unable to initialise /proc/video\n");
425 video_proc_entry->owner = THIS_MODULE;
426 video_dev_proc_entry = create_proc_entry("dev", S_IFDIR, video_proc_entry);
428 if (video_dev_proc_entry == NULL) {
429 printk("video_dev: unable to initialise /proc/video/dev\n");
433 video_dev_proc_entry->owner = THIS_MODULE;
436 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
437 static void videodev_proc_destroy(void)
439 if (video_dev_proc_entry != NULL)
440 remove_proc_entry("dev", video_proc_entry);
442 if (video_proc_entry != NULL)
443 remove_proc_entry("video", &proc_root);
447 static void videodev_proc_create_dev (struct video_device *vfd, char *name)
449 struct videodev_proc_data *d;
450 struct proc_dir_entry *p;
452 if (video_dev_proc_entry == NULL)
455 d = kmalloc (sizeof (struct videodev_proc_data), GFP_KERNEL);
459 p = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, video_dev_proc_entry);
463 p->read_proc = videodev_proc_read;
467 strcpy (d->name, name);
469 /* How can I get capability information ? */
471 list_add (&d->proc_list, &videodev_proc_list);
474 static void videodev_proc_destroy_dev (struct video_device *vfd)
476 struct list_head *tmp;
477 struct videodev_proc_data *d;
479 list_for_each (tmp, &videodev_proc_list) {
480 d = list_entry(tmp, struct videodev_proc_data, proc_list);
481 if (vfd == d->vdev) {
482 remove_proc_entry(d->name, video_dev_proc_entry);
483 list_del (&d->proc_list);
490 #endif /* CONFIG_VIDEO_PROC_FS */
492 static struct file_operations video_fops=
501 release: video_release,
506 * video_register_device - register video4linux devices
507 * @vfd: video device structure we want to register
508 * @type: type of device to register
509 * @nr: which device number (0 == /dev/video0, 1 == /dev/video1, ...
512 * The registration code assigns minor numbers based on the type
513 * requested. -ENFILE is returned in all the device slots for this
514 * category are full. If not then the minor field is set and the
515 * driver initialize function is called (if non %NULL).
517 * Zero is returned on success.
521 * %VFL_TYPE_GRABBER - A frame grabber
523 * %VFL_TYPE_VTX - A teletext device
525 * %VFL_TYPE_VBI - Vertical blank data (undecoded)
527 * %VFL_TYPE_RADIO - A radio card
530 int video_register_device(struct video_device *vfd, int type, int nr)
541 case VFL_TYPE_GRABBER:
565 /* pick a minor number */
566 down(&videodev_lock);
567 if (nr >= 0 && nr < end-base) {
568 /* use the one the driver asked for */
570 if (NULL != video_device[i]) {
576 for(i=base;i<end;i++)
577 if (NULL == video_device[i])
588 /* The init call may sleep so we book the slot out
591 if(vfd->initialize) {
592 err=vfd->initialize(vfd);
594 video_device[i]=NULL;
599 sprintf (name, "v4l/%s%d", name_base, i - base);
601 * Start the device root only. Anything else
602 * has serious privacy issues.
605 devfs_register (NULL, name, DEVFS_FL_DEFAULT,
606 VIDEO_MAJOR, vfd->minor,
607 S_IFCHR | S_IRUSR | S_IWUSR,
610 init_MUTEX(&vfd->lock);
612 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
613 sprintf (name, "%s%d", name_base, i - base);
614 videodev_proc_create_dev (vfd, name);
620 * video_unregister_device - unregister a video4linux device
621 * @vfd: the device to unregister
623 * This unregisters the passed device and deassigns the minor
624 * number. Future open calls will be met with errors.
627 void video_unregister_device(struct video_device *vfd)
629 down(&videodev_lock);
631 if(video_device[vfd->minor]!=vfd)
632 panic("videodev: bad unregister");
634 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
635 videodev_proc_destroy_dev (vfd);
638 devfs_unregister (vfd->devfs_handle);
641 video_device[vfd->minor]=NULL;
648 * Initialise video for linux
651 static int __init videodev_init(void)
653 printk(KERN_INFO "Linux video capture interface: v1.00\n");
654 if(devfs_register_chrdev(VIDEO_MAJOR,"video_capture", &video_fops))
656 printk("video_dev: unable to get major %d\n", VIDEO_MAJOR);
660 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
661 videodev_proc_create ();
667 static void __exit videodev_exit(void)
669 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
670 videodev_proc_destroy ();
672 devfs_unregister_chrdev(VIDEO_MAJOR, "video_capture");
675 module_init(videodev_init)
676 module_exit(videodev_exit)
678 EXPORT_SYMBOL(video_device_alloc);
679 EXPORT_SYMBOL(video_device_release);
680 EXPORT_SYMBOL(video_register_device);
681 EXPORT_SYMBOL(video_unregister_device);
682 EXPORT_SYMBOL(video_devdata);
683 EXPORT_SYMBOL(video_usercopy);
684 EXPORT_SYMBOL(video_exclusive_open);
685 EXPORT_SYMBOL(video_exclusive_release);
687 MODULE_AUTHOR("Alan Cox");
688 MODULE_DESCRIPTION("Device registrar for Video4Linux drivers");
689 MODULE_LICENSE("GPL");