linux/drivers/media/usb/gspca/sunplus.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *              Sunplus spca504(abc) spca533 spca536 library
   4 *              Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
   5 *
   6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
   7 */
   8
   9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  10
  11#define MODULE_NAME "sunplus"
  12
  13#include "gspca.h"
  14#include "jpeg.h"
  15
  16MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
  17MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
  18MODULE_LICENSE("GPL");
  19
  20#define QUALITY 85
  21
  22/* specific webcam descriptor */
  23struct sd {
  24        struct gspca_dev gspca_dev;     /* !! must be the first item */
  25
  26        bool autogain;
  27
  28        u8 bridge;
  29#define BRIDGE_SPCA504 0
  30#define BRIDGE_SPCA504B 1
  31#define BRIDGE_SPCA504C 2
  32#define BRIDGE_SPCA533 3
  33#define BRIDGE_SPCA536 4
  34        u8 subtype;
  35#define AiptekMiniPenCam13 1
  36#define LogitechClickSmart420 2
  37#define LogitechClickSmart820 3
  38#define MegapixV4 4
  39#define MegaImageVI 5
  40
  41        u8 jpeg_hdr[JPEG_HDR_SZ];
  42};
  43
  44static const struct v4l2_pix_format vga_mode[] = {
  45        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  46                .bytesperline = 320,
  47                .sizeimage = 320 * 240 * 3 / 8 + 590,
  48                .colorspace = V4L2_COLORSPACE_JPEG,
  49                .priv = 2},
  50        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  51                .bytesperline = 640,
  52                .sizeimage = 640 * 480 * 3 / 8 + 590,
  53                .colorspace = V4L2_COLORSPACE_JPEG,
  54                .priv = 1},
  55};
  56
  57static const struct v4l2_pix_format custom_mode[] = {
  58        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  59                .bytesperline = 320,
  60                .sizeimage = 320 * 240 * 3 / 8 + 590,
  61                .colorspace = V4L2_COLORSPACE_JPEG,
  62                .priv = 2},
  63        {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  64                .bytesperline = 464,
  65                .sizeimage = 464 * 480 * 3 / 8 + 590,
  66                .colorspace = V4L2_COLORSPACE_JPEG,
  67                .priv = 1},
  68};
  69
  70static const struct v4l2_pix_format vga_mode2[] = {
  71        {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  72                .bytesperline = 176,
  73                .sizeimage = 176 * 144 * 3 / 8 + 590,
  74                .colorspace = V4L2_COLORSPACE_JPEG,
  75                .priv = 4},
  76        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  77                .bytesperline = 320,
  78                .sizeimage = 320 * 240 * 3 / 8 + 590,
  79                .colorspace = V4L2_COLORSPACE_JPEG,
  80                .priv = 3},
  81        {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  82                .bytesperline = 352,
  83                .sizeimage = 352 * 288 * 3 / 8 + 590,
  84                .colorspace = V4L2_COLORSPACE_JPEG,
  85                .priv = 2},
  86        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  87                .bytesperline = 640,
  88                .sizeimage = 640 * 480 * 3 / 8 + 590,
  89                .colorspace = V4L2_COLORSPACE_JPEG,
  90                .priv = 1},
  91};
  92
  93#define SPCA50X_OFFSET_DATA 10
  94#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
  95#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
  96#define SPCA504_PCCAM600_OFFSET_MODE     5
  97#define SPCA504_PCCAM600_OFFSET_DATA     14
  98 /* Frame packet header offsets for the spca533 */
  99#define SPCA533_OFFSET_DATA     16
 100#define SPCA533_OFFSET_FRAMSEQ  15
 101/* Frame packet header offsets for the spca536 */
 102#define SPCA536_OFFSET_DATA     4
 103#define SPCA536_OFFSET_FRAMSEQ  1
 104
 105struct cmd {
 106        u8 req;
 107        u16 val;
 108        u16 idx;
 109};
 110
 111/* Initialisation data for the Creative PC-CAM 600 */
 112static const struct cmd spca504_pccam600_init_data[] = {
 113/*      {0xa0, 0x0000, 0x0503},  * capture mode */
 114        {0x00, 0x0000, 0x2000},
 115        {0x00, 0x0013, 0x2301},
 116        {0x00, 0x0003, 0x2000},
 117        {0x00, 0x0001, 0x21ac},
 118        {0x00, 0x0001, 0x21a6},
 119        {0x00, 0x0000, 0x21a7}, /* brightness */
 120        {0x00, 0x0020, 0x21a8}, /* contrast */
 121        {0x00, 0x0001, 0x21ac}, /* sat/hue */
 122        {0x00, 0x0000, 0x21ad}, /* hue */
 123        {0x00, 0x001a, 0x21ae}, /* saturation */
 124        {0x00, 0x0002, 0x21a3}, /* gamma */
 125        {0x30, 0x0154, 0x0008},
 126        {0x30, 0x0004, 0x0006},
 127        {0x30, 0x0258, 0x0009},
 128        {0x30, 0x0004, 0x0000},
 129        {0x30, 0x0093, 0x0004},
 130        {0x30, 0x0066, 0x0005},
 131        {0x00, 0x0000, 0x2000},
 132        {0x00, 0x0013, 0x2301},
 133        {0x00, 0x0003, 0x2000},
 134        {0x00, 0x0013, 0x2301},
 135        {0x00, 0x0003, 0x2000},
 136};
 137
 138/* Creative PC-CAM 600 specific open data, sent before using the
 139 * generic initialisation data from spca504_open_data.
 140 */
 141static const struct cmd spca504_pccam600_open_data[] = {
 142        {0x00, 0x0001, 0x2501},
 143        {0x20, 0x0500, 0x0001}, /* snapshot mode */
 144        {0x00, 0x0003, 0x2880},
 145        {0x00, 0x0001, 0x2881},
 146};
 147
 148/* Initialisation data for the logitech clicksmart 420 */
 149static const struct cmd spca504A_clicksmart420_init_data[] = {
 150/*      {0xa0, 0x0000, 0x0503},  * capture mode */
 151        {0x00, 0x0000, 0x2000},
 152        {0x00, 0x0013, 0x2301},
 153        {0x00, 0x0003, 0x2000},
 154        {0x00, 0x0001, 0x21ac},
 155        {0x00, 0x0001, 0x21a6},
 156        {0x00, 0x0000, 0x21a7}, /* brightness */
 157        {0x00, 0x0020, 0x21a8}, /* contrast */
 158        {0x00, 0x0001, 0x21ac}, /* sat/hue */
 159        {0x00, 0x0000, 0x21ad}, /* hue */
 160        {0x00, 0x001a, 0x21ae}, /* saturation */
 161        {0x00, 0x0002, 0x21a3}, /* gamma */
 162        {0x30, 0x0004, 0x000a},
 163        {0xb0, 0x0001, 0x0000},
 164
 165        {0xa1, 0x0080, 0x0001},
 166        {0x30, 0x0049, 0x0000},
 167        {0x30, 0x0060, 0x0005},
 168        {0x0c, 0x0004, 0x0000},
 169        {0x00, 0x0000, 0x0000},
 170        {0x00, 0x0000, 0x2000},
 171        {0x00, 0x0013, 0x2301},
 172        {0x00, 0x0003, 0x2000},
 173};
 174
 175/* clicksmart 420 open data ? */
 176static const struct cmd spca504A_clicksmart420_open_data[] = {
 177        {0x00, 0x0001, 0x2501},
 178        {0x20, 0x0502, 0x0000},
 179        {0x06, 0x0000, 0x0000},
 180        {0x00, 0x0004, 0x2880},
 181        {0x00, 0x0001, 0x2881},
 182
 183        {0xa0, 0x0000, 0x0503},
 184};
 185
 186static const u8 qtable_creative_pccam[2][64] = {
 187        {                               /* Q-table Y-components */
 188         0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
 189         0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
 190         0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
 191         0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
 192         0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
 193         0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
 194         0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
 195         0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
 196        {                               /* Q-table C-components */
 197         0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
 198         0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
 199         0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 200         0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 201         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 202         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 203         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 204         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
 205};
 206
 207/* FIXME: This Q-table is identical to the Creative PC-CAM one,
 208 *              except for one byte. Possibly a typo?
 209 *              NWG: 18/05/2003.
 210 */
 211static const u8 qtable_spca504_default[2][64] = {
 212        {                               /* Q-table Y-components */
 213         0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
 214         0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
 215         0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
 216         0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
 217         0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
 218         0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
 219         0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
 220         0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
 221         },
 222        {                               /* Q-table C-components */
 223         0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
 224         0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
 225         0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 226         0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 227         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 228         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 229         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 230         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
 231};
 232
 233/* read <len> bytes to gspca_dev->usb_buf */
 234static void reg_r(struct gspca_dev *gspca_dev,
 235                  u8 req,
 236                  u16 index,
 237                  u16 len)
 238{
 239        int ret;
 240
 241        if (len > USB_BUF_SZ) {
 242                gspca_err(gspca_dev, "reg_r: buffer overflow\n");
 243                return;
 244        }
 245        if (len == 0) {
 246                gspca_err(gspca_dev, "reg_r: zero-length read\n");
 247                return;
 248        }
 249        if (gspca_dev->usb_err < 0)
 250                return;
 251        ret = usb_control_msg(gspca_dev->dev,
 252                        usb_rcvctrlpipe(gspca_dev->dev, 0),
 253                        req,
 254                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 255                        0,              /* value */
 256                        index,
 257                        gspca_dev->usb_buf, len,
 258                        500);
 259        if (ret < 0) {
 260                pr_err("reg_r err %d\n", ret);
 261                gspca_dev->usb_err = ret;
 262                /*
 263                 * Make sure the buffer is zeroed to avoid uninitialized
 264                 * values.
 265                 */
 266                memset(gspca_dev->usb_buf, 0, USB_BUF_SZ);
 267        }
 268}
 269
 270/* write one byte */
 271static void reg_w_1(struct gspca_dev *gspca_dev,
 272                   u8 req,
 273                   u16 value,
 274                   u16 index,
 275                   u16 byte)
 276{
 277        int ret;
 278
 279        if (gspca_dev->usb_err < 0)
 280                return;
 281        gspca_dev->usb_buf[0] = byte;
 282        ret = usb_control_msg(gspca_dev->dev,
 283                        usb_sndctrlpipe(gspca_dev->dev, 0),
 284                        req,
 285                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 286                        value, index,
 287                        gspca_dev->usb_buf, 1,
 288                        500);
 289        if (ret < 0) {
 290                pr_err("reg_w_1 err %d\n", ret);
 291                gspca_dev->usb_err = ret;
 292        }
 293}
 294
 295/* write req / index / value */
 296static void reg_w_riv(struct gspca_dev *gspca_dev,
 297                     u8 req, u16 index, u16 value)
 298{
 299        struct usb_device *dev = gspca_dev->dev;
 300        int ret;
 301
 302        if (gspca_dev->usb_err < 0)
 303                return;
 304        ret = usb_control_msg(dev,
 305                        usb_sndctrlpipe(dev, 0),
 306                        req,
 307                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 308                        value, index, NULL, 0, 500);
 309        if (ret < 0) {
 310                pr_err("reg_w_riv err %d\n", ret);
 311                gspca_dev->usb_err = ret;
 312                return;
 313        }
 314        gspca_dbg(gspca_dev, D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x\n",
 315                  req, index, value);
 316}
 317
 318static void write_vector(struct gspca_dev *gspca_dev,
 319                        const struct cmd *data, int ncmds)
 320{
 321        while (--ncmds >= 0) {
 322                reg_w_riv(gspca_dev, data->req, data->idx, data->val);
 323                data++;
 324        }
 325}
 326
 327static void setup_qtable(struct gspca_dev *gspca_dev,
 328                        const u8 qtable[2][64])
 329{
 330        int i;
 331
 332        /* loop over y components */
 333        for (i = 0; i < 64; i++)
 334                reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
 335
 336        /* loop over c components */
 337        for (i = 0; i < 64; i++)
 338                reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
 339}
 340
 341static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
 342                             u8 req, u16 idx, u16 val)
 343{
 344        reg_w_riv(gspca_dev, req, idx, val);
 345        reg_r(gspca_dev, 0x01, 0x0001, 1);
 346        gspca_dbg(gspca_dev, D_FRAM, "before wait 0x%04x\n",
 347                  gspca_dev->usb_buf[0]);
 348        reg_w_riv(gspca_dev, req, idx, val);
 349
 350        msleep(200);
 351        reg_r(gspca_dev, 0x01, 0x0001, 1);
 352        gspca_dbg(gspca_dev, D_FRAM, "after wait 0x%04x\n",
 353                  gspca_dev->usb_buf[0]);
 354}
 355
 356static void spca504_read_info(struct gspca_dev *gspca_dev)
 357{
 358        int i;
 359        u8 info[6];
 360
 361        if (gspca_debug < D_STREAM)
 362                return;
 363
 364        for (i = 0; i < 6; i++) {
 365                reg_r(gspca_dev, 0, i, 1);
 366                info[i] = gspca_dev->usb_buf[0];
 367        }
 368        gspca_dbg(gspca_dev, D_STREAM,
 369                  "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0\n",
 370                  info[0], info[1], info[2],
 371                  info[3], info[4], info[5]);
 372}
 373
 374static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
 375                        u8 req,
 376                        u16 idx, u16 val, u8 endcode, u8 count)
 377{
 378        u16 status;
 379
 380        reg_w_riv(gspca_dev, req, idx, val);
 381        reg_r(gspca_dev, 0x01, 0x0001, 1);
 382        if (gspca_dev->usb_err < 0)
 383                return;
 384        gspca_dbg(gspca_dev, D_FRAM, "Status 0x%02x Need 0x%02x\n",
 385                  gspca_dev->usb_buf[0], endcode);
 386        if (!count)
 387                return;
 388        count = 200;
 389        while (--count > 0) {
 390                msleep(10);
 391                /* gsmart mini2 write a each wait setting 1 ms is enough */
 392/*              reg_w_riv(gspca_dev, req, idx, val); */
 393                reg_r(gspca_dev, 0x01, 0x0001, 1);
 394                status = gspca_dev->usb_buf[0];
 395                if (status == endcode) {
 396                        gspca_dbg(gspca_dev, D_FRAM, "status 0x%04x after wait %d\n",
 397                                  status, 200 - count);
 398                                break;
 399                }
 400        }
 401}
 402
 403static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
 404{
 405        int count = 10;
 406
 407        while (--count > 0) {
 408                reg_r(gspca_dev, 0x21, 0, 1);
 409                if ((gspca_dev->usb_buf[0] & 0x01) == 0)
 410                        break;
 411                msleep(10);
 412        }
 413}
 414
 415static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
 416{
 417        int count = 50;
 418
 419        while (--count > 0) {
 420                reg_r(gspca_dev, 0x21, 1, 1);
 421                if (gspca_dev->usb_buf[0] != 0) {
 422                        reg_w_1(gspca_dev, 0x21, 0, 1, 0);
 423                        reg_r(gspca_dev, 0x21, 1, 1);
 424                        spca504B_PollingDataReady(gspca_dev);
 425                        break;
 426                }
 427                msleep(10);
 428        }
 429}
 430
 431static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
 432{
 433        u8 *data;
 434
 435        if (gspca_debug < D_STREAM)
 436                return;
 437
 438        data = gspca_dev->usb_buf;
 439        reg_r(gspca_dev, 0x20, 0, 5);
 440        gspca_dbg(gspca_dev, D_STREAM, "FirmWare: %d %d %d %d %d\n",
 441                  data[0], data[1], data[2], data[3], data[4]);
 442        reg_r(gspca_dev, 0x23, 0, 64);
 443        reg_r(gspca_dev, 0x23, 1, 64);
 444}
 445
 446static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
 447{
 448        struct sd *sd = (struct sd *) gspca_dev;
 449        u8 Size;
 450
 451        Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 452        switch (sd->bridge) {
 453        case BRIDGE_SPCA533:
 454                reg_w_riv(gspca_dev, 0x31, 0, 0);
 455                spca504B_WaitCmdStatus(gspca_dev);
 456                spca504B_PollingDataReady(gspca_dev);
 457                spca50x_GetFirmware(gspca_dev);
 458
 459                reg_w_1(gspca_dev, 0x24, 0, 8, 2);              /* type */
 460                reg_r(gspca_dev, 0x24, 8, 1);
 461
 462                reg_w_1(gspca_dev, 0x25, 0, 4, Size);
 463                reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
 464                spca504B_PollingDataReady(gspca_dev);
 465
 466                /* Init the cam width height with some values get on init ? */
 467                reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
 468                spca504B_WaitCmdStatus(gspca_dev);
 469                spca504B_PollingDataReady(gspca_dev);
 470                break;
 471        default:
 472/* case BRIDGE_SPCA504B: */
 473/* case BRIDGE_SPCA536: */
 474                reg_w_1(gspca_dev, 0x25, 0, 4, Size);
 475                reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
 476                reg_w_1(gspca_dev, 0x27, 0, 0, 6);
 477                reg_r(gspca_dev, 0x27, 0, 1);                   /* type */
 478                spca504B_PollingDataReady(gspca_dev);
 479                break;
 480        case BRIDGE_SPCA504:
 481                Size += 3;
 482                if (sd->subtype == AiptekMiniPenCam13) {
 483                        /* spca504a aiptek */
 484                        spca504A_acknowledged_command(gspca_dev,
 485                                                0x08, Size, 0,
 486                                                0x80 | (Size & 0x0f), 1);
 487                        spca504A_acknowledged_command(gspca_dev,
 488                                                        1, 3, 0, 0x9f, 0);
 489                } else {
 490                        spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
 491                }
 492                break;
 493        case BRIDGE_SPCA504C:
 494                /* capture mode */
 495                reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
 496                reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
 497                break;
 498        }
 499}
 500
 501static void spca504_wait_status(struct gspca_dev *gspca_dev)
 502{
 503        int cnt;
 504
 505        cnt = 256;
 506        while (--cnt > 0) {
 507                /* With this we get the status, when return 0 it's all ok */
 508                reg_r(gspca_dev, 0x06, 0x00, 1);
 509                if (gspca_dev->usb_buf[0] == 0)
 510                        return;
 511                msleep(10);
 512        }
 513}
 514
 515static void spca504B_setQtable(struct gspca_dev *gspca_dev)
 516{
 517        reg_w_1(gspca_dev, 0x26, 0, 0, 3);
 518        reg_r(gspca_dev, 0x26, 0, 1);
 519        spca504B_PollingDataReady(gspca_dev);
 520}
 521
 522static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
 523{
 524        struct sd *sd = (struct sd *) gspca_dev;
 525        u16 reg;
 526
 527        reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
 528        reg_w_riv(gspca_dev, 0x00, reg, val);
 529}
 530
 531static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
 532{
 533        struct sd *sd = (struct sd *) gspca_dev;
 534        u16 reg;
 535
 536        reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
 537        reg_w_riv(gspca_dev, 0x00, reg, val);
 538}
 539
 540static void setcolors(struct gspca_dev *gspca_dev, s32 val)
 541{
 542        struct sd *sd = (struct sd *) gspca_dev;
 543        u16 reg;
 544
 545        reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
 546        reg_w_riv(gspca_dev, 0x00, reg, val);
 547}
 548
 549static void init_ctl_reg(struct gspca_dev *gspca_dev)
 550{
 551        struct sd *sd = (struct sd *) gspca_dev;
 552        int pollreg = 1;
 553
 554        switch (sd->bridge) {
 555        case BRIDGE_SPCA504:
 556        case BRIDGE_SPCA504C:
 557                pollreg = 0;
 558                fallthrough;
 559        default:
 560/*      case BRIDGE_SPCA533: */
 561/*      case BRIDGE_SPCA504B: */
 562                reg_w_riv(gspca_dev, 0, 0x21ad, 0x00);  /* hue */
 563                reg_w_riv(gspca_dev, 0, 0x21ac, 0x01);  /* sat/hue */
 564                reg_w_riv(gspca_dev, 0, 0x21a3, 0x00);  /* gamma */
 565                break;
 566        case BRIDGE_SPCA536:
 567                reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
 568                reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
 569                reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
 570                break;
 571        }
 572        if (pollreg)
 573                spca504B_PollingDataReady(gspca_dev);
 574}
 575
 576/* this function is called at probe time */
 577static int sd_config(struct gspca_dev *gspca_dev,
 578                        const struct usb_device_id *id)
 579{
 580        struct sd *sd = (struct sd *) gspca_dev;
 581        struct cam *cam;
 582
 583        cam = &gspca_dev->cam;
 584
 585        sd->bridge = id->driver_info >> 8;
 586        sd->subtype = id->driver_info;
 587
 588        if (sd->subtype == AiptekMiniPenCam13) {
 589
 590                /* try to get the firmware as some cam answer 2.0.1.2.2
 591                 * and should be a spca504b then overwrite that setting */
 592                reg_r(gspca_dev, 0x20, 0, 1);
 593                switch (gspca_dev->usb_buf[0]) {
 594                case 1:
 595                        break;          /* (right bridge/subtype) */
 596                case 2:
 597                        sd->bridge = BRIDGE_SPCA504B;
 598                        sd->subtype = 0;
 599                        break;
 600                default:
 601                        return -ENODEV;
 602                }
 603        }
 604
 605        switch (sd->bridge) {
 606        default:
 607/*      case BRIDGE_SPCA504B: */
 608/*      case BRIDGE_SPCA504: */
 609/*      case BRIDGE_SPCA536: */
 610                cam->cam_mode = vga_mode;
 611                cam->nmodes = ARRAY_SIZE(vga_mode);
 612                break;
 613        case BRIDGE_SPCA533:
 614                cam->cam_mode = custom_mode;
 615                if (sd->subtype == MegaImageVI)         /* 320x240 only */
 616                        cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
 617                else
 618                        cam->nmodes = ARRAY_SIZE(custom_mode);
 619                break;
 620        case BRIDGE_SPCA504C:
 621                cam->cam_mode = vga_mode2;
 622                cam->nmodes = ARRAY_SIZE(vga_mode2);
 623                break;
 624        }
 625        return 0;
 626}
 627
 628/* this function is called at probe and resume time */
 629static int sd_init(struct gspca_dev *gspca_dev)
 630{
 631        struct sd *sd = (struct sd *) gspca_dev;
 632
 633        switch (sd->bridge) {
 634        case BRIDGE_SPCA504B:
 635                reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
 636                reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
 637                reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
 638                reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
 639                reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
 640                reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
 641                fallthrough;
 642        case BRIDGE_SPCA533:
 643                spca504B_PollingDataReady(gspca_dev);
 644                spca50x_GetFirmware(gspca_dev);
 645                break;
 646        case BRIDGE_SPCA536:
 647                spca50x_GetFirmware(gspca_dev);
 648                reg_r(gspca_dev, 0x00, 0x5002, 1);
 649                reg_w_1(gspca_dev, 0x24, 0, 0, 0);
 650                reg_r(gspca_dev, 0x24, 0, 1);
 651                spca504B_PollingDataReady(gspca_dev);
 652                reg_w_riv(gspca_dev, 0x34, 0, 0);
 653                spca504B_WaitCmdStatus(gspca_dev);
 654                break;
 655        case BRIDGE_SPCA504C:   /* pccam600 */
 656                gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504 (PC-CAM 600)\n");
 657                reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
 658                reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001);     /* reset */
 659                spca504_wait_status(gspca_dev);
 660                if (sd->subtype == LogitechClickSmart420)
 661                        write_vector(gspca_dev,
 662                                spca504A_clicksmart420_open_data,
 663                                ARRAY_SIZE(spca504A_clicksmart420_open_data));
 664                else
 665                        write_vector(gspca_dev, spca504_pccam600_open_data,
 666                                ARRAY_SIZE(spca504_pccam600_open_data));
 667                setup_qtable(gspca_dev, qtable_creative_pccam);
 668                break;
 669        default:
 670/*      case BRIDGE_SPCA504: */
 671                gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504\n");
 672                if (sd->subtype == AiptekMiniPenCam13) {
 673                        spca504_read_info(gspca_dev);
 674
 675                        /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
 676                        spca504A_acknowledged_command(gspca_dev, 0x24,
 677                                                        8, 3, 0x9e, 1);
 678                        /* Twice sequential need status 0xff->0x9e->0x9d */
 679                        spca504A_acknowledged_command(gspca_dev, 0x24,
 680                                                        8, 3, 0x9e, 0);
 681
 682                        spca504A_acknowledged_command(gspca_dev, 0x24,
 683                                                        0, 0, 0x9d, 1);
 684                        /******************************/
 685                        /* spca504a aiptek */
 686                        spca504A_acknowledged_command(gspca_dev, 0x08,
 687                                                        6, 0, 0x86, 1);
 688/*                      reg_write (dev, 0, 0x2000, 0); */
 689/*                      reg_write (dev, 0, 0x2883, 1); */
 690/*                      spca504A_acknowledged_command (gspca_dev, 0x08,
 691                                                        6, 0, 0x86, 1); */
 692/*                      spca504A_acknowledged_command (gspca_dev, 0x24,
 693                                                        0, 0, 0x9D, 1); */
 694                        reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
 695                                                        /* L92 sno1t.txt */
 696                        reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
 697                        spca504A_acknowledged_command(gspca_dev, 0x01,
 698                                                        0x0f, 0, 0xff, 0);
 699                }
 700                /* setup qtable */
 701                reg_w_riv(gspca_dev, 0, 0x2000, 0);
 702                reg_w_riv(gspca_dev, 0, 0x2883, 1);
 703                setup_qtable(gspca_dev, qtable_spca504_default);
 704                break;
 705        }
 706        return gspca_dev->usb_err;
 707}
 708
 709static int sd_start(struct gspca_dev *gspca_dev)
 710{
 711        struct sd *sd = (struct sd *) gspca_dev;
 712        int enable;
 713
 714        /* create the JPEG header */
 715        jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
 716                        gspca_dev->pixfmt.width,
 717                        0x22);          /* JPEG 411 */
 718        jpeg_set_qual(sd->jpeg_hdr, QUALITY);
 719
 720        if (sd->bridge == BRIDGE_SPCA504B)
 721                spca504B_setQtable(gspca_dev);
 722        spca504B_SetSizeType(gspca_dev);
 723        switch (sd->bridge) {
 724        default:
 725/*      case BRIDGE_SPCA504B: */
 726/*      case BRIDGE_SPCA533: */
 727/*      case BRIDGE_SPCA536: */
 728                switch (sd->subtype) {
 729                case MegapixV4:
 730                case LogitechClickSmart820:
 731                case MegaImageVI:
 732                        reg_w_riv(gspca_dev, 0xf0, 0, 0);
 733                        spca504B_WaitCmdStatus(gspca_dev);
 734                        reg_w_riv(gspca_dev, 0xf0, 4, 0);
 735                        spca504B_WaitCmdStatus(gspca_dev);
 736                        break;
 737                default:
 738                        reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
 739                        spca504B_WaitCmdStatus(gspca_dev);
 740                        spca504B_PollingDataReady(gspca_dev);
 741                        break;
 742                }
 743                break;
 744        case BRIDGE_SPCA504:
 745                if (sd->subtype == AiptekMiniPenCam13) {
 746                        spca504_read_info(gspca_dev);
 747
 748                        /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
 749                        spca504A_acknowledged_command(gspca_dev, 0x24,
 750                                                        8, 3, 0x9e, 1);
 751                        /* Twice sequential need status 0xff->0x9e->0x9d */
 752                        spca504A_acknowledged_command(gspca_dev, 0x24,
 753                                                        8, 3, 0x9e, 0);
 754                        spca504A_acknowledged_command(gspca_dev, 0x24,
 755                                                        0, 0, 0x9d, 1);
 756                } else {
 757                        spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
 758                        spca504_read_info(gspca_dev);
 759                        spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
 760                        spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
 761                }
 762                spca504B_SetSizeType(gspca_dev);
 763                reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
 764                                                        /* L92 sno1t.txt */
 765                reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
 766                break;
 767        case BRIDGE_SPCA504C:
 768                if (sd->subtype == LogitechClickSmart420) {
 769                        write_vector(gspca_dev,
 770                                spca504A_clicksmart420_init_data,
 771                                ARRAY_SIZE(spca504A_clicksmart420_init_data));
 772                } else {
 773                        write_vector(gspca_dev, spca504_pccam600_init_data,
 774                                ARRAY_SIZE(spca504_pccam600_init_data));
 775                }
 776                enable = (sd->autogain ? 0x04 : 0x01);
 777                reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
 778                                                        /* auto exposure */
 779                reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
 780                                                        /* auto whiteness */
 781
 782                /* set default exposure compensation and whiteness balance */
 783                reg_w_riv(gspca_dev, 0x30, 0x0001, 800);        /* ~ 20 fps */
 784                reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
 785                spca504B_SetSizeType(gspca_dev);
 786                break;
 787        }
 788        init_ctl_reg(gspca_dev);
 789        return gspca_dev->usb_err;
 790}
 791
 792static void sd_stopN(struct gspca_dev *gspca_dev)
 793{
 794        struct sd *sd = (struct sd *) gspca_dev;
 795
 796        switch (sd->bridge) {
 797        default:
 798/*      case BRIDGE_SPCA533: */
 799/*      case BRIDGE_SPCA536: */
 800/*      case BRIDGE_SPCA504B: */
 801                reg_w_riv(gspca_dev, 0x31, 0, 0);
 802                spca504B_WaitCmdStatus(gspca_dev);
 803                spca504B_PollingDataReady(gspca_dev);
 804                break;
 805        case BRIDGE_SPCA504:
 806        case BRIDGE_SPCA504C:
 807                reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
 808
 809                if (sd->subtype == AiptekMiniPenCam13) {
 810                        /* spca504a aiptek */
 811/*                      spca504A_acknowledged_command(gspca_dev, 0x08,
 812                                                         6, 0, 0x86, 1); */
 813                        spca504A_acknowledged_command(gspca_dev, 0x24,
 814                                                        0x00, 0x00, 0x9d, 1);
 815                        spca504A_acknowledged_command(gspca_dev, 0x01,
 816                                                        0x0f, 0x00, 0xff, 1);
 817                } else {
 818                        spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
 819                        reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
 820                }
 821                break;
 822        }
 823}
 824
 825static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 826                        u8 *data,                       /* isoc packet */
 827                        int len)                        /* iso packet length */
 828{
 829        struct sd *sd = (struct sd *) gspca_dev;
 830        int i, sof = 0;
 831        static u8 ffd9[] = {0xff, 0xd9};
 832
 833/* frames are jpeg 4.1.1 without 0xff escape */
 834        switch (sd->bridge) {
 835        case BRIDGE_SPCA533:
 836                if (data[0] == 0xff) {
 837                        if (data[1] != 0x01) {  /* drop packet */
 838/*                              gspca_dev->last_packet_type = DISCARD_PACKET; */
 839                                return;
 840                        }
 841                        sof = 1;
 842                        data += SPCA533_OFFSET_DATA;
 843                        len -= SPCA533_OFFSET_DATA;
 844                } else {
 845                        data += 1;
 846                        len -= 1;
 847                }
 848                break;
 849        case BRIDGE_SPCA536:
 850                if (data[0] == 0xff) {
 851                        sof = 1;
 852                        data += SPCA536_OFFSET_DATA;
 853                        len -= SPCA536_OFFSET_DATA;
 854                } else {
 855                        data += 2;
 856                        len -= 2;
 857                }
 858                break;
 859        default:
 860/*      case BRIDGE_SPCA504: */
 861/*      case BRIDGE_SPCA504B: */
 862                switch (data[0]) {
 863                case 0xfe:                      /* start of frame */
 864                        sof = 1;
 865                        data += SPCA50X_OFFSET_DATA;
 866                        len -= SPCA50X_OFFSET_DATA;
 867                        break;
 868                case 0xff:                      /* drop packet */
 869/*                      gspca_dev->last_packet_type = DISCARD_PACKET; */
 870                        return;
 871                default:
 872                        data += 1;
 873                        len -= 1;
 874                        break;
 875                }
 876                break;
 877        case BRIDGE_SPCA504C:
 878                switch (data[0]) {
 879                case 0xfe:                      /* start of frame */
 880                        sof = 1;
 881                        data += SPCA504_PCCAM600_OFFSET_DATA;
 882                        len -= SPCA504_PCCAM600_OFFSET_DATA;
 883                        break;
 884                case 0xff:                      /* drop packet */
 885/*                      gspca_dev->last_packet_type = DISCARD_PACKET; */
 886                        return;
 887                default:
 888                        data += 1;
 889                        len -= 1;
 890                        break;
 891                }
 892                break;
 893        }
 894        if (sof) {              /* start of frame */
 895                gspca_frame_add(gspca_dev, LAST_PACKET,
 896                                ffd9, 2);
 897
 898                /* put the JPEG header in the new frame */
 899                gspca_frame_add(gspca_dev, FIRST_PACKET,
 900                        sd->jpeg_hdr, JPEG_HDR_SZ);
 901        }
 902
 903        /* add 0x00 after 0xff */
 904        i = 0;
 905        do {
 906                if (data[i] == 0xff) {
 907                        gspca_frame_add(gspca_dev, INTER_PACKET,
 908                                        data, i + 1);
 909                        len -= i;
 910                        data += i;
 911                        *data = 0x00;
 912                        i = 0;
 913                }
 914                i++;
 915        } while (i < len);
 916        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 917}
 918
 919static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 920{
 921        struct gspca_dev *gspca_dev =
 922                container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 923        struct sd *sd = (struct sd *)gspca_dev;
 924
 925        gspca_dev->usb_err = 0;
 926
 927        if (!gspca_dev->streaming)
 928                return 0;
 929
 930        switch (ctrl->id) {
 931        case V4L2_CID_BRIGHTNESS:
 932                setbrightness(gspca_dev, ctrl->val);
 933                break;
 934        case V4L2_CID_CONTRAST:
 935                setcontrast(gspca_dev, ctrl->val);
 936                break;
 937        case V4L2_CID_SATURATION:
 938                setcolors(gspca_dev, ctrl->val);
 939                break;
 940        case V4L2_CID_AUTOGAIN:
 941                sd->autogain = ctrl->val;
 942                break;
 943        }
 944        return gspca_dev->usb_err;
 945}
 946
 947static const struct v4l2_ctrl_ops sd_ctrl_ops = {
 948        .s_ctrl = sd_s_ctrl,
 949};
 950
 951static int sd_init_controls(struct gspca_dev *gspca_dev)
 952{
 953        struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 954
 955        gspca_dev->vdev.ctrl_handler = hdl;
 956        v4l2_ctrl_handler_init(hdl, 4);
 957        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 958                        V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
 959        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 960                        V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
 961        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 962                        V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
 963        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 964                        V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
 965
 966        if (hdl->error) {
 967                pr_err("Could not initialize controls\n");
 968                return hdl->error;
 969        }
 970        return 0;
 971}
 972
 973/* sub-driver description */
 974static const struct sd_desc sd_desc = {
 975        .name = MODULE_NAME,
 976        .config = sd_config,
 977        .init = sd_init,
 978        .init_controls = sd_init_controls,
 979        .start = sd_start,
 980        .stopN = sd_stopN,
 981        .pkt_scan = sd_pkt_scan,
 982};
 983
 984/* -- module initialisation -- */
 985#define BS(bridge, subtype) \
 986        .driver_info = (BRIDGE_ ## bridge << 8) \
 987                        | (subtype)
 988static const struct usb_device_id device_table[] = {
 989        {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
 990        {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
 991        {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
 992        {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
 993        {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
 994        {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
 995        {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
 996        {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
 997        {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
 998        {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
 999        {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1000        {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1001        {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1002        {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1003        {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1004        {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1005        {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1006        {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1007        {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1008        {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1009        {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1010        {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1011        {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1012        {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1013        {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1014        {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1015        {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1016        {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1017        {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1018        {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1019        {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1020        {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1021        {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1022        {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1023        {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1024        {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1025        {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1026        {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1027        {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
1028        {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1029        {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1030        {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1031        {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1032        {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1033        {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1034        {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1035        {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1036        {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1037        {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1038        {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1039        {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1040        {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1041        {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1042        {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1043        {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1044        {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1045        {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1046        {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1047        {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1048        {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1049        {}
1050};
1051MODULE_DEVICE_TABLE(usb, device_table);
1052
1053/* -- device connect -- */
1054static int sd_probe(struct usb_interface *intf,
1055                        const struct usb_device_id *id)
1056{
1057        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1058                                THIS_MODULE);
1059}
1060
1061static struct usb_driver sd_driver = {
1062        .name = MODULE_NAME,
1063        .id_table = device_table,
1064        .probe = sd_probe,
1065        .disconnect = gspca_disconnect,
1066#ifdef CONFIG_PM
1067        .suspend = gspca_suspend,
1068        .resume = gspca_resume,
1069        .reset_resume = gspca_resume,
1070#endif
1071};
1072
1073module_usb_driver(sd_driver);
1074