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