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