Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * SN9C2028 library
0004  *
0005  * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
0006  */
0007 
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009 
0010 #define MODULE_NAME "sn9c2028"
0011 
0012 #include "gspca.h"
0013 
0014 MODULE_AUTHOR("Theodore Kilgore");
0015 MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver");
0016 MODULE_LICENSE("GPL");
0017 
0018 /* specific webcam descriptor */
0019 struct sd {
0020     struct gspca_dev gspca_dev;  /* !! must be the first item */
0021     u8 sof_read;
0022     u16 model;
0023 
0024 #define MIN_AVG_LUM 8500
0025 #define MAX_AVG_LUM 10000
0026     int avg_lum;
0027     u8 avg_lum_l;
0028 
0029     struct { /* autogain and gain control cluster */
0030         struct v4l2_ctrl *autogain;
0031         struct v4l2_ctrl *gain;
0032     };
0033 };
0034 
0035 struct init_command {
0036     unsigned char instruction[6];
0037     unsigned char to_read; /* length to read. 0 means no reply requested */
0038 };
0039 
0040 /* How to change the resolution of any of the VGA cams is unknown */
0041 static const struct v4l2_pix_format vga_mode[] = {
0042     {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
0043         .bytesperline = 640,
0044         .sizeimage = 640 * 480 * 3 / 4,
0045         .colorspace = V4L2_COLORSPACE_SRGB,
0046         .priv = 0},
0047 };
0048 
0049 /* No way to change the resolution of the CIF cams is known */
0050 static const struct v4l2_pix_format cif_mode[] = {
0051     {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
0052         .bytesperline = 352,
0053         .sizeimage = 352 * 288 * 3 / 4,
0054         .colorspace = V4L2_COLORSPACE_SRGB,
0055         .priv = 0},
0056 };
0057 
0058 /* the bytes to write are in gspca_dev->usb_buf */
0059 static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
0060 {
0061     int rc;
0062 
0063     gspca_dbg(gspca_dev, D_USBO, "sending command %02x%02x%02x%02x%02x%02x\n",
0064           command[0], command[1], command[2],
0065           command[3], command[4], command[5]);
0066 
0067     memcpy(gspca_dev->usb_buf, command, 6);
0068     rc = usb_control_msg(gspca_dev->dev,
0069             usb_sndctrlpipe(gspca_dev->dev, 0),
0070             USB_REQ_GET_CONFIGURATION,
0071             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
0072             2, 0, gspca_dev->usb_buf, 6, 500);
0073     if (rc < 0) {
0074         pr_err("command write [%02x] error %d\n",
0075                gspca_dev->usb_buf[0], rc);
0076         return rc;
0077     }
0078 
0079     return 0;
0080 }
0081 
0082 static int sn9c2028_read1(struct gspca_dev *gspca_dev)
0083 {
0084     int rc;
0085 
0086     rc = usb_control_msg(gspca_dev->dev,
0087             usb_rcvctrlpipe(gspca_dev->dev, 0),
0088             USB_REQ_GET_STATUS,
0089             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
0090             1, 0, gspca_dev->usb_buf, 1, 500);
0091     if (rc != 1) {
0092         pr_err("read1 error %d\n", rc);
0093         return (rc < 0) ? rc : -EIO;
0094     }
0095     gspca_dbg(gspca_dev, D_USBI, "read1 response %02x\n",
0096           gspca_dev->usb_buf[0]);
0097     return gspca_dev->usb_buf[0];
0098 }
0099 
0100 static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
0101 {
0102     int rc;
0103     rc = usb_control_msg(gspca_dev->dev,
0104             usb_rcvctrlpipe(gspca_dev->dev, 0),
0105             USB_REQ_GET_STATUS,
0106             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
0107             4, 0, gspca_dev->usb_buf, 4, 500);
0108     if (rc != 4) {
0109         pr_err("read4 error %d\n", rc);
0110         return (rc < 0) ? rc : -EIO;
0111     }
0112     memcpy(reading, gspca_dev->usb_buf, 4);
0113     gspca_dbg(gspca_dev, D_USBI, "read4 response %02x%02x%02x%02x\n",
0114           reading[0], reading[1], reading[2], reading[3]);
0115     return rc;
0116 }
0117 
0118 static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
0119 {
0120     int i, status;
0121     __u8 reading[4];
0122 
0123     status = sn9c2028_command(gspca_dev, command);
0124     if (status < 0)
0125         return status;
0126 
0127     status = -1;
0128     for (i = 0; i < 256 && status < 2; i++)
0129         status = sn9c2028_read1(gspca_dev);
0130     if (status < 0) {
0131         pr_err("long command status read error %d\n", status);
0132         return status;
0133     }
0134 
0135     memset(reading, 0, 4);
0136     status = sn9c2028_read4(gspca_dev, reading);
0137     if (status < 0)
0138         return status;
0139 
0140     /* in general, the first byte of the response is the first byte of
0141      * the command, or'ed with 8 */
0142     status = sn9c2028_read1(gspca_dev);
0143     if (status < 0)
0144         return status;
0145 
0146     return 0;
0147 }
0148 
0149 static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command)
0150 {
0151     int err_code;
0152 
0153     err_code = sn9c2028_command(gspca_dev, command);
0154     if (err_code < 0)
0155         return err_code;
0156 
0157     err_code = sn9c2028_read1(gspca_dev);
0158     if (err_code < 0)
0159         return err_code;
0160 
0161     return 0;
0162 }
0163 
0164 /* this function is called at probe time */
0165 static int sd_config(struct gspca_dev *gspca_dev,
0166              const struct usb_device_id *id)
0167 {
0168     struct sd *sd = (struct sd *) gspca_dev;
0169     struct cam *cam = &gspca_dev->cam;
0170 
0171     gspca_dbg(gspca_dev, D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)\n",
0172           id->idVendor, id->idProduct);
0173 
0174     sd->model = id->idProduct;
0175 
0176     switch (sd->model) {
0177     case 0x7005:
0178         gspca_dbg(gspca_dev, D_PROBE, "Genius Smart 300 camera\n");
0179         break;
0180     case 0x7003:
0181         gspca_dbg(gspca_dev, D_PROBE, "Genius Videocam Live v2\n");
0182         break;
0183     case 0x8000:
0184         gspca_dbg(gspca_dev, D_PROBE, "DC31VC\n");
0185         break;
0186     case 0x8001:
0187         gspca_dbg(gspca_dev, D_PROBE, "Spy camera\n");
0188         break;
0189     case 0x8003:
0190         gspca_dbg(gspca_dev, D_PROBE, "CIF camera\n");
0191         break;
0192     case 0x8008:
0193         gspca_dbg(gspca_dev, D_PROBE, "Mini-Shotz ms-350 camera\n");
0194         break;
0195     case 0x800a:
0196         gspca_dbg(gspca_dev, D_PROBE, "Vivitar 3350b type camera\n");
0197         cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
0198         break;
0199     }
0200 
0201     switch (sd->model) {
0202     case 0x8000:
0203     case 0x8001:
0204     case 0x8003:
0205         cam->cam_mode = cif_mode;
0206         cam->nmodes = ARRAY_SIZE(cif_mode);
0207         break;
0208     default:
0209         cam->cam_mode = vga_mode;
0210         cam->nmodes = ARRAY_SIZE(vga_mode);
0211     }
0212     return 0;
0213 }
0214 
0215 /* this function is called at probe and resume time */
0216 static int sd_init(struct gspca_dev *gspca_dev)
0217 {
0218     int status;
0219 
0220     sn9c2028_read1(gspca_dev);
0221     sn9c2028_read1(gspca_dev);
0222     status = sn9c2028_read1(gspca_dev);
0223 
0224     return (status < 0) ? status : 0;
0225 }
0226 
0227 static int run_start_commands(struct gspca_dev *gspca_dev,
0228                   struct init_command *cam_commands, int n)
0229 {
0230     int i, err_code = -1;
0231 
0232     for (i = 0; i < n; i++) {
0233         switch (cam_commands[i].to_read) {
0234         case 4:
0235             err_code = sn9c2028_long_command(gspca_dev,
0236                     cam_commands[i].instruction);
0237             break;
0238         case 1:
0239             err_code = sn9c2028_short_command(gspca_dev,
0240                     cam_commands[i].instruction);
0241             break;
0242         case 0:
0243             err_code = sn9c2028_command(gspca_dev,
0244                     cam_commands[i].instruction);
0245             break;
0246         }
0247         if (err_code < 0)
0248             return err_code;
0249     }
0250     return 0;
0251 }
0252 
0253 static void set_gain(struct gspca_dev *gspca_dev, s32 g)
0254 {
0255     struct sd *sd = (struct sd *) gspca_dev;
0256 
0257     struct init_command genius_vcam_live_gain_cmds[] = {
0258         {{0x1d, 0x25, 0x10 /* This byte is gain */,
0259           0x20, 0xab, 0x00}, 0},
0260     };
0261     if (!gspca_dev->streaming)
0262         return;
0263 
0264     switch (sd->model) {
0265     case 0x7003:
0266         genius_vcam_live_gain_cmds[0].instruction[2] = g;
0267         run_start_commands(gspca_dev, genius_vcam_live_gain_cmds,
0268                    ARRAY_SIZE(genius_vcam_live_gain_cmds));
0269         break;
0270     default:
0271         break;
0272     }
0273 }
0274 
0275 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
0276 {
0277     struct gspca_dev *gspca_dev =
0278         container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0279     struct sd *sd = (struct sd *)gspca_dev;
0280 
0281     gspca_dev->usb_err = 0;
0282 
0283     if (!gspca_dev->streaming)
0284         return 0;
0285 
0286     switch (ctrl->id) {
0287     /* standalone gain control */
0288     case V4L2_CID_GAIN:
0289         set_gain(gspca_dev, ctrl->val);
0290         break;
0291     /* autogain */
0292     case V4L2_CID_AUTOGAIN:
0293         set_gain(gspca_dev, sd->gain->val);
0294         break;
0295     }
0296     return gspca_dev->usb_err;
0297 }
0298 
0299 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
0300     .s_ctrl = sd_s_ctrl,
0301 };
0302 
0303 
0304 static int sd_init_controls(struct gspca_dev *gspca_dev)
0305 {
0306     struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0307     struct sd *sd = (struct sd *)gspca_dev;
0308 
0309     gspca_dev->vdev.ctrl_handler = hdl;
0310     v4l2_ctrl_handler_init(hdl, 2);
0311 
0312     switch (sd->model) {
0313     case 0x7003:
0314         sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0315             V4L2_CID_GAIN, 0, 20, 1, 0);
0316         sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0317             V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
0318         break;
0319     default:
0320         break;
0321     }
0322 
0323     return 0;
0324 }
0325 static int start_spy_cam(struct gspca_dev *gspca_dev)
0326 {
0327     struct init_command spy_start_commands[] = {
0328         {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
0329         {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
0330         {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
0331         {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
0332         {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
0333         {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
0334         {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width  352 */
0335         {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */
0336         /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */
0337         {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4},
0338         {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/
0339         /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */
0340         {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
0341         /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */
0342         {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
0343         {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
0344         /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */
0345         {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
0346         {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
0347         /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */
0348         {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
0349         {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
0350         {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
0351         {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
0352         {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
0353         {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4},
0354         {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/
0355         /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
0356         {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
0357         /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */
0358         {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
0359         {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */
0360         {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4},
0361         /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
0362         {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4},
0363         {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4},
0364         {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4},
0365         {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
0366         {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4},
0367         {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4},
0368         {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4},
0369         /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */
0370         /* brightness or gain. 0 is default. 4 is good
0371          * indoors at night with incandescent lighting */
0372         {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4},
0373         {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/
0374         {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4},
0375         {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
0376         {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4},
0377         {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4},
0378         /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */
0379         {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */
0380         /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */
0381         {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1},
0382         {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */
0383         /* Camera should start to capture now. */
0384     };
0385 
0386     return run_start_commands(gspca_dev, spy_start_commands,
0387                   ARRAY_SIZE(spy_start_commands));
0388 }
0389 
0390 static int start_cif_cam(struct gspca_dev *gspca_dev)
0391 {
0392     struct init_command cif_start_commands[] = {
0393         {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
0394         /* The entire sequence below seems redundant */
0395         /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
0396         {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
0397         {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4},
0398         {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4},
0399         {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
0400         {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width?
0401         {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height?
0402         {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
0403         {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
0404         {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
0405         {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
0406         {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
0407         {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
0408         {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
0409         {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
0410         {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
0411         {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
0412         {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
0413         {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/
0414         {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1},
0415         {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1},
0416         {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1},
0417         {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
0418         {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1},
0419         {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1},
0420         {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1},
0421         {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1},
0422         {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
0423         {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1},
0424         {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1},
0425         {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1},
0426         {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1},
0427         {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1},
0428         {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1},
0429         {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1},
0430         {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1},
0431         {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1},
0432         {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
0433         {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1},
0434         {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1},
0435         {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
0436         {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */
0437         {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */
0438         /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
0439          * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing
0440          * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */
0441         /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
0442          * causes subsampling
0443          * but not a change in the resolution setting! */
0444         {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
0445         {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4},
0446         {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4},
0447         {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4},
0448         {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
0449         {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1},
0450         {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1},
0451         {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
0452         {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1},
0453         {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
0454         {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
0455         {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
0456         {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1},
0457         {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
0458         {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
0459         {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */
0460         /* Camera should start to capture now. */
0461     };
0462 
0463     return run_start_commands(gspca_dev, cif_start_commands,
0464                   ARRAY_SIZE(cif_start_commands));
0465 }
0466 
0467 static int start_ms350_cam(struct gspca_dev *gspca_dev)
0468 {
0469     struct init_command ms350_start_commands[] = {
0470         {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
0471         {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
0472         {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
0473         {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
0474         {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
0475         {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
0476         {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
0477         {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
0478         {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
0479         {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
0480         {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4},
0481         {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
0482         {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
0483         {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
0484         {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
0485         {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
0486         {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
0487         {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
0488         {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
0489         {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
0490         {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
0491         {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4},
0492         {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4},
0493         {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4},
0494         {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4},
0495         {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4},
0496         {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4},
0497         {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4},
0498         {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4},
0499         {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4},
0500         {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4},
0501         {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4},
0502         {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
0503         {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4},
0504         {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4},
0505         {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4},
0506         {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4},
0507         {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
0508         {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4},
0509         {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
0510         {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4},
0511         {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4},
0512         {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4},
0513         {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4},
0514         {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width  */
0515         {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */
0516         {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */
0517         {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
0518         {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */
0519         {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
0520         {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
0521         {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
0522         {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
0523         {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1},
0524         {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
0525         {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1},
0526         {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1},
0527         {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0},
0528         /* Camera should start to capture now. */
0529     };
0530 
0531     return run_start_commands(gspca_dev, ms350_start_commands,
0532                   ARRAY_SIZE(ms350_start_commands));
0533 }
0534 
0535 static int start_genius_cam(struct gspca_dev *gspca_dev)
0536 {
0537     struct init_command genius_start_commands[] = {
0538         {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
0539         {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
0540         {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
0541         {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
0542         {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
0543         /* "preliminary" width and height settings */
0544         {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
0545         {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
0546         {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
0547         {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
0548         {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
0549         {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
0550         {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
0551         {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
0552         {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
0553         {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
0554         {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
0555         {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
0556         {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
0557         {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
0558         {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
0559         {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
0560         {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
0561         {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
0562         {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
0563         {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
0564         {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
0565         {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
0566         {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
0567         {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
0568         {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
0569         {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
0570         {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
0571         {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
0572         {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
0573         {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
0574         {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
0575         {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
0576         {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */
0577         {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */
0578         {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
0579         {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
0580         {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
0581         {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
0582         {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
0583         {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
0584         {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
0585         {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
0586         {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
0587         {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
0588         {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
0589         {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
0590         {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
0591         {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
0592         {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
0593         {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
0594         {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
0595         {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
0596         {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
0597         {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
0598         {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
0599         {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}
0600         /* Camera should start to capture now. */
0601     };
0602 
0603     return run_start_commands(gspca_dev, genius_start_commands,
0604                   ARRAY_SIZE(genius_start_commands));
0605 }
0606 
0607 static int start_genius_videocam_live(struct gspca_dev *gspca_dev)
0608 {
0609     int r;
0610     struct sd *sd = (struct sd *) gspca_dev;
0611     struct init_command genius_vcam_live_start_commands[] = {
0612         {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 0},
0613         {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
0614         {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
0615         {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
0616         {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
0617 
0618         {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
0619         {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
0620         {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
0621         {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
0622         {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
0623         {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
0624         {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
0625         {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
0626         {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
0627         {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
0628         {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
0629         {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
0630         {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
0631         {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
0632         {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
0633         {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
0634         {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
0635         {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
0636         {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
0637         {{0x1c, 0x20, 0x00, 0x2d, 0x00, 0x00}, 4},
0638         {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
0639         {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
0640         {{0x13, 0x22, 0x01, 0x00, 0x00, 0x00}, 4},
0641         {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
0642         {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
0643         {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
0644         {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
0645         {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
0646         {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
0647         {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
0648         {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
0649         {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
0650         {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
0651         {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
0652         {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
0653         {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
0654         {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
0655         {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
0656         {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
0657         {{0x11, 0x01, 0x04, 0x00, 0x00, 0x00}, 4},
0658         {{0x11, 0x02, 0x92, 0x00, 0x00, 0x00}, 4},
0659         {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
0660         {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
0661         {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
0662         {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
0663         {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
0664         {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
0665         {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
0666         {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
0667         {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
0668         {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
0669         {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
0670         {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
0671         {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
0672         {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
0673         {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
0674         {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
0675         {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
0676         {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
0677         {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
0678         {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
0679         {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
0680         {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
0681         {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
0682         {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
0683         {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
0684         {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
0685         {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
0686         {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
0687         {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
0688         {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
0689         {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
0690         {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
0691         {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
0692         {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
0693         {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
0694         {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
0695         {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
0696         {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
0697         {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
0698         {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
0699         {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
0700         {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
0701         {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
0702         {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0},
0703         /* Camera should start to capture now. */
0704         {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 0},
0705         {{0x1b, 0x32, 0x26, 0x00, 0x00, 0x00}, 0},
0706         {{0x1d, 0x25, 0x10, 0x20, 0xab, 0x00}, 0},
0707     };
0708 
0709     r = run_start_commands(gspca_dev, genius_vcam_live_start_commands,
0710                   ARRAY_SIZE(genius_vcam_live_start_commands));
0711     if (r < 0)
0712         return r;
0713 
0714     if (sd->gain)
0715         set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
0716 
0717     return r;
0718 }
0719 
0720 static int start_vivitar_cam(struct gspca_dev *gspca_dev)
0721 {
0722     struct init_command vivitar_start_commands[] = {
0723         {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
0724         {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
0725         {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
0726         {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4},
0727         {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
0728         {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
0729         {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
0730         {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
0731         {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
0732         {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4},
0733         /*
0734          * Above is changed from OEM 0x0b. Fixes Bayer tiling.
0735          * Presumably gives a vertical shift of one row.
0736          */
0737         {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
0738         /* Above seems to do horizontal shift. */
0739         {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
0740         {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
0741         {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
0742         {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
0743         {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
0744         {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
0745         /* Above three commands seem to relate to brightness. */
0746         {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
0747         {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
0748         {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
0749         {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1},
0750         {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1},
0751         {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1},
0752         {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1},
0753         {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
0754         {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1},
0755         {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1},
0756         {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1},
0757         {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1},
0758         {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1},
0759         {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1},
0760         {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1},
0761         {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1},
0762         {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
0763         {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1},
0764         {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1},
0765         {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1},
0766         {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1},
0767         {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1},
0768         {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1},
0769         {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1},
0770         {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1},
0771         {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1},
0772         {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1},
0773         {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1},
0774         {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1},
0775         {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1},
0776         {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1},
0777         {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1},
0778         {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1},
0779         {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1},
0780         {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1},
0781         {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1},
0782         {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1},
0783         /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
0784         {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
0785         {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */
0786         {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
0787         {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1},
0788         {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
0789         {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1},
0790         {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
0791         {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1},
0792         /* Above is brightness; OEM driver setting is 0x10 */
0793         {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
0794         {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
0795         {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}
0796     };
0797 
0798     return run_start_commands(gspca_dev, vivitar_start_commands,
0799                   ARRAY_SIZE(vivitar_start_commands));
0800 }
0801 
0802 static int sd_start(struct gspca_dev *gspca_dev)
0803 {
0804     struct sd *sd = (struct sd *) gspca_dev;
0805     int err_code;
0806 
0807     sd->sof_read = 0;
0808 
0809     switch (sd->model) {
0810     case 0x7005:
0811         err_code = start_genius_cam(gspca_dev);
0812         break;
0813     case 0x7003:
0814         err_code = start_genius_videocam_live(gspca_dev);
0815         break;
0816     case 0x8001:
0817         err_code = start_spy_cam(gspca_dev);
0818         break;
0819     case 0x8003:
0820         err_code = start_cif_cam(gspca_dev);
0821         break;
0822     case 0x8008:
0823         err_code = start_ms350_cam(gspca_dev);
0824         break;
0825     case 0x800a:
0826         err_code = start_vivitar_cam(gspca_dev);
0827         break;
0828     default:
0829         pr_err("Starting unknown camera, please report this\n");
0830         return -ENXIO;
0831     }
0832 
0833     sd->avg_lum = -1;
0834 
0835     return err_code;
0836 }
0837 
0838 static void sd_stopN(struct gspca_dev *gspca_dev)
0839 {
0840     int result;
0841     __u8 data[6];
0842 
0843     result = sn9c2028_read1(gspca_dev);
0844     if (result < 0)
0845         gspca_err(gspca_dev, "Camera Stop read failed\n");
0846 
0847     memset(data, 0, 6);
0848     data[0] = 0x14;
0849     result = sn9c2028_command(gspca_dev, data);
0850     if (result < 0)
0851         gspca_err(gspca_dev, "Camera Stop command failed\n");
0852 }
0853 
0854 static void do_autogain(struct gspca_dev *gspca_dev, int avg_lum)
0855 {
0856     struct sd *sd = (struct sd *) gspca_dev;
0857     s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain);
0858 
0859     if (avg_lum == -1)
0860         return;
0861 
0862     if (avg_lum < MIN_AVG_LUM) {
0863         if (cur_gain == sd->gain->maximum)
0864             return;
0865         cur_gain++;
0866         v4l2_ctrl_s_ctrl(sd->gain, cur_gain);
0867     }
0868     if (avg_lum > MAX_AVG_LUM) {
0869         if (cur_gain == sd->gain->minimum)
0870             return;
0871         cur_gain--;
0872         v4l2_ctrl_s_ctrl(sd->gain, cur_gain);
0873     }
0874 
0875 }
0876 
0877 static void sd_dqcallback(struct gspca_dev *gspca_dev)
0878 {
0879     struct sd *sd = (struct sd *) gspca_dev;
0880 
0881     if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain))
0882         return;
0883 
0884     do_autogain(gspca_dev, sd->avg_lum);
0885 }
0886 
0887 /* Include sn9c2028 sof detection functions */
0888 #include "sn9c2028.h"
0889 
0890 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0891             __u8 *data,         /* isoc packet */
0892             int len)            /* iso packet length */
0893 {
0894     unsigned char *sof;
0895 
0896     sof = sn9c2028_find_sof(gspca_dev, data, len);
0897     if (sof) {
0898         int n;
0899 
0900         /* finish decoding current frame */
0901         n = sof - data;
0902         if (n > sizeof sn9c2028_sof_marker)
0903             n -= sizeof sn9c2028_sof_marker;
0904         else
0905             n = 0;
0906         gspca_frame_add(gspca_dev, LAST_PACKET, data, n);
0907         /* Start next frame. */
0908         gspca_frame_add(gspca_dev, FIRST_PACKET,
0909             sn9c2028_sof_marker, sizeof sn9c2028_sof_marker);
0910         len -= sof - data;
0911         data = sof;
0912     }
0913     gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
0914 }
0915 
0916 /* sub-driver description */
0917 static const struct sd_desc sd_desc = {
0918     .name = MODULE_NAME,
0919     .config = sd_config,
0920     .init = sd_init,
0921     .init_controls = sd_init_controls,
0922     .start = sd_start,
0923     .stopN = sd_stopN,
0924     .dq_callback = sd_dqcallback,
0925     .pkt_scan = sd_pkt_scan,
0926 };
0927 
0928 /* -- module initialisation -- */
0929 static const struct usb_device_id device_table[] = {
0930     {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */
0931     {USB_DEVICE(0x0458, 0x7003)}, /* Genius Videocam Live v2  */
0932     /* The Genius Smart is untested. I can't find an owner ! */
0933     /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */
0934     {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */
0935     {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */
0936     /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */
0937     {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */
0938     {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */
0939     {}
0940 };
0941 MODULE_DEVICE_TABLE(usb, device_table);
0942 
0943 /* -- device connect -- */
0944 static int sd_probe(struct usb_interface *intf,
0945             const struct usb_device_id *id)
0946 {
0947     return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
0948                    THIS_MODULE);
0949 }
0950 
0951 static struct usb_driver sd_driver = {
0952     .name = MODULE_NAME,
0953     .id_table = device_table,
0954     .probe = sd_probe,
0955     .disconnect = gspca_disconnect,
0956 #ifdef CONFIG_PM
0957     .suspend = gspca_suspend,
0958     .resume = gspca_resume,
0959     .reset_resume = gspca_resume,
0960 #endif
0961 };
0962 
0963 module_usb_driver(sd_driver);