2 * Video4Linux Colour QuickCam driver
3 * Copyright 1997-2000 Philip Blundell <philb@gnu.org>
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
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
15 * force_rgb=1 -- force data format to RGB (default is BGR)
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>
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>
26 #include <linux/module.h>
27 #include <linux/delay.h>
28 #include <linux/errno.h>
30 #include <linux/init.h>
31 #include <linux/kernel.h>
32 #include <linux/slab.h>
34 #include <linux/parport.h>
35 #include <linux/sched.h>
36 #include <linux/mutex.h>
37 #include <linux/jiffies.h>
38 #include <linux/version.h>
39 #include <linux/videodev2.h>
40 #include <asm/uaccess.h>
41 #include <media/v4l2-device.h>
42 #include <media/v4l2-common.h>
43 #include <media/v4l2-ioctl.h>
46 struct v4l2_device v4l2_dev
;
47 struct video_device vdev
;
48 struct pardevice
*pdev
;
49 struct parport
*pport
;
51 int ccd_width
, ccd_height
;
53 int contrast
, brightness
, whitebal
;
55 unsigned int bidirectional
;
62 /* The three possible QuickCam modes */
63 #define QC_MILLIONS 0x18
64 #define QC_BILLIONS 0x10
65 #define QC_THOUSANDS 0x08 /* with VIDEC compression (not supported) */
67 /* The three possible decimations */
68 #define QC_DECIMATION_1 0
69 #define QC_DECIMATION_2 2
70 #define QC_DECIMATION_4 4
72 #define BANNER "Colour QuickCam for Video4Linux v0.06"
74 static int parport
[MAX_CAMS
] = { [1 ... MAX_CAMS
-1] = -1 };
77 static int video_nr
= -1;
79 /* FIXME: parport=auto would never have worked, surely? --RR */
80 MODULE_PARM_DESC(parport
, "parport=<auto|n[,n]...> for port detection method\n"
81 "probe=<0|1|2> for camera detection method\n"
82 "force_rgb=<0|1> for RGB data format (default BGR)");
83 module_param_array(parport
, int, NULL
, 0);
84 module_param(probe
, int, 0);
85 module_param(force_rgb
, bool, 0);
86 module_param(video_nr
, int, 0);
88 static struct qcam
*qcams
[MAX_CAMS
];
89 static unsigned int num_cams
;
91 static inline void qcam_set_ack(struct qcam
*qcam
, unsigned int i
)
93 /* note: the QC specs refer to the PCAck pin by voltage, not
94 software level. PC ports have builtin inverters. */
95 parport_frob_control(qcam
->pport
, 8, i
? 8 : 0);
98 static inline unsigned int qcam_ready1(struct qcam
*qcam
)
100 return (parport_read_status(qcam
->pport
) & 0x8) ? 1 : 0;
103 static inline unsigned int qcam_ready2(struct qcam
*qcam
)
105 return (parport_read_data(qcam
->pport
) & 0x1) ? 1 : 0;
108 static unsigned int qcam_await_ready1(struct qcam
*qcam
, int value
)
110 struct v4l2_device
*v4l2_dev
= &qcam
->v4l2_dev
;
111 unsigned long oldjiffies
= jiffies
;
114 for (oldjiffies
= jiffies
;
115 time_before(jiffies
, oldjiffies
+ msecs_to_jiffies(40));)
116 if (qcam_ready1(qcam
) == value
)
119 /* If the camera didn't respond within 1/25 second, poll slowly
121 for (i
= 0; i
< 50; i
++) {
122 if (qcam_ready1(qcam
) == value
)
124 msleep_interruptible(100);
127 /* Probably somebody pulled the plug out. Not much we can do. */
128 v4l2_err(v4l2_dev
, "ready1 timeout (%d) %x %x\n", value
,
129 parport_read_status(qcam
->pport
),
130 parport_read_control(qcam
->pport
));
134 static unsigned int qcam_await_ready2(struct qcam
*qcam
, int value
)
136 struct v4l2_device
*v4l2_dev
= &qcam
->v4l2_dev
;
137 unsigned long oldjiffies
= jiffies
;
140 for (oldjiffies
= jiffies
;
141 time_before(jiffies
, oldjiffies
+ msecs_to_jiffies(40));)
142 if (qcam_ready2(qcam
) == value
)
145 /* If the camera didn't respond within 1/25 second, poll slowly
147 for (i
= 0; i
< 50; i
++) {
148 if (qcam_ready2(qcam
) == value
)
150 msleep_interruptible(100);
153 /* Probably somebody pulled the plug out. Not much we can do. */
154 v4l2_err(v4l2_dev
, "ready2 timeout (%d) %x %x %x\n", value
,
155 parport_read_status(qcam
->pport
),
156 parport_read_control(qcam
->pport
),
157 parport_read_data(qcam
->pport
));
161 static int qcam_read_data(struct qcam
*qcam
)
165 qcam_set_ack(qcam
, 0);
166 if (qcam_await_ready1(qcam
, 1))
168 idata
= parport_read_status(qcam
->pport
) & 0xf0;
169 qcam_set_ack(qcam
, 1);
170 if (qcam_await_ready1(qcam
, 0))
172 idata
|= parport_read_status(qcam
->pport
) >> 4;
176 static int qcam_write_data(struct qcam
*qcam
, unsigned int data
)
178 struct v4l2_device
*v4l2_dev
= &qcam
->v4l2_dev
;
181 parport_write_data(qcam
->pport
, data
);
182 idata
= qcam_read_data(qcam
);
184 v4l2_warn(v4l2_dev
, "sent %x but received %x\n", data
,
191 static inline int qcam_set(struct qcam
*qcam
, unsigned int cmd
, unsigned int data
)
193 if (qcam_write_data(qcam
, cmd
))
195 if (qcam_write_data(qcam
, data
))
200 static inline int qcam_get(struct qcam
*qcam
, unsigned int cmd
)
202 if (qcam_write_data(qcam
, cmd
))
204 return qcam_read_data(qcam
);
207 static int qc_detect(struct qcam
*qcam
)
209 unsigned int stat
, ostat
, i
, count
= 0;
211 /* The probe routine below is not very reliable. The IEEE-1284
212 probe takes precedence. */
213 /* XXX Currently parport provides no way to distinguish between
214 "the IEEE probe was not done" and "the probe was done, but
215 no device was found". Fix this one day. */
216 if (qcam
->pport
->probe_info
[0].class == PARPORT_CLASS_MEDIA
217 && qcam
->pport
->probe_info
[0].model
218 && !strcmp(qcam
->pdev
->port
->probe_info
[0].model
,
219 "Color QuickCam 2.0")) {
220 printk(KERN_DEBUG
"QuickCam: Found by IEEE1284 probe.\n");
227 parport_write_control(qcam
->pport
, 0xc);
229 /* look for a heartbeat */
230 ostat
= stat
= parport_read_status(qcam
->pport
);
231 for (i
= 0; i
< 250; i
++) {
233 stat
= parport_read_status(qcam
->pport
);
241 /* Reset the camera and try again */
242 parport_write_control(qcam
->pport
, 0xc);
243 parport_write_control(qcam
->pport
, 0x8);
245 parport_write_control(qcam
->pport
, 0xc);
249 ostat
= stat
= parport_read_status(qcam
->pport
);
250 for (i
= 0; i
< 250; i
++) {
252 stat
= parport_read_status(qcam
->pport
);
260 /* no (or flatline) camera, give up */
264 static void qc_reset(struct qcam
*qcam
)
266 parport_write_control(qcam
->pport
, 0xc);
267 parport_write_control(qcam
->pport
, 0x8);
269 parport_write_control(qcam
->pport
, 0xc);
273 /* Reset the QuickCam and program for brightness, contrast,
274 * white-balance, and resolution. */
276 static void qc_setup(struct qcam
*qcam
)
280 /* Set the brightness. */
281 qcam_set(qcam
, 11, qcam
->brightness
);
283 /* Set the height and width. These refer to the actual
284 CCD area *before* applying the selected decimation. */
285 qcam_set(qcam
, 17, qcam
->ccd_height
);
286 qcam_set(qcam
, 19, qcam
->ccd_width
/ 2);
288 /* Set top and left. */
289 qcam_set(qcam
, 0xd, qcam
->top
);
290 qcam_set(qcam
, 0xf, qcam
->left
);
292 /* Set contrast and white balance. */
293 qcam_set(qcam
, 0x19, qcam
->contrast
);
294 qcam_set(qcam
, 0x1f, qcam
->whitebal
);
297 qcam_set(qcam
, 45, 2);
300 /* Read some bytes from the camera and put them in the buffer.
301 nbytes should be a multiple of 3, because bidirectional mode gives
302 us three bytes at a time. */
304 static unsigned int qcam_read_bytes(struct qcam
*qcam
, unsigned char *buf
, unsigned int nbytes
)
306 unsigned int bytes
= 0;
308 qcam_set_ack(qcam
, 0);
309 if (qcam
->bidirectional
) {
310 /* It's a bidirectional port */
311 while (bytes
< nbytes
) {
312 unsigned int lo1
, hi1
, lo2
, hi2
;
313 unsigned char r
, g
, b
;
315 if (qcam_await_ready2(qcam
, 1))
317 lo1
= parport_read_data(qcam
->pport
) >> 1;
318 hi1
= ((parport_read_status(qcam
->pport
) >> 3) & 0x1f) ^ 0x10;
319 qcam_set_ack(qcam
, 1);
320 if (qcam_await_ready2(qcam
, 0))
322 lo2
= parport_read_data(qcam
->pport
) >> 1;
323 hi2
= ((parport_read_status(qcam
->pport
) >> 3) & 0x1f) ^ 0x10;
324 qcam_set_ack(qcam
, 0);
325 r
= lo1
| ((hi1
& 1) << 7);
326 g
= ((hi1
& 0x1e) << 3) | ((hi2
& 0x1e) >> 1);
327 b
= lo2
| ((hi2
& 1) << 7);
339 /* It's a unidirectional port */
340 int i
= 0, n
= bytes
;
341 unsigned char rgb
[3];
343 while (bytes
< nbytes
) {
346 if (qcam_await_ready1(qcam
, 1))
348 hi
= (parport_read_status(qcam
->pport
) & 0xf0);
349 qcam_set_ack(qcam
, 1);
350 if (qcam_await_ready1(qcam
, 0))
352 lo
= (parport_read_status(qcam
->pport
) & 0xf0);
353 qcam_set_ack(qcam
, 0);
355 rgb
[(i
= bytes
++ % 3)] = (hi
| (lo
>> 4)) ^ 0x88;
379 static long qc_capture(struct qcam
*qcam
, char __user
*buf
, unsigned long len
)
381 struct v4l2_device
*v4l2_dev
= &qcam
->v4l2_dev
;
382 unsigned lines
, pixelsperline
, bitsperxfer
;
383 unsigned int is_bi_dir
= qcam
->bidirectional
;
384 size_t wantlen
, outptr
= 0;
387 if (!access_ok(VERIFY_WRITE
, buf
, len
))
390 /* Wait for camera to become ready */
392 int i
= qcam_get(qcam
, 41);
403 if (qcam_set(qcam
, 7, (qcam
->mode
| (is_bi_dir
? 1 : 0)) + 1))
406 lines
= qcam
->height
;
407 pixelsperline
= qcam
->width
;
408 bitsperxfer
= (is_bi_dir
) ? 24 : 8;
411 /* Turn the port around */
412 parport_data_reverse(qcam
->pport
);
414 qcam_set_ack(qcam
, 0);
415 if (qcam_await_ready1(qcam
, 1)) {
419 qcam_set_ack(qcam
, 1);
420 if (qcam_await_ready1(qcam
, 0)) {
426 wantlen
= lines
* pixelsperline
* 24 / 8;
431 s
= (wantlen
> BUFSZ
) ? BUFSZ
: wantlen
;
432 t
= qcam_read_bytes(qcam
, tmpbuf
, s
);
434 size_t sz
= len
- outptr
;
438 if (__copy_to_user(buf
+ outptr
, tmpbuf
, sz
))
451 v4l2_err(v4l2_dev
, "short read.\n");
453 parport_data_forward(qcam
->pport
);
462 l
= qcam_read_bytes(qcam
, tmpbuf
, 3);
464 } while (l
&& (tmpbuf
[0] == 0x7e || tmpbuf
[1] == 0x7e || tmpbuf
[2] == 0x7e));
466 if (tmpbuf
[0] != 0xe || tmpbuf
[1] != 0x0 || tmpbuf
[2] != 0xf)
467 v4l2_err(v4l2_dev
, "bad EOF\n");
469 if (tmpbuf
[0] != 0xf || tmpbuf
[1] != 0x0 || tmpbuf
[2] != 0xe)
470 v4l2_err(v4l2_dev
, "bad EOF\n");
472 qcam_set_ack(qcam
, 0);
473 if (qcam_await_ready1(qcam
, 1)) {
474 v4l2_err(v4l2_dev
, "no ack after EOF\n");
475 parport_data_forward(qcam
->pport
);
479 parport_data_forward(qcam
->pport
);
481 qcam_set_ack(qcam
, 1);
482 if (qcam_await_ready1(qcam
, 0)) {
483 v4l2_err(v4l2_dev
, "no ack to port turnaround\n");
491 l
= qcam_read_bytes(qcam
, tmpbuf
, 1);
493 } while (l
&& tmpbuf
[0] == 0x7e);
494 l
= qcam_read_bytes(qcam
, tmpbuf
+ 1, 2);
496 if (tmpbuf
[0] != 0xe || tmpbuf
[1] != 0x0 || tmpbuf
[2] != 0xf)
497 v4l2_err(v4l2_dev
, "bad EOF\n");
499 if (tmpbuf
[0] != 0xf || tmpbuf
[1] != 0x0 || tmpbuf
[2] != 0xe)
500 v4l2_err(v4l2_dev
, "bad EOF\n");
504 qcam_write_data(qcam
, 0);
509 * Video4linux interfacing
512 static int qcam_querycap(struct file
*file
, void *priv
,
513 struct v4l2_capability
*vcap
)
515 struct qcam
*qcam
= video_drvdata(file
);
517 strlcpy(vcap
->driver
, qcam
->v4l2_dev
.name
, sizeof(vcap
->driver
));
518 strlcpy(vcap
->card
, "Color Quickcam", sizeof(vcap
->card
));
519 strlcpy(vcap
->bus_info
, "parport", sizeof(vcap
->bus_info
));
520 vcap
->version
= KERNEL_VERSION(0, 0, 3);
521 vcap
->capabilities
= V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_READWRITE
;
525 static int qcam_enum_input(struct file
*file
, void *fh
, struct v4l2_input
*vin
)
529 strlcpy(vin
->name
, "Camera", sizeof(vin
->name
));
530 vin
->type
= V4L2_INPUT_TYPE_CAMERA
;
538 static int qcam_g_input(struct file
*file
, void *fh
, unsigned int *inp
)
544 static int qcam_s_input(struct file
*file
, void *fh
, unsigned int inp
)
546 return (inp
> 0) ? -EINVAL
: 0;
549 static int qcam_queryctrl(struct file
*file
, void *priv
,
550 struct v4l2_queryctrl
*qc
)
553 case V4L2_CID_BRIGHTNESS
:
554 return v4l2_ctrl_query_fill(qc
, 0, 255, 1, 240);
555 case V4L2_CID_CONTRAST
:
556 return v4l2_ctrl_query_fill(qc
, 0, 255, 1, 192);
558 return v4l2_ctrl_query_fill(qc
, 0, 255, 1, 128);
563 static int qcam_g_ctrl(struct file
*file
, void *priv
,
564 struct v4l2_control
*ctrl
)
566 struct qcam
*qcam
= video_drvdata(file
);
570 case V4L2_CID_BRIGHTNESS
:
571 ctrl
->value
= qcam
->brightness
;
573 case V4L2_CID_CONTRAST
:
574 ctrl
->value
= qcam
->contrast
;
577 ctrl
->value
= qcam
->whitebal
;
586 static int qcam_s_ctrl(struct file
*file
, void *priv
,
587 struct v4l2_control
*ctrl
)
589 struct qcam
*qcam
= video_drvdata(file
);
592 mutex_lock(&qcam
->lock
);
594 case V4L2_CID_BRIGHTNESS
:
595 qcam
->brightness
= ctrl
->value
;
597 case V4L2_CID_CONTRAST
:
598 qcam
->contrast
= ctrl
->value
;
601 qcam
->whitebal
= ctrl
->value
;
608 parport_claim_or_block(qcam
->pdev
);
610 parport_release(qcam
->pdev
);
612 mutex_unlock(&qcam
->lock
);
616 static int qcam_g_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_format
*fmt
)
618 struct qcam
*qcam
= video_drvdata(file
);
619 struct v4l2_pix_format
*pix
= &fmt
->fmt
.pix
;
621 pix
->width
= qcam
->width
;
622 pix
->height
= qcam
->height
;
623 pix
->pixelformat
= V4L2_PIX_FMT_RGB24
;
624 pix
->field
= V4L2_FIELD_NONE
;
625 pix
->bytesperline
= 3 * qcam
->width
;
626 pix
->sizeimage
= 3 * qcam
->width
* qcam
->height
;
628 pix
->colorspace
= V4L2_COLORSPACE_SRGB
;
632 static int qcam_try_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_format
*fmt
)
634 struct v4l2_pix_format
*pix
= &fmt
->fmt
.pix
;
636 if (pix
->height
< 60 || pix
->width
< 80) {
639 } else if (pix
->height
< 120 || pix
->width
< 160) {
646 pix
->pixelformat
= V4L2_PIX_FMT_RGB24
;
647 pix
->field
= V4L2_FIELD_NONE
;
648 pix
->bytesperline
= 3 * pix
->width
;
649 pix
->sizeimage
= 3 * pix
->width
* pix
->height
;
651 pix
->colorspace
= V4L2_COLORSPACE_SRGB
;
655 static int qcam_s_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_format
*fmt
)
657 struct qcam
*qcam
= video_drvdata(file
);
658 struct v4l2_pix_format
*pix
= &fmt
->fmt
.pix
;
659 int ret
= qcam_try_fmt_vid_cap(file
, fh
, fmt
);
663 switch (pix
->height
) {
665 qcam
->mode
= QC_DECIMATION_4
;
668 qcam
->mode
= QC_DECIMATION_2
;
671 qcam
->mode
= QC_DECIMATION_1
;
675 mutex_lock(&qcam
->lock
);
676 qcam
->mode
|= QC_MILLIONS
;
677 qcam
->height
= pix
->height
;
678 qcam
->width
= pix
->width
;
679 parport_claim_or_block(qcam
->pdev
);
681 parport_release(qcam
->pdev
);
682 mutex_unlock(&qcam
->lock
);
686 static int qcam_enum_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_fmtdesc
*fmt
)
688 static struct v4l2_fmtdesc formats
[] = {
690 "RGB 8:8:8", V4L2_PIX_FMT_RGB24
,
694 enum v4l2_buf_type type
= fmt
->type
;
699 *fmt
= formats
[fmt
->index
];
704 static ssize_t
qcam_read(struct file
*file
, char __user
*buf
,
705 size_t count
, loff_t
*ppos
)
707 struct qcam
*qcam
= video_drvdata(file
);
710 mutex_lock(&qcam
->lock
);
711 parport_claim_or_block(qcam
->pdev
);
712 /* Probably should have a semaphore against multiple users */
713 len
= qc_capture(qcam
, buf
, count
);
714 parport_release(qcam
->pdev
);
715 mutex_unlock(&qcam
->lock
);
719 static const struct v4l2_file_operations qcam_fops
= {
720 .owner
= THIS_MODULE
,
721 .unlocked_ioctl
= video_ioctl2
,
725 static const struct v4l2_ioctl_ops qcam_ioctl_ops
= {
726 .vidioc_querycap
= qcam_querycap
,
727 .vidioc_g_input
= qcam_g_input
,
728 .vidioc_s_input
= qcam_s_input
,
729 .vidioc_enum_input
= qcam_enum_input
,
730 .vidioc_queryctrl
= qcam_queryctrl
,
731 .vidioc_g_ctrl
= qcam_g_ctrl
,
732 .vidioc_s_ctrl
= qcam_s_ctrl
,
733 .vidioc_enum_fmt_vid_cap
= qcam_enum_fmt_vid_cap
,
734 .vidioc_g_fmt_vid_cap
= qcam_g_fmt_vid_cap
,
735 .vidioc_s_fmt_vid_cap
= qcam_s_fmt_vid_cap
,
736 .vidioc_try_fmt_vid_cap
= qcam_try_fmt_vid_cap
,
739 /* Initialize the QuickCam driver control structure. */
741 static struct qcam
*qcam_init(struct parport
*port
)
744 struct v4l2_device
*v4l2_dev
;
746 qcam
= kzalloc(sizeof(*qcam
), GFP_KERNEL
);
750 v4l2_dev
= &qcam
->v4l2_dev
;
751 strlcpy(v4l2_dev
->name
, "c-qcam", sizeof(v4l2_dev
->name
));
753 if (v4l2_device_register(NULL
, v4l2_dev
) < 0) {
754 v4l2_err(v4l2_dev
, "Could not register v4l2_device\n");
759 qcam
->pdev
= parport_register_device(port
, "c-qcam", NULL
, NULL
,
762 qcam
->bidirectional
= (qcam
->pport
->modes
& PARPORT_MODE_TRISTATE
) ? 1 : 0;
764 if (qcam
->pdev
== NULL
) {
765 v4l2_err(v4l2_dev
, "couldn't register for %s.\n", port
->name
);
770 strlcpy(qcam
->vdev
.name
, "Colour QuickCam", sizeof(qcam
->vdev
.name
));
771 qcam
->vdev
.v4l2_dev
= v4l2_dev
;
772 qcam
->vdev
.fops
= &qcam_fops
;
773 qcam
->vdev
.ioctl_ops
= &qcam_ioctl_ops
;
774 qcam
->vdev
.release
= video_device_release_empty
;
775 video_set_drvdata(&qcam
->vdev
, qcam
);
777 mutex_init(&qcam
->lock
);
778 qcam
->width
= qcam
->ccd_width
= 320;
779 qcam
->height
= qcam
->ccd_height
= 240;
780 qcam
->mode
= QC_MILLIONS
| QC_DECIMATION_1
;
781 qcam
->contrast
= 192;
782 qcam
->brightness
= 240;
783 qcam
->whitebal
= 128;
789 static int init_cqcam(struct parport
*port
)
792 struct v4l2_device
*v4l2_dev
;
794 if (parport
[0] != -1) {
795 /* The user gave specific instructions */
798 for (i
= 0; i
< MAX_CAMS
&& parport
[i
] != -1; i
++) {
799 if (parport
[0] == port
->number
)
806 if (num_cams
== MAX_CAMS
)
809 qcam
= qcam_init(port
);
813 v4l2_dev
= &qcam
->v4l2_dev
;
815 parport_claim_or_block(qcam
->pdev
);
819 if (probe
&& qc_detect(qcam
) == 0) {
820 parport_release(qcam
->pdev
);
821 parport_unregister_device(qcam
->pdev
);
828 parport_release(qcam
->pdev
);
830 if (video_register_device(&qcam
->vdev
, VFL_TYPE_GRABBER
, video_nr
) < 0) {
831 v4l2_err(v4l2_dev
, "Unable to register Colour QuickCam on %s\n",
833 parport_unregister_device(qcam
->pdev
);
838 v4l2_info(v4l2_dev
, "%s: Colour QuickCam found on %s\n",
839 video_device_node_name(&qcam
->vdev
), qcam
->pport
->name
);
841 qcams
[num_cams
++] = qcam
;
846 static void close_cqcam(struct qcam
*qcam
)
848 video_unregister_device(&qcam
->vdev
);
849 parport_unregister_device(qcam
->pdev
);
853 static void cq_attach(struct parport
*port
)
858 static void cq_detach(struct parport
*port
)
860 /* Write this some day. */
863 static struct parport_driver cqcam_driver
= {
869 static int __init
cqcam_init(void)
871 printk(KERN_INFO BANNER
"\n");
873 return parport_register_driver(&cqcam_driver
);
876 static void __exit
cqcam_cleanup(void)
880 for (i
= 0; i
< num_cams
; i
++)
881 close_cqcam(qcams
[i
]);
883 parport_unregister_driver(&cqcam_driver
);
886 MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
887 MODULE_DESCRIPTION(BANNER
);
888 MODULE_LICENSE("GPL");
890 module_init(cqcam_init
);
891 module_exit(cqcam_cleanup
);