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