linux/drivers/media/video/gspca/spca500.c
<<
>>
Prefs
   1/*
   2 * SPCA500 chip based cameras initialization data
   3 *
   4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 *
  20 */
  21
  22#define MODULE_NAME "spca500"
  23
  24#include "gspca.h"
  25#include "jpeg.h"
  26
  27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
  28MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
  29MODULE_LICENSE("GPL");
  30
  31/* specific webcam descriptor */
  32struct sd {
  33        struct gspca_dev gspca_dev;             /* !! must be the first item */
  34
  35        unsigned char brightness;
  36        unsigned char contrast;
  37        unsigned char colors;
  38        u8 quality;
  39#define QUALITY_MIN 70
  40#define QUALITY_MAX 95
  41#define QUALITY_DEF 85
  42
  43        char subtype;
  44#define AgfaCl20 0
  45#define AiptekPocketDV 1
  46#define BenqDC1016 2
  47#define CreativePCCam300 3
  48#define DLinkDSC350 4
  49#define Gsmartmini 5
  50#define IntelPocketPCCamera 6
  51#define KodakEZ200 7
  52#define LogitechClickSmart310 8
  53#define LogitechClickSmart510 9
  54#define LogitechTraveler 10
  55#define MustekGsmart300 11
  56#define Optimedia 12
  57#define PalmPixDC85 13
  58#define ToptroIndus 14
  59
  60        u8 *jpeg_hdr;
  61};
  62
  63/* V4L2 controls supported by the driver */
  64static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
  65static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
  66static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
  67static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
  68static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
  69static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
  70
  71static struct ctrl sd_ctrls[] = {
  72        {
  73            {
  74                .id      = V4L2_CID_BRIGHTNESS,
  75                .type    = V4L2_CTRL_TYPE_INTEGER,
  76                .name    = "Brightness",
  77                .minimum = 0,
  78                .maximum = 255,
  79                .step    = 1,
  80#define BRIGHTNESS_DEF 127
  81                .default_value = BRIGHTNESS_DEF,
  82            },
  83            .set = sd_setbrightness,
  84            .get = sd_getbrightness,
  85        },
  86        {
  87            {
  88                .id      = V4L2_CID_CONTRAST,
  89                .type    = V4L2_CTRL_TYPE_INTEGER,
  90                .name    = "Contrast",
  91                .minimum = 0,
  92                .maximum = 63,
  93                .step    = 1,
  94#define CONTRAST_DEF 31
  95                .default_value = CONTRAST_DEF,
  96            },
  97            .set = sd_setcontrast,
  98            .get = sd_getcontrast,
  99        },
 100        {
 101            {
 102                .id      = V4L2_CID_SATURATION,
 103                .type    = V4L2_CTRL_TYPE_INTEGER,
 104                .name    = "Color",
 105                .minimum = 0,
 106                .maximum = 63,
 107                .step    = 1,
 108#define COLOR_DEF 31
 109                .default_value = COLOR_DEF,
 110            },
 111            .set = sd_setcolors,
 112            .get = sd_getcolors,
 113        },
 114};
 115
 116static const struct v4l2_pix_format vga_mode[] = {
 117        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 118                .bytesperline = 320,
 119                .sizeimage = 320 * 240 * 3 / 8 + 590,
 120                .colorspace = V4L2_COLORSPACE_JPEG,
 121                .priv = 1},
 122        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 123                .bytesperline = 640,
 124                .sizeimage = 640 * 480 * 3 / 8 + 590,
 125                .colorspace = V4L2_COLORSPACE_JPEG,
 126                .priv = 0},
 127};
 128
 129static const struct v4l2_pix_format sif_mode[] = {
 130        {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 131                .bytesperline = 176,
 132                .sizeimage = 176 * 144 * 3 / 8 + 590,
 133                .colorspace = V4L2_COLORSPACE_JPEG,
 134                .priv = 1},
 135        {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 136                .bytesperline = 352,
 137                .sizeimage = 352 * 288 * 3 / 8 + 590,
 138                .colorspace = V4L2_COLORSPACE_JPEG,
 139                .priv = 0},
 140};
 141
 142/* Frame packet header offsets for the spca500 */
 143#define SPCA500_OFFSET_PADDINGLB 2
 144#define SPCA500_OFFSET_PADDINGHB 3
 145#define SPCA500_OFFSET_MODE      4
 146#define SPCA500_OFFSET_IMGWIDTH  5
 147#define SPCA500_OFFSET_IMGHEIGHT 6
 148#define SPCA500_OFFSET_IMGMODE   7
 149#define SPCA500_OFFSET_QTBLINDEX 8
 150#define SPCA500_OFFSET_FRAMSEQ   9
 151#define SPCA500_OFFSET_CDSPINFO  10
 152#define SPCA500_OFFSET_GPIO      11
 153#define SPCA500_OFFSET_AUGPIO    12
 154#define SPCA500_OFFSET_DATA      16
 155
 156
 157static const __u16 spca500_visual_defaults[][3] = {
 158        {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
 159                                 * hue (H byte) = 0,
 160                                 * saturation/hue enable,
 161                                 * brightness/contrast enable.
 162                                 */
 163        {0x00, 0x0000, 0x8167}, /* brightness = 0 */
 164        {0x00, 0x0020, 0x8168}, /* contrast = 0 */
 165        {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
 166                                 * hue (H byte) = 0, saturation/hue enable,
 167                                 * brightness/contrast enable.
 168                                 * was 0x0003, now 0x0000.
 169                                 */
 170        {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
 171        {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
 172        {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
 173        {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
 174        {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
 175        {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
 176        {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
 177        {0x0c, 0x0004, 0x0000},
 178        /* set interface */
 179        {}
 180};
 181static const __u16 Clicksmart510_defaults[][3] = {
 182        {0x00, 0x00, 0x8211},
 183        {0x00, 0x01, 0x82c0},
 184        {0x00, 0x10, 0x82cb},
 185        {0x00, 0x0f, 0x800d},
 186        {0x00, 0x82, 0x8225},
 187        {0x00, 0x21, 0x8228},
 188        {0x00, 0x00, 0x8203},
 189        {0x00, 0x00, 0x8204},
 190        {0x00, 0x08, 0x8205},
 191        {0x00, 0xf8, 0x8206},
 192        {0x00, 0x28, 0x8207},
 193        {0x00, 0xa0, 0x8208},
 194        {0x00, 0x08, 0x824a},
 195        {0x00, 0x08, 0x8214},
 196        {0x00, 0x80, 0x82c1},
 197        {0x00, 0x00, 0x82c2},
 198        {0x00, 0x00, 0x82ca},
 199        {0x00, 0x80, 0x82c1},
 200        {0x00, 0x04, 0x82c2},
 201        {0x00, 0x00, 0x82ca},
 202        {0x00, 0xfc, 0x8100},
 203        {0x00, 0xfc, 0x8105},
 204        {0x00, 0x30, 0x8101},
 205        {0x00, 0x00, 0x8102},
 206        {0x00, 0x00, 0x8103},
 207        {0x00, 0x66, 0x8107},
 208        {0x00, 0x00, 0x816b},
 209        {0x00, 0x00, 0x8155},
 210        {0x00, 0x01, 0x8156},
 211        {0x00, 0x60, 0x8157},
 212        {0x00, 0x40, 0x8158},
 213        {0x00, 0x0a, 0x8159},
 214        {0x00, 0x06, 0x815a},
 215        {0x00, 0x00, 0x813f},
 216        {0x00, 0x00, 0x8200},
 217        {0x00, 0x19, 0x8201},
 218        {0x00, 0x00, 0x82c1},
 219        {0x00, 0xa0, 0x82c2},
 220        {0x00, 0x00, 0x82ca},
 221        {0x00, 0x00, 0x8117},
 222        {0x00, 0x00, 0x8118},
 223        {0x00, 0x65, 0x8119},
 224        {0x00, 0x00, 0x811a},
 225        {0x00, 0x00, 0x811b},
 226        {0x00, 0x55, 0x811c},
 227        {0x00, 0x65, 0x811d},
 228        {0x00, 0x55, 0x811e},
 229        {0x00, 0x16, 0x811f},
 230        {0x00, 0x19, 0x8120},
 231        {0x00, 0x80, 0x8103},
 232        {0x00, 0x83, 0x816b},
 233        {0x00, 0x25, 0x8168},
 234        {0x00, 0x01, 0x820f},
 235        {0x00, 0xff, 0x8115},
 236        {0x00, 0x48, 0x8116},
 237        {0x00, 0x50, 0x8151},
 238        {0x00, 0x40, 0x8152},
 239        {0x00, 0x78, 0x8153},
 240        {0x00, 0x40, 0x8154},
 241        {0x00, 0x00, 0x8167},
 242        {0x00, 0x20, 0x8168},
 243        {0x00, 0x00, 0x816a},
 244        {0x00, 0x03, 0x816b},
 245        {0x00, 0x20, 0x8169},
 246        {0x00, 0x60, 0x8157},
 247        {0x00, 0x00, 0x8190},
 248        {0x00, 0x00, 0x81a1},
 249        {0x00, 0x00, 0x81b2},
 250        {0x00, 0x27, 0x8191},
 251        {0x00, 0x27, 0x81a2},
 252        {0x00, 0x27, 0x81b3},
 253        {0x00, 0x4b, 0x8192},
 254        {0x00, 0x4b, 0x81a3},
 255        {0x00, 0x4b, 0x81b4},
 256        {0x00, 0x66, 0x8193},
 257        {0x00, 0x66, 0x81a4},
 258        {0x00, 0x66, 0x81b5},
 259        {0x00, 0x79, 0x8194},
 260        {0x00, 0x79, 0x81a5},
 261        {0x00, 0x79, 0x81b6},
 262        {0x00, 0x8a, 0x8195},
 263        {0x00, 0x8a, 0x81a6},
 264        {0x00, 0x8a, 0x81b7},
 265        {0x00, 0x9b, 0x8196},
 266        {0x00, 0x9b, 0x81a7},
 267        {0x00, 0x9b, 0x81b8},
 268        {0x00, 0xa6, 0x8197},
 269        {0x00, 0xa6, 0x81a8},
 270        {0x00, 0xa6, 0x81b9},
 271        {0x00, 0xb2, 0x8198},
 272        {0x00, 0xb2, 0x81a9},
 273        {0x00, 0xb2, 0x81ba},
 274        {0x00, 0xbe, 0x8199},
 275        {0x00, 0xbe, 0x81aa},
 276        {0x00, 0xbe, 0x81bb},
 277        {0x00, 0xc8, 0x819a},
 278        {0x00, 0xc8, 0x81ab},
 279        {0x00, 0xc8, 0x81bc},
 280        {0x00, 0xd2, 0x819b},
 281        {0x00, 0xd2, 0x81ac},
 282        {0x00, 0xd2, 0x81bd},
 283        {0x00, 0xdb, 0x819c},
 284        {0x00, 0xdb, 0x81ad},
 285        {0x00, 0xdb, 0x81be},
 286        {0x00, 0xe4, 0x819d},
 287        {0x00, 0xe4, 0x81ae},
 288        {0x00, 0xe4, 0x81bf},
 289        {0x00, 0xed, 0x819e},
 290        {0x00, 0xed, 0x81af},
 291        {0x00, 0xed, 0x81c0},
 292        {0x00, 0xf7, 0x819f},
 293        {0x00, 0xf7, 0x81b0},
 294        {0x00, 0xf7, 0x81c1},
 295        {0x00, 0xff, 0x81a0},
 296        {0x00, 0xff, 0x81b1},
 297        {0x00, 0xff, 0x81c2},
 298        {0x00, 0x03, 0x8156},
 299        {0x00, 0x00, 0x8211},
 300        {0x00, 0x20, 0x8168},
 301        {0x00, 0x01, 0x8202},
 302        {0x00, 0x30, 0x8101},
 303        {0x00, 0x00, 0x8111},
 304        {0x00, 0x00, 0x8112},
 305        {0x00, 0x00, 0x8113},
 306        {0x00, 0x00, 0x8114},
 307        {}
 308};
 309
 310static const __u8 qtable_creative_pccam[2][64] = {
 311        {                               /* Q-table Y-components */
 312         0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
 313         0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
 314         0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
 315         0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
 316         0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
 317         0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
 318         0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
 319         0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
 320        {                               /* Q-table C-components */
 321         0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
 322         0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
 323         0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 324         0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 325         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 326         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 327         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 328         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
 329};
 330
 331static const __u8 qtable_kodak_ez200[2][64] = {
 332        {                               /* Q-table Y-components */
 333         0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
 334         0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
 335         0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
 336         0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
 337         0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
 338         0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
 339         0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
 340         0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
 341        {                               /* Q-table C-components */
 342         0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
 343         0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
 344         0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
 345         0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
 346         0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
 347         0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
 348         0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
 349         0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
 350};
 351
 352static const __u8 qtable_pocketdv[2][64] = {
 353        {               /* Q-table Y-components start registers 0x8800 */
 354         0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
 355         0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
 356         0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
 357         0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
 358         0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
 359         0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
 360         0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
 361         0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
 362         },
 363        {               /* Q-table C-components start registers 0x8840 */
 364         0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
 365         0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
 366         0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
 367         0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
 368         0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
 369         0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
 370         0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
 371         0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
 372};
 373
 374/* read 'len' bytes to gspca_dev->usb_buf */
 375static void reg_r(struct gspca_dev *gspca_dev,
 376                  __u16 index,
 377                  __u16 length)
 378{
 379        usb_control_msg(gspca_dev->dev,
 380                        usb_rcvctrlpipe(gspca_dev->dev, 0),
 381                        0,
 382                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 383                        0,              /* value */
 384                        index, gspca_dev->usb_buf, length, 500);
 385}
 386
 387static int reg_w(struct gspca_dev *gspca_dev,
 388                     __u16 req, __u16 index, __u16 value)
 389{
 390        int ret;
 391
 392        PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
 393        ret = usb_control_msg(gspca_dev->dev,
 394                        usb_sndctrlpipe(gspca_dev->dev, 0),
 395                        req,
 396                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 397                        value, index, NULL, 0, 500);
 398        if (ret < 0)
 399                PDEBUG(D_ERR, "reg write: error %d", ret);
 400        return ret;
 401}
 402
 403/* returns: negative is error, pos or zero is data */
 404static int reg_r_12(struct gspca_dev *gspca_dev,
 405                        __u16 req,      /* bRequest */
 406                        __u16 index,    /* wIndex */
 407                        __u16 length)   /* wLength (1 or 2 only) */
 408{
 409        int ret;
 410
 411        gspca_dev->usb_buf[1] = 0;
 412        ret = usb_control_msg(gspca_dev->dev,
 413                        usb_rcvctrlpipe(gspca_dev->dev, 0),
 414                        req,
 415                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 416                        0,              /* value */
 417                        index,
 418                        gspca_dev->usb_buf, length,
 419                        500);           /* timeout */
 420        if (ret < 0) {
 421                PDEBUG(D_ERR, "reg_r_12 err %d", ret);
 422                return -1;
 423        }
 424        return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
 425}
 426
 427/*
 428 * Simple function to wait for a given 8-bit value to be returned from
 429 * a reg_read call.
 430 * Returns: negative is error or timeout, zero is success.
 431 */
 432static int reg_r_wait(struct gspca_dev *gspca_dev,
 433                        __u16 reg, __u16 index, __u16 value)
 434{
 435        int ret, cnt = 20;
 436
 437        while (--cnt > 0) {
 438                ret = reg_r_12(gspca_dev, reg, index, 1);
 439                if (ret == value)
 440                        return 0;
 441                msleep(50);
 442        }
 443        return -EIO;
 444}
 445
 446static int write_vector(struct gspca_dev *gspca_dev,
 447                        const __u16 data[][3])
 448{
 449        int ret, i = 0;
 450
 451        while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
 452                ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
 453                if (ret < 0)
 454                        return ret;
 455                i++;
 456        }
 457        return 0;
 458}
 459
 460static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
 461                                unsigned int request,
 462                                unsigned int ybase,
 463                                unsigned int cbase,
 464                                const __u8 qtable[2][64])
 465{
 466        int i, err;
 467
 468        /* loop over y components */
 469        for (i = 0; i < 64; i++) {
 470                err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
 471                if (err < 0)
 472                        return err;
 473        }
 474
 475        /* loop over c components */
 476        for (i = 0; i < 64; i++) {
 477                err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
 478                if (err < 0)
 479                        return err;
 480        }
 481        return 0;
 482}
 483
 484static void spca500_ping310(struct gspca_dev *gspca_dev)
 485{
 486        reg_r(gspca_dev, 0x0d04, 2);
 487        PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
 488                gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
 489}
 490
 491static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
 492{
 493        reg_r(gspca_dev, 0x0d05, 2);
 494        PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
 495                gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
 496        reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
 497        spca500_ping310(gspca_dev);
 498
 499        reg_w(gspca_dev, 0x00, 0x8168, 0x22);
 500        reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
 501        reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
 502        reg_w(gspca_dev, 0x00, 0x8169, 0x25);
 503        reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
 504        reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
 505        reg_w(gspca_dev, 0x00, 0x813f, 0x03);
 506        reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
 507        reg_w(gspca_dev, 0x00, 0x8153, 0x78);
 508        reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
 509                                                /* 00 for adjust shutter */
 510        reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
 511        reg_w(gspca_dev, 0x00, 0x8169, 0x25);
 512        reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
 513}
 514
 515static void spca500_setmode(struct gspca_dev *gspca_dev,
 516                        __u8 xmult, __u8 ymult)
 517{
 518        int mode;
 519
 520        /* set x multiplier */
 521        reg_w(gspca_dev, 0, 0x8001, xmult);
 522
 523        /* set y multiplier */
 524        reg_w(gspca_dev, 0, 0x8002, ymult);
 525
 526        /* use compressed mode, VGA, with mode specific subsample */
 527        mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
 528        reg_w(gspca_dev, 0, 0x8003, mode << 4);
 529}
 530
 531static int spca500_full_reset(struct gspca_dev *gspca_dev)
 532{
 533        int err;
 534
 535        /* send the reset command */
 536        err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
 537        if (err < 0)
 538                return err;
 539
 540        /* wait for the reset to complete */
 541        err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
 542        if (err < 0)
 543                return err;
 544        err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
 545        if (err < 0)
 546                return err;
 547        err = reg_r_wait(gspca_dev, 0x06, 0, 0);
 548        if (err < 0) {
 549                PDEBUG(D_ERR, "reg_r_wait() failed");
 550                return err;
 551        }
 552        /* all ok */
 553        return 0;
 554}
 555
 556/* Synchro the Bridge with sensor */
 557/* Maybe that will work on all spca500 chip */
 558/* because i only own a clicksmart310 try for that chip */
 559/* using spca50x_set_packet_size() cause an Ooops here */
 560/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
 561/* up-port the same feature as in 2.4.x kernel */
 562static int spca500_synch310(struct gspca_dev *gspca_dev)
 563{
 564        if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
 565                PDEBUG(D_ERR, "Set packet size: set interface error");
 566                goto error;
 567        }
 568        spca500_ping310(gspca_dev);
 569
 570        reg_r(gspca_dev, 0x0d00, 1);
 571
 572        /* need alt setting here */
 573        PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
 574
 575        /* Windoze use pipe with altsetting 6 why 7 here */
 576        if (usb_set_interface(gspca_dev->dev,
 577                                gspca_dev->iface,
 578                                gspca_dev->alt) < 0) {
 579                PDEBUG(D_ERR, "Set packet size: set interface error");
 580                goto error;
 581        }
 582        return 0;
 583error:
 584        return -EBUSY;
 585}
 586
 587static void spca500_reinit(struct gspca_dev *gspca_dev)
 588{
 589        int err;
 590        __u8 Data;
 591
 592        /* some unknow command from Aiptek pocket dv and family300 */
 593
 594        reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
 595        reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
 596        reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
 597
 598        /* enable drop packet */
 599        reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
 600
 601        err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
 602                                 qtable_pocketdv);
 603        if (err < 0)
 604                PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
 605
 606        /* set qtable index */
 607        reg_w(gspca_dev, 0x00, 0x8880, 2);
 608        /* family cam Quicksmart stuff */
 609        reg_w(gspca_dev, 0x00, 0x800a, 0x00);
 610        /* Set agc transfer: synced inbetween frames */
 611        reg_w(gspca_dev, 0x00, 0x820f, 0x01);
 612        /* Init SDRAM - needed for SDRAM access */
 613        reg_w(gspca_dev, 0x00, 0x870a, 0x04);
 614        /*Start init sequence or stream */
 615        reg_w(gspca_dev, 0, 0x8003, 0x00);
 616        /* switch to video camera mode */
 617        reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 618        msleep(2000);
 619        if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
 620                reg_r(gspca_dev, 0x816b, 1);
 621                Data = gspca_dev->usb_buf[0];
 622                reg_w(gspca_dev, 0x00, 0x816b, Data);
 623        }
 624}
 625
 626/* this function is called at probe time */
 627static int sd_config(struct gspca_dev *gspca_dev,
 628                        const struct usb_device_id *id)
 629{
 630        struct sd *sd = (struct sd *) gspca_dev;
 631        struct cam *cam;
 632
 633        cam = &gspca_dev->cam;
 634        sd->subtype = id->driver_info;
 635        if (sd->subtype != LogitechClickSmart310) {
 636                cam->cam_mode = vga_mode;
 637                cam->nmodes = ARRAY_SIZE(vga_mode);
 638        } else {
 639                cam->cam_mode = sif_mode;
 640                cam->nmodes = ARRAY_SIZE(sif_mode);
 641        }
 642        sd->brightness = BRIGHTNESS_DEF;
 643        sd->contrast = CONTRAST_DEF;
 644        sd->colors = COLOR_DEF;
 645        sd->quality = QUALITY_DEF;
 646        return 0;
 647}
 648
 649/* this function is called at probe and resume time */
 650static int sd_init(struct gspca_dev *gspca_dev)
 651{
 652        struct sd *sd = (struct sd *) gspca_dev;
 653
 654        /* initialisation of spca500 based cameras is deferred */
 655        PDEBUG(D_STREAM, "SPCA500 init");
 656        if (sd->subtype == LogitechClickSmart310)
 657                spca500_clksmart310_init(gspca_dev);
 658/*      else
 659                spca500_initialise(gspca_dev); */
 660        PDEBUG(D_STREAM, "SPCA500 init done");
 661        return 0;
 662}
 663
 664static int sd_start(struct gspca_dev *gspca_dev)
 665{
 666        struct sd *sd = (struct sd *) gspca_dev;
 667        int err;
 668        __u8 Data;
 669        __u8 xmult, ymult;
 670
 671        /* create the JPEG header */
 672        sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
 673        if (!sd->jpeg_hdr)
 674                return -ENOMEM;
 675        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 676                        0x22);          /* JPEG 411 */
 677        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
 678
 679        if (sd->subtype == LogitechClickSmart310) {
 680                xmult = 0x16;
 681                ymult = 0x12;
 682        } else {
 683                xmult = 0x28;
 684                ymult = 0x1e;
 685        }
 686
 687        /* is there a sensor here ? */
 688        reg_r(gspca_dev, 0x8a04, 1);
 689        PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
 690                gspca_dev->usb_buf[0]);
 691        PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
 692                gspca_dev->curr_mode, xmult, ymult);
 693
 694        /* setup qtable */
 695        switch (sd->subtype) {
 696        case LogitechClickSmart310:
 697                 spca500_setmode(gspca_dev, xmult, ymult);
 698
 699                /* enable drop packet */
 700                reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
 701                reg_w(gspca_dev, 0x00, 0x8880, 3);
 702                err = spca50x_setup_qtable(gspca_dev,
 703                                           0x00, 0x8800, 0x8840,
 704                                           qtable_creative_pccam);
 705                if (err < 0)
 706                        PDEBUG(D_ERR, "spca50x_setup_qtable failed");
 707                /* Init SDRAM - needed for SDRAM access */
 708                reg_w(gspca_dev, 0x00, 0x870a, 0x04);
 709
 710                /* switch to video camera mode */
 711                reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 712                msleep(500);
 713                if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
 714                        PDEBUG(D_ERR, "reg_r_wait() failed");
 715
 716                reg_r(gspca_dev, 0x816b, 1);
 717                Data = gspca_dev->usb_buf[0];
 718                reg_w(gspca_dev, 0x00, 0x816b, Data);
 719
 720                spca500_synch310(gspca_dev);
 721
 722                write_vector(gspca_dev, spca500_visual_defaults);
 723                spca500_setmode(gspca_dev, xmult, ymult);
 724                /* enable drop packet */
 725                err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
 726                if (err < 0)
 727                        PDEBUG(D_ERR, "failed to enable drop packet");
 728                reg_w(gspca_dev, 0x00, 0x8880, 3);
 729                err = spca50x_setup_qtable(gspca_dev,
 730                                           0x00, 0x8800, 0x8840,
 731                                           qtable_creative_pccam);
 732                if (err < 0)
 733                        PDEBUG(D_ERR, "spca50x_setup_qtable failed");
 734
 735                /* Init SDRAM - needed for SDRAM access */
 736                reg_w(gspca_dev, 0x00, 0x870a, 0x04);
 737
 738                /* switch to video camera mode */
 739                reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 740
 741                if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
 742                        PDEBUG(D_ERR, "reg_r_wait() failed");
 743
 744                reg_r(gspca_dev, 0x816b, 1);
 745                Data = gspca_dev->usb_buf[0];
 746                reg_w(gspca_dev, 0x00, 0x816b, Data);
 747                break;
 748        case CreativePCCam300:          /* Creative PC-CAM 300 640x480 CCD */
 749        case IntelPocketPCCamera:       /* FIXME: Temporary fix for
 750                                         *      Intel Pocket PC Camera
 751                                         *      - NWG (Sat 29th March 2003) */
 752
 753                /* do a full reset */
 754                err = spca500_full_reset(gspca_dev);
 755                if (err < 0)
 756                        PDEBUG(D_ERR, "spca500_full_reset failed");
 757
 758                /* enable drop packet */
 759                err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
 760                if (err < 0)
 761                        PDEBUG(D_ERR, "failed to enable drop packet");
 762                reg_w(gspca_dev, 0x00, 0x8880, 3);
 763                err = spca50x_setup_qtable(gspca_dev,
 764                                           0x00, 0x8800, 0x8840,
 765                                           qtable_creative_pccam);
 766                if (err < 0)
 767                        PDEBUG(D_ERR, "spca50x_setup_qtable failed");
 768
 769                spca500_setmode(gspca_dev, xmult, ymult);
 770                reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
 771
 772                /* switch to video camera mode */
 773                reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 774
 775                if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
 776                        PDEBUG(D_ERR, "reg_r_wait() failed");
 777
 778                reg_r(gspca_dev, 0x816b, 1);
 779                Data = gspca_dev->usb_buf[0];
 780                reg_w(gspca_dev, 0x00, 0x816b, Data);
 781
 782/*              write_vector(gspca_dev, spca500_visual_defaults); */
 783                break;
 784        case KodakEZ200:                /* Kodak EZ200 */
 785
 786                /* do a full reset */
 787                err = spca500_full_reset(gspca_dev);
 788                if (err < 0)
 789                        PDEBUG(D_ERR, "spca500_full_reset failed");
 790                /* enable drop packet */
 791                reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
 792                reg_w(gspca_dev, 0x00, 0x8880, 0);
 793                err = spca50x_setup_qtable(gspca_dev,
 794                                           0x00, 0x8800, 0x8840,
 795                                           qtable_kodak_ez200);
 796                if (err < 0)
 797                        PDEBUG(D_ERR, "spca50x_setup_qtable failed");
 798                spca500_setmode(gspca_dev, xmult, ymult);
 799
 800                reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
 801
 802                /* switch to video camera mode */
 803                reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 804
 805                if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
 806                        PDEBUG(D_ERR, "reg_r_wait() failed");
 807
 808                reg_r(gspca_dev, 0x816b, 1);
 809                Data = gspca_dev->usb_buf[0];
 810                reg_w(gspca_dev, 0x00, 0x816b, Data);
 811
 812/*              write_vector(gspca_dev, spca500_visual_defaults); */
 813                break;
 814
 815        case BenqDC1016:
 816        case DLinkDSC350:               /* FamilyCam 300 */
 817        case AiptekPocketDV:            /* Aiptek PocketDV */
 818        case Gsmartmini:                /*Mustek Gsmart Mini */
 819        case MustekGsmart300:           /* Mustek Gsmart 300 */
 820        case PalmPixDC85:
 821        case Optimedia:
 822        case ToptroIndus:
 823        case AgfaCl20:
 824                spca500_reinit(gspca_dev);
 825                reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
 826                /* enable drop packet */
 827                reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
 828
 829                err = spca50x_setup_qtable(gspca_dev,
 830                                   0x00, 0x8800, 0x8840, qtable_pocketdv);
 831                if (err < 0)
 832                        PDEBUG(D_ERR, "spca50x_setup_qtable failed");
 833                reg_w(gspca_dev, 0x00, 0x8880, 2);
 834
 835                /* familycam Quicksmart pocketDV stuff */
 836                reg_w(gspca_dev, 0x00, 0x800a, 0x00);
 837                /* Set agc transfer: synced inbetween frames */
 838                reg_w(gspca_dev, 0x00, 0x820f, 0x01);
 839                /* Init SDRAM - needed for SDRAM access */
 840                reg_w(gspca_dev, 0x00, 0x870a, 0x04);
 841
 842                spca500_setmode(gspca_dev, xmult, ymult);
 843                /* switch to video camera mode */
 844                reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 845
 846                reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
 847
 848                reg_r(gspca_dev, 0x816b, 1);
 849                Data = gspca_dev->usb_buf[0];
 850                reg_w(gspca_dev, 0x00, 0x816b, Data);
 851                break;
 852        case LogitechTraveler:
 853        case LogitechClickSmart510:
 854                reg_w(gspca_dev, 0x02, 0x00, 0x00);
 855                /* enable drop packet */
 856                reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
 857
 858                err = spca50x_setup_qtable(gspca_dev,
 859                                        0x00, 0x8800,
 860                                        0x8840, qtable_creative_pccam);
 861                if (err < 0)
 862                        PDEBUG(D_ERR, "spca50x_setup_qtable failed");
 863                reg_w(gspca_dev, 0x00, 0x8880, 3);
 864                reg_w(gspca_dev, 0x00, 0x800a, 0x00);
 865                /* Init SDRAM - needed for SDRAM access */
 866                reg_w(gspca_dev, 0x00, 0x870a, 0x04);
 867
 868                spca500_setmode(gspca_dev, xmult, ymult);
 869
 870                /* switch to video camera mode */
 871                reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 872                reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
 873
 874                reg_r(gspca_dev, 0x816b, 1);
 875                Data = gspca_dev->usb_buf[0];
 876                reg_w(gspca_dev, 0x00, 0x816b, Data);
 877                write_vector(gspca_dev, Clicksmart510_defaults);
 878                break;
 879        }
 880        return 0;
 881}
 882
 883static void sd_stopN(struct gspca_dev *gspca_dev)
 884{
 885        reg_w(gspca_dev, 0, 0x8003, 0x00);
 886
 887        /* switch to video camera mode */
 888        reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 889        reg_r(gspca_dev, 0x8000, 1);
 890        PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
 891                gspca_dev->usb_buf[0]);
 892}
 893
 894static void sd_stop0(struct gspca_dev *gspca_dev)
 895{
 896        struct sd *sd = (struct sd *) gspca_dev;
 897
 898        kfree(sd->jpeg_hdr);
 899}
 900
 901static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 902                        struct gspca_frame *frame,      /* target */
 903                        __u8 *data,                     /* isoc packet */
 904                        int len)                        /* iso packet length */
 905{
 906        struct sd *sd = (struct sd *) gspca_dev;
 907        int i;
 908        static __u8 ffd9[] = {0xff, 0xd9};
 909
 910/* frames are jpeg 4.1.1 without 0xff escape */
 911        if (data[0] == 0xff) {
 912                if (data[1] != 0x01) {  /* drop packet */
 913/*                      gspca_dev->last_packet_type = DISCARD_PACKET; */
 914                        return;
 915                }
 916                frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
 917                                        ffd9, 2);
 918
 919                /* put the JPEG header in the new frame */
 920                gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
 921                        sd->jpeg_hdr, JPEG_HDR_SZ);
 922
 923                data += SPCA500_OFFSET_DATA;
 924                len -= SPCA500_OFFSET_DATA;
 925        } else {
 926                data += 1;
 927                len -= 1;
 928        }
 929
 930        /* add 0x00 after 0xff */
 931        i = 0;
 932        do {
 933                if (data[i] == 0xff) {
 934                        gspca_frame_add(gspca_dev, INTER_PACKET, frame,
 935                                        data, i + 1);
 936                        len -= i;
 937                        data += i;
 938                        *data = 0x00;
 939                        i = 0;
 940                }
 941                i++;
 942        } while (i < len);
 943        gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 944}
 945
 946static void setbrightness(struct gspca_dev *gspca_dev)
 947{
 948        struct sd *sd = (struct sd *) gspca_dev;
 949
 950        reg_w(gspca_dev, 0x00, 0x8167,
 951                        (__u8) (sd->brightness - 128));
 952}
 953
 954static void setcontrast(struct gspca_dev *gspca_dev)
 955{
 956        struct sd *sd = (struct sd *) gspca_dev;
 957
 958        reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
 959}
 960
 961static void setcolors(struct gspca_dev *gspca_dev)
 962{
 963        struct sd *sd = (struct sd *) gspca_dev;
 964
 965        reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
 966}
 967
 968static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 969{
 970        struct sd *sd = (struct sd *) gspca_dev;
 971
 972        sd->brightness = val;
 973        if (gspca_dev->streaming)
 974                setbrightness(gspca_dev);
 975        return 0;
 976}
 977
 978static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
 979{
 980        struct sd *sd = (struct sd *) gspca_dev;
 981
 982        *val = sd->brightness;
 983        return 0;
 984}
 985
 986static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
 987{
 988        struct sd *sd = (struct sd *) gspca_dev;
 989
 990        sd->contrast = val;
 991        if (gspca_dev->streaming)
 992                setcontrast(gspca_dev);
 993        return 0;
 994}
 995
 996static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
 997{
 998        struct sd *sd = (struct sd *) gspca_dev;
 999
1000        *val = sd->contrast;
1001        return 0;
1002}
1003
1004static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1005{
1006        struct sd *sd = (struct sd *) gspca_dev;
1007
1008        sd->colors = val;
1009        if (gspca_dev->streaming)
1010                setcolors(gspca_dev);
1011        return 0;
1012}
1013
1014static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1015{
1016        struct sd *sd = (struct sd *) gspca_dev;
1017
1018        *val = sd->colors;
1019        return 0;
1020}
1021
1022static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1023                        struct v4l2_jpegcompression *jcomp)
1024{
1025        struct sd *sd = (struct sd *) gspca_dev;
1026
1027        if (jcomp->quality < QUALITY_MIN)
1028                sd->quality = QUALITY_MIN;
1029        else if (jcomp->quality > QUALITY_MAX)
1030                sd->quality = QUALITY_MAX;
1031        else
1032                sd->quality = jcomp->quality;
1033        if (gspca_dev->streaming)
1034                jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1035        return 0;
1036}
1037
1038static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1039                        struct v4l2_jpegcompression *jcomp)
1040{
1041        struct sd *sd = (struct sd *) gspca_dev;
1042
1043        memset(jcomp, 0, sizeof *jcomp);
1044        jcomp->quality = sd->quality;
1045        jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1046                        | V4L2_JPEG_MARKER_DQT;
1047        return 0;
1048}
1049
1050/* sub-driver description */
1051static struct sd_desc sd_desc = {
1052        .name = MODULE_NAME,
1053        .ctrls = sd_ctrls,
1054        .nctrls = ARRAY_SIZE(sd_ctrls),
1055        .config = sd_config,
1056        .init = sd_init,
1057        .start = sd_start,
1058        .stopN = sd_stopN,
1059        .stop0 = sd_stop0,
1060        .pkt_scan = sd_pkt_scan,
1061        .get_jcomp = sd_get_jcomp,
1062        .set_jcomp = sd_set_jcomp,
1063};
1064
1065/* -- module initialisation -- */
1066static const __devinitdata struct usb_device_id device_table[] = {
1067        {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
1068        {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
1069        {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
1070        {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
1071        {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
1072        {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
1073        {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
1074        {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
1075        {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
1076        {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
1077        {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
1078        {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
1079        {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
1080        {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
1081        {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
1082        {}
1083};
1084MODULE_DEVICE_TABLE(usb, device_table);
1085
1086/* -- device connect -- */
1087static int sd_probe(struct usb_interface *intf,
1088                        const struct usb_device_id *id)
1089{
1090        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1091                                THIS_MODULE);
1092}
1093
1094static struct usb_driver sd_driver = {
1095        .name = MODULE_NAME,
1096        .id_table = device_table,
1097        .probe = sd_probe,
1098        .disconnect = gspca_disconnect,
1099#ifdef CONFIG_PM
1100        .suspend = gspca_suspend,
1101        .resume = gspca_resume,
1102#endif
1103};
1104
1105/* -- module insert / remove -- */
1106static int __init sd_mod_init(void)
1107{
1108        int ret;
1109        ret = usb_register(&sd_driver);
1110        if (ret < 0)
1111                return ret;
1112        PDEBUG(D_PROBE, "registered");
1113        return 0;
1114}
1115static void __exit sd_mod_exit(void)
1116{
1117        usb_deregister(&sd_driver);
1118        PDEBUG(D_PROBE, "deregistered");
1119}
1120
1121module_init(sd_mod_init);
1122module_exit(sd_mod_exit);
1123
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.