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