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