linux/drivers/media/video/gspca/sunplus.c
<<
>>
Prefs
   1/*
   2 *              Sunplus spca504(abc) spca533 spca536 library
   3 *              Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
   4 *
   5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 */
  21
  22#define MODULE_NAME "sunplus"
  23
  24#include "gspca.h"
  25#include "jpeg.h"
  26
  27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
  28MODULE_DESCRIPTION("GSPCA/SPCA5xx 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        s8 brightness;
  36        u8 contrast;
  37        u8 colors;
  38        u8 autogain;
  39        u8 quality;
  40#define QUALITY_MIN 70
  41#define QUALITY_MAX 95
  42#define QUALITY_DEF 85
  43
  44        u8 bridge;
  45#define BRIDGE_SPCA504 0
  46#define BRIDGE_SPCA504B 1
  47#define BRIDGE_SPCA504C 2
  48#define BRIDGE_SPCA533 3
  49#define BRIDGE_SPCA536 4
  50        u8 subtype;
  51#define AiptekMiniPenCam13 1
  52#define LogitechClickSmart420 2
  53#define LogitechClickSmart820 3
  54#define MegapixV4 4
  55#define MegaImageVI 5
  56
  57        u8 *jpeg_hdr;
  58};
  59
  60/* V4L2 controls supported by the driver */
  61static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
  62static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
  63static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
  64static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
  65static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
  66static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
  67static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
  68static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
  69
  70static struct ctrl sd_ctrls[] = {
  71        {
  72            {
  73                .id      = V4L2_CID_BRIGHTNESS,
  74                .type    = V4L2_CTRL_TYPE_INTEGER,
  75                .name    = "Brightness",
  76                .minimum = -128,
  77                .maximum = 127,
  78                .step    = 1,
  79#define BRIGHTNESS_DEF 0
  80                .default_value = BRIGHTNESS_DEF,
  81            },
  82            .set = sd_setbrightness,
  83            .get = sd_getbrightness,
  84        },
  85        {
  86            {
  87                .id      = V4L2_CID_CONTRAST,
  88                .type    = V4L2_CTRL_TYPE_INTEGER,
  89                .name    = "Contrast",
  90                .minimum = 0,
  91                .maximum = 0xff,
  92                .step    = 1,
  93#define CONTRAST_DEF 0x20
  94                .default_value = CONTRAST_DEF,
  95            },
  96            .set = sd_setcontrast,
  97            .get = sd_getcontrast,
  98        },
  99        {
 100            {
 101                .id      = V4L2_CID_SATURATION,
 102                .type    = V4L2_CTRL_TYPE_INTEGER,
 103                .name    = "Color",
 104                .minimum = 0,
 105                .maximum = 0xff,
 106                .step    = 1,
 107#define COLOR_DEF 0x1a
 108                .default_value = COLOR_DEF,
 109            },
 110            .set = sd_setcolors,
 111            .get = sd_getcolors,
 112        },
 113        {
 114            {
 115                .id      = V4L2_CID_AUTOGAIN,
 116                .type    = V4L2_CTRL_TYPE_BOOLEAN,
 117                .name    = "Auto Gain",
 118                .minimum = 0,
 119                .maximum = 1,
 120                .step    = 1,
 121#define AUTOGAIN_DEF 1
 122                .default_value = AUTOGAIN_DEF,
 123            },
 124            .set = sd_setautogain,
 125            .get = sd_getautogain,
 126        },
 127};
 128
 129static const struct v4l2_pix_format vga_mode[] = {
 130        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 131                .bytesperline = 320,
 132                .sizeimage = 320 * 240 * 3 / 8 + 590,
 133                .colorspace = V4L2_COLORSPACE_JPEG,
 134                .priv = 2},
 135        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 136                .bytesperline = 640,
 137                .sizeimage = 640 * 480 * 3 / 8 + 590,
 138                .colorspace = V4L2_COLORSPACE_JPEG,
 139                .priv = 1},
 140};
 141
 142static const struct v4l2_pix_format custom_mode[] = {
 143        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 144                .bytesperline = 320,
 145                .sizeimage = 320 * 240 * 3 / 8 + 590,
 146                .colorspace = V4L2_COLORSPACE_JPEG,
 147                .priv = 2},
 148        {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 149                .bytesperline = 464,
 150                .sizeimage = 464 * 480 * 3 / 8 + 590,
 151                .colorspace = V4L2_COLORSPACE_JPEG,
 152                .priv = 1},
 153};
 154
 155static const struct v4l2_pix_format vga_mode2[] = {
 156        {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 157                .bytesperline = 176,
 158                .sizeimage = 176 * 144 * 3 / 8 + 590,
 159                .colorspace = V4L2_COLORSPACE_JPEG,
 160                .priv = 4},
 161        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 162                .bytesperline = 320,
 163                .sizeimage = 320 * 240 * 3 / 8 + 590,
 164                .colorspace = V4L2_COLORSPACE_JPEG,
 165                .priv = 3},
 166        {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 167                .bytesperline = 352,
 168                .sizeimage = 352 * 288 * 3 / 8 + 590,
 169                .colorspace = V4L2_COLORSPACE_JPEG,
 170                .priv = 2},
 171        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 172                .bytesperline = 640,
 173                .sizeimage = 640 * 480 * 3 / 8 + 590,
 174                .colorspace = V4L2_COLORSPACE_JPEG,
 175                .priv = 1},
 176};
 177
 178#define SPCA50X_OFFSET_DATA 10
 179#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
 180#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
 181#define SPCA504_PCCAM600_OFFSET_MODE     5
 182#define SPCA504_PCCAM600_OFFSET_DATA     14
 183 /* Frame packet header offsets for the spca533 */
 184#define SPCA533_OFFSET_DATA     16
 185#define SPCA533_OFFSET_FRAMSEQ  15
 186/* Frame packet header offsets for the spca536 */
 187#define SPCA536_OFFSET_DATA     4
 188#define SPCA536_OFFSET_FRAMSEQ  1
 189
 190struct cmd {
 191        u8 req;
 192        u16 val;
 193        u16 idx;
 194};
 195
 196/* Initialisation data for the Creative PC-CAM 600 */
 197static const struct cmd spca504_pccam600_init_data[] = {
 198/*      {0xa0, 0x0000, 0x0503},  * capture mode */
 199        {0x00, 0x0000, 0x2000},
 200        {0x00, 0x0013, 0x2301},
 201        {0x00, 0x0003, 0x2000},
 202        {0x00, 0x0001, 0x21ac},
 203        {0x00, 0x0001, 0x21a6},
 204        {0x00, 0x0000, 0x21a7}, /* brightness */
 205        {0x00, 0x0020, 0x21a8}, /* contrast */
 206        {0x00, 0x0001, 0x21ac}, /* sat/hue */
 207        {0x00, 0x0000, 0x21ad}, /* hue */
 208        {0x00, 0x001a, 0x21ae}, /* saturation */
 209        {0x00, 0x0002, 0x21a3}, /* gamma */
 210        {0x30, 0x0154, 0x0008},
 211        {0x30, 0x0004, 0x0006},
 212        {0x30, 0x0258, 0x0009},
 213        {0x30, 0x0004, 0x0000},
 214        {0x30, 0x0093, 0x0004},
 215        {0x30, 0x0066, 0x0005},
 216        {0x00, 0x0000, 0x2000},
 217        {0x00, 0x0013, 0x2301},
 218        {0x00, 0x0003, 0x2000},
 219        {0x00, 0x0013, 0x2301},
 220        {0x00, 0x0003, 0x2000},
 221};
 222
 223/* Creative PC-CAM 600 specific open data, sent before using the
 224 * generic initialisation data from spca504_open_data.
 225 */
 226static const struct cmd spca504_pccam600_open_data[] = {
 227        {0x00, 0x0001, 0x2501},
 228        {0x20, 0x0500, 0x0001}, /* snapshot mode */
 229        {0x00, 0x0003, 0x2880},
 230        {0x00, 0x0001, 0x2881},
 231};
 232
 233/* Initialisation data for the logitech clicksmart 420 */
 234static const struct cmd spca504A_clicksmart420_init_data[] = {
 235/*      {0xa0, 0x0000, 0x0503},  * capture mode */
 236        {0x00, 0x0000, 0x2000},
 237        {0x00, 0x0013, 0x2301},
 238        {0x00, 0x0003, 0x2000},
 239        {0x00, 0x0001, 0x21ac},
 240        {0x00, 0x0001, 0x21a6},
 241        {0x00, 0x0000, 0x21a7}, /* brightness */
 242        {0x00, 0x0020, 0x21a8}, /* contrast */
 243        {0x00, 0x0001, 0x21ac}, /* sat/hue */
 244        {0x00, 0x0000, 0x21ad}, /* hue */
 245        {0x00, 0x001a, 0x21ae}, /* saturation */
 246        {0x00, 0x0002, 0x21a3}, /* gamma */
 247        {0x30, 0x0004, 0x000a},
 248        {0xb0, 0x0001, 0x0000},
 249
 250
 251        {0xa1, 0x0080, 0x0001},
 252        {0x30, 0x0049, 0x0000},
 253        {0x30, 0x0060, 0x0005},
 254        {0x0c, 0x0004, 0x0000},
 255        {0x00, 0x0000, 0x0000},
 256        {0x00, 0x0000, 0x2000},
 257        {0x00, 0x0013, 0x2301},
 258        {0x00, 0x0003, 0x2000},
 259        {0x00, 0x0000, 0x2000},
 260
 261};
 262
 263/* clicksmart 420 open data ? */
 264static const struct cmd spca504A_clicksmart420_open_data[] = {
 265        {0x00, 0x0001, 0x2501},
 266        {0x20, 0x0502, 0x0000},
 267        {0x06, 0x0000, 0x0000},
 268        {0x00, 0x0004, 0x2880},
 269        {0x00, 0x0001, 0x2881},
 270/* look like setting a qTable */
 271        {0x00, 0x0006, 0x2800},
 272        {0x00, 0x0004, 0x2801},
 273        {0x00, 0x0004, 0x2802},
 274        {0x00, 0x0006, 0x2803},
 275        {0x00, 0x000a, 0x2804},
 276        {0x00, 0x0010, 0x2805},
 277        {0x00, 0x0014, 0x2806},
 278        {0x00, 0x0018, 0x2807},
 279        {0x00, 0x0005, 0x2808},
 280        {0x00, 0x0005, 0x2809},
 281        {0x00, 0x0006, 0x280a},
 282        {0x00, 0x0008, 0x280b},
 283        {0x00, 0x000a, 0x280c},
 284        {0x00, 0x0017, 0x280d},
 285        {0x00, 0x0018, 0x280e},
 286        {0x00, 0x0016, 0x280f},
 287
 288        {0x00, 0x0006, 0x2810},
 289        {0x00, 0x0005, 0x2811},
 290        {0x00, 0x0006, 0x2812},
 291        {0x00, 0x000a, 0x2813},
 292        {0x00, 0x0010, 0x2814},
 293        {0x00, 0x0017, 0x2815},
 294        {0x00, 0x001c, 0x2816},
 295        {0x00, 0x0016, 0x2817},
 296        {0x00, 0x0006, 0x2818},
 297        {0x00, 0x0007, 0x2819},
 298        {0x00, 0x0009, 0x281a},
 299        {0x00, 0x000c, 0x281b},
 300        {0x00, 0x0014, 0x281c},
 301        {0x00, 0x0023, 0x281d},
 302        {0x00, 0x0020, 0x281e},
 303        {0x00, 0x0019, 0x281f},
 304
 305        {0x00, 0x0007, 0x2820},
 306        {0x00, 0x0009, 0x2821},
 307        {0x00, 0x000f, 0x2822},
 308        {0x00, 0x0016, 0x2823},
 309        {0x00, 0x001b, 0x2824},
 310        {0x00, 0x002c, 0x2825},
 311        {0x00, 0x0029, 0x2826},
 312        {0x00, 0x001f, 0x2827},
 313        {0x00, 0x000a, 0x2828},
 314        {0x00, 0x000e, 0x2829},
 315        {0x00, 0x0016, 0x282a},
 316        {0x00, 0x001a, 0x282b},
 317        {0x00, 0x0020, 0x282c},
 318        {0x00, 0x002a, 0x282d},
 319        {0x00, 0x002d, 0x282e},
 320        {0x00, 0x0025, 0x282f},
 321
 322        {0x00, 0x0014, 0x2830},
 323        {0x00, 0x001a, 0x2831},
 324        {0x00, 0x001f, 0x2832},
 325        {0x00, 0x0023, 0x2833},
 326        {0x00, 0x0029, 0x2834},
 327        {0x00, 0x0030, 0x2835},
 328        {0x00, 0x0030, 0x2836},
 329        {0x00, 0x0028, 0x2837},
 330        {0x00, 0x001d, 0x2838},
 331        {0x00, 0x0025, 0x2839},
 332        {0x00, 0x0026, 0x283a},
 333        {0x00, 0x0027, 0x283b},
 334        {0x00, 0x002d, 0x283c},
 335        {0x00, 0x0028, 0x283d},
 336        {0x00, 0x0029, 0x283e},
 337        {0x00, 0x0028, 0x283f},
 338
 339        {0x00, 0x0007, 0x2840},
 340        {0x00, 0x0007, 0x2841},
 341        {0x00, 0x000a, 0x2842},
 342        {0x00, 0x0013, 0x2843},
 343        {0x00, 0x0028, 0x2844},
 344        {0x00, 0x0028, 0x2845},
 345        {0x00, 0x0028, 0x2846},
 346        {0x00, 0x0028, 0x2847},
 347        {0x00, 0x0007, 0x2848},
 348        {0x00, 0x0008, 0x2849},
 349        {0x00, 0x000a, 0x284a},
 350        {0x00, 0x001a, 0x284b},
 351        {0x00, 0x0028, 0x284c},
 352        {0x00, 0x0028, 0x284d},
 353        {0x00, 0x0028, 0x284e},
 354        {0x00, 0x0028, 0x284f},
 355
 356        {0x00, 0x000a, 0x2850},
 357        {0x00, 0x000a, 0x2851},
 358        {0x00, 0x0016, 0x2852},
 359        {0x00, 0x0028, 0x2853},
 360        {0x00, 0x0028, 0x2854},
 361        {0x00, 0x0028, 0x2855},
 362        {0x00, 0x0028, 0x2856},
 363        {0x00, 0x0028, 0x2857},
 364        {0x00, 0x0013, 0x2858},
 365        {0x00, 0x001a, 0x2859},
 366        {0x00, 0x0028, 0x285a},
 367        {0x00, 0x0028, 0x285b},
 368        {0x00, 0x0028, 0x285c},
 369        {0x00, 0x0028, 0x285d},
 370        {0x00, 0x0028, 0x285e},
 371        {0x00, 0x0028, 0x285f},
 372
 373        {0x00, 0x0028, 0x2860},
 374        {0x00, 0x0028, 0x2861},
 375        {0x00, 0x0028, 0x2862},
 376        {0x00, 0x0028, 0x2863},
 377        {0x00, 0x0028, 0x2864},
 378        {0x00, 0x0028, 0x2865},
 379        {0x00, 0x0028, 0x2866},
 380        {0x00, 0x0028, 0x2867},
 381        {0x00, 0x0028, 0x2868},
 382        {0x00, 0x0028, 0x2869},
 383        {0x00, 0x0028, 0x286a},
 384        {0x00, 0x0028, 0x286b},
 385        {0x00, 0x0028, 0x286c},
 386        {0x00, 0x0028, 0x286d},
 387        {0x00, 0x0028, 0x286e},
 388        {0x00, 0x0028, 0x286f},
 389
 390        {0x00, 0x0028, 0x2870},
 391        {0x00, 0x0028, 0x2871},
 392        {0x00, 0x0028, 0x2872},
 393        {0x00, 0x0028, 0x2873},
 394        {0x00, 0x0028, 0x2874},
 395        {0x00, 0x0028, 0x2875},
 396        {0x00, 0x0028, 0x2876},
 397        {0x00, 0x0028, 0x2877},
 398        {0x00, 0x0028, 0x2878},
 399        {0x00, 0x0028, 0x2879},
 400        {0x00, 0x0028, 0x287a},
 401        {0x00, 0x0028, 0x287b},
 402        {0x00, 0x0028, 0x287c},
 403        {0x00, 0x0028, 0x287d},
 404        {0x00, 0x0028, 0x287e},
 405        {0x00, 0x0028, 0x287f},
 406
 407        {0xa0, 0x0000, 0x0503},
 408};
 409
 410static const u8 qtable_creative_pccam[2][64] = {
 411        {                               /* Q-table Y-components */
 412         0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
 413         0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
 414         0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
 415         0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
 416         0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
 417         0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
 418         0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
 419         0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
 420        {                               /* Q-table C-components */
 421         0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
 422         0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
 423         0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 424         0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 425         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 426         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 427         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 428         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
 429};
 430
 431/* FIXME: This Q-table is identical to the Creative PC-CAM one,
 432 *              except for one byte. Possibly a typo?
 433 *              NWG: 18/05/2003.
 434 */
 435static const u8 qtable_spca504_default[2][64] = {
 436        {                               /* Q-table Y-components */
 437         0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
 438         0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
 439         0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
 440         0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
 441         0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
 442         0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
 443         0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
 444         0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
 445         },
 446        {                               /* Q-table C-components */
 447         0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
 448         0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
 449         0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 450         0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 451         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 452         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 453         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 454         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
 455};
 456
 457/* read <len> bytes to gspca_dev->usb_buf */
 458static void reg_r(struct gspca_dev *gspca_dev,
 459                  u8 req,
 460                  u16 index,
 461                  u16 len)
 462{
 463#ifdef GSPCA_DEBUG
 464        if (len > USB_BUF_SZ) {
 465                err("reg_r: buffer overflow");
 466                return;
 467        }
 468#endif
 469        usb_control_msg(gspca_dev->dev,
 470                        usb_rcvctrlpipe(gspca_dev->dev, 0),
 471                        req,
 472                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 473                        0,              /* value */
 474                        index,
 475                        len ? gspca_dev->usb_buf : NULL, len,
 476                        500);
 477}
 478
 479/* write one byte */
 480static void reg_w_1(struct gspca_dev *gspca_dev,
 481                   u8 req,
 482                   u16 value,
 483                   u16 index,
 484                   u16 byte)
 485{
 486        gspca_dev->usb_buf[0] = byte;
 487        usb_control_msg(gspca_dev->dev,
 488                        usb_sndctrlpipe(gspca_dev->dev, 0),
 489                        req,
 490                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 491                        value, index,
 492                        gspca_dev->usb_buf, 1,
 493                        500);
 494}
 495
 496/* write req / index / value */
 497static int reg_w_riv(struct usb_device *dev,
 498                     u8 req, u16 index, u16 value)
 499{
 500        int ret;
 501
 502        ret = usb_control_msg(dev,
 503                        usb_sndctrlpipe(dev, 0),
 504                        req,
 505                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 506                        value, index, NULL, 0, 500);
 507        PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
 508                req, index, value, ret);
 509        if (ret < 0)
 510                PDEBUG(D_ERR, "reg write: error %d", ret);
 511        return ret;
 512}
 513
 514/* read 1 byte */
 515static int reg_r_1(struct gspca_dev *gspca_dev,
 516                        u16 value)      /* wValue */
 517{
 518        int ret;
 519
 520        ret = usb_control_msg(gspca_dev->dev,
 521                        usb_rcvctrlpipe(gspca_dev->dev, 0),
 522                        0x20,                   /* request */
 523                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 524                        value,
 525                        0,                      /* index */
 526                        gspca_dev->usb_buf, 1,
 527                        500);                   /* timeout */
 528        if (ret < 0) {
 529                PDEBUG(D_ERR, "reg_r_1 err %d", ret);
 530                return 0;
 531        }
 532        return gspca_dev->usb_buf[0];
 533}
 534
 535/* read 1 or 2 bytes - returns < 0 if error */
 536static int reg_r_12(struct gspca_dev *gspca_dev,
 537                        u8 req,         /* bRequest */
 538                        u16 index,      /* wIndex */
 539                        u16 length)     /* wLength (1 or 2 only) */
 540{
 541        int ret;
 542
 543        gspca_dev->usb_buf[1] = 0;
 544        ret = usb_control_msg(gspca_dev->dev,
 545                        usb_rcvctrlpipe(gspca_dev->dev, 0),
 546                        req,
 547                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 548                        0,              /* value */
 549                        index,
 550                        gspca_dev->usb_buf, length,
 551                        500);
 552        if (ret < 0) {
 553                PDEBUG(D_ERR, "reg_read err %d", ret);
 554                return -1;
 555        }
 556        return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
 557}
 558
 559static int write_vector(struct gspca_dev *gspca_dev,
 560                        const struct cmd *data, int ncmds)
 561{
 562        struct usb_device *dev = gspca_dev->dev;
 563        int ret;
 564
 565        while (--ncmds >= 0) {
 566                ret = reg_w_riv(dev, data->req, data->idx, data->val);
 567                if (ret < 0) {
 568                        PDEBUG(D_ERR,
 569                           "Register write failed for 0x%02x, 0x%04x, 0x%04x",
 570                                data->req, data->val, data->idx);
 571                        return ret;
 572                }
 573                data++;
 574        }
 575        return 0;
 576}
 577
 578static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
 579                                const u8 qtable[2][64])
 580{
 581        struct usb_device *dev = gspca_dev->dev;
 582        int i, err;
 583
 584        /* loop over y components */
 585        for (i = 0; i < 64; i++) {
 586                err = reg_w_riv(dev, 0x00, 0x2800 + i, qtable[0][i]);
 587                if (err < 0)
 588                        return err;
 589        }
 590
 591        /* loop over c components */
 592        for (i = 0; i < 64; i++) {
 593                err = reg_w_riv(dev, 0x00, 0x2840 + i, qtable[1][i]);
 594                if (err < 0)
 595                        return err;
 596        }
 597        return 0;
 598}
 599
 600static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
 601                             u8 req, u16 idx, u16 val)
 602{
 603        struct usb_device *dev = gspca_dev->dev;
 604        int notdone;
 605
 606        reg_w_riv(dev, req, idx, val);
 607        notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
 608        reg_w_riv(dev, req, idx, val);
 609
 610        PDEBUG(D_FRAM, "before wait 0x%04x", notdone);
 611
 612        msleep(200);
 613        notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
 614        PDEBUG(D_FRAM, "after wait 0x%04x", notdone);
 615}
 616
 617static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
 618                        u8 req,
 619                        u16 idx, u16 val, u8 stat, u8 count)
 620{
 621        struct usb_device *dev = gspca_dev->dev;
 622        int status;
 623        u8 endcode;
 624
 625        reg_w_riv(dev, req, idx, val);
 626        status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
 627        endcode = stat;
 628        PDEBUG(D_FRAM, "Status 0x%x Need 0x%04x", status, stat);
 629        if (!count)
 630                return;
 631        count = 200;
 632        while (--count > 0) {
 633                msleep(10);
 634                /* gsmart mini2 write a each wait setting 1 ms is enought */
 635/*              reg_w_riv(dev, req, idx, val); */
 636                status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
 637                if (status == endcode) {
 638                        PDEBUG(D_FRAM, "status 0x%04x after wait %d",
 639                                status, 200 - count);
 640                                break;
 641                }
 642        }
 643}
 644
 645static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
 646{
 647        int count = 10;
 648
 649        while (--count > 0) {
 650                reg_r(gspca_dev, 0x21, 0, 1);
 651                if ((gspca_dev->usb_buf[0] & 0x01) == 0)
 652                        break;
 653                msleep(10);
 654        }
 655        return gspca_dev->usb_buf[0];
 656}
 657
 658static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
 659{
 660        int count = 50;
 661
 662        while (--count > 0) {
 663                reg_r(gspca_dev, 0x21, 1, 1);
 664                if (gspca_dev->usb_buf[0] != 0) {
 665                        reg_w_1(gspca_dev, 0x21, 0, 1, 0);
 666                        reg_r(gspca_dev, 0x21, 1, 1);
 667                        spca504B_PollingDataReady(gspca_dev);
 668                        break;
 669                }
 670                msleep(10);
 671        }
 672}
 673
 674static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
 675{
 676        u8 *data;
 677
 678        data = gspca_dev->usb_buf;
 679        reg_r(gspca_dev, 0x20, 0, 5);
 680        PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
 681                data[0], data[1], data[2], data[3], data[4]);
 682        reg_r(gspca_dev, 0x23, 0, 64);
 683        reg_r(gspca_dev, 0x23, 1, 64);
 684}
 685
 686static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
 687{
 688        struct sd *sd = (struct sd *) gspca_dev;
 689        struct usb_device *dev = gspca_dev->dev;
 690        u8 Size;
 691        int rc;
 692
 693        Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 694        switch (sd->bridge) {
 695        case BRIDGE_SPCA533:
 696                reg_w_riv(dev, 0x31, 0, 0);
 697                spca504B_WaitCmdStatus(gspca_dev);
 698                rc = spca504B_PollingDataReady(gspca_dev);
 699                spca50x_GetFirmware(gspca_dev);
 700                reg_w_1(gspca_dev, 0x24, 0, 8, 2);              /* type */
 701                reg_r(gspca_dev, 0x24, 8, 1);
 702
 703                reg_w_1(gspca_dev, 0x25, 0, 4, Size);
 704                reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
 705                rc = spca504B_PollingDataReady(gspca_dev);
 706
 707                /* Init the cam width height with some values get on init ? */
 708                reg_w_riv(dev, 0x31, 0, 0x04);
 709                spca504B_WaitCmdStatus(gspca_dev);
 710                rc = spca504B_PollingDataReady(gspca_dev);
 711                break;
 712        default:
 713/* case BRIDGE_SPCA504B: */
 714/* case BRIDGE_SPCA536: */
 715                reg_w_1(gspca_dev, 0x25, 0, 4, Size);
 716                reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
 717                reg_w_1(gspca_dev, 0x27, 0, 0, 6);
 718                reg_r(gspca_dev, 0x27, 0, 1);                   /* type */
 719                rc = spca504B_PollingDataReady(gspca_dev);
 720                break;
 721        case BRIDGE_SPCA504:
 722                Size += 3;
 723                if (sd->subtype == AiptekMiniPenCam13) {
 724                        /* spca504a aiptek */
 725                        spca504A_acknowledged_command(gspca_dev,
 726                                                0x08, Size, 0,
 727                                                0x80 | (Size & 0x0f), 1);
 728                        spca504A_acknowledged_command(gspca_dev,
 729                                                        1, 3, 0, 0x9f, 0);
 730                } else {
 731                        spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
 732                }
 733                break;
 734        case BRIDGE_SPCA504C:
 735                /* capture mode */
 736                reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
 737                reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
 738                break;
 739        }
 740}
 741
 742static void spca504_wait_status(struct gspca_dev *gspca_dev)
 743{
 744        int cnt;
 745
 746        cnt = 256;
 747        while (--cnt > 0) {
 748                /* With this we get the status, when return 0 it's all ok */
 749                if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
 750                        return;
 751                msleep(10);
 752        }
 753}
 754
 755static void spca504B_setQtable(struct gspca_dev *gspca_dev)
 756{
 757        reg_w_1(gspca_dev, 0x26, 0, 0, 3);
 758        reg_r(gspca_dev, 0x26, 0, 1);
 759        spca504B_PollingDataReady(gspca_dev);
 760}
 761
 762static void setbrightness(struct gspca_dev *gspca_dev)
 763{
 764        struct sd *sd = (struct sd *) gspca_dev;
 765        struct usb_device *dev = gspca_dev->dev;
 766        u16 reg;
 767
 768        reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
 769        reg_w_riv(dev, 0x00, reg, sd->brightness);
 770}
 771
 772static void setcontrast(struct gspca_dev *gspca_dev)
 773{
 774        struct sd *sd = (struct sd *) gspca_dev;
 775        struct usb_device *dev = gspca_dev->dev;
 776        u16 reg;
 777
 778        reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
 779        reg_w_riv(dev, 0x00, reg, sd->contrast);
 780}
 781
 782static void setcolors(struct gspca_dev *gspca_dev)
 783{
 784        struct sd *sd = (struct sd *) gspca_dev;
 785        struct usb_device *dev = gspca_dev->dev;
 786        u16 reg;
 787
 788        reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
 789        reg_w_riv(dev, 0x00, reg, sd->colors);
 790}
 791
 792static void init_ctl_reg(struct gspca_dev *gspca_dev)
 793{
 794        struct sd *sd = (struct sd *) gspca_dev;
 795        struct usb_device *dev = gspca_dev->dev;
 796        int pollreg = 1;
 797
 798        setbrightness(gspca_dev);
 799        setcontrast(gspca_dev);
 800        setcolors(gspca_dev);
 801
 802        switch (sd->bridge) {
 803        case BRIDGE_SPCA504:
 804        case BRIDGE_SPCA504C:
 805                pollreg = 0;
 806                /* fall thru */
 807        default:
 808/*      case BRIDGE_SPCA533: */
 809/*      case BRIDGE_SPCA504B: */
 810                reg_w_riv(dev, 0, 0x00, 0x21ad);        /* hue */
 811                reg_w_riv(dev, 0, 0x01, 0x21ac);        /* sat/hue */
 812                reg_w_riv(dev, 0, 0x00, 0x21a3);        /* gamma */
 813                break;
 814        case BRIDGE_SPCA536:
 815                reg_w_riv(dev, 0, 0x40, 0x20f5);
 816                reg_w_riv(dev, 0, 0x01, 0x20f4);
 817                reg_w_riv(dev, 0, 0x00, 0x2089);
 818                break;
 819        }
 820        if (pollreg)
 821                spca504B_PollingDataReady(gspca_dev);
 822}
 823
 824/* this function is called at probe time */
 825static int sd_config(struct gspca_dev *gspca_dev,
 826                        const struct usb_device_id *id)
 827{
 828        struct sd *sd = (struct sd *) gspca_dev;
 829        struct cam *cam;
 830
 831        cam = &gspca_dev->cam;
 832
 833        sd->bridge = id->driver_info >> 8;
 834        sd->subtype = id->driver_info;
 835
 836        if (sd->subtype == AiptekMiniPenCam13) {
 837/* try to get the firmware as some cam answer 2.0.1.2.2
 838 * and should be a spca504b then overwrite that setting */
 839                reg_r(gspca_dev, 0x20, 0, 1);
 840                switch (gspca_dev->usb_buf[0]) {
 841                case 1:
 842                        break;          /* (right bridge/subtype) */
 843                case 2:
 844                        sd->bridge = BRIDGE_SPCA504B;
 845                        sd->subtype = 0;
 846                        break;
 847                default:
 848                        return -ENODEV;
 849                }
 850        }
 851
 852        switch (sd->bridge) {
 853        default:
 854/*      case BRIDGE_SPCA504B: */
 855/*      case BRIDGE_SPCA504: */
 856/*      case BRIDGE_SPCA536: */
 857                cam->cam_mode = vga_mode;
 858                cam->nmodes =ARRAY_SIZE(vga_mode);
 859                break;
 860        case BRIDGE_SPCA533:
 861                cam->cam_mode = custom_mode;
 862                if (sd->subtype == MegaImageVI)         /* 320x240 only */
 863                        cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
 864                else
 865                        cam->nmodes = ARRAY_SIZE(custom_mode);
 866                break;
 867        case BRIDGE_SPCA504C:
 868                cam->cam_mode = vga_mode2;
 869                cam->nmodes = ARRAY_SIZE(vga_mode2);
 870                break;
 871        }
 872        sd->brightness = BRIGHTNESS_DEF;
 873        sd->contrast = CONTRAST_DEF;
 874        sd->colors = COLOR_DEF;
 875        sd->autogain = AUTOGAIN_DEF;
 876        sd->quality = QUALITY_DEF;
 877        return 0;
 878}
 879
 880/* this function is called at probe and resume time */
 881static int sd_init(struct gspca_dev *gspca_dev)
 882{
 883        struct sd *sd = (struct sd *) gspca_dev;
 884        struct usb_device *dev = gspca_dev->dev;
 885        int i, err_code;
 886        u8 info[6];
 887
 888        switch (sd->bridge) {
 889        case BRIDGE_SPCA504B:
 890                reg_w_riv(dev, 0x1d, 0x00, 0);
 891                reg_w_riv(dev, 0, 0x01, 0x2306);
 892                reg_w_riv(dev, 0, 0x00, 0x0d04);
 893                reg_w_riv(dev, 0, 0x00, 0x2000);
 894                reg_w_riv(dev, 0, 0x13, 0x2301);
 895                reg_w_riv(dev, 0, 0x00, 0x2306);
 896                /* fall thru */
 897        case BRIDGE_SPCA533:
 898                spca504B_PollingDataReady(gspca_dev);
 899                spca50x_GetFirmware(gspca_dev);
 900                break;
 901        case BRIDGE_SPCA536:
 902                spca50x_GetFirmware(gspca_dev);
 903                reg_r(gspca_dev, 0x00, 0x5002, 1);
 904                reg_w_1(gspca_dev, 0x24, 0, 0, 0);
 905                reg_r(gspca_dev, 0x24, 0, 1);
 906                spca504B_PollingDataReady(gspca_dev);
 907                reg_w_riv(dev, 0x34, 0, 0);
 908                spca504B_WaitCmdStatus(gspca_dev);
 909                break;
 910        case BRIDGE_SPCA504C:   /* pccam600 */
 911                PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
 912                reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
 913                reg_w_riv(dev, 0xe0, 0x0000, 0x0001);   /* reset */
 914                spca504_wait_status(gspca_dev);
 915                if (sd->subtype == LogitechClickSmart420)
 916                        write_vector(gspca_dev,
 917                                spca504A_clicksmart420_open_data,
 918                                ARRAY_SIZE(spca504A_clicksmart420_open_data));
 919                else
 920                        write_vector(gspca_dev, spca504_pccam600_open_data,
 921                                ARRAY_SIZE(spca504_pccam600_open_data));
 922                err_code = spca50x_setup_qtable(gspca_dev,
 923                                                qtable_creative_pccam);
 924                if (err_code < 0) {
 925                        PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
 926                        return err_code;
 927                }
 928                break;
 929        default:
 930/*      case BRIDGE_SPCA504: */
 931                PDEBUG(D_STREAM, "Opening SPCA504");
 932                if (sd->subtype == AiptekMiniPenCam13) {
 933                        /*****************************/
 934                        for (i = 0; i < 6; i++)
 935                                info[i] = reg_r_1(gspca_dev, i);
 936                        PDEBUG(D_STREAM,
 937                                "Read info: %d %d %d %d %d %d."
 938                                " Should be 1,0,2,2,0,0",
 939                                info[0], info[1], info[2],
 940                                info[3], info[4], info[5]);
 941                        /* spca504a aiptek */
 942                        /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
 943                        spca504A_acknowledged_command(gspca_dev, 0x24,
 944                                                        8, 3, 0x9e, 1);
 945                        /* Twice sequencial need status 0xff->0x9e->0x9d */
 946                        spca504A_acknowledged_command(gspca_dev, 0x24,
 947                                                        8, 3, 0x9e, 0);
 948
 949                        spca504A_acknowledged_command(gspca_dev, 0x24,
 950                                                        0, 0, 0x9d, 1);
 951                        /******************************/
 952                        /* spca504a aiptek */
 953                        spca504A_acknowledged_command(gspca_dev, 0x08,
 954                                                        6, 0, 0x86, 1);
 955/*                      reg_write (dev, 0, 0x2000, 0); */
 956/*                      reg_write (dev, 0, 0x2883, 1); */
 957/*                      spca504A_acknowledged_command (gspca_dev, 0x08,
 958                                                        6, 0, 0x86, 1); */
 959/*                      spca504A_acknowledged_command (gspca_dev, 0x24,
 960                                                        0, 0, 0x9D, 1); */
 961                        reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */
 962                        reg_w_riv(dev, 0x00, 0x2310, 0x05);
 963                        spca504A_acknowledged_command(gspca_dev, 0x01,
 964                                                        0x0f, 0, 0xff, 0);
 965                }
 966                /* setup qtable */
 967                reg_w_riv(dev, 0, 0x2000, 0);
 968                reg_w_riv(dev, 0, 0x2883, 1);
 969                err_code = spca50x_setup_qtable(gspca_dev,
 970                                                qtable_spca504_default);
 971                if (err_code < 0) {
 972                        PDEBUG(D_ERR, "spca50x_setup_qtable failed");
 973                        return err_code;
 974                }
 975                break;
 976        }
 977        return 0;
 978}
 979
 980static int sd_start(struct gspca_dev *gspca_dev)
 981{
 982        struct sd *sd = (struct sd *) gspca_dev;
 983        struct usb_device *dev = gspca_dev->dev;
 984        int enable;
 985        int i;
 986        u8 info[6];
 987
 988        /* create the JPEG header */
 989        sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
 990        if (!sd->jpeg_hdr)
 991                return -ENOMEM;
 992        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 993                        0x22);          /* JPEG 411 */
 994        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
 995
 996        if (sd->bridge == BRIDGE_SPCA504B)
 997                spca504B_setQtable(gspca_dev);
 998        spca504B_SetSizeType(gspca_dev);
 999        switch (sd->bridge) {
1000        default:
1001/*      case BRIDGE_SPCA504B: */
1002/*      case BRIDGE_SPCA533: */
1003/*      case BRIDGE_SPCA536: */
1004                switch (sd->subtype) {
1005                case MegapixV4:
1006                case LogitechClickSmart820:
1007                case MegaImageVI:
1008                        reg_w_riv(dev, 0xf0, 0, 0);
1009                        spca504B_WaitCmdStatus(gspca_dev);
1010                        reg_r(gspca_dev, 0xf0, 4, 0);
1011                        spca504B_WaitCmdStatus(gspca_dev);
1012                        break;
1013                default:
1014                        reg_w_riv(dev, 0x31, 0, 0x04);
1015                        spca504B_WaitCmdStatus(gspca_dev);
1016                        spca504B_PollingDataReady(gspca_dev);
1017                        break;
1018                }
1019                break;
1020        case BRIDGE_SPCA504:
1021                if (sd->subtype == AiptekMiniPenCam13) {
1022                        for (i = 0; i < 6; i++)
1023                                info[i] = reg_r_1(gspca_dev, i);
1024                        PDEBUG(D_STREAM,
1025                                "Read info: %d %d %d %d %d %d."
1026                                " Should be 1,0,2,2,0,0",
1027                                info[0], info[1], info[2],
1028                                info[3], info[4], info[5]);
1029                        /* spca504a aiptek */
1030                        /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1031                        spca504A_acknowledged_command(gspca_dev, 0x24,
1032                                                        8, 3, 0x9e, 1);
1033                        /* Twice sequencial need status 0xff->0x9e->0x9d */
1034                        spca504A_acknowledged_command(gspca_dev, 0x24,
1035                                                        8, 3, 0x9e, 0);
1036                        spca504A_acknowledged_command(gspca_dev, 0x24,
1037                                                        0, 0, 0x9d, 1);
1038                } else {
1039                        spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1040                        for (i = 0; i < 6; i++)
1041                                info[i] = reg_r_1(gspca_dev, i);
1042                        PDEBUG(D_STREAM,
1043                                "Read info: %d %d %d %d %d %d."
1044                                " Should be 1,0,2,2,0,0",
1045                                info[0], info[1], info[2],
1046                                info[3], info[4], info[5]);
1047                        spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1048                        spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1049                }
1050                spca504B_SetSizeType(gspca_dev);
1051                reg_w_riv(dev, 0x00, 0x270c, 0x05);     /* L92 sno1t.txt */
1052                reg_w_riv(dev, 0x00, 0x2310, 0x05);
1053                break;
1054        case BRIDGE_SPCA504C:
1055                if (sd->subtype == LogitechClickSmart420) {
1056                        write_vector(gspca_dev,
1057                                spca504A_clicksmart420_init_data,
1058                                ARRAY_SIZE(spca504A_clicksmart420_init_data));
1059                } else {
1060                        write_vector(gspca_dev, spca504_pccam600_init_data,
1061                                ARRAY_SIZE(spca504_pccam600_init_data));
1062                }
1063                enable = (sd->autogain ? 0x04 : 0x01);
1064                reg_w_riv(dev, 0x0c, 0x0000, enable);   /* auto exposure */
1065                reg_w_riv(dev, 0xb0, 0x0000, enable);   /* auto whiteness */
1066
1067                /* set default exposure compensation and whiteness balance */
1068                reg_w_riv(dev, 0x30, 0x0001, 800);      /* ~ 20 fps */
1069                reg_w_riv(dev, 0x30, 0x0002, 1600);
1070                spca504B_SetSizeType(gspca_dev);
1071                break;
1072        }
1073        init_ctl_reg(gspca_dev);
1074        return 0;
1075}
1076
1077static void sd_stopN(struct gspca_dev *gspca_dev)
1078{
1079        struct sd *sd = (struct sd *) gspca_dev;
1080        struct usb_device *dev = gspca_dev->dev;
1081
1082        switch (sd->bridge) {
1083        default:
1084/*      case BRIDGE_SPCA533: */
1085/*      case BRIDGE_SPCA536: */
1086/*      case BRIDGE_SPCA504B: */
1087                reg_w_riv(dev, 0x31, 0, 0);
1088                spca504B_WaitCmdStatus(gspca_dev);
1089                spca504B_PollingDataReady(gspca_dev);
1090                break;
1091        case BRIDGE_SPCA504:
1092        case BRIDGE_SPCA504C:
1093                reg_w_riv(dev, 0x00, 0x2000, 0x0000);
1094
1095                if (sd->subtype == AiptekMiniPenCam13) {
1096                        /* spca504a aiptek */
1097/*                      spca504A_acknowledged_command(gspca_dev, 0x08,
1098                                                         6, 0, 0x86, 1); */
1099                        spca504A_acknowledged_command(gspca_dev, 0x24,
1100                                                        0x00, 0x00, 0x9d, 1);
1101                        spca504A_acknowledged_command(gspca_dev, 0x01,
1102                                                        0x0f, 0x00, 0xff, 1);
1103                } else {
1104                        spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1105                        reg_w_riv(dev, 0x01, 0x000f, 0x0000);
1106                }
1107                break;
1108        }
1109}
1110
1111static void sd_stop0(struct gspca_dev *gspca_dev)
1112{
1113        struct sd *sd = (struct sd *) gspca_dev;
1114
1115        kfree(sd->jpeg_hdr);
1116}
1117
1118static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1119                        struct gspca_frame *frame,      /* target */
1120                        u8 *data,                       /* isoc packet */
1121                        int len)                        /* iso packet length */
1122{
1123        struct sd *sd = (struct sd *) gspca_dev;
1124        int i, sof = 0;
1125        static u8 ffd9[] = {0xff, 0xd9};
1126
1127/* frames are jpeg 4.1.1 without 0xff escape */
1128        switch (sd->bridge) {
1129        case BRIDGE_SPCA533:
1130                if (data[0] == 0xff) {
1131                        if (data[1] != 0x01) {  /* drop packet */
1132/*                              gspca_dev->last_packet_type = DISCARD_PACKET; */
1133                                return;
1134                        }
1135                        sof = 1;
1136                        data += SPCA533_OFFSET_DATA;
1137                        len -= SPCA533_OFFSET_DATA;
1138                } else {
1139                        data += 1;
1140                        len -= 1;
1141                }
1142                break;
1143        case BRIDGE_SPCA536:
1144                if (data[0] == 0xff) {
1145                        sof = 1;
1146                        data += SPCA536_OFFSET_DATA;
1147                        len -= SPCA536_OFFSET_DATA;
1148                } else {
1149                        data += 2;
1150                        len -= 2;
1151                }
1152                break;
1153        default:
1154/*      case BRIDGE_SPCA504: */
1155/*      case BRIDGE_SPCA504B: */
1156                switch (data[0]) {
1157                case 0xfe:                      /* start of frame */
1158                        sof = 1;
1159                        data += SPCA50X_OFFSET_DATA;
1160                        len -= SPCA50X_OFFSET_DATA;
1161                        break;
1162                case 0xff:                      /* drop packet */
1163/*                      gspca_dev->last_packet_type = DISCARD_PACKET; */
1164                        return;
1165                default:
1166                        data += 1;
1167                        len -= 1;
1168                        break;
1169                }
1170                break;
1171        case BRIDGE_SPCA504C:
1172                switch (data[0]) {
1173                case 0xfe:                      /* start of frame */
1174                        sof = 1;
1175                        data += SPCA504_PCCAM600_OFFSET_DATA;
1176                        len -= SPCA504_PCCAM600_OFFSET_DATA;
1177                        break;
1178                case 0xff:                      /* drop packet */
1179/*                      gspca_dev->last_packet_type = DISCARD_PACKET; */
1180                        return;
1181                default:
1182                        data += 1;
1183                        len -= 1;
1184                        break;
1185                }
1186                break;
1187        }
1188        if (sof) {              /* start of frame */
1189                frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1190                                        ffd9, 2);
1191
1192                /* put the JPEG header in the new frame */
1193                gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
1194                        sd->jpeg_hdr, JPEG_HDR_SZ);
1195        }
1196
1197        /* add 0x00 after 0xff */
1198        i = 0;
1199        do {
1200                if (data[i] == 0xff) {
1201                        gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1202                                        data, i + 1);
1203                        len -= i;
1204                        data += i;
1205                        *data = 0x00;
1206                        i = 0;
1207                }
1208                i++;
1209        } while (i < len);
1210        gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1211}
1212
1213static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1214{
1215        struct sd *sd = (struct sd *) gspca_dev;
1216
1217        sd->brightness = val;
1218        if (gspca_dev->streaming)
1219                setbrightness(gspca_dev);
1220        return 0;
1221}
1222
1223static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1224{
1225        struct sd *sd = (struct sd *) gspca_dev;
1226
1227        *val = sd->brightness;
1228        return 0;
1229}
1230
1231static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1232{
1233        struct sd *sd = (struct sd *) gspca_dev;
1234
1235        sd->contrast = val;
1236        if (gspca_dev->streaming)
1237                setcontrast(gspca_dev);
1238        return 0;
1239}
1240
1241static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1242{
1243        struct sd *sd = (struct sd *) gspca_dev;
1244
1245        *val = sd->contrast;
1246        return 0;
1247}
1248
1249static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1250{
1251        struct sd *sd = (struct sd *) gspca_dev;
1252
1253        sd->colors = val;
1254        if (gspca_dev->streaming)
1255                setcolors(gspca_dev);
1256        return 0;
1257}
1258
1259static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1260{
1261        struct sd *sd = (struct sd *) gspca_dev;
1262
1263        *val = sd->colors;
1264        return 0;
1265}
1266
1267static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1268{
1269        struct sd *sd = (struct sd *) gspca_dev;
1270
1271        sd->autogain = val;
1272        return 0;
1273}
1274
1275static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1276{
1277        struct sd *sd = (struct sd *) gspca_dev;
1278
1279        *val = sd->autogain;
1280        return 0;
1281}
1282
1283static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1284                        struct v4l2_jpegcompression *jcomp)
1285{
1286        struct sd *sd = (struct sd *) gspca_dev;
1287
1288        if (jcomp->quality < QUALITY_MIN)
1289                sd->quality = QUALITY_MIN;
1290        else if (jcomp->quality > QUALITY_MAX)
1291                sd->quality = QUALITY_MAX;
1292        else
1293                sd->quality = jcomp->quality;
1294        if (gspca_dev->streaming)
1295                jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1296        return 0;
1297}
1298
1299static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1300                        struct v4l2_jpegcompression *jcomp)
1301{
1302        struct sd *sd = (struct sd *) gspca_dev;
1303
1304        memset(jcomp, 0, sizeof *jcomp);
1305        jcomp->quality = sd->quality;
1306        jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1307                        | V4L2_JPEG_MARKER_DQT;
1308        return 0;
1309}
1310
1311/* sub-driver description */
1312static const struct sd_desc sd_desc = {
1313        .name = MODULE_NAME,
1314        .ctrls = sd_ctrls,
1315        .nctrls = ARRAY_SIZE(sd_ctrls),
1316        .config = sd_config,
1317        .init = sd_init,
1318        .start = sd_start,
1319        .stopN = sd_stopN,
1320        .stop0 = sd_stop0,
1321        .pkt_scan = sd_pkt_scan,
1322        .get_jcomp = sd_get_jcomp,
1323        .set_jcomp = sd_set_jcomp,
1324};
1325
1326/* -- module initialisation -- */
1327#define BS(bridge, subtype) \
1328        .driver_info = (BRIDGE_ ## bridge << 8) \
1329                        | (subtype)
1330static const __devinitdata struct usb_device_id device_table[] = {
1331        {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1332        {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1333        {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1334        {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1335        {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1336        {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1337        {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1338        {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1339        {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1340        {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1341        {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1342        {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1343        {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1344        {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1345        {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1346        {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1347        {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1348        {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1349        {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1350        {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1351        {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1352        {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1353        {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1354        {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1355        {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1356        {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1357        {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1358        {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1359        {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1360        {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1361        {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1362        {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1363        {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1364        {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1365        {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1366        {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1367        {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1368        {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1369        {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1370        {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1371        {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1372        {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1373        {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1374        {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1375        {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1376        {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1377        {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1378        {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1379        {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1380        {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1381        {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1382        {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1383        {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1384        {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1385        {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1386        {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1387        {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1388        {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1389        {}
1390};
1391MODULE_DEVICE_TABLE(usb, device_table);
1392
1393/* -- device connect -- */
1394static int sd_probe(struct usb_interface *intf,
1395                        const struct usb_device_id *id)
1396{
1397        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1398                                THIS_MODULE);
1399}
1400
1401static struct usb_driver sd_driver = {
1402        .name = MODULE_NAME,
1403        .id_table = device_table,
1404        .probe = sd_probe,
1405        .disconnect = gspca_disconnect,
1406#ifdef CONFIG_PM
1407        .suspend = gspca_suspend,
1408        .resume = gspca_resume,
1409#endif
1410};
1411
1412/* -- module insert / remove -- */
1413static int __init sd_mod_init(void)
1414{
1415        int ret;
1416        ret = usb_register(&sd_driver);
1417        if (ret < 0)
1418                return ret;
1419        PDEBUG(D_PROBE, "registered");
1420        return 0;
1421}
1422static void __exit sd_mod_exit(void)
1423{
1424        usb_deregister(&sd_driver);
1425        PDEBUG(D_PROBE, "deregistered");
1426}
1427
1428module_init(sd_mod_init);
1429module_exit(sd_mod_exit);
1430