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 */
35 __u8 packet[ISO_MAX_SIZE + 128];
36 /* !! no more than 128 ff in an ISO packet */
38 unsigned char brightness;
39 unsigned char contrast;
41 unsigned char autogain;
43 #define QUALITY_MIN 70
44 #define QUALITY_MAX 95
45 #define QUALITY_DEF 85
48 #define BRIDGE_SPCA504 0
49 #define BRIDGE_SPCA504B 1
50 #define BRIDGE_SPCA504C 2
51 #define BRIDGE_SPCA533 3
52 #define BRIDGE_SPCA536 4
54 #define AiptekMiniPenCam13 1
55 #define LogitechClickSmart420 2
56 #define LogitechClickSmart820 3
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 struct ctrl sd_ctrls[] = {
73 #define SD_BRIGHTNESS 0
76 .id = V4L2_CID_BRIGHTNESS,
77 .type = V4L2_CTRL_TYPE_INTEGER,
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
90 .id = V4L2_CID_CONTRAST,
91 .type = V4L2_CTRL_TYPE_INTEGER,
96 .default_value = 0x20,
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
104 .id = V4L2_CID_SATURATION,
105 .type = V4L2_CTRL_TYPE_INTEGER,
110 .default_value = 0x1a,
115 #define SD_AUTOGAIN 3
118 .id = V4L2_CID_AUTOGAIN,
119 .type = V4L2_CTRL_TYPE_BOOLEAN,
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,
134 .sizeimage = 320 * 240 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
137 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
139 .sizeimage = 640 * 480 * 3 / 8 + 590,
140 .colorspace = V4L2_COLORSPACE_JPEG,
144 static const struct v4l2_pix_format custom_mode[] = {
145 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
147 .sizeimage = 320 * 240 * 3 / 8 + 590,
148 .colorspace = V4L2_COLORSPACE_JPEG,
150 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
152 .sizeimage = 464 * 480 * 3 / 8 + 590,
153 .colorspace = V4L2_COLORSPACE_JPEG,
157 static const struct v4l2_pix_format vga_mode2[] = {
158 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
160 .sizeimage = 176 * 144 * 3 / 8 + 590,
161 .colorspace = V4L2_COLORSPACE_JPEG,
163 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
165 .sizeimage = 320 * 240 * 3 / 8 + 590,
166 .colorspace = V4L2_COLORSPACE_JPEG,
168 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
170 .sizeimage = 352 * 288 * 3 / 8 + 590,
171 .colorspace = V4L2_COLORSPACE_JPEG,
173 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
175 .sizeimage = 640 * 480 * 3 / 8 + 590,
176 .colorspace = V4L2_COLORSPACE_JPEG,
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 /* Initialisation data for the Creative PC-CAM 600 */
193 static const __u16 spca504_pccam600_init_data[][3] = {
194 /* {0xa0, 0x0000, 0x0503}, * capture mode */
195 {0x00, 0x0000, 0x2000},
196 {0x00, 0x0013, 0x2301},
197 {0x00, 0x0003, 0x2000},
198 {0x00, 0x0001, 0x21ac},
199 {0x00, 0x0001, 0x21a6},
200 {0x00, 0x0000, 0x21a7}, /* brightness */
201 {0x00, 0x0020, 0x21a8}, /* contrast */
202 {0x00, 0x0001, 0x21ac}, /* sat/hue */
203 {0x00, 0x0000, 0x21ad}, /* hue */
204 {0x00, 0x001a, 0x21ae}, /* saturation */
205 {0x00, 0x0002, 0x21a3}, /* gamma */
206 {0x30, 0x0154, 0x0008},
207 {0x30, 0x0004, 0x0006},
208 {0x30, 0x0258, 0x0009},
209 {0x30, 0x0004, 0x0000},
210 {0x30, 0x0093, 0x0004},
211 {0x30, 0x0066, 0x0005},
212 {0x00, 0x0000, 0x2000},
213 {0x00, 0x0013, 0x2301},
214 {0x00, 0x0003, 0x2000},
215 {0x00, 0x0013, 0x2301},
216 {0x00, 0x0003, 0x2000},
220 /* Creative PC-CAM 600 specific open data, sent before using the
221 * generic initialisation data from spca504_open_data.
223 static const __u16 spca504_pccam600_open_data[][3] = {
224 {0x00, 0x0001, 0x2501},
225 {0x20, 0x0500, 0x0001}, /* snapshot mode */
226 {0x00, 0x0003, 0x2880},
227 {0x00, 0x0001, 0x2881},
231 /* Initialisation data for the logitech clicksmart 420 */
232 static const __u16 spca504A_clicksmart420_init_data[][3] = {
233 /* {0xa0, 0x0000, 0x0503}, * capture mode */
234 {0x00, 0x0000, 0x2000},
235 {0x00, 0x0013, 0x2301},
236 {0x00, 0x0003, 0x2000},
237 {0x00, 0x0001, 0x21ac},
238 {0x00, 0x0001, 0x21a6},
239 {0x00, 0x0000, 0x21a7}, /* brightness */
240 {0x00, 0x0020, 0x21a8}, /* contrast */
241 {0x00, 0x0001, 0x21ac}, /* sat/hue */
242 {0x00, 0x0000, 0x21ad}, /* hue */
243 {0x00, 0x001a, 0x21ae}, /* saturation */
244 {0x00, 0x0002, 0x21a3}, /* gamma */
245 {0x30, 0x0004, 0x000a},
246 {0xb0, 0x0001, 0x0000},
249 {0x0a1, 0x0080, 0x0001},
250 {0x30, 0x0049, 0x0000},
251 {0x30, 0x0060, 0x0005},
252 {0x0c, 0x0004, 0x0000},
253 {0x00, 0x0000, 0x0000},
254 {0x00, 0x0000, 0x2000},
255 {0x00, 0x0013, 0x2301},
256 {0x00, 0x0003, 0x2000},
257 {0x00, 0x0000, 0x2000},
262 /* clicksmart 420 open data ? */
263 static const __u16 spca504A_clicksmart420_open_data[][3] = {
264 {0x00, 0x0001, 0x2501},
265 {0x20, 0x0502, 0x0000},
266 {0x06, 0x0000, 0x0000},
267 {0x00, 0x0004, 0x2880},
268 {0x00, 0x0001, 0x2881},
269 /* look like setting a qTable */
270 {0x00, 0x0006, 0x2800},
271 {0x00, 0x0004, 0x2801},
272 {0x00, 0x0004, 0x2802},
273 {0x00, 0x0006, 0x2803},
274 {0x00, 0x000a, 0x2804},
275 {0x00, 0x0010, 0x2805},
276 {0x00, 0x0014, 0x2806},
277 {0x00, 0x0018, 0x2807},
278 {0x00, 0x0005, 0x2808},
279 {0x00, 0x0005, 0x2809},
280 {0x00, 0x0006, 0x280a},
281 {0x00, 0x0008, 0x280b},
282 {0x00, 0x000a, 0x280c},
283 {0x00, 0x0017, 0x280d},
284 {0x00, 0x0018, 0x280e},
285 {0x00, 0x0016, 0x280f},
287 {0x00, 0x0006, 0x2810},
288 {0x00, 0x0005, 0x2811},
289 {0x00, 0x0006, 0x2812},
290 {0x00, 0x000a, 0x2813},
291 {0x00, 0x0010, 0x2814},
292 {0x00, 0x0017, 0x2815},
293 {0x00, 0x001c, 0x2816},
294 {0x00, 0x0016, 0x2817},
295 {0x00, 0x0006, 0x2818},
296 {0x00, 0x0007, 0x2819},
297 {0x00, 0x0009, 0x281a},
298 {0x00, 0x000c, 0x281b},
299 {0x00, 0x0014, 0x281c},
300 {0x00, 0x0023, 0x281d},
301 {0x00, 0x0020, 0x281e},
302 {0x00, 0x0019, 0x281f},
304 {0x00, 0x0007, 0x2820},
305 {0x00, 0x0009, 0x2821},
306 {0x00, 0x000f, 0x2822},
307 {0x00, 0x0016, 0x2823},
308 {0x00, 0x001b, 0x2824},
309 {0x00, 0x002c, 0x2825},
310 {0x00, 0x0029, 0x2826},
311 {0x00, 0x001f, 0x2827},
312 {0x00, 0x000a, 0x2828},
313 {0x00, 0x000e, 0x2829},
314 {0x00, 0x0016, 0x282a},
315 {0x00, 0x001a, 0x282b},
316 {0x00, 0x0020, 0x282c},
317 {0x00, 0x002a, 0x282d},
318 {0x00, 0x002d, 0x282e},
319 {0x00, 0x0025, 0x282f},
321 {0x00, 0x0014, 0x2830},
322 {0x00, 0x001a, 0x2831},
323 {0x00, 0x001f, 0x2832},
324 {0x00, 0x0023, 0x2833},
325 {0x00, 0x0029, 0x2834},
326 {0x00, 0x0030, 0x2835},
327 {0x00, 0x0030, 0x2836},
328 {0x00, 0x0028, 0x2837},
329 {0x00, 0x001d, 0x2838},
330 {0x00, 0x0025, 0x2839},
331 {0x00, 0x0026, 0x283a},
332 {0x00, 0x0027, 0x283b},
333 {0x00, 0x002d, 0x283c},
334 {0x00, 0x0028, 0x283d},
335 {0x00, 0x0029, 0x283e},
336 {0x00, 0x0028, 0x283f},
338 {0x00, 0x0007, 0x2840},
339 {0x00, 0x0007, 0x2841},
340 {0x00, 0x000a, 0x2842},
341 {0x00, 0x0013, 0x2843},
342 {0x00, 0x0028, 0x2844},
343 {0x00, 0x0028, 0x2845},
344 {0x00, 0x0028, 0x2846},
345 {0x00, 0x0028, 0x2847},
346 {0x00, 0x0007, 0x2848},
347 {0x00, 0x0008, 0x2849},
348 {0x00, 0x000a, 0x284a},
349 {0x00, 0x001a, 0x284b},
350 {0x00, 0x0028, 0x284c},
351 {0x00, 0x0028, 0x284d},
352 {0x00, 0x0028, 0x284e},
353 {0x00, 0x0028, 0x284f},
355 {0x00, 0x000a, 0x2850},
356 {0x00, 0x000a, 0x2851},
357 {0x00, 0x0016, 0x2852},
358 {0x00, 0x0028, 0x2853},
359 {0x00, 0x0028, 0x2854},
360 {0x00, 0x0028, 0x2855},
361 {0x00, 0x0028, 0x2856},
362 {0x00, 0x0028, 0x2857},
363 {0x00, 0x0013, 0x2858},
364 {0x00, 0x001a, 0x2859},
365 {0x00, 0x0028, 0x285a},
366 {0x00, 0x0028, 0x285b},
367 {0x00, 0x0028, 0x285c},
368 {0x00, 0x0028, 0x285d},
369 {0x00, 0x0028, 0x285e},
370 {0x00, 0x0028, 0x285f},
372 {0x00, 0x0028, 0x2860},
373 {0x00, 0x0028, 0x2861},
374 {0x00, 0x0028, 0x2862},
375 {0x00, 0x0028, 0x2863},
376 {0x00, 0x0028, 0x2864},
377 {0x00, 0x0028, 0x2865},
378 {0x00, 0x0028, 0x2866},
379 {0x00, 0x0028, 0x2867},
380 {0x00, 0x0028, 0x2868},
381 {0x00, 0x0028, 0x2869},
382 {0x00, 0x0028, 0x286a},
383 {0x00, 0x0028, 0x286b},
384 {0x00, 0x0028, 0x286c},
385 {0x00, 0x0028, 0x286d},
386 {0x00, 0x0028, 0x286e},
387 {0x00, 0x0028, 0x286f},
389 {0x00, 0x0028, 0x2870},
390 {0x00, 0x0028, 0x2871},
391 {0x00, 0x0028, 0x2872},
392 {0x00, 0x0028, 0x2873},
393 {0x00, 0x0028, 0x2874},
394 {0x00, 0x0028, 0x2875},
395 {0x00, 0x0028, 0x2876},
396 {0x00, 0x0028, 0x2877},
397 {0x00, 0x0028, 0x2878},
398 {0x00, 0x0028, 0x2879},
399 {0x00, 0x0028, 0x287a},
400 {0x00, 0x0028, 0x287b},
401 {0x00, 0x0028, 0x287c},
402 {0x00, 0x0028, 0x287d},
403 {0x00, 0x0028, 0x287e},
404 {0x00, 0x0028, 0x287f},
406 {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,
464 if (len > USB_BUF_SZ) {
465 err("reg_r: buffer overflow");
469 usb_control_msg(gspca_dev->dev,
470 usb_rcvctrlpipe(gspca_dev->dev, 0),
472 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
475 len ? gspca_dev->usb_buf : NULL, len,
479 /* write <len> bytes from gspca_dev->usb_buf */
480 static void reg_w(struct gspca_dev *gspca_dev,
487 if (len > USB_BUF_SZ) {
488 err("reg_w: buffer overflow");
492 usb_control_msg(gspca_dev->dev,
493 usb_sndctrlpipe(gspca_dev->dev, 0),
495 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
497 len ? gspca_dev->usb_buf : NULL, len,
501 /* write req / index / value */
502 static int reg_w_riv(struct usb_device *dev,
503 __u16 req, __u16 index, __u16 value)
507 ret = usb_control_msg(dev,
508 usb_sndctrlpipe(dev, 0),
510 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
511 value, index, NULL, 0, 500);
512 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
513 req, index, value, ret);
515 PDEBUG(D_ERR, "reg write: error %d", ret);
520 static int reg_r_1(struct gspca_dev *gspca_dev,
521 __u16 value) /* wValue */
525 ret = usb_control_msg(gspca_dev->dev,
526 usb_rcvctrlpipe(gspca_dev->dev, 0),
528 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
531 gspca_dev->usb_buf, 1,
534 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
537 return gspca_dev->usb_buf[0];
540 /* read 1 or 2 bytes - returns < 0 if error */
541 static int reg_r_12(struct gspca_dev *gspca_dev,
542 __u16 req, /* bRequest */
543 __u16 index, /* wIndex */
544 __u16 length) /* wLength (1 or 2 only) */
548 gspca_dev->usb_buf[1] = 0;
549 ret = usb_control_msg(gspca_dev->dev,
550 usb_rcvctrlpipe(gspca_dev->dev, 0),
552 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
555 gspca_dev->usb_buf, length,
558 PDEBUG(D_ERR, "reg_read err %d", ret);
561 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
564 static int write_vector(struct gspca_dev *gspca_dev,
565 const __u16 data[][3])
567 struct usb_device *dev = gspca_dev->dev;
570 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
571 ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
574 "Register write failed for 0x%x,0x%x,0x%x",
575 data[i][0], data[i][1], data[i][2]);
583 static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
584 unsigned int request,
587 const __u8 qtable[2][64])
589 struct usb_device *dev = gspca_dev->dev;
592 /* loop over y components */
593 for (i = 0; i < 64; i++) {
594 err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
599 /* loop over c components */
600 for (i = 0; i < 64; i++) {
601 err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
608 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
609 __u16 req, __u16 idx, __u16 val)
611 struct usb_device *dev = gspca_dev->dev;
614 reg_w_riv(dev, req, idx, val);
615 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
616 reg_w_riv(dev, req, idx, val);
618 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
621 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
622 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
625 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
627 __u16 idx, __u16 val, __u8 stat, __u8 count)
629 struct usb_device *dev = gspca_dev->dev;
633 reg_w_riv(dev, req, idx, val);
634 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
636 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
640 while (--count > 0) {
642 /* gsmart mini2 write a each wait setting 1 ms is enought */
643 /* reg_w_riv(dev, req, idx, val); */
644 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
645 if (status == endcode) {
646 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
647 status, 200 - count);
653 static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
657 while (--count > 0) {
658 reg_r(gspca_dev, 0x21, 0, 1);
659 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
663 return gspca_dev->usb_buf[0];
666 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
670 while (--count > 0) {
671 reg_r(gspca_dev, 0x21, 1, 1);
672 if (gspca_dev->usb_buf[0] != 0) {
673 gspca_dev->usb_buf[0] = 0;
674 reg_w(gspca_dev, 0x21, 0, 1, 1);
675 reg_r(gspca_dev, 0x21, 1, 1);
676 spca504B_PollingDataReady(gspca_dev);
683 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
687 data = gspca_dev->usb_buf;
688 reg_r(gspca_dev, 0x20, 0, 5);
689 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
690 data[0], data[1], data[2], data[3], data[4]);
691 reg_r(gspca_dev, 0x23, 0, 64);
692 reg_r(gspca_dev, 0x23, 1, 64);
695 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
697 struct sd *sd = (struct sd *) gspca_dev;
698 struct usb_device *dev = gspca_dev->dev;
703 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
705 switch (sd->bridge) {
707 reg_w(gspca_dev, 0x31, 0, 0, 0);
708 spca504B_WaitCmdStatus(gspca_dev);
709 rc = spca504B_PollingDataReady(gspca_dev);
710 spca50x_GetFirmware(gspca_dev);
711 gspca_dev->usb_buf[0] = 2; /* type */
712 reg_w(gspca_dev, 0x24, 0, 8, 1);
713 reg_r(gspca_dev, 0x24, 8, 1);
715 gspca_dev->usb_buf[0] = Size;
716 reg_w(gspca_dev, 0x25, 0, 4, 1);
717 reg_r(gspca_dev, 0x25, 4, 1); /* size */
718 rc = spca504B_PollingDataReady(gspca_dev);
720 /* Init the cam width height with some values get on init ? */
721 reg_w(gspca_dev, 0x31, 0, 4, 0);
722 spca504B_WaitCmdStatus(gspca_dev);
723 rc = spca504B_PollingDataReady(gspca_dev);
726 /* case BRIDGE_SPCA504B: */
727 /* case BRIDGE_SPCA536: */
728 gspca_dev->usb_buf[0] = Size;
729 reg_w(gspca_dev, 0x25, 0, 4, 1);
730 reg_r(gspca_dev, 0x25, 4, 1); /* size */
732 gspca_dev->usb_buf[0] = Type;
733 reg_w(gspca_dev, 0x27, 0, 0, 1);
734 reg_r(gspca_dev, 0x27, 0, 1); /* type */
735 rc = spca504B_PollingDataReady(gspca_dev);
739 if (sd->subtype == AiptekMiniPenCam13) {
740 /* spca504a aiptek */
741 spca504A_acknowledged_command(gspca_dev,
743 0x80 | (Size & 0x0f), 1);
744 spca504A_acknowledged_command(gspca_dev,
747 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
750 case BRIDGE_SPCA504C:
752 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
753 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
758 static void spca504_wait_status(struct gspca_dev *gspca_dev)
764 /* With this we get the status, when return 0 it's all ok */
765 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
771 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
773 gspca_dev->usb_buf[0] = 3;
774 reg_w(gspca_dev, 0x26, 0, 0, 1);
775 reg_r(gspca_dev, 0x26, 0, 1);
776 spca504B_PollingDataReady(gspca_dev);
779 static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
781 struct sd *sd = (struct sd *) gspca_dev;
784 switch (sd->bridge) {
786 case BRIDGE_SPCA504C:
790 /* case BRIDGE_SPCA533: */
791 /* case BRIDGE_SPCA504B: */
792 reg_w(gspca_dev, 0, 0, 0x21a7, 0); /* brightness */
793 reg_w(gspca_dev, 0, 0x20, 0x21a8, 0); /* contrast */
794 reg_w(gspca_dev, 0, 0, 0x21ad, 0); /* hue */
795 reg_w(gspca_dev, 0, 1, 0x21ac, 0); /* sat/hue */
796 reg_w(gspca_dev, 0, 0x20, 0x21ae, 0); /* saturation */
797 reg_w(gspca_dev, 0, 0, 0x21a3, 0); /* gamma */
800 reg_w(gspca_dev, 0, 0, 0x20f0, 0);
801 reg_w(gspca_dev, 0, 0x21, 0x20f1, 0);
802 reg_w(gspca_dev, 0, 0x40, 0x20f5, 0);
803 reg_w(gspca_dev, 0, 1, 0x20f4, 0);
804 reg_w(gspca_dev, 0, 0x40, 0x20f6, 0);
805 reg_w(gspca_dev, 0, 0, 0x2089, 0);
809 spca504B_PollingDataReady(gspca_dev);
812 /* this function is called at probe time */
813 static int sd_config(struct gspca_dev *gspca_dev,
814 const struct usb_device_id *id)
816 struct sd *sd = (struct sd *) gspca_dev;
819 cam = &gspca_dev->cam;
821 sd->bridge = id->driver_info >> 8;
822 sd->subtype = id->driver_info;
824 if (sd->subtype == AiptekMiniPenCam13) {
825 /* try to get the firmware as some cam answer 2.0.1.2.2
826 * and should be a spca504b then overwrite that setting */
827 reg_r(gspca_dev, 0x20, 0, 1);
828 switch (gspca_dev->usb_buf[0]) {
830 break; /* (right bridge/subtype) */
832 sd->bridge = BRIDGE_SPCA504B;
840 switch (sd->bridge) {
842 /* case BRIDGE_SPCA504B: */
843 /* case BRIDGE_SPCA504: */
844 /* case BRIDGE_SPCA536: */
845 cam->cam_mode = vga_mode;
846 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
849 cam->cam_mode = custom_mode;
850 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
852 case BRIDGE_SPCA504C:
853 cam->cam_mode = vga_mode2;
854 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
857 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
858 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
859 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
860 sd->quality = QUALITY_DEF;
864 /* this function is called at probe and resume time */
865 static int sd_init(struct gspca_dev *gspca_dev)
867 struct sd *sd = (struct sd *) gspca_dev;
868 struct usb_device *dev = gspca_dev->dev;
874 switch (sd->bridge) {
875 case BRIDGE_SPCA504B:
876 reg_w(gspca_dev, 0x1d, 0, 0, 0);
877 reg_w(gspca_dev, 0, 1, 0x2306, 0);
878 reg_w(gspca_dev, 0, 0, 0x0d04, 0);
879 reg_w(gspca_dev, 0, 0, 0x2000, 0);
880 reg_w(gspca_dev, 0, 0x13, 0x2301, 0);
881 reg_w(gspca_dev, 0, 0, 0x2306, 0);
884 rc = spca504B_PollingDataReady(gspca_dev);
885 spca50x_GetFirmware(gspca_dev);
888 spca50x_GetFirmware(gspca_dev);
889 reg_r(gspca_dev, 0x00, 0x5002, 1);
890 gspca_dev->usb_buf[0] = 0;
891 reg_w(gspca_dev, 0x24, 0, 0, 1);
892 reg_r(gspca_dev, 0x24, 0, 1);
893 rc = spca504B_PollingDataReady(gspca_dev);
894 reg_w(gspca_dev, 0x34, 0, 0, 0);
895 spca504B_WaitCmdStatus(gspca_dev);
897 case BRIDGE_SPCA504C: /* pccam600 */
898 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
899 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
900 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
901 spca504_wait_status(gspca_dev);
902 if (sd->subtype == LogitechClickSmart420)
903 write_vector(gspca_dev,
904 spca504A_clicksmart420_open_data);
906 write_vector(gspca_dev, spca504_pccam600_open_data);
907 err_code = spca50x_setup_qtable(gspca_dev,
909 0x2840, qtable_creative_pccam);
911 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
916 /* case BRIDGE_SPCA504: */
917 PDEBUG(D_STREAM, "Opening SPCA504");
918 if (sd->subtype == AiptekMiniPenCam13) {
919 /*****************************/
920 for (i = 0; i < 6; i++)
921 info[i] = reg_r_1(gspca_dev, i);
923 "Read info: %d %d %d %d %d %d."
924 " Should be 1,0,2,2,0,0",
925 info[0], info[1], info[2],
926 info[3], info[4], info[5]);
927 /* spca504a aiptek */
928 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
929 spca504A_acknowledged_command(gspca_dev, 0x24,
931 /* Twice sequencial need status 0xff->0x9e->0x9d */
932 spca504A_acknowledged_command(gspca_dev, 0x24,
935 spca504A_acknowledged_command(gspca_dev, 0x24,
937 /******************************/
938 /* spca504a aiptek */
939 spca504A_acknowledged_command(gspca_dev, 0x08,
941 /* reg_write (dev, 0, 0x2000, 0); */
942 /* reg_write (dev, 0, 0x2883, 1); */
943 /* spca504A_acknowledged_command (gspca_dev, 0x08,
945 /* spca504A_acknowledged_command (gspca_dev, 0x24,
947 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
948 reg_w_riv(dev, 0x0, 0x2310, 0x05);
949 spca504A_acknowledged_command(gspca_dev, 0x01,
953 reg_w_riv(dev, 0, 0x2000, 0);
954 reg_w_riv(dev, 0, 0x2883, 1);
955 err_code = spca50x_setup_qtable(gspca_dev,
958 qtable_spca504_default);
960 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
968 static int sd_start(struct gspca_dev *gspca_dev)
970 struct sd *sd = (struct sd *) gspca_dev;
971 struct usb_device *dev = gspca_dev->dev;
977 /* create the JPEG header */
978 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
979 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
980 0x22); /* JPEG 411 */
981 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
983 if (sd->bridge == BRIDGE_SPCA504B)
984 spca504B_setQtable(gspca_dev);
985 spca504B_SetSizeType(gspca_dev);
986 switch (sd->bridge) {
988 /* case BRIDGE_SPCA504B: */
989 /* case BRIDGE_SPCA533: */
990 /* case BRIDGE_SPCA536: */
991 if (sd->subtype == MegapixV4 ||
992 sd->subtype == LogitechClickSmart820) {
993 reg_w(gspca_dev, 0xf0, 0, 0, 0);
994 spca504B_WaitCmdStatus(gspca_dev);
995 reg_r(gspca_dev, 0xf0, 4, 0);
996 spca504B_WaitCmdStatus(gspca_dev);
998 reg_w(gspca_dev, 0x31, 0, 4, 0);
999 spca504B_WaitCmdStatus(gspca_dev);
1000 rc = spca504B_PollingDataReady(gspca_dev);
1003 case BRIDGE_SPCA504:
1004 if (sd->subtype == AiptekMiniPenCam13) {
1005 for (i = 0; i < 6; i++)
1006 info[i] = reg_r_1(gspca_dev, i);
1008 "Read info: %d %d %d %d %d %d."
1009 " Should be 1,0,2,2,0,0",
1010 info[0], info[1], info[2],
1011 info[3], info[4], info[5]);
1012 /* spca504a aiptek */
1013 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1014 spca504A_acknowledged_command(gspca_dev, 0x24,
1016 /* Twice sequencial need status 0xff->0x9e->0x9d */
1017 spca504A_acknowledged_command(gspca_dev, 0x24,
1019 spca504A_acknowledged_command(gspca_dev, 0x24,
1022 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1023 for (i = 0; i < 6; i++)
1024 info[i] = reg_r_1(gspca_dev, i);
1026 "Read info: %d %d %d %d %d %d."
1027 " Should be 1,0,2,2,0,0",
1028 info[0], info[1], info[2],
1029 info[3], info[4], info[5]);
1030 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1031 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1033 spca504B_SetSizeType(gspca_dev);
1034 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1035 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1037 case BRIDGE_SPCA504C:
1038 if (sd->subtype == LogitechClickSmart420) {
1039 write_vector(gspca_dev,
1040 spca504A_clicksmart420_init_data);
1042 write_vector(gspca_dev, spca504_pccam600_init_data);
1044 enable = (sd->autogain ? 0x04 : 0x01);
1045 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1046 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
1048 /* set default exposure compensation and whiteness balance */
1049 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1050 reg_w_riv(dev, 0x30, 0x0002, 1600);
1051 spca504B_SetSizeType(gspca_dev);
1054 sp5xx_initContBrigHueRegisters(gspca_dev);
1058 static void sd_stopN(struct gspca_dev *gspca_dev)
1060 struct sd *sd = (struct sd *) gspca_dev;
1061 struct usb_device *dev = gspca_dev->dev;
1063 switch (sd->bridge) {
1065 /* case BRIDGE_SPCA533: */
1066 /* case BRIDGE_SPCA536: */
1067 /* case BRIDGE_SPCA504B: */
1068 reg_w(gspca_dev, 0x31, 0, 0, 0);
1069 spca504B_WaitCmdStatus(gspca_dev);
1070 spca504B_PollingDataReady(gspca_dev);
1072 case BRIDGE_SPCA504:
1073 case BRIDGE_SPCA504C:
1074 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
1076 if (sd->subtype == AiptekMiniPenCam13) {
1077 /* spca504a aiptek */
1078 /* spca504A_acknowledged_command(gspca_dev, 0x08,
1080 spca504A_acknowledged_command(gspca_dev, 0x24,
1081 0x00, 0x00, 0x9d, 1);
1082 spca504A_acknowledged_command(gspca_dev, 0x01,
1083 0x0f, 0x00, 0xff, 1);
1085 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1086 reg_w_riv(dev, 0x01, 0x000f, 0x00);
1092 static void sd_stop0(struct gspca_dev *gspca_dev)
1094 struct sd *sd = (struct sd *) gspca_dev;
1096 kfree(sd->jpeg_hdr);
1099 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1100 struct gspca_frame *frame, /* target */
1101 __u8 *data, /* isoc packet */
1102 int len) /* iso packet length */
1104 struct sd *sd = (struct sd *) gspca_dev;
1106 unsigned char *s, *d;
1107 static unsigned char ffd9[] = {0xff, 0xd9};
1109 /* frames are jpeg 4.1.1 without 0xff escape */
1110 switch (sd->bridge) {
1111 case BRIDGE_SPCA533:
1112 if (data[0] == 0xff) {
1113 if (data[1] != 0x01) { /* drop packet */
1114 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1118 data += SPCA533_OFFSET_DATA;
1119 len -= SPCA533_OFFSET_DATA;
1125 case BRIDGE_SPCA536:
1126 if (data[0] == 0xff) {
1128 data += SPCA536_OFFSET_DATA;
1129 len -= SPCA536_OFFSET_DATA;
1136 /* case BRIDGE_SPCA504: */
1137 /* case BRIDGE_SPCA504B: */
1139 case 0xfe: /* start of frame */
1141 data += SPCA50X_OFFSET_DATA;
1142 len -= SPCA50X_OFFSET_DATA;
1144 case 0xff: /* drop packet */
1145 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1153 case BRIDGE_SPCA504C:
1155 case 0xfe: /* start of frame */
1157 data += SPCA504_PCCAM600_OFFSET_DATA;
1158 len -= SPCA504_PCCAM600_OFFSET_DATA;
1160 case 0xff: /* drop packet */
1161 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1170 if (sof) { /* start of frame */
1171 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1174 /* put the JPEG header in the new frame */
1175 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
1176 sd->jpeg_hdr, JPEG_HDR_SZ);
1179 /* add 0x00 after 0xff */
1180 for (i = len; --i >= 0; )
1181 if (data[i] == 0xff)
1183 if (i < 0) { /* no 0xff */
1184 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1189 for (i = 0; i < len; i++) {
1194 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1195 sd->packet, d - sd->packet);
1198 static void setbrightness(struct gspca_dev *gspca_dev)
1200 struct sd *sd = (struct sd *) gspca_dev;
1201 struct usb_device *dev = gspca_dev->dev;
1203 switch (sd->bridge) {
1205 /* case BRIDGE_SPCA533: */
1206 /* case BRIDGE_SPCA504B: */
1207 /* case BRIDGE_SPCA504: */
1208 /* case BRIDGE_SPCA504C: */
1209 reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
1211 case BRIDGE_SPCA536:
1212 reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
1217 static void setcontrast(struct gspca_dev *gspca_dev)
1219 struct sd *sd = (struct sd *) gspca_dev;
1220 struct usb_device *dev = gspca_dev->dev;
1222 switch (sd->bridge) {
1224 /* case BRIDGE_SPCA533: */
1225 /* case BRIDGE_SPCA504B: */
1226 /* case BRIDGE_SPCA504: */
1227 /* case BRIDGE_SPCA504C: */
1228 reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
1230 case BRIDGE_SPCA536:
1231 reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
1236 static void setcolors(struct gspca_dev *gspca_dev)
1238 struct sd *sd = (struct sd *) gspca_dev;
1239 struct usb_device *dev = gspca_dev->dev;
1241 switch (sd->bridge) {
1243 /* case BRIDGE_SPCA533: */
1244 /* case BRIDGE_SPCA504B: */
1245 /* case BRIDGE_SPCA504: */
1246 /* case BRIDGE_SPCA504C: */
1247 reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
1249 case BRIDGE_SPCA536:
1250 reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
1255 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1257 struct sd *sd = (struct sd *) gspca_dev;
1259 sd->brightness = val;
1260 if (gspca_dev->streaming)
1261 setbrightness(gspca_dev);
1265 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1267 struct sd *sd = (struct sd *) gspca_dev;
1269 *val = sd->brightness;
1273 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1275 struct sd *sd = (struct sd *) gspca_dev;
1278 if (gspca_dev->streaming)
1279 setcontrast(gspca_dev);
1283 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1285 struct sd *sd = (struct sd *) gspca_dev;
1287 *val = sd->contrast;
1291 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1293 struct sd *sd = (struct sd *) gspca_dev;
1296 if (gspca_dev->streaming)
1297 setcolors(gspca_dev);
1301 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1303 struct sd *sd = (struct sd *) gspca_dev;
1309 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1311 struct sd *sd = (struct sd *) gspca_dev;
1317 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1319 struct sd *sd = (struct sd *) gspca_dev;
1321 *val = sd->autogain;
1325 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1326 struct v4l2_jpegcompression *jcomp)
1328 struct sd *sd = (struct sd *) gspca_dev;
1330 if (jcomp->quality < QUALITY_MIN)
1331 sd->quality = QUALITY_MIN;
1332 else if (jcomp->quality > QUALITY_MAX)
1333 sd->quality = QUALITY_MAX;
1335 sd->quality = jcomp->quality;
1336 if (gspca_dev->streaming)
1337 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1341 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1342 struct v4l2_jpegcompression *jcomp)
1344 struct sd *sd = (struct sd *) gspca_dev;
1346 memset(jcomp, 0, sizeof *jcomp);
1347 jcomp->quality = sd->quality;
1348 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1349 | V4L2_JPEG_MARKER_DQT;
1353 /* sub-driver description */
1354 static const struct sd_desc sd_desc = {
1355 .name = MODULE_NAME,
1357 .nctrls = ARRAY_SIZE(sd_ctrls),
1358 .config = sd_config,
1363 .pkt_scan = sd_pkt_scan,
1364 .get_jcomp = sd_get_jcomp,
1365 .set_jcomp = sd_set_jcomp,
1368 /* -- module initialisation -- */
1369 #define BS(bridge, subtype) \
1370 .driver_info = (BRIDGE_ ## bridge << 8) \
1372 static const __devinitdata struct usb_device_id device_table[] = {
1373 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1374 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1375 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1376 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1377 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1378 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1379 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1380 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1381 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1382 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1383 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1384 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1385 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1386 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1387 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1388 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1389 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1390 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1391 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1392 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1393 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1394 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1395 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1396 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1397 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1398 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1399 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1400 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1401 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1402 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1403 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1404 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1405 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1406 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1407 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1408 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1409 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1410 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1411 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1412 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1413 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1414 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1415 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1416 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1417 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1418 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1419 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1420 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1421 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1422 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1423 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1424 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1425 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1426 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1427 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1428 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1429 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1432 MODULE_DEVICE_TABLE(usb, device_table);
1434 /* -- device connect -- */
1435 static int sd_probe(struct usb_interface *intf,
1436 const struct usb_device_id *id)
1438 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1442 static struct usb_driver sd_driver = {
1443 .name = MODULE_NAME,
1444 .id_table = device_table,
1446 .disconnect = gspca_disconnect,
1448 .suspend = gspca_suspend,
1449 .resume = gspca_resume,
1453 /* -- module insert / remove -- */
1454 static int __init sd_mod_init(void)
1457 ret = usb_register(&sd_driver);
1460 PDEBUG(D_PROBE, "registered");
1463 static void __exit sd_mod_exit(void)
1465 usb_deregister(&sd_driver);
1466 PDEBUG(D_PROBE, "deregistered");
1469 module_init(sd_mod_init);
1470 module_exit(sd_mod_exit);