1 /*
2  * Video capture interface for Linux
3  *
4  *		A generic video device interface for the LINUX operating system
5  *		using a set of device structures/vectors for low level operations.
6  *
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.
11  *
12  * Author:	Alan Cox, <alan@redhat.com>
13  *
14  * Fixes:	20000516  Claudio Matsuoka <claudio@conectiva.com>
15  *		- Added procfs support
16  */
17 
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>
25 #include <linux/mm.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>
34 
35 #include <linux/videodev.h>
36 
37 #define VIDEO_NUM_DEVICES	256
38 
39 /*
40  *	Active devices
41  */
42 
43 static struct video_device *video_device[VIDEO_NUM_DEVICES];
44 static DECLARE_MUTEX(videodev_lock);
45 
46 
47 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
48 
49 #include <linux/proc_fs.h>
50 
51 struct videodev_proc_data {
52 	struct list_head proc_list;
53 	char name[16];
54 	struct video_device *vdev;
55 	struct proc_dir_entry *proc_entry;
56 };
57 
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);
62 
63 #endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
64 
video_device_alloc(void)65 struct video_device *video_device_alloc(void)
66 {
67 	struct video_device *vfd;
68 	vfd = kmalloc(sizeof(*vfd),GFP_KERNEL);
69 	if (NULL == vfd)
70 		return NULL;
71 	memset(vfd,0,sizeof(*vfd));
72 	return vfd;
73 }
74 
video_device_release(struct video_device * vfd)75 void video_device_release(struct video_device *vfd)
76 {
77 	kfree(vfd);
78 }
79 
80 /*
81  *	Read will do some smarts later on. Buffer pin etc.
82  */
83 
video_read(struct file * file,char * buf,size_t count,loff_t * ppos)84 static ssize_t video_read(struct file *file,
85 	char *buf, size_t count, loff_t *ppos)
86 {
87 	struct video_device *vfl = video_devdata(file);
88 	if(vfl->read)
89 		return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
90 	else
91 		return -EINVAL;
92 }
93 
94 
95 /*
96  *	Write for now does nothing. No reason it shouldnt do overlay setting
97  *	for some boards I guess..
98  */
99 
video_write(struct file * file,const char * buf,size_t count,loff_t * ppos)100 static ssize_t video_write(struct file *file, const char *buf,
101 	size_t count, loff_t *ppos)
102 {
103 	struct video_device *vfl = video_devdata(file);
104 	if(vfl->write)
105 		return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK);
106 	else
107 		return 0;
108 }
109 
video_devdata(struct file * file)110 struct video_device* video_devdata(struct file *file)
111 {
112 	return video_device[minor(file->f_dentry->d_inode->i_rdev)];
113 }
114 
115 /*
116  *	Poll to see if we're readable, can probably be used for timing on incoming
117  *	frames, etc..
118  */
119 
video_poll(struct file * file,poll_table * wait)120 static unsigned int video_poll(struct file *file, poll_table * wait)
121 {
122 	struct video_device *vfl = video_devdata(file);
123 	if(vfl->poll)
124 		return vfl->poll(vfl, file, wait);
125 	else
126 		return 0;
127 }
128 
129 
130 /*
131  *	Open a video device.
132  */
133 
video_open(struct inode * inode,struct file * file)134 static int video_open(struct inode *inode, struct file *file)
135 {
136 	unsigned int minor = minor(inode->i_rdev);
137 	int err = 0;
138 	struct video_device *vfl;
139 
140 	if(minor>=VIDEO_NUM_DEVICES)
141 		return -ENODEV;
142 	down(&videodev_lock);
143 	vfl=video_device[minor];
144 	if(vfl==NULL) {
145 		char modname[20];
146 
147 		up(&videodev_lock);
148 		sprintf (modname, "char-major-%d-%d", VIDEO_MAJOR, minor);
149 		request_module(modname);
150 		down(&videodev_lock);
151 		vfl=video_device[minor];
152 		if (vfl==NULL) {
153 			err = -ENODEV;
154 			goto unlock_out;
155 		}
156 	}
157 	if (vfl->fops) {
158 		struct file_operations *old_fops;
159 
160 		old_fops = file->f_op;
161                 file->f_op = fops_get(vfl->fops);
162                 if(file->f_op->open)
163                         err = file->f_op->open(inode,file);
164                 if (err) {
165                         fops_put(file->f_op);
166                         file->f_op = fops_get(old_fops);
167                 }
168                 fops_put(old_fops);
169 		goto unlock_out;
170 	}
171 	if(vfl->users) {
172 		err = -EBUSY;
173 		goto unlock_out;
174 	}
175 	vfl->users++;		/* In case vfl->open sleeps */
176 
177 	if(vfl->owner)
178 		__MOD_INC_USE_COUNT(vfl->owner);
179 
180 	if (vfl->open) {
181 		err=vfl->open(vfl,0);	/* Tell the device it is open */
182 		if (err) {
183 			vfl->users--;
184 			if(vfl->owner)
185 				__MOD_DEC_USE_COUNT(vfl->owner);
186 			goto unlock_out;
187 		}
188 	}
189 	err = 0;
190 
191 unlock_out:
192 	up(&videodev_lock);
193 	return err;
194 }
195 
196 /*
197  *	Last close of a video for Linux device
198  */
199 
video_release(struct inode * inode,struct file * file)200 static int video_release(struct inode *inode, struct file *file)
201 {
202 	struct video_device *vfl;
203 	struct module *owner;
204 
205 	vfl = video_devdata(file);
206 	owner = vfl->owner;
207 	if (vfl->close)
208 		vfl->close(vfl);
209 
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);
214 	if (NULL != vfl)
215 		vfl->users--;
216 	if (owner)
217 		__MOD_DEC_USE_COUNT(owner);
218 	up(&videodev_lock);
219 	return 0;
220 }
221 
video_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg)222 static int video_ioctl(struct inode *inode, struct file *file,
223 	unsigned int cmd, unsigned long arg)
224 {
225 	struct video_device *vfl = video_devdata(file);
226 	int err=vfl->ioctl(vfl, cmd, (void *)arg);
227 
228 	if(err!=-ENOIOCTLCMD)
229 		return err;
230 
231 	switch(cmd)
232 	{
233 		default:
234 			return -EINVAL;
235 	}
236 }
237 
238 /*
239  *	We need to do MMAP support
240  */
241 
video_mmap(struct file * file,struct vm_area_struct * vma)242 int video_mmap(struct file *file, struct vm_area_struct *vma)
243 {
244 	int ret = -EINVAL;
245 	struct video_device *vfl = video_devdata(file);
246 	if(vfl->mmap) {
247 		lock_kernel();
248 		ret = vfl->mmap(vfl, (char *)vma->vm_start,
249 				(unsigned long)(vma->vm_end-vma->vm_start));
250 		unlock_kernel();
251 	}
252 	return ret;
253 }
254 
255 /*
256  * helper function -- handles userspace copying for ioctl arguments
257  */
258 int
video_usercopy(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg,int (* func)(struct inode * inode,struct file * file,unsigned int cmd,void * arg))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))
263 {
264 	char	sbuf[128];
265 	void    *mbuf = NULL;
266 	void	*parg = NULL;
267 	int	err  = -EINVAL;
268 
269 	/*  Copy arguments into temp kernel buffer  */
270 	switch (_IOC_DIR(cmd)) {
271 	case _IOC_NONE:
272 		parg = (void *)arg;
273 		break;
274 	case _IOC_READ: /* some v4l ioctls are marked wrong ... */
275 	case _IOC_WRITE:
276 	case (_IOC_WRITE | _IOC_READ):
277 		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
278 			parg = sbuf;
279 		} else {
280 			/* too big to allocate from stack */
281 			mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
282 			if (NULL == mbuf)
283 				return -ENOMEM;
284 			parg = mbuf;
285 		}
286 
287 		err = -EFAULT;
288 		if (copy_from_user(parg, (void *)arg, _IOC_SIZE(cmd)))
289 			goto out;
290 		break;
291 	}
292 
293 	/* call driver */
294 	err = func(inode, file, cmd, parg);
295 	if (err == -ENOIOCTLCMD)
296 		err = -EINVAL;
297 	if (err < 0)
298 		goto out;
299 
300 	/*  Copy results into user buffer  */
301 	switch (_IOC_DIR(cmd))
302 	{
303 	case _IOC_READ:
304 	case (_IOC_WRITE | _IOC_READ):
305 		if (copy_to_user((void *)arg, parg, _IOC_SIZE(cmd)))
306 			err = -EFAULT;
307 		break;
308 	}
309 
310 out:
311 	if (mbuf)
312 		kfree(mbuf);
313 	return err;
314 }
315 
316 /*
317  * open/release helper functions -- handle exclusive opens
318  */
video_exclusive_open(struct inode * inode,struct file * file)319 extern int video_exclusive_open(struct inode *inode, struct file *file)
320 {
321 	struct  video_device *vfl = video_devdata(file);
322 	int retval = 0;
323 
324 	down(&vfl->lock);
325 	if (vfl->users) {
326 		retval = -EBUSY;
327 	} else {
328 		vfl->users++;
329 	}
330 	up(&vfl->lock);
331 	return retval;
332 }
333 
video_exclusive_release(struct inode * inode,struct file * file)334 extern int video_exclusive_release(struct inode *inode, struct file *file)
335 {
336 	struct  video_device *vfl = video_devdata(file);
337 
338 	vfl->users--;
339 	return 0;
340 }
341 
342 /*
343  *	/proc support
344  */
345 
346 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
347 
348 /* Hmm... i'd like to see video_capability information here, but
349  * how can I access it (without changing the other drivers? -claudio
350  */
videodev_proc_read(char * page,char ** start,off_t off,int count,int * eof,void * data)351 static int videodev_proc_read(char *page, char **start, off_t off,
352 			       int count, int *eof, void *data)
353 {
354 	char *out = page;
355 	struct video_device *vfd = data;
356 	struct videodev_proc_data *d;
357 	struct list_head *tmp;
358 	int len;
359 	char c = ' ';
360 
361 	list_for_each (tmp, &videodev_proc_list) {
362 		d = list_entry(tmp, struct videodev_proc_data, proc_list);
363 		if (vfd == d->vdev)
364 			break;
365 	}
366 
367 	/* Sanity check */
368 	if (tmp == &videodev_proc_list)
369 		goto skip;
370 
371 #define PRINT_VID_TYPE(x) do { if (vfd->type & x) \
372 	out += sprintf (out, "%c%s", c, #x); c='|';} while (0)
373 
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);
392 #if 0
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);
399 #endif
400 
401 skip:
402 	len = out - page;
403 	len -= off;
404 	if (len < count) {
405 		*eof = 1;
406 		if (len <= 0)
407 			return 0;
408 	} else
409 		len = count;
410 
411 	*start = page + off;
412 
413 	return len;
414 }
415 
videodev_proc_create(void)416 static void videodev_proc_create(void)
417 {
418 	video_proc_entry = create_proc_entry("video", S_IFDIR, &proc_root);
419 
420 	if (video_proc_entry == NULL) {
421 		printk("video_dev: unable to initialise /proc/video\n");
422 		return;
423 	}
424 
425 	video_proc_entry->owner = THIS_MODULE;
426 	video_dev_proc_entry = create_proc_entry("dev", S_IFDIR, video_proc_entry);
427 
428 	if (video_dev_proc_entry == NULL) {
429 		printk("video_dev: unable to initialise /proc/video/dev\n");
430 		return;
431 	}
432 
433 	video_dev_proc_entry->owner = THIS_MODULE;
434 }
435 
436 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
videodev_proc_destroy(void)437 static void videodev_proc_destroy(void)
438 {
439 	if (video_dev_proc_entry != NULL)
440 		remove_proc_entry("dev", video_proc_entry);
441 
442 	if (video_proc_entry != NULL)
443 		remove_proc_entry("video", &proc_root);
444 }
445 #endif
446 
videodev_proc_create_dev(struct video_device * vfd,char * name)447 static void videodev_proc_create_dev (struct video_device *vfd, char *name)
448 {
449 	struct videodev_proc_data *d;
450 	struct proc_dir_entry *p;
451 
452 	if (video_dev_proc_entry == NULL)
453 		return;
454 
455 	d = kmalloc (sizeof (struct videodev_proc_data), GFP_KERNEL);
456 	if (!d)
457 		return;
458 
459 	p = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, video_dev_proc_entry);
460 	if (!p)
461 		return;
462 	p->data = vfd;
463 	p->read_proc = videodev_proc_read;
464 
465 	d->proc_entry = p;
466 	d->vdev = vfd;
467 	strcpy (d->name, name);
468 
469 	/* How can I get capability information ? */
470 
471 	list_add (&d->proc_list, &videodev_proc_list);
472 }
473 
videodev_proc_destroy_dev(struct video_device * vfd)474 static void videodev_proc_destroy_dev (struct video_device *vfd)
475 {
476 	struct list_head *tmp;
477 	struct videodev_proc_data *d;
478 
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);
484 			kfree(d);
485 			break;
486 		}
487 	}
488 }
489 
490 #endif /* CONFIG_VIDEO_PROC_FS */
491 
492 static struct file_operations video_fops=
493 {
494 	owner:		THIS_MODULE,
495 	llseek:		no_llseek,
496 	read:		video_read,
497 	write:		video_write,
498 	ioctl:		video_ioctl,
499 	mmap:		video_mmap,
500 	open:		video_open,
501 	release:	video_release,
502 	poll:		video_poll,
503 };
504 
505 /**
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, ...
510  *             -1 == first free)
511  *
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).
516  *
517  *	Zero is returned on success.
518  *
519  *	Valid types are
520  *
521  *	%VFL_TYPE_GRABBER - A frame grabber
522  *
523  *	%VFL_TYPE_VTX - A teletext device
524  *
525  *	%VFL_TYPE_VBI - Vertical blank data (undecoded)
526  *
527  *	%VFL_TYPE_RADIO - A radio card
528  */
529 
video_register_device(struct video_device * vfd,int type,int nr)530 int video_register_device(struct video_device *vfd, int type, int nr)
531 {
532 	int i=0;
533 	int base;
534 	int err;
535 	int end;
536 	char *name_base;
537 	char name[16];
538 
539 	switch(type)
540 	{
541 		case VFL_TYPE_GRABBER:
542 			base=0;
543 			end=64;
544 			name_base = "video";
545 			break;
546 		case VFL_TYPE_VTX:
547 			base=192;
548 			end=224;
549 			name_base = "vtx";
550 			break;
551 		case VFL_TYPE_VBI:
552 			base=224;
553 			end=240;
554 			name_base = "vbi";
555 			break;
556 		case VFL_TYPE_RADIO:
557 			base=64;
558 			end=128;
559 			name_base = "radio";
560 			break;
561 		default:
562 			return -1;
563 	}
564 
565 	/* pick a minor number */
566 	down(&videodev_lock);
567 	if (nr >= 0  &&  nr < end-base) {
568 		/* use the one the driver asked for */
569 		i = base+nr;
570 		if (NULL != video_device[i]) {
571 			up(&videodev_lock);
572 			return -ENFILE;
573 		}
574 	} else {
575 		/* use first free */
576 		for(i=base;i<end;i++)
577 			if (NULL == video_device[i])
578 				break;
579 		if (i == end) {
580 			up(&videodev_lock);
581 			return -ENFILE;
582 		}
583 	}
584 	video_device[i]=vfd;
585 	vfd->minor=i;
586 	up(&videodev_lock);
587 
588 	/* The init call may sleep so we book the slot out
589 	   then call */
590 	MOD_INC_USE_COUNT;
591 	if(vfd->initialize) {
592 		err=vfd->initialize(vfd);
593 		if(err<0) {
594 			video_device[i]=NULL;
595 			MOD_DEC_USE_COUNT;
596 			return err;
597 		}
598 	}
599 	sprintf (name, "v4l/%s%d", name_base, i - base);
600 	/*
601 	 *	Start the device root only. Anything else
602 	 *	has serious privacy issues.
603 	 */
604 	vfd->devfs_handle =
605 		devfs_register (NULL, name, DEVFS_FL_DEFAULT,
606 				VIDEO_MAJOR, vfd->minor,
607 				S_IFCHR | S_IRUSR | S_IWUSR,
608 				&video_fops,
609 				NULL);
610 	init_MUTEX(&vfd->lock);
611 
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);
615 #endif
616 	return 0;
617 }
618 
619 /**
620  *	video_unregister_device - unregister a video4linux device
621  *	@vfd: the device to unregister
622  *
623  *	This unregisters the passed device and deassigns the minor
624  *	number. Future open calls will be met with errors.
625  */
626 
video_unregister_device(struct video_device * vfd)627 void video_unregister_device(struct video_device *vfd)
628 {
629 	down(&videodev_lock);
630 
631 	if(video_device[vfd->minor]!=vfd)
632 		panic("videodev: bad unregister");
633 
634 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
635 	videodev_proc_destroy_dev (vfd);
636 #endif
637 
638 	devfs_unregister (vfd->devfs_handle);
639 	if (vfd->release)
640 		vfd->release(vfd);
641 	video_device[vfd->minor]=NULL;
642 	MOD_DEC_USE_COUNT;
643 	up(&videodev_lock);
644 }
645 
646 
647 /*
648  *	Initialise video for linux
649  */
650 
videodev_init(void)651 static int __init videodev_init(void)
652 {
653 	printk(KERN_INFO "Linux video capture interface: v1.00\n");
654 	if(devfs_register_chrdev(VIDEO_MAJOR,"video_capture", &video_fops))
655 	{
656 		printk("video_dev: unable to get major %d\n", VIDEO_MAJOR);
657 		return -EIO;
658 	}
659 
660 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
661 	videodev_proc_create ();
662 #endif
663 
664 	return 0;
665 }
666 
videodev_exit(void)667 static void __exit videodev_exit(void)
668 {
669 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
670 	videodev_proc_destroy ();
671 #endif
672 	devfs_unregister_chrdev(VIDEO_MAJOR, "video_capture");
673 }
674 
675 module_init(videodev_init)
676 module_exit(videodev_exit)
677 
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);
686 
687 MODULE_AUTHOR("Alan Cox");
688 MODULE_DESCRIPTION("Device registrar for Video4Linux drivers");
689 MODULE_LICENSE("GPL");
690 
691 
692 /*
693  * Local variables:
694  * c-basic-offset: 8
695  * End:
696  */
697