added mtd driver
[linux-2.4.git] / drivers / media / video / videodev.c
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
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
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  
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
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
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
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
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         
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
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   
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
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  */
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
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  */
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
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)
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
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
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
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  
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  
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
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  */