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