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