Import 2.3.5
[davej-history.git] / drivers / char / videodev.c
blob141fcf1bcd1625cf10b0cd96f374870405da9f0b
1 /*
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:
17 #include <linux/config.h>
18 #include <linux/version.h>
19 #include <linux/module.h>
20 #include <linux/types.h>
21 #include <linux/kernel.h>
22 #include <linux/sched.h>
23 #include <linux/mm.h>
24 #include <linux/string.h>
25 #include <linux/errno.h>
26 #include <linux/videodev.h>
28 #if LINUX_VERSION_CODE >= 0x020100
29 #include <asm/uaccess.h>
30 #endif
31 #include <asm/system.h>
33 #include <linux/kmod.h>
36 #define VIDEO_NUM_DEVICES 256
39 * Active devices
42 static struct video_device *video_device[VIDEO_NUM_DEVICES];
44 #ifdef CONFIG_VIDEO_BT848
45 extern int init_bttv_cards(struct video_init *);
46 extern int i2c_tuner_init(struct video_init *);
47 #endif
48 #ifdef CONFIG_VIDEO_SAA5249
49 extern int init_saa_5249(struct video_init *);
50 #endif
51 #ifdef CONFIG_VIDEO_CQCAM
52 extern int init_colour_qcams(struct video_init *);
53 #endif
54 #ifdef CONFIG_VIDEO_BWQCAM
55 extern int init_bw_qcams(struct video_init *);
56 #endif
57 #ifdef CONFIG_VIDEO_PLANB
58 extern int init_planbs(struct video_init *);
59 #endif
60 #ifdef CONFIG_RADIO_AZTECH
61 extern int aztech_init(struct video_init *);
62 #endif
63 #ifdef CONFIG_RADIO_RTRACK
64 extern int rtrack_init(struct video_init *);
65 #endif
66 #ifdef CONFIG_RADIO_SF16FMI
67 extern int fmi_init(struct video_init *);
68 #endif
69 #ifdef CONFIG_RADIO_MIROPCM20
70 extern int pcm20_init(struct video_init *);
71 #endif
72 #ifdef CONFIG_RADIO_GEMTEK
73 extern int gemtek_init(struct video_init *);
74 #endif
75 #ifdef CONFIG_RADIO_TYPHOON
76 extern int typhoon_init(struct video_init *);
77 #endif
78 #ifdef CONFIG_RADIO_CADET
79 extern int cadet_init(struct video_init *);
80 #endif
81 #ifdef CONFIG_VIDEO_PMS
82 extern int init_pms_cards(struct video_init *);
83 #endif
85 static struct video_init video_init_list[]={
86 #ifdef CONFIG_VIDEO_BT848
87 {"i2c-tuner", i2c_tuner_init},
88 {"bttv", init_bttv_cards},
89 #endif
90 #ifdef CONFIG_VIDEO_SAA5249
91 {"saa5249", init_saa_5249},
92 #endif
93 #ifdef CONFIG_VIDEO_CQCAM
94 {"c-qcam", init_colour_qcams},
95 #endif
96 #ifdef CONFIG_VIDEO_BWQCAM
97 {"bw-qcam", init_bw_qcams},
98 #endif
99 #ifdef CONFIG_VIDEO_PMS
100 {"PMS", init_pms_cards},
101 #endif
102 #ifdef CONFIG_VIDEO_PLANB
103 {"planb", init_planbs},
104 #endif
105 #ifdef CONFIG_RADIO_AZTECH
106 {"Aztech", aztech_init},
107 #endif
108 #ifdef CONFIG_RADIO_RTRACK
109 {"RTrack", rtrack_init},
110 #endif
111 #ifdef CONFIG_RADIO_SF16FMI
112 {"SF16FMI", fmi_init},
113 #endif
114 #ifdef CONFIG_RADIO_MIROPCM20
115 {"PCM20", pcm20_init},
116 #endif
117 #ifdef CONFIG_RADIO_CADET
118 {"Cadet", cadet_init},
119 #endif
120 #ifdef CONFIG_RADIO_GEMTEK
121 {"GemTek", gemtek_init},
122 #endif
123 #ifdef CONFIG_RADIO_TYPHOON
124 {"radio-typhoon", typhoon_init},
125 #endif
126 {"end", NULL}
129 #if LINUX_VERSION_CODE >= 0x020100
131 * Read will do some smarts later on. Buffer pin etc.
134 static ssize_t video_read(struct file *file,
135 char *buf, size_t count, loff_t *ppos)
137 struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
138 if(vfl->read)
139 return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
140 else
141 return -EINVAL;
147 * Write for now does nothing. No reason it shouldnt do overlay setting
148 * for some boards I guess..
151 static ssize_t video_write(struct file *file, const char *buf,
152 size_t count, loff_t *ppos)
154 struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
155 if(vfl->write)
156 return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK);
157 else
158 return 0;
162 * Poll to see if we're readable, can probably be used for timing on incoming
163 * frames, etc..
166 static unsigned int video_poll(struct file *file, poll_table * wait)
168 struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
169 if(vfl->poll)
170 return vfl->poll(vfl, file, wait);
171 else
172 return 0;
176 #else
177 static int video_read(struct inode *ino,struct file *file,
178 char *buf, int count)
180 int err;
181 struct video_device *vfl=video_device[MINOR(ino->i_rdev)];
182 if (vfl->read)
183 return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
184 else
185 return -EINVAL;
188 static int video_write(struct inode *ino,struct file *file, const char *buf,
189 int count)
191 int err;
192 struct video_device *vfl=video_device[MINOR(ino->i_rdev)];
193 if (vfl->write)
194 return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK);
195 else
196 return 0;
199 #endif
202 * Open a video device.
205 static int video_open(struct inode *inode, struct file *file)
207 unsigned int minor = MINOR(inode->i_rdev);
208 int err;
209 struct video_device *vfl;
211 if(minor>=VIDEO_NUM_DEVICES)
212 return -ENODEV;
214 vfl=video_device[minor];
215 if(vfl==NULL) {
216 char modname[20];
218 sprintf (modname, "char-major-%d-%d", VIDEO_MAJOR, minor);
219 request_module(modname);
220 vfl=video_device[minor];
221 if (vfl==NULL)
222 return -ENODEV;
224 if(vfl->busy)
225 return -EBUSY;
226 vfl->busy=1; /* In case vfl->open sleeps */
228 if(vfl->open)
230 err=vfl->open(vfl,0); /* Tell the device it is open */
231 if(err)
233 vfl->busy=0;
234 return err;
237 return 0;
241 * Last close of a video for Linux device
244 static int video_release(struct inode *inode, struct file *file)
246 struct video_device *vfl=video_device[MINOR(inode->i_rdev)];
247 if(vfl->close)
248 vfl->close(vfl);
249 vfl->busy=0;
250 return 0;
254 * Question: Should we be able to capture and then seek around the
255 * image ?
258 #if LINUX_VERSION_CODE >= 0x020100
259 static long long video_lseek(struct file * file,
260 long long offset, int origin)
262 return -ESPIPE;
264 #else
265 static long long video_lseek(struct inode *inode, struct file * file,
266 long long offset, int origin)
268 return -ESPIPE;
270 #endif
273 static int video_ioctl(struct inode *inode, struct file *file,
274 unsigned int cmd, unsigned long arg)
276 struct video_device *vfl=video_device[MINOR(inode->i_rdev)];
277 int err=vfl->ioctl(vfl, cmd, (void *)arg);
279 if(err!=-ENOIOCTLCMD)
280 return err;
282 switch(cmd)
284 default:
285 return -EINVAL;
290 * We need to do MMAP support
294 #if LINUX_VERSION_CODE >= 0x020100
295 int video_mmap(struct file *file, struct vm_area_struct *vma)
297 struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
298 #else
299 static int video_mmap(struct inode * ino, struct file * file,
300 struct vm_area_struct * vma)
302 struct video_device *vfl=video_device[MINOR(ino->i_rdev)];
303 #endif
304 if(vfl->mmap)
305 return vfl->mmap(vfl, (char *)vma->vm_start,
306 (unsigned long)(vma->vm_end-vma->vm_start));
307 return -EINVAL;
311 * Video For Linux device drivers request registration here.
314 int video_register_device(struct video_device *vfd, int type)
316 int i=0;
317 int base;
318 int err;
319 int end;
321 switch(type)
323 case VFL_TYPE_GRABBER:
324 base=0;
325 end=64;
326 break;
327 case VFL_TYPE_VTX:
328 base=192;
329 end=224;
330 break;
331 case VFL_TYPE_VBI:
332 base=224;
333 end=240;
334 break;
335 case VFL_TYPE_RADIO:
336 base=64;
337 end=128;
338 break;
339 default:
340 return -1;
343 for(i=base;i<end;i++)
345 if(video_device[i]==NULL)
347 video_device[i]=vfd;
348 vfd->minor=i;
349 /* The init call may sleep so we book the slot out
350 then call */
351 MOD_INC_USE_COUNT;
352 if(vfd->initialize)
354 err=vfd->initialize(vfd);
355 if(err<0)
357 video_device[i]=NULL;
358 MOD_DEC_USE_COUNT;
359 return err;
362 return 0;
365 return -ENFILE;
369 * Unregister an unused video for linux device
372 void video_unregister_device(struct video_device *vfd)
374 if(video_device[vfd->minor]!=vfd)
375 panic("vfd: bad unregister");
376 video_device[vfd->minor]=NULL;
377 MOD_DEC_USE_COUNT;
381 static struct file_operations video_fops=
383 video_lseek,
384 video_read,
385 video_write,
386 NULL, /* readdir */
387 #if LINUX_VERSION_CODE >= 0x020100
388 video_poll, /* poll */
389 #else
390 NULL,
391 #endif
392 video_ioctl,
393 video_mmap,
394 video_open,
395 #if LINUX_VERSION_CODE >= 0x020100
396 NULL, /* flush */
397 #endif
398 video_release
402 * Initialise video for linux
405 int videodev_init(void)
407 struct video_init *vfli = video_init_list;
409 printk(KERN_INFO "Linux video capture interface: v1.00\n");
410 if(register_chrdev(VIDEO_MAJOR,"video_capture", &video_fops))
412 printk("video_dev: unable to get major %d\n", VIDEO_MAJOR);
413 return -EIO;
417 * Init kernel installed video drivers
420 while(vfli->init!=NULL)
422 vfli->init(vfli);
423 vfli++;
425 return 0;
428 #ifdef MODULE
429 int init_module(void)
431 return videodev_init();
434 void cleanup_module(void)
436 unregister_chrdev(VIDEO_MAJOR, "video_capture");
445 #endif
447 #if LINUX_VERSION_CODE >= 0x020100
448 EXPORT_SYMBOL(video_register_device);
449 EXPORT_SYMBOL(video_unregister_device);
450 #endif