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 (gspca_dev->usb_err < 0)
 246                return;
 247        ret = usb_control_msg(gspca_dev->dev,
 248                        usb_rcvctrlpipe(gspca_dev->dev, 0),
 249                        req,
 250                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 251                        0,              /* value */
 252                        index,
 253                        len ? gspca_dev->usb_buf : NULL, len,
 254                        500);
 255        if (ret < 0) {
 256                pr_err("reg_r err %d\n", ret);
 257                gspca_dev->usb_err = ret;
 258        }
 259}
 260
 261/* write one byte */
 262static void reg_w_1(struct gspca_dev *gspca_dev,
 263                   u8 req,
 264                   u16 value,
 265                   u16 index,
 266                   u16 byte)
 267{
 268        int ret;
 269
 270        if (gspca_dev->usb_err < 0)
 271                return;
 272        gspca_dev->usb_buf[0] = byte;
 273        ret = usb_control_msg(gspca_dev->dev,
 274                        usb_sndctrlpipe(gspca_dev->dev, 0),
 275                        req,
 276                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 277                        value, index,
 278                        gspca_dev->usb_buf, 1,
 279                        500);
 280        if (ret < 0) {
 281                pr_err("reg_w_1 err %d\n", ret);
 282                gspca_dev->usb_err = ret;
 283        }
 284}
 285
 286/* write req / index / value */
 287static void reg_w_riv(struct gspca_dev *gspca_dev,
 288                     u8 req, u16 index, u16 value)
 289{
 290        struct usb_device *dev = gspca_dev->dev;
 291        int ret;
 292
 293        if (gspca_dev->usb_err < 0)
 294                return;
 295        ret = usb_control_msg(dev,
 296                        usb_sndctrlpipe(dev, 0),
 297                        req,
 298                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 299                        value, index, NULL, 0, 500);
 300        if (ret < 0) {
 301                pr_err("reg_w_riv err %d\n", ret);
 302                gspca_dev->usb_err = ret;
 303                return;
 304        }
 305        gspca_dbg(gspca_dev, D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x\n",
 306                  req, index, value);
 307}
 308
 309static void write_vector(struct gspca_dev *gspca_dev,
 310                        const struct cmd *data, int ncmds)
 311{
 312        while (--ncmds >= 0) {
 313                reg_w_riv(gspca_dev, data->req, data->idx, data->val);
 314                data++;
 315        }
 316}
 317
 318static void setup_qtable(struct gspca_dev *gspca_dev,
 319                        const u8 qtable[2][64])
 320{
 321        int i;
 322
 323        /* loop over y components */
 324        for (i = 0; i < 64; i++)
 325                reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
 326
 327        /* loop over c components */
 328        for (i = 0; i < 64; i++)
 329                reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
 330}
 331
 332static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
 333                             u8 req, u16 idx, u16 val)
 334{
 335        reg_w_riv(gspca_dev, req, idx, val);
 336        reg_r(gspca_dev, 0x01, 0x0001, 1);
 337        gspca_dbg(gspca_dev, D_FRAM, "before wait 0x%04x\n",
 338                  gspca_dev->usb_buf[0]);
 339        reg_w_riv(gspca_dev, req, idx, val);
 340
 341        msleep(200);
 342        reg_r(gspca_dev, 0x01, 0x0001, 1);
 343        gspca_dbg(gspca_dev, D_FRAM, "after wait 0x%04x\n",
 344                  gspca_dev->usb_buf[0]);
 345}
 346
 347static void spca504_read_info(struct gspca_dev *gspca_dev)
 348{
 349        int i;
 350        u8 info[6];
 351
 352        if (gspca_debug < D_STREAM)
 353                return;
 354
 355        for (i = 0; i < 6; i++) {
 356                reg_r(gspca_dev, 0, i, 1);
 357                info[i] = gspca_dev->usb_buf[0];
 358        }
 359        gspca_dbg(gspca_dev, D_STREAM,
 360                  "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0\n",
 361                  info[0], info[1], info[2],
 362                  info[3], info[4], info[5]);
 363}
 364
 365static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
 366                        u8 req,
 367                        u16 idx, u16 val, u8 endcode, u8 count)
 368{
 369        u16 status;
 370
 371        reg_w_riv(gspca_dev, req, idx, val);
 372        reg_r(gspca_dev, 0x01, 0x0001, 1);
 373        if (gspca_dev->usb_err < 0)
 374                return;
 375        gspca_dbg(gspca_dev, D_FRAM, "Status 0x%02x Need 0x%02x\n",
 376                  gspca_dev->usb_buf[0], endcode);
 377        if (!count)
 378                return;
 379        count = 200;
 380        while (--count > 0) {
 381                msleep(10);
 382                /* gsmart mini2 write a each wait setting 1 ms is enough */
 383/*              reg_w_riv(gspca_dev, req, idx, val); */
 384                reg_r(gspca_dev, 0x01, 0x0001, 1);
 385                status = gspca_dev->usb_buf[0];
 386                if (status == endcode) {
 387                        gspca_dbg(gspca_dev, D_FRAM, "status 0x%04x after wait %d\n",
 388                                  status, 200 - count);
 389                                break;
 390                }
 391        }
 392}
 393
 394static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
 395{
 396        int count = 10;
 397
 398        while (--count > 0) {
 399                reg_r(gspca_dev, 0x21, 0, 1);
 400                if ((gspca_dev->usb_buf[0] & 0x01) == 0)
 401                        break;
 402                msleep(10);
 403        }
 404}
 405
 406static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
 407{
 408        int count = 50;
 409
 410        while (--count > 0) {
 411                reg_r(gspca_dev, 0x21, 1, 1);
 412                if (gspca_dev->usb_buf[0] != 0) {
 413                        reg_w_1(gspca_dev, 0x21, 0, 1, 0);
 414                        reg_r(gspca_dev, 0x21, 1, 1);
 415                        spca504B_PollingDataReady(gspca_dev);
 416                        break;
 417                }
 418                msleep(10);
 419        }
 420}
 421
 422static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
 423{
 424        u8 *data;
 425
 426        if (gspca_debug < D_STREAM)
 427                return;
 428
 429        data = gspca_dev->usb_buf;
 430        reg_r(gspca_dev, 0x20, 0, 5);
 431        gspca_dbg(gspca_dev, D_STREAM, "FirmWare: %d %d %d %d %d\n",
 432                  data[0], data[1], data[2], data[3], data[4]);
 433        reg_r(gspca_dev, 0x23, 0, 64);
 434        reg_r(gspca_dev, 0x23, 1, 64);
 435}
 436
 437static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
 438{
 439        struct sd *sd = (struct sd *) gspca_dev;
 440        u8 Size;
 441
 442        Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 443        switch (sd->bridge) {
 444        case BRIDGE_SPCA533:
 445                reg_w_riv(gspca_dev, 0x31, 0, 0);
 446                spca504B_WaitCmdStatus(gspca_dev);
 447                spca504B_PollingDataReady(gspca_dev);
 448                spca50x_GetFirmware(gspca_dev);
 449
 450                reg_w_1(gspca_dev, 0x24, 0, 8, 2);              /* type */
 451                reg_r(gspca_dev, 0x24, 8, 1);
 452
 453                reg_w_1(gspca_dev, 0x25, 0, 4, Size);
 454                reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
 455                spca504B_PollingDataReady(gspca_dev);
 456
 457                /* Init the cam width height with some values get on init ? */
 458                reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
 459                spca504B_WaitCmdStatus(gspca_dev);
 460                spca504B_PollingDataReady(gspca_dev);
 461                break;
 462        default:
 463/* case BRIDGE_SPCA504B: */
 464/* case BRIDGE_SPCA536: */
 465                reg_w_1(gspca_dev, 0x25, 0, 4, Size);
 466                reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
 467                reg_w_1(gspca_dev, 0x27, 0, 0, 6);
 468                reg_r(gspca_dev, 0x27, 0, 1);                   /* type */
 469                spca504B_PollingDataReady(gspca_dev);
 470                break;
 471        case BRIDGE_SPCA504:
 472                Size += 3;
 473                if (sd->subtype == AiptekMiniPenCam13) {
 474                        /* spca504a aiptek */
 475                        spca504A_acknowledged_command(gspca_dev,
 476                                                0x08, Size, 0,
 477                                                0x80 | (Size & 0x0f), 1);
 478                        spca504A_acknowledged_command(gspca_dev,
 479                                                        1, 3, 0, 0x9f, 0);
 480                } else {
 481                        spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
 482                }
 483                break;
 484        case BRIDGE_SPCA504C:
 485                /* capture mode */
 486                reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
 487                reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
 488                break;
 489        }
 490}
 491
 492static void spca504_wait_status(struct gspca_dev *gspca_dev)
 493{
 494        int cnt;
 495
 496        cnt = 256;
 497        while (--cnt > 0) {
 498                /* With this we get the status, when return 0 it's all ok */
 499                reg_r(gspca_dev, 0x06, 0x00, 1);
 500                if (gspca_dev->usb_buf[0] == 0)
 501                        return;
 502                msleep(10);
 503        }
 504}
 505
 506static void spca504B_setQtable(struct gspca_dev *gspca_dev)
 507{
 508        reg_w_1(gspca_dev, 0x26, 0, 0, 3);
 509        reg_r(gspca_dev, 0x26, 0, 1);
 510        spca504B_PollingDataReady(gspca_dev);
 511}
 512
 513static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
 514{
 515        struct sd *sd = (struct sd *) gspca_dev;
 516        u16 reg;
 517
 518        reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
 519        reg_w_riv(gspca_dev, 0x00, reg, val);
 520}
 521
 522static void setcontrast(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 ? 0x20f1 : 0x21a8;
 528        reg_w_riv(gspca_dev, 0x00, reg, val);
 529}
 530
 531static void setcolors(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 ? 0x20f6 : 0x21ae;
 537        reg_w_riv(gspca_dev, 0x00, reg, val);
 538}
 539
 540static void init_ctl_reg(struct gspca_dev *gspca_dev)
 541{
 542        struct sd *sd = (struct sd *) gspca_dev;
 543        int pollreg = 1;
 544
 545        switch (sd->bridge) {
 546        case BRIDGE_SPCA504:
 547        case BRIDGE_SPCA504C:
 548                pollreg = 0;
 549                /* fall through */
 550        default:
 551/*      case BRIDGE_SPCA533: */
 552/*      case BRIDGE_SPCA504B: */
 553                reg_w_riv(gspca_dev, 0, 0x21ad, 0x00);  /* hue */
 554                reg_w_riv(gspca_dev, 0, 0x21ac, 0x01);  /* sat/hue */
 555                reg_w_riv(gspca_dev, 0, 0x21a3, 0x00);  /* gamma */
 556                break;
 557        case BRIDGE_SPCA536:
 558                reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
 559                reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
 560                reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
 561                break;
 562        }
 563        if (pollreg)
 564                spca504B_PollingDataReady(gspca_dev);
 565}
 566
 567/* this function is called at probe time */
 568static int sd_config(struct gspca_dev *gspca_dev,
 569                        const struct usb_device_id *id)
 570{
 571        struct sd *sd = (struct sd *) gspca_dev;
 572        struct cam *cam;
 573
 574        cam = &gspca_dev->cam;
 575
 576        sd->bridge = id->driver_info >> 8;
 577        sd->subtype = id->driver_info;
 578
 579        if (sd->subtype == AiptekMiniPenCam13) {
 580
 581                /* try to get the firmware as some cam answer 2.0.1.2.2
 582                 * and should be a spca504b then overwrite that setting */
 583                reg_r(gspca_dev, 0x20, 0, 1);
 584                switch (gspca_dev->usb_buf[0]) {
 585                case 1:
 586                        break;          /* (right bridge/subtype) */
 587                case 2:
 588                        sd->bridge = BRIDGE_SPCA504B;
 589                        sd->subtype = 0;
 590                        break;
 591                default:
 592                        return -ENODEV;
 593                }
 594        }
 595
 596        switch (sd->bridge) {
 597        default:
 598/*      case BRIDGE_SPCA504B: */
 599/*      case BRIDGE_SPCA504: */
 600/*      case BRIDGE_SPCA536: */
 601                cam->cam_mode = vga_mode;
 602                cam->nmodes = ARRAY_SIZE(vga_mode);
 603                break;
 604        case BRIDGE_SPCA533:
 605                cam->cam_mode = custom_mode;
 606                if (sd->subtype == MegaImageVI)         /* 320x240 only */
 607                        cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
 608                else
 609                        cam->nmodes = ARRAY_SIZE(custom_mode);
 610                break;
 611        case BRIDGE_SPCA504C:
 612                cam->cam_mode = vga_mode2;
 613                cam->nmodes = ARRAY_SIZE(vga_mode2);
 614                break;
 615        }
 616        return 0;
 617}
 618
 619/* this function is called at probe and resume time */
 620static int sd_init(struct gspca_dev *gspca_dev)
 621{
 622        struct sd *sd = (struct sd *) gspca_dev;
 623
 624        switch (sd->bridge) {
 625        case BRIDGE_SPCA504B:
 626                reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
 627                reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
 628                reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
 629                reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
 630                reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
 631                reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
 632                /* fall through */
 633        case BRIDGE_SPCA533:
 634                spca504B_PollingDataReady(gspca_dev);
 635                spca50x_GetFirmware(gspca_dev);
 636                break;
 637        case BRIDGE_SPCA536:
 638                spca50x_GetFirmware(gspca_dev);
 639                reg_r(gspca_dev, 0x00, 0x5002, 1);
 640                reg_w_1(gspca_dev, 0x24, 0, 0, 0);
 641                reg_r(gspca_dev, 0x24, 0, 1);
 642                spca504B_PollingDataReady(gspca_dev);
 643                reg_w_riv(gspca_dev, 0x34, 0, 0);
 644                spca504B_WaitCmdStatus(gspca_dev);
 645                break;
 646        case BRIDGE_SPCA504C:   /* pccam600 */
 647                gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504 (PC-CAM 600)\n");
 648                reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
 649                reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001);     /* reset */
 650                spca504_wait_status(gspca_dev);
 651                if (sd->subtype == LogitechClickSmart420)
 652                        write_vector(gspca_dev,
 653                                spca504A_clicksmart420_open_data,
 654                                ARRAY_SIZE(spca504A_clicksmart420_open_data));
 655                else
 656                        write_vector(gspca_dev, spca504_pccam600_open_data,
 657                                ARRAY_SIZE(spca504_pccam600_open_data));
 658                setup_qtable(gspca_dev, qtable_creative_pccam);
 659                break;
 660        default:
 661/*      case BRIDGE_SPCA504: */
 662                gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504\n");
 663                if (sd->subtype == AiptekMiniPenCam13) {
 664                        spca504_read_info(gspca_dev);
 665
 666                        /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
 667                        spca504A_acknowledged_command(gspca_dev, 0x24,
 668                                                        8, 3, 0x9e, 1);
 669                        /* Twice sequential need status 0xff->0x9e->0x9d */
 670                        spca504A_acknowledged_command(gspca_dev, 0x24,
 671                                                        8, 3, 0x9e, 0);
 672
 673                        spca504A_acknowledged_command(gspca_dev, 0x24,
 674                                                        0, 0, 0x9d, 1);
 675                        /******************************/
 676                        /* spca504a aiptek */
 677                        spca504A_acknowledged_command(gspca_dev, 0x08,
 678                                                        6, 0, 0x86, 1);
 679/*                      reg_write (dev, 0, 0x2000, 0); */
 680/*                      reg_write (dev, 0, 0x2883, 1); */
 681/*                      spca504A_acknowledged_command (gspca_dev, 0x08,
 682                                                        6, 0, 0x86, 1); */
 683/*                      spca504A_acknowledged_command (gspca_dev, 0x24,
 684                                                        0, 0, 0x9D, 1); */
 685                        reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
 686                                                        /* L92 sno1t.txt */
 687                        reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
 688                        spca504A_acknowledged_command(gspca_dev, 0x01,
 689                                                        0x0f, 0, 0xff, 0);
 690                }
 691                /* setup qtable */
 692                reg_w_riv(gspca_dev, 0, 0x2000, 0);
 693                reg_w_riv(gspca_dev, 0, 0x2883, 1);
 694                setup_qtable(gspca_dev, qtable_spca504_default);
 695                break;
 696        }
 697        return gspca_dev->usb_err;
 698}
 699
 700static int sd_start(struct gspca_dev *gspca_dev)
 701{
 702        struct sd *sd = (struct sd *) gspca_dev;
 703        int enable;
 704
 705        /* create the JPEG header */
 706        jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
 707                        gspca_dev->pixfmt.width,
 708                        0x22);          /* JPEG 411 */
 709        jpeg_set_qual(sd->jpeg_hdr, QUALITY);
 710
 711        if (sd->bridge == BRIDGE_SPCA504B)
 712                spca504B_setQtable(gspca_dev);
 713        spca504B_SetSizeType(gspca_dev);
 714        switch (sd->bridge) {
 715        default:
 716/*      case BRIDGE_SPCA504B: */
 717/*      case BRIDGE_SPCA533: */
 718/*      case BRIDGE_SPCA536: */
 719                switch (sd->subtype) {
 720                case MegapixV4:
 721                case LogitechClickSmart820:
 722                case MegaImageVI:
 723                        reg_w_riv(gspca_dev, 0xf0, 0, 0);
 724                        spca504B_WaitCmdStatus(gspca_dev);
 725                        reg_r(gspca_dev, 0xf0, 4, 0);
 726                        spca504B_WaitCmdStatus(gspca_dev);
 727                        break;
 728                default:
 729                        reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
 730                        spca504B_WaitCmdStatus(gspca_dev);
 731                        spca504B_PollingDataReady(gspca_dev);
 732                        break;
 733                }
 734                break;
 735        case BRIDGE_SPCA504:
 736                if (sd->subtype == AiptekMiniPenCam13) {
 737                        spca504_read_info(gspca_dev);
 738
 739                        /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
 740                        spca504A_acknowledged_command(gspca_dev, 0x24,
 741                                                        8, 3, 0x9e, 1);
 742                        /* Twice sequential need status 0xff->0x9e->0x9d */
 743                        spca504A_acknowledged_command(gspca_dev, 0x24,
 744                                                        8, 3, 0x9e, 0);
 745                        spca504A_acknowledged_command(gspca_dev, 0x24,
 746                                                        0, 0, 0x9d, 1);
 747                } else {
 748                        spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
 749                        spca504_read_info(gspca_dev);
 750                        spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
 751                        spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
 752                }
 753                spca504B_SetSizeType(gspca_dev);
 754                reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
 755                                                        /* L92 sno1t.txt */
 756                reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
 757                break;
 758        case BRIDGE_SPCA504C:
 759                if (sd->subtype == LogitechClickSmart420) {
 760                        write_vector(gspca_dev,
 761                                spca504A_clicksmart420_init_data,
 762                                ARRAY_SIZE(spca504A_clicksmart420_init_data));
 763                } else {
 764                        write_vector(gspca_dev, spca504_pccam600_init_data,
 765                                ARRAY_SIZE(spca504_pccam600_init_data));
 766                }
 767                enable = (sd->autogain ? 0x04 : 0x01);
 768                reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
 769                                                        /* auto exposure */
 770                reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
 771                                                        /* auto whiteness */
 772
 773                /* set default exposure compensation and whiteness balance */
 774                reg_w_riv(gspca_dev, 0x30, 0x0001, 800);        /* ~ 20 fps */
 775                reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
 776                spca504B_SetSizeType(gspca_dev);
 777                break;
 778        }
 779        init_ctl_reg(gspca_dev);
 780        return gspca_dev->usb_err;
 781}
 782
 783static void sd_stopN(struct gspca_dev *gspca_dev)
 784{
 785        struct sd *sd = (struct sd *) gspca_dev;
 786
 787        switch (sd->bridge) {
 788        default:
 789/*      case BRIDGE_SPCA533: */
 790/*      case BRIDGE_SPCA536: */
 791/*      case BRIDGE_SPCA504B: */
 792                reg_w_riv(gspca_dev, 0x31, 0, 0);
 793                spca504B_WaitCmdStatus(gspca_dev);
 794                spca504B_PollingDataReady(gspca_dev);
 795                break;
 796        case BRIDGE_SPCA504:
 797        case BRIDGE_SPCA504C:
 798                reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
 799
 800                if (sd->subtype == AiptekMiniPenCam13) {
 801                        /* spca504a aiptek */
 802/*                      spca504A_acknowledged_command(gspca_dev, 0x08,
 803                                                         6, 0, 0x86, 1); */
 804                        spca504A_acknowledged_command(gspca_dev, 0x24,
 805                                                        0x00, 0x00, 0x9d, 1);
 806                        spca504A_acknowledged_command(gspca_dev, 0x01,
 807                                                        0x0f, 0x00, 0xff, 1);
 808                } else {
 809                        spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
 810                        reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
 811                }
 812                break;
 813        }
 814}
 815
 816static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 817                        u8 *data,                       /* isoc packet */
 818                        int len)                        /* iso packet length */
 819{
 820        struct sd *sd = (struct sd *) gspca_dev;
 821        int i, sof = 0;
 822        static u8 ffd9[] = {0xff, 0xd9};
 823
 824/* frames are jpeg 4.1.1 without 0xff escape */
 825        switch (sd->bridge) {
 826        case BRIDGE_SPCA533:
 827                if (data[0] == 0xff) {
 828                        if (data[1] != 0x01) {  /* drop packet */
 829/*                              gspca_dev->last_packet_type = DISCARD_PACKET; */
 830                                return;
 831                        }
 832                        sof = 1;
 833                        data += SPCA533_OFFSET_DATA;
 834                        len -= SPCA533_OFFSET_DATA;
 835                } else {
 836                        data += 1;
 837                        len -= 1;
 838                }
 839                break;
 840        case BRIDGE_SPCA536:
 841                if (data[0] == 0xff) {
 842                        sof = 1;
 843                        data += SPCA536_OFFSET_DATA;
 844                        len -= SPCA536_OFFSET_DATA;
 845                } else {
 846                        data += 2;
 847                        len -= 2;
 848                }
 849                break;
 850        default:
 851/*      case BRIDGE_SPCA504: */
 852/*      case BRIDGE_SPCA504B: */
 853                switch (data[0]) {
 854                case 0xfe:                      /* start of frame */
 855                        sof = 1;
 856                        data += SPCA50X_OFFSET_DATA;
 857                        len -= SPCA50X_OFFSET_DATA;
 858                        break;
 859                case 0xff:                      /* drop packet */
 860/*                      gspca_dev->last_packet_type = DISCARD_PACKET; */
 861                        return;
 862                default:
 863                        data += 1;
 864                        len -= 1;
 865                        break;
 866                }
 867                break;
 868        case BRIDGE_SPCA504C:
 869                switch (data[0]) {
 870                case 0xfe:                      /* start of frame */
 871                        sof = 1;
 872                        data += SPCA504_PCCAM600_OFFSET_DATA;
 873                        len -= SPCA504_PCCAM600_OFFSET_DATA;
 874                        break;
 875                case 0xff:                      /* drop packet */
 876/*                      gspca_dev->last_packet_type = DISCARD_PACKET; */
 877                        return;
 878                default:
 879                        data += 1;
 880                        len -= 1;
 881                        break;
 882                }
 883                break;
 884        }
 885        if (sof) {              /* start of frame */
 886                gspca_frame_add(gspca_dev, LAST_PACKET,
 887                                ffd9, 2);
 888
 889                /* put the JPEG header in the new frame */
 890                gspca_frame_add(gspca_dev, FIRST_PACKET,
 891                        sd->jpeg_hdr, JPEG_HDR_SZ);
 892        }
 893
 894        /* add 0x00 after 0xff */
 895        i = 0;
 896        do {
 897                if (data[i] == 0xff) {
 898                        gspca_frame_add(gspca_dev, INTER_PACKET,
 899                                        data, i + 1);
 900                        len -= i;
 901                        data += i;
 902                        *data = 0x00;
 903                        i = 0;
 904                }
 905                i++;
 906        } while (i < len);
 907        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 908}
 909
 910static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 911{
 912        struct gspca_dev *gspca_dev =
 913                container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 914        struct sd *sd = (struct sd *)gspca_dev;
 915
 916        gspca_dev->usb_err = 0;
 917
 918        if (!gspca_dev->streaming)
 919                return 0;
 920
 921        switch (ctrl->id) {
 922        case V4L2_CID_BRIGHTNESS:
 923                setbrightness(gspca_dev, ctrl->val);
 924                break;
 925        case V4L2_CID_CONTRAST:
 926                setcontrast(gspca_dev, ctrl->val);
 927                break;
 928        case V4L2_CID_SATURATION:
 929                setcolors(gspca_dev, ctrl->val);
 930                break;
 931        case V4L2_CID_AUTOGAIN:
 932                sd->autogain = ctrl->val;
 933                break;
 934        }
 935        return gspca_dev->usb_err;
 936}
 937
 938static const struct v4l2_ctrl_ops sd_ctrl_ops = {
 939        .s_ctrl = sd_s_ctrl,
 940};
 941
 942static int sd_init_controls(struct gspca_dev *gspca_dev)
 943{
 944        struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 945
 946        gspca_dev->vdev.ctrl_handler = hdl;
 947        v4l2_ctrl_handler_init(hdl, 4);
 948        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 949                        V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
 950        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 951                        V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
 952        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 953                        V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
 954        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 955                        V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
 956
 957        if (hdl->error) {
 958                pr_err("Could not initialize controls\n");
 959                return hdl->error;
 960        }
 961        return 0;
 962}
 963
 964/* sub-driver description */
 965static const struct sd_desc sd_desc = {
 966        .name = MODULE_NAME,
 967        .config = sd_config,
 968        .init = sd_init,
 969        .init_controls = sd_init_controls,
 970        .start = sd_start,
 971        .stopN = sd_stopN,
 972        .pkt_scan = sd_pkt_scan,
 973};
 974
 975/* -- module initialisation -- */
 976#define BS(bridge, subtype) \
 977        .driver_info = (BRIDGE_ ## bridge << 8) \
 978                        | (subtype)
 979static const struct usb_device_id device_table[] = {
 980        {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
 981        {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
 982        {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
 983        {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
 984        {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
 985        {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
 986        {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
 987        {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
 988        {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
 989        {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
 990        {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
 991        {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
 992        {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
 993        {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
 994        {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
 995        {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
 996        {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
 997        {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
 998        {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
 999        {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1000        {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1001        {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1002        {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1003        {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1004        {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1005        {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1006        {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1007        {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1008        {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1009        {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1010        {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1011        {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1012        {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1013        {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1014        {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1015        {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1016        {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1017        {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1018        {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
1019        {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1020        {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1021        {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1022        {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1023        {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1024        {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1025        {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1026        {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1027        {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1028        {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1029        {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1030        {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1031        {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1032        {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1033        {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1034        {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1035        {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1036        {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1037        {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1038        {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1039        {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1040        {}
1041};
1042MODULE_DEVICE_TABLE(usb, device_table);
1043
1044/* -- device connect -- */
1045static int sd_probe(struct usb_interface *intf,
1046                        const struct usb_device_id *id)
1047{
1048        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1049                                THIS_MODULE);
1050}
1051
1052static struct usb_driver sd_driver = {
1053        .name = MODULE_NAME,
1054        .id_table = device_table,
1055        .probe = sd_probe,
1056        .disconnect = gspca_disconnect,
1057#ifdef CONFIG_PM
1058        .suspend = gspca_suspend,
1059        .resume = gspca_resume,
1060        .reset_resume = gspca_resume,
1061#endif
1062};
1063
1064module_usb_driver(sd_driver);
1065