Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/c-qcam.c
17642 views
1
/*
2
* Video4Linux Colour QuickCam driver
3
* Copyright 1997-2000 Philip Blundell <[email protected]>
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 <[email protected]>
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 <[email protected]>
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
45
struct 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
74
static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
75
static int probe = 2;
76
static int force_rgb;
77
static int video_nr = -1;
78
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);
87
88
static struct qcam *qcams[MAX_CAMS];
89
static unsigned int num_cams;
90
91
static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
92
{
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);
96
}
97
98
static inline unsigned int qcam_ready1(struct qcam *qcam)
99
{
100
return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
101
}
102
103
static inline unsigned int qcam_ready2(struct qcam *qcam)
104
{
105
return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
106
}
107
108
static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
109
{
110
struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
111
unsigned long oldjiffies = jiffies;
112
unsigned int i;
113
114
for (oldjiffies = jiffies;
115
time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
116
if (qcam_ready1(qcam) == value)
117
return 0;
118
119
/* If the camera didn't respond within 1/25 second, poll slowly
120
for a while. */
121
for (i = 0; i < 50; i++) {
122
if (qcam_ready1(qcam) == value)
123
return 0;
124
msleep_interruptible(100);
125
}
126
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));
131
return 1;
132
}
133
134
static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
135
{
136
struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
137
unsigned long oldjiffies = jiffies;
138
unsigned int i;
139
140
for (oldjiffies = jiffies;
141
time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
142
if (qcam_ready2(qcam) == value)
143
return 0;
144
145
/* If the camera didn't respond within 1/25 second, poll slowly
146
for a while. */
147
for (i = 0; i < 50; i++) {
148
if (qcam_ready2(qcam) == value)
149
return 0;
150
msleep_interruptible(100);
151
}
152
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));
158
return 1;
159
}
160
161
static int qcam_read_data(struct qcam *qcam)
162
{
163
unsigned int idata;
164
165
qcam_set_ack(qcam, 0);
166
if (qcam_await_ready1(qcam, 1))
167
return -1;
168
idata = parport_read_status(qcam->pport) & 0xf0;
169
qcam_set_ack(qcam, 1);
170
if (qcam_await_ready1(qcam, 0))
171
return -1;
172
idata |= parport_read_status(qcam->pport) >> 4;
173
return idata;
174
}
175
176
static int qcam_write_data(struct qcam *qcam, unsigned int data)
177
{
178
struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
179
unsigned int idata;
180
181
parport_write_data(qcam->pport, data);
182
idata = qcam_read_data(qcam);
183
if (data != idata) {
184
v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
185
idata);
186
return 1;
187
}
188
return 0;
189
}
190
191
static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
192
{
193
if (qcam_write_data(qcam, cmd))
194
return -1;
195
if (qcam_write_data(qcam, data))
196
return -1;
197
return 0;
198
}
199
200
static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
201
{
202
if (qcam_write_data(qcam, cmd))
203
return -1;
204
return qcam_read_data(qcam);
205
}
206
207
static int qc_detect(struct qcam *qcam)
208
{
209
unsigned int stat, ostat, i, count = 0;
210
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");
221
return 1;
222
}
223
224
if (probe < 2)
225
return 0;
226
227
parport_write_control(qcam->pport, 0xc);
228
229
/* look for a heartbeat */
230
ostat = stat = parport_read_status(qcam->pport);
231
for (i = 0; i < 250; i++) {
232
mdelay(1);
233
stat = parport_read_status(qcam->pport);
234
if (ostat != stat) {
235
if (++count >= 3)
236
return 1;
237
ostat = stat;
238
}
239
}
240
241
/* Reset the camera and try again */
242
parport_write_control(qcam->pport, 0xc);
243
parport_write_control(qcam->pport, 0x8);
244
mdelay(1);
245
parport_write_control(qcam->pport, 0xc);
246
mdelay(1);
247
count = 0;
248
249
ostat = stat = parport_read_status(qcam->pport);
250
for (i = 0; i < 250; i++) {
251
mdelay(1);
252
stat = parport_read_status(qcam->pport);
253
if (ostat != stat) {
254
if (++count >= 3)
255
return 1;
256
ostat = stat;
257
}
258
}
259
260
/* no (or flatline) camera, give up */
261
return 0;
262
}
263
264
static void qc_reset(struct qcam *qcam)
265
{
266
parport_write_control(qcam->pport, 0xc);
267
parport_write_control(qcam->pport, 0x8);
268
mdelay(1);
269
parport_write_control(qcam->pport, 0xc);
270
mdelay(1);
271
}
272
273
/* Reset the QuickCam and program for brightness, contrast,
274
* white-balance, and resolution. */
275
276
static void qc_setup(struct qcam *qcam)
277
{
278
qc_reset(qcam);
279
280
/* Set the brightness. */
281
qcam_set(qcam, 11, qcam->brightness);
282
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);
287
288
/* Set top and left. */
289
qcam_set(qcam, 0xd, qcam->top);
290
qcam_set(qcam, 0xf, qcam->left);
291
292
/* Set contrast and white balance. */
293
qcam_set(qcam, 0x19, qcam->contrast);
294
qcam_set(qcam, 0x1f, qcam->whitebal);
295
296
/* Set the speed. */
297
qcam_set(qcam, 45, 2);
298
}
299
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. */
303
304
static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
305
{
306
unsigned int bytes = 0;
307
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;
314
315
if (qcam_await_ready2(qcam, 1))
316
return bytes;
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))
321
return bytes;
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);
328
if (force_rgb) {
329
buf[bytes++] = r;
330
buf[bytes++] = g;
331
buf[bytes++] = b;
332
} else {
333
buf[bytes++] = b;
334
buf[bytes++] = g;
335
buf[bytes++] = r;
336
}
337
}
338
} else {
339
/* It's a unidirectional port */
340
int i = 0, n = bytes;
341
unsigned char rgb[3];
342
343
while (bytes < nbytes) {
344
unsigned int hi, lo;
345
346
if (qcam_await_ready1(qcam, 1))
347
return bytes;
348
hi = (parport_read_status(qcam->pport) & 0xf0);
349
qcam_set_ack(qcam, 1);
350
if (qcam_await_ready1(qcam, 0))
351
return bytes;
352
lo = (parport_read_status(qcam->pport) & 0xf0);
353
qcam_set_ack(qcam, 0);
354
/* flip some bits */
355
rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
356
if (i >= 2) {
357
get_fragment:
358
if (force_rgb) {
359
buf[n++] = rgb[0];
360
buf[n++] = rgb[1];
361
buf[n++] = rgb[2];
362
} else {
363
buf[n++] = rgb[2];
364
buf[n++] = rgb[1];
365
buf[n++] = rgb[0];
366
}
367
}
368
}
369
if (i) {
370
i = 0;
371
goto get_fragment;
372
}
373
}
374
return bytes;
375
}
376
377
#define BUFSZ 150
378
379
static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
380
{
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;
385
char tmpbuf[BUFSZ];
386
387
if (!access_ok(VERIFY_WRITE, buf, len))
388
return -EFAULT;
389
390
/* Wait for camera to become ready */
391
for (;;) {
392
int i = qcam_get(qcam, 41);
393
394
if (i == -1) {
395
qc_setup(qcam);
396
return -EIO;
397
}
398
if ((i & 0x80) == 0)
399
break;
400
schedule();
401
}
402
403
if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
404
return -EIO;
405
406
lines = qcam->height;
407
pixelsperline = qcam->width;
408
bitsperxfer = (is_bi_dir) ? 24 : 8;
409
410
if (is_bi_dir) {
411
/* Turn the port around */
412
parport_data_reverse(qcam->pport);
413
mdelay(3);
414
qcam_set_ack(qcam, 0);
415
if (qcam_await_ready1(qcam, 1)) {
416
qc_setup(qcam);
417
return -EIO;
418
}
419
qcam_set_ack(qcam, 1);
420
if (qcam_await_ready1(qcam, 0)) {
421
qc_setup(qcam);
422
return -EIO;
423
}
424
}
425
426
wantlen = lines * pixelsperline * 24 / 8;
427
428
while (wantlen) {
429
size_t t, s;
430
431
s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
432
t = qcam_read_bytes(qcam, tmpbuf, s);
433
if (outptr < len) {
434
size_t sz = len - outptr;
435
436
if (sz > t)
437
sz = t;
438
if (__copy_to_user(buf + outptr, tmpbuf, sz))
439
break;
440
outptr += sz;
441
}
442
wantlen -= t;
443
if (t < s)
444
break;
445
cond_resched();
446
}
447
448
len = outptr;
449
450
if (wantlen) {
451
v4l2_err(v4l2_dev, "short read.\n");
452
if (is_bi_dir)
453
parport_data_forward(qcam->pport);
454
qc_setup(qcam);
455
return len;
456
}
457
458
if (is_bi_dir) {
459
int l;
460
461
do {
462
l = qcam_read_bytes(qcam, tmpbuf, 3);
463
cond_resched();
464
} while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
465
if (force_rgb) {
466
if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
467
v4l2_err(v4l2_dev, "bad EOF\n");
468
} else {
469
if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
470
v4l2_err(v4l2_dev, "bad EOF\n");
471
}
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);
476
qc_setup(qcam);
477
return len;
478
}
479
parport_data_forward(qcam->pport);
480
mdelay(3);
481
qcam_set_ack(qcam, 1);
482
if (qcam_await_ready1(qcam, 0)) {
483
v4l2_err(v4l2_dev, "no ack to port turnaround\n");
484
qc_setup(qcam);
485
return len;
486
}
487
} else {
488
int l;
489
490
do {
491
l = qcam_read_bytes(qcam, tmpbuf, 1);
492
cond_resched();
493
} while (l && tmpbuf[0] == 0x7e);
494
l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
495
if (force_rgb) {
496
if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
497
v4l2_err(v4l2_dev, "bad EOF\n");
498
} else {
499
if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
500
v4l2_err(v4l2_dev, "bad EOF\n");
501
}
502
}
503
504
qcam_write_data(qcam, 0);
505
return len;
506
}
507
508
/*
509
* Video4linux interfacing
510
*/
511
512
static int qcam_querycap(struct file *file, void *priv,
513
struct v4l2_capability *vcap)
514
{
515
struct qcam *qcam = video_drvdata(file);
516
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;
522
return 0;
523
}
524
525
static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
526
{
527
if (vin->index > 0)
528
return -EINVAL;
529
strlcpy(vin->name, "Camera", sizeof(vin->name));
530
vin->type = V4L2_INPUT_TYPE_CAMERA;
531
vin->audioset = 0;
532
vin->tuner = 0;
533
vin->std = 0;
534
vin->status = 0;
535
return 0;
536
}
537
538
static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
539
{
540
*inp = 0;
541
return 0;
542
}
543
544
static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
545
{
546
return (inp > 0) ? -EINVAL : 0;
547
}
548
549
static int qcam_queryctrl(struct file *file, void *priv,
550
struct v4l2_queryctrl *qc)
551
{
552
switch (qc->id) {
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);
557
case V4L2_CID_GAMMA:
558
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
559
}
560
return -EINVAL;
561
}
562
563
static int qcam_g_ctrl(struct file *file, void *priv,
564
struct v4l2_control *ctrl)
565
{
566
struct qcam *qcam = video_drvdata(file);
567
int ret = 0;
568
569
switch (ctrl->id) {
570
case V4L2_CID_BRIGHTNESS:
571
ctrl->value = qcam->brightness;
572
break;
573
case V4L2_CID_CONTRAST:
574
ctrl->value = qcam->contrast;
575
break;
576
case V4L2_CID_GAMMA:
577
ctrl->value = qcam->whitebal;
578
break;
579
default:
580
ret = -EINVAL;
581
break;
582
}
583
return ret;
584
}
585
586
static int qcam_s_ctrl(struct file *file, void *priv,
587
struct v4l2_control *ctrl)
588
{
589
struct qcam *qcam = video_drvdata(file);
590
int ret = 0;
591
592
mutex_lock(&qcam->lock);
593
switch (ctrl->id) {
594
case V4L2_CID_BRIGHTNESS:
595
qcam->brightness = ctrl->value;
596
break;
597
case V4L2_CID_CONTRAST:
598
qcam->contrast = ctrl->value;
599
break;
600
case V4L2_CID_GAMMA:
601
qcam->whitebal = ctrl->value;
602
break;
603
default:
604
ret = -EINVAL;
605
break;
606
}
607
if (ret == 0) {
608
parport_claim_or_block(qcam->pdev);
609
qc_setup(qcam);
610
parport_release(qcam->pdev);
611
}
612
mutex_unlock(&qcam->lock);
613
return ret;
614
}
615
616
static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
617
{
618
struct qcam *qcam = video_drvdata(file);
619
struct v4l2_pix_format *pix = &fmt->fmt.pix;
620
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;
627
/* Just a guess */
628
pix->colorspace = V4L2_COLORSPACE_SRGB;
629
return 0;
630
}
631
632
static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
633
{
634
struct v4l2_pix_format *pix = &fmt->fmt.pix;
635
636
if (pix->height < 60 || pix->width < 80) {
637
pix->height = 60;
638
pix->width = 80;
639
} else if (pix->height < 120 || pix->width < 160) {
640
pix->height = 120;
641
pix->width = 160;
642
} else {
643
pix->height = 240;
644
pix->width = 320;
645
}
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;
650
/* Just a guess */
651
pix->colorspace = V4L2_COLORSPACE_SRGB;
652
return 0;
653
}
654
655
static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
656
{
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);
660
661
if (ret)
662
return ret;
663
switch (pix->height) {
664
case 60:
665
qcam->mode = QC_DECIMATION_4;
666
break;
667
case 120:
668
qcam->mode = QC_DECIMATION_2;
669
break;
670
default:
671
qcam->mode = QC_DECIMATION_1;
672
break;
673
}
674
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);
680
qc_setup(qcam);
681
parport_release(qcam->pdev);
682
mutex_unlock(&qcam->lock);
683
return 0;
684
}
685
686
static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
687
{
688
static struct v4l2_fmtdesc formats[] = {
689
{ 0, 0, 0,
690
"RGB 8:8:8", V4L2_PIX_FMT_RGB24,
691
{ 0, 0, 0, 0 }
692
},
693
};
694
enum v4l2_buf_type type = fmt->type;
695
696
if (fmt->index > 0)
697
return -EINVAL;
698
699
*fmt = formats[fmt->index];
700
fmt->type = type;
701
return 0;
702
}
703
704
static ssize_t qcam_read(struct file *file, char __user *buf,
705
size_t count, loff_t *ppos)
706
{
707
struct qcam *qcam = video_drvdata(file);
708
int len;
709
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);
716
return len;
717
}
718
719
static const struct v4l2_file_operations qcam_fops = {
720
.owner = THIS_MODULE,
721
.unlocked_ioctl = video_ioctl2,
722
.read = qcam_read,
723
};
724
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,
737
};
738
739
/* Initialize the QuickCam driver control structure. */
740
741
static struct qcam *qcam_init(struct parport *port)
742
{
743
struct qcam *qcam;
744
struct v4l2_device *v4l2_dev;
745
746
qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
747
if (qcam == NULL)
748
return NULL;
749
750
v4l2_dev = &qcam->v4l2_dev;
751
strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
752
753
if (v4l2_device_register(NULL, v4l2_dev) < 0) {
754
v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
755
return NULL;
756
}
757
758
qcam->pport = port;
759
qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
760
NULL, 0, NULL);
761
762
qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
763
764
if (qcam->pdev == NULL) {
765
v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
766
kfree(qcam);
767
return NULL;
768
}
769
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);
776
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;
784
qcam->top = 1;
785
qcam->left = 14;
786
return qcam;
787
}
788
789
static int init_cqcam(struct parport *port)
790
{
791
struct qcam *qcam;
792
struct v4l2_device *v4l2_dev;
793
794
if (parport[0] != -1) {
795
/* The user gave specific instructions */
796
int i, found = 0;
797
798
for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) {
799
if (parport[0] == port->number)
800
found = 1;
801
}
802
if (!found)
803
return -ENODEV;
804
}
805
806
if (num_cams == MAX_CAMS)
807
return -ENOSPC;
808
809
qcam = qcam_init(port);
810
if (qcam == NULL)
811
return -ENODEV;
812
813
v4l2_dev = &qcam->v4l2_dev;
814
815
parport_claim_or_block(qcam->pdev);
816
817
qc_reset(qcam);
818
819
if (probe && qc_detect(qcam) == 0) {
820
parport_release(qcam->pdev);
821
parport_unregister_device(qcam->pdev);
822
kfree(qcam);
823
return -ENODEV;
824
}
825
826
qc_setup(qcam);
827
828
parport_release(qcam->pdev);
829
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",
832
qcam->pport->name);
833
parport_unregister_device(qcam->pdev);
834
kfree(qcam);
835
return -ENODEV;
836
}
837
838
v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
839
video_device_node_name(&qcam->vdev), qcam->pport->name);
840
841
qcams[num_cams++] = qcam;
842
843
return 0;
844
}
845
846
static void close_cqcam(struct qcam *qcam)
847
{
848
video_unregister_device(&qcam->vdev);
849
parport_unregister_device(qcam->pdev);
850
kfree(qcam);
851
}
852
853
static void cq_attach(struct parport *port)
854
{
855
init_cqcam(port);
856
}
857
858
static void cq_detach(struct parport *port)
859
{
860
/* Write this some day. */
861
}
862
863
static struct parport_driver cqcam_driver = {
864
.name = "cqcam",
865
.attach = cq_attach,
866
.detach = cq_detach,
867
};
868
869
static int __init cqcam_init(void)
870
{
871
printk(KERN_INFO BANNER "\n");
872
873
return parport_register_driver(&cqcam_driver);
874
}
875
876
static void __exit cqcam_cleanup(void)
877
{
878
unsigned int i;
879
880
for (i = 0; i < num_cams; i++)
881
close_cqcam(qcams[i]);
882
883
parport_unregister_driver(&cqcam_driver);
884
}
885
886
MODULE_AUTHOR("Philip Blundell <[email protected]>");
887
MODULE_DESCRIPTION(BANNER);
888
MODULE_LICENSE("GPL");
889
890
module_init(cqcam_init);
891
module_exit(cqcam_cleanup);
892
893