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