linux/drivers/media/video/gspca/t613.c History
<<
>>
Prefs
   1/*
   2 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; either version 2 of the License, or
   7 * any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the Free Software
  16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 *
  18 *Notes: * t613  + tas5130A
  19 *      * Focus to light do not balance well as in win.
  20 *        Quality in win is not good, but its kinda better.
  21 *       * Fix some "extraneous bytes", most of apps will show the image anyway
  22 *       * Gamma table, is there, but its really doing something?
  23 *       * 7~8 Fps, its ok, max on win its 10.
  24 *                      Costantino Leandro
  25 */
  26
  27#define MODULE_NAME "t613"
  28
  29#include "gspca.h"
  30
  31#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
  32
  33MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
  34MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
  35MODULE_LICENSE("GPL");
  36
  37struct sd {
  38        struct gspca_dev gspca_dev;     /* !! must be the first item */
  39
  40        u8 brightness;
  41        u8 contrast;
  42        u8 colors;
  43        u8 autogain;
  44        u8 gamma;
  45        u8 sharpness;
  46        u8 freq;
  47        u8 whitebalance;
  48        u8 mirror;
  49        u8 effect;
  50
  51        u8 sensor;
  52#define SENSOR_OM6802 0
  53#define SENSOR_OTHER 1
  54#define SENSOR_TAS5130A 2
  55};
  56
  57/* V4L2 controls supported by the driver */
  58static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
  59static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
  60static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
  61static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
  62static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
  63static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
  64static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
  65static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
  66static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
  67static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
  68static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
  69static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
  70static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
  71static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
  72static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
  73static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
  74static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
  75static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
  76static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
  77static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
  78static int sd_querymenu(struct gspca_dev *gspca_dev,
  79                        struct v4l2_querymenu *menu);
  80
  81static struct ctrl sd_ctrls[] = {
  82        {
  83         {
  84          .id = V4L2_CID_BRIGHTNESS,
  85          .type = V4L2_CTRL_TYPE_INTEGER,
  86          .name = "Brightness",
  87          .minimum = 0,
  88          .maximum = 14,
  89          .step = 1,
  90#define BRIGHTNESS_DEF 8
  91          .default_value = BRIGHTNESS_DEF,
  92          },
  93         .set = sd_setbrightness,
  94         .get = sd_getbrightness,
  95         },
  96        {
  97         {
  98          .id = V4L2_CID_CONTRAST,
  99          .type = V4L2_CTRL_TYPE_INTEGER,
 100          .name = "Contrast",
 101          .minimum = 0,
 102          .maximum = 0x0d,
 103          .step = 1,
 104#define CONTRAST_DEF 0x07
 105          .default_value = CONTRAST_DEF,
 106          },
 107         .set = sd_setcontrast,
 108         .get = sd_getcontrast,
 109         },
 110        {
 111         {
 112          .id = V4L2_CID_SATURATION,
 113          .type = V4L2_CTRL_TYPE_INTEGER,
 114          .name = "Color",
 115          .minimum = 0,
 116          .maximum = 0x0f,
 117          .step = 1,
 118#define COLORS_DEF 0x05
 119          .default_value = COLORS_DEF,
 120          },
 121         .set = sd_setcolors,
 122         .get = sd_getcolors,
 123         },
 124#define GAMMA_MAX 16
 125#define GAMMA_DEF 10
 126        {
 127         {
 128          .id = V4L2_CID_GAMMA, /* (gamma on win) */
 129          .type = V4L2_CTRL_TYPE_INTEGER,
 130          .name = "Gamma",
 131          .minimum = 0,
 132          .maximum = GAMMA_MAX - 1,
 133          .step = 1,
 134          .default_value = GAMMA_DEF,
 135          },
 136         .set = sd_setgamma,
 137         .get = sd_getgamma,
 138         },
 139        {
 140         {
 141          .id = V4L2_CID_GAIN,  /* here, i activate only the lowlight,
 142                                 * some apps dont bring up the
 143                                 * backligth_compensation control) */
 144          .type = V4L2_CTRL_TYPE_INTEGER,
 145          .name = "Low Light",
 146          .minimum = 0,
 147          .maximum = 1,
 148          .step = 1,
 149#define AUTOGAIN_DEF 0x01
 150          .default_value = AUTOGAIN_DEF,
 151          },
 152         .set = sd_setlowlight,
 153         .get = sd_getlowlight,
 154         },
 155        {
 156         {
 157          .id = V4L2_CID_HFLIP,
 158          .type = V4L2_CTRL_TYPE_BOOLEAN,
 159          .name = "Mirror Image",
 160          .minimum = 0,
 161          .maximum = 1,
 162          .step = 1,
 163#define MIRROR_DEF 0
 164          .default_value = MIRROR_DEF,
 165          },
 166         .set = sd_setflip,
 167         .get = sd_getflip
 168        },
 169        {
 170         {
 171          .id = V4L2_CID_POWER_LINE_FREQUENCY,
 172          .type = V4L2_CTRL_TYPE_MENU,
 173          .name = "Light Frequency Filter",
 174          .minimum = 1,         /* 1 -> 0x50, 2->0x60 */
 175          .maximum = 2,
 176          .step = 1,
 177#define FREQ_DEF 1
 178          .default_value = FREQ_DEF,
 179          },
 180         .set = sd_setfreq,
 181         .get = sd_getfreq},
 182
 183        {
 184         {
 185          .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
 186          .type = V4L2_CTRL_TYPE_INTEGER,
 187          .name = "White Balance",
 188          .minimum = 0,
 189          .maximum = 1,
 190          .step = 1,
 191#define WHITE_BALANCE_DEF 0
 192          .default_value = WHITE_BALANCE_DEF,
 193          },
 194         .set = sd_setwhitebalance,
 195         .get = sd_getwhitebalance
 196        },
 197        {
 198         {
 199          .id = V4L2_CID_SHARPNESS,
 200          .type = V4L2_CTRL_TYPE_INTEGER,
 201          .name = "Sharpness",
 202          .minimum = 0,
 203          .maximum = 15,
 204          .step = 1,
 205#define SHARPNESS_DEF 0x06
 206          .default_value = SHARPNESS_DEF,
 207          },
 208         .set = sd_setsharpness,
 209         .get = sd_getsharpness,
 210         },
 211        {
 212         {
 213          .id = V4L2_CID_EFFECTS,
 214          .type = V4L2_CTRL_TYPE_MENU,
 215          .name = "Webcam Effects",
 216          .minimum = 0,
 217          .maximum = 4,
 218          .step = 1,
 219#define EFFECTS_DEF 0
 220          .default_value = EFFECTS_DEF,
 221          },
 222         .set = sd_seteffect,
 223         .get = sd_geteffect
 224        },
 225};
 226
 227static char *effects_control[] = {
 228        "Normal",
 229        "Emboss",               /* disabled */
 230        "Monochrome",
 231        "Sepia",
 232        "Sketch",
 233        "Sun Effect",           /* disabled */
 234        "Negative",
 235};
 236
 237static const struct v4l2_pix_format vga_mode_t16[] = {
 238        {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 239                .bytesperline = 160,
 240                .sizeimage = 160 * 120 * 4 / 8 + 590,
 241                .colorspace = V4L2_COLORSPACE_JPEG,
 242                .priv = 4},
 243        {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 244                .bytesperline = 176,
 245                .sizeimage = 176 * 144 * 3 / 8 + 590,
 246                .colorspace = V4L2_COLORSPACE_JPEG,
 247                .priv = 3},
 248        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 249                .bytesperline = 320,
 250                .sizeimage = 320 * 240 * 3 / 8 + 590,
 251                .colorspace = V4L2_COLORSPACE_JPEG,
 252                .priv = 2},
 253        {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 254                .bytesperline = 352,
 255                .sizeimage = 352 * 288 * 3 / 8 + 590,
 256                .colorspace = V4L2_COLORSPACE_JPEG,
 257                .priv = 1},
 258        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 259                .bytesperline = 640,
 260                .sizeimage = 640 * 480 * 3 / 8 + 590,
 261                .colorspace = V4L2_COLORSPACE_JPEG,
 262                .priv = 0},
 263};
 264
 265/* sensor specific data */
 266struct additional_sensor_data {
 267        const u8 n3[6];
 268        const u8 *n4, n4sz;
 269        const u8 reg80, reg8e;
 270        const u8 nset8[6];
 271        const u8 data1[10];
 272        const u8 data2[9];
 273        const u8 data3[9];
 274        const u8 data4[4];
 275        const u8 data5[6];
 276        const u8 stream[4];
 277};
 278
 279static const u8 n4_om6802[] = {
 280        0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
 281        0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
 282        0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
 283        0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
 284        0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
 285        0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
 286        0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
 287        0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
 288        0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
 289};
 290static const u8 n4_other[] = {
 291        0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
 292        0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
 293        0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
 294        0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
 295        0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
 296        0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
 297        0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
 298        0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
 299};
 300static const u8 n4_tas5130a[] = {
 301        0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
 302        0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
 303        0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
 304        0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
 305        0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
 306        0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
 307        0xc6, 0xda
 308};
 309
 310static const struct additional_sensor_data sensor_data[] = {
 311    {                           /* 0: OM6802 */
 312        .n3 =
 313                {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
 314        .n4 = n4_om6802,
 315        .n4sz = sizeof n4_om6802,
 316        .reg80 = 0x3c,
 317        .reg8e = 0x33,
 318        .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
 319        .data1 =
 320                {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
 321                 0xb3, 0xfc},
 322        .data2 =
 323                {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
 324                 0xff},
 325        .data3 =
 326                {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
 327                 0xff},
 328        .data4 =        /*Freq (50/60Hz). Splitted for test purpose */
 329                {0x66, 0xca, 0xa8, 0xf0},
 330        .data5 =        /* this could be removed later */
 331                {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
 332        .stream =
 333                {0x0b, 0x04, 0x0a, 0x78},
 334    },
 335    {                           /* 1: OTHER */
 336        .n3 =
 337                {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
 338        .n4 = n4_other,
 339        .n4sz = sizeof n4_other,
 340        .reg80 = 0xac,
 341        .reg8e = 0xb8,
 342        .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
 343        .data1 =
 344                {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
 345                 0xe8, 0xfc},
 346        .data2 =
 347                {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
 348                 0xd9},
 349        .data3 =
 350                {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
 351                 0xd9},
 352        .data4 =
 353                {0x66, 0x00, 0xa8, 0xa8},
 354        .data5 =
 355                {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
 356        .stream =
 357                {0x0b, 0x04, 0x0a, 0x00},
 358    },
 359    {                           /* 2: TAS5130A */
 360        .n3 =
 361                {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
 362        .n4 = n4_tas5130a,
 363        .n4sz = sizeof n4_tas5130a,
 364        .reg80 = 0x3c,
 365        .reg8e = 0xb4,
 366        .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
 367        .data1 =
 368                {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
 369                 0xc8, 0xfc},
 370        .data2 =
 371                {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
 372                 0xe0},
 373        .data3 =
 374                {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
 375                 0xe0},
 376        .data4 =        /* Freq (50/60Hz). Splitted for test purpose */
 377                {0x66, 0x00, 0xa8, 0xe8},
 378        .data5 =
 379                {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
 380        .stream =
 381                {0x0b, 0x04, 0x0a, 0x40},
 382    },
 383};
 384
 385#define MAX_EFFECTS 7
 386/* easily done by soft, this table could be removed,
 387 * i keep it here just in case */
 388static const u8 effects_table[MAX_EFFECTS][6] = {
 389        {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00},   /* Normal */
 390        {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04},   /* Repujar */
 391        {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20},   /* Monochrome */
 392        {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80},   /* Sepia */
 393        {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02},   /* Croquis */
 394        {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10},   /* Sun Effect */
 395        {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40},   /* Negative */
 396};
 397
 398static const u8 gamma_table[GAMMA_MAX][17] = {
 399        {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9,        /* 0 */
 400         0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
 401         0xff},
 402        {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad,        /* 1 */
 403         0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
 404         0xff},
 405        {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6,        /* 2 */
 406         0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
 407         0xff},
 408        {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e,        /* 3 */
 409         0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
 410         0xff},
 411        {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95,        /* 4 */
 412         0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
 413         0xff},
 414        {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87,        /* 5 */
 415         0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
 416         0xff},
 417        {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67,        /* 6 */
 418         0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
 419         0xff},
 420        {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70,        /* 7 */
 421         0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
 422         0xff},
 423        {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79,        /* 8 */
 424         0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
 425         0xff},
 426        {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84,        /* 9 */
 427         0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
 428         0xff},
 429        {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e,        /* 10 */
 430         0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
 431         0xff},
 432        {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b,        /* 11 */
 433         0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
 434         0xff},
 435        {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8,        /* 12 */
 436         0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
 437         0xff},
 438        {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7,        /* 13 */
 439         0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
 440         0xff},
 441        {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6,        /* 14 */
 442         0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
 443         0xff},
 444        {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8,        /* 15 */
 445         0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
 446         0xff}
 447};
 448
 449static const u8 tas5130a_sensor_init[][8] = {
 450        {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
 451        {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
 452        {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
 453};
 454
 455static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
 456
 457/* read 1 byte */
 458static u8 reg_r(struct gspca_dev *gspca_dev,
 459                   u16 index)
 460{
 461        usb_control_msg(gspca_dev->dev,
 462                        usb_rcvctrlpipe(gspca_dev->dev, 0),
 463                        0,              /* request */
 464                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 465                        0,              /* value */
 466                        index,
 467                        gspca_dev->usb_buf, 1, 500);
 468        return gspca_dev->usb_buf[0];
 469}
 470
 471static void reg_w(struct gspca_dev *gspca_dev,
 472                  u16 index)
 473{
 474        usb_control_msg(gspca_dev->dev,
 475                        usb_sndctrlpipe(gspca_dev->dev, 0),
 476                        0,
 477                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 478                        0, index,
 479                        NULL, 0, 500);
 480}
 481
 482static void reg_w_buf(struct gspca_dev *gspca_dev,
 483                  const u8 *buffer, u16 len)
 484{
 485        if (len <= USB_BUF_SZ) {
 486                memcpy(gspca_dev->usb_buf, buffer, len);
 487                usb_control_msg(gspca_dev->dev,
 488                                usb_sndctrlpipe(gspca_dev->dev, 0),
 489                                0,
 490                           USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 491                                0x01, 0,
 492                                gspca_dev->usb_buf, len, 500);
 493        } else {
 494                u8 *tmpbuf;
 495
 496                tmpbuf = kmalloc(len, GFP_KERNEL);
 497                memcpy(tmpbuf, buffer, len);
 498                usb_control_msg(gspca_dev->dev,
 499                                usb_sndctrlpipe(gspca_dev->dev, 0),
 500                                0,
 501                           USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 502                                0x01, 0,
 503                                tmpbuf, len, 500);
 504                kfree(tmpbuf);
 505        }
 506}
 507
 508/* write values to consecutive registers */
 509static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
 510                        u8 reg,
 511                        const u8 *buffer, u16 len)
 512{
 513        int i;
 514        u8 *p, *tmpbuf;
 515
 516        if (len * 2 <= USB_BUF_SZ)
 517                p = tmpbuf = gspca_dev->usb_buf;
 518        else
 519                p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
 520        i = len;
 521        while (--i >= 0) {
 522                *p++ = reg++;
 523                *p++ = *buffer++;
 524        }
 525        usb_control_msg(gspca_dev->dev,
 526                        usb_sndctrlpipe(gspca_dev->dev, 0),
 527                        0,
 528                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 529                        0x01, 0,
 530                        tmpbuf, len * 2, 500);
 531        if (len * 2 > USB_BUF_SZ)
 532                kfree(tmpbuf);
 533}
 534
 535/* Reported as OM6802*/
 536static void om6802_sensor_init(struct gspca_dev *gspca_dev)
 537{
 538        int i;
 539        const u8 *p;
 540        u8 byte;
 541        u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
 542        static const u8 sensor_init[] = {
 543                0xdf, 0x6d,
 544                0xdd, 0x18,
 545                0x5a, 0xe0,
 546                0x5c, 0x07,
 547                0x5d, 0xb0,
 548                0x5e, 0x1e,
 549                0x60, 0x71,
 550                0xef, 0x00,
 551                0xe9, 0x00,
 552                0xea, 0x00,
 553                0x90, 0x24,
 554                0x91, 0xb2,
 555                0x82, 0x32,
 556                0xfd, 0x41,
 557                0x00                    /* table end */
 558        };
 559
 560        reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
 561        msleep(100);
 562        i = 4;
 563        while (--i > 0) {
 564                byte = reg_r(gspca_dev, 0x0060);
 565                if (!(byte & 0x01))
 566                        break;
 567                msleep(100);
 568        }
 569        byte = reg_r(gspca_dev, 0x0063);
 570        if (byte != 0x17) {
 571                err("Bad sensor reset %02x", byte);
 572                /* continue? */
 573        }
 574
 575        p = sensor_init;
 576        while (*p != 0) {
 577                val[1] = *p++;
 578                val[3] = *p++;
 579                if (*p == 0)
 580                        reg_w(gspca_dev, 0x3c80);
 581                reg_w_buf(gspca_dev, val, sizeof val);
 582                i = 4;
 583                while (--i >= 0) {
 584                        msleep(15);
 585                        byte = reg_r(gspca_dev, 0x60);
 586                        if (!(byte & 0x01))
 587                                break;
 588                }
 589        }
 590        msleep(15);
 591        reg_w(gspca_dev, 0x3c80);
 592}
 593
 594/* this function is called at probe time */
 595static int sd_config(struct gspca_dev *gspca_dev,
 596                     const struct usb_device_id *id)
 597{
 598        struct sd *sd = (struct sd *) gspca_dev;
 599        struct cam *cam;
 600
 601        cam = &gspca_dev->cam;
 602
 603        cam->cam_mode = vga_mode_t16;
 604        cam->nmodes = ARRAY_SIZE(vga_mode_t16);
 605
 606        sd->brightness = BRIGHTNESS_DEF;
 607        sd->contrast = CONTRAST_DEF;
 608        sd->colors = COLORS_DEF;
 609        sd->gamma = GAMMA_DEF;
 610        sd->autogain = AUTOGAIN_DEF;
 611        sd->mirror = MIRROR_DEF;
 612        sd->freq = FREQ_DEF;
 613        sd->whitebalance = WHITE_BALANCE_DEF;
 614        sd->sharpness = SHARPNESS_DEF;
 615        sd->effect = EFFECTS_DEF;
 616        return 0;
 617}
 618
 619static void setbrightness(struct gspca_dev *gspca_dev)
 620{
 621        struct sd *sd = (struct sd *) gspca_dev;
 622        unsigned int brightness;
 623        u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
 624
 625        brightness = sd->brightness;
 626        if (brightness < 7) {
 627                set6[1] = 0x26;
 628                set6[3] = 0x70 - brightness * 0x10;
 629        } else {
 630                set6[3] = 0x00 + ((brightness - 7) * 0x10);
 631        }
 632
 633        reg_w_buf(gspca_dev, set6, sizeof set6);
 634}
 635
 636static void setcontrast(struct gspca_dev *gspca_dev)
 637{
 638        struct sd *sd = (struct sd *) gspca_dev;
 639        unsigned int contrast = sd->contrast;
 640        u16 reg_to_write;
 641
 642        if (contrast < 7)
 643                reg_to_write = 0x8ea9 - contrast * 0x200;
 644        else
 645                reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
 646
 647        reg_w(gspca_dev, reg_to_write);
 648}
 649
 650static void setcolors(struct gspca_dev *gspca_dev)
 651{
 652        struct sd *sd = (struct sd *) gspca_dev;
 653        u16 reg_to_write;
 654
 655        reg_to_write = 0x80bb + sd->colors * 0x100;     /* was 0xc0 */
 656        reg_w(gspca_dev, reg_to_write);
 657}
 658
 659static void setgamma(struct gspca_dev *gspca_dev)
 660{
 661        struct sd *sd = (struct sd *) gspca_dev;
 662
 663        PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
 664        reg_w_ixbuf(gspca_dev, 0x90,
 665                gamma_table[sd->gamma], sizeof gamma_table[0]);
 666}
 667
 668static void setwhitebalance(struct gspca_dev *gspca_dev)
 669{
 670        struct sd *sd = (struct sd *) gspca_dev;
 671
 672        u8 white_balance[8] =
 673                {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
 674
 675        if (sd->whitebalance)
 676                white_balance[7] = 0x3c;
 677
 678        reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
 679}
 680
 681static void setsharpness(struct gspca_dev *gspca_dev)
 682{
 683        struct sd *sd = (struct sd *) gspca_dev;
 684        u16 reg_to_write;
 685
 686        reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
 687
 688        reg_w(gspca_dev, reg_to_write);
 689}
 690
 691/* this function is called at probe and resume time */
 692static int sd_init(struct gspca_dev *gspca_dev)
 693{
 694        /* some of this registers are not really neded, because
 695         * they are overriden by setbrigthness, setcontrast, etc,
 696         * but wont hurt anyway, and can help someone with similar webcam
 697         * to see the initial parameters.*/
 698        struct sd *sd = (struct sd *) gspca_dev;
 699        const struct additional_sensor_data *sensor;
 700        int i;
 701        u16 sensor_id;
 702        u8 test_byte = 0;
 703
 704        static const u8 read_indexs[] =
 705                { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
 706                  0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
 707        static const u8 n1[] =
 708                        {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
 709        static const u8 n2[] =
 710                        {0x08, 0x00};
 711
 712        sensor_id = (reg_r(gspca_dev, 0x06) << 8)
 713                        | reg_r(gspca_dev, 0x07);
 714        switch (sensor_id & 0xff0f) {
 715        case 0x0801:
 716                PDEBUG(D_PROBE, "sensor tas5130a");
 717                sd->sensor = SENSOR_TAS5130A;
 718                break;
 719        case 0x0803:
 720                PDEBUG(D_PROBE, "sensor 'other'");
 721                sd->sensor = SENSOR_OTHER;
 722                break;
 723        case 0x0807:
 724                PDEBUG(D_PROBE, "sensor om6802");
 725                sd->sensor = SENSOR_OM6802;
 726                break;
 727        default:
 728                PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
 729                return -EINVAL;
 730        }
 731
 732        if (sd->sensor == SENSOR_OM6802) {
 733                reg_w_buf(gspca_dev, n1, sizeof n1);
 734                i = 5;
 735                while (--i >= 0) {
 736                        reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
 737                        test_byte = reg_r(gspca_dev, 0x0063);
 738                        msleep(100);
 739                        if (test_byte == 0x17)
 740                                break;          /* OK */
 741                }
 742                if (i < 0) {
 743                        err("Bad sensor reset %02x", test_byte);
 744                        return -EIO;
 745                }
 746                reg_w_buf(gspca_dev, n2, sizeof n2);
 747        }
 748
 749        i = 0;
 750        while (read_indexs[i] != 0x00) {
 751                test_byte = reg_r(gspca_dev, read_indexs[i]);
 752                PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
 753                       test_byte);
 754                i++;
 755        }
 756
 757        sensor = &sensor_data[sd->sensor];
 758        reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
 759        reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
 760
 761        reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
 762        reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
 763        reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
 764
 765        reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
 766        reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
 767        reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
 768
 769        setbrightness(gspca_dev);
 770        setcontrast(gspca_dev);
 771        setgamma(gspca_dev);
 772        setcolors(gspca_dev);
 773        setsharpness(gspca_dev);
 774        setwhitebalance(gspca_dev);
 775
 776        reg_w(gspca_dev, 0x2087);       /* tied to white balance? */
 777        reg_w(gspca_dev, 0x2088);
 778        reg_w(gspca_dev, 0x2089);
 779
 780        reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
 781        reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
 782        reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
 783        reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
 784
 785        reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
 786        reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
 787        reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
 788
 789        return 0;
 790}
 791
 792static void setflip(struct gspca_dev *gspca_dev)
 793{
 794        struct sd *sd = (struct sd *) gspca_dev;
 795        u8 flipcmd[8] =
 796                {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
 797
 798        if (sd->mirror)
 799                flipcmd[3] = 0x01;
 800
 801        reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
 802}
 803
 804static void seteffect(struct gspca_dev *gspca_dev)
 805{
 806        struct sd *sd = (struct sd *) gspca_dev;
 807
 808        reg_w_buf(gspca_dev, effects_table[sd->effect],
 809                                sizeof effects_table[0]);
 810        if (sd->effect == 1 || sd->effect == 5) {
 811                PDEBUG(D_CONF,
 812                       "This effect have been disabled for webcam \"safety\"");
 813                return;
 814        }
 815
 816        if (sd->effect == 1 || sd->effect == 4)
 817                reg_w(gspca_dev, 0x4aa6);
 818        else
 819                reg_w(gspca_dev, 0xfaa6);
 820}
 821
 822static void setlightfreq(struct gspca_dev *gspca_dev)
 823{
 824        struct sd *sd = (struct sd *) gspca_dev;
 825        u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
 826
 827        if (sd->freq == 2)      /* 60hz */
 828                freq[1] = 0x00;
 829
 830        reg_w_buf(gspca_dev, freq, sizeof freq);
 831}
 832
 833/* Is this really needed?
 834 * i added some module parameters for test with some users */
 835static void poll_sensor(struct gspca_dev *gspca_dev)
 836{
 837        static const u8 poll1[] =
 838                {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
 839                 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
 840                 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
 841                 0x60, 0x14};
 842        static const u8 poll2[] =
 843                {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
 844                 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
 845        static const u8 poll3[] =
 846                {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
 847        static const u8 poll4[] =
 848                {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
 849                 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
 850                 0xc2, 0x80, 0xc3, 0x10};
 851
 852        PDEBUG(D_STREAM, "[Sensor requires polling]");
 853        reg_w_buf(gspca_dev, poll1, sizeof poll1);
 854        reg_w_buf(gspca_dev, poll2, sizeof poll2);
 855        reg_w_buf(gspca_dev, poll3, sizeof poll3);
 856        reg_w_buf(gspca_dev, poll4, sizeof poll4);
 857}
 858
 859static int sd_start(struct gspca_dev *gspca_dev)
 860{
 861        struct sd *sd = (struct sd *) gspca_dev;
 862        const struct additional_sensor_data *sensor;
 863        int i, mode;
 864        u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
 865        static const u8 t3[] =
 866                { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
 867
 868        mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 869        switch (mode) {
 870        case 0:         /* 640x480 (0x00) */
 871                break;
 872        case 1:         /* 352x288 */
 873                t2[1] = 0x40;
 874                break;
 875        case 2:         /* 320x240 */
 876                t2[1] = 0x10;
 877                break;
 878        case 3:         /* 176x144 */
 879                t2[1] = 0x50;
 880                break;
 881        default:
 882/*      case 4:          * 160x120 */
 883                t2[1] = 0x20;
 884                break;
 885        }
 886
 887        switch (sd->sensor) {
 888        case SENSOR_OM6802:
 889                om6802_sensor_init(gspca_dev);
 890                break;
 891        case SENSOR_OTHER:
 892                break;
 893        default:
 894/*      case SENSOR_TAS5130A: */
 895                i = 0;
 896                for (;;) {
 897                        reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
 898                                         sizeof tas5130a_sensor_init[0]);
 899                        if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
 900                                break;
 901                        i++;
 902                }
 903                reg_w(gspca_dev, 0x3c80);
 904                /* just in case and to keep sync with logs (for mine) */
 905                reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
 906                                 sizeof tas5130a_sensor_init[0]);
 907                reg_w(gspca_dev, 0x3c80);
 908                break;
 909        }
 910        sensor = &sensor_data[sd->sensor];
 911        reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
 912        reg_r(gspca_dev, 0x0012);
 913        reg_w_buf(gspca_dev, t2, sizeof t2);
 914        reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
 915        reg_w(gspca_dev, 0x0013);
 916        msleep(15);
 917        reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
 918        reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
 919
 920        if (sd->sensor == SENSOR_OM6802)
 921                poll_sensor(gspca_dev);
 922
 923        return 0;
 924}
 925
 926static void sd_stopN(struct gspca_dev *gspca_dev)
 927{
 928        struct sd *sd = (struct sd *) gspca_dev;
 929
 930        reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
 931                        sizeof sensor_data[sd->sensor].stream);
 932        reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
 933                        sizeof sensor_data[sd->sensor].stream);
 934        if (sd->sensor == SENSOR_OM6802) {
 935                msleep(20);
 936                reg_w(gspca_dev, 0x0309);
 937        }
 938}
 939
 940static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 941                        struct gspca_frame *frame,      /* target */
 942                        u8 *data,                       /* isoc packet */
 943                        int len)                        /* iso packet length */
 944{
 945        static u8 ffd9[] = { 0xff, 0xd9 };
 946
 947        if (data[0] == 0x5a) {
 948                /* Control Packet, after this came the header again,
 949                 * but extra bytes came in the packet before this,
 950                 * sometimes an EOF arrives, sometimes not... */
 951                return;
 952        }
 953        data += 2;
 954        len -= 2;
 955        if (data[0] == 0xff && data[1] == 0xd8) {
 956                /* extra bytes....., could be processed too but would be
 957                 * a waste of time, right now leave the application and
 958                 * libjpeg do it for ourserlves.. */
 959                frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
 960                                        ffd9, 2);
 961                gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
 962                return;
 963        }
 964
 965        if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
 966                /* Just in case, i have seen packets with the marker,
 967                 * other's do not include it... */
 968                len -= 2;
 969        }
 970        gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 971}
 972
 973static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 974{
 975        struct sd *sd = (struct sd *) gspca_dev;
 976
 977        sd->brightness = val;
 978        if (gspca_dev->streaming)
 979                setbrightness(gspca_dev);
 980        return 0;
 981}
 982
 983static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
 984{
 985        struct sd *sd = (struct sd *) gspca_dev;
 986
 987        *val = sd->brightness;
 988        return *val;
 989}
 990
 991static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
 992{
 993        struct sd *sd = (struct sd *) gspca_dev;
 994
 995        sd->whitebalance = val;
 996        if (gspca_dev->streaming)
 997                setwhitebalance(gspca_dev);
 998        return 0;
 999}
1000
1001static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
1002{
1003        struct sd *sd = (struct sd *) gspca_dev;
1004
1005        *val = sd->whitebalance;
1006        return *val;
1007}
1008
1009static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
1010{
1011        struct sd *sd = (struct sd *) gspca_dev;
1012
1013        sd->mirror = val;
1014        if (gspca_dev->streaming)
1015                setflip(gspca_dev);
1016        return 0;
1017}
1018
1019static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
1020{
1021        struct sd *sd = (struct sd *) gspca_dev;
1022
1023        *val = sd->mirror;
1024        return *val;
1025}
1026
1027static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1028{
1029        struct sd *sd = (struct sd *) gspca_dev;
1030
1031        sd->effect = val;
1032        if (gspca_dev->streaming)
1033                seteffect(gspca_dev);
1034        return 0;
1035}
1036
1037static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1038{
1039        struct sd *sd = (struct sd *) gspca_dev;
1040
1041        *val = sd->effect;
1042        return *val;
1043}
1044
1045static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1046{
1047        struct sd *sd = (struct sd *) gspca_dev;
1048
1049        sd->contrast = val;
1050        if (gspca_dev->streaming)
1051                setcontrast(gspca_dev);
1052        return 0;
1053}
1054
1055static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1056{
1057        struct sd *sd = (struct sd *) gspca_dev;
1058
1059        *val = sd->contrast;
1060        return *val;
1061}
1062
1063static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1064{
1065        struct sd *sd = (struct sd *) gspca_dev;
1066
1067        sd->colors = val;
1068        if (gspca_dev->streaming)
1069                setcolors(gspca_dev);
1070        return 0;
1071}
1072
1073static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1074{
1075        struct sd *sd = (struct sd *) gspca_dev;
1076
1077        *val = sd->colors;
1078        return 0;
1079}
1080
1081static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1082{
1083        struct sd *sd = (struct sd *) gspca_dev;
1084
1085        sd->gamma = val;
1086        if (gspca_dev->streaming)
1087                setgamma(gspca_dev);
1088        return 0;
1089}
1090
1091static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1092{
1093        struct sd *sd = (struct sd *) gspca_dev;
1094
1095        *val = sd->gamma;
1096        return 0;
1097}
1098
1099static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1100{
1101        struct sd *sd = (struct sd *) gspca_dev;
1102
1103        sd->freq = val;
1104        if (gspca_dev->streaming)
1105                setlightfreq(gspca_dev);
1106        return 0;
1107}
1108
1109static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1110{
1111        struct sd *sd = (struct sd *) gspca_dev;
1112
1113        *val = sd->freq;
1114        return 0;
1115}
1116
1117static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1118{
1119        struct sd *sd = (struct sd *) gspca_dev;
1120
1121        sd->sharpness = val;
1122        if (gspca_dev->streaming)
1123                setsharpness(gspca_dev);
1124        return 0;
1125}
1126
1127static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1128{
1129        struct sd *sd = (struct sd *) gspca_dev;
1130
1131        *val = sd->sharpness;
1132        return 0;
1133}
1134
1135/* Low Light set  here......*/
1136static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1137{
1138        struct sd *sd = (struct sd *) gspca_dev;
1139
1140        sd->autogain = val;
1141        if (val != 0)
1142                reg_w(gspca_dev, 0xf48e);
1143        else
1144                reg_w(gspca_dev, 0xb48e);
1145        return 0;
1146}
1147
1148static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1149{
1150        struct sd *sd = (struct sd *) gspca_dev;
1151
1152        *val = sd->autogain;
1153        return 0;
1154}
1155
1156static int sd_querymenu(struct gspca_dev *gspca_dev,
1157                        struct v4l2_querymenu *menu)
1158{
1159        switch (menu->id) {
1160        case V4L2_CID_POWER_LINE_FREQUENCY:
1161                switch (menu->index) {
1162                case 1:         /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1163                        strcpy((char *) menu->name, "50 Hz");
1164                        return 0;
1165                case 2:         /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1166                        strcpy((char *) menu->name, "60 Hz");
1167                        return 0;
1168                }
1169                break;
1170        case V4L2_CID_EFFECTS:
1171                if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1172                        strncpy((char *) menu->name,
1173                                effects_control[menu->index], 32);
1174                        return 0;
1175                }
1176                break;
1177        }
1178        return -EINVAL;
1179}
1180
1181/* sub-driver description */
1182static const struct sd_desc sd_desc = {
1183        .name = MODULE_NAME,
1184        .ctrls = sd_ctrls,
1185        .nctrls = ARRAY_SIZE(sd_ctrls),
1186        .config = sd_config,
1187        .init = sd_init,
1188        .start = sd_start,
1189        .stopN = sd_stopN,
1190        .pkt_scan = sd_pkt_scan,
1191        .querymenu = sd_querymenu,
1192};
1193
1194/* -- module initialisation -- */
1195static const __devinitdata struct usb_device_id device_table[] = {
1196        {USB_DEVICE(0x17a1, 0x0128)},
1197        {}
1198};
1199MODULE_DEVICE_TABLE(usb, device_table);
1200
1201/* -- device connect -- */
1202static int sd_probe(struct usb_interface *intf,
1203                    const struct usb_device_id *id)
1204{
1205        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1206                               THIS_MODULE);
1207}
1208
1209static struct usb_driver sd_driver = {
1210        .name = MODULE_NAME,
1211        .id_table = device_table,
1212        .probe = sd_probe,
1213        .disconnect = gspca_disconnect,
1214#ifdef CONFIG_PM
1215        .suspend = gspca_suspend,
1216        .resume = gspca_resume,
1217#endif
1218};
1219
1220/* -- module insert / remove -- */
1221static int __init sd_mod_init(void)
1222{
1223        int ret;
1224        ret = usb_register(&sd_driver);
1225        if (ret < 0)
1226                return ret;
1227        PDEBUG(D_PROBE, "registered");
1228        return 0;
1229}
1230static void __exit sd_mod_exit(void)
1231{
1232        usb_deregister(&sd_driver);
1233        PDEBUG(D_PROBE, "deregistered");
1234}
1235
1236module_init(sd_mod_init);
1237module_exit(sd_mod_exit);
1238
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.