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