root/drivers/media/usb/gspca/sn9c2028.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sn9c2028_command
  2. sn9c2028_read1
  3. sn9c2028_read4
  4. sn9c2028_long_command
  5. sn9c2028_short_command
  6. sd_config
  7. sd_init
  8. run_start_commands
  9. set_gain
  10. sd_s_ctrl
  11. sd_init_controls
  12. start_spy_cam
  13. start_cif_cam
  14. start_ms350_cam
  15. start_genius_cam
  16. start_genius_videocam_live
  17. start_vivitar_cam
  18. sd_start
  19. sd_stopN
  20. do_autogain
  21. sd_dqcallback
  22. sd_pkt_scan
  23. sd_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * SN9C2028 library
   4  *
   5  * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
   6  */
   7 
   8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   9 
  10 #define MODULE_NAME "sn9c2028"
  11 
  12 #include "gspca.h"
  13 
  14 MODULE_AUTHOR("Theodore Kilgore");
  15 MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver");
  16 MODULE_LICENSE("GPL");
  17 
  18 /* specific webcam descriptor */
  19 struct sd {
  20         struct gspca_dev gspca_dev;  /* !! must be the first item */
  21         u8 sof_read;
  22         u16 model;
  23 
  24 #define MIN_AVG_LUM 8500
  25 #define MAX_AVG_LUM 10000
  26         int avg_lum;
  27         u8 avg_lum_l;
  28 
  29         struct { /* autogain and gain control cluster */
  30                 struct v4l2_ctrl *autogain;
  31                 struct v4l2_ctrl *gain;
  32         };
  33 };
  34 
  35 struct init_command {
  36         unsigned char instruction[6];
  37         unsigned char to_read; /* length to read. 0 means no reply requested */
  38 };
  39 
  40 /* How to change the resolution of any of the VGA cams is unknown */
  41 static const struct v4l2_pix_format vga_mode[] = {
  42         {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
  43                 .bytesperline = 640,
  44                 .sizeimage = 640 * 480 * 3 / 4,
  45                 .colorspace = V4L2_COLORSPACE_SRGB,
  46                 .priv = 0},
  47 };
  48 
  49 /* No way to change the resolution of the CIF cams is known */
  50 static const struct v4l2_pix_format cif_mode[] = {
  51         {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
  52                 .bytesperline = 352,
  53                 .sizeimage = 352 * 288 * 3 / 4,
  54                 .colorspace = V4L2_COLORSPACE_SRGB,
  55                 .priv = 0},
  56 };
  57 
  58 /* the bytes to write are in gspca_dev->usb_buf */
  59 static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
  60 {
  61         int rc;
  62 
  63         gspca_dbg(gspca_dev, D_USBO, "sending command %02x%02x%02x%02x%02x%02x\n",
  64                   command[0], command[1], command[2],
  65                   command[3], command[4], command[5]);
  66 
  67         memcpy(gspca_dev->usb_buf, command, 6);
  68         rc = usb_control_msg(gspca_dev->dev,
  69                         usb_sndctrlpipe(gspca_dev->dev, 0),
  70                         USB_REQ_GET_CONFIGURATION,
  71                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
  72                         2, 0, gspca_dev->usb_buf, 6, 500);
  73         if (rc < 0) {
  74                 pr_err("command write [%02x] error %d\n",
  75                        gspca_dev->usb_buf[0], rc);
  76                 return rc;
  77         }
  78 
  79         return 0;
  80 }
  81 
  82 static int sn9c2028_read1(struct gspca_dev *gspca_dev)
  83 {
  84         int rc;
  85 
  86         rc = usb_control_msg(gspca_dev->dev,
  87                         usb_rcvctrlpipe(gspca_dev->dev, 0),
  88                         USB_REQ_GET_STATUS,
  89                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
  90                         1, 0, gspca_dev->usb_buf, 1, 500);
  91         if (rc != 1) {
  92                 pr_err("read1 error %d\n", rc);
  93                 return (rc < 0) ? rc : -EIO;
  94         }
  95         gspca_dbg(gspca_dev, D_USBI, "read1 response %02x\n",
  96                   gspca_dev->usb_buf[0]);
  97         return gspca_dev->usb_buf[0];
  98 }
  99 
 100 static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
 101 {
 102         int rc;
 103         rc = usb_control_msg(gspca_dev->dev,
 104                         usb_rcvctrlpipe(gspca_dev->dev, 0),
 105                         USB_REQ_GET_STATUS,
 106                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 107                         4, 0, gspca_dev->usb_buf, 4, 500);
 108         if (rc != 4) {
 109                 pr_err("read4 error %d\n", rc);
 110                 return (rc < 0) ? rc : -EIO;
 111         }
 112         memcpy(reading, gspca_dev->usb_buf, 4);
 113         gspca_dbg(gspca_dev, D_USBI, "read4 response %02x%02x%02x%02x\n",
 114                   reading[0], reading[1], reading[2], reading[3]);
 115         return rc;
 116 }
 117 
 118 static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
 119 {
 120         int i, status;
 121         __u8 reading[4];
 122 
 123         status = sn9c2028_command(gspca_dev, command);
 124         if (status < 0)
 125                 return status;
 126 
 127         status = -1;
 128         for (i = 0; i < 256 && status < 2; i++)
 129                 status = sn9c2028_read1(gspca_dev);
 130         if (status < 0) {
 131                 pr_err("long command status read error %d\n", status);
 132                 return status;
 133         }
 134 
 135         memset(reading, 0, 4);
 136         status = sn9c2028_read4(gspca_dev, reading);
 137         if (status < 0)
 138                 return status;
 139 
 140         /* in general, the first byte of the response is the first byte of
 141          * the command, or'ed with 8 */
 142         status = sn9c2028_read1(gspca_dev);
 143         if (status < 0)
 144                 return status;
 145 
 146         return 0;
 147 }
 148 
 149 static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command)
 150 {
 151         int err_code;
 152 
 153         err_code = sn9c2028_command(gspca_dev, command);
 154         if (err_code < 0)
 155                 return err_code;
 156 
 157         err_code = sn9c2028_read1(gspca_dev);
 158         if (err_code < 0)
 159                 return err_code;
 160 
 161         return 0;
 162 }
 163 
 164 /* this function is called at probe time */
 165 static int sd_config(struct gspca_dev *gspca_dev,
 166                      const struct usb_device_id *id)
 167 {
 168         struct sd *sd = (struct sd *) gspca_dev;
 169         struct cam *cam = &gspca_dev->cam;
 170 
 171         gspca_dbg(gspca_dev, D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)\n",
 172                   id->idVendor, id->idProduct);
 173 
 174         sd->model = id->idProduct;
 175 
 176         switch (sd->model) {
 177         case 0x7005:
 178                 gspca_dbg(gspca_dev, D_PROBE, "Genius Smart 300 camera\n");
 179                 break;
 180         case 0x7003:
 181                 gspca_dbg(gspca_dev, D_PROBE, "Genius Videocam Live v2\n");
 182                 break;
 183         case 0x8000:
 184                 gspca_dbg(gspca_dev, D_PROBE, "DC31VC\n");
 185                 break;
 186         case 0x8001:
 187                 gspca_dbg(gspca_dev, D_PROBE, "Spy camera\n");
 188                 break;
 189         case 0x8003:
 190                 gspca_dbg(gspca_dev, D_PROBE, "CIF camera\n");
 191                 break;
 192         case 0x8008:
 193                 gspca_dbg(gspca_dev, D_PROBE, "Mini-Shotz ms-350 camera\n");
 194                 break;
 195         case 0x800a:
 196                 gspca_dbg(gspca_dev, D_PROBE, "Vivitar 3350b type camera\n");
 197                 cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
 198                 break;
 199         }
 200 
 201         switch (sd->model) {
 202         case 0x8000:
 203         case 0x8001:
 204         case 0x8003:
 205                 cam->cam_mode = cif_mode;
 206                 cam->nmodes = ARRAY_SIZE(cif_mode);
 207                 break;
 208         default:
 209                 cam->cam_mode = vga_mode;
 210                 cam->nmodes = ARRAY_SIZE(vga_mode);
 211         }
 212         return 0;
 213 }
 214 
 215 /* this function is called at probe and resume time */
 216 static int sd_init(struct gspca_dev *gspca_dev)
 217 {
 218         int status = -1;
 219 
 220         sn9c2028_read1(gspca_dev);
 221         sn9c2028_read1(gspca_dev);
 222         status = sn9c2028_read1(gspca_dev);
 223 
 224         return (status < 0) ? status : 0;
 225 }
 226 
 227 static int run_start_commands(struct gspca_dev *gspca_dev,
 228                               struct init_command *cam_commands, int n)
 229 {
 230         int i, err_code = -1;
 231 
 232         for (i = 0; i < n; i++) {
 233                 switch (cam_commands[i].to_read) {
 234                 case 4:
 235                         err_code = sn9c2028_long_command(gspca_dev,
 236                                         cam_commands[i].instruction);
 237                         break;
 238                 case 1:
 239                         err_code = sn9c2028_short_command(gspca_dev,
 240                                         cam_commands[i].instruction);
 241                         break;
 242                 case 0:
 243                         err_code = sn9c2028_command(gspca_dev,
 244                                         cam_commands[i].instruction);
 245                         break;
 246                 }
 247                 if (err_code < 0)
 248                         return err_code;
 249         }
 250         return 0;
 251 }
 252 
 253 static void set_gain(struct gspca_dev *gspca_dev, s32 g)
 254 {
 255         struct sd *sd = (struct sd *) gspca_dev;
 256 
 257         struct init_command genius_vcam_live_gain_cmds[] = {
 258                 {{0x1d, 0x25, 0x10 /* This byte is gain */,
 259                   0x20, 0xab, 0x00}, 0},
 260         };
 261         if (!gspca_dev->streaming)
 262                 return;
 263 
 264         switch (sd->model) {
 265         case 0x7003:
 266                 genius_vcam_live_gain_cmds[0].instruction[2] = g;
 267                 run_start_commands(gspca_dev, genius_vcam_live_gain_cmds,
 268                                    ARRAY_SIZE(genius_vcam_live_gain_cmds));
 269                 break;
 270         default:
 271                 break;
 272         }
 273 }
 274 
 275 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 276 {
 277         struct gspca_dev *gspca_dev =
 278                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 279         struct sd *sd = (struct sd *)gspca_dev;
 280 
 281         gspca_dev->usb_err = 0;
 282 
 283         if (!gspca_dev->streaming)
 284                 return 0;
 285 
 286         switch (ctrl->id) {
 287         /* standalone gain control */
 288         case V4L2_CID_GAIN:
 289                 set_gain(gspca_dev, ctrl->val);
 290                 break;
 291         /* autogain */
 292         case V4L2_CID_AUTOGAIN:
 293                 set_gain(gspca_dev, sd->gain->val);
 294                 break;
 295         }
 296         return gspca_dev->usb_err;
 297 }
 298 
 299 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
 300         .s_ctrl = sd_s_ctrl,
 301 };
 302 
 303 
 304 static int sd_init_controls(struct gspca_dev *gspca_dev)
 305 {
 306         struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 307         struct sd *sd = (struct sd *)gspca_dev;
 308 
 309         gspca_dev->vdev.ctrl_handler = hdl;
 310         v4l2_ctrl_handler_init(hdl, 2);
 311 
 312         switch (sd->model) {
 313         case 0x7003:
 314                 sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 315                         V4L2_CID_GAIN, 0, 20, 1, 0);
 316                 sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 317                         V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
 318                 break;
 319         default:
 320                 break;
 321         }
 322 
 323         return 0;
 324 }
 325 static int start_spy_cam(struct gspca_dev *gspca_dev)
 326 {
 327         struct init_command spy_start_commands[] = {
 328                 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 329                 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
 330                 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
 331                 {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
 332                 {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
 333                 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
 334                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width  352 */
 335                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */
 336                 /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */
 337                 {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4},
 338                 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/
 339                 /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */
 340                 {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
 341                 /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */
 342                 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
 343                 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
 344                 /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */
 345                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 346                 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
 347                 /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */
 348                 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
 349                 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
 350                 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
 351                 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
 352                 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
 353                 {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4},
 354                 {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/
 355                 /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
 356                 {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
 357                 /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */
 358                 {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
 359                 {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */
 360                 {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4},
 361                 /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
 362                 {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4},
 363                 {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4},
 364                 {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4},
 365                 {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
 366                 {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4},
 367                 {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4},
 368                 {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4},
 369                 /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */
 370                 /* brightness or gain. 0 is default. 4 is good
 371                  * indoors at night with incandescent lighting */
 372                 {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4},
 373                 {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/
 374                 {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4},
 375                 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
 376                 {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4},
 377                 {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4},
 378                 /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */
 379                 {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */
 380                 /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */
 381                 {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1},
 382                 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */
 383                 /* Camera should start to capture now. */
 384         };
 385 
 386         return run_start_commands(gspca_dev, spy_start_commands,
 387                                   ARRAY_SIZE(spy_start_commands));
 388 }
 389 
 390 static int start_cif_cam(struct gspca_dev *gspca_dev)
 391 {
 392         struct init_command cif_start_commands[] = {
 393                 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 394                 /* The entire sequence below seems redundant */
 395                 /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
 396                 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
 397                 {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4},
 398                 {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4},
 399                 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
 400                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width?
 401                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height?
 402                 {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
 403                 {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
 404                 {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
 405                 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
 406                 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
 407                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 408                 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
 409                 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
 410                 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
 411                 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
 412                 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
 413                 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/
 414                 {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1},
 415                 {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1},
 416                 {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1},
 417                 {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
 418                 {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1},
 419                 {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1},
 420                 {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1},
 421                 {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1},
 422                 {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
 423                 {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1},
 424                 {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1},
 425                 {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1},
 426                 {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1},
 427                 {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1},
 428                 {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1},
 429                 {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1},
 430                 {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1},
 431                 {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1},
 432                 {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
 433                 {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1},
 434                 {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1},
 435                 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
 436                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */
 437                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */
 438                 /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
 439                  * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing
 440                  * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */
 441                 /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
 442                  * causes subsampling
 443                  * but not a change in the resolution setting! */
 444                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 445                 {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4},
 446                 {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4},
 447                 {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4},
 448                 {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
 449                 {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1},
 450                 {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1},
 451                 {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
 452                 {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1},
 453                 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
 454                 {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
 455                 {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
 456                 {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1},
 457                 {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
 458                 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
 459                 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */
 460                 /* Camera should start to capture now. */
 461         };
 462 
 463         return run_start_commands(gspca_dev, cif_start_commands,
 464                                   ARRAY_SIZE(cif_start_commands));
 465 }
 466 
 467 static int start_ms350_cam(struct gspca_dev *gspca_dev)
 468 {
 469         struct init_command ms350_start_commands[] = {
 470                 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 471                 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 472                 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
 473                 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
 474                 {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
 475                 {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
 476                 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
 477                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
 478                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
 479                 {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
 480                 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4},
 481                 {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
 482                 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
 483                 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
 484                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 485                 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
 486                 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
 487                 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
 488                 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
 489                 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
 490                 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
 491                 {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4},
 492                 {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4},
 493                 {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4},
 494                 {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4},
 495                 {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4},
 496                 {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4},
 497                 {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4},
 498                 {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4},
 499                 {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4},
 500                 {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4},
 501                 {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4},
 502                 {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
 503                 {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4},
 504                 {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4},
 505                 {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4},
 506                 {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4},
 507                 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
 508                 {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4},
 509                 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
 510                 {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4},
 511                 {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4},
 512                 {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4},
 513                 {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4},
 514                 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width  */
 515                 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */
 516                 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */
 517                 {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
 518                 {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */
 519                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 520                 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
 521                 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
 522                 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
 523                 {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1},
 524                 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
 525                 {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1},
 526                 {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1},
 527                 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0},
 528                 /* Camera should start to capture now. */
 529         };
 530 
 531         return run_start_commands(gspca_dev, ms350_start_commands,
 532                                   ARRAY_SIZE(ms350_start_commands));
 533 }
 534 
 535 static int start_genius_cam(struct gspca_dev *gspca_dev)
 536 {
 537         struct init_command genius_start_commands[] = {
 538                 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 539                 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 540                 {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
 541                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
 542                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
 543                 /* "preliminary" width and height settings */
 544                 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
 545                 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
 546                 {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
 547                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 548                 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
 549                 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
 550                 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
 551                 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
 552                 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
 553                 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
 554                 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
 555                 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
 556                 {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
 557                 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
 558                 {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
 559                 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
 560                 {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
 561                 {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
 562                 {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
 563                 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
 564                 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
 565                 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
 566                 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
 567                 {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
 568                 {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
 569                 {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
 570                 {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
 571                 {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
 572                 {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
 573                 {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
 574                 {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
 575                 {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
 576                 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */
 577                 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */
 578                 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
 579                 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
 580                 {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
 581                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 582                 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
 583                 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
 584                 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
 585                 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
 586                 {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
 587                 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
 588                 {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
 589                 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
 590                 {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
 591                 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
 592                 {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
 593                 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
 594                 {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
 595                 {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
 596                 {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
 597                 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
 598                 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
 599                 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}
 600                 /* Camera should start to capture now. */
 601         };
 602 
 603         return run_start_commands(gspca_dev, genius_start_commands,
 604                                   ARRAY_SIZE(genius_start_commands));
 605 }
 606 
 607 static int start_genius_videocam_live(struct gspca_dev *gspca_dev)
 608 {
 609         int r;
 610         struct sd *sd = (struct sd *) gspca_dev;
 611         struct init_command genius_vcam_live_start_commands[] = {
 612                 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 0},
 613                 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 614                 {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
 615                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
 616                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
 617 
 618                 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
 619                 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
 620                 {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
 621                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 622                 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
 623                 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
 624                 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
 625                 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
 626                 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
 627                 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
 628                 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
 629                 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
 630                 {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
 631                 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
 632                 {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
 633                 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
 634                 {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
 635                 {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
 636                 {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
 637                 {{0x1c, 0x20, 0x00, 0x2d, 0x00, 0x00}, 4},
 638                 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
 639                 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
 640                 {{0x13, 0x22, 0x01, 0x00, 0x00, 0x00}, 4},
 641                 {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
 642                 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
 643                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
 644                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
 645                 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
 646                 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
 647                 {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
 648                 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
 649                 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
 650                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 651                 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
 652                 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
 653                 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
 654                 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
 655                 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
 656                 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
 657                 {{0x11, 0x01, 0x04, 0x00, 0x00, 0x00}, 4},
 658                 {{0x11, 0x02, 0x92, 0x00, 0x00, 0x00}, 4},
 659                 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
 660                 {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
 661                 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
 662                 {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
 663                 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
 664                 {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
 665                 {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
 666                 {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
 667                 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
 668                 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
 669                 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
 670                 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
 671                 {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
 672                 {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
 673                 {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
 674                 {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
 675                 {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
 676                 {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
 677                 {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
 678                 {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
 679                 {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
 680                 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
 681                 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
 682                 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
 683                 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
 684                 {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
 685                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 686                 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
 687                 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
 688                 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
 689                 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
 690                 {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
 691                 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
 692                 {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
 693                 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
 694                 {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
 695                 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
 696                 {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
 697                 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
 698                 {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
 699                 {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
 700                 {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
 701                 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
 702                 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0},
 703                 /* Camera should start to capture now. */
 704                 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 0},
 705                 {{0x1b, 0x32, 0x26, 0x00, 0x00, 0x00}, 0},
 706                 {{0x1d, 0x25, 0x10, 0x20, 0xab, 0x00}, 0},
 707         };
 708 
 709         r = run_start_commands(gspca_dev, genius_vcam_live_start_commands,
 710                                   ARRAY_SIZE(genius_vcam_live_start_commands));
 711         if (r < 0)
 712                 return r;
 713 
 714         if (sd->gain)
 715                 set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
 716 
 717         return r;
 718 }
 719 
 720 static int start_vivitar_cam(struct gspca_dev *gspca_dev)
 721 {
 722         struct init_command vivitar_start_commands[] = {
 723                 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
 724                 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
 725                 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
 726                 {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4},
 727                 {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
 728                 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
 729                 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
 730                 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
 731                 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
 732                 {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4},
 733                 /*
 734                  * Above is changed from OEM 0x0b. Fixes Bayer tiling.
 735                  * Presumably gives a vertical shift of one row.
 736                  */
 737                 {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
 738                 /* Above seems to do horizontal shift. */
 739                 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
 740                 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
 741                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
 742                 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
 743                 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
 744                 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
 745                 /* Above three commands seem to relate to brightness. */
 746                 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
 747                 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
 748                 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
 749                 {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1},
 750                 {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1},
 751                 {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1},
 752                 {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1},
 753                 {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
 754                 {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1},
 755                 {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1},
 756                 {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1},
 757                 {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1},
 758                 {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1},
 759                 {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1},
 760                 {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1},
 761                 {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1},
 762                 {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
 763                 {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1},
 764                 {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1},
 765                 {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1},
 766                 {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1},
 767                 {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1},
 768                 {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1},
 769                 {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1},
 770                 {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1},
 771                 {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1},
 772                 {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1},
 773                 {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1},
 774                 {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1},
 775                 {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1},
 776                 {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1},
 777                 {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1},
 778                 {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1},
 779                 {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1},
 780                 {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1},
 781                 {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1},
 782                 {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1},
 783                 /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
 784                 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
 785                 {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */
 786                 {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
 787                 {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1},
 788                 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
 789                 {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1},
 790                 {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
 791                 {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1},
 792                 /* Above is brightness; OEM driver setting is 0x10 */
 793                 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
 794                 {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
 795                 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}
 796         };
 797 
 798         return run_start_commands(gspca_dev, vivitar_start_commands,
 799                                   ARRAY_SIZE(vivitar_start_commands));
 800 }
 801 
 802 static int sd_start(struct gspca_dev *gspca_dev)
 803 {
 804         struct sd *sd = (struct sd *) gspca_dev;
 805         int err_code;
 806 
 807         sd->sof_read = 0;
 808 
 809         switch (sd->model) {
 810         case 0x7005:
 811                 err_code = start_genius_cam(gspca_dev);
 812                 break;
 813         case 0x7003:
 814                 err_code = start_genius_videocam_live(gspca_dev);
 815                 break;
 816         case 0x8001:
 817                 err_code = start_spy_cam(gspca_dev);
 818                 break;
 819         case 0x8003:
 820                 err_code = start_cif_cam(gspca_dev);
 821                 break;
 822         case 0x8008:
 823                 err_code = start_ms350_cam(gspca_dev);
 824                 break;
 825         case 0x800a:
 826                 err_code = start_vivitar_cam(gspca_dev);
 827                 break;
 828         default:
 829                 pr_err("Starting unknown camera, please report this\n");
 830                 return -ENXIO;
 831         }
 832 
 833         sd->avg_lum = -1;
 834 
 835         return err_code;
 836 }
 837 
 838 static void sd_stopN(struct gspca_dev *gspca_dev)
 839 {
 840         int result;
 841         __u8 data[6];
 842 
 843         result = sn9c2028_read1(gspca_dev);
 844         if (result < 0)
 845                 gspca_err(gspca_dev, "Camera Stop read failed\n");
 846 
 847         memset(data, 0, 6);
 848         data[0] = 0x14;
 849         result = sn9c2028_command(gspca_dev, data);
 850         if (result < 0)
 851                 gspca_err(gspca_dev, "Camera Stop command failed\n");
 852 }
 853 
 854 static void do_autogain(struct gspca_dev *gspca_dev, int avg_lum)
 855 {
 856         struct sd *sd = (struct sd *) gspca_dev;
 857         s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain);
 858 
 859         if (avg_lum == -1)
 860                 return;
 861 
 862         if (avg_lum < MIN_AVG_LUM) {
 863                 if (cur_gain == sd->gain->maximum)
 864                         return;
 865                 cur_gain++;
 866                 v4l2_ctrl_s_ctrl(sd->gain, cur_gain);
 867         }
 868         if (avg_lum > MAX_AVG_LUM) {
 869                 if (cur_gain == sd->gain->minimum)
 870                         return;
 871                 cur_gain--;
 872                 v4l2_ctrl_s_ctrl(sd->gain, cur_gain);
 873         }
 874 
 875 }
 876 
 877 static void sd_dqcallback(struct gspca_dev *gspca_dev)
 878 {
 879         struct sd *sd = (struct sd *) gspca_dev;
 880 
 881         if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain))
 882                 return;
 883 
 884         do_autogain(gspca_dev, sd->avg_lum);
 885 }
 886 
 887 /* Include sn9c2028 sof detection functions */
 888 #include "sn9c2028.h"
 889 
 890 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 891                         __u8 *data,                     /* isoc packet */
 892                         int len)                        /* iso packet length */
 893 {
 894         unsigned char *sof;
 895 
 896         sof = sn9c2028_find_sof(gspca_dev, data, len);
 897         if (sof) {
 898                 int n;
 899 
 900                 /* finish decoding current frame */
 901                 n = sof - data;
 902                 if (n > sizeof sn9c2028_sof_marker)
 903                         n -= sizeof sn9c2028_sof_marker;
 904                 else
 905                         n = 0;
 906                 gspca_frame_add(gspca_dev, LAST_PACKET, data, n);
 907                 /* Start next frame. */
 908                 gspca_frame_add(gspca_dev, FIRST_PACKET,
 909                         sn9c2028_sof_marker, sizeof sn9c2028_sof_marker);
 910                 len -= sof - data;
 911                 data = sof;
 912         }
 913         gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 914 }
 915 
 916 /* sub-driver description */
 917 static const struct sd_desc sd_desc = {
 918         .name = MODULE_NAME,
 919         .config = sd_config,
 920         .init = sd_init,
 921         .init_controls = sd_init_controls,
 922         .start = sd_start,
 923         .stopN = sd_stopN,
 924         .dq_callback = sd_dqcallback,
 925         .pkt_scan = sd_pkt_scan,
 926 };
 927 
 928 /* -- module initialisation -- */
 929 static const struct usb_device_id device_table[] = {
 930         {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */
 931         {USB_DEVICE(0x0458, 0x7003)}, /* Genius Videocam Live v2  */
 932         /* The Genius Smart is untested. I can't find an owner ! */
 933         /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */
 934         {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */
 935         {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */
 936         /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */
 937         {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */
 938         {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */
 939         {}
 940 };
 941 MODULE_DEVICE_TABLE(usb, device_table);
 942 
 943 /* -- device connect -- */
 944 static int sd_probe(struct usb_interface *intf,
 945                         const struct usb_device_id *id)
 946 {
 947         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 948                                THIS_MODULE);
 949 }
 950 
 951 static struct usb_driver sd_driver = {
 952         .name = MODULE_NAME,
 953         .id_table = device_table,
 954         .probe = sd_probe,
 955         .disconnect = gspca_disconnect,
 956 #ifdef CONFIG_PM
 957         .suspend = gspca_suspend,
 958         .resume = gspca_resume,
 959         .reset_resume = gspca_resume,
 960 #endif
 961 };
 962 
 963 module_usb_driver(sd_driver);

/* [<][>][^][v][top][bottom][index][help] */