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