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;
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
57 /* V4L2 controls supported by the driver */
58 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
59 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
60 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
61 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
62 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
63 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
64 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
65 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
67 static struct ctrl sd_ctrls[] = {
68 #define SD_BRIGHTNESS 0
71 .id = V4L2_CID_BRIGHTNESS,
72 .type = V4L2_CTRL_TYPE_INTEGER,
79 .set = sd_setbrightness,
80 .get = sd_getbrightness,
85 .id = V4L2_CID_CONTRAST,
86 .type = V4L2_CTRL_TYPE_INTEGER,
91 .default_value = 0x20,
93 .set = sd_setcontrast,
94 .get = sd_getcontrast,
99 .id = V4L2_CID_SATURATION,
100 .type = V4L2_CTRL_TYPE_INTEGER,
105 .default_value = 0x1a,
110 #define SD_AUTOGAIN 3
113 .id = V4L2_CID_AUTOGAIN,
114 .type = V4L2_CTRL_TYPE_BOOLEAN,
121 .set = sd_setautogain,
122 .get = sd_getautogain,
126 static struct v4l2_pix_format vga_mode[] = {
127 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
129 .sizeimage = 320 * 240 * 3 / 8 + 590,
130 .colorspace = V4L2_COLORSPACE_JPEG,
132 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
134 .sizeimage = 640 * 480 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
139 static struct v4l2_pix_format custom_mode[] = {
140 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
142 .sizeimage = 320 * 240 * 3 / 8 + 590,
143 .colorspace = V4L2_COLORSPACE_JPEG,
145 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
147 .sizeimage = 464 * 480 * 3 / 8 + 590,
148 .colorspace = V4L2_COLORSPACE_JPEG,
152 static struct v4l2_pix_format vga_mode2[] = {
153 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
155 .sizeimage = 176 * 144 * 3 / 8 + 590,
156 .colorspace = V4L2_COLORSPACE_JPEG,
158 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
160 .sizeimage = 320 * 240 * 3 / 8 + 590,
161 .colorspace = V4L2_COLORSPACE_JPEG,
163 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
165 .sizeimage = 352 * 288 * 3 / 8 + 590,
166 .colorspace = V4L2_COLORSPACE_JPEG,
168 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
170 .sizeimage = 640 * 480 * 3 / 8 + 590,
171 .colorspace = V4L2_COLORSPACE_JPEG,
175 #define SPCA50X_OFFSET_DATA 10
176 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
177 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
178 #define SPCA504_PCCAM600_OFFSET_MODE 5
179 #define SPCA504_PCCAM600_OFFSET_DATA 14
180 /* Frame packet header offsets for the spca533 */
181 #define SPCA533_OFFSET_DATA 16
182 #define SPCA533_OFFSET_FRAMSEQ 15
183 /* Frame packet header offsets for the spca536 */
184 #define SPCA536_OFFSET_DATA 4
185 #define SPCA536_OFFSET_FRAMSEQ 1
187 /* Initialisation data for the Creative PC-CAM 600 */
188 static const __u16 spca504_pccam600_init_data[][3] = {
189 /* {0xa0, 0x0000, 0x0503}, * capture mode */
190 {0x00, 0x0000, 0x2000},
191 {0x00, 0x0013, 0x2301},
192 {0x00, 0x0003, 0x2000},
193 {0x00, 0x0001, 0x21ac},
194 {0x00, 0x0001, 0x21a6},
195 {0x00, 0x0000, 0x21a7}, /* brightness */
196 {0x00, 0x0020, 0x21a8}, /* contrast */
197 {0x00, 0x0001, 0x21ac}, /* sat/hue */
198 {0x00, 0x0000, 0x21ad}, /* hue */
199 {0x00, 0x001a, 0x21ae}, /* saturation */
200 {0x00, 0x0002, 0x21a3}, /* gamma */
201 {0x30, 0x0154, 0x0008},
202 {0x30, 0x0004, 0x0006},
203 {0x30, 0x0258, 0x0009},
204 {0x30, 0x0004, 0x0000},
205 {0x30, 0x0093, 0x0004},
206 {0x30, 0x0066, 0x0005},
207 {0x00, 0x0000, 0x2000},
208 {0x00, 0x0013, 0x2301},
209 {0x00, 0x0003, 0x2000},
210 {0x00, 0x0013, 0x2301},
211 {0x00, 0x0003, 0x2000},
215 /* Creative PC-CAM 600 specific open data, sent before using the
216 * generic initialisation data from spca504_open_data.
218 static const __u16 spca504_pccam600_open_data[][3] = {
219 {0x00, 0x0001, 0x2501},
220 {0x20, 0x0500, 0x0001}, /* snapshot mode */
221 {0x00, 0x0003, 0x2880},
222 {0x00, 0x0001, 0x2881},
226 /* Initialisation data for the logitech clicksmart 420 */
227 static const __u16 spca504A_clicksmart420_init_data[][3] = {
228 /* {0xa0, 0x0000, 0x0503}, * capture mode */
229 {0x00, 0x0000, 0x2000},
230 {0x00, 0x0013, 0x2301},
231 {0x00, 0x0003, 0x2000},
232 {0x00, 0x0001, 0x21ac},
233 {0x00, 0x0001, 0x21a6},
234 {0x00, 0x0000, 0x21a7}, /* brightness */
235 {0x00, 0x0020, 0x21a8}, /* contrast */
236 {0x00, 0x0001, 0x21ac}, /* sat/hue */
237 {0x00, 0x0000, 0x21ad}, /* hue */
238 {0x00, 0x001a, 0x21ae}, /* saturation */
239 {0x00, 0x0002, 0x21a3}, /* gamma */
240 {0x30, 0x0004, 0x000a},
241 {0xb0, 0x0001, 0x0000},
244 {0x0a1, 0x0080, 0x0001},
245 {0x30, 0x0049, 0x0000},
246 {0x30, 0x0060, 0x0005},
247 {0x0c, 0x0004, 0x0000},
248 {0x00, 0x0000, 0x0000},
249 {0x00, 0x0000, 0x2000},
250 {0x00, 0x0013, 0x2301},
251 {0x00, 0x0003, 0x2000},
252 {0x00, 0x0000, 0x2000},
257 /* clicksmart 420 open data ? */
258 static const __u16 spca504A_clicksmart420_open_data[][3] = {
259 {0x00, 0x0001, 0x2501},
260 {0x20, 0x0502, 0x0000},
261 {0x06, 0x0000, 0x0000},
262 {0x00, 0x0004, 0x2880},
263 {0x00, 0x0001, 0x2881},
264 /* look like setting a qTable */
265 {0x00, 0x0006, 0x2800},
266 {0x00, 0x0004, 0x2801},
267 {0x00, 0x0004, 0x2802},
268 {0x00, 0x0006, 0x2803},
269 {0x00, 0x000a, 0x2804},
270 {0x00, 0x0010, 0x2805},
271 {0x00, 0x0014, 0x2806},
272 {0x00, 0x0018, 0x2807},
273 {0x00, 0x0005, 0x2808},
274 {0x00, 0x0005, 0x2809},
275 {0x00, 0x0006, 0x280a},
276 {0x00, 0x0008, 0x280b},
277 {0x00, 0x000a, 0x280c},
278 {0x00, 0x0017, 0x280d},
279 {0x00, 0x0018, 0x280e},
280 {0x00, 0x0016, 0x280f},
282 {0x00, 0x0006, 0x2810},
283 {0x00, 0x0005, 0x2811},
284 {0x00, 0x0006, 0x2812},
285 {0x00, 0x000a, 0x2813},
286 {0x00, 0x0010, 0x2814},
287 {0x00, 0x0017, 0x2815},
288 {0x00, 0x001c, 0x2816},
289 {0x00, 0x0016, 0x2817},
290 {0x00, 0x0006, 0x2818},
291 {0x00, 0x0007, 0x2819},
292 {0x00, 0x0009, 0x281a},
293 {0x00, 0x000c, 0x281b},
294 {0x00, 0x0014, 0x281c},
295 {0x00, 0x0023, 0x281d},
296 {0x00, 0x0020, 0x281e},
297 {0x00, 0x0019, 0x281f},
299 {0x00, 0x0007, 0x2820},
300 {0x00, 0x0009, 0x2821},
301 {0x00, 0x000f, 0x2822},
302 {0x00, 0x0016, 0x2823},
303 {0x00, 0x001b, 0x2824},
304 {0x00, 0x002c, 0x2825},
305 {0x00, 0x0029, 0x2826},
306 {0x00, 0x001f, 0x2827},
307 {0x00, 0x000a, 0x2828},
308 {0x00, 0x000e, 0x2829},
309 {0x00, 0x0016, 0x282a},
310 {0x00, 0x001a, 0x282b},
311 {0x00, 0x0020, 0x282c},
312 {0x00, 0x002a, 0x282d},
313 {0x00, 0x002d, 0x282e},
314 {0x00, 0x0025, 0x282f},
316 {0x00, 0x0014, 0x2830},
317 {0x00, 0x001a, 0x2831},
318 {0x00, 0x001f, 0x2832},
319 {0x00, 0x0023, 0x2833},
320 {0x00, 0x0029, 0x2834},
321 {0x00, 0x0030, 0x2835},
322 {0x00, 0x0030, 0x2836},
323 {0x00, 0x0028, 0x2837},
324 {0x00, 0x001d, 0x2838},
325 {0x00, 0x0025, 0x2839},
326 {0x00, 0x0026, 0x283a},
327 {0x00, 0x0027, 0x283b},
328 {0x00, 0x002d, 0x283c},
329 {0x00, 0x0028, 0x283d},
330 {0x00, 0x0029, 0x283e},
331 {0x00, 0x0028, 0x283f},
333 {0x00, 0x0007, 0x2840},
334 {0x00, 0x0007, 0x2841},
335 {0x00, 0x000a, 0x2842},
336 {0x00, 0x0013, 0x2843},
337 {0x00, 0x0028, 0x2844},
338 {0x00, 0x0028, 0x2845},
339 {0x00, 0x0028, 0x2846},
340 {0x00, 0x0028, 0x2847},
341 {0x00, 0x0007, 0x2848},
342 {0x00, 0x0008, 0x2849},
343 {0x00, 0x000a, 0x284a},
344 {0x00, 0x001a, 0x284b},
345 {0x00, 0x0028, 0x284c},
346 {0x00, 0x0028, 0x284d},
347 {0x00, 0x0028, 0x284e},
348 {0x00, 0x0028, 0x284f},
350 {0x00, 0x000a, 0x2850},
351 {0x00, 0x000a, 0x2851},
352 {0x00, 0x0016, 0x2852},
353 {0x00, 0x0028, 0x2853},
354 {0x00, 0x0028, 0x2854},
355 {0x00, 0x0028, 0x2855},
356 {0x00, 0x0028, 0x2856},
357 {0x00, 0x0028, 0x2857},
358 {0x00, 0x0013, 0x2858},
359 {0x00, 0x001a, 0x2859},
360 {0x00, 0x0028, 0x285a},
361 {0x00, 0x0028, 0x285b},
362 {0x00, 0x0028, 0x285c},
363 {0x00, 0x0028, 0x285d},
364 {0x00, 0x0028, 0x285e},
365 {0x00, 0x0028, 0x285f},
367 {0x00, 0x0028, 0x2860},
368 {0x00, 0x0028, 0x2861},
369 {0x00, 0x0028, 0x2862},
370 {0x00, 0x0028, 0x2863},
371 {0x00, 0x0028, 0x2864},
372 {0x00, 0x0028, 0x2865},
373 {0x00, 0x0028, 0x2866},
374 {0x00, 0x0028, 0x2867},
375 {0x00, 0x0028, 0x2868},
376 {0x00, 0x0028, 0x2869},
377 {0x00, 0x0028, 0x286a},
378 {0x00, 0x0028, 0x286b},
379 {0x00, 0x0028, 0x286c},
380 {0x00, 0x0028, 0x286d},
381 {0x00, 0x0028, 0x286e},
382 {0x00, 0x0028, 0x286f},
384 {0x00, 0x0028, 0x2870},
385 {0x00, 0x0028, 0x2871},
386 {0x00, 0x0028, 0x2872},
387 {0x00, 0x0028, 0x2873},
388 {0x00, 0x0028, 0x2874},
389 {0x00, 0x0028, 0x2875},
390 {0x00, 0x0028, 0x2876},
391 {0x00, 0x0028, 0x2877},
392 {0x00, 0x0028, 0x2878},
393 {0x00, 0x0028, 0x2879},
394 {0x00, 0x0028, 0x287a},
395 {0x00, 0x0028, 0x287b},
396 {0x00, 0x0028, 0x287c},
397 {0x00, 0x0028, 0x287d},
398 {0x00, 0x0028, 0x287e},
399 {0x00, 0x0028, 0x287f},
401 {0xa0, 0x0000, 0x0503},
405 static const __u8 qtable_creative_pccam[2][64] = {
406 { /* Q-table Y-components */
407 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
408 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
409 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
410 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
411 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
412 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
413 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
414 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
415 { /* Q-table C-components */
416 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
417 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
418 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
419 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
420 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
421 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
426 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
427 * except for one byte. Possibly a typo?
430 static const __u8 qtable_spca504_default[2][64] = {
431 { /* Q-table Y-components */
432 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
433 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
434 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
435 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
436 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
437 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
438 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
439 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
441 { /* Q-table C-components */
442 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
443 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
444 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
445 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
446 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
447 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
452 /* read <len> bytes to gspca_dev->usb_buf */
453 static void reg_r(struct gspca_dev *gspca_dev,
459 if (len > USB_BUF_SZ) {
460 err("reg_r: buffer overflow");
464 usb_control_msg(gspca_dev->dev,
465 usb_rcvctrlpipe(gspca_dev->dev, 0),
467 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
470 len ? gspca_dev->usb_buf : NULL, len,
474 /* write <len> bytes from gspca_dev->usb_buf */
475 static void reg_w(struct gspca_dev *gspca_dev,
482 if (len > USB_BUF_SZ) {
483 err("reg_w: buffer overflow");
487 usb_control_msg(gspca_dev->dev,
488 usb_sndctrlpipe(gspca_dev->dev, 0),
490 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
492 len ? gspca_dev->usb_buf : NULL, len,
496 /* write req / index / value */
497 static int reg_w_riv(struct usb_device *dev,
498 __u16 req, __u16 index, __u16 value)
502 ret = usb_control_msg(dev,
503 usb_sndctrlpipe(dev, 0),
505 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
506 value, index, NULL, 0, 500);
507 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
508 req, index, value, ret);
510 PDEBUG(D_ERR, "reg write: error %d", ret);
515 static int reg_r_1(struct gspca_dev *gspca_dev,
516 __u16 value) /* wValue */
520 ret = usb_control_msg(gspca_dev->dev,
521 usb_rcvctrlpipe(gspca_dev->dev, 0),
523 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
526 gspca_dev->usb_buf, 1,
529 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
532 return gspca_dev->usb_buf[0];
535 /* read 1 or 2 bytes - returns < 0 if error */
536 static int reg_r_12(struct gspca_dev *gspca_dev,
537 __u16 req, /* bRequest */
538 __u16 index, /* wIndex */
539 __u16 length) /* wLength (1 or 2 only) */
543 gspca_dev->usb_buf[1] = 0;
544 ret = usb_control_msg(gspca_dev->dev,
545 usb_rcvctrlpipe(gspca_dev->dev, 0),
547 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
550 gspca_dev->usb_buf, length,
553 PDEBUG(D_ERR, "reg_read err %d", ret);
556 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
559 static int write_vector(struct gspca_dev *gspca_dev,
560 const __u16 data[][3])
562 struct usb_device *dev = gspca_dev->dev;
565 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
566 ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
569 "Register write failed for 0x%x,0x%x,0x%x",
570 data[i][0], data[i][1], data[i][2]);
578 static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
579 unsigned int request,
582 const __u8 qtable[2][64])
584 struct usb_device *dev = gspca_dev->dev;
587 /* loop over y components */
588 for (i = 0; i < 64; i++) {
589 err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
594 /* loop over c components */
595 for (i = 0; i < 64; i++) {
596 err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
603 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
604 __u16 req, __u16 idx, __u16 val)
606 struct usb_device *dev = gspca_dev->dev;
609 reg_w_riv(dev, req, idx, val);
610 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
611 reg_w_riv(dev, req, idx, val);
613 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
616 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
617 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
620 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
622 __u16 idx, __u16 val, __u8 stat, __u8 count)
624 struct usb_device *dev = gspca_dev->dev;
628 reg_w_riv(dev, req, idx, val);
629 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
631 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
635 while (--count > 0) {
637 /* gsmart mini2 write a each wait setting 1 ms is enought */
638 /* reg_w_riv(dev, req, idx, val); */
639 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
640 if (status == endcode) {
641 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
642 status, 200 - count);
648 static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
652 while (--count > 0) {
653 reg_r(gspca_dev, 0x21, 0, 1);
654 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
658 return gspca_dev->usb_buf[0];
661 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
665 while (--count > 0) {
666 reg_r(gspca_dev, 0x21, 1, 1);
667 if (gspca_dev->usb_buf[0] != 0) {
668 gspca_dev->usb_buf[0] = 0;
669 reg_w(gspca_dev, 0x21, 0, 1, 1);
670 reg_r(gspca_dev, 0x21, 1, 1);
671 spca504B_PollingDataReady(gspca_dev);
678 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
682 data = gspca_dev->usb_buf;
683 reg_r(gspca_dev, 0x20, 0, 5);
684 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
685 data[0], data[1], data[2], data[3], data[4]);
686 reg_r(gspca_dev, 0x23, 0, 64);
687 reg_r(gspca_dev, 0x23, 1, 64);
690 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
692 struct sd *sd = (struct sd *) gspca_dev;
693 struct usb_device *dev = gspca_dev->dev;
698 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
700 switch (sd->bridge) {
702 reg_w(gspca_dev, 0x31, 0, 0, 0);
703 spca504B_WaitCmdStatus(gspca_dev);
704 rc = spca504B_PollingDataReady(gspca_dev);
705 spca50x_GetFirmware(gspca_dev);
706 gspca_dev->usb_buf[0] = 2; /* type */
707 reg_w(gspca_dev, 0x24, 0, 8, 1);
708 reg_r(gspca_dev, 0x24, 8, 1);
710 gspca_dev->usb_buf[0] = Size;
711 reg_w(gspca_dev, 0x25, 0, 4, 1);
712 reg_r(gspca_dev, 0x25, 4, 1); /* size */
713 rc = spca504B_PollingDataReady(gspca_dev);
715 /* Init the cam width height with some values get on init ? */
716 reg_w(gspca_dev, 0x31, 0, 4, 0);
717 spca504B_WaitCmdStatus(gspca_dev);
718 rc = spca504B_PollingDataReady(gspca_dev);
721 /* case BRIDGE_SPCA504B: */
722 /* case BRIDGE_SPCA536: */
723 gspca_dev->usb_buf[0] = Size;
724 reg_w(gspca_dev, 0x25, 0, 4, 1);
725 reg_r(gspca_dev, 0x25, 4, 1); /* size */
727 gspca_dev->usb_buf[0] = Type;
728 reg_w(gspca_dev, 0x27, 0, 0, 1);
729 reg_r(gspca_dev, 0x27, 0, 1); /* type */
730 rc = spca504B_PollingDataReady(gspca_dev);
734 if (sd->subtype == AiptekMiniPenCam13) {
735 /* spca504a aiptek */
736 spca504A_acknowledged_command(gspca_dev,
738 0x80 | (Size & 0x0f), 1);
739 spca504A_acknowledged_command(gspca_dev,
742 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
745 case BRIDGE_SPCA504C:
747 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
748 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
753 static void spca504_wait_status(struct gspca_dev *gspca_dev)
759 /* With this we get the status, when return 0 it's all ok */
760 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
766 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
768 gspca_dev->usb_buf[0] = 3;
769 reg_w(gspca_dev, 0x26, 0, 0, 1);
770 reg_r(gspca_dev, 0x26, 0, 1);
771 spca504B_PollingDataReady(gspca_dev);
774 static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
776 struct sd *sd = (struct sd *) gspca_dev;
779 switch (sd->bridge) {
781 case BRIDGE_SPCA504C:
785 /* case BRIDGE_SPCA533: */
786 /* case BRIDGE_SPCA504B: */
787 reg_w(gspca_dev, 0, 0, 0x21a7, 0); /* brightness */
788 reg_w(gspca_dev, 0, 0x20, 0x21a8, 0); /* contrast */
789 reg_w(gspca_dev, 0, 0, 0x21ad, 0); /* hue */
790 reg_w(gspca_dev, 0, 1, 0x21ac, 0); /* sat/hue */
791 reg_w(gspca_dev, 0, 0x20, 0x21ae, 0); /* saturation */
792 reg_w(gspca_dev, 0, 0, 0x21a3, 0); /* gamma */
795 reg_w(gspca_dev, 0, 0, 0x20f0, 0);
796 reg_w(gspca_dev, 0, 0x21, 0x20f1, 0);
797 reg_w(gspca_dev, 0, 0x40, 0x20f5, 0);
798 reg_w(gspca_dev, 0, 1, 0x20f4, 0);
799 reg_w(gspca_dev, 0, 0x40, 0x20f6, 0);
800 reg_w(gspca_dev, 0, 0, 0x2089, 0);
804 spca504B_PollingDataReady(gspca_dev);
807 /* this function is called at probe time */
808 static int sd_config(struct gspca_dev *gspca_dev,
809 const struct usb_device_id *id)
811 struct sd *sd = (struct sd *) gspca_dev;
814 cam = &gspca_dev->cam;
817 sd->bridge = id->driver_info >> 8;
818 sd->subtype = id->driver_info;
820 if (sd->subtype == AiptekMiniPenCam13) {
821 /* try to get the firmware as some cam answer 2.0.1.2.2
822 * and should be a spca504b then overwrite that setting */
823 reg_r(gspca_dev, 0x20, 0, 1);
824 switch (gspca_dev->usb_buf[0]) {
826 break; /* (right bridge/subtype) */
828 sd->bridge = BRIDGE_SPCA504B;
836 switch (sd->bridge) {
838 /* case BRIDGE_SPCA504B: */
839 /* case BRIDGE_SPCA504: */
840 /* case BRIDGE_SPCA536: */
841 cam->cam_mode = vga_mode;
842 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
845 cam->cam_mode = custom_mode;
846 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
848 case BRIDGE_SPCA504C:
849 cam->cam_mode = vga_mode2;
850 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
853 sd->qindex = 5; /* set the quantization table */
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;
860 /* this function is called at probe and resume time */
861 static int sd_init(struct gspca_dev *gspca_dev)
863 struct sd *sd = (struct sd *) gspca_dev;
864 struct usb_device *dev = gspca_dev->dev;
870 switch (sd->bridge) {
871 case BRIDGE_SPCA504B:
872 reg_w(gspca_dev, 0x1d, 0, 0, 0);
873 reg_w(gspca_dev, 0, 1, 0x2306, 0);
874 reg_w(gspca_dev, 0, 0, 0x0d04, 0);
875 reg_w(gspca_dev, 0, 0, 0x2000, 0);
876 reg_w(gspca_dev, 0, 0x13, 0x2301, 0);
877 reg_w(gspca_dev, 0, 0, 0x2306, 0);
880 rc = spca504B_PollingDataReady(gspca_dev);
881 spca50x_GetFirmware(gspca_dev);
884 spca50x_GetFirmware(gspca_dev);
885 reg_r(gspca_dev, 0x00, 0x5002, 1);
886 gspca_dev->usb_buf[0] = 0;
887 reg_w(gspca_dev, 0x24, 0, 0, 1);
888 reg_r(gspca_dev, 0x24, 0, 1);
889 rc = spca504B_PollingDataReady(gspca_dev);
890 reg_w(gspca_dev, 0x34, 0, 0, 0);
891 spca504B_WaitCmdStatus(gspca_dev);
893 case BRIDGE_SPCA504C: /* pccam600 */
894 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
895 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
896 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
897 spca504_wait_status(gspca_dev);
898 if (sd->subtype == LogitechClickSmart420)
899 write_vector(gspca_dev,
900 spca504A_clicksmart420_open_data);
902 write_vector(gspca_dev, spca504_pccam600_open_data);
903 err_code = spca50x_setup_qtable(gspca_dev,
905 0x2840, qtable_creative_pccam);
907 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
912 /* case BRIDGE_SPCA504: */
913 PDEBUG(D_STREAM, "Opening SPCA504");
914 if (sd->subtype == AiptekMiniPenCam13) {
915 /*****************************/
916 for (i = 0; i < 6; i++)
917 info[i] = reg_r_1(gspca_dev, i);
919 "Read info: %d %d %d %d %d %d."
920 " Should be 1,0,2,2,0,0",
921 info[0], info[1], info[2],
922 info[3], info[4], info[5]);
923 /* spca504a aiptek */
924 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
925 spca504A_acknowledged_command(gspca_dev, 0x24,
927 /* Twice sequencial need status 0xff->0x9e->0x9d */
928 spca504A_acknowledged_command(gspca_dev, 0x24,
931 spca504A_acknowledged_command(gspca_dev, 0x24,
933 /******************************/
934 /* spca504a aiptek */
935 spca504A_acknowledged_command(gspca_dev, 0x08,
937 /* reg_write (dev, 0, 0x2000, 0); */
938 /* reg_write (dev, 0, 0x2883, 1); */
939 /* spca504A_acknowledged_command (gspca_dev, 0x08,
941 /* spca504A_acknowledged_command (gspca_dev, 0x24,
943 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
944 reg_w_riv(dev, 0x0, 0x2310, 0x05);
945 spca504A_acknowledged_command(gspca_dev, 0x01,
949 reg_w_riv(dev, 0, 0x2000, 0);
950 reg_w_riv(dev, 0, 0x2883, 1);
951 err_code = spca50x_setup_qtable(gspca_dev,
954 qtable_spca504_default);
956 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
964 static void sd_start(struct gspca_dev *gspca_dev)
966 struct sd *sd = (struct sd *) gspca_dev;
967 struct usb_device *dev = gspca_dev->dev;
973 if (sd->bridge == BRIDGE_SPCA504B)
974 spca504B_setQtable(gspca_dev);
975 spca504B_SetSizeType(gspca_dev);
976 switch (sd->bridge) {
978 /* case BRIDGE_SPCA504B: */
979 /* case BRIDGE_SPCA533: */
980 /* case BRIDGE_SPCA536: */
981 if (sd->subtype == MegapixV4 ||
982 sd->subtype == LogitechClickSmart820) {
983 reg_w(gspca_dev, 0xf0, 0, 0, 0);
984 spca504B_WaitCmdStatus(gspca_dev);
985 reg_r(gspca_dev, 0xf0, 4, 0);
986 spca504B_WaitCmdStatus(gspca_dev);
988 reg_w(gspca_dev, 0x31, 0, 4, 0);
989 spca504B_WaitCmdStatus(gspca_dev);
990 rc = spca504B_PollingDataReady(gspca_dev);
994 if (sd->subtype == AiptekMiniPenCam13) {
995 for (i = 0; i < 6; i++)
996 info[i] = reg_r_1(gspca_dev, i);
998 "Read info: %d %d %d %d %d %d."
999 " Should be 1,0,2,2,0,0",
1000 info[0], info[1], info[2],
1001 info[3], info[4], info[5]);
1002 /* spca504a aiptek */
1003 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1004 spca504A_acknowledged_command(gspca_dev, 0x24,
1006 /* Twice sequencial need status 0xff->0x9e->0x9d */
1007 spca504A_acknowledged_command(gspca_dev, 0x24,
1009 spca504A_acknowledged_command(gspca_dev, 0x24,
1012 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1013 for (i = 0; i < 6; i++)
1014 info[i] = reg_r_1(gspca_dev, i);
1016 "Read info: %d %d %d %d %d %d."
1017 " Should be 1,0,2,2,0,0",
1018 info[0], info[1], info[2],
1019 info[3], info[4], info[5]);
1020 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1021 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1023 spca504B_SetSizeType(gspca_dev);
1024 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1025 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1027 case BRIDGE_SPCA504C:
1028 if (sd->subtype == LogitechClickSmart420) {
1029 write_vector(gspca_dev,
1030 spca504A_clicksmart420_init_data);
1032 write_vector(gspca_dev, spca504_pccam600_init_data);
1034 enable = (sd->autogain ? 0x04 : 0x01);
1035 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1036 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
1038 /* set default exposure compensation and whiteness balance */
1039 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1040 reg_w_riv(dev, 0x30, 0x0002, 1600);
1041 spca504B_SetSizeType(gspca_dev);
1044 sp5xx_initContBrigHueRegisters(gspca_dev);
1047 static void sd_stopN(struct gspca_dev *gspca_dev)
1049 struct sd *sd = (struct sd *) gspca_dev;
1050 struct usb_device *dev = gspca_dev->dev;
1052 switch (sd->bridge) {
1054 /* case BRIDGE_SPCA533: */
1055 /* case BRIDGE_SPCA536: */
1056 /* case BRIDGE_SPCA504B: */
1057 reg_w(gspca_dev, 0x31, 0, 0, 0);
1058 spca504B_WaitCmdStatus(gspca_dev);
1059 spca504B_PollingDataReady(gspca_dev);
1061 case BRIDGE_SPCA504:
1062 case BRIDGE_SPCA504C:
1063 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
1065 if (sd->subtype == AiptekMiniPenCam13) {
1066 /* spca504a aiptek */
1067 /* spca504A_acknowledged_command(gspca_dev, 0x08,
1069 spca504A_acknowledged_command(gspca_dev, 0x24,
1070 0x00, 0x00, 0x9d, 1);
1071 spca504A_acknowledged_command(gspca_dev, 0x01,
1072 0x0f, 0x00, 0xff, 1);
1074 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1075 reg_w_riv(dev, 0x01, 0x000f, 0x00);
1081 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1082 struct gspca_frame *frame, /* target */
1083 __u8 *data, /* isoc packet */
1084 int len) /* iso packet length */
1086 struct sd *sd = (struct sd *) gspca_dev;
1088 unsigned char *s, *d;
1089 static unsigned char ffd9[] = {0xff, 0xd9};
1091 /* frames are jpeg 4.1.1 without 0xff escape */
1092 switch (sd->bridge) {
1093 case BRIDGE_SPCA533:
1094 if (data[0] == 0xff) {
1095 if (data[1] != 0x01) { /* drop packet */
1096 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1100 data += SPCA533_OFFSET_DATA;
1101 len -= SPCA533_OFFSET_DATA;
1107 case BRIDGE_SPCA536:
1108 if (data[0] == 0xff) {
1110 data += SPCA536_OFFSET_DATA;
1111 len -= SPCA536_OFFSET_DATA;
1118 /* case BRIDGE_SPCA504: */
1119 /* case BRIDGE_SPCA504B: */
1121 case 0xfe: /* start of frame */
1123 data += SPCA50X_OFFSET_DATA;
1124 len -= SPCA50X_OFFSET_DATA;
1126 case 0xff: /* drop packet */
1127 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1135 case BRIDGE_SPCA504C:
1137 case 0xfe: /* start of frame */
1139 data += SPCA504_PCCAM600_OFFSET_DATA;
1140 len -= SPCA504_PCCAM600_OFFSET_DATA;
1142 case 0xff: /* drop packet */
1143 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1152 if (sof) { /* start of frame */
1153 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1156 /* put the JPEG header in the new frame */
1157 jpeg_put_header(gspca_dev, frame,
1158 ((struct sd *) gspca_dev)->qindex,
1162 /* add 0x00 after 0xff */
1163 for (i = len; --i >= 0; )
1164 if (data[i] == 0xff)
1166 if (i < 0) { /* no 0xff */
1167 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1172 for (i = 0; i < len; i++) {
1177 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1178 sd->packet, d - sd->packet);
1181 static void setbrightness(struct gspca_dev *gspca_dev)
1183 struct sd *sd = (struct sd *) gspca_dev;
1184 struct usb_device *dev = gspca_dev->dev;
1186 switch (sd->bridge) {
1188 /* case BRIDGE_SPCA533: */
1189 /* case BRIDGE_SPCA504B: */
1190 /* case BRIDGE_SPCA504: */
1191 /* case BRIDGE_SPCA504C: */
1192 reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
1194 case BRIDGE_SPCA536:
1195 reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
1200 static void getbrightness(struct gspca_dev *gspca_dev)
1202 struct sd *sd = (struct sd *) gspca_dev;
1203 __u16 brightness = 0;
1205 switch (sd->bridge) {
1207 /* case BRIDGE_SPCA533: */
1208 /* case BRIDGE_SPCA504B: */
1209 /* case BRIDGE_SPCA504: */
1210 /* case BRIDGE_SPCA504C: */
1211 brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2);
1213 case BRIDGE_SPCA536:
1214 brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2);
1217 sd->brightness = ((brightness & 0xff) - 128) % 255;
1220 static void setcontrast(struct gspca_dev *gspca_dev)
1222 struct sd *sd = (struct sd *) gspca_dev;
1223 struct usb_device *dev = gspca_dev->dev;
1225 switch (sd->bridge) {
1227 /* case BRIDGE_SPCA533: */
1228 /* case BRIDGE_SPCA504B: */
1229 /* case BRIDGE_SPCA504: */
1230 /* case BRIDGE_SPCA504C: */
1231 reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
1233 case BRIDGE_SPCA536:
1234 reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
1239 static void getcontrast(struct gspca_dev *gspca_dev)
1241 struct sd *sd = (struct sd *) gspca_dev;
1243 switch (sd->bridge) {
1245 /* case BRIDGE_SPCA533: */
1246 /* case BRIDGE_SPCA504B: */
1247 /* case BRIDGE_SPCA504: */
1248 /* case BRIDGE_SPCA504C: */
1249 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2);
1251 case BRIDGE_SPCA536:
1252 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2);
1257 static void setcolors(struct gspca_dev *gspca_dev)
1259 struct sd *sd = (struct sd *) gspca_dev;
1260 struct usb_device *dev = gspca_dev->dev;
1262 switch (sd->bridge) {
1264 /* case BRIDGE_SPCA533: */
1265 /* case BRIDGE_SPCA504B: */
1266 /* case BRIDGE_SPCA504: */
1267 /* case BRIDGE_SPCA504C: */
1268 reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
1270 case BRIDGE_SPCA536:
1271 reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
1276 static void getcolors(struct gspca_dev *gspca_dev)
1278 struct sd *sd = (struct sd *) gspca_dev;
1280 switch (sd->bridge) {
1282 /* case BRIDGE_SPCA533: */
1283 /* case BRIDGE_SPCA504B: */
1284 /* case BRIDGE_SPCA504: */
1285 /* case BRIDGE_SPCA504C: */
1286 sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1;
1288 case BRIDGE_SPCA536:
1289 sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1;
1294 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1296 struct sd *sd = (struct sd *) gspca_dev;
1298 sd->brightness = val;
1299 if (gspca_dev->streaming)
1300 setbrightness(gspca_dev);
1304 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1306 struct sd *sd = (struct sd *) gspca_dev;
1308 getbrightness(gspca_dev);
1309 *val = sd->brightness;
1313 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1315 struct sd *sd = (struct sd *) gspca_dev;
1318 if (gspca_dev->streaming)
1319 setcontrast(gspca_dev);
1323 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1325 struct sd *sd = (struct sd *) gspca_dev;
1327 getcontrast(gspca_dev);
1328 *val = sd->contrast;
1332 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1334 struct sd *sd = (struct sd *) gspca_dev;
1337 if (gspca_dev->streaming)
1338 setcolors(gspca_dev);
1342 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1344 struct sd *sd = (struct sd *) gspca_dev;
1346 getcolors(gspca_dev);
1351 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1353 struct sd *sd = (struct sd *) gspca_dev;
1359 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1361 struct sd *sd = (struct sd *) gspca_dev;
1363 *val = sd->autogain;
1367 /* sub-driver description */
1368 static const struct sd_desc sd_desc = {
1369 .name = MODULE_NAME,
1371 .nctrls = ARRAY_SIZE(sd_ctrls),
1372 .config = sd_config,
1376 .pkt_scan = sd_pkt_scan,
1379 /* -- module initialisation -- */
1380 #define BS(bridge, subtype) \
1381 .driver_info = (BRIDGE_ ## bridge << 8) \
1383 static const __devinitdata struct usb_device_id device_table[] = {
1384 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1385 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1386 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1387 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1388 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1389 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1390 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1391 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1392 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1393 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1394 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1395 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1396 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1397 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1398 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1399 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1400 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1401 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1402 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1403 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1404 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1405 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1406 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1407 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1408 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1409 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1410 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1411 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1412 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1413 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1414 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1415 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1416 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1417 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1418 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1419 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1420 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1421 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1422 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1423 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1424 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1425 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1426 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1427 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1428 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1429 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1430 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1431 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1432 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1433 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1434 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1435 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1436 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1437 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1438 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1439 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1440 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1443 MODULE_DEVICE_TABLE(usb, device_table);
1445 /* -- device connect -- */
1446 static int sd_probe(struct usb_interface *intf,
1447 const struct usb_device_id *id)
1449 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1453 static struct usb_driver sd_driver = {
1454 .name = MODULE_NAME,
1455 .id_table = device_table,
1457 .disconnect = gspca_disconnect,
1459 .suspend = gspca_suspend,
1460 .resume = gspca_resume,
1464 /* -- module insert / remove -- */
1465 static int __init sd_mod_init(void)
1467 if (usb_register(&sd_driver) < 0)
1469 PDEBUG(D_PROBE, "registered");
1472 static void __exit sd_mod_exit(void)
1474 usb_deregister(&sd_driver);
1475 PDEBUG(D_PROBE, "deregistered");
1478 module_init(sd_mod_init);
1479 module_exit(sd_mod_exit);