linux/drivers/media/usb/gspca/pac7311.c
<<
>>
Prefs
   1/*
   2 *              Pixart PAC7311 library
   3 *              Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
   4 *
   5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 * GNU General Public License for more details.
  16 */
  17
  18/* Some documentation about various registers as determined by trial and error.
  19 *
  20 * Register page 1:
  21 *
  22 * Address      Description
  23 * 0x08         Unknown compressor related, must always be 8 except when not
  24 *              in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
  25 * 0x1b         Auto white balance related, bit 0 is AWB enable (inverted)
  26 *              bits 345 seem to toggle per color gains on/off (inverted)
  27 * 0x78         Global control, bit 6 controls the LED (inverted)
  28 * 0x80         Compression balance, interesting settings:
  29 *              0x01 Use this to allow the camera to switch to higher compr.
  30 *                   on the fly. Needed to stay within bandwidth @ 640x480@30
  31 *              0x1c From usb captures under Windows for 640x480
  32 *              0x2a Values >= this switch the camera to a lower compression,
  33 *                   using the same table for both luminance and chrominance.
  34 *                   This gives a sharper picture. Usable only at 640x480@ <
  35 *                   15 fps or 320x240 / 160x120. Note currently the driver
  36 *                   does not use this as the quality gain is small and the
  37 *                   generated JPG-s are only understood by v4l-utils >= 0.8.9
  38 *              0x3f From usb captures under Windows for 320x240
  39 *              0x69 From usb captures under Windows for 160x120
  40 *
  41 * Register page 4:
  42 *
  43 * Address      Description
  44 * 0x02         Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
  45 *              the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
  46 * 0x0f         Master gain 1-245, low value = high gain
  47 * 0x10         Another gain 0-15, limited influence (1-2x gain I guess)
  48 * 0x21         Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
  49 *              Note setting vflip disabled leads to a much lower image quality,
  50 *              so we always vflip, and tell userspace to flip it back
  51 * 0x27         Seems to toggle various gains on / off, Setting bit 7 seems to
  52 *              completely disable the analog amplification block. Set to 0x68
  53 *              for max gain, 0x14 for minimal gain.
  54 */
  55
  56#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  57
  58#define MODULE_NAME "pac7311"
  59
  60#include <linux/input.h>
  61#include "gspca.h"
  62/* Include pac common sof detection functions */
  63#include "pac_common.h"
  64
  65#define PAC7311_GAIN_DEFAULT     122
  66#define PAC7311_EXPOSURE_DEFAULT   3 /* 20 fps, avoid using high compr. */
  67
  68MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
  69MODULE_DESCRIPTION("Pixart PAC7311");
  70MODULE_LICENSE("GPL");
  71
  72struct sd {
  73        struct gspca_dev gspca_dev;             /* !! must be the first item */
  74
  75        struct v4l2_ctrl *contrast;
  76        struct v4l2_ctrl *hflip;
  77
  78        u8 sof_read;
  79        u8 autogain_ignore_frames;
  80
  81        atomic_t avg_lum;
  82};
  83
  84static const struct v4l2_pix_format vga_mode[] = {
  85        {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
  86                .bytesperline = 160,
  87                .sizeimage = 160 * 120 * 3 / 8 + 590,
  88                .colorspace = V4L2_COLORSPACE_JPEG,
  89                .priv = 2},
  90        {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
  91                .bytesperline = 320,
  92                .sizeimage = 320 * 240 * 3 / 8 + 590,
  93                .colorspace = V4L2_COLORSPACE_JPEG,
  94                .priv = 1},
  95        {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
  96                .bytesperline = 640,
  97                .sizeimage = 640 * 480 * 3 / 8 + 590,
  98                .colorspace = V4L2_COLORSPACE_JPEG,
  99                .priv = 0},
 100};
 101
 102#define LOAD_PAGE4              254
 103#define END_OF_SEQUENCE         0
 104
 105static const __u8 init_7311[] = {
 106        0xff, 0x01,
 107        0x78, 0x40,     /* Bit_0=start stream, Bit_6=LED */
 108        0x78, 0x40,     /* Bit_0=start stream, Bit_6=LED */
 109        0x78, 0x44,     /* Bit_0=start stream, Bit_6=LED */
 110        0xff, 0x04,
 111        0x27, 0x80,
 112        0x28, 0xca,
 113        0x29, 0x53,
 114        0x2a, 0x0e,
 115        0xff, 0x01,
 116        0x3e, 0x20,
 117};
 118
 119static const __u8 start_7311[] = {
 120/*      index, len, [value]* */
 121        0xff, 1,        0x01,           /* page 1 */
 122        0x02, 43,       0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
 123                        0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
 124                        0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
 125                        0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
 126                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 127                        0x00, 0x00, 0x00,
 128        0x3e, 42,       0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
 129                        0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
 130                        0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
 131                        0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
 132                        0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
 133                        0xd0, 0xff,
 134        0x78, 6,        0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
 135        0x7f, 18,       0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
 136                        0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
 137                        0x18, 0x20,
 138        0x96, 3,        0x01, 0x08, 0x04,
 139        0xa0, 4,        0x44, 0x44, 0x44, 0x04,
 140        0xf0, 13,       0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
 141                        0x3f, 0x00, 0x0a, 0x01, 0x00,
 142        0xff, 1,        0x04,           /* page 4 */
 143        0, LOAD_PAGE4,                  /* load the page 4 */
 144        0x11, 1,        0x01,
 145        0, END_OF_SEQUENCE              /* end of sequence */
 146};
 147
 148#define SKIP            0xaa
 149/* page 4 - the value SKIP says skip the index - see reg_w_page() */
 150static const __u8 page4_7311[] = {
 151        SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
 152        0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
 153        0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
 154        0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
 155        SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
 156        0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
 157        0x23, 0x28, 0x04, 0x11, 0x00, 0x00
 158};
 159
 160static void reg_w_buf(struct gspca_dev *gspca_dev,
 161                  __u8 index,
 162                  const u8 *buffer, int len)
 163{
 164        int ret;
 165
 166        if (gspca_dev->usb_err < 0)
 167                return;
 168        memcpy(gspca_dev->usb_buf, buffer, len);
 169        ret = usb_control_msg(gspca_dev->dev,
 170                        usb_sndctrlpipe(gspca_dev->dev, 0),
 171                        0,              /* request */
 172                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 173                        0,              /* value */
 174                        index, gspca_dev->usb_buf, len,
 175                        500);
 176        if (ret < 0) {
 177                pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
 178                       index, ret);
 179                gspca_dev->usb_err = ret;
 180        }
 181}
 182
 183
 184static void reg_w(struct gspca_dev *gspca_dev,
 185                  __u8 index,
 186                  __u8 value)
 187{
 188        int ret;
 189
 190        if (gspca_dev->usb_err < 0)
 191                return;
 192        gspca_dev->usb_buf[0] = value;
 193        ret = usb_control_msg(gspca_dev->dev,
 194                        usb_sndctrlpipe(gspca_dev->dev, 0),
 195                        0,                      /* request */
 196                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 197                        0, index, gspca_dev->usb_buf, 1,
 198                        500);
 199        if (ret < 0) {
 200                pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
 201                       index, value, ret);
 202                gspca_dev->usb_err = ret;
 203        }
 204}
 205
 206static void reg_w_seq(struct gspca_dev *gspca_dev,
 207                const __u8 *seq, int len)
 208{
 209        while (--len >= 0) {
 210                reg_w(gspca_dev, seq[0], seq[1]);
 211                seq += 2;
 212        }
 213}
 214
 215/* load the beginning of a page */
 216static void reg_w_page(struct gspca_dev *gspca_dev,
 217                        const __u8 *page, int len)
 218{
 219        int index;
 220        int ret = 0;
 221
 222        if (gspca_dev->usb_err < 0)
 223                return;
 224        for (index = 0; index < len; index++) {
 225                if (page[index] == SKIP)                /* skip this index */
 226                        continue;
 227                gspca_dev->usb_buf[0] = page[index];
 228                ret = usb_control_msg(gspca_dev->dev,
 229                                usb_sndctrlpipe(gspca_dev->dev, 0),
 230                                0,                      /* request */
 231                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 232                                0, index, gspca_dev->usb_buf, 1,
 233                                500);
 234                if (ret < 0) {
 235                        pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
 236                               index, page[index], ret);
 237                        gspca_dev->usb_err = ret;
 238                        break;
 239                }
 240        }
 241}
 242
 243/* output a variable sequence */
 244static void reg_w_var(struct gspca_dev *gspca_dev,
 245                        const __u8 *seq,
 246                        const __u8 *page4, unsigned int page4_len)
 247{
 248        int index, len;
 249
 250        for (;;) {
 251                index = *seq++;
 252                len = *seq++;
 253                switch (len) {
 254                case END_OF_SEQUENCE:
 255                        return;
 256                case LOAD_PAGE4:
 257                        reg_w_page(gspca_dev, page4, page4_len);
 258                        break;
 259                default:
 260                        if (len > USB_BUF_SZ) {
 261                                gspca_err(gspca_dev, "Incorrect variable sequence\n");
 262                                return;
 263                        }
 264                        while (len > 0) {
 265                                if (len < 8) {
 266                                        reg_w_buf(gspca_dev,
 267                                                index, seq, len);
 268                                        seq += len;
 269                                        break;
 270                                }
 271                                reg_w_buf(gspca_dev, index, seq, 8);
 272                                seq += 8;
 273                                index += 8;
 274                                len -= 8;
 275                        }
 276                }
 277        }
 278        /* not reached */
 279}
 280
 281/* this function is called at probe time for pac7311 */
 282static int sd_config(struct gspca_dev *gspca_dev,
 283                        const struct usb_device_id *id)
 284{
 285        struct cam *cam = &gspca_dev->cam;
 286
 287        cam->cam_mode = vga_mode;
 288        cam->nmodes = ARRAY_SIZE(vga_mode);
 289        cam->input_flags = V4L2_IN_ST_VFLIP;
 290
 291        return 0;
 292}
 293
 294static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
 295{
 296        reg_w(gspca_dev, 0xff, 0x04);
 297        reg_w(gspca_dev, 0x10, val);
 298        /* load registers to sensor (Bit 0, auto clear) */
 299        reg_w(gspca_dev, 0x11, 0x01);
 300}
 301
 302static void setgain(struct gspca_dev *gspca_dev, s32 val)
 303{
 304        reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
 305        reg_w(gspca_dev, 0x0e, 0x00);
 306        reg_w(gspca_dev, 0x0f, gspca_dev->gain->maximum - val + 1);
 307
 308        /* load registers to sensor (Bit 0, auto clear) */
 309        reg_w(gspca_dev, 0x11, 0x01);
 310}
 311
 312static void setexposure(struct gspca_dev *gspca_dev, s32 val)
 313{
 314        reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
 315        reg_w(gspca_dev, 0x02, val);
 316
 317        /* load registers to sensor (Bit 0, auto clear) */
 318        reg_w(gspca_dev, 0x11, 0x01);
 319
 320        /*
 321         * Page 1 register 8 must always be 0x08 except when not in
 322         *  640x480 mode and page 4 reg 2 <= 3 then it must be 9
 323         */
 324        reg_w(gspca_dev, 0xff, 0x01);
 325        if (gspca_dev->pixfmt.width != 640 && val <= 3)
 326                reg_w(gspca_dev, 0x08, 0x09);
 327        else
 328                reg_w(gspca_dev, 0x08, 0x08);
 329
 330        /*
 331         * Page1 register 80 sets the compression balance, normally we
 332         * want / use 0x1c, but for 640x480@30fps we must allow the
 333         * camera to use higher compression or we may run out of
 334         * bandwidth.
 335         */
 336        if (gspca_dev->pixfmt.width == 640 && val == 2)
 337                reg_w(gspca_dev, 0x80, 0x01);
 338        else
 339                reg_w(gspca_dev, 0x80, 0x1c);
 340
 341        /* load registers to sensor (Bit 0, auto clear) */
 342        reg_w(gspca_dev, 0x11, 0x01);
 343}
 344
 345static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
 346{
 347        __u8 data;
 348
 349        reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
 350        data = (hflip ? 0x04 : 0x00) |
 351               (vflip ? 0x08 : 0x00);
 352        reg_w(gspca_dev, 0x21, data);
 353
 354        /* load registers to sensor (Bit 0, auto clear) */
 355        reg_w(gspca_dev, 0x11, 0x01);
 356}
 357
 358/* this function is called at probe and resume time for pac7311 */
 359static int sd_init(struct gspca_dev *gspca_dev)
 360{
 361        reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
 362        return gspca_dev->usb_err;
 363}
 364
 365static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 366{
 367        struct gspca_dev *gspca_dev =
 368                container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 369        struct sd *sd = (struct sd *)gspca_dev;
 370
 371        gspca_dev->usb_err = 0;
 372
 373        if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
 374                /* when switching to autogain set defaults to make sure
 375                   we are on a valid point of the autogain gain /
 376                   exposure knee graph, and give this change time to
 377                   take effect before doing autogain. */
 378                gspca_dev->exposure->val    = PAC7311_EXPOSURE_DEFAULT;
 379                gspca_dev->gain->val        = PAC7311_GAIN_DEFAULT;
 380                sd->autogain_ignore_frames  = PAC_AUTOGAIN_IGNORE_FRAMES;
 381        }
 382
 383        if (!gspca_dev->streaming)
 384                return 0;
 385
 386        switch (ctrl->id) {
 387        case V4L2_CID_CONTRAST:
 388                setcontrast(gspca_dev, ctrl->val);
 389                break;
 390        case V4L2_CID_AUTOGAIN:
 391                if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
 392                        setexposure(gspca_dev, gspca_dev->exposure->val);
 393                if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
 394                        setgain(gspca_dev, gspca_dev->gain->val);
 395                break;
 396        case V4L2_CID_HFLIP:
 397                sethvflip(gspca_dev, sd->hflip->val, 1);
 398                break;
 399        default:
 400                return -EINVAL;
 401        }
 402        return gspca_dev->usb_err;
 403}
 404
 405static const struct v4l2_ctrl_ops sd_ctrl_ops = {
 406        .s_ctrl = sd_s_ctrl,
 407};
 408
 409/* this function is called at probe time */
 410static int sd_init_controls(struct gspca_dev *gspca_dev)
 411{
 412        struct sd *sd = (struct sd *) gspca_dev;
 413        struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 414
 415        gspca_dev->vdev.ctrl_handler = hdl;
 416        v4l2_ctrl_handler_init(hdl, 5);
 417
 418        sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 419                                        V4L2_CID_CONTRAST, 0, 15, 1, 7);
 420        gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 421                                        V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
 422        gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 423                                        V4L2_CID_EXPOSURE, 2, 63, 1,
 424                                        PAC7311_EXPOSURE_DEFAULT);
 425        gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 426                                        V4L2_CID_GAIN, 0, 244, 1,
 427                                        PAC7311_GAIN_DEFAULT);
 428        sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 429                V4L2_CID_HFLIP, 0, 1, 1, 0);
 430
 431        if (hdl->error) {
 432                pr_err("Could not initialize controls\n");
 433                return hdl->error;
 434        }
 435
 436        v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
 437        return 0;
 438}
 439
 440/* -- start the camera -- */
 441static int sd_start(struct gspca_dev *gspca_dev)
 442{
 443        struct sd *sd = (struct sd *) gspca_dev;
 444
 445        sd->sof_read = 0;
 446
 447        reg_w_var(gspca_dev, start_7311,
 448                page4_7311, sizeof(page4_7311));
 449        setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
 450        setgain(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->gain));
 451        setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
 452        sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 1);
 453
 454        /* set correct resolution */
 455        switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
 456        case 2:                                 /* 160x120 */
 457                reg_w(gspca_dev, 0xff, 0x01);
 458                reg_w(gspca_dev, 0x17, 0x20);
 459                reg_w(gspca_dev, 0x87, 0x10);
 460                break;
 461        case 1:                                 /* 320x240 */
 462                reg_w(gspca_dev, 0xff, 0x01);
 463                reg_w(gspca_dev, 0x17, 0x30);
 464                reg_w(gspca_dev, 0x87, 0x11);
 465                break;
 466        case 0:                                 /* 640x480 */
 467                reg_w(gspca_dev, 0xff, 0x01);
 468                reg_w(gspca_dev, 0x17, 0x00);
 469                reg_w(gspca_dev, 0x87, 0x12);
 470                break;
 471        }
 472
 473        sd->sof_read = 0;
 474        sd->autogain_ignore_frames = 0;
 475        atomic_set(&sd->avg_lum, -1);
 476
 477        /* start stream */
 478        reg_w(gspca_dev, 0xff, 0x01);
 479        reg_w(gspca_dev, 0x78, 0x05);
 480
 481        return gspca_dev->usb_err;
 482}
 483
 484static void sd_stopN(struct gspca_dev *gspca_dev)
 485{
 486        reg_w(gspca_dev, 0xff, 0x04);
 487        reg_w(gspca_dev, 0x27, 0x80);
 488        reg_w(gspca_dev, 0x28, 0xca);
 489        reg_w(gspca_dev, 0x29, 0x53);
 490        reg_w(gspca_dev, 0x2a, 0x0e);
 491        reg_w(gspca_dev, 0xff, 0x01);
 492        reg_w(gspca_dev, 0x3e, 0x20);
 493        reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
 494        reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
 495        reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
 496}
 497
 498static void do_autogain(struct gspca_dev *gspca_dev)
 499{
 500        struct sd *sd = (struct sd *) gspca_dev;
 501        int avg_lum = atomic_read(&sd->avg_lum);
 502        int desired_lum, deadzone;
 503
 504        if (avg_lum == -1)
 505                return;
 506
 507        desired_lum = 170;
 508        deadzone = 20;
 509
 510        if (sd->autogain_ignore_frames > 0)
 511                sd->autogain_ignore_frames--;
 512        else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
 513                                                    desired_lum, deadzone))
 514                sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
 515}
 516
 517/* JPEG header, part 1 */
 518static const unsigned char pac_jpeg_header1[] = {
 519  0xff, 0xd8,           /* SOI: Start of Image */
 520
 521  0xff, 0xc0,           /* SOF0: Start of Frame (Baseline DCT) */
 522  0x00, 0x11,           /* length = 17 bytes (including this length field) */
 523  0x08                  /* Precision: 8 */
 524  /* 2 bytes is placed here: number of image lines */
 525  /* 2 bytes is placed here: samples per line */
 526};
 527
 528/* JPEG header, continued */
 529static const unsigned char pac_jpeg_header2[] = {
 530  0x03,                 /* Number of image components: 3 */
 531  0x01, 0x21, 0x00,     /* ID=1, Subsampling 1x1, Quantization table: 0 */
 532  0x02, 0x11, 0x01,     /* ID=2, Subsampling 2x1, Quantization table: 1 */
 533  0x03, 0x11, 0x01,     /* ID=3, Subsampling 2x1, Quantization table: 1 */
 534
 535  0xff, 0xda,           /* SOS: Start Of Scan */
 536  0x00, 0x0c,           /* length = 12 bytes (including this length field) */
 537  0x03,                 /* number of components: 3 */
 538  0x01, 0x00,           /* selector 1, table 0x00 */
 539  0x02, 0x11,           /* selector 2, table 0x11 */
 540  0x03, 0x11,           /* selector 3, table 0x11 */
 541  0x00, 0x3f,           /* Spectral selection: 0 .. 63 */
 542  0x00                  /* Successive approximation: 0 */
 543};
 544
 545static void pac_start_frame(struct gspca_dev *gspca_dev,
 546                __u16 lines, __u16 samples_per_line)
 547{
 548        unsigned char tmpbuf[4];
 549
 550        gspca_frame_add(gspca_dev, FIRST_PACKET,
 551                pac_jpeg_header1, sizeof(pac_jpeg_header1));
 552
 553        tmpbuf[0] = lines >> 8;
 554        tmpbuf[1] = lines & 0xff;
 555        tmpbuf[2] = samples_per_line >> 8;
 556        tmpbuf[3] = samples_per_line & 0xff;
 557
 558        gspca_frame_add(gspca_dev, INTER_PACKET,
 559                tmpbuf, sizeof(tmpbuf));
 560        gspca_frame_add(gspca_dev, INTER_PACKET,
 561                pac_jpeg_header2, sizeof(pac_jpeg_header2));
 562}
 563
 564/* this function is run at interrupt level */
 565static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 566                        u8 *data,                       /* isoc packet */
 567                        int len)                        /* iso packet length */
 568{
 569        struct sd *sd = (struct sd *) gspca_dev;
 570        u8 *image;
 571        unsigned char *sof;
 572
 573        sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
 574        if (sof) {
 575                int n, lum_offset, footer_length;
 576
 577                /*
 578                 * 6 bytes after the FF D9 EOF marker a number of lumination
 579                 * bytes are send corresponding to different parts of the
 580                 * image, the 14th and 15th byte after the EOF seem to
 581                 * correspond to the center of the image.
 582                 */
 583                lum_offset = 24 + sizeof pac_sof_marker;
 584                footer_length = 26;
 585
 586                /* Finish decoding current frame */
 587                n = (sof - data) - (footer_length + sizeof pac_sof_marker);
 588                if (n < 0) {
 589                        gspca_dev->image_len += n;
 590                        n = 0;
 591                } else {
 592                        gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
 593                }
 594                image = gspca_dev->image;
 595                if (image != NULL
 596                 && image[gspca_dev->image_len - 2] == 0xff
 597                 && image[gspca_dev->image_len - 1] == 0xd9)
 598                        gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
 599
 600                n = sof - data;
 601                len -= n;
 602                data = sof;
 603
 604                /* Get average lumination */
 605                if (gspca_dev->last_packet_type == LAST_PACKET &&
 606                                n >= lum_offset)
 607                        atomic_set(&sd->avg_lum, data[-lum_offset] +
 608                                                data[-lum_offset + 1]);
 609                else
 610                        atomic_set(&sd->avg_lum, -1);
 611
 612                /* Start the new frame with the jpeg header */
 613                pac_start_frame(gspca_dev,
 614                        gspca_dev->pixfmt.height, gspca_dev->pixfmt.width);
 615        }
 616        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 617}
 618
 619#if IS_ENABLED(CONFIG_INPUT)
 620static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
 621                        u8 *data,               /* interrupt packet data */
 622                        int len)                /* interrupt packet length */
 623{
 624        int ret = -EINVAL;
 625        u8 data0, data1;
 626
 627        if (len == 2) {
 628                data0 = data[0];
 629                data1 = data[1];
 630                if ((data0 == 0x00 && data1 == 0x11) ||
 631                    (data0 == 0x22 && data1 == 0x33) ||
 632                    (data0 == 0x44 && data1 == 0x55) ||
 633                    (data0 == 0x66 && data1 == 0x77) ||
 634                    (data0 == 0x88 && data1 == 0x99) ||
 635                    (data0 == 0xaa && data1 == 0xbb) ||
 636                    (data0 == 0xcc && data1 == 0xdd) ||
 637                    (data0 == 0xee && data1 == 0xff)) {
 638                        input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
 639                        input_sync(gspca_dev->input_dev);
 640                        input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
 641                        input_sync(gspca_dev->input_dev);
 642                        ret = 0;
 643                }
 644        }
 645
 646        return ret;
 647}
 648#endif
 649
 650static const struct sd_desc sd_desc = {
 651        .name = MODULE_NAME,
 652        .config = sd_config,
 653        .init = sd_init,
 654        .init_controls = sd_init_controls,
 655        .start = sd_start,
 656        .stopN = sd_stopN,
 657        .pkt_scan = sd_pkt_scan,
 658        .dq_callback = do_autogain,
 659#if IS_ENABLED(CONFIG_INPUT)
 660        .int_pkt_scan = sd_int_pkt_scan,
 661#endif
 662};
 663
 664/* -- module initialisation -- */
 665static const struct usb_device_id device_table[] = {
 666        {USB_DEVICE(0x093a, 0x2600)},
 667        {USB_DEVICE(0x093a, 0x2601)},
 668        {USB_DEVICE(0x093a, 0x2603)},
 669        {USB_DEVICE(0x093a, 0x2608)},
 670        {USB_DEVICE(0x093a, 0x260e)},
 671        {USB_DEVICE(0x093a, 0x260f)},
 672        {}
 673};
 674MODULE_DEVICE_TABLE(usb, device_table);
 675
 676/* -- device connect -- */
 677static int sd_probe(struct usb_interface *intf,
 678                        const struct usb_device_id *id)
 679{
 680        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 681                                THIS_MODULE);
 682}
 683
 684static struct usb_driver sd_driver = {
 685        .name = MODULE_NAME,
 686        .id_table = device_table,
 687        .probe = sd_probe,
 688        .disconnect = gspca_disconnect,
 689#ifdef CONFIG_PM
 690        .suspend = gspca_suspend,
 691        .resume = gspca_resume,
 692        .reset_resume = gspca_resume,
 693#endif
 694};
 695
 696module_usb_driver(sd_driver);
 697