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
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 MODULE_NAME "sunplus"
27 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
29 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev; /* !! must be the first item */
40 #define QUALITY_MIN 70
41 #define QUALITY_MAX 95
42 #define QUALITY_DEF 85
45 #define BRIDGE_SPCA504 0
46 #define BRIDGE_SPCA504B 1
47 #define BRIDGE_SPCA504C 2
48 #define BRIDGE_SPCA533 3
49 #define BRIDGE_SPCA536 4
51 #define AiptekMiniPenCam13 1
52 #define LogitechClickSmart420 2
53 #define LogitechClickSmart820 3
60 /* V4L2 controls supported by the driver */
61 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
62 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
63 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
70 static struct ctrl sd_ctrls[] = {
73 .id = V4L2_CID_BRIGHTNESS,
74 .type = V4L2_CTRL_TYPE_INTEGER,
79 #define BRIGHTNESS_DEF 0
80 .default_value = BRIGHTNESS_DEF,
82 .set = sd_setbrightness,
83 .get = sd_getbrightness,
87 .id = V4L2_CID_CONTRAST,
88 .type = V4L2_CTRL_TYPE_INTEGER,
93 #define CONTRAST_DEF 0x20
94 .default_value = CONTRAST_DEF,
96 .set = sd_setcontrast,
97 .get = sd_getcontrast,
101 .id = V4L2_CID_SATURATION,
102 .type = V4L2_CTRL_TYPE_INTEGER,
107 #define COLOR_DEF 0x1a
108 .default_value = COLOR_DEF,
115 .id = V4L2_CID_AUTOGAIN,
116 .type = V4L2_CTRL_TYPE_BOOLEAN,
121 #define AUTOGAIN_DEF 1
122 .default_value = AUTOGAIN_DEF,
124 .set = sd_setautogain,
125 .get = sd_getautogain,
129 static const struct v4l2_pix_format vga_mode[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
132 .sizeimage = 320 * 240 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
135 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
137 .sizeimage = 640 * 480 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
142 static const struct v4l2_pix_format custom_mode[] = {
143 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
145 .sizeimage = 320 * 240 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
148 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
150 .sizeimage = 464 * 480 * 3 / 8 + 590,
151 .colorspace = V4L2_COLORSPACE_JPEG,
155 static const struct v4l2_pix_format vga_mode2[] = {
156 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
158 .sizeimage = 176 * 144 * 3 / 8 + 590,
159 .colorspace = V4L2_COLORSPACE_JPEG,
161 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
163 .sizeimage = 320 * 240 * 3 / 8 + 590,
164 .colorspace = V4L2_COLORSPACE_JPEG,
166 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
168 .sizeimage = 352 * 288 * 3 / 8 + 590,
169 .colorspace = V4L2_COLORSPACE_JPEG,
171 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
173 .sizeimage = 640 * 480 * 3 / 8 + 590,
174 .colorspace = V4L2_COLORSPACE_JPEG,
178 #define SPCA50X_OFFSET_DATA 10
179 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
180 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
181 #define SPCA504_PCCAM600_OFFSET_MODE 5
182 #define SPCA504_PCCAM600_OFFSET_DATA 14
183 /* Frame packet header offsets for the spca533 */
184 #define SPCA533_OFFSET_DATA 16
185 #define SPCA533_OFFSET_FRAMSEQ 15
186 /* Frame packet header offsets for the spca536 */
187 #define SPCA536_OFFSET_DATA 4
188 #define SPCA536_OFFSET_FRAMSEQ 1
196 /* Initialisation data for the Creative PC-CAM 600 */
197 static const struct cmd spca504_pccam600_init_data[] = {
198 /* {0xa0, 0x0000, 0x0503}, * capture mode */
199 {0x00, 0x0000, 0x2000},
200 {0x00, 0x0013, 0x2301},
201 {0x00, 0x0003, 0x2000},
202 {0x00, 0x0001, 0x21ac},
203 {0x00, 0x0001, 0x21a6},
204 {0x00, 0x0000, 0x21a7}, /* brightness */
205 {0x00, 0x0020, 0x21a8}, /* contrast */
206 {0x00, 0x0001, 0x21ac}, /* sat/hue */
207 {0x00, 0x0000, 0x21ad}, /* hue */
208 {0x00, 0x001a, 0x21ae}, /* saturation */
209 {0x00, 0x0002, 0x21a3}, /* gamma */
210 {0x30, 0x0154, 0x0008},
211 {0x30, 0x0004, 0x0006},
212 {0x30, 0x0258, 0x0009},
213 {0x30, 0x0004, 0x0000},
214 {0x30, 0x0093, 0x0004},
215 {0x30, 0x0066, 0x0005},
216 {0x00, 0x0000, 0x2000},
217 {0x00, 0x0013, 0x2301},
218 {0x00, 0x0003, 0x2000},
219 {0x00, 0x0013, 0x2301},
220 {0x00, 0x0003, 0x2000},
223 /* Creative PC-CAM 600 specific open data, sent before using the
224 * generic initialisation data from spca504_open_data.
226 static const struct cmd spca504_pccam600_open_data[] = {
227 {0x00, 0x0001, 0x2501},
228 {0x20, 0x0500, 0x0001}, /* snapshot mode */
229 {0x00, 0x0003, 0x2880},
230 {0x00, 0x0001, 0x2881},
233 /* Initialisation data for the logitech clicksmart 420 */
234 static const struct cmd spca504A_clicksmart420_init_data[] = {
235 /* {0xa0, 0x0000, 0x0503}, * capture mode */
236 {0x00, 0x0000, 0x2000},
237 {0x00, 0x0013, 0x2301},
238 {0x00, 0x0003, 0x2000},
239 {0x00, 0x0001, 0x21ac},
240 {0x00, 0x0001, 0x21a6},
241 {0x00, 0x0000, 0x21a7}, /* brightness */
242 {0x00, 0x0020, 0x21a8}, /* contrast */
243 {0x00, 0x0001, 0x21ac}, /* sat/hue */
244 {0x00, 0x0000, 0x21ad}, /* hue */
245 {0x00, 0x001a, 0x21ae}, /* saturation */
246 {0x00, 0x0002, 0x21a3}, /* gamma */
247 {0x30, 0x0004, 0x000a},
248 {0xb0, 0x0001, 0x0000},
251 {0xa1, 0x0080, 0x0001},
252 {0x30, 0x0049, 0x0000},
253 {0x30, 0x0060, 0x0005},
254 {0x0c, 0x0004, 0x0000},
255 {0x00, 0x0000, 0x0000},
256 {0x00, 0x0000, 0x2000},
257 {0x00, 0x0013, 0x2301},
258 {0x00, 0x0003, 0x2000},
259 {0x00, 0x0000, 0x2000},
263 /* clicksmart 420 open data ? */
264 static const struct cmd spca504A_clicksmart420_open_data[] = {
265 {0x00, 0x0001, 0x2501},
266 {0x20, 0x0502, 0x0000},
267 {0x06, 0x0000, 0x0000},
268 {0x00, 0x0004, 0x2880},
269 {0x00, 0x0001, 0x2881},
270 /* look like setting a qTable */
271 {0x00, 0x0006, 0x2800},
272 {0x00, 0x0004, 0x2801},
273 {0x00, 0x0004, 0x2802},
274 {0x00, 0x0006, 0x2803},
275 {0x00, 0x000a, 0x2804},
276 {0x00, 0x0010, 0x2805},
277 {0x00, 0x0014, 0x2806},
278 {0x00, 0x0018, 0x2807},
279 {0x00, 0x0005, 0x2808},
280 {0x00, 0x0005, 0x2809},
281 {0x00, 0x0006, 0x280a},
282 {0x00, 0x0008, 0x280b},
283 {0x00, 0x000a, 0x280c},
284 {0x00, 0x0017, 0x280d},
285 {0x00, 0x0018, 0x280e},
286 {0x00, 0x0016, 0x280f},
288 {0x00, 0x0006, 0x2810},
289 {0x00, 0x0005, 0x2811},
290 {0x00, 0x0006, 0x2812},
291 {0x00, 0x000a, 0x2813},
292 {0x00, 0x0010, 0x2814},
293 {0x00, 0x0017, 0x2815},
294 {0x00, 0x001c, 0x2816},
295 {0x00, 0x0016, 0x2817},
296 {0x00, 0x0006, 0x2818},
297 {0x00, 0x0007, 0x2819},
298 {0x00, 0x0009, 0x281a},
299 {0x00, 0x000c, 0x281b},
300 {0x00, 0x0014, 0x281c},
301 {0x00, 0x0023, 0x281d},
302 {0x00, 0x0020, 0x281e},
303 {0x00, 0x0019, 0x281f},
305 {0x00, 0x0007, 0x2820},
306 {0x00, 0x0009, 0x2821},
307 {0x00, 0x000f, 0x2822},
308 {0x00, 0x0016, 0x2823},
309 {0x00, 0x001b, 0x2824},
310 {0x00, 0x002c, 0x2825},
311 {0x00, 0x0029, 0x2826},
312 {0x00, 0x001f, 0x2827},
313 {0x00, 0x000a, 0x2828},
314 {0x00, 0x000e, 0x2829},
315 {0x00, 0x0016, 0x282a},
316 {0x00, 0x001a, 0x282b},
317 {0x00, 0x0020, 0x282c},
318 {0x00, 0x002a, 0x282d},
319 {0x00, 0x002d, 0x282e},
320 {0x00, 0x0025, 0x282f},
322 {0x00, 0x0014, 0x2830},
323 {0x00, 0x001a, 0x2831},
324 {0x00, 0x001f, 0x2832},
325 {0x00, 0x0023, 0x2833},
326 {0x00, 0x0029, 0x2834},
327 {0x00, 0x0030, 0x2835},
328 {0x00, 0x0030, 0x2836},
329 {0x00, 0x0028, 0x2837},
330 {0x00, 0x001d, 0x2838},
331 {0x00, 0x0025, 0x2839},
332 {0x00, 0x0026, 0x283a},
333 {0x00, 0x0027, 0x283b},
334 {0x00, 0x002d, 0x283c},
335 {0x00, 0x0028, 0x283d},
336 {0x00, 0x0029, 0x283e},
337 {0x00, 0x0028, 0x283f},
339 {0x00, 0x0007, 0x2840},
340 {0x00, 0x0007, 0x2841},
341 {0x00, 0x000a, 0x2842},
342 {0x00, 0x0013, 0x2843},
343 {0x00, 0x0028, 0x2844},
344 {0x00, 0x0028, 0x2845},
345 {0x00, 0x0028, 0x2846},
346 {0x00, 0x0028, 0x2847},
347 {0x00, 0x0007, 0x2848},
348 {0x00, 0x0008, 0x2849},
349 {0x00, 0x000a, 0x284a},
350 {0x00, 0x001a, 0x284b},
351 {0x00, 0x0028, 0x284c},
352 {0x00, 0x0028, 0x284d},
353 {0x00, 0x0028, 0x284e},
354 {0x00, 0x0028, 0x284f},
356 {0x00, 0x000a, 0x2850},
357 {0x00, 0x000a, 0x2851},
358 {0x00, 0x0016, 0x2852},
359 {0x00, 0x0028, 0x2853},
360 {0x00, 0x0028, 0x2854},
361 {0x00, 0x0028, 0x2855},
362 {0x00, 0x0028, 0x2856},
363 {0x00, 0x0028, 0x2857},
364 {0x00, 0x0013, 0x2858},
365 {0x00, 0x001a, 0x2859},
366 {0x00, 0x0028, 0x285a},
367 {0x00, 0x0028, 0x285b},
368 {0x00, 0x0028, 0x285c},
369 {0x00, 0x0028, 0x285d},
370 {0x00, 0x0028, 0x285e},
371 {0x00, 0x0028, 0x285f},
373 {0x00, 0x0028, 0x2860},
374 {0x00, 0x0028, 0x2861},
375 {0x00, 0x0028, 0x2862},
376 {0x00, 0x0028, 0x2863},
377 {0x00, 0x0028, 0x2864},
378 {0x00, 0x0028, 0x2865},
379 {0x00, 0x0028, 0x2866},
380 {0x00, 0x0028, 0x2867},
381 {0x00, 0x0028, 0x2868},
382 {0x00, 0x0028, 0x2869},
383 {0x00, 0x0028, 0x286a},
384 {0x00, 0x0028, 0x286b},
385 {0x00, 0x0028, 0x286c},
386 {0x00, 0x0028, 0x286d},
387 {0x00, 0x0028, 0x286e},
388 {0x00, 0x0028, 0x286f},
390 {0x00, 0x0028, 0x2870},
391 {0x00, 0x0028, 0x2871},
392 {0x00, 0x0028, 0x2872},
393 {0x00, 0x0028, 0x2873},
394 {0x00, 0x0028, 0x2874},
395 {0x00, 0x0028, 0x2875},
396 {0x00, 0x0028, 0x2876},
397 {0x00, 0x0028, 0x2877},
398 {0x00, 0x0028, 0x2878},
399 {0x00, 0x0028, 0x2879},
400 {0x00, 0x0028, 0x287a},
401 {0x00, 0x0028, 0x287b},
402 {0x00, 0x0028, 0x287c},
403 {0x00, 0x0028, 0x287d},
404 {0x00, 0x0028, 0x287e},
405 {0x00, 0x0028, 0x287f},
407 {0xa0, 0x0000, 0x0503},
410 static const u8 qtable_creative_pccam[2][64] = {
411 { /* Q-table Y-components */
412 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
413 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
414 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
415 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
416 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
417 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
418 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
419 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
420 { /* Q-table C-components */
421 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
424 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
425 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
426 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
427 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
428 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
431 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
432 * except for one byte. Possibly a typo?
435 static const u8 qtable_spca504_default[2][64] = {
436 { /* Q-table Y-components */
437 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
438 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
439 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
440 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
441 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
442 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
443 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
444 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
446 { /* Q-table C-components */
447 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
450 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
451 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
452 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
453 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
454 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
457 /* read <len> bytes to gspca_dev->usb_buf */
458 static void reg_r(struct gspca_dev *gspca_dev,
466 if (len > USB_BUF_SZ) {
467 err("reg_r: buffer overflow");
471 if (gspca_dev->usb_err < 0)
473 ret = usb_control_msg(gspca_dev->dev,
474 usb_rcvctrlpipe(gspca_dev->dev, 0),
476 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
479 len ? gspca_dev->usb_buf : NULL, len,
482 PDEBUG(D_ERR, "reg_r err %d", ret);
483 gspca_dev->usb_err = ret;
488 static void reg_w_1(struct gspca_dev *gspca_dev,
496 if (gspca_dev->usb_err < 0)
498 gspca_dev->usb_buf[0] = byte;
499 ret = usb_control_msg(gspca_dev->dev,
500 usb_sndctrlpipe(gspca_dev->dev, 0),
502 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
504 gspca_dev->usb_buf, 1,
507 PDEBUG(D_ERR, "reg_w_1 err %d", ret);
508 gspca_dev->usb_err = ret;
512 /* write req / index / value */
513 static void reg_w_riv(struct gspca_dev *gspca_dev,
514 u8 req, u16 index, u16 value)
516 struct usb_device *dev = gspca_dev->dev;
519 if (gspca_dev->usb_err < 0)
521 ret = usb_control_msg(dev,
522 usb_sndctrlpipe(dev, 0),
524 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
525 value, index, NULL, 0, 500);
527 PDEBUG(D_ERR, "reg_w_riv err %d", ret);
528 gspca_dev->usb_err = ret;
531 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
536 static u8 reg_r_1(struct gspca_dev *gspca_dev,
537 u16 value) /* wValue */
541 if (gspca_dev->usb_err < 0)
543 ret = usb_control_msg(gspca_dev->dev,
544 usb_rcvctrlpipe(gspca_dev->dev, 0),
546 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
549 gspca_dev->usb_buf, 1,
552 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
553 gspca_dev->usb_err = ret;
556 return gspca_dev->usb_buf[0];
559 /* read 1 or 2 bytes */
560 static u16 reg_r_12(struct gspca_dev *gspca_dev,
561 u8 req, /* bRequest */
562 u16 index, /* wIndex */
563 u16 length) /* wLength (1 or 2 only) */
567 if (gspca_dev->usb_err < 0)
569 gspca_dev->usb_buf[1] = 0;
570 ret = usb_control_msg(gspca_dev->dev,
571 usb_rcvctrlpipe(gspca_dev->dev, 0),
573 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
576 gspca_dev->usb_buf, length,
579 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
580 gspca_dev->usb_err = ret;
583 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
586 static void write_vector(struct gspca_dev *gspca_dev,
587 const struct cmd *data, int ncmds)
589 while (--ncmds >= 0) {
590 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
595 static void setup_qtable(struct gspca_dev *gspca_dev,
596 const u8 qtable[2][64])
600 /* loop over y components */
601 for (i = 0; i < 64; i++)
602 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
604 /* loop over c components */
605 for (i = 0; i < 64; i++)
606 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
609 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
610 u8 req, u16 idx, u16 val)
614 reg_w_riv(gspca_dev, req, idx, val);
615 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
616 reg_w_riv(gspca_dev, req, idx, val);
618 PDEBUG(D_FRAM, "before wait 0x%04x", notdone);
621 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
622 PDEBUG(D_FRAM, "after wait 0x%04x", notdone);
625 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
627 u16 idx, u16 val, u16 endcode, u8 count)
631 reg_w_riv(gspca_dev, req, idx, val);
632 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
633 if (gspca_dev->usb_err < 0)
635 PDEBUG(D_FRAM, "Status 0x%04x Need 0x%04x", status, endcode);
639 while (--count > 0) {
641 /* gsmart mini2 write a each wait setting 1 ms is enough */
642 /* reg_w_riv(gspca_dev, req, idx, val); */
643 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
644 if (status == endcode) {
645 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
646 status, 200 - count);
652 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
656 while (--count > 0) {
657 reg_r(gspca_dev, 0x21, 0, 1);
658 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
664 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
668 while (--count > 0) {
669 reg_r(gspca_dev, 0x21, 1, 1);
670 if (gspca_dev->usb_buf[0] != 0) {
671 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
672 reg_r(gspca_dev, 0x21, 1, 1);
673 spca504B_PollingDataReady(gspca_dev);
680 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
684 data = gspca_dev->usb_buf;
685 reg_r(gspca_dev, 0x20, 0, 5);
686 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
687 data[0], data[1], data[2], data[3], data[4]);
688 reg_r(gspca_dev, 0x23, 0, 64);
689 reg_r(gspca_dev, 0x23, 1, 64);
692 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
694 struct sd *sd = (struct sd *) gspca_dev;
697 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
698 switch (sd->bridge) {
700 reg_w_riv(gspca_dev, 0x31, 0, 0);
701 spca504B_WaitCmdStatus(gspca_dev);
702 spca504B_PollingDataReady(gspca_dev);
703 spca50x_GetFirmware(gspca_dev);
704 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
705 reg_r(gspca_dev, 0x24, 8, 1);
707 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
708 reg_r(gspca_dev, 0x25, 4, 1); /* size */
709 spca504B_PollingDataReady(gspca_dev);
711 /* Init the cam width height with some values get on init ? */
712 reg_w_riv(gspca_dev, 0x31, 0, 0x04);
713 spca504B_WaitCmdStatus(gspca_dev);
714 spca504B_PollingDataReady(gspca_dev);
717 /* case BRIDGE_SPCA504B: */
718 /* case BRIDGE_SPCA536: */
719 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
720 reg_r(gspca_dev, 0x25, 4, 1); /* size */
721 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
722 reg_r(gspca_dev, 0x27, 0, 1); /* type */
723 spca504B_PollingDataReady(gspca_dev);
727 if (sd->subtype == AiptekMiniPenCam13) {
728 /* spca504a aiptek */
729 spca504A_acknowledged_command(gspca_dev,
731 0x80 | (Size & 0x0f), 1);
732 spca504A_acknowledged_command(gspca_dev,
735 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
738 case BRIDGE_SPCA504C:
740 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
741 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
746 static void spca504_wait_status(struct gspca_dev *gspca_dev)
752 /* With this we get the status, when return 0 it's all ok */
753 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
759 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
761 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
762 reg_r(gspca_dev, 0x26, 0, 1);
763 spca504B_PollingDataReady(gspca_dev);
766 static void setbrightness(struct gspca_dev *gspca_dev)
768 struct sd *sd = (struct sd *) gspca_dev;
771 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
772 reg_w_riv(gspca_dev, 0x00, reg, sd->brightness);
775 static void setcontrast(struct gspca_dev *gspca_dev)
777 struct sd *sd = (struct sd *) gspca_dev;
780 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
781 reg_w_riv(gspca_dev, 0x00, reg, sd->contrast);
784 static void setcolors(struct gspca_dev *gspca_dev)
786 struct sd *sd = (struct sd *) gspca_dev;
789 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
790 reg_w_riv(gspca_dev, 0x00, reg, sd->colors);
793 static void init_ctl_reg(struct gspca_dev *gspca_dev)
795 struct sd *sd = (struct sd *) gspca_dev;
798 setbrightness(gspca_dev);
799 setcontrast(gspca_dev);
800 setcolors(gspca_dev);
802 switch (sd->bridge) {
804 case BRIDGE_SPCA504C:
808 /* case BRIDGE_SPCA533: */
809 /* case BRIDGE_SPCA504B: */
810 reg_w_riv(gspca_dev, 0, 0x00, 0x21ad); /* hue */
811 reg_w_riv(gspca_dev, 0, 0x01, 0x21ac); /* sat/hue */
812 reg_w_riv(gspca_dev, 0, 0x00, 0x21a3); /* gamma */
815 reg_w_riv(gspca_dev, 0, 0x40, 0x20f5);
816 reg_w_riv(gspca_dev, 0, 0x01, 0x20f4);
817 reg_w_riv(gspca_dev, 0, 0x00, 0x2089);
821 spca504B_PollingDataReady(gspca_dev);
824 /* this function is called at probe time */
825 static int sd_config(struct gspca_dev *gspca_dev,
826 const struct usb_device_id *id)
828 struct sd *sd = (struct sd *) gspca_dev;
831 cam = &gspca_dev->cam;
833 sd->bridge = id->driver_info >> 8;
834 sd->subtype = id->driver_info;
836 if (sd->subtype == AiptekMiniPenCam13) {
837 /* try to get the firmware as some cam answer 2.0.1.2.2
838 * and should be a spca504b then overwrite that setting */
839 reg_r(gspca_dev, 0x20, 0, 1);
840 switch (gspca_dev->usb_buf[0]) {
842 break; /* (right bridge/subtype) */
844 sd->bridge = BRIDGE_SPCA504B;
852 switch (sd->bridge) {
854 /* case BRIDGE_SPCA504B: */
855 /* case BRIDGE_SPCA504: */
856 /* case BRIDGE_SPCA536: */
857 cam->cam_mode = vga_mode;
858 cam->nmodes =ARRAY_SIZE(vga_mode);
861 cam->cam_mode = custom_mode;
862 if (sd->subtype == MegaImageVI) /* 320x240 only */
863 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
865 cam->nmodes = ARRAY_SIZE(custom_mode);
867 case BRIDGE_SPCA504C:
868 cam->cam_mode = vga_mode2;
869 cam->nmodes = ARRAY_SIZE(vga_mode2);
872 sd->brightness = BRIGHTNESS_DEF;
873 sd->contrast = CONTRAST_DEF;
874 sd->colors = COLOR_DEF;
875 sd->autogain = AUTOGAIN_DEF;
876 sd->quality = QUALITY_DEF;
880 /* this function is called at probe and resume time */
881 static int sd_init(struct gspca_dev *gspca_dev)
883 struct sd *sd = (struct sd *) gspca_dev;
887 switch (sd->bridge) {
888 case BRIDGE_SPCA504B:
889 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
890 reg_w_riv(gspca_dev, 0, 0x01, 0x2306);
891 reg_w_riv(gspca_dev, 0, 0x00, 0x0d04);
892 reg_w_riv(gspca_dev, 0, 0x00, 0x2000);
893 reg_w_riv(gspca_dev, 0, 0x13, 0x2301);
894 reg_w_riv(gspca_dev, 0, 0x00, 0x2306);
897 spca504B_PollingDataReady(gspca_dev);
898 spca50x_GetFirmware(gspca_dev);
901 spca50x_GetFirmware(gspca_dev);
902 reg_r(gspca_dev, 0x00, 0x5002, 1);
903 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
904 reg_r(gspca_dev, 0x24, 0, 1);
905 spca504B_PollingDataReady(gspca_dev);
906 reg_w_riv(gspca_dev, 0x34, 0, 0);
907 spca504B_WaitCmdStatus(gspca_dev);
909 case BRIDGE_SPCA504C: /* pccam600 */
910 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
911 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
912 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
913 spca504_wait_status(gspca_dev);
914 if (sd->subtype == LogitechClickSmart420)
915 write_vector(gspca_dev,
916 spca504A_clicksmart420_open_data,
917 ARRAY_SIZE(spca504A_clicksmart420_open_data));
919 write_vector(gspca_dev, spca504_pccam600_open_data,
920 ARRAY_SIZE(spca504_pccam600_open_data));
921 setup_qtable(gspca_dev, qtable_creative_pccam);
924 /* case BRIDGE_SPCA504: */
925 PDEBUG(D_STREAM, "Opening SPCA504");
926 if (sd->subtype == AiptekMiniPenCam13) {
927 /*****************************/
928 for (i = 0; i < 6; i++)
929 info[i] = reg_r_1(gspca_dev, i);
931 "Read info: %d %d %d %d %d %d."
932 " Should be 1,0,2,2,0,0",
933 info[0], info[1], info[2],
934 info[3], info[4], info[5]);
935 /* spca504a aiptek */
936 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
937 spca504A_acknowledged_command(gspca_dev, 0x24,
939 /* Twice sequencial need status 0xff->0x9e->0x9d */
940 spca504A_acknowledged_command(gspca_dev, 0x24,
943 spca504A_acknowledged_command(gspca_dev, 0x24,
945 /******************************/
946 /* spca504a aiptek */
947 spca504A_acknowledged_command(gspca_dev, 0x08,
949 /* reg_write (dev, 0, 0x2000, 0); */
950 /* reg_write (dev, 0, 0x2883, 1); */
951 /* spca504A_acknowledged_command (gspca_dev, 0x08,
953 /* spca504A_acknowledged_command (gspca_dev, 0x24,
955 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
957 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
958 spca504A_acknowledged_command(gspca_dev, 0x01,
962 reg_w_riv(gspca_dev, 0, 0x2000, 0);
963 reg_w_riv(gspca_dev, 0, 0x2883, 1);
964 setup_qtable(gspca_dev, qtable_spca504_default);
967 return gspca_dev->usb_err;
970 static int sd_start(struct gspca_dev *gspca_dev)
972 struct sd *sd = (struct sd *) gspca_dev;
977 /* create the JPEG header */
978 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
981 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
982 0x22); /* JPEG 411 */
983 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
985 if (sd->bridge == BRIDGE_SPCA504B)
986 spca504B_setQtable(gspca_dev);
987 spca504B_SetSizeType(gspca_dev);
988 switch (sd->bridge) {
990 /* case BRIDGE_SPCA504B: */
991 /* case BRIDGE_SPCA533: */
992 /* case BRIDGE_SPCA536: */
993 switch (sd->subtype) {
995 case LogitechClickSmart820:
997 reg_w_riv(gspca_dev, 0xf0, 0, 0);
998 spca504B_WaitCmdStatus(gspca_dev);
999 reg_r(gspca_dev, 0xf0, 4, 0);
1000 spca504B_WaitCmdStatus(gspca_dev);
1003 reg_w_riv(gspca_dev, 0x31, 0, 0x04);
1004 spca504B_WaitCmdStatus(gspca_dev);
1005 spca504B_PollingDataReady(gspca_dev);
1009 case BRIDGE_SPCA504:
1010 if (sd->subtype == AiptekMiniPenCam13) {
1011 for (i = 0; i < 6; i++)
1012 info[i] = reg_r_1(gspca_dev, i);
1014 "Read info: %d %d %d %d %d %d."
1015 " Should be 1,0,2,2,0,0",
1016 info[0], info[1], info[2],
1017 info[3], info[4], info[5]);
1018 /* spca504a aiptek */
1019 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1020 spca504A_acknowledged_command(gspca_dev, 0x24,
1022 /* Twice sequencial need status 0xff->0x9e->0x9d */
1023 spca504A_acknowledged_command(gspca_dev, 0x24,
1025 spca504A_acknowledged_command(gspca_dev, 0x24,
1028 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1029 for (i = 0; i < 6; i++)
1030 info[i] = reg_r_1(gspca_dev, i);
1032 "Read info: %d %d %d %d %d %d."
1033 " Should be 1,0,2,2,0,0",
1034 info[0], info[1], info[2],
1035 info[3], info[4], info[5]);
1036 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1037 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1039 spca504B_SetSizeType(gspca_dev);
1040 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
1042 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
1044 case BRIDGE_SPCA504C:
1045 if (sd->subtype == LogitechClickSmart420) {
1046 write_vector(gspca_dev,
1047 spca504A_clicksmart420_init_data,
1048 ARRAY_SIZE(spca504A_clicksmart420_init_data));
1050 write_vector(gspca_dev, spca504_pccam600_init_data,
1051 ARRAY_SIZE(spca504_pccam600_init_data));
1053 enable = (sd->autogain ? 0x04 : 0x01);
1054 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
1056 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
1057 /* auto whiteness */
1059 /* set default exposure compensation and whiteness balance */
1060 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1061 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
1062 spca504B_SetSizeType(gspca_dev);
1065 init_ctl_reg(gspca_dev);
1066 return gspca_dev->usb_err;
1069 static void sd_stopN(struct gspca_dev *gspca_dev)
1071 struct sd *sd = (struct sd *) gspca_dev;
1073 switch (sd->bridge) {
1075 /* case BRIDGE_SPCA533: */
1076 /* case BRIDGE_SPCA536: */
1077 /* case BRIDGE_SPCA504B: */
1078 reg_w_riv(gspca_dev, 0x31, 0, 0);
1079 spca504B_WaitCmdStatus(gspca_dev);
1080 spca504B_PollingDataReady(gspca_dev);
1082 case BRIDGE_SPCA504:
1083 case BRIDGE_SPCA504C:
1084 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
1086 if (sd->subtype == AiptekMiniPenCam13) {
1087 /* spca504a aiptek */
1088 /* spca504A_acknowledged_command(gspca_dev, 0x08,
1090 spca504A_acknowledged_command(gspca_dev, 0x24,
1091 0x00, 0x00, 0x9d, 1);
1092 spca504A_acknowledged_command(gspca_dev, 0x01,
1093 0x0f, 0x00, 0xff, 1);
1095 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1096 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
1102 static void sd_stop0(struct gspca_dev *gspca_dev)
1104 struct sd *sd = (struct sd *) gspca_dev;
1106 kfree(sd->jpeg_hdr);
1109 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1110 u8 *data, /* isoc packet */
1111 int len) /* iso packet length */
1113 struct sd *sd = (struct sd *) gspca_dev;
1115 static u8 ffd9[] = {0xff, 0xd9};
1117 /* frames are jpeg 4.1.1 without 0xff escape */
1118 switch (sd->bridge) {
1119 case BRIDGE_SPCA533:
1120 if (data[0] == 0xff) {
1121 if (data[1] != 0x01) { /* drop packet */
1122 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1126 data += SPCA533_OFFSET_DATA;
1127 len -= SPCA533_OFFSET_DATA;
1133 case BRIDGE_SPCA536:
1134 if (data[0] == 0xff) {
1136 data += SPCA536_OFFSET_DATA;
1137 len -= SPCA536_OFFSET_DATA;
1144 /* case BRIDGE_SPCA504: */
1145 /* case BRIDGE_SPCA504B: */
1147 case 0xfe: /* start of frame */
1149 data += SPCA50X_OFFSET_DATA;
1150 len -= SPCA50X_OFFSET_DATA;
1152 case 0xff: /* drop packet */
1153 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1161 case BRIDGE_SPCA504C:
1163 case 0xfe: /* start of frame */
1165 data += SPCA504_PCCAM600_OFFSET_DATA;
1166 len -= SPCA504_PCCAM600_OFFSET_DATA;
1168 case 0xff: /* drop packet */
1169 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1178 if (sof) { /* start of frame */
1179 gspca_frame_add(gspca_dev, LAST_PACKET,
1182 /* put the JPEG header in the new frame */
1183 gspca_frame_add(gspca_dev, FIRST_PACKET,
1184 sd->jpeg_hdr, JPEG_HDR_SZ);
1187 /* add 0x00 after 0xff */
1190 if (data[i] == 0xff) {
1191 gspca_frame_add(gspca_dev, INTER_PACKET,
1200 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1203 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1205 struct sd *sd = (struct sd *) gspca_dev;
1207 sd->brightness = val;
1208 if (gspca_dev->streaming)
1209 setbrightness(gspca_dev);
1210 return gspca_dev->usb_err;
1213 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1215 struct sd *sd = (struct sd *) gspca_dev;
1217 *val = sd->brightness;
1221 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1223 struct sd *sd = (struct sd *) gspca_dev;
1226 if (gspca_dev->streaming)
1227 setcontrast(gspca_dev);
1228 return gspca_dev->usb_err;
1231 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1233 struct sd *sd = (struct sd *) gspca_dev;
1235 *val = sd->contrast;
1239 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1241 struct sd *sd = (struct sd *) gspca_dev;
1244 if (gspca_dev->streaming)
1245 setcolors(gspca_dev);
1246 return gspca_dev->usb_err;
1249 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1251 struct sd *sd = (struct sd *) gspca_dev;
1257 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1259 struct sd *sd = (struct sd *) gspca_dev;
1265 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1267 struct sd *sd = (struct sd *) gspca_dev;
1269 *val = sd->autogain;
1273 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1274 struct v4l2_jpegcompression *jcomp)
1276 struct sd *sd = (struct sd *) gspca_dev;
1278 if (jcomp->quality < QUALITY_MIN)
1279 sd->quality = QUALITY_MIN;
1280 else if (jcomp->quality > QUALITY_MAX)
1281 sd->quality = QUALITY_MAX;
1283 sd->quality = jcomp->quality;
1284 if (gspca_dev->streaming)
1285 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1286 return gspca_dev->usb_err;
1289 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1290 struct v4l2_jpegcompression *jcomp)
1292 struct sd *sd = (struct sd *) gspca_dev;
1294 memset(jcomp, 0, sizeof *jcomp);
1295 jcomp->quality = sd->quality;
1296 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1297 | V4L2_JPEG_MARKER_DQT;
1301 /* sub-driver description */
1302 static const struct sd_desc sd_desc = {
1303 .name = MODULE_NAME,
1305 .nctrls = ARRAY_SIZE(sd_ctrls),
1306 .config = sd_config,
1311 .pkt_scan = sd_pkt_scan,
1312 .get_jcomp = sd_get_jcomp,
1313 .set_jcomp = sd_set_jcomp,
1316 /* -- module initialisation -- */
1317 #define BS(bridge, subtype) \
1318 .driver_info = (BRIDGE_ ## bridge << 8) \
1320 static const __devinitdata struct usb_device_id device_table[] = {
1321 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1322 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1323 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1324 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1325 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1326 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1327 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1328 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1329 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1330 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1331 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1332 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1333 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1334 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1335 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1336 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1337 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1338 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1339 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1340 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1341 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1342 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1343 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1344 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1345 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1346 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1347 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1348 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1349 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1350 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1351 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1352 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1353 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1354 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1355 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1356 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1357 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1358 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1359 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1360 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1361 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1362 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1363 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1364 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1365 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1366 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1367 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1368 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1369 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1370 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1371 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1372 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1373 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1374 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1375 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1376 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1377 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1378 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1381 MODULE_DEVICE_TABLE(usb, device_table);
1383 /* -- device connect -- */
1384 static int sd_probe(struct usb_interface *intf,
1385 const struct usb_device_id *id)
1387 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1391 static struct usb_driver sd_driver = {
1392 .name = MODULE_NAME,
1393 .id_table = device_table,
1395 .disconnect = gspca_disconnect,
1397 .suspend = gspca_suspend,
1398 .resume = gspca_resume,
1402 /* -- module insert / remove -- */
1403 static int __init sd_mod_init(void)
1406 ret = usb_register(&sd_driver);
1409 PDEBUG(D_PROBE, "registered");
1412 static void __exit sd_mod_exit(void)
1414 usb_deregister(&sd_driver);
1415 PDEBUG(D_PROBE, "deregistered");
1418 module_init(sd_mod_init);
1419 module_exit(sd_mod_exit);