v2.4.8 -> v2.4.8.1
[opensuse:kernel.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/videodev.h>
29 #include <linux/init.h>
30
31 #include <asm/uaccess.h>
32 #include <asm/system.h>
33 #include <asm/semaphore.h>
34
35 #include <linux/kmod.h>
36
37
38 #define VIDEO_NUM_DEVICES       256 
39
40 /*
41  *      Active devices 
42  */
43  
44 static struct video_device *video_device[VIDEO_NUM_DEVICES];
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
66 #ifdef CONFIG_VIDEO_BWQCAM
67 extern int init_bw_qcams(struct video_init *);
68 #endif
69 #ifdef CONFIG_VIDEO_CPIA
70 extern int cpia_init(struct video_init *);
71 #endif
72 #ifdef CONFIG_VIDEO_PLANB
73 extern int init_planbs(struct video_init *);
74 #endif
75
76 static struct video_init video_init_list[]={
77 #ifdef CONFIG_VIDEO_BWQCAM
78         {"bw-qcam", init_bw_qcams},
79 #endif  
80 #ifdef CONFIG_VIDEO_CPIA
81         {"cpia", cpia_init},
82 #endif  
83 #ifdef CONFIG_VIDEO_PLANB
84         {"planb", init_planbs},
85 #endif
86         {"end", NULL}
87 };
88
89 /*
90  *      Read will do some smarts later on. Buffer pin etc.
91  */
92  
93 static ssize_t video_read(struct file *file,
94         char *buf, size_t count, loff_t *ppos)
95 {
96         struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
97         if(vfl->read)
98                 return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
99         else
100                 return -EINVAL;
101 }
102
103
104 /*
105  *      Write for now does nothing. No reason it shouldnt do overlay setting
106  *      for some boards I guess..
107  */
108
109 static ssize_t video_write(struct file *file, const char *buf, 
110         size_t count, loff_t *ppos)
111 {
112         struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
113         if(vfl->write)
114                 return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK);
115         else
116                 return 0;
117 }
118
119 /*
120  *      Poll to see if we're readable, can probably be used for timing on incoming
121  *  frames, etc..
122  */
123
124 static unsigned int video_poll(struct file *file, poll_table * wait)
125 {
126         struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
127         if(vfl->poll)
128                 return vfl->poll(vfl, file, wait);
129         else
130                 return 0;
131 }
132
133
134 /*
135  *      Open a video device.
136  */
137
138 static int video_open(struct inode *inode, struct file *file)
139 {
140         unsigned int minor = MINOR(inode->i_rdev);
141         int err, retval = 0;
142         struct video_device *vfl;
143         
144         if(minor>=VIDEO_NUM_DEVICES)
145                 return -ENODEV;
146         lock_kernel();          
147         vfl=video_device[minor];
148         if(vfl==NULL) {
149                 char modname[20];
150
151                 sprintf (modname, "char-major-%d-%d", VIDEO_MAJOR, minor);
152                 request_module(modname);
153                 vfl=video_device[minor];
154                 if (vfl==NULL) {
155                         retval = -ENODEV;
156                         goto error_out;
157                 }
158         }
159         if(vfl->busy) {
160                 retval = -EBUSY;
161                 goto error_out;
162         }
163         vfl->busy=1;            /* In case vfl->open sleeps */
164         
165         if(vfl->owner)
166                 __MOD_INC_USE_COUNT(vfl->owner);
167         unlock_kernel();
168         
169         if(vfl->open)
170         {
171                 err=vfl->open(vfl,0);   /* Tell the device it is open */
172                 if(err)
173                 {
174                         vfl->busy=0;
175                         if(vfl->owner)
176                                 __MOD_DEC_USE_COUNT(vfl->owner);
177                         
178                         return err;
179                 }
180         }
181         return 0;
182 error_out:
183         unlock_kernel();
184         return retval;
185 }
186
187 /*
188  *      Last close of a video for Linux device
189  */
190         
191 static int video_release(struct inode *inode, struct file *file)
192 {
193         struct video_device *vfl;
194         lock_kernel();
195         vfl=video_device[MINOR(inode->i_rdev)];
196         if(vfl->close)
197                 vfl->close(vfl);
198         vfl->busy=0;
199         if(vfl->owner)
200                 __MOD_DEC_USE_COUNT(vfl->owner);
201         unlock_kernel();
202         return 0;
203 }
204
205 static int video_ioctl(struct inode *inode, struct file *file,
206         unsigned int cmd, unsigned long arg)
207 {
208         struct video_device *vfl=video_device[MINOR(inode->i_rdev)];
209         int err=vfl->ioctl(vfl, cmd, (void *)arg);
210
211         if(err!=-ENOIOCTLCMD)
212                 return err;
213         
214         switch(cmd)
215         {
216                 default:
217                         return -EINVAL;
218         }
219 }
220
221 /*
222  *      We need to do MMAP support
223  */
224  
225  
226 int video_mmap(struct file *file, struct vm_area_struct *vma)
227 {
228         int ret = -EINVAL;
229         struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
230         if(vfl->mmap) {
231                 lock_kernel();
232                 ret = vfl->mmap(vfl, (char *)vma->vm_start, 
233                                 (unsigned long)(vma->vm_end-vma->vm_start));
234                 unlock_kernel();
235         }
236         return ret;
237 }
238
239 /*
240  *      /proc support
241  */
242
243 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
244
245 /* Hmm... i'd like to see video_capability information here, but
246  * how can I access it (without changing the other drivers? -claudio
247  */
248 static int videodev_proc_read(char *page, char **start, off_t off,
249                                int count, int *eof, void *data)
250 {
251         char *out = page;
252         struct video_device *vfd = data;
253         struct videodev_proc_data *d;
254         struct list_head *tmp;
255         int len;
256         char c = ' ';
257
258         list_for_each (tmp, &videodev_proc_list) {
259                 d = list_entry(tmp, struct videodev_proc_data, proc_list);
260                 if (vfd == d->vdev)
261                         break;
262         }
263
264         /* Sanity check */
265         if (tmp == &videodev_proc_list)
266                 goto skip;
267                 
268 #define PRINT_VID_TYPE(x) do { if (vfd->type & x) \
269         out += sprintf (out, "%c%s", c, #x); c='|';} while (0)
270
271         out += sprintf (out, "name            : %s\n", vfd->name);
272         out += sprintf (out, "type            :");
273                 PRINT_VID_TYPE(VID_TYPE_CAPTURE);
274                 PRINT_VID_TYPE(VID_TYPE_TUNER);
275                 PRINT_VID_TYPE(VID_TYPE_TELETEXT);
276                 PRINT_VID_TYPE(VID_TYPE_OVERLAY);
277                 PRINT_VID_TYPE(VID_TYPE_CHROMAKEY);
278                 PRINT_VID_TYPE(VID_TYPE_CLIPPING);
279                 PRINT_VID_TYPE(VID_TYPE_FRAMERAM);
280                 PRINT_VID_TYPE(VID_TYPE_SCALES);
281                 PRINT_VID_TYPE(VID_TYPE_MONOCHROME);
282                 PRINT_VID_TYPE(VID_TYPE_SUBCAPTURE);
283                 PRINT_VID_TYPE(VID_TYPE_MPEG_DECODER);
284                 PRINT_VID_TYPE(VID_TYPE_MPEG_ENCODER);
285                 PRINT_VID_TYPE(VID_TYPE_MJPEG_DECODER);
286                 PRINT_VID_TYPE(VID_TYPE_MJPEG_ENCODER);
287         out += sprintf (out, "\n");
288         out += sprintf (out, "hardware        : 0x%x\n", vfd->hardware);
289 #if 0
290         out += sprintf (out, "channels        : %d\n", d->vcap.channels);
291         out += sprintf (out, "audios          : %d\n", d->vcap.audios);
292         out += sprintf (out, "maxwidth        : %d\n", d->vcap.maxwidth);
293         out += sprintf (out, "maxheight       : %d\n", d->vcap.maxheight);
294         out += sprintf (out, "minwidth        : %d\n", d->vcap.minwidth);
295         out += sprintf (out, "minheight       : %d\n", d->vcap.minheight);
296 #endif
297
298 skip:
299         len = out - page;
300         len -= off;
301         if (len < count) {
302                 *eof = 1;
303                 if (len <= 0)
304                         return 0;
305         } else
306                 len = count;
307
308         *start = page + off;
309
310         return len;
311 }
312
313 static void videodev_proc_create(void)
314 {
315         video_proc_entry = create_proc_entry("video", S_IFDIR, &proc_root);
316
317         if (video_proc_entry == NULL) {
318                 printk("video_dev: unable to initialise /proc/video\n");
319                 return;
320         }
321
322         video_proc_entry->owner = THIS_MODULE;
323         video_dev_proc_entry = create_proc_entry("dev", S_IFDIR, video_proc_entry);
324
325         if (video_dev_proc_entry == NULL) {
326                 printk("video_dev: unable to initialise /proc/video/dev\n");
327                 return;
328         }
329
330         video_dev_proc_entry->owner = THIS_MODULE;
331 }
332
333 #ifdef MODULE
334 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
335 static void videodev_proc_destroy(void)
336 {
337         if (video_dev_proc_entry != NULL)
338                 remove_proc_entry("dev", video_proc_entry);
339
340         if (video_proc_entry != NULL)
341                 remove_proc_entry("video", &proc_root);
342 }
343 #endif
344 #endif
345
346 static void videodev_proc_create_dev (struct video_device *vfd, char *name)
347 {
348         struct videodev_proc_data *d;
349         struct proc_dir_entry *p;
350
351         if (video_dev_proc_entry == NULL)
352                 return;
353
354         d = kmalloc (sizeof (struct videodev_proc_data), GFP_KERNEL);
355         if (!d)
356                 return;
357
358         p = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, video_dev_proc_entry);
359         if (!p)
360                 return;
361         p->data = vfd;
362         p->read_proc = videodev_proc_read;
363
364         d->proc_entry = p;
365         d->vdev = vfd;
366         strcpy (d->name, name);
367
368         /* How can I get capability information ? */
369
370         list_add (&d->proc_list, &videodev_proc_list);
371 }
372
373 static void videodev_proc_destroy_dev (struct video_device *vfd)
374 {
375         struct list_head *tmp;
376         struct videodev_proc_data *d;
377
378         list_for_each (tmp, &videodev_proc_list) {
379                 d = list_entry(tmp, struct videodev_proc_data, proc_list);
380                 if (vfd == d->vdev) {
381                         remove_proc_entry(d->name, video_dev_proc_entry);
382                         list_del (&d->proc_list);
383                         kfree(d);
384                         break;
385                 }
386         }
387 }
388
389 #endif /* CONFIG_VIDEO_PROC_FS */
390
391 extern struct file_operations video_fops;
392
393 /**
394  *      video_register_device - register video4linux devices
395  *      @vfd:  video device structure we want to register
396  *      @type: type of device to register
397  *      @nr:   which device number (0 == /dev/video0, 1 == /dev/video1, ...
398  *             -1 == first free)
399  *      
400  *      The registration code assigns minor numbers based on the type
401  *      requested. -ENFILE is returned in all the device slots for this
402  *      category are full. If not then the minor field is set and the
403  *      driver initialize function is called (if non %NULL).
404  *
405  *      Zero is returned on success.
406  *
407  *      Valid types are
408  *
409  *      %VFL_TYPE_GRABBER - A frame grabber
410  *
411  *      %VFL_TYPE_VTX - A teletext device
412  *
413  *      %VFL_TYPE_VBI - Vertical blank data (undecoded)
414  *
415  *      %VFL_TYPE_RADIO - A radio card  
416  */
417
418 static DECLARE_MUTEX(videodev_register_lock);
419
420 int video_register_device(struct video_device *vfd, int type, int nr)
421 {
422         int i=0;
423         int base;
424         int err;
425         int end;
426         char *name_base;
427         char name[16];
428         
429         switch(type)
430         {
431                 case VFL_TYPE_GRABBER:
432                         base=0;
433                         end=64;
434                         name_base = "video";
435                         break;
436                 case VFL_TYPE_VTX:
437                         base=192;
438                         end=224;
439                         name_base = "vtx";
440                         break;
441                 case VFL_TYPE_VBI:
442                         base=224;
443                         end=240;
444                         name_base = "vbi";
445                         break;
446                 case VFL_TYPE_RADIO:
447                         base=64;
448                         end=128;
449                         name_base = "radio";
450                         break;
451                 default:
452                         return -1;
453         }
454
455         /* pick a minor number */
456         down(&videodev_register_lock);
457         if (-1 == nr) {
458                 /* use first free */
459                 for(i=base;i<end;i++)
460                         if (NULL == video_device[i])
461                                 break;
462                 if (i == end) {
463                         up(&videodev_register_lock);
464                         return -ENFILE;
465                 }
466         } else {
467                 /* use the one the driver asked for */
468                 i = base+nr;
469                 if (NULL != video_device[i]) {
470                         up(&videodev_register_lock);
471                         return -ENFILE;
472                 }
473         }
474         video_device[i]=vfd;
475         vfd->minor=i;
476         up(&videodev_register_lock);
477
478         /* The init call may sleep so we book the slot out
479            then call */
480         MOD_INC_USE_COUNT;
481         if(vfd->initialize) {
482                 err=vfd->initialize(vfd);
483                 if(err<0) {
484                         video_device[i]=NULL;
485                         MOD_DEC_USE_COUNT;
486                         return err;
487                 }
488         }
489         sprintf (name, "v4l/%s%d", name_base, i - base);
490         /*
491          *      Start the device root only. Anything else
492          *      has serious privacy issues.
493          */
494         vfd->devfs_handle =
495                 devfs_register (NULL, name, DEVFS_FL_DEFAULT,
496                                 VIDEO_MAJOR, vfd->minor,
497                                 S_IFCHR | S_IRUSR | S_IWUSR,
498                                 &video_fops,
499                                 NULL);
500         
501 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
502         sprintf (name, "%s%d", name_base, i - base);
503         videodev_proc_create_dev (vfd, name);
504 #endif
505         return 0;
506 }
507
508 /**
509  *      video_unregister_device - unregister a video4linux device
510  *      @vfd: the device to unregister
511  *
512  *      This unregisters the passed device and deassigns the minor
513  *      number. Future open calls will be met with errors.
514  */
515  
516 void video_unregister_device(struct video_device *vfd)
517 {
518         if(video_device[vfd->minor]!=vfd)
519                 panic("vfd: bad unregister");
520
521 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
522         videodev_proc_destroy_dev (vfd);
523 #endif
524
525         devfs_unregister (vfd->devfs_handle);
526         video_device[vfd->minor]=NULL;
527         MOD_DEC_USE_COUNT;
528 }
529
530
531 static struct file_operations video_fops=
532 {
533         owner:          THIS_MODULE,
534         llseek:         no_llseek,
535         read:           video_read,
536         write:          video_write,
537         ioctl:          video_ioctl,
538         mmap:           video_mmap,
539         open:           video_open,
540         release:        video_release,
541         poll:           video_poll,
542 };
543
544 /*
545  *      Initialise video for linux
546  */
547  
548 static int __init videodev_init(void)
549 {
550         struct video_init *vfli = video_init_list;
551         
552         printk(KERN_INFO "Linux video capture interface: v1.00\n");
553         if(devfs_register_chrdev(VIDEO_MAJOR,"video_capture", &video_fops))
554         {
555                 printk("video_dev: unable to get major %d\n", VIDEO_MAJOR);
556                 return -EIO;
557         }
558
559         /*
560          *      Init kernel installed video drivers
561          */
562                 
563 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
564         videodev_proc_create ();
565 #endif
566         
567         while(vfli->init!=NULL)
568         {
569                 vfli->init(vfli);
570                 vfli++;
571         }
572         return 0;
573 }
574
575 static void __exit videodev_exit(void)
576 {
577 #ifdef MODULE           
578 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
579         videodev_proc_destroy ();
580 #endif
581 #endif
582         
583         devfs_unregister_chrdev(VIDEO_MAJOR, "video_capture");
584 }
585
586 module_init(videodev_init)
587 module_exit(videodev_exit)
588
589 EXPORT_SYMBOL(video_register_device);
590 EXPORT_SYMBOL(video_unregister_device);
591
592 MODULE_AUTHOR("Alan Cox");
593 MODULE_DESCRIPTION("Device registrar for Video4Linux drivers");
594
595 /*
596  * Local variables:
597  * c-basic-offset: 8
598  * End:
599  */