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