2 * Video4Linux: Colour QuickCam driver
4 * Philip Blundell <philb@gnu.org>, December 30 1997
6 * Largely untested (seems to work at 24bpp with a bidirectional port,
11 #include <linux/module.h>
12 #include <linux/config.h>
13 #include <linux/delay.h>
14 #include <linux/errno.h>
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/malloc.h>
20 #include <linux/parport.h>
21 #include <linux/sched.h>
22 #include <linux/version.h>
23 #include <linux/videodev.h>
24 #include <asm/uaccess.h>
28 static __inline__
void qcam_set_ack(struct qcam_device
*qcam
, unsigned int i
)
30 /* note: the QC specs refer to the PCAck pin by voltage, not
31 software level. PC ports have builtin inverters. */
32 parport_frob_control(qcam
->pport
, 8, i
?8:0);
35 static __inline__
unsigned int qcam_ready1(struct qcam_device
*qcam
)
37 return (parport_read_status(qcam
->pport
) & 0x8)?1:0;
41 static __inline__
unsigned int qcam_ready2(struct qcam_device
*qcam
)
43 return (parport_read_data(qcam
->pport
) & 0x1)?1:0;
46 static inline unsigned int qcam_await_ready1(struct qcam_device
*qcam
, int value
)
48 unsigned long oldjiffies
= jiffies
;
51 for (oldjiffies
= jiffies
; (jiffies
- oldjiffies
) < (HZ
/25); )
52 if (qcam_ready1(qcam
) == value
)
55 /* If the camera didn't respond within 1/25 second, poll slowly
57 for (i
= 0; i
< 50; i
++)
59 if (qcam_ready1(qcam
) == value
)
61 current
->state
=TASK_INTERRUPTIBLE
;
62 current
->timeout
= jiffies
+HZ
/10;
66 /* Probably somebody pulled the plug out. Not much we can do. */
67 printk(KERN_ERR
"c-qcam: ready1 timeout (%d) %x %x\n", value
,
68 parport_read_status(qcam
->pport
),
69 parport_read_control(qcam
->pport
));
73 static inline unsigned int qcam_await_ready2(struct qcam_device
*qcam
, int value
)
75 unsigned long oldjiffies
= jiffies
;
78 for (oldjiffies
= jiffies
; (jiffies
- oldjiffies
) < (HZ
/25); )
79 if (qcam_ready2(qcam
) == value
)
82 /* If the camera didn't respond within 1/25 second, poll slowly
84 for (i
= 0; i
< 50; i
++)
86 if (qcam_ready2(qcam
) == value
)
88 current
->state
=TASK_INTERRUPTIBLE
;
89 current
->timeout
= jiffies
+HZ
/10;
93 /* Probably somebody pulled the plug out. Not much we can do. */
94 printk(KERN_ERR
"c-qcam: ready2 timeout (%d) %x %x %x\n", value
,
95 parport_read_status(qcam
->pport
),
96 parport_read_control(qcam
->pport
),
97 parport_read_data(qcam
->pport
));
101 static inline int qcam_read_data(struct qcam_device
*qcam
)
104 qcam_set_ack(qcam
, 0);
105 if (qcam_await_ready1(qcam
, 1)) return -1;
106 idata
= parport_read_status(qcam
->pport
) & 0xf0;
107 qcam_set_ack(qcam
, 1);
108 if (qcam_await_ready1(qcam
, 0)) return -1;
109 idata
|= (parport_read_status(qcam
->pport
) >> 4);
113 static int qcam_write_data(struct qcam_device
*qcam
, unsigned int data
)
116 parport_write_data(qcam
->pport
, data
);
117 idata
= qcam_read_data(qcam
);
120 printk(KERN_WARNING
"cqcam: sent %x but received %x\n", data
,
127 static inline int qcam_set(struct qcam_device
*qcam
, unsigned int cmd
, unsigned int data
)
129 if (qcam_write_data(qcam
, cmd
))
131 if (qcam_write_data(qcam
, data
))
136 static inline int qcam_get(struct qcam_device
*qcam
, unsigned int cmd
)
138 if (qcam_write_data(qcam
, cmd
))
140 return qcam_read_data(qcam
);
143 static int qc_detect(struct qcam_device
*qcam
)
145 unsigned int stat
, ostat
, i
, count
= 0;
147 parport_write_control(qcam
->pport
, 0xc);
149 /* look for a heartbeat */
150 ostat
= stat
= parport_read_status(qcam
->pport
);
151 for (i
=0; i
<250; i
++)
154 stat
= parport_read_status(qcam
->pport
);
157 if (++count
>= 3) return 1;
162 /* no (or flatline) camera, give up */
166 static void qc_reset(struct qcam_device
*qcam
)
168 parport_write_control(qcam
->pport
, 0xc);
169 parport_write_control(qcam
->pport
, 0x8);
171 parport_write_control(qcam
->pport
, 0xc);
175 /* Reset the QuickCam and program for brightness, contrast,
176 * white-balance, and resolution. */
178 static void qc_setup(struct qcam_device
*q
)
182 /* Set the brightness. */
183 qcam_set(q
, 11, q
->brightness
);
185 /* Set the height. */
186 qcam_set(q
, 17, q
->height
);
189 qcam_set(q
, 19, q
->width
/2);
191 /* Set top and left. */
192 qcam_set(q
, 0xd, q
->top
);
193 qcam_set(q
, 0xf, q
->left
);
195 /* Set contrast and white balance. */
196 qcam_set(q
, 0x19, q
->contrast
);
197 qcam_set(q
, 0x1f, q
->whitebal
);
203 /* Read some bytes from the camera and put them in the buffer.
204 nbytes should be a multiple of 3, because bidirectional mode gives
205 us three bytes at a time. */
207 static unsigned int qcam_read_bytes(struct qcam_device
*q
, unsigned char *buf
, unsigned int nbytes
)
209 unsigned int bytes
= 0;
211 if (q
->bidirectional
)
213 /* It's a bidirectional port */
214 while (bytes
< nbytes
)
216 unsigned int lo1
, hi1
, lo2
, hi2
;
217 if (qcam_await_ready2(q
, 1)) return bytes
;
218 lo1
= parport_read_data(q
->pport
) >> 1;
219 hi1
= ((parport_read_status(q
->pport
) >> 3) & 0x1f) ^ 0x10;
221 if (qcam_await_ready2(q
, 0)) return bytes
;
222 lo2
= parport_read_data(q
->pport
) >> 1;
223 hi2
= ((parport_read_status(q
->pport
) >> 3) & 0x1f) ^ 0x10;
225 buf
[bytes
++] = (lo1
| ((hi1
& 1)<<7));
226 buf
[bytes
++] = ((hi1
& 0x1e)<<3) | ((hi2
& 0x1e)>>1);
227 buf
[bytes
++] = (lo2
| ((hi2
& 1)<<7));
232 /* It's a unidirectional port */
233 while (bytes
< nbytes
)
236 if (qcam_await_ready1(q
, 1)) return bytes
;
237 hi
= (parport_read_status(q
->pport
) & 0xf0);
239 if (qcam_await_ready1(q
, 0)) return bytes
;
240 lo
= (parport_read_status(q
->pport
) & 0xf0);
242 /* flip some bits; cqcam gets this wrong */
243 buf
[bytes
++] = (hi
| lo
) ^ 0x88;
249 /* Convert the data the camera gives us into the desired output format.
250 At the moment this is a no-op because read_bytes() does all the
251 required stuff, for 24bpp at least. */
252 static size_t qcam_munge_buffer(struct qcam_device
*q
, char *inbuf
, size_t inlen
, char *outbuf
, size_t outlen
)
258 while (inlen
&& (outptr
<= (outlen
-3)))
260 unsigned char r
, g
, b
;
264 put_user(r
, outbuf
+(outptr
++));
265 put_user(g
, outbuf
+(outptr
++));
266 put_user(b
, outbuf
+(outptr
++));
272 printk("c-qcam: can't convert this format (%d).\n", q
->bpp
);
278 static long qc_capture(struct qcam_device
*q
, char *buf
, unsigned long len
)
280 unsigned int tbpp
= 0, tdecimation
= 0, lines
, pixelsperline
, bitsperxfer
;
281 unsigned int is_bi_dir
= q
->bidirectional
;
282 size_t wantlen
, outptr
= 0;
283 char *tmpbuf
= kmalloc(768, GFP_KERNEL
);
286 printk(KERN_ERR
"cqcam: couldn't allocate a buffer.\n");
290 /* Wait for camera to become ready */
293 int i
= qcam_get(q
, 41);
307 case 24: tbpp
= QC_24BPP
; break;
308 case 32: tbpp
= QC_32BPP
; break;
309 case 16: tbpp
= QC_16BPP
; break;
310 default: printk("qcam: Bad bpp.\n");
312 switch (q
->transfer_scale
) {
313 case 1: tdecimation
= QC_1_1
; break;
314 case 2: tdecimation
= QC_2_1
; break;
315 case 4: tdecimation
= QC_4_1
; break;
316 default: printk("qcam: Bad decimation.\n");
319 qcam_set(q
, 7, (tbpp
| tdecimation
) + ((is_bi_dir
)?1:0) + 1);
321 lines
= q
->height
/ q
->transfer_scale
;
322 pixelsperline
= q
->width
/ q
->transfer_scale
;
323 bitsperxfer
= (is_bi_dir
) ? 24 : 8;
327 /* Turn the port around */
328 parport_frob_control(q
->pport
, 0x20, 0x20);
331 if (qcam_await_ready1(q
, 1)) {
337 if (qcam_await_ready1(q
, 0)) {
344 wantlen
= lines
* pixelsperline
* q
->bpp
/ 8;
349 s
= (wantlen
> 768)?768:wantlen
;
350 t
= qcam_read_bytes(q
, tmpbuf
, s
);
353 o
= qcam_munge_buffer(q
, tmpbuf
, t
, buf
+ outptr
,
368 printk("qcam: short read.\n");
370 parport_frob_control(q
->pport
, 0x20, 0);
380 l
= qcam_read_bytes(q
, tmpbuf
, 3);
383 } while (l
&& (tmpbuf
[0] == 0x7e || tmpbuf
[1] == 0x7e || tmpbuf
[2] == 0x7e));
384 if (tmpbuf
[0] != 0xe || tmpbuf
[1] != 0x0 || tmpbuf
[2] != 0xf)
385 printk("qcam: bad EOF\n");
387 if (qcam_await_ready1(q
, 1))
389 printk("qcam: no ack after EOF\n");
390 parport_frob_control(q
->pport
, 0x20, 0);
395 parport_frob_control(q
->pport
, 0x20, 0);
398 if (qcam_await_ready1(q
, 0))
400 printk("qcam: no ack to port turnaround\n");
410 l
= qcam_read_bytes(q
, tmpbuf
, 1);
413 } while (l
&& tmpbuf
[0] == 0x7e);
414 l
= qcam_read_bytes(q
, tmpbuf
+1, 2);
415 if (tmpbuf
[0] != 0xe || tmpbuf
[1] != 0x0 || tmpbuf
[2] != 0xf)
416 printk("qcam: bad EOF\n");
421 qcam_write_data(q
, 0);
427 * Video4linux interfacing
430 static int qcam_open(struct video_device
*dev
, int flags
)
436 static void qcam_close(struct video_device
*dev
)
441 static int qcam_init_done(struct video_device
*dev
)
446 static long qcam_write(struct video_device
*v
, const char *buf
, unsigned long count
, int noblock
)
451 static int qcam_ioctl(struct video_device
*dev
, unsigned int cmd
, void *arg
)
453 struct qcam_device
*qcam
=(struct qcam_device
*)dev
;
459 struct video_capability b
;
460 strcpy(b
.name
, "Quickcam");
461 b
.type
= VID_TYPE_CAPTURE
|VID_TYPE_SCALES
;
468 if(copy_to_user(arg
, &b
,sizeof(b
)))
474 struct video_channel v
;
475 if(copy_from_user(&v
, arg
, sizeof(v
)))
481 /* Good question.. its composite or SVHS so.. */
482 v
.type
= VIDEO_TYPE_CAMERA
;
483 strcpy(v
.name
, "Camera");
484 if(copy_to_user(arg
, &v
, sizeof(v
)))
491 if(copy_from_user(&v
, arg
,sizeof(v
)))
499 struct video_tuner v
;
500 if(copy_from_user(&v
, arg
, sizeof(v
))!=0)
504 strcpy(v
.name
, "Format");
508 v
.mode
= VIDEO_MODE_AUTO
;
509 if(copy_to_user(arg
,&v
,sizeof(v
))!=0)
515 struct video_tuner v
;
516 if(copy_from_user(&v
, arg
, sizeof(v
))!=0)
520 if(v
.mode
!=VIDEO_MODE_AUTO
)
526 struct video_picture p
;
529 p
.brightness
=qcam
->brightness
<<8;
530 p
.contrast
=qcam
->contrast
<<8;
531 p
.whiteness
=qcam
->whitebal
<<8;
533 p
.palette
=VIDEO_PALETTE_RGB24
;
534 if(copy_to_user(arg
, &p
, sizeof(p
)))
540 struct video_picture p
;
541 if(copy_from_user(&p
, arg
, sizeof(p
)))
544 if (p
.palette
!= VIDEO_PALETTE_RGB24
)
548 * Now load the camera.
550 qcam
->brightness
= p
.brightness
>>8;
551 qcam
->contrast
= p
.contrast
>>8;
552 qcam
->whitebal
= p
.whiteness
>>8;
555 parport_claim_or_block(qcam
->pdev
);
557 parport_release(qcam
->pdev
);
562 struct video_window vw
;
563 if(copy_from_user(&vw
, arg
,sizeof(vw
)))
569 if(vw
.height
<60||vw
.height
>240)
571 if(vw
.width
<80||vw
.width
>320)
576 qcam
->transfer_scale
= 4;
578 if(vw
.width
>=160 && vw
.height
>=120)
580 qcam
->transfer_scale
= 2;
582 if(vw
.width
>=320 && vw
.height
>=240)
586 qcam
->transfer_scale
= 1;
588 /* Ok we figured out what to use from our wide choice */
589 parport_claim_or_block(qcam
->pdev
);
591 parport_release(qcam
->pdev
);
596 struct video_window vw
;
599 vw
.width
=qcam
->width
/qcam
->transfer_scale
;
600 vw
.height
=qcam
->height
/qcam
->transfer_scale
;
603 if(copy_to_user(arg
, &vw
, sizeof(vw
)))
629 static long qcam_read(struct video_device
*v
, char *buf
, unsigned long count
, int noblock
)
631 struct qcam_device
*qcam
=(struct qcam_device
*)v
;
633 parport_claim_or_block(qcam
->pdev
);
634 /* Probably should have a semaphore against multiple users */
635 len
= qc_capture(qcam
, buf
,count
);
636 parport_release(qcam
->pdev
);
640 /* video device template */
641 static struct video_device qcam_template
=
658 /* Initialize the QuickCam driver control structure. */
660 static struct qcam_device
*qcam_init(struct parport
*port
)
662 struct qcam_device
*q
;
664 q
= kmalloc(sizeof(struct qcam_device
), GFP_KERNEL
);
667 q
->pdev
= parport_register_device(port
, "c-qcam", NULL
, NULL
,
670 q
->bidirectional
= (q
->pport
->modes
& PARPORT_MODE_PCPS2
)?1:0;
674 printk(KERN_ERR
"c-qcam: couldn't register for %s.\n",
680 memcpy(&q
->vdev
, &qcam_template
, sizeof(qcam_template
));
685 q
->transfer_scale
= 1;
695 static struct qcam_device
*qcams
[MAX_CAMS
];
696 static unsigned int num_cams
= 0;
698 int init_cqcam(struct parport
*port
)
700 struct qcam_device
*qcam
;
702 if (num_cams
== MAX_CAMS
)
704 printk(KERN_ERR
"Too many Quickcams (max %d)\n", MAX_CAMS
);
708 qcam
= qcam_init(port
);
712 parport_claim_or_block(qcam
->pdev
);
716 if (qc_detect(qcam
)==0)
718 parport_release(qcam
->pdev
);
719 parport_unregister_device(qcam
->pdev
);
726 parport_release(qcam
->pdev
);
728 printk(KERN_INFO
"Connectix Colour Quickcam on %s\n",
731 if (video_register_device(&qcam
->vdev
)==-1)
733 parport_unregister_device(qcam
->pdev
);
738 qcams
[num_cams
++] = qcam
;
743 void close_cqcam(struct qcam_device
*qcam
)
745 video_unregister_device(&qcam
->vdev
);
746 parport_unregister_device(qcam
->pdev
);
751 int init_module(void)
753 struct parport
*port
;
755 for (port
= parport_enumerate(); port
; port
=port
->next
)
758 return (num_cams
)?0:-ENODEV
;
761 void cleanup_module(void)
764 for (i
= 0; i
< num_cams
; i
++)
765 close_cqcam(qcams
[i
]);
768 __initfunc(int init_colour_qcams(struct video_init
*unused
))
770 struct parport
*port
;
772 for (port
= parport_enumerate(); port
; port
=port
->next
)