Merge branch 'imx-for-2.6.38' of git://git.pengutronix.de/git/ukl/linux-2.6 into...
[pandora-kernel.git] / drivers / media / video / 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 MODULE_NAME "sn9c2028"
22
23 #include "gspca.h"
24
25 MODULE_AUTHOR("Theodore Kilgore");
26 MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver");
27 MODULE_LICENSE("GPL");
28
29 /* specific webcam descriptor */
30 struct sd {
31         struct gspca_dev gspca_dev;  /* !! must be the first item */
32         u8 sof_read;
33         u16 model;
34 };
35
36 struct init_command {
37         unsigned char instruction[6];
38         unsigned char to_read; /* length to read. 0 means no reply requested */
39 };
40
41 /* V4L2 controls supported by the driver */
42 static const struct ctrl sd_ctrls[] = {
43 };
44
45 /* How to change the resolution of any of the VGA cams is unknown */
46 static const struct v4l2_pix_format vga_mode[] = {
47         {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
48                 .bytesperline = 640,
49                 .sizeimage = 640 * 480 * 3 / 4,
50                 .colorspace = V4L2_COLORSPACE_SRGB,
51                 .priv = 0},
52 };
53
54 /* No way to change the resolution of the CIF cams is known */
55 static const struct v4l2_pix_format cif_mode[] = {
56         {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
57                 .bytesperline = 352,
58                 .sizeimage = 352 * 288 * 3 / 4,
59                 .colorspace = V4L2_COLORSPACE_SRGB,
60                 .priv = 0},
61 };
62
63 /* the bytes to write are in gspca_dev->usb_buf */
64 static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
65 {
66         int rc;
67
68         PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0],
69                command[1], command[2], command[3], command[4], command[5]);
70
71         memcpy(gspca_dev->usb_buf, command, 6);
72         rc = usb_control_msg(gspca_dev->dev,
73                         usb_sndctrlpipe(gspca_dev->dev, 0),
74                         USB_REQ_GET_CONFIGURATION,
75                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
76                         2, 0, gspca_dev->usb_buf, 6, 500);
77         if (rc < 0) {
78                 err("command write [%02x] error %d",
79                                 gspca_dev->usb_buf[0], rc);
80                 return rc;
81         }
82
83         return 0;
84 }
85
86 static int sn9c2028_read1(struct gspca_dev *gspca_dev)
87 {
88         int rc;
89
90         rc = usb_control_msg(gspca_dev->dev,
91                         usb_rcvctrlpipe(gspca_dev->dev, 0),
92                         USB_REQ_GET_STATUS,
93                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
94                         1, 0, gspca_dev->usb_buf, 1, 500);
95         if (rc != 1) {
96                 err("read1 error %d", rc);
97                 return (rc < 0) ? rc : -EIO;
98         }
99         PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
100         return gspca_dev->usb_buf[0];
101 }
102
103 static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
104 {
105         int rc;
106         rc = usb_control_msg(gspca_dev->dev,
107                         usb_rcvctrlpipe(gspca_dev->dev, 0),
108                         USB_REQ_GET_STATUS,
109                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
110                         4, 0, gspca_dev->usb_buf, 4, 500);
111         if (rc != 4) {
112                 err("read4 error %d", rc);
113                 return (rc < 0) ? rc : -EIO;
114         }
115         memcpy(reading, gspca_dev->usb_buf, 4);
116         PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0],
117                reading[1], reading[2], reading[3]);
118         return rc;
119 }
120
121 static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
122 {
123         int i, status;
124         __u8 reading[4];
125
126         status = sn9c2028_command(gspca_dev, command);
127         if (status < 0)
128                 return status;
129
130         status = -1;
131         for (i = 0; i < 256 && status < 2; i++)
132                 status = sn9c2028_read1(gspca_dev);
133         if (status != 2) {
134                 err("long command status read error %d", status);
135                 return (status < 0) ? status : -EIO;
136         }
137
138         memset(reading, 0, 4);
139         status = sn9c2028_read4(gspca_dev, reading);
140         if (status < 0)
141                 return status;
142
143         /* in general, the first byte of the response is the first byte of
144          * the command, or'ed with 8 */
145         status = sn9c2028_read1(gspca_dev);
146         if (status < 0)
147                 return status;
148
149         return 0;
150 }
151
152 static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command)
153 {
154         int err_code;
155
156         err_code = sn9c2028_command(gspca_dev, command);
157         if (err_code < 0)
158                 return err_code;
159
160         err_code = sn9c2028_read1(gspca_dev);
161         if (err_code < 0)
162                 return err_code;
163
164         return 0;
165 }
166
167 /* this function is called at probe time */
168 static int sd_config(struct gspca_dev *gspca_dev,
169                      const struct usb_device_id *id)
170 {
171         struct sd *sd = (struct sd *) gspca_dev;
172         struct cam *cam = &gspca_dev->cam;
173
174         PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)",
175                id->idVendor, id->idProduct);
176
177         sd->model = id->idProduct;
178
179         switch (sd->model) {
180         case 0x7005:
181                 PDEBUG(D_PROBE, "Genius Smart 300 camera");
182                 break;
183         case 0x8000:
184                 PDEBUG(D_PROBE, "DC31VC");
185                 break;
186         case 0x8001:
187                 PDEBUG(D_PROBE, "Spy camera");
188                 break;
189         case 0x8003:
190                 PDEBUG(D_PROBE, "CIF camera");
191                 break;
192         case 0x8008:
193                 PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera");
194                 break;
195         case 0x800a:
196                 PDEBUG(D_PROBE, "Vivitar 3350b type camera");
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 int start_spy_cam(struct gspca_dev *gspca_dev)
254 {
255         struct init_command spy_start_commands[] = {
256                 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
257                 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
258                 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
259                 {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
260                 {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
261                 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
262                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width  352 */
263                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */
264                 /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */
265                 {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4},
266                 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/
267                 /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */
268                 {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
269                 /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */
270                 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
271                 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
272                 /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */
273                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
274                 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
275                 /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */
276                 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
277                 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
278                 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
279                 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
280                 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
281                 {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4},
282                 {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/
283                 /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
284                 {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
285                 /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */
286                 {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
287                 {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */
288                 {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4},
289                 /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
290                 {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4},
291                 {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4},
292                 {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4},
293                 {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
294                 {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4},
295                 {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4},
296                 {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4},
297                 /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */
298                 /* brightness or gain. 0 is default. 4 is good
299                  * indoors at night with incandescent lighting */
300                 {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4},
301                 {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/
302                 {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4},
303                 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
304                 {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4},
305                 {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4},
306                 /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */
307                 {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */
308                 /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */
309                 {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1},
310                 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */
311                 /* Camera should start to capture now. */
312         };
313
314         return run_start_commands(gspca_dev, spy_start_commands,
315                                   ARRAY_SIZE(spy_start_commands));
316 }
317
318 static int start_cif_cam(struct gspca_dev *gspca_dev)
319 {
320         struct init_command cif_start_commands[] = {
321                 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
322                 /* The entire sequence below seems redundant */
323                 /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
324                 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
325                 {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4},
326                 {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4},
327                 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
328                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width?
329                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height?
330                 {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
331                 {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
332                 {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
333                 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
334                 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
335                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
336                 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
337                 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
338                 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
339                 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
340                 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
341                 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/
342                 {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1},
343                 {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1},
344                 {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1},
345                 {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
346                 {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1},
347                 {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1},
348                 {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1},
349                 {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1},
350                 {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
351                 {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1},
352                 {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1},
353                 {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1},
354                 {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1},
355                 {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1},
356                 {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1},
357                 {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1},
358                 {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1},
359                 {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1},
360                 {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
361                 {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1},
362                 {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1},
363                 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
364                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */
365                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */
366                 /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
367                  * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing
368                  * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */
369                 /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
370                  * causes subsampling
371                  * but not a change in the resolution setting! */
372                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
373                 {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4},
374                 {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4},
375                 {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4},
376                 {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
377                 {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1},
378                 {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1},
379                 {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
380                 {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1},
381                 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
382                 {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
383                 {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
384                 {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1},
385                 {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
386                 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
387                 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */
388                 /* Camera should start to capture now. */
389         };
390
391         return run_start_commands(gspca_dev, cif_start_commands,
392                                   ARRAY_SIZE(cif_start_commands));
393 }
394
395 static int start_ms350_cam(struct gspca_dev *gspca_dev)
396 {
397         struct init_command ms350_start_commands[] = {
398                 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
399                 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
400                 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
401                 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
402                 {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
403                 {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
404                 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
405                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
406                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
407                 {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
408                 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4},
409                 {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
410                 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
411                 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
412                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
413                 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
414                 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
415                 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
416                 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
417                 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
418                 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
419                 {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4},
420                 {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4},
421                 {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4},
422                 {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4},
423                 {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4},
424                 {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4},
425                 {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4},
426                 {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4},
427                 {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4},
428                 {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4},
429                 {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4},
430                 {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
431                 {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4},
432                 {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4},
433                 {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4},
434                 {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4},
435                 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
436                 {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4},
437                 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
438                 {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4},
439                 {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4},
440                 {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4},
441                 {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4},
442                 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width  */
443                 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */
444                 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */
445                 {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
446                 {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */
447                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
448                 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
449                 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
450                 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
451                 {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1},
452                 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
453                 {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1},
454                 {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1},
455                 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0},
456                 /* Camera should start to capture now. */
457         };
458
459         return run_start_commands(gspca_dev, ms350_start_commands,
460                                   ARRAY_SIZE(ms350_start_commands));
461 }
462
463 static int start_genius_cam(struct gspca_dev *gspca_dev)
464 {
465         struct init_command genius_start_commands[] = {
466                 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
467                 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
468                 {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
469                 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
470                 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
471                 /* "preliminary" width and height settings */
472                 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
473                 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
474                 {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
475                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
476                 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
477                 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
478                 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
479                 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
480                 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
481                 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
482                 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
483                 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
484                 {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
485                 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
486                 {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
487                 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
488                 {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
489                 {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
490                 {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
491                 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
492                 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
493                 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
494                 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
495                 {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
496                 {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
497                 {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
498                 {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
499                 {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
500                 {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
501                 {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
502                 {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
503                 {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
504                 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */
505                 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */
506                 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
507                 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
508                 {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
509                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
510                 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
511                 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
512                 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
513                 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
514                 {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
515                 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
516                 {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
517                 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
518                 {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
519                 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
520                 {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
521                 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
522                 {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
523                 {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
524                 {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
525                 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
526                 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
527                 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}
528                 /* Camera should start to capture now. */
529         };
530
531         return run_start_commands(gspca_dev, genius_start_commands,
532                                   ARRAY_SIZE(genius_start_commands));
533 }
534
535 static int start_vivitar_cam(struct gspca_dev *gspca_dev)
536 {
537         struct init_command vivitar_start_commands[] = {
538                 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
539                 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
540                 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
541                 {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4},
542                 {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
543                 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
544                 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
545                 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
546                 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
547                 {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4},
548                 /*
549                  * Above is changed from OEM 0x0b. Fixes Bayer tiling.
550                  * Presumably gives a vertical shift of one row.
551                  */
552                 {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
553                 /* Above seems to do horizontal shift. */
554                 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
555                 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
556                 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
557                 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
558                 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
559                 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
560                 /* Above three commands seem to relate to brightness. */
561                 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
562                 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
563                 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
564                 {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1},
565                 {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1},
566                 {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1},
567                 {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1},
568                 {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
569                 {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1},
570                 {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1},
571                 {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1},
572                 {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1},
573                 {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1},
574                 {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1},
575                 {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1},
576                 {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1},
577                 {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
578                 {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1},
579                 {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1},
580                 {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1},
581                 {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1},
582                 {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1},
583                 {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1},
584                 {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1},
585                 {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1},
586                 {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1},
587                 {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1},
588                 {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1},
589                 {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1},
590                 {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1},
591                 {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1},
592                 {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1},
593                 {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1},
594                 {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1},
595                 {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1},
596                 {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1},
597                 {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1},
598                 /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
599                 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
600                 {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */
601                 {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
602                 {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1},
603                 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
604                 {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1},
605                 {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
606                 {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1},
607                 /* Above is brightness; OEM driver setting is 0x10 */
608                 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
609                 {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
610                 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}
611         };
612
613         return run_start_commands(gspca_dev, vivitar_start_commands,
614                                   ARRAY_SIZE(vivitar_start_commands));
615 }
616
617 static int sd_start(struct gspca_dev *gspca_dev)
618 {
619         struct sd *sd = (struct sd *) gspca_dev;
620         int err_code;
621
622         sd->sof_read = 0;
623
624         switch (sd->model) {
625         case 0x7005:
626                 err_code = start_genius_cam(gspca_dev);
627                 break;
628         case 0x8001:
629                 err_code = start_spy_cam(gspca_dev);
630                 break;
631         case 0x8003:
632                 err_code = start_cif_cam(gspca_dev);
633                 break;
634         case 0x8008:
635                 err_code = start_ms350_cam(gspca_dev);
636                 break;
637         case 0x800a:
638                 err_code = start_vivitar_cam(gspca_dev);
639                 break;
640         default:
641                 err("Starting unknown camera, please report this");
642                 return -ENXIO;
643         }
644
645         return err_code;
646 }
647
648 static void sd_stopN(struct gspca_dev *gspca_dev)
649 {
650         int result;
651         __u8 data[6];
652
653         result = sn9c2028_read1(gspca_dev);
654         if (result < 0)
655                 PDEBUG(D_ERR, "Camera Stop read failed");
656
657         memset(data, 0, 6);
658         data[0] = 0x14;
659         result = sn9c2028_command(gspca_dev, data);
660         if (result < 0)
661                 PDEBUG(D_ERR, "Camera Stop command failed");
662 }
663
664 /* Include sn9c2028 sof detection functions */
665 #include "sn9c2028.h"
666
667 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
668                         __u8 *data,                     /* isoc packet */
669                         int len)                        /* iso packet length */
670 {
671         unsigned char *sof;
672
673         sof = sn9c2028_find_sof(gspca_dev, data, len);
674         if (sof) {
675                 int n;
676
677                 /* finish decoding current frame */
678                 n = sof - data;
679                 if (n > sizeof sn9c2028_sof_marker)
680                         n -= sizeof sn9c2028_sof_marker;
681                 else
682                         n = 0;
683                 gspca_frame_add(gspca_dev, LAST_PACKET, data, n);
684                 /* Start next frame. */
685                 gspca_frame_add(gspca_dev, FIRST_PACKET,
686                         sn9c2028_sof_marker, sizeof sn9c2028_sof_marker);
687                 len -= sof - data;
688                 data = sof;
689         }
690         gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
691 }
692
693 /* sub-driver description */
694 static const struct sd_desc sd_desc = {
695         .name = MODULE_NAME,
696         .ctrls = sd_ctrls,
697         .nctrls = ARRAY_SIZE(sd_ctrls),
698         .config = sd_config,
699         .init = sd_init,
700         .start = sd_start,
701         .stopN = sd_stopN,
702         .pkt_scan = sd_pkt_scan,
703 };
704
705 /* -- module initialisation -- */
706 static const __devinitdata struct usb_device_id device_table[] = {
707         {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */
708         /* The Genius Smart is untested. I can't find an owner ! */
709         /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */
710         {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */
711         {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */
712         /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */
713         {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */
714         {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */
715         {}
716 };
717 MODULE_DEVICE_TABLE(usb, device_table);
718
719 /* -- device connect -- */
720 static int sd_probe(struct usb_interface *intf,
721                         const struct usb_device_id *id)
722 {
723         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
724                                THIS_MODULE);
725 }
726
727 static struct usb_driver sd_driver = {
728         .name = MODULE_NAME,
729         .id_table = device_table,
730         .probe = sd_probe,
731         .disconnect = gspca_disconnect,
732 #ifdef CONFIG_PM
733         .suspend = gspca_suspend,
734         .resume = gspca_resume,
735 #endif
736 };
737
738 /* -- module insert / remove -- */
739 static int __init sd_mod_init(void)
740 {
741         return usb_register(&sd_driver);
742 }
743
744 static void __exit sd_mod_exit(void)
745 {
746         usb_deregister(&sd_driver);
747 }
748
749 module_init(sd_mod_init);
750 module_exit(sd_mod_exit);