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/videodev2.h>
39 #include <asm/uaccess.h>
40 #include <media/v4l2-device.h>
41 #include <media/v4l2-common.h>
42 #include <media/v4l2-ioctl.h>
45 struct v4l2_device v4l2_dev
;
46 struct video_device vdev
;
47 struct pardevice
*pdev
;
48 struct parport
*pport
;
50 int ccd_width
, ccd_height
;
52 int contrast
, brightness
, whitebal
;
54 unsigned int bidirectional
;
61 /* The three possible QuickCam modes */
62 #define QC_MILLIONS 0x18
63 #define QC_BILLIONS 0x10
64 #define QC_THOUSANDS 0x08 /* with VIDEC compression (not supported) */
66 /* The three possible decimations */
67 #define QC_DECIMATION_1 0
68 #define QC_DECIMATION_2 2
69 #define QC_DECIMATION_4 4
71 #define BANNER "Colour QuickCam for Video4Linux v0.06"
73 static int parport
[MAX_CAMS
] = { [1 ... MAX_CAMS
-1] = -1 };
75 static bool force_rgb
;
76 static int video_nr
= -1;
78 /* FIXME: parport=auto would never have worked, surely? --RR */
79 MODULE_PARM_DESC(parport
, "parport=<auto|n[,n]...> for port detection method\n"
80 "probe=<0|1|2> for camera detection method\n"
81 "force_rgb=<0|1> for RGB data format (default BGR)");
82 module_param_array(parport
, int, NULL
, 0);
83 module_param(probe
, int, 0);
84 module_param(force_rgb
, bool, 0);
85 module_param(video_nr
, int, 0);
87 static struct qcam
*qcams
[MAX_CAMS
];
88 static unsigned int num_cams
;
90 static inline void qcam_set_ack(struct qcam
*qcam
, unsigned int i
)
92 /* note: the QC specs refer to the PCAck pin by voltage, not
93 software level. PC ports have builtin inverters. */
94 parport_frob_control(qcam
->pport
, 8, i
? 8 : 0);
97 static inline unsigned int qcam_ready1(struct qcam
*qcam
)
99 return (parport_read_status(qcam
->pport
) & 0x8) ? 1 : 0;
102 static inline unsigned int qcam_ready2(struct qcam
*qcam
)
104 return (parport_read_data(qcam
->pport
) & 0x1) ? 1 : 0;
107 static unsigned int qcam_await_ready1(struct qcam
*qcam
, int value
)
109 struct v4l2_device
*v4l2_dev
= &qcam
->v4l2_dev
;
110 unsigned long oldjiffies
= jiffies
;
113 for (oldjiffies
= jiffies
;
114 time_before(jiffies
, oldjiffies
+ msecs_to_jiffies(40));)
115 if (qcam_ready1(qcam
) == value
)
118 /* If the camera didn't respond within 1/25 second, poll slowly
120 for (i
= 0; i
< 50; i
++) {
121 if (qcam_ready1(qcam
) == value
)
123 msleep_interruptible(100);
126 /* Probably somebody pulled the plug out. Not much we can do. */
127 v4l2_err(v4l2_dev
, "ready1 timeout (%d) %x %x\n", value
,
128 parport_read_status(qcam
->pport
),
129 parport_read_control(qcam
->pport
));
133 static unsigned int qcam_await_ready2(struct qcam
*qcam
, int value
)
135 struct v4l2_device
*v4l2_dev
= &qcam
->v4l2_dev
;
136 unsigned long oldjiffies
= jiffies
;
139 for (oldjiffies
= jiffies
;
140 time_before(jiffies
, oldjiffies
+ msecs_to_jiffies(40));)
141 if (qcam_ready2(qcam
) == value
)
144 /* If the camera didn't respond within 1/25 second, poll slowly
146 for (i
= 0; i
< 50; i
++) {
147 if (qcam_ready2(qcam
) == value
)
149 msleep_interruptible(100);
152 /* Probably somebody pulled the plug out. Not much we can do. */
153 v4l2_err(v4l2_dev
, "ready2 timeout (%d) %x %x %x\n", value
,
154 parport_read_status(qcam
->pport
),
155 parport_read_control(qcam
->pport
),
156 parport_read_data(qcam
->pport
));
160 static int qcam_read_data(struct qcam
*qcam
)
164 qcam_set_ack(qcam
, 0);
165 if (qcam_await_ready1(qcam
, 1))
167 idata
= parport_read_status(qcam
->pport
) & 0xf0;
168 qcam_set_ack(qcam
, 1);
169 if (qcam_await_ready1(qcam
, 0))
171 idata
|= parport_read_status(qcam
->pport
) >> 4;
175 static int qcam_write_data(struct qcam
*qcam
, unsigned int data
)
177 struct v4l2_device
*v4l2_dev
= &qcam
->v4l2_dev
;
180 parport_write_data(qcam
->pport
, data
);
181 idata
= qcam_read_data(qcam
);
183 v4l2_warn(v4l2_dev
, "sent %x but received %x\n", data
,
190 static inline int qcam_set(struct qcam
*qcam
, unsigned int cmd
, unsigned int data
)
192 if (qcam_write_data(qcam
, cmd
))
194 if (qcam_write_data(qcam
, data
))
199 static inline int qcam_get(struct qcam
*qcam
, unsigned int cmd
)
201 if (qcam_write_data(qcam
, cmd
))
203 return qcam_read_data(qcam
);
206 static int qc_detect(struct qcam
*qcam
)
208 unsigned int stat
, ostat
, i
, count
= 0;
210 /* The probe routine below is not very reliable. The IEEE-1284
211 probe takes precedence. */
212 /* XXX Currently parport provides no way to distinguish between
213 "the IEEE probe was not done" and "the probe was done, but
214 no device was found". Fix this one day. */
215 if (qcam
->pport
->probe_info
[0].class == PARPORT_CLASS_MEDIA
216 && qcam
->pport
->probe_info
[0].model
217 && !strcmp(qcam
->pdev
->port
->probe_info
[0].model
,
218 "Color QuickCam 2.0")) {
219 printk(KERN_DEBUG
"QuickCam: Found by IEEE1284 probe.\n");
226 parport_write_control(qcam
->pport
, 0xc);
228 /* look for a heartbeat */
229 ostat
= stat
= parport_read_status(qcam
->pport
);
230 for (i
= 0; i
< 250; i
++) {
232 stat
= parport_read_status(qcam
->pport
);
240 /* Reset the camera and try again */
241 parport_write_control(qcam
->pport
, 0xc);
242 parport_write_control(qcam
->pport
, 0x8);
244 parport_write_control(qcam
->pport
, 0xc);
248 ostat
= stat
= parport_read_status(qcam
->pport
);
249 for (i
= 0; i
< 250; i
++) {
251 stat
= parport_read_status(qcam
->pport
);
259 /* no (or flatline) camera, give up */
263 static void qc_reset(struct qcam
*qcam
)
265 parport_write_control(qcam
->pport
, 0xc);
266 parport_write_control(qcam
->pport
, 0x8);
268 parport_write_control(qcam
->pport
, 0xc);
272 /* Reset the QuickCam and program for brightness, contrast,
273 * white-balance, and resolution. */
275 static void qc_setup(struct qcam
*qcam
)
279 /* Set the brightness. */
280 qcam_set(qcam
, 11, qcam
->brightness
);
282 /* Set the height and width. These refer to the actual
283 CCD area *before* applying the selected decimation. */
284 qcam_set(qcam
, 17, qcam
->ccd_height
);
285 qcam_set(qcam
, 19, qcam
->ccd_width
/ 2);
287 /* Set top and left. */
288 qcam_set(qcam
, 0xd, qcam
->top
);
289 qcam_set(qcam
, 0xf, qcam
->left
);
291 /* Set contrast and white balance. */
292 qcam_set(qcam
, 0x19, qcam
->contrast
);
293 qcam_set(qcam
, 0x1f, qcam
->whitebal
);
296 qcam_set(qcam
, 45, 2);
299 /* Read some bytes from the camera and put them in the buffer.
300 nbytes should be a multiple of 3, because bidirectional mode gives
301 us three bytes at a time. */
303 static unsigned int qcam_read_bytes(struct qcam
*qcam
, unsigned char *buf
, unsigned int nbytes
)
305 unsigned int bytes
= 0;
307 qcam_set_ack(qcam
, 0);
308 if (qcam
->bidirectional
) {
309 /* It's a bidirectional port */
310 while (bytes
< nbytes
) {
311 unsigned int lo1
, hi1
, lo2
, hi2
;
312 unsigned char r
, g
, b
;
314 if (qcam_await_ready2(qcam
, 1))
316 lo1
= parport_read_data(qcam
->pport
) >> 1;
317 hi1
= ((parport_read_status(qcam
->pport
) >> 3) & 0x1f) ^ 0x10;
318 qcam_set_ack(qcam
, 1);
319 if (qcam_await_ready2(qcam
, 0))
321 lo2
= parport_read_data(qcam
->pport
) >> 1;
322 hi2
= ((parport_read_status(qcam
->pport
) >> 3) & 0x1f) ^ 0x10;
323 qcam_set_ack(qcam
, 0);
324 r
= lo1
| ((hi1
& 1) << 7);
325 g
= ((hi1
& 0x1e) << 3) | ((hi2
& 0x1e) >> 1);
326 b
= lo2
| ((hi2
& 1) << 7);
338 /* It's a unidirectional port */
339 int i
= 0, n
= bytes
;
340 unsigned char rgb
[3];
342 while (bytes
< nbytes
) {
345 if (qcam_await_ready1(qcam
, 1))
347 hi
= (parport_read_status(qcam
->pport
) & 0xf0);
348 qcam_set_ack(qcam
, 1);
349 if (qcam_await_ready1(qcam
, 0))
351 lo
= (parport_read_status(qcam
->pport
) & 0xf0);
352 qcam_set_ack(qcam
, 0);
354 rgb
[(i
= bytes
++ % 3)] = (hi
| (lo
>> 4)) ^ 0x88;
378 static long qc_capture(struct qcam
*qcam
, char __user
*buf
, unsigned long len
)
380 struct v4l2_device
*v4l2_dev
= &qcam
->v4l2_dev
;
381 unsigned lines
, pixelsperline
;
382 unsigned int is_bi_dir
= qcam
->bidirectional
;
383 size_t wantlen
, outptr
= 0;
386 if (!access_ok(VERIFY_WRITE
, buf
, len
))
389 /* Wait for camera to become ready */
391 int i
= qcam_get(qcam
, 41);
402 if (qcam_set(qcam
, 7, (qcam
->mode
| (is_bi_dir
? 1 : 0)) + 1))
405 lines
= qcam
->height
;
406 pixelsperline
= qcam
->width
;
409 /* Turn the port around */
410 parport_data_reverse(qcam
->pport
);
412 qcam_set_ack(qcam
, 0);
413 if (qcam_await_ready1(qcam
, 1)) {
417 qcam_set_ack(qcam
, 1);
418 if (qcam_await_ready1(qcam
, 0)) {
424 wantlen
= lines
* pixelsperline
* 24 / 8;
429 s
= (wantlen
> BUFSZ
) ? BUFSZ
: wantlen
;
430 t
= qcam_read_bytes(qcam
, tmpbuf
, s
);
432 size_t sz
= len
- outptr
;
436 if (__copy_to_user(buf
+ outptr
, tmpbuf
, sz
))
449 v4l2_err(v4l2_dev
, "short read.\n");
451 parport_data_forward(qcam
->pport
);
460 l
= qcam_read_bytes(qcam
, tmpbuf
, 3);
462 } while (l
&& (tmpbuf
[0] == 0x7e || tmpbuf
[1] == 0x7e || tmpbuf
[2] == 0x7e));
464 if (tmpbuf
[0] != 0xe || tmpbuf
[1] != 0x0 || tmpbuf
[2] != 0xf)
465 v4l2_err(v4l2_dev
, "bad EOF\n");
467 if (tmpbuf
[0] != 0xf || tmpbuf
[1] != 0x0 || tmpbuf
[2] != 0xe)
468 v4l2_err(v4l2_dev
, "bad EOF\n");
470 qcam_set_ack(qcam
, 0);
471 if (qcam_await_ready1(qcam
, 1)) {
472 v4l2_err(v4l2_dev
, "no ack after EOF\n");
473 parport_data_forward(qcam
->pport
);
477 parport_data_forward(qcam
->pport
);
479 qcam_set_ack(qcam
, 1);
480 if (qcam_await_ready1(qcam
, 0)) {
481 v4l2_err(v4l2_dev
, "no ack to port turnaround\n");
489 l
= qcam_read_bytes(qcam
, tmpbuf
, 1);
491 } while (l
&& tmpbuf
[0] == 0x7e);
492 l
= qcam_read_bytes(qcam
, tmpbuf
+ 1, 2);
494 if (tmpbuf
[0] != 0xe || tmpbuf
[1] != 0x0 || tmpbuf
[2] != 0xf)
495 v4l2_err(v4l2_dev
, "bad EOF\n");
497 if (tmpbuf
[0] != 0xf || tmpbuf
[1] != 0x0 || tmpbuf
[2] != 0xe)
498 v4l2_err(v4l2_dev
, "bad EOF\n");
502 qcam_write_data(qcam
, 0);
507 * Video4linux interfacing
510 static int qcam_querycap(struct file
*file
, void *priv
,
511 struct v4l2_capability
*vcap
)
513 struct qcam
*qcam
= video_drvdata(file
);
515 strlcpy(vcap
->driver
, qcam
->v4l2_dev
.name
, sizeof(vcap
->driver
));
516 strlcpy(vcap
->card
, "Color Quickcam", sizeof(vcap
->card
));
517 strlcpy(vcap
->bus_info
, "parport", sizeof(vcap
->bus_info
));
518 vcap
->capabilities
= V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_READWRITE
;
522 static int qcam_enum_input(struct file
*file
, void *fh
, struct v4l2_input
*vin
)
526 strlcpy(vin
->name
, "Camera", sizeof(vin
->name
));
527 vin
->type
= V4L2_INPUT_TYPE_CAMERA
;
535 static int qcam_g_input(struct file
*file
, void *fh
, unsigned int *inp
)
541 static int qcam_s_input(struct file
*file
, void *fh
, unsigned int inp
)
543 return (inp
> 0) ? -EINVAL
: 0;
546 static int qcam_queryctrl(struct file
*file
, void *priv
,
547 struct v4l2_queryctrl
*qc
)
550 case V4L2_CID_BRIGHTNESS
:
551 return v4l2_ctrl_query_fill(qc
, 0, 255, 1, 240);
552 case V4L2_CID_CONTRAST
:
553 return v4l2_ctrl_query_fill(qc
, 0, 255, 1, 192);
555 return v4l2_ctrl_query_fill(qc
, 0, 255, 1, 128);
560 static int qcam_g_ctrl(struct file
*file
, void *priv
,
561 struct v4l2_control
*ctrl
)
563 struct qcam
*qcam
= video_drvdata(file
);
567 case V4L2_CID_BRIGHTNESS
:
568 ctrl
->value
= qcam
->brightness
;
570 case V4L2_CID_CONTRAST
:
571 ctrl
->value
= qcam
->contrast
;
574 ctrl
->value
= qcam
->whitebal
;
583 static int qcam_s_ctrl(struct file
*file
, void *priv
,
584 struct v4l2_control
*ctrl
)
586 struct qcam
*qcam
= video_drvdata(file
);
589 mutex_lock(&qcam
->lock
);
591 case V4L2_CID_BRIGHTNESS
:
592 qcam
->brightness
= ctrl
->value
;
594 case V4L2_CID_CONTRAST
:
595 qcam
->contrast
= ctrl
->value
;
598 qcam
->whitebal
= ctrl
->value
;
605 parport_claim_or_block(qcam
->pdev
);
607 parport_release(qcam
->pdev
);
609 mutex_unlock(&qcam
->lock
);
613 static int qcam_g_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_format
*fmt
)
615 struct qcam
*qcam
= video_drvdata(file
);
616 struct v4l2_pix_format
*pix
= &fmt
->fmt
.pix
;
618 pix
->width
= qcam
->width
;
619 pix
->height
= qcam
->height
;
620 pix
->pixelformat
= V4L2_PIX_FMT_RGB24
;
621 pix
->field
= V4L2_FIELD_NONE
;
622 pix
->bytesperline
= 3 * qcam
->width
;
623 pix
->sizeimage
= 3 * qcam
->width
* qcam
->height
;
625 pix
->colorspace
= V4L2_COLORSPACE_SRGB
;
629 static int qcam_try_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_format
*fmt
)
631 struct v4l2_pix_format
*pix
= &fmt
->fmt
.pix
;
633 if (pix
->height
< 60 || pix
->width
< 80) {
636 } else if (pix
->height
< 120 || pix
->width
< 160) {
643 pix
->pixelformat
= V4L2_PIX_FMT_RGB24
;
644 pix
->field
= V4L2_FIELD_NONE
;
645 pix
->bytesperline
= 3 * pix
->width
;
646 pix
->sizeimage
= 3 * pix
->width
* pix
->height
;
648 pix
->colorspace
= V4L2_COLORSPACE_SRGB
;
652 static int qcam_s_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_format
*fmt
)
654 struct qcam
*qcam
= video_drvdata(file
);
655 struct v4l2_pix_format
*pix
= &fmt
->fmt
.pix
;
656 int ret
= qcam_try_fmt_vid_cap(file
, fh
, fmt
);
660 switch (pix
->height
) {
662 qcam
->mode
= QC_DECIMATION_4
;
665 qcam
->mode
= QC_DECIMATION_2
;
668 qcam
->mode
= QC_DECIMATION_1
;
672 mutex_lock(&qcam
->lock
);
673 qcam
->mode
|= QC_MILLIONS
;
674 qcam
->height
= pix
->height
;
675 qcam
->width
= pix
->width
;
676 parport_claim_or_block(qcam
->pdev
);
678 parport_release(qcam
->pdev
);
679 mutex_unlock(&qcam
->lock
);
683 static int qcam_enum_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_fmtdesc
*fmt
)
685 static struct v4l2_fmtdesc formats
[] = {
687 "RGB 8:8:8", V4L2_PIX_FMT_RGB24
,
691 enum v4l2_buf_type type
= fmt
->type
;
696 *fmt
= formats
[fmt
->index
];
701 static ssize_t
qcam_read(struct file
*file
, char __user
*buf
,
702 size_t count
, loff_t
*ppos
)
704 struct qcam
*qcam
= video_drvdata(file
);
707 mutex_lock(&qcam
->lock
);
708 parport_claim_or_block(qcam
->pdev
);
709 /* Probably should have a semaphore against multiple users */
710 len
= qc_capture(qcam
, buf
, count
);
711 parport_release(qcam
->pdev
);
712 mutex_unlock(&qcam
->lock
);
716 static const struct v4l2_file_operations qcam_fops
= {
717 .owner
= THIS_MODULE
,
718 .unlocked_ioctl
= video_ioctl2
,
722 static const struct v4l2_ioctl_ops qcam_ioctl_ops
= {
723 .vidioc_querycap
= qcam_querycap
,
724 .vidioc_g_input
= qcam_g_input
,
725 .vidioc_s_input
= qcam_s_input
,
726 .vidioc_enum_input
= qcam_enum_input
,
727 .vidioc_queryctrl
= qcam_queryctrl
,
728 .vidioc_g_ctrl
= qcam_g_ctrl
,
729 .vidioc_s_ctrl
= qcam_s_ctrl
,
730 .vidioc_enum_fmt_vid_cap
= qcam_enum_fmt_vid_cap
,
731 .vidioc_g_fmt_vid_cap
= qcam_g_fmt_vid_cap
,
732 .vidioc_s_fmt_vid_cap
= qcam_s_fmt_vid_cap
,
733 .vidioc_try_fmt_vid_cap
= qcam_try_fmt_vid_cap
,
736 /* Initialize the QuickCam driver control structure. */
738 static struct qcam
*qcam_init(struct parport
*port
)
741 struct v4l2_device
*v4l2_dev
;
743 qcam
= kzalloc(sizeof(*qcam
), GFP_KERNEL
);
747 v4l2_dev
= &qcam
->v4l2_dev
;
748 strlcpy(v4l2_dev
->name
, "c-qcam", sizeof(v4l2_dev
->name
));
750 if (v4l2_device_register(NULL
, v4l2_dev
) < 0) {
751 v4l2_err(v4l2_dev
, "Could not register v4l2_device\n");
757 qcam
->pdev
= parport_register_device(port
, "c-qcam", NULL
, NULL
,
760 qcam
->bidirectional
= (qcam
->pport
->modes
& PARPORT_MODE_TRISTATE
) ? 1 : 0;
762 if (qcam
->pdev
== NULL
) {
763 v4l2_err(v4l2_dev
, "couldn't register for %s.\n", port
->name
);
768 strlcpy(qcam
->vdev
.name
, "Colour QuickCam", sizeof(qcam
->vdev
.name
));
769 qcam
->vdev
.v4l2_dev
= v4l2_dev
;
770 qcam
->vdev
.fops
= &qcam_fops
;
771 qcam
->vdev
.ioctl_ops
= &qcam_ioctl_ops
;
772 qcam
->vdev
.release
= video_device_release_empty
;
773 video_set_drvdata(&qcam
->vdev
, qcam
);
775 mutex_init(&qcam
->lock
);
776 qcam
->width
= qcam
->ccd_width
= 320;
777 qcam
->height
= qcam
->ccd_height
= 240;
778 qcam
->mode
= QC_MILLIONS
| QC_DECIMATION_1
;
779 qcam
->contrast
= 192;
780 qcam
->brightness
= 240;
781 qcam
->whitebal
= 128;
787 static int init_cqcam(struct parport
*port
)
790 struct v4l2_device
*v4l2_dev
;
792 if (parport
[0] != -1) {
793 /* The user gave specific instructions */
796 for (i
= 0; i
< MAX_CAMS
&& parport
[i
] != -1; i
++) {
797 if (parport
[0] == port
->number
)
804 if (num_cams
== MAX_CAMS
)
807 qcam
= qcam_init(port
);
811 v4l2_dev
= &qcam
->v4l2_dev
;
813 parport_claim_or_block(qcam
->pdev
);
817 if (probe
&& qc_detect(qcam
) == 0) {
818 parport_release(qcam
->pdev
);
819 parport_unregister_device(qcam
->pdev
);
826 parport_release(qcam
->pdev
);
828 if (video_register_device(&qcam
->vdev
, VFL_TYPE_GRABBER
, video_nr
) < 0) {
829 v4l2_err(v4l2_dev
, "Unable to register Colour QuickCam on %s\n",
831 parport_unregister_device(qcam
->pdev
);
836 v4l2_info(v4l2_dev
, "%s: Colour QuickCam found on %s\n",
837 video_device_node_name(&qcam
->vdev
), qcam
->pport
->name
);
839 qcams
[num_cams
++] = qcam
;
844 static void close_cqcam(struct qcam
*qcam
)
846 video_unregister_device(&qcam
->vdev
);
847 parport_unregister_device(qcam
->pdev
);
851 static void cq_attach(struct parport
*port
)
856 static void cq_detach(struct parport
*port
)
858 /* Write this some day. */
861 static struct parport_driver cqcam_driver
= {
867 static int __init
cqcam_init(void)
869 printk(KERN_INFO BANNER
"\n");
871 return parport_register_driver(&cqcam_driver
);
874 static void __exit
cqcam_cleanup(void)
878 for (i
= 0; i
< num_cams
; i
++)
879 close_cqcam(qcams
[i
]);
881 parport_unregister_driver(&cqcam_driver
);
884 MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
885 MODULE_DESCRIPTION(BANNER
);
886 MODULE_LICENSE("GPL");
887 MODULE_VERSION("0.0.4");
889 module_init(cqcam_init
);
890 module_exit(cqcam_cleanup
);