Version:  2.0.40 2.2.26 2.4.37 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16

Linux/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 
 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[] = {
 45         {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
 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[] = {
 54         {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
 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),
 72                         USB_REQ_GET_CONFIGURATION,
 73                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 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),
 90                         USB_REQ_GET_STATUS,
 91                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 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),
106                         USB_REQ_GET_STATUS,
107                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
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");
195                 cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
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                 PERR("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                 PERR("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);
736 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us