Avoid beyond bounds copy while caching ACL
[zen-stable.git] / drivers / media / video / gspca / sunplus.c
blobc80f0c0c75b6e6905bde114d148470cf6d95ee5c
1 /*
2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24 #define MODULE_NAME "sunplus"
26 #include "gspca.h"
27 #include "jpeg.h"
29 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
31 MODULE_LICENSE("GPL");
33 /* specific webcam descriptor */
34 struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
37 s8 brightness;
38 u8 contrast;
39 u8 colors;
40 u8 autogain;
41 u8 quality;
42 #define QUALITY_MIN 70
43 #define QUALITY_MAX 95
44 #define QUALITY_DEF 85
46 u8 bridge;
47 #define BRIDGE_SPCA504 0
48 #define BRIDGE_SPCA504B 1
49 #define BRIDGE_SPCA504C 2
50 #define BRIDGE_SPCA533 3
51 #define BRIDGE_SPCA536 4
52 u8 subtype;
53 #define AiptekMiniPenCam13 1
54 #define LogitechClickSmart420 2
55 #define LogitechClickSmart820 3
56 #define MegapixV4 4
57 #define MegaImageVI 5
59 u8 jpeg_hdr[JPEG_HDR_SZ];
62 /* V4L2 controls supported by the driver */
63 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
69 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
72 static const struct ctrl sd_ctrls[] = {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = -128,
79 .maximum = 127,
80 .step = 1,
81 #define BRIGHTNESS_DEF 0
82 .default_value = BRIGHTNESS_DEF,
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Contrast",
92 .minimum = 0,
93 .maximum = 0xff,
94 .step = 1,
95 #define CONTRAST_DEF 0x20
96 .default_value = CONTRAST_DEF,
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Color",
106 .minimum = 0,
107 .maximum = 0xff,
108 .step = 1,
109 #define COLOR_DEF 0x1a
110 .default_value = COLOR_DEF,
112 .set = sd_setcolors,
113 .get = sd_getcolors,
117 .id = V4L2_CID_AUTOGAIN,
118 .type = V4L2_CTRL_TYPE_BOOLEAN,
119 .name = "Auto Gain",
120 .minimum = 0,
121 .maximum = 1,
122 .step = 1,
123 #define AUTOGAIN_DEF 1
124 .default_value = AUTOGAIN_DEF,
126 .set = sd_setautogain,
127 .get = sd_getautogain,
131 static const struct v4l2_pix_format vga_mode[] = {
132 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133 .bytesperline = 320,
134 .sizeimage = 320 * 240 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
136 .priv = 2},
137 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
138 .bytesperline = 640,
139 .sizeimage = 640 * 480 * 3 / 8 + 590,
140 .colorspace = V4L2_COLORSPACE_JPEG,
141 .priv = 1},
144 static const struct v4l2_pix_format custom_mode[] = {
145 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
146 .bytesperline = 320,
147 .sizeimage = 320 * 240 * 3 / 8 + 590,
148 .colorspace = V4L2_COLORSPACE_JPEG,
149 .priv = 2},
150 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
151 .bytesperline = 464,
152 .sizeimage = 464 * 480 * 3 / 8 + 590,
153 .colorspace = V4L2_COLORSPACE_JPEG,
154 .priv = 1},
157 static const struct v4l2_pix_format vga_mode2[] = {
158 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
159 .bytesperline = 176,
160 .sizeimage = 176 * 144 * 3 / 8 + 590,
161 .colorspace = V4L2_COLORSPACE_JPEG,
162 .priv = 4},
163 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
164 .bytesperline = 320,
165 .sizeimage = 320 * 240 * 3 / 8 + 590,
166 .colorspace = V4L2_COLORSPACE_JPEG,
167 .priv = 3},
168 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
169 .bytesperline = 352,
170 .sizeimage = 352 * 288 * 3 / 8 + 590,
171 .colorspace = V4L2_COLORSPACE_JPEG,
172 .priv = 2},
173 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
174 .bytesperline = 640,
175 .sizeimage = 640 * 480 * 3 / 8 + 590,
176 .colorspace = V4L2_COLORSPACE_JPEG,
177 .priv = 1},
180 #define SPCA50X_OFFSET_DATA 10
181 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
182 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
183 #define SPCA504_PCCAM600_OFFSET_MODE 5
184 #define SPCA504_PCCAM600_OFFSET_DATA 14
185 /* Frame packet header offsets for the spca533 */
186 #define SPCA533_OFFSET_DATA 16
187 #define SPCA533_OFFSET_FRAMSEQ 15
188 /* Frame packet header offsets for the spca536 */
189 #define SPCA536_OFFSET_DATA 4
190 #define SPCA536_OFFSET_FRAMSEQ 1
192 struct cmd {
193 u8 req;
194 u16 val;
195 u16 idx;
198 /* Initialisation data for the Creative PC-CAM 600 */
199 static const struct cmd spca504_pccam600_init_data[] = {
200 /* {0xa0, 0x0000, 0x0503}, * capture mode */
201 {0x00, 0x0000, 0x2000},
202 {0x00, 0x0013, 0x2301},
203 {0x00, 0x0003, 0x2000},
204 {0x00, 0x0001, 0x21ac},
205 {0x00, 0x0001, 0x21a6},
206 {0x00, 0x0000, 0x21a7}, /* brightness */
207 {0x00, 0x0020, 0x21a8}, /* contrast */
208 {0x00, 0x0001, 0x21ac}, /* sat/hue */
209 {0x00, 0x0000, 0x21ad}, /* hue */
210 {0x00, 0x001a, 0x21ae}, /* saturation */
211 {0x00, 0x0002, 0x21a3}, /* gamma */
212 {0x30, 0x0154, 0x0008},
213 {0x30, 0x0004, 0x0006},
214 {0x30, 0x0258, 0x0009},
215 {0x30, 0x0004, 0x0000},
216 {0x30, 0x0093, 0x0004},
217 {0x30, 0x0066, 0x0005},
218 {0x00, 0x0000, 0x2000},
219 {0x00, 0x0013, 0x2301},
220 {0x00, 0x0003, 0x2000},
221 {0x00, 0x0013, 0x2301},
222 {0x00, 0x0003, 0x2000},
225 /* Creative PC-CAM 600 specific open data, sent before using the
226 * generic initialisation data from spca504_open_data.
228 static const struct cmd spca504_pccam600_open_data[] = {
229 {0x00, 0x0001, 0x2501},
230 {0x20, 0x0500, 0x0001}, /* snapshot mode */
231 {0x00, 0x0003, 0x2880},
232 {0x00, 0x0001, 0x2881},
235 /* Initialisation data for the logitech clicksmart 420 */
236 static const struct cmd spca504A_clicksmart420_init_data[] = {
237 /* {0xa0, 0x0000, 0x0503}, * capture mode */
238 {0x00, 0x0000, 0x2000},
239 {0x00, 0x0013, 0x2301},
240 {0x00, 0x0003, 0x2000},
241 {0x00, 0x0001, 0x21ac},
242 {0x00, 0x0001, 0x21a6},
243 {0x00, 0x0000, 0x21a7}, /* brightness */
244 {0x00, 0x0020, 0x21a8}, /* contrast */
245 {0x00, 0x0001, 0x21ac}, /* sat/hue */
246 {0x00, 0x0000, 0x21ad}, /* hue */
247 {0x00, 0x001a, 0x21ae}, /* saturation */
248 {0x00, 0x0002, 0x21a3}, /* gamma */
249 {0x30, 0x0004, 0x000a},
250 {0xb0, 0x0001, 0x0000},
252 {0xa1, 0x0080, 0x0001},
253 {0x30, 0x0049, 0x0000},
254 {0x30, 0x0060, 0x0005},
255 {0x0c, 0x0004, 0x0000},
256 {0x00, 0x0000, 0x0000},
257 {0x00, 0x0000, 0x2000},
258 {0x00, 0x0013, 0x2301},
259 {0x00, 0x0003, 0x2000},
262 /* clicksmart 420 open data ? */
263 static const struct cmd spca504A_clicksmart420_open_data[] = {
264 {0x00, 0x0001, 0x2501},
265 {0x20, 0x0502, 0x0000},
266 {0x06, 0x0000, 0x0000},
267 {0x00, 0x0004, 0x2880},
268 {0x00, 0x0001, 0x2881},
270 {0xa0, 0x0000, 0x0503},
273 static const u8 qtable_creative_pccam[2][64] = {
274 { /* Q-table Y-components */
275 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
276 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
277 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
278 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
279 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
280 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
281 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
282 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
283 { /* Q-table C-components */
284 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
285 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
286 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
287 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
288 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
289 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
290 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
291 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
294 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
295 * except for one byte. Possibly a typo?
296 * NWG: 18/05/2003.
298 static const u8 qtable_spca504_default[2][64] = {
299 { /* Q-table Y-components */
300 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
301 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
302 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
303 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
304 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
305 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
306 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
307 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
309 { /* Q-table C-components */
310 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
311 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
312 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
313 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
314 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
315 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
316 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
317 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
320 /* read <len> bytes to gspca_dev->usb_buf */
321 static void reg_r(struct gspca_dev *gspca_dev,
322 u8 req,
323 u16 index,
324 u16 len)
326 int ret;
328 #ifdef GSPCA_DEBUG
329 if (len > USB_BUF_SZ) {
330 pr_err("reg_r: buffer overflow\n");
331 return;
333 #endif
334 if (gspca_dev->usb_err < 0)
335 return;
336 ret = usb_control_msg(gspca_dev->dev,
337 usb_rcvctrlpipe(gspca_dev->dev, 0),
338 req,
339 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
340 0, /* value */
341 index,
342 len ? gspca_dev->usb_buf : NULL, len,
343 500);
344 if (ret < 0) {
345 pr_err("reg_r err %d\n", ret);
346 gspca_dev->usb_err = ret;
350 /* write one byte */
351 static void reg_w_1(struct gspca_dev *gspca_dev,
352 u8 req,
353 u16 value,
354 u16 index,
355 u16 byte)
357 int ret;
359 if (gspca_dev->usb_err < 0)
360 return;
361 gspca_dev->usb_buf[0] = byte;
362 ret = usb_control_msg(gspca_dev->dev,
363 usb_sndctrlpipe(gspca_dev->dev, 0),
364 req,
365 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
366 value, index,
367 gspca_dev->usb_buf, 1,
368 500);
369 if (ret < 0) {
370 pr_err("reg_w_1 err %d\n", ret);
371 gspca_dev->usb_err = ret;
375 /* write req / index / value */
376 static void reg_w_riv(struct gspca_dev *gspca_dev,
377 u8 req, u16 index, u16 value)
379 struct usb_device *dev = gspca_dev->dev;
380 int ret;
382 if (gspca_dev->usb_err < 0)
383 return;
384 ret = usb_control_msg(dev,
385 usb_sndctrlpipe(dev, 0),
386 req,
387 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
388 value, index, NULL, 0, 500);
389 if (ret < 0) {
390 pr_err("reg_w_riv err %d\n", ret);
391 gspca_dev->usb_err = ret;
392 return;
394 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
395 req, index, value);
398 static void write_vector(struct gspca_dev *gspca_dev,
399 const struct cmd *data, int ncmds)
401 while (--ncmds >= 0) {
402 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
403 data++;
407 static void setup_qtable(struct gspca_dev *gspca_dev,
408 const u8 qtable[2][64])
410 int i;
412 /* loop over y components */
413 for (i = 0; i < 64; i++)
414 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
416 /* loop over c components */
417 for (i = 0; i < 64; i++)
418 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
421 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
422 u8 req, u16 idx, u16 val)
424 reg_w_riv(gspca_dev, req, idx, val);
425 reg_r(gspca_dev, 0x01, 0x0001, 1);
426 PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
427 reg_w_riv(gspca_dev, req, idx, val);
429 msleep(200);
430 reg_r(gspca_dev, 0x01, 0x0001, 1);
431 PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
434 #ifdef GSPCA_DEBUG
435 static void spca504_read_info(struct gspca_dev *gspca_dev)
437 int i;
438 u8 info[6];
440 for (i = 0; i < 6; i++) {
441 reg_r(gspca_dev, 0, i, 1);
442 info[i] = gspca_dev->usb_buf[0];
444 PDEBUG(D_STREAM,
445 "Read info: %d %d %d %d %d %d."
446 " Should be 1,0,2,2,0,0",
447 info[0], info[1], info[2],
448 info[3], info[4], info[5]);
450 #endif
452 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
453 u8 req,
454 u16 idx, u16 val, u8 endcode, u8 count)
456 u16 status;
458 reg_w_riv(gspca_dev, req, idx, val);
459 reg_r(gspca_dev, 0x01, 0x0001, 1);
460 if (gspca_dev->usb_err < 0)
461 return;
462 PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
463 gspca_dev->usb_buf[0], endcode);
464 if (!count)
465 return;
466 count = 200;
467 while (--count > 0) {
468 msleep(10);
469 /* gsmart mini2 write a each wait setting 1 ms is enough */
470 /* reg_w_riv(gspca_dev, req, idx, val); */
471 reg_r(gspca_dev, 0x01, 0x0001, 1);
472 status = gspca_dev->usb_buf[0];
473 if (status == endcode) {
474 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
475 status, 200 - count);
476 break;
481 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
483 int count = 10;
485 while (--count > 0) {
486 reg_r(gspca_dev, 0x21, 0, 1);
487 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
488 break;
489 msleep(10);
493 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
495 int count = 50;
497 while (--count > 0) {
498 reg_r(gspca_dev, 0x21, 1, 1);
499 if (gspca_dev->usb_buf[0] != 0) {
500 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
501 reg_r(gspca_dev, 0x21, 1, 1);
502 spca504B_PollingDataReady(gspca_dev);
503 break;
505 msleep(10);
509 #ifdef GSPCA_DEBUG
510 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
512 u8 *data;
514 data = gspca_dev->usb_buf;
515 reg_r(gspca_dev, 0x20, 0, 5);
516 PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
517 data[0], data[1], data[2], data[3], data[4]);
518 reg_r(gspca_dev, 0x23, 0, 64);
519 reg_r(gspca_dev, 0x23, 1, 64);
521 #endif
523 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
525 struct sd *sd = (struct sd *) gspca_dev;
526 u8 Size;
528 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
529 switch (sd->bridge) {
530 case BRIDGE_SPCA533:
531 reg_w_riv(gspca_dev, 0x31, 0, 0);
532 spca504B_WaitCmdStatus(gspca_dev);
533 spca504B_PollingDataReady(gspca_dev);
534 #ifdef GSPCA_DEBUG
535 spca50x_GetFirmware(gspca_dev);
536 #endif
537 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
538 reg_r(gspca_dev, 0x24, 8, 1);
540 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
541 reg_r(gspca_dev, 0x25, 4, 1); /* size */
542 spca504B_PollingDataReady(gspca_dev);
544 /* Init the cam width height with some values get on init ? */
545 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
546 spca504B_WaitCmdStatus(gspca_dev);
547 spca504B_PollingDataReady(gspca_dev);
548 break;
549 default:
550 /* case BRIDGE_SPCA504B: */
551 /* case BRIDGE_SPCA536: */
552 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
553 reg_r(gspca_dev, 0x25, 4, 1); /* size */
554 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
555 reg_r(gspca_dev, 0x27, 0, 1); /* type */
556 spca504B_PollingDataReady(gspca_dev);
557 break;
558 case BRIDGE_SPCA504:
559 Size += 3;
560 if (sd->subtype == AiptekMiniPenCam13) {
561 /* spca504a aiptek */
562 spca504A_acknowledged_command(gspca_dev,
563 0x08, Size, 0,
564 0x80 | (Size & 0x0f), 1);
565 spca504A_acknowledged_command(gspca_dev,
566 1, 3, 0, 0x9f, 0);
567 } else {
568 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
570 break;
571 case BRIDGE_SPCA504C:
572 /* capture mode */
573 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
574 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
575 break;
579 static void spca504_wait_status(struct gspca_dev *gspca_dev)
581 int cnt;
583 cnt = 256;
584 while (--cnt > 0) {
585 /* With this we get the status, when return 0 it's all ok */
586 reg_r(gspca_dev, 0x06, 0x00, 1);
587 if (gspca_dev->usb_buf[0] == 0)
588 return;
589 msleep(10);
593 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
595 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
596 reg_r(gspca_dev, 0x26, 0, 1);
597 spca504B_PollingDataReady(gspca_dev);
600 static void setbrightness(struct gspca_dev *gspca_dev)
602 struct sd *sd = (struct sd *) gspca_dev;
603 u16 reg;
605 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
606 reg_w_riv(gspca_dev, 0x00, reg, sd->brightness);
609 static void setcontrast(struct gspca_dev *gspca_dev)
611 struct sd *sd = (struct sd *) gspca_dev;
612 u16 reg;
614 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
615 reg_w_riv(gspca_dev, 0x00, reg, sd->contrast);
618 static void setcolors(struct gspca_dev *gspca_dev)
620 struct sd *sd = (struct sd *) gspca_dev;
621 u16 reg;
623 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
624 reg_w_riv(gspca_dev, 0x00, reg, sd->colors);
627 static void init_ctl_reg(struct gspca_dev *gspca_dev)
629 struct sd *sd = (struct sd *) gspca_dev;
630 int pollreg = 1;
632 setbrightness(gspca_dev);
633 setcontrast(gspca_dev);
634 setcolors(gspca_dev);
636 switch (sd->bridge) {
637 case BRIDGE_SPCA504:
638 case BRIDGE_SPCA504C:
639 pollreg = 0;
640 /* fall thru */
641 default:
642 /* case BRIDGE_SPCA533: */
643 /* case BRIDGE_SPCA504B: */
644 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
645 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
646 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
647 break;
648 case BRIDGE_SPCA536:
649 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
650 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
651 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
652 break;
654 if (pollreg)
655 spca504B_PollingDataReady(gspca_dev);
658 /* this function is called at probe time */
659 static int sd_config(struct gspca_dev *gspca_dev,
660 const struct usb_device_id *id)
662 struct sd *sd = (struct sd *) gspca_dev;
663 struct cam *cam;
665 cam = &gspca_dev->cam;
667 sd->bridge = id->driver_info >> 8;
668 sd->subtype = id->driver_info;
670 if (sd->subtype == AiptekMiniPenCam13) {
672 /* try to get the firmware as some cam answer 2.0.1.2.2
673 * and should be a spca504b then overwrite that setting */
674 reg_r(gspca_dev, 0x20, 0, 1);
675 switch (gspca_dev->usb_buf[0]) {
676 case 1:
677 break; /* (right bridge/subtype) */
678 case 2:
679 sd->bridge = BRIDGE_SPCA504B;
680 sd->subtype = 0;
681 break;
682 default:
683 return -ENODEV;
687 switch (sd->bridge) {
688 default:
689 /* case BRIDGE_SPCA504B: */
690 /* case BRIDGE_SPCA504: */
691 /* case BRIDGE_SPCA536: */
692 cam->cam_mode = vga_mode;
693 cam->nmodes = ARRAY_SIZE(vga_mode);
694 break;
695 case BRIDGE_SPCA533:
696 cam->cam_mode = custom_mode;
697 if (sd->subtype == MegaImageVI) /* 320x240 only */
698 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
699 else
700 cam->nmodes = ARRAY_SIZE(custom_mode);
701 break;
702 case BRIDGE_SPCA504C:
703 cam->cam_mode = vga_mode2;
704 cam->nmodes = ARRAY_SIZE(vga_mode2);
705 break;
707 sd->brightness = BRIGHTNESS_DEF;
708 sd->contrast = CONTRAST_DEF;
709 sd->colors = COLOR_DEF;
710 sd->autogain = AUTOGAIN_DEF;
711 sd->quality = QUALITY_DEF;
712 return 0;
715 /* this function is called at probe and resume time */
716 static int sd_init(struct gspca_dev *gspca_dev)
718 struct sd *sd = (struct sd *) gspca_dev;
720 switch (sd->bridge) {
721 case BRIDGE_SPCA504B:
722 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
723 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
724 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
725 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
726 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
727 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
728 /* fall thru */
729 case BRIDGE_SPCA533:
730 spca504B_PollingDataReady(gspca_dev);
731 #ifdef GSPCA_DEBUG
732 spca50x_GetFirmware(gspca_dev);
733 #endif
734 break;
735 case BRIDGE_SPCA536:
736 #ifdef GSPCA_DEBUG
737 spca50x_GetFirmware(gspca_dev);
738 #endif
739 reg_r(gspca_dev, 0x00, 0x5002, 1);
740 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
741 reg_r(gspca_dev, 0x24, 0, 1);
742 spca504B_PollingDataReady(gspca_dev);
743 reg_w_riv(gspca_dev, 0x34, 0, 0);
744 spca504B_WaitCmdStatus(gspca_dev);
745 break;
746 case BRIDGE_SPCA504C: /* pccam600 */
747 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
748 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
749 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
750 spca504_wait_status(gspca_dev);
751 if (sd->subtype == LogitechClickSmart420)
752 write_vector(gspca_dev,
753 spca504A_clicksmart420_open_data,
754 ARRAY_SIZE(spca504A_clicksmart420_open_data));
755 else
756 write_vector(gspca_dev, spca504_pccam600_open_data,
757 ARRAY_SIZE(spca504_pccam600_open_data));
758 setup_qtable(gspca_dev, qtable_creative_pccam);
759 break;
760 default:
761 /* case BRIDGE_SPCA504: */
762 PDEBUG(D_STREAM, "Opening SPCA504");
763 if (sd->subtype == AiptekMiniPenCam13) {
764 #ifdef GSPCA_DEBUG
765 spca504_read_info(gspca_dev);
766 #endif
768 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
769 spca504A_acknowledged_command(gspca_dev, 0x24,
770 8, 3, 0x9e, 1);
771 /* Twice sequential need status 0xff->0x9e->0x9d */
772 spca504A_acknowledged_command(gspca_dev, 0x24,
773 8, 3, 0x9e, 0);
775 spca504A_acknowledged_command(gspca_dev, 0x24,
776 0, 0, 0x9d, 1);
777 /******************************/
778 /* spca504a aiptek */
779 spca504A_acknowledged_command(gspca_dev, 0x08,
780 6, 0, 0x86, 1);
781 /* reg_write (dev, 0, 0x2000, 0); */
782 /* reg_write (dev, 0, 0x2883, 1); */
783 /* spca504A_acknowledged_command (gspca_dev, 0x08,
784 6, 0, 0x86, 1); */
785 /* spca504A_acknowledged_command (gspca_dev, 0x24,
786 0, 0, 0x9D, 1); */
787 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
788 /* L92 sno1t.txt */
789 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
790 spca504A_acknowledged_command(gspca_dev, 0x01,
791 0x0f, 0, 0xff, 0);
793 /* setup qtable */
794 reg_w_riv(gspca_dev, 0, 0x2000, 0);
795 reg_w_riv(gspca_dev, 0, 0x2883, 1);
796 setup_qtable(gspca_dev, qtable_spca504_default);
797 break;
799 return gspca_dev->usb_err;
802 static int sd_start(struct gspca_dev *gspca_dev)
804 struct sd *sd = (struct sd *) gspca_dev;
805 int enable;
807 /* create the JPEG header */
808 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
809 0x22); /* JPEG 411 */
810 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
812 if (sd->bridge == BRIDGE_SPCA504B)
813 spca504B_setQtable(gspca_dev);
814 spca504B_SetSizeType(gspca_dev);
815 switch (sd->bridge) {
816 default:
817 /* case BRIDGE_SPCA504B: */
818 /* case BRIDGE_SPCA533: */
819 /* case BRIDGE_SPCA536: */
820 switch (sd->subtype) {
821 case MegapixV4:
822 case LogitechClickSmart820:
823 case MegaImageVI:
824 reg_w_riv(gspca_dev, 0xf0, 0, 0);
825 spca504B_WaitCmdStatus(gspca_dev);
826 reg_r(gspca_dev, 0xf0, 4, 0);
827 spca504B_WaitCmdStatus(gspca_dev);
828 break;
829 default:
830 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
831 spca504B_WaitCmdStatus(gspca_dev);
832 spca504B_PollingDataReady(gspca_dev);
833 break;
835 break;
836 case BRIDGE_SPCA504:
837 if (sd->subtype == AiptekMiniPenCam13) {
838 #ifdef GSPCA_DEBUG
839 spca504_read_info(gspca_dev);
840 #endif
842 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
843 spca504A_acknowledged_command(gspca_dev, 0x24,
844 8, 3, 0x9e, 1);
845 /* Twice sequential need status 0xff->0x9e->0x9d */
846 spca504A_acknowledged_command(gspca_dev, 0x24,
847 8, 3, 0x9e, 0);
848 spca504A_acknowledged_command(gspca_dev, 0x24,
849 0, 0, 0x9d, 1);
850 } else {
851 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
852 #ifdef GSPCA_DEBUG
853 spca504_read_info(gspca_dev);
854 #endif
855 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
856 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
858 spca504B_SetSizeType(gspca_dev);
859 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
860 /* L92 sno1t.txt */
861 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
862 break;
863 case BRIDGE_SPCA504C:
864 if (sd->subtype == LogitechClickSmart420) {
865 write_vector(gspca_dev,
866 spca504A_clicksmart420_init_data,
867 ARRAY_SIZE(spca504A_clicksmart420_init_data));
868 } else {
869 write_vector(gspca_dev, spca504_pccam600_init_data,
870 ARRAY_SIZE(spca504_pccam600_init_data));
872 enable = (sd->autogain ? 0x04 : 0x01);
873 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
874 /* auto exposure */
875 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
876 /* auto whiteness */
878 /* set default exposure compensation and whiteness balance */
879 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
880 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
881 spca504B_SetSizeType(gspca_dev);
882 break;
884 init_ctl_reg(gspca_dev);
885 return gspca_dev->usb_err;
888 static void sd_stopN(struct gspca_dev *gspca_dev)
890 struct sd *sd = (struct sd *) gspca_dev;
892 switch (sd->bridge) {
893 default:
894 /* case BRIDGE_SPCA533: */
895 /* case BRIDGE_SPCA536: */
896 /* case BRIDGE_SPCA504B: */
897 reg_w_riv(gspca_dev, 0x31, 0, 0);
898 spca504B_WaitCmdStatus(gspca_dev);
899 spca504B_PollingDataReady(gspca_dev);
900 break;
901 case BRIDGE_SPCA504:
902 case BRIDGE_SPCA504C:
903 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
905 if (sd->subtype == AiptekMiniPenCam13) {
906 /* spca504a aiptek */
907 /* spca504A_acknowledged_command(gspca_dev, 0x08,
908 6, 0, 0x86, 1); */
909 spca504A_acknowledged_command(gspca_dev, 0x24,
910 0x00, 0x00, 0x9d, 1);
911 spca504A_acknowledged_command(gspca_dev, 0x01,
912 0x0f, 0x00, 0xff, 1);
913 } else {
914 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
915 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
917 break;
921 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
922 u8 *data, /* isoc packet */
923 int len) /* iso packet length */
925 struct sd *sd = (struct sd *) gspca_dev;
926 int i, sof = 0;
927 static u8 ffd9[] = {0xff, 0xd9};
929 /* frames are jpeg 4.1.1 without 0xff escape */
930 switch (sd->bridge) {
931 case BRIDGE_SPCA533:
932 if (data[0] == 0xff) {
933 if (data[1] != 0x01) { /* drop packet */
934 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
935 return;
937 sof = 1;
938 data += SPCA533_OFFSET_DATA;
939 len -= SPCA533_OFFSET_DATA;
940 } else {
941 data += 1;
942 len -= 1;
944 break;
945 case BRIDGE_SPCA536:
946 if (data[0] == 0xff) {
947 sof = 1;
948 data += SPCA536_OFFSET_DATA;
949 len -= SPCA536_OFFSET_DATA;
950 } else {
951 data += 2;
952 len -= 2;
954 break;
955 default:
956 /* case BRIDGE_SPCA504: */
957 /* case BRIDGE_SPCA504B: */
958 switch (data[0]) {
959 case 0xfe: /* start of frame */
960 sof = 1;
961 data += SPCA50X_OFFSET_DATA;
962 len -= SPCA50X_OFFSET_DATA;
963 break;
964 case 0xff: /* drop packet */
965 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
966 return;
967 default:
968 data += 1;
969 len -= 1;
970 break;
972 break;
973 case BRIDGE_SPCA504C:
974 switch (data[0]) {
975 case 0xfe: /* start of frame */
976 sof = 1;
977 data += SPCA504_PCCAM600_OFFSET_DATA;
978 len -= SPCA504_PCCAM600_OFFSET_DATA;
979 break;
980 case 0xff: /* drop packet */
981 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
982 return;
983 default:
984 data += 1;
985 len -= 1;
986 break;
988 break;
990 if (sof) { /* start of frame */
991 gspca_frame_add(gspca_dev, LAST_PACKET,
992 ffd9, 2);
994 /* put the JPEG header in the new frame */
995 gspca_frame_add(gspca_dev, FIRST_PACKET,
996 sd->jpeg_hdr, JPEG_HDR_SZ);
999 /* add 0x00 after 0xff */
1000 i = 0;
1001 do {
1002 if (data[i] == 0xff) {
1003 gspca_frame_add(gspca_dev, INTER_PACKET,
1004 data, i + 1);
1005 len -= i;
1006 data += i;
1007 *data = 0x00;
1008 i = 0;
1010 i++;
1011 } while (i < len);
1012 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1015 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1017 struct sd *sd = (struct sd *) gspca_dev;
1019 sd->brightness = val;
1020 if (gspca_dev->streaming)
1021 setbrightness(gspca_dev);
1022 return gspca_dev->usb_err;
1025 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1027 struct sd *sd = (struct sd *) gspca_dev;
1029 *val = sd->brightness;
1030 return 0;
1033 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1035 struct sd *sd = (struct sd *) gspca_dev;
1037 sd->contrast = val;
1038 if (gspca_dev->streaming)
1039 setcontrast(gspca_dev);
1040 return gspca_dev->usb_err;
1043 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1045 struct sd *sd = (struct sd *) gspca_dev;
1047 *val = sd->contrast;
1048 return 0;
1051 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1053 struct sd *sd = (struct sd *) gspca_dev;
1055 sd->colors = val;
1056 if (gspca_dev->streaming)
1057 setcolors(gspca_dev);
1058 return gspca_dev->usb_err;
1061 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1063 struct sd *sd = (struct sd *) gspca_dev;
1065 *val = sd->colors;
1066 return 0;
1069 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1071 struct sd *sd = (struct sd *) gspca_dev;
1073 sd->autogain = val;
1074 return 0;
1077 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1079 struct sd *sd = (struct sd *) gspca_dev;
1081 *val = sd->autogain;
1082 return 0;
1085 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1086 struct v4l2_jpegcompression *jcomp)
1088 struct sd *sd = (struct sd *) gspca_dev;
1090 if (jcomp->quality < QUALITY_MIN)
1091 sd->quality = QUALITY_MIN;
1092 else if (jcomp->quality > QUALITY_MAX)
1093 sd->quality = QUALITY_MAX;
1094 else
1095 sd->quality = jcomp->quality;
1096 if (gspca_dev->streaming)
1097 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1098 return gspca_dev->usb_err;
1101 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1102 struct v4l2_jpegcompression *jcomp)
1104 struct sd *sd = (struct sd *) gspca_dev;
1106 memset(jcomp, 0, sizeof *jcomp);
1107 jcomp->quality = sd->quality;
1108 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1109 | V4L2_JPEG_MARKER_DQT;
1110 return 0;
1113 /* sub-driver description */
1114 static const struct sd_desc sd_desc = {
1115 .name = MODULE_NAME,
1116 .ctrls = sd_ctrls,
1117 .nctrls = ARRAY_SIZE(sd_ctrls),
1118 .config = sd_config,
1119 .init = sd_init,
1120 .start = sd_start,
1121 .stopN = sd_stopN,
1122 .pkt_scan = sd_pkt_scan,
1123 .get_jcomp = sd_get_jcomp,
1124 .set_jcomp = sd_set_jcomp,
1127 /* -- module initialisation -- */
1128 #define BS(bridge, subtype) \
1129 .driver_info = (BRIDGE_ ## bridge << 8) \
1130 | (subtype)
1131 static const struct usb_device_id device_table[] = {
1132 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1133 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1134 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1135 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1136 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1137 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1138 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1139 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1140 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1141 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1142 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1143 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1144 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1145 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1146 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1147 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1148 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1149 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1150 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1151 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1152 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1153 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1154 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1155 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1156 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1157 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1158 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1159 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1160 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1161 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1162 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1163 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1164 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1165 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1166 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1167 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1168 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1169 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1170 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1171 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1172 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1173 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1174 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1175 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1176 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1177 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1178 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1179 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1180 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1181 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1182 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1183 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1184 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1185 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1186 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1187 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1188 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1189 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1190 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1193 MODULE_DEVICE_TABLE(usb, device_table);
1195 /* -- device connect -- */
1196 static int sd_probe(struct usb_interface *intf,
1197 const struct usb_device_id *id)
1199 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1200 THIS_MODULE);
1203 static struct usb_driver sd_driver = {
1204 .name = MODULE_NAME,
1205 .id_table = device_table,
1206 .probe = sd_probe,
1207 .disconnect = gspca_disconnect,
1208 #ifdef CONFIG_PM
1209 .suspend = gspca_suspend,
1210 .resume = gspca_resume,
1211 #endif
1214 module_usb_driver(sd_driver);