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 unsigned char brightness;
36 unsigned char contrast;
38 unsigned char autogain;
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
59 /* V4L2 controls supported by the driver */
60 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
61 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
62 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
63 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
64 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
65 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
66 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
67 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
69 static struct ctrl sd_ctrls[] = {
70 #define SD_BRIGHTNESS 0
73 .id = V4L2_CID_BRIGHTNESS,
74 .type = V4L2_CTRL_TYPE_INTEGER,
81 .set = sd_setbrightness,
82 .get = sd_getbrightness,
87 .id = V4L2_CID_CONTRAST,
88 .type = V4L2_CTRL_TYPE_INTEGER,
93 .default_value = 0x20,
95 .set = sd_setcontrast,
96 .get = sd_getcontrast,
101 .id = V4L2_CID_SATURATION,
102 .type = V4L2_CTRL_TYPE_INTEGER,
107 .default_value = 0x1a,
112 #define SD_AUTOGAIN 3
115 .id = V4L2_CID_AUTOGAIN,
116 .type = V4L2_CTRL_TYPE_BOOLEAN,
123 .set = sd_setautogain,
124 .get = sd_getautogain,
128 static const struct v4l2_pix_format vga_mode[] = {
129 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .sizeimage = 320 * 240 * 3 / 8 + 590,
132 .colorspace = V4L2_COLORSPACE_JPEG,
134 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .sizeimage = 640 * 480 * 3 / 8 + 590,
137 .colorspace = V4L2_COLORSPACE_JPEG,
141 static const struct v4l2_pix_format custom_mode[] = {
142 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .sizeimage = 320 * 240 * 3 / 8 + 590,
145 .colorspace = V4L2_COLORSPACE_JPEG,
147 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
149 .sizeimage = 464 * 480 * 3 / 8 + 590,
150 .colorspace = V4L2_COLORSPACE_JPEG,
154 static const struct v4l2_pix_format vga_mode2[] = {
155 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
157 .sizeimage = 176 * 144 * 3 / 8 + 590,
158 .colorspace = V4L2_COLORSPACE_JPEG,
160 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
162 .sizeimage = 320 * 240 * 3 / 8 + 590,
163 .colorspace = V4L2_COLORSPACE_JPEG,
165 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
167 .sizeimage = 352 * 288 * 3 / 8 + 590,
168 .colorspace = V4L2_COLORSPACE_JPEG,
170 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
172 .sizeimage = 640 * 480 * 3 / 8 + 590,
173 .colorspace = V4L2_COLORSPACE_JPEG,
177 #define SPCA50X_OFFSET_DATA 10
178 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
179 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
180 #define SPCA504_PCCAM600_OFFSET_MODE 5
181 #define SPCA504_PCCAM600_OFFSET_DATA 14
182 /* Frame packet header offsets for the spca533 */
183 #define SPCA533_OFFSET_DATA 16
184 #define SPCA533_OFFSET_FRAMSEQ 15
185 /* Frame packet header offsets for the spca536 */
186 #define SPCA536_OFFSET_DATA 4
187 #define SPCA536_OFFSET_FRAMSEQ 1
189 /* Initialisation data for the Creative PC-CAM 600 */
190 static const __u16 spca504_pccam600_init_data[][3] = {
191 /* {0xa0, 0x0000, 0x0503}, * capture mode */
192 {0x00, 0x0000, 0x2000},
193 {0x00, 0x0013, 0x2301},
194 {0x00, 0x0003, 0x2000},
195 {0x00, 0x0001, 0x21ac},
196 {0x00, 0x0001, 0x21a6},
197 {0x00, 0x0000, 0x21a7}, /* brightness */
198 {0x00, 0x0020, 0x21a8}, /* contrast */
199 {0x00, 0x0001, 0x21ac}, /* sat/hue */
200 {0x00, 0x0000, 0x21ad}, /* hue */
201 {0x00, 0x001a, 0x21ae}, /* saturation */
202 {0x00, 0x0002, 0x21a3}, /* gamma */
203 {0x30, 0x0154, 0x0008},
204 {0x30, 0x0004, 0x0006},
205 {0x30, 0x0258, 0x0009},
206 {0x30, 0x0004, 0x0000},
207 {0x30, 0x0093, 0x0004},
208 {0x30, 0x0066, 0x0005},
209 {0x00, 0x0000, 0x2000},
210 {0x00, 0x0013, 0x2301},
211 {0x00, 0x0003, 0x2000},
212 {0x00, 0x0013, 0x2301},
213 {0x00, 0x0003, 0x2000},
217 /* Creative PC-CAM 600 specific open data, sent before using the
218 * generic initialisation data from spca504_open_data.
220 static const __u16 spca504_pccam600_open_data[][3] = {
221 {0x00, 0x0001, 0x2501},
222 {0x20, 0x0500, 0x0001}, /* snapshot mode */
223 {0x00, 0x0003, 0x2880},
224 {0x00, 0x0001, 0x2881},
228 /* Initialisation data for the logitech clicksmart 420 */
229 static const __u16 spca504A_clicksmart420_init_data[][3] = {
230 /* {0xa0, 0x0000, 0x0503}, * capture mode */
231 {0x00, 0x0000, 0x2000},
232 {0x00, 0x0013, 0x2301},
233 {0x00, 0x0003, 0x2000},
234 {0x00, 0x0001, 0x21ac},
235 {0x00, 0x0001, 0x21a6},
236 {0x00, 0x0000, 0x21a7}, /* brightness */
237 {0x00, 0x0020, 0x21a8}, /* contrast */
238 {0x00, 0x0001, 0x21ac}, /* sat/hue */
239 {0x00, 0x0000, 0x21ad}, /* hue */
240 {0x00, 0x001a, 0x21ae}, /* saturation */
241 {0x00, 0x0002, 0x21a3}, /* gamma */
242 {0x30, 0x0004, 0x000a},
243 {0xb0, 0x0001, 0x0000},
246 {0x0a1, 0x0080, 0x0001},
247 {0x30, 0x0049, 0x0000},
248 {0x30, 0x0060, 0x0005},
249 {0x0c, 0x0004, 0x0000},
250 {0x00, 0x0000, 0x0000},
251 {0x00, 0x0000, 0x2000},
252 {0x00, 0x0013, 0x2301},
253 {0x00, 0x0003, 0x2000},
254 {0x00, 0x0000, 0x2000},
259 /* clicksmart 420 open data ? */
260 static const __u16 spca504A_clicksmart420_open_data[][3] = {
261 {0x00, 0x0001, 0x2501},
262 {0x20, 0x0502, 0x0000},
263 {0x06, 0x0000, 0x0000},
264 {0x00, 0x0004, 0x2880},
265 {0x00, 0x0001, 0x2881},
266 /* look like setting a qTable */
267 {0x00, 0x0006, 0x2800},
268 {0x00, 0x0004, 0x2801},
269 {0x00, 0x0004, 0x2802},
270 {0x00, 0x0006, 0x2803},
271 {0x00, 0x000a, 0x2804},
272 {0x00, 0x0010, 0x2805},
273 {0x00, 0x0014, 0x2806},
274 {0x00, 0x0018, 0x2807},
275 {0x00, 0x0005, 0x2808},
276 {0x00, 0x0005, 0x2809},
277 {0x00, 0x0006, 0x280a},
278 {0x00, 0x0008, 0x280b},
279 {0x00, 0x000a, 0x280c},
280 {0x00, 0x0017, 0x280d},
281 {0x00, 0x0018, 0x280e},
282 {0x00, 0x0016, 0x280f},
284 {0x00, 0x0006, 0x2810},
285 {0x00, 0x0005, 0x2811},
286 {0x00, 0x0006, 0x2812},
287 {0x00, 0x000a, 0x2813},
288 {0x00, 0x0010, 0x2814},
289 {0x00, 0x0017, 0x2815},
290 {0x00, 0x001c, 0x2816},
291 {0x00, 0x0016, 0x2817},
292 {0x00, 0x0006, 0x2818},
293 {0x00, 0x0007, 0x2819},
294 {0x00, 0x0009, 0x281a},
295 {0x00, 0x000c, 0x281b},
296 {0x00, 0x0014, 0x281c},
297 {0x00, 0x0023, 0x281d},
298 {0x00, 0x0020, 0x281e},
299 {0x00, 0x0019, 0x281f},
301 {0x00, 0x0007, 0x2820},
302 {0x00, 0x0009, 0x2821},
303 {0x00, 0x000f, 0x2822},
304 {0x00, 0x0016, 0x2823},
305 {0x00, 0x001b, 0x2824},
306 {0x00, 0x002c, 0x2825},
307 {0x00, 0x0029, 0x2826},
308 {0x00, 0x001f, 0x2827},
309 {0x00, 0x000a, 0x2828},
310 {0x00, 0x000e, 0x2829},
311 {0x00, 0x0016, 0x282a},
312 {0x00, 0x001a, 0x282b},
313 {0x00, 0x0020, 0x282c},
314 {0x00, 0x002a, 0x282d},
315 {0x00, 0x002d, 0x282e},
316 {0x00, 0x0025, 0x282f},
318 {0x00, 0x0014, 0x2830},
319 {0x00, 0x001a, 0x2831},
320 {0x00, 0x001f, 0x2832},
321 {0x00, 0x0023, 0x2833},
322 {0x00, 0x0029, 0x2834},
323 {0x00, 0x0030, 0x2835},
324 {0x00, 0x0030, 0x2836},
325 {0x00, 0x0028, 0x2837},
326 {0x00, 0x001d, 0x2838},
327 {0x00, 0x0025, 0x2839},
328 {0x00, 0x0026, 0x283a},
329 {0x00, 0x0027, 0x283b},
330 {0x00, 0x002d, 0x283c},
331 {0x00, 0x0028, 0x283d},
332 {0x00, 0x0029, 0x283e},
333 {0x00, 0x0028, 0x283f},
335 {0x00, 0x0007, 0x2840},
336 {0x00, 0x0007, 0x2841},
337 {0x00, 0x000a, 0x2842},
338 {0x00, 0x0013, 0x2843},
339 {0x00, 0x0028, 0x2844},
340 {0x00, 0x0028, 0x2845},
341 {0x00, 0x0028, 0x2846},
342 {0x00, 0x0028, 0x2847},
343 {0x00, 0x0007, 0x2848},
344 {0x00, 0x0008, 0x2849},
345 {0x00, 0x000a, 0x284a},
346 {0x00, 0x001a, 0x284b},
347 {0x00, 0x0028, 0x284c},
348 {0x00, 0x0028, 0x284d},
349 {0x00, 0x0028, 0x284e},
350 {0x00, 0x0028, 0x284f},
352 {0x00, 0x000a, 0x2850},
353 {0x00, 0x000a, 0x2851},
354 {0x00, 0x0016, 0x2852},
355 {0x00, 0x0028, 0x2853},
356 {0x00, 0x0028, 0x2854},
357 {0x00, 0x0028, 0x2855},
358 {0x00, 0x0028, 0x2856},
359 {0x00, 0x0028, 0x2857},
360 {0x00, 0x0013, 0x2858},
361 {0x00, 0x001a, 0x2859},
362 {0x00, 0x0028, 0x285a},
363 {0x00, 0x0028, 0x285b},
364 {0x00, 0x0028, 0x285c},
365 {0x00, 0x0028, 0x285d},
366 {0x00, 0x0028, 0x285e},
367 {0x00, 0x0028, 0x285f},
369 {0x00, 0x0028, 0x2860},
370 {0x00, 0x0028, 0x2861},
371 {0x00, 0x0028, 0x2862},
372 {0x00, 0x0028, 0x2863},
373 {0x00, 0x0028, 0x2864},
374 {0x00, 0x0028, 0x2865},
375 {0x00, 0x0028, 0x2866},
376 {0x00, 0x0028, 0x2867},
377 {0x00, 0x0028, 0x2868},
378 {0x00, 0x0028, 0x2869},
379 {0x00, 0x0028, 0x286a},
380 {0x00, 0x0028, 0x286b},
381 {0x00, 0x0028, 0x286c},
382 {0x00, 0x0028, 0x286d},
383 {0x00, 0x0028, 0x286e},
384 {0x00, 0x0028, 0x286f},
386 {0x00, 0x0028, 0x2870},
387 {0x00, 0x0028, 0x2871},
388 {0x00, 0x0028, 0x2872},
389 {0x00, 0x0028, 0x2873},
390 {0x00, 0x0028, 0x2874},
391 {0x00, 0x0028, 0x2875},
392 {0x00, 0x0028, 0x2876},
393 {0x00, 0x0028, 0x2877},
394 {0x00, 0x0028, 0x2878},
395 {0x00, 0x0028, 0x2879},
396 {0x00, 0x0028, 0x287a},
397 {0x00, 0x0028, 0x287b},
398 {0x00, 0x0028, 0x287c},
399 {0x00, 0x0028, 0x287d},
400 {0x00, 0x0028, 0x287e},
401 {0x00, 0x0028, 0x287f},
403 {0xa0, 0x0000, 0x0503},
407 static const __u8 qtable_creative_pccam[2][64] = {
408 { /* Q-table Y-components */
409 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
410 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
411 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
412 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
413 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
414 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
415 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
416 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
417 { /* Q-table C-components */
418 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
419 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
420 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
421 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
424 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
425 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
428 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
429 * except for one byte. Possibly a typo?
432 static const __u8 qtable_spca504_default[2][64] = {
433 { /* Q-table Y-components */
434 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
435 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
436 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
437 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
438 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
439 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
440 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
441 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
443 { /* Q-table C-components */
444 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
445 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
446 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
447 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
450 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
451 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
454 /* read <len> bytes to gspca_dev->usb_buf */
455 static void reg_r(struct gspca_dev *gspca_dev,
461 if (len > USB_BUF_SZ) {
462 err("reg_r: buffer overflow");
466 usb_control_msg(gspca_dev->dev,
467 usb_rcvctrlpipe(gspca_dev->dev, 0),
469 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
472 len ? gspca_dev->usb_buf : NULL, len,
476 /* write <len> bytes from gspca_dev->usb_buf */
477 static void reg_w(struct gspca_dev *gspca_dev,
484 if (len > USB_BUF_SZ) {
485 err("reg_w: buffer overflow");
489 usb_control_msg(gspca_dev->dev,
490 usb_sndctrlpipe(gspca_dev->dev, 0),
492 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
494 len ? gspca_dev->usb_buf : NULL, len,
498 /* write req / index / value */
499 static int reg_w_riv(struct usb_device *dev,
500 __u16 req, __u16 index, __u16 value)
504 ret = usb_control_msg(dev,
505 usb_sndctrlpipe(dev, 0),
507 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
508 value, index, NULL, 0, 500);
509 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
510 req, index, value, ret);
512 PDEBUG(D_ERR, "reg write: error %d", ret);
517 static int reg_r_1(struct gspca_dev *gspca_dev,
518 __u16 value) /* wValue */
522 ret = usb_control_msg(gspca_dev->dev,
523 usb_rcvctrlpipe(gspca_dev->dev, 0),
525 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
528 gspca_dev->usb_buf, 1,
531 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
534 return gspca_dev->usb_buf[0];
537 /* read 1 or 2 bytes - returns < 0 if error */
538 static int reg_r_12(struct gspca_dev *gspca_dev,
539 __u16 req, /* bRequest */
540 __u16 index, /* wIndex */
541 __u16 length) /* wLength (1 or 2 only) */
545 gspca_dev->usb_buf[1] = 0;
546 ret = usb_control_msg(gspca_dev->dev,
547 usb_rcvctrlpipe(gspca_dev->dev, 0),
549 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
552 gspca_dev->usb_buf, length,
555 PDEBUG(D_ERR, "reg_read err %d", ret);
558 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
561 static int write_vector(struct gspca_dev *gspca_dev,
562 const __u16 data[][3])
564 struct usb_device *dev = gspca_dev->dev;
567 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
568 ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
571 "Register write failed for 0x%x,0x%x,0x%x",
572 data[i][0], data[i][1], data[i][2]);
580 static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
581 unsigned int request,
584 const __u8 qtable[2][64])
586 struct usb_device *dev = gspca_dev->dev;
589 /* loop over y components */
590 for (i = 0; i < 64; i++) {
591 err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
596 /* loop over c components */
597 for (i = 0; i < 64; i++) {
598 err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
605 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
606 __u16 req, __u16 idx, __u16 val)
608 struct usb_device *dev = gspca_dev->dev;
611 reg_w_riv(dev, req, idx, val);
612 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
613 reg_w_riv(dev, req, idx, val);
615 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
618 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
619 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
622 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
624 __u16 idx, __u16 val, __u8 stat, __u8 count)
626 struct usb_device *dev = gspca_dev->dev;
630 reg_w_riv(dev, req, idx, val);
631 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
633 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
637 while (--count > 0) {
639 /* gsmart mini2 write a each wait setting 1 ms is enought */
640 /* reg_w_riv(dev, req, idx, val); */
641 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
642 if (status == endcode) {
643 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
644 status, 200 - count);
650 static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
654 while (--count > 0) {
655 reg_r(gspca_dev, 0x21, 0, 1);
656 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
660 return gspca_dev->usb_buf[0];
663 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
667 while (--count > 0) {
668 reg_r(gspca_dev, 0x21, 1, 1);
669 if (gspca_dev->usb_buf[0] != 0) {
670 gspca_dev->usb_buf[0] = 0;
671 reg_w(gspca_dev, 0x21, 0, 1, 1);
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;
695 struct usb_device *dev = gspca_dev->dev;
700 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
702 switch (sd->bridge) {
704 reg_w(gspca_dev, 0x31, 0, 0, 0);
705 spca504B_WaitCmdStatus(gspca_dev);
706 rc = spca504B_PollingDataReady(gspca_dev);
707 spca50x_GetFirmware(gspca_dev);
708 gspca_dev->usb_buf[0] = 2; /* type */
709 reg_w(gspca_dev, 0x24, 0, 8, 1);
710 reg_r(gspca_dev, 0x24, 8, 1);
712 gspca_dev->usb_buf[0] = Size;
713 reg_w(gspca_dev, 0x25, 0, 4, 1);
714 reg_r(gspca_dev, 0x25, 4, 1); /* size */
715 rc = spca504B_PollingDataReady(gspca_dev);
717 /* Init the cam width height with some values get on init ? */
718 reg_w(gspca_dev, 0x31, 0, 4, 0);
719 spca504B_WaitCmdStatus(gspca_dev);
720 rc = spca504B_PollingDataReady(gspca_dev);
723 /* case BRIDGE_SPCA504B: */
724 /* case BRIDGE_SPCA536: */
725 gspca_dev->usb_buf[0] = Size;
726 reg_w(gspca_dev, 0x25, 0, 4, 1);
727 reg_r(gspca_dev, 0x25, 4, 1); /* size */
729 gspca_dev->usb_buf[0] = Type;
730 reg_w(gspca_dev, 0x27, 0, 0, 1);
731 reg_r(gspca_dev, 0x27, 0, 1); /* type */
732 rc = spca504B_PollingDataReady(gspca_dev);
736 if (sd->subtype == AiptekMiniPenCam13) {
737 /* spca504a aiptek */
738 spca504A_acknowledged_command(gspca_dev,
740 0x80 | (Size & 0x0f), 1);
741 spca504A_acknowledged_command(gspca_dev,
744 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
747 case BRIDGE_SPCA504C:
749 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
750 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
755 static void spca504_wait_status(struct gspca_dev *gspca_dev)
761 /* With this we get the status, when return 0 it's all ok */
762 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
768 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
770 gspca_dev->usb_buf[0] = 3;
771 reg_w(gspca_dev, 0x26, 0, 0, 1);
772 reg_r(gspca_dev, 0x26, 0, 1);
773 spca504B_PollingDataReady(gspca_dev);
776 static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
778 struct sd *sd = (struct sd *) gspca_dev;
781 switch (sd->bridge) {
783 case BRIDGE_SPCA504C:
787 /* case BRIDGE_SPCA533: */
788 /* case BRIDGE_SPCA504B: */
789 reg_w(gspca_dev, 0, 0, 0x21a7, 0); /* brightness */
790 reg_w(gspca_dev, 0, 0x20, 0x21a8, 0); /* contrast */
791 reg_w(gspca_dev, 0, 0, 0x21ad, 0); /* hue */
792 reg_w(gspca_dev, 0, 1, 0x21ac, 0); /* sat/hue */
793 reg_w(gspca_dev, 0, 0x20, 0x21ae, 0); /* saturation */
794 reg_w(gspca_dev, 0, 0, 0x21a3, 0); /* gamma */
797 reg_w(gspca_dev, 0, 0, 0x20f0, 0);
798 reg_w(gspca_dev, 0, 0x21, 0x20f1, 0);
799 reg_w(gspca_dev, 0, 0x40, 0x20f5, 0);
800 reg_w(gspca_dev, 0, 1, 0x20f4, 0);
801 reg_w(gspca_dev, 0, 0x40, 0x20f6, 0);
802 reg_w(gspca_dev, 0, 0, 0x2089, 0);
806 spca504B_PollingDataReady(gspca_dev);
809 /* this function is called at probe time */
810 static int sd_config(struct gspca_dev *gspca_dev,
811 const struct usb_device_id *id)
813 struct sd *sd = (struct sd *) gspca_dev;
816 cam = &gspca_dev->cam;
818 sd->bridge = id->driver_info >> 8;
819 sd->subtype = id->driver_info;
821 if (sd->subtype == AiptekMiniPenCam13) {
822 /* try to get the firmware as some cam answer 2.0.1.2.2
823 * and should be a spca504b then overwrite that setting */
824 reg_r(gspca_dev, 0x20, 0, 1);
825 switch (gspca_dev->usb_buf[0]) {
827 break; /* (right bridge/subtype) */
829 sd->bridge = BRIDGE_SPCA504B;
837 switch (sd->bridge) {
839 /* case BRIDGE_SPCA504B: */
840 /* case BRIDGE_SPCA504: */
841 /* case BRIDGE_SPCA536: */
842 cam->cam_mode = vga_mode;
843 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
846 cam->cam_mode = custom_mode;
847 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
849 case BRIDGE_SPCA504C:
850 cam->cam_mode = vga_mode2;
851 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
854 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
855 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
856 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
857 sd->quality = QUALITY_DEF;
861 /* this function is called at probe and resume time */
862 static int sd_init(struct gspca_dev *gspca_dev)
864 struct sd *sd = (struct sd *) gspca_dev;
865 struct usb_device *dev = gspca_dev->dev;
871 switch (sd->bridge) {
872 case BRIDGE_SPCA504B:
873 reg_w(gspca_dev, 0x1d, 0, 0, 0);
874 reg_w(gspca_dev, 0, 1, 0x2306, 0);
875 reg_w(gspca_dev, 0, 0, 0x0d04, 0);
876 reg_w(gspca_dev, 0, 0, 0x2000, 0);
877 reg_w(gspca_dev, 0, 0x13, 0x2301, 0);
878 reg_w(gspca_dev, 0, 0, 0x2306, 0);
881 rc = spca504B_PollingDataReady(gspca_dev);
882 spca50x_GetFirmware(gspca_dev);
885 spca50x_GetFirmware(gspca_dev);
886 reg_r(gspca_dev, 0x00, 0x5002, 1);
887 gspca_dev->usb_buf[0] = 0;
888 reg_w(gspca_dev, 0x24, 0, 0, 1);
889 reg_r(gspca_dev, 0x24, 0, 1);
890 rc = spca504B_PollingDataReady(gspca_dev);
891 reg_w(gspca_dev, 0x34, 0, 0, 0);
892 spca504B_WaitCmdStatus(gspca_dev);
894 case BRIDGE_SPCA504C: /* pccam600 */
895 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
896 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
897 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
898 spca504_wait_status(gspca_dev);
899 if (sd->subtype == LogitechClickSmart420)
900 write_vector(gspca_dev,
901 spca504A_clicksmart420_open_data);
903 write_vector(gspca_dev, spca504_pccam600_open_data);
904 err_code = spca50x_setup_qtable(gspca_dev,
906 0x2840, qtable_creative_pccam);
908 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
913 /* case BRIDGE_SPCA504: */
914 PDEBUG(D_STREAM, "Opening SPCA504");
915 if (sd->subtype == AiptekMiniPenCam13) {
916 /*****************************/
917 for (i = 0; i < 6; i++)
918 info[i] = reg_r_1(gspca_dev, i);
920 "Read info: %d %d %d %d %d %d."
921 " Should be 1,0,2,2,0,0",
922 info[0], info[1], info[2],
923 info[3], info[4], info[5]);
924 /* spca504a aiptek */
925 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
926 spca504A_acknowledged_command(gspca_dev, 0x24,
928 /* Twice sequencial need status 0xff->0x9e->0x9d */
929 spca504A_acknowledged_command(gspca_dev, 0x24,
932 spca504A_acknowledged_command(gspca_dev, 0x24,
934 /******************************/
935 /* spca504a aiptek */
936 spca504A_acknowledged_command(gspca_dev, 0x08,
938 /* reg_write (dev, 0, 0x2000, 0); */
939 /* reg_write (dev, 0, 0x2883, 1); */
940 /* spca504A_acknowledged_command (gspca_dev, 0x08,
942 /* spca504A_acknowledged_command (gspca_dev, 0x24,
944 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
945 reg_w_riv(dev, 0x0, 0x2310, 0x05);
946 spca504A_acknowledged_command(gspca_dev, 0x01,
950 reg_w_riv(dev, 0, 0x2000, 0);
951 reg_w_riv(dev, 0, 0x2883, 1);
952 err_code = spca50x_setup_qtable(gspca_dev,
955 qtable_spca504_default);
957 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
965 static int sd_start(struct gspca_dev *gspca_dev)
967 struct sd *sd = (struct sd *) gspca_dev;
968 struct usb_device *dev = gspca_dev->dev;
974 /* create the JPEG header */
975 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
976 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
977 0x22); /* JPEG 411 */
978 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
980 if (sd->bridge == BRIDGE_SPCA504B)
981 spca504B_setQtable(gspca_dev);
982 spca504B_SetSizeType(gspca_dev);
983 switch (sd->bridge) {
985 /* case BRIDGE_SPCA504B: */
986 /* case BRIDGE_SPCA533: */
987 /* case BRIDGE_SPCA536: */
988 if (sd->subtype == MegapixV4 ||
989 sd->subtype == LogitechClickSmart820) {
990 reg_w(gspca_dev, 0xf0, 0, 0, 0);
991 spca504B_WaitCmdStatus(gspca_dev);
992 reg_r(gspca_dev, 0xf0, 4, 0);
993 spca504B_WaitCmdStatus(gspca_dev);
995 reg_w(gspca_dev, 0x31, 0, 4, 0);
996 spca504B_WaitCmdStatus(gspca_dev);
997 rc = spca504B_PollingDataReady(gspca_dev);
1000 case BRIDGE_SPCA504:
1001 if (sd->subtype == AiptekMiniPenCam13) {
1002 for (i = 0; i < 6; i++)
1003 info[i] = reg_r_1(gspca_dev, i);
1005 "Read info: %d %d %d %d %d %d."
1006 " Should be 1,0,2,2,0,0",
1007 info[0], info[1], info[2],
1008 info[3], info[4], info[5]);
1009 /* spca504a aiptek */
1010 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1011 spca504A_acknowledged_command(gspca_dev, 0x24,
1013 /* Twice sequencial need status 0xff->0x9e->0x9d */
1014 spca504A_acknowledged_command(gspca_dev, 0x24,
1016 spca504A_acknowledged_command(gspca_dev, 0x24,
1019 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1020 for (i = 0; i < 6; i++)
1021 info[i] = reg_r_1(gspca_dev, i);
1023 "Read info: %d %d %d %d %d %d."
1024 " Should be 1,0,2,2,0,0",
1025 info[0], info[1], info[2],
1026 info[3], info[4], info[5]);
1027 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1028 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1030 spca504B_SetSizeType(gspca_dev);
1031 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1032 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1034 case BRIDGE_SPCA504C:
1035 if (sd->subtype == LogitechClickSmart420) {
1036 write_vector(gspca_dev,
1037 spca504A_clicksmart420_init_data);
1039 write_vector(gspca_dev, spca504_pccam600_init_data);
1041 enable = (sd->autogain ? 0x04 : 0x01);
1042 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1043 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
1045 /* set default exposure compensation and whiteness balance */
1046 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1047 reg_w_riv(dev, 0x30, 0x0002, 1600);
1048 spca504B_SetSizeType(gspca_dev);
1051 sp5xx_initContBrigHueRegisters(gspca_dev);
1055 static void sd_stopN(struct gspca_dev *gspca_dev)
1057 struct sd *sd = (struct sd *) gspca_dev;
1058 struct usb_device *dev = gspca_dev->dev;
1060 switch (sd->bridge) {
1062 /* case BRIDGE_SPCA533: */
1063 /* case BRIDGE_SPCA536: */
1064 /* case BRIDGE_SPCA504B: */
1065 reg_w(gspca_dev, 0x31, 0, 0, 0);
1066 spca504B_WaitCmdStatus(gspca_dev);
1067 spca504B_PollingDataReady(gspca_dev);
1069 case BRIDGE_SPCA504:
1070 case BRIDGE_SPCA504C:
1071 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
1073 if (sd->subtype == AiptekMiniPenCam13) {
1074 /* spca504a aiptek */
1075 /* spca504A_acknowledged_command(gspca_dev, 0x08,
1077 spca504A_acknowledged_command(gspca_dev, 0x24,
1078 0x00, 0x00, 0x9d, 1);
1079 spca504A_acknowledged_command(gspca_dev, 0x01,
1080 0x0f, 0x00, 0xff, 1);
1082 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1083 reg_w_riv(dev, 0x01, 0x000f, 0x00);
1089 static void sd_stop0(struct gspca_dev *gspca_dev)
1091 struct sd *sd = (struct sd *) gspca_dev;
1093 kfree(sd->jpeg_hdr);
1096 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1097 struct gspca_frame *frame, /* target */
1098 __u8 *data, /* isoc packet */
1099 int len) /* iso packet length */
1101 struct sd *sd = (struct sd *) gspca_dev;
1103 static unsigned char ffd9[] = {0xff, 0xd9};
1105 /* frames are jpeg 4.1.1 without 0xff escape */
1106 switch (sd->bridge) {
1107 case BRIDGE_SPCA533:
1108 if (data[0] == 0xff) {
1109 if (data[1] != 0x01) { /* drop packet */
1110 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1114 data += SPCA533_OFFSET_DATA;
1115 len -= SPCA533_OFFSET_DATA;
1121 case BRIDGE_SPCA536:
1122 if (data[0] == 0xff) {
1124 data += SPCA536_OFFSET_DATA;
1125 len -= SPCA536_OFFSET_DATA;
1132 /* case BRIDGE_SPCA504: */
1133 /* case BRIDGE_SPCA504B: */
1135 case 0xfe: /* start of frame */
1137 data += SPCA50X_OFFSET_DATA;
1138 len -= SPCA50X_OFFSET_DATA;
1140 case 0xff: /* drop packet */
1141 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1149 case BRIDGE_SPCA504C:
1151 case 0xfe: /* start of frame */
1153 data += SPCA504_PCCAM600_OFFSET_DATA;
1154 len -= SPCA504_PCCAM600_OFFSET_DATA;
1156 case 0xff: /* drop packet */
1157 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1166 if (sof) { /* start of frame */
1167 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1170 /* put the JPEG header in the new frame */
1171 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
1172 sd->jpeg_hdr, JPEG_HDR_SZ);
1175 /* add 0x00 after 0xff */
1178 if (data[i] == 0xff) {
1179 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1188 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1191 static void setbrightness(struct gspca_dev *gspca_dev)
1193 struct sd *sd = (struct sd *) gspca_dev;
1194 struct usb_device *dev = gspca_dev->dev;
1196 switch (sd->bridge) {
1198 /* case BRIDGE_SPCA533: */
1199 /* case BRIDGE_SPCA504B: */
1200 /* case BRIDGE_SPCA504: */
1201 /* case BRIDGE_SPCA504C: */
1202 reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
1204 case BRIDGE_SPCA536:
1205 reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
1210 static void setcontrast(struct gspca_dev *gspca_dev)
1212 struct sd *sd = (struct sd *) gspca_dev;
1213 struct usb_device *dev = gspca_dev->dev;
1215 switch (sd->bridge) {
1217 /* case BRIDGE_SPCA533: */
1218 /* case BRIDGE_SPCA504B: */
1219 /* case BRIDGE_SPCA504: */
1220 /* case BRIDGE_SPCA504C: */
1221 reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
1223 case BRIDGE_SPCA536:
1224 reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
1229 static void setcolors(struct gspca_dev *gspca_dev)
1231 struct sd *sd = (struct sd *) gspca_dev;
1232 struct usb_device *dev = gspca_dev->dev;
1234 switch (sd->bridge) {
1236 /* case BRIDGE_SPCA533: */
1237 /* case BRIDGE_SPCA504B: */
1238 /* case BRIDGE_SPCA504: */
1239 /* case BRIDGE_SPCA504C: */
1240 reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
1242 case BRIDGE_SPCA536:
1243 reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
1248 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1250 struct sd *sd = (struct sd *) gspca_dev;
1252 sd->brightness = val;
1253 if (gspca_dev->streaming)
1254 setbrightness(gspca_dev);
1258 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1260 struct sd *sd = (struct sd *) gspca_dev;
1262 *val = sd->brightness;
1266 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1268 struct sd *sd = (struct sd *) gspca_dev;
1271 if (gspca_dev->streaming)
1272 setcontrast(gspca_dev);
1276 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1278 struct sd *sd = (struct sd *) gspca_dev;
1280 *val = sd->contrast;
1284 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1286 struct sd *sd = (struct sd *) gspca_dev;
1289 if (gspca_dev->streaming)
1290 setcolors(gspca_dev);
1294 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1296 struct sd *sd = (struct sd *) gspca_dev;
1302 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1304 struct sd *sd = (struct sd *) gspca_dev;
1310 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1312 struct sd *sd = (struct sd *) gspca_dev;
1314 *val = sd->autogain;
1318 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1319 struct v4l2_jpegcompression *jcomp)
1321 struct sd *sd = (struct sd *) gspca_dev;
1323 if (jcomp->quality < QUALITY_MIN)
1324 sd->quality = QUALITY_MIN;
1325 else if (jcomp->quality > QUALITY_MAX)
1326 sd->quality = QUALITY_MAX;
1328 sd->quality = jcomp->quality;
1329 if (gspca_dev->streaming)
1330 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1334 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1335 struct v4l2_jpegcompression *jcomp)
1337 struct sd *sd = (struct sd *) gspca_dev;
1339 memset(jcomp, 0, sizeof *jcomp);
1340 jcomp->quality = sd->quality;
1341 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1342 | V4L2_JPEG_MARKER_DQT;
1346 /* sub-driver description */
1347 static const struct sd_desc sd_desc = {
1348 .name = MODULE_NAME,
1350 .nctrls = ARRAY_SIZE(sd_ctrls),
1351 .config = sd_config,
1356 .pkt_scan = sd_pkt_scan,
1357 .get_jcomp = sd_get_jcomp,
1358 .set_jcomp = sd_set_jcomp,
1361 /* -- module initialisation -- */
1362 #define BS(bridge, subtype) \
1363 .driver_info = (BRIDGE_ ## bridge << 8) \
1365 static const __devinitdata struct usb_device_id device_table[] = {
1366 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1367 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1368 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1369 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1370 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1371 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1372 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1373 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1374 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1375 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1376 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1377 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1378 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1379 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1380 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1381 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1382 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1383 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1384 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1385 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1386 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1387 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1388 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1389 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1390 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1391 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1392 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1393 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1394 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1395 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1396 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1397 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1398 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1399 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1400 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1401 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1402 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1403 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1404 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1405 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1406 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1407 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1408 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1409 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1410 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1411 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1412 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1413 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1414 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1415 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1416 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1417 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1418 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1419 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1420 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1421 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1422 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1425 MODULE_DEVICE_TABLE(usb, device_table);
1427 /* -- device connect -- */
1428 static int sd_probe(struct usb_interface *intf,
1429 const struct usb_device_id *id)
1431 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1435 static struct usb_driver sd_driver = {
1436 .name = MODULE_NAME,
1437 .id_table = device_table,
1439 .disconnect = gspca_disconnect,
1441 .suspend = gspca_suspend,
1442 .resume = gspca_resume,
1446 /* -- module insert / remove -- */
1447 static int __init sd_mod_init(void)
1450 ret = usb_register(&sd_driver);
1453 PDEBUG(D_PROBE, "registered");
1456 static void __exit sd_mod_exit(void)
1458 usb_deregister(&sd_driver);
1459 PDEBUG(D_PROBE, "deregistered");
1462 module_init(sd_mod_init);
1463 module_exit(sd_mod_exit);