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