• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/media/video/
1/*
2 *	Video4Linux Colour QuickCam driver
3 *	Copyright 1997-2000 Philip Blundell <philb@gnu.org>
4 *
5 *    Module parameters:
6 *
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
10 *
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
14 *
15 *	force_rgb=1       -- force data format to RGB (default is BGR)
16 *
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>
20 *
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>
24 */
25
26#include <linux/module.h>
27#include <linux/delay.h>
28#include <linux/errno.h>
29#include <linux/fs.h>
30#include <linux/init.h>
31#include <linux/kernel.h>
32#include <linux/slab.h>
33#include <linux/mm.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>
44
45struct qcam {
46	struct v4l2_device v4l2_dev;
47	struct video_device vdev;
48	struct pardevice *pdev;
49	struct parport *pport;
50	int width, height;
51	int ccd_width, ccd_height;
52	int mode;
53	int contrast, brightness, whitebal;
54	int top, left;
55	unsigned int bidirectional;
56	struct mutex lock;
57};
58
59/* cameras maximum */
60#define MAX_CAMS 4
61
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) */
66
67/* The three possible decimations */
68#define QC_DECIMATION_1		0
69#define QC_DECIMATION_2		2
70#define QC_DECIMATION_4		4
71
72#define BANNER "Colour QuickCam for Video4Linux v0.06"
73
74static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
75static int probe = 2;
76static int force_rgb;
77static int video_nr = -1;
78
79MODULE_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)");
82module_param_array(parport, int, NULL, 0);
83module_param(probe, int, 0);
84module_param(force_rgb, bool, 0);
85module_param(video_nr, int, 0);
86
87static struct qcam *qcams[MAX_CAMS];
88static unsigned int num_cams;
89
90static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
91{
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);
95}
96
97static inline unsigned int qcam_ready1(struct qcam *qcam)
98{
99	return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
100}
101
102static inline unsigned int qcam_ready2(struct qcam *qcam)
103{
104	return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
105}
106
107static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
108{
109	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
110	unsigned long oldjiffies = jiffies;
111	unsigned int i;
112
113	for (oldjiffies = jiffies;
114	     time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
115		if (qcam_ready1(qcam) == value)
116			return 0;
117
118	/* If the camera didn't respond within 1/25 second, poll slowly
119	   for a while. */
120	for (i = 0; i < 50; i++) {
121		if (qcam_ready1(qcam) == value)
122			return 0;
123		msleep_interruptible(100);
124	}
125
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));
130	return 1;
131}
132
133static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
134{
135	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
136	unsigned long oldjiffies = jiffies;
137	unsigned int i;
138
139	for (oldjiffies = jiffies;
140	     time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
141		if (qcam_ready2(qcam) == value)
142			return 0;
143
144	/* If the camera didn't respond within 1/25 second, poll slowly
145	   for a while. */
146	for (i = 0; i < 50; i++) {
147		if (qcam_ready2(qcam) == value)
148			return 0;
149		msleep_interruptible(100);
150	}
151
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));
157	return 1;
158}
159
160static int qcam_read_data(struct qcam *qcam)
161{
162	unsigned int idata;
163
164	qcam_set_ack(qcam, 0);
165	if (qcam_await_ready1(qcam, 1))
166		return -1;
167	idata = parport_read_status(qcam->pport) & 0xf0;
168	qcam_set_ack(qcam, 1);
169	if (qcam_await_ready1(qcam, 0))
170		return -1;
171	idata |= parport_read_status(qcam->pport) >> 4;
172	return idata;
173}
174
175static int qcam_write_data(struct qcam *qcam, unsigned int data)
176{
177	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
178	unsigned int idata;
179
180	parport_write_data(qcam->pport, data);
181	idata = qcam_read_data(qcam);
182	if (data != idata) {
183		v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
184		       idata);
185		return 1;
186	}
187	return 0;
188}
189
190static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
191{
192	if (qcam_write_data(qcam, cmd))
193		return -1;
194	if (qcam_write_data(qcam, data))
195		return -1;
196	return 0;
197}
198
199static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
200{
201	if (qcam_write_data(qcam, cmd))
202		return -1;
203	return qcam_read_data(qcam);
204}
205
206static int qc_detect(struct qcam *qcam)
207{
208	unsigned int stat, ostat, i, count = 0;
209
210	/* The probe routine below is not very reliable.  The IEEE-1284
211	   probe takes precedence. */
212	if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
213	    && qcam->pport->probe_info[0].model
214	    && !strcmp(qcam->pdev->port->probe_info[0].model,
215		       "Color QuickCam 2.0")) {
216		printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
217		return 1;
218	}
219
220	if (probe < 2)
221		return 0;
222
223	parport_write_control(qcam->pport, 0xc);
224
225	/* look for a heartbeat */
226	ostat = stat = parport_read_status(qcam->pport);
227	for (i = 0; i < 250; i++) {
228		mdelay(1);
229		stat = parport_read_status(qcam->pport);
230		if (ostat != stat) {
231			if (++count >= 3)
232				return 1;
233			ostat = stat;
234		}
235	}
236
237	/* Reset the camera and try again */
238	parport_write_control(qcam->pport, 0xc);
239	parport_write_control(qcam->pport, 0x8);
240	mdelay(1);
241	parport_write_control(qcam->pport, 0xc);
242	mdelay(1);
243	count = 0;
244
245	ostat = stat = parport_read_status(qcam->pport);
246	for (i = 0; i < 250; i++) {
247		mdelay(1);
248		stat = parport_read_status(qcam->pport);
249		if (ostat != stat) {
250			if (++count >= 3)
251				return 1;
252			ostat = stat;
253		}
254	}
255
256	/* no (or flatline) camera, give up */
257	return 0;
258}
259
260static void qc_reset(struct qcam *qcam)
261{
262	parport_write_control(qcam->pport, 0xc);
263	parport_write_control(qcam->pport, 0x8);
264	mdelay(1);
265	parport_write_control(qcam->pport, 0xc);
266	mdelay(1);
267}
268
269/* Reset the QuickCam and program for brightness, contrast,
270 * white-balance, and resolution. */
271
272static void qc_setup(struct qcam *qcam)
273{
274	qc_reset(qcam);
275
276	/* Set the brightness. */
277	qcam_set(qcam, 11, qcam->brightness);
278
279	/* Set the height and width.  These refer to the actual
280	   CCD area *before* applying the selected decimation.  */
281	qcam_set(qcam, 17, qcam->ccd_height);
282	qcam_set(qcam, 19, qcam->ccd_width / 2);
283
284	/* Set top and left.  */
285	qcam_set(qcam, 0xd, qcam->top);
286	qcam_set(qcam, 0xf, qcam->left);
287
288	/* Set contrast and white balance.  */
289	qcam_set(qcam, 0x19, qcam->contrast);
290	qcam_set(qcam, 0x1f, qcam->whitebal);
291
292	/* Set the speed.  */
293	qcam_set(qcam, 45, 2);
294}
295
296/* Read some bytes from the camera and put them in the buffer.
297   nbytes should be a multiple of 3, because bidirectional mode gives
298   us three bytes at a time.  */
299
300static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
301{
302	unsigned int bytes = 0;
303
304	qcam_set_ack(qcam, 0);
305	if (qcam->bidirectional) {
306		/* It's a bidirectional port */
307		while (bytes < nbytes) {
308			unsigned int lo1, hi1, lo2, hi2;
309			unsigned char r, g, b;
310
311			if (qcam_await_ready2(qcam, 1))
312				return bytes;
313			lo1 = parport_read_data(qcam->pport) >> 1;
314			hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
315			qcam_set_ack(qcam, 1);
316			if (qcam_await_ready2(qcam, 0))
317				return bytes;
318			lo2 = parport_read_data(qcam->pport) >> 1;
319			hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
320			qcam_set_ack(qcam, 0);
321			r = lo1 | ((hi1 & 1) << 7);
322			g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1);
323			b = lo2 | ((hi2 & 1) << 7);
324			if (force_rgb) {
325				buf[bytes++] = r;
326				buf[bytes++] = g;
327				buf[bytes++] = b;
328			} else {
329				buf[bytes++] = b;
330				buf[bytes++] = g;
331				buf[bytes++] = r;
332			}
333		}
334	} else {
335		/* It's a unidirectional port */
336		int i = 0, n = bytes;
337		unsigned char rgb[3];
338
339		while (bytes < nbytes) {
340			unsigned int hi, lo;
341
342			if (qcam_await_ready1(qcam, 1))
343				return bytes;
344			hi = (parport_read_status(qcam->pport) & 0xf0);
345			qcam_set_ack(qcam, 1);
346			if (qcam_await_ready1(qcam, 0))
347				return bytes;
348			lo = (parport_read_status(qcam->pport) & 0xf0);
349			qcam_set_ack(qcam, 0);
350			/* flip some bits */
351			rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
352			if (i >= 2) {
353get_fragment:
354				if (force_rgb) {
355					buf[n++] = rgb[0];
356					buf[n++] = rgb[1];
357					buf[n++] = rgb[2];
358				} else {
359					buf[n++] = rgb[2];
360					buf[n++] = rgb[1];
361					buf[n++] = rgb[0];
362				}
363			}
364		}
365		if (i) {
366			i = 0;
367			goto get_fragment;
368		}
369	}
370	return bytes;
371}
372
373#define BUFSZ	150
374
375static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
376{
377	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
378	unsigned lines, pixelsperline, bitsperxfer;
379	unsigned int is_bi_dir = qcam->bidirectional;
380	size_t wantlen, outptr = 0;
381	char tmpbuf[BUFSZ];
382
383	if (!access_ok(VERIFY_WRITE, buf, len))
384		return -EFAULT;
385
386	/* Wait for camera to become ready */
387	for (;;) {
388		int i = qcam_get(qcam, 41);
389
390		if (i == -1) {
391			qc_setup(qcam);
392			return -EIO;
393		}
394		if ((i & 0x80) == 0)
395			break;
396		schedule();
397	}
398
399	if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
400		return -EIO;
401
402	lines = qcam->height;
403	pixelsperline = qcam->width;
404	bitsperxfer = (is_bi_dir) ? 24 : 8;
405
406	if (is_bi_dir) {
407		/* Turn the port around */
408		parport_data_reverse(qcam->pport);
409		mdelay(3);
410		qcam_set_ack(qcam, 0);
411		if (qcam_await_ready1(qcam, 1)) {
412			qc_setup(qcam);
413			return -EIO;
414		}
415		qcam_set_ack(qcam, 1);
416		if (qcam_await_ready1(qcam, 0)) {
417			qc_setup(qcam);
418			return -EIO;
419		}
420	}
421
422	wantlen = lines * pixelsperline * 24 / 8;
423
424	while (wantlen) {
425		size_t t, s;
426
427		s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
428		t = qcam_read_bytes(qcam, tmpbuf, s);
429		if (outptr < len) {
430			size_t sz = len - outptr;
431
432			if (sz > t)
433				sz = t;
434			if (__copy_to_user(buf + outptr, tmpbuf, sz))
435				break;
436			outptr += sz;
437		}
438		wantlen -= t;
439		if (t < s)
440			break;
441		cond_resched();
442	}
443
444	len = outptr;
445
446	if (wantlen) {
447		v4l2_err(v4l2_dev, "short read.\n");
448		if (is_bi_dir)
449			parport_data_forward(qcam->pport);
450		qc_setup(qcam);
451		return len;
452	}
453
454	if (is_bi_dir) {
455		int l;
456
457		do {
458			l = qcam_read_bytes(qcam, tmpbuf, 3);
459			cond_resched();
460		} while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
461		if (force_rgb) {
462			if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
463				v4l2_err(v4l2_dev, "bad EOF\n");
464		} else {
465			if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
466				v4l2_err(v4l2_dev, "bad EOF\n");
467		}
468		qcam_set_ack(qcam, 0);
469		if (qcam_await_ready1(qcam, 1)) {
470			v4l2_err(v4l2_dev, "no ack after EOF\n");
471			parport_data_forward(qcam->pport);
472			qc_setup(qcam);
473			return len;
474		}
475		parport_data_forward(qcam->pport);
476		mdelay(3);
477		qcam_set_ack(qcam, 1);
478		if (qcam_await_ready1(qcam, 0)) {
479			v4l2_err(v4l2_dev, "no ack to port turnaround\n");
480			qc_setup(qcam);
481			return len;
482		}
483	} else {
484		int l;
485
486		do {
487			l = qcam_read_bytes(qcam, tmpbuf, 1);
488			cond_resched();
489		} while (l && tmpbuf[0] == 0x7e);
490		l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
491		if (force_rgb) {
492			if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
493				v4l2_err(v4l2_dev, "bad EOF\n");
494		} else {
495			if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
496				v4l2_err(v4l2_dev, "bad EOF\n");
497		}
498	}
499
500	qcam_write_data(qcam, 0);
501	return len;
502}
503
504/*
505 *	Video4linux interfacing
506 */
507
508static int qcam_querycap(struct file *file, void  *priv,
509					struct v4l2_capability *vcap)
510{
511	struct qcam *qcam = video_drvdata(file);
512
513	strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
514	strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
515	strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
516	vcap->version = KERNEL_VERSION(0, 0, 3);
517	vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
518	return 0;
519}
520
521static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
522{
523	if (vin->index > 0)
524		return -EINVAL;
525	strlcpy(vin->name, "Camera", sizeof(vin->name));
526	vin->type = V4L2_INPUT_TYPE_CAMERA;
527	vin->audioset = 0;
528	vin->tuner = 0;
529	vin->std = 0;
530	vin->status = 0;
531	return 0;
532}
533
534static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
535{
536	*inp = 0;
537	return 0;
538}
539
540static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
541{
542	return (inp > 0) ? -EINVAL : 0;
543}
544
545static int qcam_queryctrl(struct file *file, void *priv,
546					struct v4l2_queryctrl *qc)
547{
548	switch (qc->id) {
549	case V4L2_CID_BRIGHTNESS:
550		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 240);
551	case V4L2_CID_CONTRAST:
552		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192);
553	case V4L2_CID_GAMMA:
554		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
555	}
556	return -EINVAL;
557}
558
559static int qcam_g_ctrl(struct file *file, void *priv,
560					struct v4l2_control *ctrl)
561{
562	struct qcam *qcam = video_drvdata(file);
563	int ret = 0;
564
565	switch (ctrl->id) {
566	case V4L2_CID_BRIGHTNESS:
567		ctrl->value = qcam->brightness;
568		break;
569	case V4L2_CID_CONTRAST:
570		ctrl->value = qcam->contrast;
571		break;
572	case V4L2_CID_GAMMA:
573		ctrl->value = qcam->whitebal;
574		break;
575	default:
576		ret = -EINVAL;
577		break;
578	}
579	return ret;
580}
581
582static int qcam_s_ctrl(struct file *file, void *priv,
583					struct v4l2_control *ctrl)
584{
585	struct qcam *qcam = video_drvdata(file);
586	int ret = 0;
587
588	mutex_lock(&qcam->lock);
589	switch (ctrl->id) {
590	case V4L2_CID_BRIGHTNESS:
591		qcam->brightness = ctrl->value;
592		break;
593	case V4L2_CID_CONTRAST:
594		qcam->contrast = ctrl->value;
595		break;
596	case V4L2_CID_GAMMA:
597		qcam->whitebal = ctrl->value;
598		break;
599	default:
600		ret = -EINVAL;
601		break;
602	}
603	if (ret == 0) {
604		parport_claim_or_block(qcam->pdev);
605		qc_setup(qcam);
606		parport_release(qcam->pdev);
607	}
608	mutex_unlock(&qcam->lock);
609	return ret;
610}
611
612static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
613{
614	struct qcam *qcam = video_drvdata(file);
615	struct v4l2_pix_format *pix = &fmt->fmt.pix;
616
617	pix->width = qcam->width;
618	pix->height = qcam->height;
619	pix->pixelformat = V4L2_PIX_FMT_RGB24;
620	pix->field = V4L2_FIELD_NONE;
621	pix->bytesperline = 3 * qcam->width;
622	pix->sizeimage = 3 * qcam->width * qcam->height;
623	/* Just a guess */
624	pix->colorspace = V4L2_COLORSPACE_SRGB;
625	return 0;
626}
627
628static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
629{
630	struct v4l2_pix_format *pix = &fmt->fmt.pix;
631
632	if (pix->height < 60 || pix->width < 80) {
633		pix->height = 60;
634		pix->width = 80;
635	} else if (pix->height < 120 || pix->width < 160) {
636		pix->height = 120;
637		pix->width = 160;
638	} else {
639		pix->height = 240;
640		pix->width = 320;
641	}
642	pix->pixelformat = V4L2_PIX_FMT_RGB24;
643	pix->field = V4L2_FIELD_NONE;
644	pix->bytesperline = 3 * pix->width;
645	pix->sizeimage = 3 * pix->width * pix->height;
646	/* Just a guess */
647	pix->colorspace = V4L2_COLORSPACE_SRGB;
648	return 0;
649}
650
651static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
652{
653	struct qcam *qcam = video_drvdata(file);
654	struct v4l2_pix_format *pix = &fmt->fmt.pix;
655	int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
656
657	if (ret)
658		return ret;
659	switch (pix->height) {
660	case 60:
661		qcam->mode = QC_DECIMATION_4;
662		break;
663	case 120:
664		qcam->mode = QC_DECIMATION_2;
665		break;
666	default:
667		qcam->mode = QC_DECIMATION_1;
668		break;
669	}
670
671	mutex_lock(&qcam->lock);
672	qcam->mode |= QC_MILLIONS;
673	qcam->height = pix->height;
674	qcam->width = pix->width;
675	parport_claim_or_block(qcam->pdev);
676	qc_setup(qcam);
677	parport_release(qcam->pdev);
678	mutex_unlock(&qcam->lock);
679	return 0;
680}
681
682static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
683{
684	static struct v4l2_fmtdesc formats[] = {
685		{ 0, 0, 0,
686		  "RGB 8:8:8", V4L2_PIX_FMT_RGB24,
687		  { 0, 0, 0, 0 }
688		},
689	};
690	enum v4l2_buf_type type = fmt->type;
691
692	if (fmt->index > 0)
693		return -EINVAL;
694
695	*fmt = formats[fmt->index];
696	fmt->type = type;
697	return 0;
698}
699
700static ssize_t qcam_read(struct file *file, char __user *buf,
701			 size_t count, loff_t *ppos)
702{
703	struct qcam *qcam = video_drvdata(file);
704	int len;
705
706	mutex_lock(&qcam->lock);
707	parport_claim_or_block(qcam->pdev);
708	/* Probably should have a semaphore against multiple users */
709	len = qc_capture(qcam, buf, count);
710	parport_release(qcam->pdev);
711	mutex_unlock(&qcam->lock);
712	return len;
713}
714
715static const struct v4l2_file_operations qcam_fops = {
716	.owner		= THIS_MODULE,
717	.ioctl		= video_ioctl2,
718	.read		= qcam_read,
719};
720
721static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
722	.vidioc_querycap    		    = qcam_querycap,
723	.vidioc_g_input      		    = qcam_g_input,
724	.vidioc_s_input      		    = qcam_s_input,
725	.vidioc_enum_input   		    = qcam_enum_input,
726	.vidioc_queryctrl 		    = qcam_queryctrl,
727	.vidioc_g_ctrl  		    = qcam_g_ctrl,
728	.vidioc_s_ctrl 			    = qcam_s_ctrl,
729	.vidioc_enum_fmt_vid_cap 	    = qcam_enum_fmt_vid_cap,
730	.vidioc_g_fmt_vid_cap 		    = qcam_g_fmt_vid_cap,
731	.vidioc_s_fmt_vid_cap  		    = qcam_s_fmt_vid_cap,
732	.vidioc_try_fmt_vid_cap  	    = qcam_try_fmt_vid_cap,
733};
734
735/* Initialize the QuickCam driver control structure. */
736
737static struct qcam *qcam_init(struct parport *port)
738{
739	struct qcam *qcam;
740	struct v4l2_device *v4l2_dev;
741
742	qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
743	if (qcam == NULL)
744		return NULL;
745
746	v4l2_dev = &qcam->v4l2_dev;
747	strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
748
749	if (v4l2_device_register(NULL, v4l2_dev) < 0) {
750		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
751		return NULL;
752	}
753
754	qcam->pport = port;
755	qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
756					  NULL, 0, NULL);
757
758	qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
759
760	if (qcam->pdev == NULL) {
761		v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
762		kfree(qcam);
763		return NULL;
764	}
765
766	strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name));
767	qcam->vdev.v4l2_dev = v4l2_dev;
768	qcam->vdev.fops = &qcam_fops;
769	qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
770	qcam->vdev.release = video_device_release_empty;
771	video_set_drvdata(&qcam->vdev, qcam);
772
773	mutex_init(&qcam->lock);
774	qcam->width = qcam->ccd_width = 320;
775	qcam->height = qcam->ccd_height = 240;
776	qcam->mode = QC_MILLIONS | QC_DECIMATION_1;
777	qcam->contrast = 192;
778	qcam->brightness = 240;
779	qcam->whitebal = 128;
780	qcam->top = 1;
781	qcam->left = 14;
782	return qcam;
783}
784
785static int init_cqcam(struct parport *port)
786{
787	struct qcam *qcam;
788	struct v4l2_device *v4l2_dev;
789
790	if (parport[0] != -1) {
791		/* The user gave specific instructions */
792		int i, found = 0;
793
794		for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) {
795			if (parport[0] == port->number)
796				found = 1;
797		}
798		if (!found)
799			return -ENODEV;
800	}
801
802	if (num_cams == MAX_CAMS)
803		return -ENOSPC;
804
805	qcam = qcam_init(port);
806	if (qcam == NULL)
807		return -ENODEV;
808
809	v4l2_dev = &qcam->v4l2_dev;
810
811	parport_claim_or_block(qcam->pdev);
812
813	qc_reset(qcam);
814
815	if (probe && qc_detect(qcam) == 0) {
816		parport_release(qcam->pdev);
817		parport_unregister_device(qcam->pdev);
818		kfree(qcam);
819		return -ENODEV;
820	}
821
822	qc_setup(qcam);
823
824	parport_release(qcam->pdev);
825
826	if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
827		v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n",
828		       qcam->pport->name);
829		parport_unregister_device(qcam->pdev);
830		kfree(qcam);
831		return -ENODEV;
832	}
833
834	v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
835	       video_device_node_name(&qcam->vdev), qcam->pport->name);
836
837	qcams[num_cams++] = qcam;
838
839	return 0;
840}
841
842static void close_cqcam(struct qcam *qcam)
843{
844	video_unregister_device(&qcam->vdev);
845	parport_unregister_device(qcam->pdev);
846	kfree(qcam);
847}
848
849static void cq_attach(struct parport *port)
850{
851	init_cqcam(port);
852}
853
854static void cq_detach(struct parport *port)
855{
856	/* Write this some day. */
857}
858
859static struct parport_driver cqcam_driver = {
860	.name = "cqcam",
861	.attach = cq_attach,
862	.detach = cq_detach,
863};
864
865static int __init cqcam_init(void)
866{
867	printk(KERN_INFO BANNER "\n");
868
869	return parport_register_driver(&cqcam_driver);
870}
871
872static void __exit cqcam_cleanup(void)
873{
874	unsigned int i;
875
876	for (i = 0; i < num_cams; i++)
877		close_cqcam(qcams[i]);
878
879	parport_unregister_driver(&cqcam_driver);
880}
881
882MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
883MODULE_DESCRIPTION(BANNER);
884MODULE_LICENSE("GPL");
885
886module_init(cqcam_init);
887module_exit(cqcam_cleanup);
888