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