1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65#include <linux/module.h>
66#include <linux/delay.h>
67#include <linux/errno.h>
68#include <linux/fs.h>
69#include <linux/init.h>
70#include <linux/kernel.h>
71#include <linux/slab.h>
72#include <linux/mm.h>
73#include <linux/parport.h>
74#include <linux/sched.h>
75#include <linux/version.h>
76#include <linux/videodev.h>
77#include <asm/semaphore.h>
78#include <asm/uaccess.h>
79
80#include "bw-qcam.h"
81
82static unsigned int maxpoll=250;
83static unsigned int yieldlines=4;
84static int video_nr = -1;
85
86#if LINUX_VERSION_CODE >= 0x020117
87MODULE_PARM(maxpoll,"i");
88MODULE_PARM(yieldlines,"i");
89MODULE_PARM(video_nr,"i");
90#endif
91
92static inline int read_lpstatus(struct qcam_device *q)
93{
94 return parport_read_status(q->pport);
95}
96
97static inline int read_lpcontrol(struct qcam_device *q)
98{
99 return parport_read_control(q->pport);
100}
101
102static inline int read_lpdata(struct qcam_device *q)
103{
104 return parport_read_data(q->pport);
105}
106
107static inline void write_lpdata(struct qcam_device *q, int d)
108{
109 parport_write_data(q->pport, d);
110}
111
112static inline void write_lpcontrol(struct qcam_device *q, int d)
113{
114 parport_write_control(q->pport, d);
115}
116
117static int qc_waithand(struct qcam_device *q, int val);
118static int qc_command(struct qcam_device *q, int command);
119static int qc_readparam(struct qcam_device *q);
120static int qc_setscanmode(struct qcam_device *q);
121static int qc_readbytes(struct qcam_device *q, char buffer[]);
122
123static struct video_device qcam_template;
124
125static int qc_calibrate(struct qcam_device *q)
126{
127
128
129
130
131
132
133 int value;
134 int count = 0;
135
136 qc_command(q, 27);
137 qc_command(q, 0);
138
139
140
141
142
143 do {
144 qc_command(q, 33);
145 value = qc_readparam(q);
146 mdelay(1);
147 schedule();
148 count++;
149 } while (value == 0xff && count<2048);
150
151 q->whitebal = value;
152 return value;
153}
154
155
156
157
158static struct qcam_device *qcam_init(struct parport *port)
159{
160 struct qcam_device *q;
161
162 q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
163 if(q==NULL)
164 return NULL;
165
166 q->pport = port;
167 q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
168 NULL, 0, NULL);
169 if (q->pdev == NULL)
170 {
171 printk(KERN_ERR "bw-qcam: couldn't register for %s.\n",
172 port->name);
173 kfree(q);
174 return NULL;
175 }
176
177 memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
178
179 init_MUTEX(&q->lock);
180
181 q->port_mode = (QC_ANY | QC_NOTSET);
182 q->width = 320;
183 q->height = 240;
184 q->bpp = 4;
185 q->transfer_scale = 2;
186 q->contrast = 192;
187 q->brightness = 180;
188 q->whitebal = 105;
189 q->top = 1;
190 q->left = 14;
191 q->mode = -1;
192 q->status = QC_PARAM_CHANGE;
193 return q;
194}
195
196
197
198
199
200
201
202static int qc_command(struct qcam_device *q, int command)
203{
204 int n1, n2;
205 int cmd;
206
207 write_lpdata(q, command);
208 write_lpcontrol(q, 6);
209
210 n1 = qc_waithand(q, 1);
211
212 write_lpcontrol(q, 0xe);
213 n2 = qc_waithand(q, 0);
214
215 cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
216 return cmd;
217}
218
219static int qc_readparam(struct qcam_device *q)
220{
221 int n1, n2;
222 int cmd;
223
224 write_lpcontrol(q, 6);
225 n1 = qc_waithand(q, 1);
226
227 write_lpcontrol(q, 0xe);
228 n2 = qc_waithand(q, 0);
229
230 cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
231 return cmd;
232}
233
234
235
236
237static int qc_waithand(struct qcam_device *q, int val)
238{
239 int status;
240 int runs=0;
241
242 if (val)
243 {
244 while (!((status = read_lpstatus(q)) & 8))
245 {
246
247
248
249
250
251
252
253 if(runs++>maxpoll)
254 {
255 current->state=TASK_INTERRUPTIBLE;
256 schedule_timeout(HZ/200);
257 }
258 if(runs>(maxpoll+1000))
259 return -1;
260 }
261 }
262 else
263 {
264 while (((status = read_lpstatus(q)) & 8))
265 {
266
267
268
269
270
271
272
273 if(runs++>maxpoll)
274 {
275 current->state=TASK_INTERRUPTIBLE;
276 schedule_timeout(HZ/200);
277 }
278 if(runs++>(maxpoll+1000))
279 return -1;
280 }
281 }
282
283 return status;
284}
285
286
287
288
289
290
291static unsigned int qc_waithand2(struct qcam_device *q, int val)
292{
293 unsigned int status;
294 int runs=0;
295
296 do
297 {
298 status = read_lpdata(q);
299
300
301
302
303
304
305
306 if(runs++>maxpoll)
307 {
308 current->state=TASK_INTERRUPTIBLE;
309 schedule_timeout(HZ/200);
310 }
311 if(runs++>(maxpoll+1000))
312 return 0;
313 }
314 while ((status & 1) != val);
315
316 return status;
317}
318
319
320
321
322
323
324
325
326
327static int qc_detect(struct qcam_device *q)
328{
329 int reg, lastreg;
330 int count = 0;
331 int i;
332
333 lastreg = reg = read_lpstatus(q) & 0xf0;
334
335 for (i = 0; i < 500; i++)
336 {
337 reg = read_lpstatus(q) & 0xf0;
338 if (reg != lastreg)
339 count++;
340 lastreg = reg;
341 mdelay(2);
342 }
343
344
345#if 0
346
347
348
349
350 printk("Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count);
351 return 1;
352#endif
353
354
355
356
357 if (count > 20 && count < 300)
358 return 1;
359 else
360 return 0;
361}
362
363
364
365
366
367
368
369static void qc_reset(struct qcam_device *q)
370{
371 switch (q->port_mode & QC_FORCE_MASK)
372 {
373 case QC_FORCE_UNIDIR:
374 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
375 break;
376
377 case QC_FORCE_BIDIR:
378 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
379 break;
380
381 case QC_ANY:
382 write_lpcontrol(q, 0x20);
383 write_lpdata(q, 0x75);
384
385 if (read_lpdata(q) != 0x75) {
386 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
387 } else {
388 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
389 }
390 break;
391 }
392
393 write_lpcontrol(q, 0xb);
394 udelay(250);
395 write_lpcontrol(q, 0xe);
396 qc_setscanmode(q);
397}
398
399
400
401
402
403
404
405
406
407
408
409static int qc_setscanmode(struct qcam_device *q)
410{
411 int old_mode = q->mode;
412
413 switch (q->transfer_scale)
414 {
415 case 1:
416 q->mode = 0;
417 break;
418 case 2:
419 q->mode = 4;
420 break;
421 case 4:
422 q->mode = 8;
423 break;
424 }
425
426 switch (q->bpp)
427 {
428 case 4:
429 break;
430 case 6:
431 q->mode += 2;
432 break;
433 }
434
435 switch (q->port_mode & QC_MODE_MASK)
436 {
437 case QC_BIDIR:
438 q->mode += 1;
439 break;
440 case QC_NOTSET:
441 case QC_UNIDIR:
442 break;
443 }
444
445 if (q->mode != old_mode)
446 q->status |= QC_PARAM_CHANGE;
447
448 return 0;
449}
450
451
452
453
454
455void qc_set(struct qcam_device *q)
456{
457 int val;
458 int val2;
459
460 qc_reset(q);
461
462
463
464
465
466 qc_command(q, 0xb);
467 qc_command(q, q->brightness);
468
469 val = q->height / q->transfer_scale;
470 qc_command(q, 0x11);
471 qc_command(q, val);
472 if ((q->port_mode & QC_MODE_MASK) == QC_UNIDIR && q->bpp == 6) {
473
474
475
476
477
478 val = q->width;
479 val2 = q->transfer_scale * 4;
480 } else {
481 val = q->width * q->bpp;
482 val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
483 q->transfer_scale;
484 }
485 val = (val + val2 - 1) / val2;
486 qc_command(q, 0x13);
487 qc_command(q, val);
488
489
490 qc_command(q, 0xd);
491 qc_command(q, q->top);
492 qc_command(q, 0xf);
493 qc_command(q, q->left / 2);
494
495 qc_command(q, 0x19);
496 qc_command(q, q->contrast);
497 qc_command(q, 0x1f);
498 qc_command(q, q->whitebal);
499
500
501
502 q->status &= (~QC_PARAM_CHANGE);
503}
504
505
506
507
508
509static inline int qc_readbytes(struct qcam_device *q, char buffer[])
510{
511 int ret=1;
512 unsigned int hi, lo;
513 unsigned int hi2, lo2;
514 static int state = 0;
515
516 if (buffer == NULL)
517 {
518 state = 0;
519 return 0;
520 }
521
522 switch (q->port_mode & QC_MODE_MASK)
523 {
524 case QC_BIDIR:
525 write_lpcontrol(q, 0x26);
526 lo = (qc_waithand2(q, 1) >> 1);
527 hi = (read_lpstatus(q) >> 3) & 0x1f;
528 write_lpcontrol(q, 0x2e);
529 lo2 = (qc_waithand2(q, 0) >> 1);
530 hi2 = (read_lpstatus(q) >> 3) & 0x1f;
531 switch (q->bpp)
532 {
533 case 4:
534 buffer[0] = lo & 0xf;
535 buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3);
536 buffer[2] = (hi & 0x1e) >> 1;
537 buffer[3] = lo2 & 0xf;
538 buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3);
539 buffer[5] = (hi2 & 0x1e) >> 1;
540 ret = 6;
541 break;
542 case 6:
543 buffer[0] = lo & 0x3f;
544 buffer[1] = ((lo & 0x40) >> 6) | (hi << 1);
545 buffer[2] = lo2 & 0x3f;
546 buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1);
547 ret = 4;
548 break;
549 }
550 break;
551
552 case QC_UNIDIR:
553 write_lpcontrol(q, 6);
554 lo = (qc_waithand(q, 1) & 0xf0) >> 4;
555 write_lpcontrol(q, 0xe);
556 hi = (qc_waithand(q, 0) & 0xf0) >> 4;
557
558 switch (q->bpp)
559 {
560 case 4:
561 buffer[0] = lo;
562 buffer[1] = hi;
563 ret = 2;
564 break;
565 case 6:
566 switch (state)
567 {
568 case 0:
569 buffer[0] = (lo << 2) | ((hi & 0xc) >> 2);
570 q->saved_bits = (hi & 3) << 4;
571 state = 1;
572 ret = 1;
573 break;
574 case 1:
575 buffer[0] = lo | q->saved_bits;
576 q->saved_bits = hi << 2;
577 state = 2;
578 ret = 1;
579 break;
580 case 2:
581 buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits;
582 buffer[1] = ((lo & 3) << 4) | hi;
583 state = 0;
584 ret = 2;
585 break;
586 }
587 break;
588 }
589 break;
590 }
591 return ret;
592}
593
594
595
596
597
598
599
600
601
602
603
604
605long qc_capture(struct qcam_device * q, char *buf, unsigned long len)
606{
607 int i, j, k, yield;
608 int bytes;
609 int linestotrans, transperline;
610 int divisor;
611 int pixels_per_line;
612 int pixels_read = 0;
613 int got=0;
614 char buffer[6];
615 int shift=8-q->bpp;
616 char invert;
617
618 if (q->mode == -1)
619 return -ENXIO;
620
621 qc_command(q, 0x7);
622 qc_command(q, q->mode);
623
624 if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
625 {
626 write_lpcontrol(q, 0x2e);
627 write_lpcontrol(q, 0x26);
628 (void) qc_waithand(q, 1);
629 write_lpcontrol(q, 0x2e);
630 (void) qc_waithand(q, 0);
631 }
632
633
634 invert = (q->bpp == 4) ? 16 : 63;
635
636 linestotrans = q->height / q->transfer_scale;
637 pixels_per_line = q->width / q->transfer_scale;
638 transperline = q->width * q->bpp;
639 divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
640 q->transfer_scale;
641 transperline = (transperline + divisor - 1) / divisor;
642
643 for (i = 0, yield = yieldlines; i < linestotrans; i++)
644 {
645 for (pixels_read = j = 0; j < transperline; j++)
646 {
647 bytes = qc_readbytes(q, buffer);
648 for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++)
649 {
650 int o;
651 if (buffer[k] == 0 && invert == 16)
652 {
653
654
655 buffer[k] = 16;
656 }
657 o=i*pixels_per_line + pixels_read + k;
658 if(o<len)
659 {
660 got++;
661 put_user((invert - buffer[k])<<shift, buf+o);
662 }
663 }
664 pixels_read += bytes;
665 }
666 (void) qc_readbytes(q, 0);
667
668
669
670
671
672
673
674 if (i >= yield) {
675 current->state=TASK_INTERRUPTIBLE;
676 schedule_timeout(HZ/200);
677 yield = i + yieldlines;
678 }
679 }
680
681 if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
682 {
683 write_lpcontrol(q, 2);
684 write_lpcontrol(q, 6);
685 udelay(3);
686 write_lpcontrol(q, 0xe);
687 }
688 if(got<len)
689 return got;
690 return len;
691}
692
693
694
695
696
697static int qcam_open(struct video_device *dev, int flags)
698{
699 return 0;
700}
701
702static void qcam_close(struct video_device *dev)
703{
704}
705
706static long qcam_write(struct video_device *v, const char *buf, unsigned long count, int noblock)
707{
708 return -EINVAL;
709}
710
711static int qcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
712{
713 struct qcam_device *qcam=(struct qcam_device *)dev;
714
715 switch(cmd)
716 {
717 case VIDIOCGCAP:
718 {
719 struct video_capability b;
720 strcpy(b.name, "Quickcam");
721 b.type = VID_TYPE_CAPTURE|VID_TYPE_SCALES|VID_TYPE_MONOCHROME;
722 b.channels = 1;
723 b.audios = 0;
724 b.maxwidth = 320;
725 b.maxheight = 240;
726 b.minwidth = 80;
727 b.minheight = 60;
728 if(copy_to_user(arg, &b,sizeof(b)))
729 return -EFAULT;
730 return 0;
731 }
732 case VIDIOCGCHAN:
733 {
734 struct video_channel v;
735 if(copy_from_user(&v, arg, sizeof(v)))
736 return -EFAULT;
737 if(v.channel!=0)
738 return -EINVAL;
739 v.flags=0;
740 v.tuners=0;
741
742 v.type = VIDEO_TYPE_CAMERA;
743 strcpy(v.name, "Camera");
744 if(copy_to_user(arg, &v, sizeof(v)))
745 return -EFAULT;
746 return 0;
747 }
748 case VIDIOCSCHAN:
749 {
750 int v;
751 if(copy_from_user(&v, arg,sizeof(v)))
752 return -EFAULT;
753 if(v!=0)
754 return -EINVAL;
755 return 0;
756 }
757 case VIDIOCGTUNER:
758 {
759 struct video_tuner v;
760 if(copy_from_user(&v, arg, sizeof(v))!=0)
761 return -EFAULT;
762 if(v.tuner)
763 return -EINVAL;
764 strcpy(v.name, "Format");
765 v.rangelow=0;
766 v.rangehigh=0;
767 v.flags= 0;
768 v.mode = VIDEO_MODE_AUTO;
769 if(copy_to_user(arg,&v,sizeof(v))!=0)
770 return -EFAULT;
771 return 0;
772 }
773 case VIDIOCSTUNER:
774 {
775 struct video_tuner v;
776 if(copy_from_user(&v, arg, sizeof(v))!=0)
777 return -EFAULT;
778 if(v.tuner)
779 return -EINVAL;
780 if(v.mode!=VIDEO_MODE_AUTO)
781 return -EINVAL;
782 return 0;
783 }
784 case VIDIOCGPICT:
785 {
786 struct video_picture p;
787 p.colour=0x8000;
788 p.hue=0x8000;
789 p.brightness=qcam->brightness<<8;
790 p.contrast=qcam->contrast<<8;
791 p.whiteness=qcam->whitebal<<8;
792 p.depth=qcam->bpp;
793 p.palette=VIDEO_PALETTE_GREY;
794 if(copy_to_user(arg, &p, sizeof(p)))
795 return -EFAULT;
796 return 0;
797 }
798 case VIDIOCSPICT:
799 {
800 struct video_picture p;
801 if(copy_from_user(&p, arg, sizeof(p)))
802 return -EFAULT;
803 if(p.palette!=VIDEO_PALETTE_GREY)
804 return -EINVAL;
805 if(p.depth!=4 && p.depth!=6)
806 return -EINVAL;
807
808
809
810
811
812 qcam->brightness = p.brightness>>8;
813 qcam->contrast = p.contrast>>8;
814 qcam->whitebal = p.whiteness>>8;
815 qcam->bpp = p.depth;
816
817 down(&qcam->lock);
818 qc_setscanmode(qcam);
819 up(&qcam->lock);
820 qcam->status |= QC_PARAM_CHANGE;
821
822 return 0;
823 }
824 case VIDIOCSWIN:
825 {
826 struct video_window vw;
827 if(copy_from_user(&vw, arg,sizeof(vw)))
828 return -EFAULT;
829 if(vw.flags)
830 return -EINVAL;
831 if(vw.clipcount)
832 return -EINVAL;
833 if(vw.height<60||vw.height>240)
834 return -EINVAL;
835 if(vw.width<80||vw.width>320)
836 return -EINVAL;
837
838 qcam->width = 320;
839 qcam->height = 240;
840 qcam->transfer_scale = 4;
841
842 if(vw.width>=160 && vw.height>=120)
843 {
844 qcam->transfer_scale = 2;
845 }
846 if(vw.width>=320 && vw.height>=240)
847 {
848 qcam->width = 320;
849 qcam->height = 240;
850 qcam->transfer_scale = 1;
851 }
852 down(&qcam->lock);
853 qc_setscanmode(qcam);
854 up(&qcam->lock);
855
856
857
858 qcam->status |= QC_PARAM_CHANGE;
859
860
861 return 0;
862 }
863 case VIDIOCGWIN:
864 {
865 struct video_window vw;
866 memset(&vw, 0, sizeof(vw));
867 vw.width=qcam->width/qcam->transfer_scale;
868 vw.height=qcam->height/qcam->transfer_scale;
869 if(copy_to_user(arg, &vw, sizeof(vw)))
870 return -EFAULT;
871 return 0;
872 }
873 case VIDIOCCAPTURE:
874 return -EINVAL;
875 case VIDIOCGFBUF:
876 return -EINVAL;
877 case VIDIOCSFBUF:
878 return -EINVAL;
879 case VIDIOCKEY:
880 return 0;
881 case VIDIOCGFREQ:
882 return -EINVAL;
883 case VIDIOCSFREQ:
884 return -EINVAL;
885 case VIDIOCGAUDIO:
886 return -EINVAL;
887 case VIDIOCSAUDIO:
888 return -EINVAL;
889 default:
890 return -ENOIOCTLCMD;
891 }
892 return 0;
893}
894
895static long qcam_read(struct video_device *v, char *buf, unsigned long count, int noblock)
896{
897 struct qcam_device *qcam=(struct qcam_device *)v;
898 int len;
899 parport_claim_or_block(qcam->pdev);
900
901 down(&qcam->lock);
902
903 qc_reset(qcam);
904
905
906 if (qcam->status & QC_PARAM_CHANGE)
907 qc_set(qcam);
908
909 len=qc_capture(qcam, buf,count);
910
911 up(&qcam->lock);
912
913 parport_release(qcam->pdev);
914 return len;
915}
916
917static struct video_device qcam_template=
918{
919 owner: THIS_MODULE,
920 name: "Connectix Quickcam",
921 type: VID_TYPE_CAPTURE,
922 hardware: VID_HARDWARE_QCAM_BW,
923 open: qcam_open,
924 close: qcam_close,
925 read: qcam_read,
926 write: qcam_write,
927 ioctl: qcam_ioctl,
928};
929
930#define MAX_CAMS 4
931static struct qcam_device *qcams[MAX_CAMS];
932static unsigned int num_cams = 0;
933
934int init_bwqcam(struct parport *port)
935{
936 struct qcam_device *qcam;
937
938 if (num_cams == MAX_CAMS)
939 {
940 printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS);
941 return -ENOSPC;
942 }
943
944 qcam=qcam_init(port);
945 if(qcam==NULL)
946 return -ENODEV;
947
948 parport_claim_or_block(qcam->pdev);
949
950 qc_reset(qcam);
951
952 if(qc_detect(qcam)==0)
953 {
954 parport_release(qcam->pdev);
955 parport_unregister_device(qcam->pdev);
956 kfree(qcam);
957 return -ENODEV;
958 }
959 qc_calibrate(qcam);
960
961 parport_release(qcam->pdev);
962
963 printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name);
964
965 if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
966 {
967 parport_unregister_device(qcam->pdev);
968 kfree(qcam);
969 return -ENODEV;
970 }
971
972 qcams[num_cams++] = qcam;
973
974 return 0;
975}
976
977void close_bwqcam(struct qcam_device *qcam)
978{
979 video_unregister_device(&qcam->vdev);
980 parport_unregister_device(qcam->pdev);
981 kfree(qcam);
982}
983
984
985
986
987#ifdef MODULE
988static char *parport[MAX_CAMS] = { NULL, };
989MODULE_PARM(parport, "1-" __MODULE_STRING(MAX_CAMS) "s");
990#endif
991
992static void __exit exit_bw_qcams(void)
993{
994 unsigned int i;
995
996 for (i = 0; i < num_cams; i++)
997 close_bwqcam(qcams[i]);
998}
999
1000static int __init init_bw_qcams(void)
1001{
1002 struct parport *port;
1003#ifdef MODULE
1004 int n;
1005
1006 if(parport[0] && strncmp(parport[0], "auto", 4)){
1007
1008 for(n=0; parport[n] && n<MAX_CAMS; n++){
1009 char *ep;
1010 unsigned long r;
1011 r = simple_strtoul(parport[n], &ep, 0);
1012 if(ep == parport[n]){
1013 printk(KERN_ERR
1014 "bw-qcam: bad port specifier \"%s\"\n",
1015 parport[n]);
1016 continue;
1017 }
1018 for (port=parport_enumerate(); port; port=port->next){
1019 if(r!=port->number)
1020 continue;
1021 init_bwqcam(port);
1022 break;
1023 }
1024 }
1025 return (num_cams)?0:-ENODEV;
1026 }
1027
1028 for (port = parport_enumerate(); port; port=port->next)
1029 init_bwqcam(port);
1030
1031
1032 if (maxpoll > 5000) {
1033 printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n");
1034 maxpoll = 5000;
1035 }
1036
1037 if (yieldlines < 1) {
1038 printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n");
1039 yieldlines = 1;
1040 }
1041
1042 return (num_cams)?0:-ENODEV;
1043#else
1044 for (port = parport_enumerate(); port; port=port->next)
1045 init_bwqcam(port);
1046 return 0;
1047#endif
1048}
1049
1050module_init(init_bw_qcams);
1051module_exit(exit_bw_qcams);
1052
1053MODULE_LICENSE("GPL");
1054