~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux-2.6.17/drivers/media/video/c-qcam.c

Version: ~ [ 2.6.16 ] ~ [ 2.6.17 ] ~
Architecture: ~ [ ia64 ] ~ [ i386 ] ~ [ arm ] ~ [ ppc ] ~ [ sparc64 ] ~

  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/videodev.h>
 37 #include <linux/mutex.h>
 38 
 39 #include <asm/uaccess.h>
 40 
 41 struct qcam_device {
 42         struct video_device vdev;
 43         struct pardevice *pdev;
 44         struct parport *pport;
 45         int width, height;
 46         int ccd_width, ccd_height;
 47         int mode;
 48         int contrast, brightness, whitebal;
 49         int top, left;
 50         unsigned int bidirectional;
 51         struct mutex lock;
 52 };
 53 
 54 /* cameras maximum */
 55 #define MAX_CAMS 4
 56 
 57 /* The three possible QuickCam modes */
 58 #define QC_MILLIONS     0x18
 59 #define QC_BILLIONS     0x10
 60 #define QC_THOUSANDS    0x08    /* with VIDEC compression (not supported) */
 61 
 62 /* The three possible decimations */
 63 #define QC_DECIMATION_1         0
 64 #define QC_DECIMATION_2         2
 65 #define QC_DECIMATION_4         4
 66 
 67 #define BANNER "Colour QuickCam for Video4Linux v0.05"
 68 
 69 static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
 70 static int probe = 2;
 71 static int force_rgb = 0;
 72 static int video_nr = -1;
 73 
 74 static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
 75 {
 76         /* note: the QC specs refer to the PCAck pin by voltage, not
 77            software level.  PC ports have builtin inverters. */
 78         parport_frob_control(qcam->pport, 8, i?8:0);
 79 }
 80 
 81 static inline unsigned int qcam_ready1(struct qcam_device *qcam)
 82 {
 83         return (parport_read_status(qcam->pport) & 0x8)?1:0;
 84 }
 85 
 86 static inline unsigned int qcam_ready2(struct qcam_device *qcam)
 87 {
 88         return (parport_read_data(qcam->pport) & 0x1)?1:0;
 89 }
 90 
 91 static unsigned int qcam_await_ready1(struct qcam_device *qcam,
 92                                              int value)
 93 {
 94         unsigned long oldjiffies = jiffies;
 95         unsigned int i;
 96 
 97         for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); )
 98                 if (qcam_ready1(qcam) == value)
 99                         return 0;
100 
101         /* If the camera didn't respond within 1/25 second, poll slowly
102            for a while. */
103         for (i = 0; i < 50; i++)
104         {
105                 if (qcam_ready1(qcam) == value)
106                         return 0;
107                 msleep_interruptible(100);
108         }
109 
110         /* Probably somebody pulled the plug out.  Not much we can do. */
111         printk(KERN_ERR "c-qcam: ready1 timeout (%d) %x %x\n", value,
112                parport_read_status(qcam->pport),
113                parport_read_control(qcam->pport));
114         return 1;
115 }
116 
117 static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
118 {
119         unsigned long oldjiffies = jiffies;
120         unsigned int i;
121 
122         for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); )
123                 if (qcam_ready2(qcam) == value)
124                         return 0;
125 
126         /* If the camera didn't respond within 1/25 second, poll slowly
127            for a while. */
128         for (i = 0; i < 50; i++)
129         {
130                 if (qcam_ready2(qcam) == value)
131                         return 0;
132                 msleep_interruptible(100);
133         }
134 
135         /* Probably somebody pulled the plug out.  Not much we can do. */
136         printk(KERN_ERR "c-qcam: ready2 timeout (%d) %x %x %x\n", value,
137                parport_read_status(qcam->pport),
138                parport_read_control(qcam->pport),
139                parport_read_data(qcam->pport));
140         return 1;
141 }
142 
143 static int qcam_read_data(struct qcam_device *qcam)
144 {
145         unsigned int idata;
146         qcam_set_ack(qcam, 0);
147         if (qcam_await_ready1(qcam, 1)) return -1;
148         idata = parport_read_status(qcam->pport) & 0xf0;
149         qcam_set_ack(qcam, 1);
150         if (qcam_await_ready1(qcam, 0)) return -1;
151         idata |= (parport_read_status(qcam->pport) >> 4);
152         return idata;
153 }
154 
155 static int qcam_write_data(struct qcam_device *qcam, unsigned int data)
156 {
157         unsigned int idata;
158         parport_write_data(qcam->pport, data);
159         idata = qcam_read_data(qcam);
160         if (data != idata)
161         {
162                 printk(KERN_WARNING "cqcam: sent %x but received %x\n", data,
163                        idata);
164                 return 1;
165         }
166         return 0;
167 }
168 
169 static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned int data)
170 {
171         if (qcam_write_data(qcam, cmd))
172                 return -1;
173         if (qcam_write_data(qcam, data))
174                 return -1;
175         return 0;
176 }
177 
178 static inline int qcam_get(struct qcam_device *qcam, unsigned int cmd)
179 {
180         if (qcam_write_data(qcam, cmd))
181                 return -1;
182         return qcam_read_data(qcam);
183 }
184 
185 static int qc_detect(struct qcam_device *qcam)
186 {
187         unsigned int stat, ostat, i, count = 0;
188 
189         /* The probe routine below is not very reliable.  The IEEE-1284
190            probe takes precedence. */
191         /* XXX Currently parport provides no way to distinguish between
192            "the IEEE probe was not done" and "the probe was done, but
193            no device was found".  Fix this one day. */
194         if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
195             && qcam->pport->probe_info[0].model
196             && !strcmp(qcam->pdev->port->probe_info[0].model,
197                        "Color QuickCam 2.0")) {
198                 printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
199                 return 1;
200         }
201 
202         if (probe < 2)
203                 return 0;
204 
205         parport_write_control(qcam->pport, 0xc);
206 
207         /* look for a heartbeat */
208         ostat = stat = parport_read_status(qcam->pport);
209         for (i=0; i<250; i++)
210         {
211                 mdelay(1);
212                 stat = parport_read_status(qcam->pport);
213                 if (ostat != stat)
214                 {
215                         if (++count >= 3) return 1;
216                         ostat = stat;
217                 }
218         }
219 
220         /* Reset the camera and try again */
221         parport_write_control(qcam->pport, 0xc);
222         parport_write_control(qcam->pport, 0x8);
223         mdelay(1);
224         parport_write_control(qcam->pport, 0xc);
225         mdelay(1);
226         count = 0;
227 
228         ostat = stat = parport_read_status(qcam->pport);
229         for (i=0; i<250; i++)
230         {
231                 mdelay(1);
232                 stat = parport_read_status(qcam->pport);
233                 if (ostat != stat)
234                 {
235                         if (++count >= 3) return 1;
236                         ostat = stat;
237                 }
238         }
239 
240         /* no (or flatline) camera, give up */
241         return 0;
242 }
243 
244 static void qc_reset(struct qcam_device *qcam)
245 {
246         parport_write_control(qcam->pport, 0xc);
247         parport_write_control(qcam->pport, 0x8);
248         mdelay(1);
249         parport_write_control(qcam->pport, 0xc);
250         mdelay(1);
251 }
252 
253 /* Reset the QuickCam and program for brightness, contrast,
254  * white-balance, and resolution. */
255 
256 static void qc_setup(struct qcam_device *q)
257 {
258         qc_reset(q);
259 
260         /* Set the brightness.  */
261         qcam_set(q, 11, q->brightness);
262 
263         /* Set the height and width.  These refer to the actual
264            CCD area *before* applying the selected decimation.  */
265         qcam_set(q, 17, q->ccd_height);
266         qcam_set(q, 19, q->ccd_width / 2);
267 
268         /* Set top and left.  */
269         qcam_set(q, 0xd, q->top);
270         qcam_set(q, 0xf, q->left);
271 
272         /* Set contrast and white balance.  */
273         qcam_set(q, 0x19, q->contrast);
274         qcam_set(q, 0x1f, q->whitebal);
275 
276         /* Set the speed.  */
277         qcam_set(q, 45, 2);
278 }
279 
280 /* Read some bytes from the camera and put them in the buffer.
281    nbytes should be a multiple of 3, because bidirectional mode gives
282    us three bytes at a time.  */
283 
284 static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, unsigned int nbytes)
285 {
286         unsigned int bytes = 0;
287 
288         qcam_set_ack(q, 0);
289         if (q->bidirectional)
290         {
291                 /* It's a bidirectional port */
292                 while (bytes < nbytes)
293                 {
294                         unsigned int lo1, hi1, lo2, hi2;
295                         unsigned char r, g, b;
296 
297                         if (qcam_await_ready2(q, 1)) return bytes;
298                         lo1 = parport_read_data(q->pport) >> 1;
299                         hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10;
300                         qcam_set_ack(q, 1);
301                         if (qcam_await_ready2(q, 0)) return bytes;
302                         lo2 = parport_read_data(q->pport) >> 1;
303                         hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10;
304                         qcam_set_ack(q, 0);
305                         r = (lo1 | ((hi1 & 1)<<7));
306                         g = ((hi1 & 0x1e)<<3) | ((hi2 & 0x1e)>>1);
307                         b = (lo2 | ((hi2 & 1)<<7));
308                         if (force_rgb) {
309                                 buf[bytes++] = r;
310                                 buf[bytes++] = g;
311                                 buf[bytes++] = b;
312                         } else {
313                                 buf[bytes++] = b;
314                                 buf[bytes++] = g;
315                                 buf[bytes++] = r;
316                         }
317                 }
318         }
319         else
320         {
321                 /* It's a unidirectional port */
322                 int i = 0, n = bytes;
323                 unsigned char rgb[3];
324 
325                 while (bytes < nbytes)
326                 {
327                         unsigned int hi, lo;
328 
329                         if (qcam_await_ready1(q, 1)) return bytes;
330                         hi = (parport_read_status(q->pport) & 0xf0);
331                         qcam_set_ack(q, 1);
332                         if (qcam_await_ready1(q, 0)) return bytes;
333                         lo = (parport_read_status(q->pport) & 0xf0);
334                         qcam_set_ack(q, 0);
335                         /* flip some bits */
336                         rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
337                         if (i >= 2) {
338 get_fragment:
339                                 if (force_rgb) {
340                                         buf[n++] = rgb[0];
341                                         buf[n++] = rgb[1];
342                                         buf[n++] = rgb[2];
343                                 } else {
344                                         buf[n++] = rgb[2];
345                                         buf[n++] = rgb[1];
346                                         buf[n++] = rgb[0];
347                                 }
348                         }
349                 }
350                 if (i) {
351                         i = 0;
352                         goto get_fragment;
353                 }
354         }
355         return bytes;
356 }
357 
358 #define BUFSZ   150
359 
360 static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len)
361 {
362         unsigned lines, pixelsperline, bitsperxfer;
363         unsigned int is_bi_dir = q->bidirectional;
364         size_t wantlen, outptr = 0;
365         char tmpbuf[BUFSZ];
366 
367         if (!access_ok(VERIFY_WRITE, buf, len))
368                 return -EFAULT;
369 
370         /* Wait for camera to become ready */
371         for (;;)
372         {
373                 int i = qcam_get(q, 41);
374                 if (i == -1) {
375                         qc_setup(q);
376                         return -EIO;
377                 }
378                 if ((i & 0x80) == 0)
379                         break;
380                 else
381                         schedule();
382         }
383 
384         if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1))
385                 return -EIO;
386 
387         lines = q->height;
388         pixelsperline = q->width;
389         bitsperxfer = (is_bi_dir) ? 24 : 8;
390 
391         if (is_bi_dir)
392         {
393                 /* Turn the port around */
394                 parport_data_reverse(q->pport);
395                 mdelay(3);
396                 qcam_set_ack(q, 0);
397                 if (qcam_await_ready1(q, 1)) {
398                         qc_setup(q);
399                         return -EIO;
400                 }
401                 qcam_set_ack(q, 1);
402                 if (qcam_await_ready1(q, 0)) {
403                         qc_setup(q);
404                         return -EIO;
405                 }
406         }
407 
408         wantlen = lines * pixelsperline * 24 / 8;
409 
410         while (wantlen)
411         {
412                 size_t t, s;
413                 s = (wantlen > BUFSZ)?BUFSZ:wantlen;
414                 t = qcam_read_bytes(q, tmpbuf, s);
415                 if (outptr < len)
416                 {
417                         size_t sz = len - outptr;
418                         if (sz > t) sz = t;
419                         if (__copy_to_user(buf+outptr, tmpbuf, sz))
420                                 break;
421                         outptr += sz;
422                 }
423                 wantlen -= t;
424                 if (t < s)
425                         break;
426                 cond_resched();
427         }
428 
429         len = outptr;
430 
431         if (wantlen)
432         {
433                 printk("qcam: short read.\n");
434                 if (is_bi_dir)
435                         parport_data_forward(q->pport);
436                 qc_setup(q);
437                 return len;
438         }
439 
440         if (is_bi_dir)
441         {
442                 int l;
443                 do {
444                         l = qcam_read_bytes(q, tmpbuf, 3);
445                         cond_resched();
446                 } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
447                 if (force_rgb) {
448                         if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
449                                 printk("qcam: bad EOF\n");
450                 } else {
451                         if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
452                                 printk("qcam: bad EOF\n");
453                 }
454                 qcam_set_ack(q, 0);
455                 if (qcam_await_ready1(q, 1))
456                 {
457                         printk("qcam: no ack after EOF\n");
458                         parport_data_forward(q->pport);
459                         qc_setup(q);
460                         return len;
461                 }
462                 parport_data_forward(q->pport);
463                 mdelay(3);
464                 qcam_set_ack(q, 1);
465                 if (qcam_await_ready1(q, 0))
466                 {
467                         printk("qcam: no ack to port turnaround\n");
468                         qc_setup(q);
469                         return len;
470                 }
471         }
472         else
473         {
474                 int l;
475                 do {
476                         l = qcam_read_bytes(q, tmpbuf, 1);
477                         cond_resched();
478                 } while (l && tmpbuf[0] == 0x7e);
479                 l = qcam_read_bytes(q, tmpbuf+1, 2);
480                 if (force_rgb) {
481                         if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
482                                 printk("qcam: bad EOF\n");
483                 } else {
484                         if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
485                                 printk("qcam: bad EOF\n");
486                 }
487         }
488 
489         qcam_write_data(q, 0);
490         return len;
491 }
492 
493 /*
494  *      Video4linux interfacing
495  */
496 
497 static int qcam_do_ioctl(struct inode *inode, struct file *file,
498                          unsigned int cmd, void *arg)
499 {
500         struct video_device *dev = video_devdata(file);
501         struct qcam_device *qcam=(struct qcam_device *)dev;
502 
503         switch(cmd)
504         {
505                 case VIDIOCGCAP:
506                 {
507                         struct video_capability *b = arg;
508                         strcpy(b->name, "Quickcam");
509                         b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES;
510                         b->channels = 1;
511                         b->audios = 0;
512                         b->maxwidth = 320;
513                         b->maxheight = 240;
514                         b->minwidth = 80;
515                         b->minheight = 60;
516                         return 0;
517                 }
518                 case VIDIOCGCHAN:
519                 {
520                         struct video_channel *v = arg;
521                         if(v->channel!=0)
522                                 return -EINVAL;
523                         v->flags=0;
524                         v->tuners=0;
525                         /* Good question.. its composite or SVHS so.. */
526                         v->type = VIDEO_TYPE_CAMERA;
527                         strcpy(v->name, "Camera");
528                         return 0;
529                 }
530                 case VIDIOCSCHAN:
531                 {
532                         struct video_channel *v = arg;
533                         if(v->channel!=0)
534                                 return -EINVAL;
535                         return 0;
536                 }
537                 case VIDIOCGTUNER:
538                 {
539                         struct video_tuner *v = arg;
540                         if(v->tuner)
541                                 return -EINVAL;
542                         memset(v,0,sizeof(*v));
543                         strcpy(v->name, "Format");
544                         v->mode = VIDEO_MODE_AUTO;
545                         return 0;
546                 }
547                 case VIDIOCSTUNER:
548                 {
549                         struct video_tuner *v = arg;
550                         if(v->tuner)
551                                 return -EINVAL;
552                         if(v->mode!=VIDEO_MODE_AUTO)
553                                 return -EINVAL;
554                         return 0;
555                 }
556                 case VIDIOCGPICT:
557                 {
558                         struct video_picture *p = arg;
559                         p->colour=0x8000;
560                         p->hue=0x8000;
561                         p->brightness=qcam->brightness<<8;
562                         p->contrast=qcam->contrast<<8;
563                         p->whiteness=qcam->whitebal<<8;
564                         p->depth=24;
565                         p->palette=VIDEO_PALETTE_RGB24;
566                         return 0;
567                 }
568                 case VIDIOCSPICT:
569                 {
570                         struct video_picture *p = arg;
571 
572                         /*
573                          *      Sanity check args
574                          */
575                         if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24)
576                                 return -EINVAL;
577 
578                         /*
579                          *      Now load the camera.
580                          */
581                         qcam->brightness = p->brightness>>8;
582                         qcam->contrast = p->contrast>>8;
583                         qcam->whitebal = p->whiteness>>8;
584 
585                         mutex_lock(&qcam->lock);
586                         parport_claim_or_block(qcam->pdev);
587                         qc_setup(qcam);
588                         parport_release(qcam->pdev);
589                         mutex_unlock(&qcam->lock);
590                         return 0;
591                 }
592                 case VIDIOCSWIN:
593                 {
594                         struct video_window *vw = arg;
595 
596                         if(vw->flags)
597                                 return -EINVAL;
598                         if(vw->clipcount)
599                                 return -EINVAL;
600                         if(vw->height<60||vw->height>240)
601                                 return -EINVAL;
602                         if(vw->width<80||vw->width>320)
603                                 return -EINVAL;
604 
605                         qcam->width = 80;
606                         qcam->height = 60;
607                         qcam->mode = QC_DECIMATION_4;
608 
609                         if(vw->width>=160 && vw->height>=120)
610                         {
611                                 qcam->width = 160;
612                                 qcam->height = 120;
613                                 qcam->mode = QC_DECIMATION_2;
614                         }
615                         if(vw->width>=320 && vw->height>=240)
616                         {
617                                 qcam->width = 320;
618                                 qcam->height = 240;
619                                 qcam->mode = QC_DECIMATION_1;
620                         }
621                         qcam->mode |= QC_MILLIONS;
622 #if 0
623                         if(vw->width>=640 && vw->height>=480)
624                         {
625                                 qcam->width = 640;
626                                 qcam->height = 480;
627                                 qcam->mode = QC_BILLIONS | QC_DECIMATION_1;
628                         }
629 #endif
630                         /* Ok we figured out what to use from our
631                            wide choice */
632                         mutex_lock(&qcam->lock);
633                         parport_claim_or_block(qcam->pdev);
634                         qc_setup(qcam);
635                         parport_release(qcam->pdev);
636                         mutex_unlock(&qcam->lock);
637                         return 0;
638                 }
639                 case VIDIOCGWIN:
640                 {
641                         struct video_window *vw = arg;
642                         memset(vw, 0, sizeof(*vw));
643                         vw->width=qcam->width;
644                         vw->height=qcam->height;
645                         return 0;
646                 }
647                 case VIDIOCKEY:
648                         return 0;
649                 case VIDIOCCAPTURE:
650                 case VIDIOCGFBUF:
651                 case VIDIOCSFBUF:
652                 case VIDIOCGFREQ:
653                 case VIDIOCSFREQ:
654                 case VIDIOCGAUDIO:
655                 case VIDIOCSAUDIO:
656                         return -EINVAL;
657                 default:
658                         return -ENOIOCTLCMD;
659         }
660         return 0;
661 }
662 
663 static int qcam_ioctl(struct inode *inode, struct file *file,
664                      unsigned int cmd, unsigned long arg)
665 {
666         return video_usercopy(inode, file, cmd, arg, qcam_do_ioctl);
667 }
668 
669 static ssize_t qcam_read(struct file *file, char __user *buf,
670                          size_t count, loff_t *ppos)
671 {
672         struct video_device *v = video_devdata(file);
673         struct qcam_device *qcam=(struct qcam_device *)v;
674         int len;
675 
676         mutex_lock(&qcam->lock);
677         parport_claim_or_block(qcam->pdev);
678         /* Probably should have a semaphore against multiple users */
679         len = qc_capture(qcam, buf,count);
680         parport_release(qcam->pdev);
681         mutex_unlock(&qcam->lock);
682         return len;
683 }
684 
685 /* video device template */
686 static struct file_operations qcam_fops = {
687         .owner          = THIS_MODULE,
688         .open           = video_exclusive_open,
689         .release        = video_exclusive_release,
690         .ioctl          = qcam_ioctl,
691         .compat_ioctl   = v4l_compat_ioctl32,
692         .read           = qcam_read,
693         .llseek         = no_llseek,
694 };
695 
696 static struct video_device qcam_template=
697 {
698         .owner          = THIS_MODULE,
699         .name           = "Colour QuickCam",
700         .type           = VID_TYPE_CAPTURE,
701         .hardware       = VID_HARDWARE_QCAM_C,
702         .fops           = &qcam_fops,
703 };
704 
705 /* Initialize the QuickCam driver control structure. */
706 
707 static struct qcam_device *qcam_init(struct parport *port)
708 {
709         struct qcam_device *q;
710 
711         q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
712         if(q==NULL)
713                 return NULL;
714 
715         q->pport = port;
716         q->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
717                                           NULL, 0, NULL);
718 
719         q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE)?1:0;
720 
721         if (q->pdev == NULL)
722         {
723                 printk(KERN_ERR "c-qcam: couldn't register for %s.\n",
724                        port->name);
725                 kfree(q);
726                 return NULL;
727         }
728 
729         memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
730 
731         mutex_init(&q->lock);
732         q->width = q->ccd_width = 320;
733         q->height = q->ccd_height = 240;
734         q->mode = QC_MILLIONS | QC_DECIMATION_1;
735         q->contrast = 192;
736         q->brightness = 240;
737         q->whitebal = 128;
738         q->top = 1;
739         q->left = 14;
740         return q;
741 }
742 
743 static struct qcam_device *qcams[MAX_CAMS];
744 static unsigned int num_cams = 0;
745 
746 static int init_cqcam(struct parport *port)
747 {
748         struct qcam_device *qcam;
749 
750         if (parport[0] != -1)
751         {
752                 /* The user gave specific instructions */
753                 int i, found = 0;
754                 for (i = 0; i < MAX_CAMS && parport[i] != -1; i++)
755                 {
756                         if (parport[0] == port->number)
757                                 found = 1;
758                 }
759                 if (!found)
760                         return -ENODEV;
761         }
762 
763         if (num_cams == MAX_CAMS)
764                 return -ENOSPC;
765 
766         qcam = qcam_init(port);
767         if (qcam==NULL)
768                 return -ENODEV;
769 
770         parport_claim_or_block(qcam->pdev);
771 
772         qc_reset(qcam);
773 
774         if (probe && qc_detect(qcam)==0)
775         {
776                 parport_release(qcam->pdev);
777                 parport_unregister_device(qcam->pdev);
778                 kfree(qcam);
779                 return -ENODEV;
780         }
781 
782         qc_setup(qcam);
783 
784         parport_release(qcam->pdev);
785 
786         if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
787         {
788                 printk(KERN_ERR "Unable to register Colour QuickCam on %s\n",
789                        qcam->pport->name);
790                 parport_unregister_device(qcam->pdev);
791                 kfree(qcam);
792                 return -ENODEV;
793         }
794 
795         printk(KERN_INFO "video%d: Colour QuickCam found on %s\n",
796                qcam->vdev.minor, qcam->pport->name);
797 
798         qcams[num_cams++] = qcam;
799 
800         return 0;
801 }
802 
803 static void close_cqcam(struct qcam_device *qcam)
804 {
805         video_unregister_device(&qcam->vdev);
806         parport_unregister_device(qcam->pdev);
807         kfree(qcam);
808 }
809 
810 static void cq_attach(struct parport *port)
811 {
812         init_cqcam(port);
813 }
814 
815 static void cq_detach(struct parport *port)
816 {
817         /* Write this some day. */
818 }
819 
820 static struct parport_driver cqcam_driver = {
821         .name = "cqcam",
822         .attach = cq_attach,
823         .detach = cq_detach,
824 };
825 
826 static int __init cqcam_init (void)
827 {
828         printk(BANNER "\n");
829 
830         return parport_register_driver(&cqcam_driver);
831 }
832 
833 static void __exit cqcam_cleanup (void)
834 {
835         unsigned int i;
836 
837         for (i = 0; i < num_cams; i++)
838                 close_cqcam(qcams[i]);
839 
840         parport_unregister_driver(&cqcam_driver);
841 }
842 
843 MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
844 MODULE_DESCRIPTION(BANNER);
845 MODULE_LICENSE("GPL");
846 
847 /* FIXME: parport=auto would never have worked, surely? --RR */
848 MODULE_PARM_DESC(parport ,"parport=<auto|n[,n]...> for port detection method\n\
849 probe=<0|1|2> for camera detection method\n\
850 force_rgb=<0|1> for RGB data format (default BGR)");
851 module_param_array(parport, int, NULL, 0);
852 module_param(probe, int, 0);
853 module_param(force_rgb, bool, 0);
854 module_param(video_nr, int, 0);
855 
856 module_init(cqcam_init);
857 module_exit(cqcam_cleanup);
858 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.