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