1 /*
2 * Video4Linux Colour QuickCam driver
3 * Copyright 1997-2000 Philip Blundell <philb@gnu.org>
4 *
5 * Module parameters:
6 *
7 * parport=auto -- probe all parports (default)
8 * parport=0 -- parport0 becomes qcam1
9 * parport=2,0,1 -- parports 2,0,1 are tried in that order
10 *
11 * probe=0 -- do no probing, assume camera is present
12 * probe=1 -- use IEEE-1284 autoprobe data only (default)
13 * probe=2 -- probe aggressively for cameras
14 *
15 * force_rgb=1 -- force data format to RGB (default is BGR)
16 *
17 * The parport parameter controls which parports will be scanned.
18 * Scanning all parports causes some printers to print a garbage page.
19 * -- March 14, 1999 Billy Donahue <billy@escape.com>
20 *
21 * Fixed data format to BGR, added force_rgb parameter. Added missing
22 * parport_unregister_driver() on module removal.
23 * -- May 28, 2000 Claudio Matsuoka <claudio@conectiva.com>
24 */
25
26 #include <linux/module.h>
27 #include <linux/delay.h>
28 #include <linux/errno.h>
29 #include <linux/fs.h>
30 #include <linux/init.h>
31 #include <linux/kernel.h>
32 #include <linux/malloc.h>
33 #include <linux/mm.h>
34 #include <linux/parport.h>
35 #include <linux/sched.h>
36 #include <linux/version.h>
37 #include <linux/videodev.h>
38 #include <asm/semaphore.h>
39 #include <asm/uaccess.h>
40
41 struct qcam_device {
42 struct video_device vdev;
43 struct pardevice *pdev;
44 struct parport *pport;
45 int width, height;
46 int ccd_width, ccd_height;
47 int mode;
48 int contrast, brightness, whitebal;
49 int top, left;
50 unsigned int bidirectional;
51 struct semaphore lock;
52 };
53
54 /* cameras maximum */
55 #define MAX_CAMS 4
56
57 /* The three possible QuickCam modes */
58 #define QC_MILLIONS 0x18
59 #define QC_BILLIONS 0x10
60 #define QC_THOUSANDS 0x08 /* with VIDEC compression (not supported) */
61
62 /* The three possible decimations */
63 #define QC_DECIMATION_1 0
64 #define QC_DECIMATION_2 2
65 #define QC_DECIMATION_4 4
66
67 #define BANNER "Colour QuickCam for Video4Linux v0.05"
68
69 static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
70 static int probe = 2;
71 static int force_rgb = 0;
72
73 static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
74 {
75 /* note: the QC specs refer to the PCAck pin by voltage, not
76 software level. PC ports have builtin inverters. */
77 parport_frob_control(qcam->pport, 8, i?8:0);
78 }
79
80 static inline unsigned int qcam_ready1(struct qcam_device *qcam)
81 {
82 return (parport_read_status(qcam->pport) & 0x8)?1:0;
83 }
84
85 static inline unsigned int qcam_ready2(struct qcam_device *qcam)
86 {
87 return (parport_read_data(qcam->pport) & 0x1)?1:0;
88 }
89
90 static unsigned int qcam_await_ready1(struct qcam_device *qcam,
91 int value)
92 {
93 unsigned long oldjiffies = jiffies;
94 unsigned int i;
95
96 for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); )
97 if (qcam_ready1(qcam) == value)
98 return 0;
99
100 /* If the camera didn't respond within 1/25 second, poll slowly
101 for a while. */
102 for (i = 0; i < 50; i++)
103 {
104 if (qcam_ready1(qcam) == value)
105 return 0;
106 current->state=TASK_INTERRUPTIBLE;
107 schedule_timeout(HZ/10);
108 }
109
110 /* Probably somebody pulled the plug out. Not much we can do. */
111 printk(KERN_ERR "c-qcam: ready1 timeout (%d) %x %x\n", value,
112 parport_read_status(qcam->pport),
113 parport_read_control(qcam->pport));
114 return 1;
115 }
116
117 static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
118 {
119 unsigned long oldjiffies = jiffies;
120 unsigned int i;
121
122 for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); )
123 if (qcam_ready2(qcam) == value)
124 return 0;
125
126 /* If the camera didn't respond within 1/25 second, poll slowly
127 for a while. */
128 for (i = 0; i < 50; i++)
129 {
130 if (qcam_ready2(qcam) == value)
131 return 0;
132 current->state=TASK_INTERRUPTIBLE;
133 schedule_timeout(HZ/10);
134 }
135
136 /* Probably somebody pulled the plug out. Not much we can do. */
137 printk(KERN_ERR "c-qcam: ready2 timeout (%d) %x %x %x\n", value,
138 parport_read_status(qcam->pport),
139 parport_read_control(qcam->pport),
140 parport_read_data(qcam->pport));
141 return 1;
142 }
143
144 static int qcam_read_data(struct qcam_device *qcam)
145 {
146 unsigned int idata;
147 qcam_set_ack(qcam, 0);
148 if (qcam_await_ready1(qcam, 1)) return -1;
149 idata = parport_read_status(qcam->pport) & 0xf0;
150 qcam_set_ack(qcam, 1);
151 if (qcam_await_ready1(qcam, 0)) return -1;
152 idata |= (parport_read_status(qcam->pport) >> 4);
153 return idata;
154 }
155
156 static int qcam_write_data(struct qcam_device *qcam, unsigned int data)
157 {
158 unsigned int idata;
159 parport_write_data(qcam->pport, data);
160 idata = qcam_read_data(qcam);
161 if (data != idata)
162 {
163 printk(KERN_WARNING "cqcam: sent %x but received %x\n", data,
164 idata);
165 return 1;
166 }
167 return 0;
168 }
169
170 static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned int data)
171 {
172 if (qcam_write_data(qcam, cmd))
173 return -1;
174 if (qcam_write_data(qcam, data))
175 return -1;
176 return 0;
177 }
178
179 static inline int qcam_get(struct qcam_device *qcam, unsigned int cmd)
180 {
181 if (qcam_write_data(qcam, cmd))
182 return -1;
183 return qcam_read_data(qcam);
184 }
185
186 static int qc_detect(struct qcam_device *qcam)
187 {
188 unsigned int stat, ostat, i, count = 0;
189
190 /* The probe routine below is not very reliable. The IEEE-1284
191 probe takes precedence. */
192 /* XXX Currently parport provides no way to distinguish between
193 "the IEEE probe was not done" and "the probe was done, but
194 no device was found". Fix this one day. */
195 if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
196 && qcam->pport->probe_info[0].model
197 && !strcmp(qcam->pdev->port->probe_info[0].model,
198 "Color QuickCam 2.0")) {
199 printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
200 return 1;
201 }
202
203 if (probe < 2)
204 return 0;
205
206 parport_write_control(qcam->pport, 0xc);
207
208 /* look for a heartbeat */
209 ostat = stat = parport_read_status(qcam->pport);
210 for (i=0; i<250; i++)
211 {
212 mdelay(1);
213 stat = parport_read_status(qcam->pport);
214 if (ostat != stat)
215 {
216 if (++count >= 3) return 1;
217 ostat = stat;
218 }
219 }
220
221 /* Reset the camera and try again */
222 parport_write_control(qcam->pport, 0xc);
223 parport_write_control(qcam->pport, 0x8);
224 mdelay(1);
225 parport_write_control(qcam->pport, 0xc);
226 mdelay(1);
227 count = 0;
228
229 ostat = stat = parport_read_status(qcam->pport);
230 for (i=0; i<250; i++)
231 {
232 mdelay(1);
233 stat = parport_read_status(qcam->pport);
234 if (ostat != stat)
235 {
236 if (++count >= 3) return 1;
237 ostat = stat;
238 }
239 }
240
241 /* no (or flatline) camera, give up */
242 return 0;
243 }
244
245 static void qc_reset(struct qcam_device *qcam)
246 {
247 parport_write_control(qcam->pport, 0xc);
248 parport_write_control(qcam->pport, 0x8);
249 mdelay(1);
250 parport_write_control(qcam->pport, 0xc);
251 mdelay(1);
252 }
253
254 /* Reset the QuickCam and program for brightness, contrast,
255 * white-balance, and resolution. */
256
257 static void qc_setup(struct qcam_device *q)
258 {
259 qc_reset(q);
260
261 /* Set the brightness. */
262 qcam_set(q, 11, q->brightness);
263
264 /* Set the height and width. These refer to the actual
265 CCD area *before* applying the selected decimation. */
266 qcam_set(q, 17, q->ccd_height);
267 qcam_set(q, 19, q->ccd_width / 2);
268
269 /* Set top and left. */
270 qcam_set(q, 0xd, q->top);
271 qcam_set(q, 0xf, q->left);
272
273 /* Set contrast and white balance. */
274 qcam_set(q, 0x19, q->contrast);
275 qcam_set(q, 0x1f, q->whitebal);
276
277 /* Set the speed. */
278 qcam_set(q, 45, 2);
279 }
280
281 /* Read some bytes from the camera and put them in the buffer.
282 nbytes should be a multiple of 3, because bidirectional mode gives
283 us three bytes at a time. */
284
285 static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, unsigned int nbytes)
286 {
287 unsigned int bytes = 0;
288
289 qcam_set_ack(q, 0);
290 if (q->bidirectional)
291 {
292 /* It's a bidirectional port */
293 while (bytes < nbytes)
294 {
295 unsigned int lo1, hi1, lo2, hi2;
296 unsigned char r, g, b;
297
298 if (qcam_await_ready2(q, 1)) return bytes;
299 lo1 = parport_read_data(q->pport) >> 1;
300 hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10;
301 qcam_set_ack(q, 1);
302 if (qcam_await_ready2(q, 0)) return bytes;
303 lo2 = parport_read_data(q->pport) >> 1;
304 hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10;
305 qcam_set_ack(q, 0);
306 r = (lo1 | ((hi1 & 1)<<7));
307 g = ((hi1 & 0x1e)<<3) | ((hi2 & 0x1e)>>1);
308 b = (lo2 | ((hi2 & 1)<<7));
309 if (force_rgb) {
310 buf[bytes++] = r;
311 buf[bytes++] = g;
312 buf[bytes++] = b;
313 } else {
314 buf[bytes++] = b;
315 buf[bytes++] = g;
316 buf[bytes++] = r;
317 }
318 }
319 }
320 else
321 {
322 /* It's a unidirectional port */
323 int i = 0, n = bytes;
324 unsigned char rgb[3];
325
326 while (bytes < nbytes)
327 {
328 unsigned int hi, lo;
329
330 if (qcam_await_ready1(q, 1)) return bytes;
331 hi = (parport_read_status(q->pport) & 0xf0);
332 qcam_set_ack(q, 1);
333 if (qcam_await_ready1(q, 0)) return bytes;
334 lo = (parport_read_status(q->pport) & 0xf0);
335 qcam_set_ack(q, 0);
336 /* flip some bits */
337 rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
338 if (i >= 2) {
339 get_fragment:
340 if (force_rgb) {
341 buf[n++] = rgb[0];
342 buf[n++] = rgb[1];
343 buf[n++] = rgb[2];
344 } else {
345 buf[n++] = rgb[2];
346 buf[n++] = rgb[1];
347 buf[n++] = rgb[0];
348 }
349 }
350 }
351 if (i) {
352 i = 0;
353 goto get_fragment;
354 }
355 }
356 return bytes;
357 }
358
359 #define BUFSZ 150
360
361 static long qc_capture(struct qcam_device *q, char *buf, unsigned long len)
362 {
363 unsigned lines, pixelsperline, bitsperxfer;
364 unsigned int is_bi_dir = q->bidirectional;
365 size_t wantlen, outptr = 0;
366 char tmpbuf[BUFSZ];
367
368 if (verify_area(VERIFY_WRITE, buf, len))
369 return -EFAULT;
370
371 /* Wait for camera to become ready */
372 for (;;)
373 {
374 int i = qcam_get(q, 41);
375 if (i == -1) {
376 qc_setup(q);
377 return -EIO;
378 }
379 if ((i & 0x80) == 0)
380 break;
381 else
382 schedule();
383 }
384
385 if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1))
386 return -EIO;
387
388 lines = q->height;
389 pixelsperline = q->width;
390 bitsperxfer = (is_bi_dir) ? 24 : 8;
391
392 if (is_bi_dir)
393 {
394 /* Turn the port around */
395 parport_data_reverse(q->pport);
396 mdelay(3);
397 qcam_set_ack(q, 0);
398 if (qcam_await_ready1(q, 1)) {
399 qc_setup(q);
400 return -EIO;
401 }
402 qcam_set_ack(q, 1);
403 if (qcam_await_ready1(q, 0)) {
404 qc_setup(q);
405 return -EIO;
406 }
407 }
408
409 wantlen = lines * pixelsperline * 24 / 8;
410
411 while (wantlen)
412 {
413 size_t t, s;
414 s = (wantlen > BUFSZ)?BUFSZ:wantlen;
415 t = qcam_read_bytes(q, tmpbuf, s);
416 if (outptr < len)
417 {
418 size_t sz = len - outptr;
419 if (sz > t) sz = t;
420 if (__copy_to_user(buf+outptr, tmpbuf, sz))
421 break;
422 outptr += sz;
423 }
424 wantlen -= t;
425 if (t < s)
426 break;
427 if (current->need_resched)
428 schedule();
429 }
430
431 len = outptr;
432
433 if (wantlen)
434 {
435 printk("qcam: short read.\n");
436 if (is_bi_dir)
437 parport_data_forward(q->pport);
438 qc_setup(q);
439 return len;
440 }
441
442 if (is_bi_dir)
443 {
444 int l;
445 do {
446 l = qcam_read_bytes(q, tmpbuf, 3);
447 if (current->need_resched)
448 schedule();
449 } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
450 if (force_rgb) {
451 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
452 printk("qcam: bad EOF\n");
453 } else {
454 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
455 printk("qcam: bad EOF\n");
456 }
457 qcam_set_ack(q, 0);
458 if (qcam_await_ready1(q, 1))
459 {
460 printk("qcam: no ack after EOF\n");
461 parport_data_forward(q->pport);
462 qc_setup(q);
463 return len;
464 }
465 parport_data_forward(q->pport);
466 mdelay(3);
467 qcam_set_ack(q, 1);
468 if (qcam_await_ready1(q, 0))
469 {
470 printk("qcam: no ack to port turnaround\n");
471 qc_setup(q);
472 return len;
473 }
474 }
475 else
476 {
477 int l;
478 do {
479 l = qcam_read_bytes(q, tmpbuf, 1);
480 if (current->need_resched)
481 schedule();
482 } while (l && tmpbuf[0] == 0x7e);
483 l = qcam_read_bytes(q, tmpbuf+1, 2);
484 if (force_rgb) {
485 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
486 printk("qcam: bad EOF\n");
487 } else {
488 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
489 printk("qcam: bad EOF\n");
490 }
491 }
492
493 qcam_write_data(q, 0);
494 return len;
495 }
496
497 /*
498 * Video4linux interfacing
499 */
500
501 static int qcam_open(struct video_device *dev, int flags)
502 {
503 MOD_INC_USE_COUNT;
504 return 0;
505 }
506
507 static void qcam_close(struct video_device *dev)
508 {
509 MOD_DEC_USE_COUNT;
510 }
511
512 static long qcam_write(struct video_device *v, const char *buf, unsigned long count, int noblock)
513 {
514 return -EINVAL;
515 }
516
517 static int qcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
518 {
519 struct qcam_device *qcam=(struct qcam_device *)dev;
520
521 switch(cmd)
522 {
523 case VIDIOCGCAP:
524 {
525 struct video_capability b;
526 strcpy(b.name, "Quickcam");
527 b.type = VID_TYPE_CAPTURE|VID_TYPE_SCALES;
528 b.channels = 1;
529 b.audios = 0;
530 b.maxwidth = 320;
531 b.maxheight = 240;
532 b.minwidth = 80;
533 b.minheight = 60;
534 if(copy_to_user(arg, &b,sizeof(b)))
535 return -EFAULT;
536 return 0;
537 }
538 case VIDIOCGCHAN:
539 {
540 struct video_channel v;
541 if(copy_from_user(&v, arg, sizeof(v)))
542 return -EFAULT;
543 if(v.channel!=0)
544 return -EINVAL;
545 v.flags=0;
546 v.tuners=0;
547 /* Good question.. its composite or SVHS so.. */
548 v.type = VIDEO_TYPE_CAMERA;
549 strcpy(v.name, "Camera");
550 if(copy_to_user(arg, &v, sizeof(v)))
551 return -EFAULT;
552 return 0;
553 }
554 case VIDIOCSCHAN:
555 {
556 int v;
557 if(copy_from_user(&v, arg,sizeof(v)))
558 return -EFAULT;
559 if(v!=0)
560 return -EINVAL;
561 return 0;
562 }
563 case VIDIOCGTUNER:
564 {
565 struct video_tuner v;
566 if(copy_from_user(&v, arg, sizeof(v))!=0)
567 return -EFAULT;
568 if(v.tuner)
569 return -EINVAL;
570 strcpy(v.name, "Format");
571 v.rangelow=0;
572 v.rangehigh=0;
573 v.flags= 0;
574 v.mode = VIDEO_MODE_AUTO;
575 if(copy_to_user(arg,&v,sizeof(v))!=0)
576 return -EFAULT;
577 return 0;
578 }
579 case VIDIOCSTUNER:
580 {
581 struct video_tuner v;
582 if(copy_from_user(&v, arg, sizeof(v))!=0)
583 return -EFAULT;
584 if(v.tuner)
585 return -EINVAL;
586 if(v.mode!=VIDEO_MODE_AUTO)
587 return -EINVAL;
588 return 0;
589 }
590 case VIDIOCGPICT:
591 {
592 struct video_picture p;
593 p.colour=0x8000;
594 p.hue=0x8000;
595 p.brightness=qcam->brightness<<8;
596 p.contrast=qcam->contrast<<8;
597 p.whiteness=qcam->whitebal<<8;
598 p.depth=24;
599 p.palette=VIDEO_PALETTE_RGB24;
600 if(copy_to_user(arg, &p, sizeof(p)))
601 return -EFAULT;
602 return 0;
603 }
604 case VIDIOCSPICT:
605 {
606 struct video_picture p;
607 if(copy_from_user(&p, arg, sizeof(p)))
608 return -EFAULT;
609
610 /*
611 * Sanity check args
612 */
613 if (p.depth != 24 || p.palette != VIDEO_PALETTE_RGB24)
614 return -EINVAL;
615
616 /*
617 * Now load the camera.
618 */
619 qcam->brightness = p.brightness>>8;
620 qcam->contrast = p.contrast>>8;
621 qcam->whitebal = p.whiteness>>8;
622
623 down(&qcam->lock);
624 parport_claim_or_block(qcam->pdev);
625 qc_setup(qcam);
626 parport_release(qcam->pdev);
627 up(&qcam->lock);
628 return 0;
629 }
630 case VIDIOCSWIN:
631 {
632 struct video_window vw;
633
634 if(copy_from_user(&vw, arg,sizeof(vw)))
635 return -EFAULT;
636 if(vw.flags)
637 return -EINVAL;
638 if(vw.clipcount)
639 return -EINVAL;
640 if(vw.height<60||vw.height>240)
641 return -EINVAL;
642 if(vw.width<80||vw.width>320)
643 return -EINVAL;
644
645 qcam->width = 80;
646 qcam->height = 60;
647 qcam->mode = QC_DECIMATION_4;
648
649 if(vw.width>=160 && vw.height>=120)
650 {
651 qcam->width = 160;
652 qcam->height = 120;
653 qcam->mode = QC_DECIMATION_2;
654 }
655 if(vw.width>=320 && vw.height>=240)
656 {
657 qcam->width = 320;
658 qcam->height = 240;
659 qcam->mode = QC_DECIMATION_1;
660 }
661 qcam->mode |= QC_MILLIONS;
662 #if 0
663 if(vw.width>=640 && vw.height>=480)
664 {
665 qcam->width = 640;
666 qcam->height = 480;
667 qcam->mode = QC_BILLIONS | QC_DECIMATION_1;
668 }
669 #endif
670 /* Ok we figured out what to use from our
671 wide choice */
672 down(&qcam->lock);
673 parport_claim_or_block(qcam->pdev);
674 qc_setup(qcam);
675 parport_release(qcam->pdev);
676 up(&qcam->lock);
677 return 0;
678 }
679 case VIDIOCGWIN:
680 {
681 struct video_window vw;
682 memset(&vw, 0, sizeof(vw));
683 vw.width=qcam->width;
684 vw.height=qcam->height;
685 if(copy_to_user(arg, &vw, sizeof(vw)))
686 return -EFAULT;
687 return 0;
688 }
689 case VIDIOCCAPTURE:
690 return -EINVAL;
691 case VIDIOCGFBUF:
692 return -EINVAL;
693 case VIDIOCSFBUF:
694 return -EINVAL;
695 case VIDIOCKEY:
696 return 0;
697 case VIDIOCGFREQ:
698 return -EINVAL;
699 case VIDIOCSFREQ:
700 return -EINVAL;
701 case VIDIOCGAUDIO:
702 return -EINVAL;
703 case VIDIOCSAUDIO:
704 return -EINVAL;
705 default:
706 return -ENOIOCTLCMD;
707 }
708 return 0;
709 }
710
711 static long qcam_read(struct video_device *v, char *buf, unsigned long count, int noblock)
712 {
713 struct qcam_device *qcam=(struct qcam_device *)v;
714 int len;
715
716 down(&qcam->lock);
717 parport_claim_or_block(qcam->pdev);
718 /* Probably should have a semaphore against multiple users */
719 len = qc_capture(qcam, buf,count);
720 parport_release(qcam->pdev);
721 up(&qcam->lock);
722 return len;
723 }
724
725 /* video device template */
726 static struct video_device qcam_template=
727 {
728 name: "Colour QuickCam",
729 type: VID_TYPE_CAPTURE,
730 hardware: VID_HARDWARE_QCAM_C,
731 open: qcam_open,
732 close: qcam_close,
733 read: qcam_read,
734 write: qcam_write,
735 ioctl: qcam_ioctl,
736 };
737
738 /* Initialize the QuickCam driver control structure. */
739
740 static struct qcam_device *qcam_init(struct parport *port)
741 {
742 struct qcam_device *q;
743
744 q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
745 if(q==NULL)
746 return NULL;
747
748 q->pport = port;
749 q->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
750 NULL, 0, NULL);
751
752 q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE)?1:0;
753
754 if (q->pdev == NULL)
755 {
756 printk(KERN_ERR "c-qcam: couldn't register for %s.\n",
757 port->name);
758 kfree(q);
759 return NULL;
760 }
761
762 memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
763
764 init_MUTEX(&q->lock);
765 q->width = q->ccd_width = 320;
766 q->height = q->ccd_height = 240;
767 q->mode = QC_MILLIONS | QC_DECIMATION_1;
768 q->contrast = 192;
769 q->brightness = 240;
770 q->whitebal = 128;
771 q->top = 1;
772 q->left = 14;
773 return q;
774 }
775
776 static struct qcam_device *qcams[MAX_CAMS];
777 static unsigned int num_cams = 0;
778
779 int init_cqcam(struct parport *port)
780 {
781 struct qcam_device *qcam;
782
783 if (parport[0] != -1)
784 {
785 /* The user gave specific instructions */
786 int i, found = 0;
787 for (i = 0; i < MAX_CAMS && parport[i] != -1; i++)
788 {
789 if (parport[0] == port->number)
790 found = 1;
791 }
792 if (!found)
793 return -ENODEV;
794 }
795
796 if (num_cams == MAX_CAMS)
797 return -ENOSPC;
798
799 qcam = qcam_init(port);
800 if (qcam==NULL)
801 return -ENODEV;
802
803 parport_claim_or_block(qcam->pdev);
804
805 qc_reset(qcam);
806
807 if (probe && qc_detect(qcam)==0)
808 {
809 parport_release(qcam->pdev);
810 parport_unregister_device(qcam->pdev);
811 kfree(qcam);
812 return -ENODEV;
813 }
814
815 qc_setup(qcam);
816
817 parport_release(qcam->pdev);
818
819 if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER)==-1)
820 {
821 printk(KERN_ERR "Unable to register Colour QuickCam on %s\n",
822 qcam->pport->name);
823 parport_unregister_device(qcam->pdev);
824 kfree(qcam);
825 return -ENODEV;
826 }
827
828 printk(KERN_INFO "video%d: Colour QuickCam found on %s\n",
829 qcam->vdev.minor, qcam->pport->name);
830
831 qcams[num_cams++] = qcam;
832
833 return 0;
834 }
835
836 void close_cqcam(struct qcam_device *qcam)
837 {
838 video_unregister_device(&qcam->vdev);
839 parport_unregister_device(qcam->pdev);
840 kfree(qcam);
841 }
842
843 static void cq_attach(struct parport *port)
844 {
845 init_cqcam(port);
846 }
847
848 static void cq_detach(struct parport *port)
849 {
850 /* Write this some day. */
851 }
852
853 static struct parport_driver cqcam_driver = {
854 "cqcam",
855 cq_attach,
856 cq_detach,
857 NULL
858 };
859
860 static int __init cqcam_init (void)
861 {
862 printk(BANNER "\n");
863
864 return parport_register_driver(&cqcam_driver);
865 }
866
867 static void __exit cqcam_cleanup (void)
868 {
869 unsigned int i;
870
871 for (i = 0; i < num_cams; i++)
872 close_cqcam(qcams[i]);
873
874 parport_unregister_driver(&cqcam_driver);
875 }
876
877 MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
878 MODULE_DESCRIPTION(BANNER);
879 MODULE_PARM_DESC(parport ,"parport=<auto|n[,n]...> for port detection method\n\
880 probe=<0|1|2> for camera detection method\n\
881 force_rgb=<0|1> for RGB data format (default BGR)");
882 MODULE_PARM(parport, "1-" __MODULE_STRING(MAX_CAMS) "i");
883 MODULE_PARM(probe, "i");
884 MODULE_PARM(force_rgb, "i");
885
886 module_init(cqcam_init);
887 module_exit(cqcam_cleanup);
888
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.