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

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

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

~ [ 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.