2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define MODULE_NAME "sunplus"
27 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
29 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev
; /* !! must be the first item */
40 #define QUALITY_MIN 70
41 #define QUALITY_MAX 95
42 #define QUALITY_DEF 85
45 #define BRIDGE_SPCA504 0
46 #define BRIDGE_SPCA504B 1
47 #define BRIDGE_SPCA504C 2
48 #define BRIDGE_SPCA533 3
49 #define BRIDGE_SPCA536 4
51 #define AiptekMiniPenCam13 1
52 #define LogitechClickSmart420 2
53 #define LogitechClickSmart820 3
60 /* V4L2 controls supported by the driver */
61 static int sd_setbrightness(struct gspca_dev
*gspca_dev
, __s32 val
);
62 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
);
63 static int sd_setcontrast(struct gspca_dev
*gspca_dev
, __s32 val
);
64 static int sd_getcontrast(struct gspca_dev
*gspca_dev
, __s32
*val
);
65 static int sd_setcolors(struct gspca_dev
*gspca_dev
, __s32 val
);
66 static int sd_getcolors(struct gspca_dev
*gspca_dev
, __s32
*val
);
67 static int sd_setautogain(struct gspca_dev
*gspca_dev
, __s32 val
);
68 static int sd_getautogain(struct gspca_dev
*gspca_dev
, __s32
*val
);
70 static struct ctrl sd_ctrls
[] = {
73 .id
= V4L2_CID_BRIGHTNESS
,
74 .type
= V4L2_CTRL_TYPE_INTEGER
,
79 #define BRIGHTNESS_DEF 0
80 .default_value
= BRIGHTNESS_DEF
,
82 .set
= sd_setbrightness
,
83 .get
= sd_getbrightness
,
87 .id
= V4L2_CID_CONTRAST
,
88 .type
= V4L2_CTRL_TYPE_INTEGER
,
93 #define CONTRAST_DEF 0x20
94 .default_value
= CONTRAST_DEF
,
96 .set
= sd_setcontrast
,
97 .get
= sd_getcontrast
,
101 .id
= V4L2_CID_SATURATION
,
102 .type
= V4L2_CTRL_TYPE_INTEGER
,
107 #define COLOR_DEF 0x1a
108 .default_value
= COLOR_DEF
,
115 .id
= V4L2_CID_AUTOGAIN
,
116 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
121 #define AUTOGAIN_DEF 1
122 .default_value
= AUTOGAIN_DEF
,
124 .set
= sd_setautogain
,
125 .get
= sd_getautogain
,
129 static const struct v4l2_pix_format vga_mode
[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
132 .sizeimage
= 320 * 240 * 3 / 8 + 590,
133 .colorspace
= V4L2_COLORSPACE_JPEG
,
135 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
137 .sizeimage
= 640 * 480 * 3 / 8 + 590,
138 .colorspace
= V4L2_COLORSPACE_JPEG
,
142 static const struct v4l2_pix_format custom_mode
[] = {
143 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
145 .sizeimage
= 320 * 240 * 3 / 8 + 590,
146 .colorspace
= V4L2_COLORSPACE_JPEG
,
148 {464, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
150 .sizeimage
= 464 * 480 * 3 / 8 + 590,
151 .colorspace
= V4L2_COLORSPACE_JPEG
,
155 static const struct v4l2_pix_format vga_mode2
[] = {
156 {176, 144, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
158 .sizeimage
= 176 * 144 * 3 / 8 + 590,
159 .colorspace
= V4L2_COLORSPACE_JPEG
,
161 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
163 .sizeimage
= 320 * 240 * 3 / 8 + 590,
164 .colorspace
= V4L2_COLORSPACE_JPEG
,
166 {352, 288, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
168 .sizeimage
= 352 * 288 * 3 / 8 + 590,
169 .colorspace
= V4L2_COLORSPACE_JPEG
,
171 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
173 .sizeimage
= 640 * 480 * 3 / 8 + 590,
174 .colorspace
= V4L2_COLORSPACE_JPEG
,
178 #define SPCA50X_OFFSET_DATA 10
179 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
180 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
181 #define SPCA504_PCCAM600_OFFSET_MODE 5
182 #define SPCA504_PCCAM600_OFFSET_DATA 14
183 /* Frame packet header offsets for the spca533 */
184 #define SPCA533_OFFSET_DATA 16
185 #define SPCA533_OFFSET_FRAMSEQ 15
186 /* Frame packet header offsets for the spca536 */
187 #define SPCA536_OFFSET_DATA 4
188 #define SPCA536_OFFSET_FRAMSEQ 1
196 /* Initialisation data for the Creative PC-CAM 600 */
197 static const struct cmd spca504_pccam600_init_data
[] = {
198 /* {0xa0, 0x0000, 0x0503}, * capture mode */
199 {0x00, 0x0000, 0x2000},
200 {0x00, 0x0013, 0x2301},
201 {0x00, 0x0003, 0x2000},
202 {0x00, 0x0001, 0x21ac},
203 {0x00, 0x0001, 0x21a6},
204 {0x00, 0x0000, 0x21a7}, /* brightness */
205 {0x00, 0x0020, 0x21a8}, /* contrast */
206 {0x00, 0x0001, 0x21ac}, /* sat/hue */
207 {0x00, 0x0000, 0x21ad}, /* hue */
208 {0x00, 0x001a, 0x21ae}, /* saturation */
209 {0x00, 0x0002, 0x21a3}, /* gamma */
210 {0x30, 0x0154, 0x0008},
211 {0x30, 0x0004, 0x0006},
212 {0x30, 0x0258, 0x0009},
213 {0x30, 0x0004, 0x0000},
214 {0x30, 0x0093, 0x0004},
215 {0x30, 0x0066, 0x0005},
216 {0x00, 0x0000, 0x2000},
217 {0x00, 0x0013, 0x2301},
218 {0x00, 0x0003, 0x2000},
219 {0x00, 0x0013, 0x2301},
220 {0x00, 0x0003, 0x2000},
223 /* Creative PC-CAM 600 specific open data, sent before using the
224 * generic initialisation data from spca504_open_data.
226 static const struct cmd spca504_pccam600_open_data
[] = {
227 {0x00, 0x0001, 0x2501},
228 {0x20, 0x0500, 0x0001}, /* snapshot mode */
229 {0x00, 0x0003, 0x2880},
230 {0x00, 0x0001, 0x2881},
233 /* Initialisation data for the logitech clicksmart 420 */
234 static const struct cmd spca504A_clicksmart420_init_data
[] = {
235 /* {0xa0, 0x0000, 0x0503}, * capture mode */
236 {0x00, 0x0000, 0x2000},
237 {0x00, 0x0013, 0x2301},
238 {0x00, 0x0003, 0x2000},
239 {0x00, 0x0001, 0x21ac},
240 {0x00, 0x0001, 0x21a6},
241 {0x00, 0x0000, 0x21a7}, /* brightness */
242 {0x00, 0x0020, 0x21a8}, /* contrast */
243 {0x00, 0x0001, 0x21ac}, /* sat/hue */
244 {0x00, 0x0000, 0x21ad}, /* hue */
245 {0x00, 0x001a, 0x21ae}, /* saturation */
246 {0x00, 0x0002, 0x21a3}, /* gamma */
247 {0x30, 0x0004, 0x000a},
248 {0xb0, 0x0001, 0x0000},
251 {0xa1, 0x0080, 0x0001},
252 {0x30, 0x0049, 0x0000},
253 {0x30, 0x0060, 0x0005},
254 {0x0c, 0x0004, 0x0000},
255 {0x00, 0x0000, 0x0000},
256 {0x00, 0x0000, 0x2000},
257 {0x00, 0x0013, 0x2301},
258 {0x00, 0x0003, 0x2000},
259 {0x00, 0x0000, 0x2000},
263 /* clicksmart 420 open data ? */
264 static const struct cmd spca504A_clicksmart420_open_data
[] = {
265 {0x00, 0x0001, 0x2501},
266 {0x20, 0x0502, 0x0000},
267 {0x06, 0x0000, 0x0000},
268 {0x00, 0x0004, 0x2880},
269 {0x00, 0x0001, 0x2881},
270 /* look like setting a qTable */
271 {0x00, 0x0006, 0x2800},
272 {0x00, 0x0004, 0x2801},
273 {0x00, 0x0004, 0x2802},
274 {0x00, 0x0006, 0x2803},
275 {0x00, 0x000a, 0x2804},
276 {0x00, 0x0010, 0x2805},
277 {0x00, 0x0014, 0x2806},
278 {0x00, 0x0018, 0x2807},
279 {0x00, 0x0005, 0x2808},
280 {0x00, 0x0005, 0x2809},
281 {0x00, 0x0006, 0x280a},
282 {0x00, 0x0008, 0x280b},
283 {0x00, 0x000a, 0x280c},
284 {0x00, 0x0017, 0x280d},
285 {0x00, 0x0018, 0x280e},
286 {0x00, 0x0016, 0x280f},
288 {0x00, 0x0006, 0x2810},
289 {0x00, 0x0005, 0x2811},
290 {0x00, 0x0006, 0x2812},
291 {0x00, 0x000a, 0x2813},
292 {0x00, 0x0010, 0x2814},
293 {0x00, 0x0017, 0x2815},
294 {0x00, 0x001c, 0x2816},
295 {0x00, 0x0016, 0x2817},
296 {0x00, 0x0006, 0x2818},
297 {0x00, 0x0007, 0x2819},
298 {0x00, 0x0009, 0x281a},
299 {0x00, 0x000c, 0x281b},
300 {0x00, 0x0014, 0x281c},
301 {0x00, 0x0023, 0x281d},
302 {0x00, 0x0020, 0x281e},
303 {0x00, 0x0019, 0x281f},
305 {0x00, 0x0007, 0x2820},
306 {0x00, 0x0009, 0x2821},
307 {0x00, 0x000f, 0x2822},
308 {0x00, 0x0016, 0x2823},
309 {0x00, 0x001b, 0x2824},
310 {0x00, 0x002c, 0x2825},
311 {0x00, 0x0029, 0x2826},
312 {0x00, 0x001f, 0x2827},
313 {0x00, 0x000a, 0x2828},
314 {0x00, 0x000e, 0x2829},
315 {0x00, 0x0016, 0x282a},
316 {0x00, 0x001a, 0x282b},
317 {0x00, 0x0020, 0x282c},
318 {0x00, 0x002a, 0x282d},
319 {0x00, 0x002d, 0x282e},
320 {0x00, 0x0025, 0x282f},
322 {0x00, 0x0014, 0x2830},
323 {0x00, 0x001a, 0x2831},
324 {0x00, 0x001f, 0x2832},
325 {0x00, 0x0023, 0x2833},
326 {0x00, 0x0029, 0x2834},
327 {0x00, 0x0030, 0x2835},
328 {0x00, 0x0030, 0x2836},
329 {0x00, 0x0028, 0x2837},
330 {0x00, 0x001d, 0x2838},
331 {0x00, 0x0025, 0x2839},
332 {0x00, 0x0026, 0x283a},
333 {0x00, 0x0027, 0x283b},
334 {0x00, 0x002d, 0x283c},
335 {0x00, 0x0028, 0x283d},
336 {0x00, 0x0029, 0x283e},
337 {0x00, 0x0028, 0x283f},
339 {0x00, 0x0007, 0x2840},
340 {0x00, 0x0007, 0x2841},
341 {0x00, 0x000a, 0x2842},
342 {0x00, 0x0013, 0x2843},
343 {0x00, 0x0028, 0x2844},
344 {0x00, 0x0028, 0x2845},
345 {0x00, 0x0028, 0x2846},
346 {0x00, 0x0028, 0x2847},
347 {0x00, 0x0007, 0x2848},
348 {0x00, 0x0008, 0x2849},
349 {0x00, 0x000a, 0x284a},
350 {0x00, 0x001a, 0x284b},
351 {0x00, 0x0028, 0x284c},
352 {0x00, 0x0028, 0x284d},
353 {0x00, 0x0028, 0x284e},
354 {0x00, 0x0028, 0x284f},
356 {0x00, 0x000a, 0x2850},
357 {0x00, 0x000a, 0x2851},
358 {0x00, 0x0016, 0x2852},
359 {0x00, 0x0028, 0x2853},
360 {0x00, 0x0028, 0x2854},
361 {0x00, 0x0028, 0x2855},
362 {0x00, 0x0028, 0x2856},
363 {0x00, 0x0028, 0x2857},
364 {0x00, 0x0013, 0x2858},
365 {0x00, 0x001a, 0x2859},
366 {0x00, 0x0028, 0x285a},
367 {0x00, 0x0028, 0x285b},
368 {0x00, 0x0028, 0x285c},
369 {0x00, 0x0028, 0x285d},
370 {0x00, 0x0028, 0x285e},
371 {0x00, 0x0028, 0x285f},
373 {0x00, 0x0028, 0x2860},
374 {0x00, 0x0028, 0x2861},
375 {0x00, 0x0028, 0x2862},
376 {0x00, 0x0028, 0x2863},
377 {0x00, 0x0028, 0x2864},
378 {0x00, 0x0028, 0x2865},
379 {0x00, 0x0028, 0x2866},
380 {0x00, 0x0028, 0x2867},
381 {0x00, 0x0028, 0x2868},
382 {0x00, 0x0028, 0x2869},
383 {0x00, 0x0028, 0x286a},
384 {0x00, 0x0028, 0x286b},
385 {0x00, 0x0028, 0x286c},
386 {0x00, 0x0028, 0x286d},
387 {0x00, 0x0028, 0x286e},
388 {0x00, 0x0028, 0x286f},
390 {0x00, 0x0028, 0x2870},
391 {0x00, 0x0028, 0x2871},
392 {0x00, 0x0028, 0x2872},
393 {0x00, 0x0028, 0x2873},
394 {0x00, 0x0028, 0x2874},
395 {0x00, 0x0028, 0x2875},
396 {0x00, 0x0028, 0x2876},
397 {0x00, 0x0028, 0x2877},
398 {0x00, 0x0028, 0x2878},
399 {0x00, 0x0028, 0x2879},
400 {0x00, 0x0028, 0x287a},
401 {0x00, 0x0028, 0x287b},
402 {0x00, 0x0028, 0x287c},
403 {0x00, 0x0028, 0x287d},
404 {0x00, 0x0028, 0x287e},
405 {0x00, 0x0028, 0x287f},
407 {0xa0, 0x0000, 0x0503},
410 static const u8 qtable_creative_pccam
[2][64] = {
411 { /* Q-table Y-components */
412 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
413 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
414 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
415 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
416 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
417 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
418 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
419 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
420 { /* Q-table C-components */
421 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
424 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
425 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
426 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
427 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
428 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
431 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
432 * except for one byte. Possibly a typo?
435 static const u8 qtable_spca504_default
[2][64] = {
436 { /* Q-table Y-components */
437 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
438 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
439 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
440 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
441 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
442 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
443 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
444 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
446 { /* Q-table C-components */
447 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
450 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
451 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
452 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
453 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
454 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
457 /* read <len> bytes to gspca_dev->usb_buf */
458 static void reg_r(struct gspca_dev
*gspca_dev
,
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
,
480 static void reg_w_1(struct gspca_dev
*gspca_dev
,
486 gspca_dev
->usb_buf
[0] = byte
;
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 gspca_dev
->usb_buf
, 1,
496 /* write req / index / value */
497 static int reg_w_riv(struct usb_device
*dev
,
498 u8 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 u8 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 struct cmd
*data
, int ncmds
)
562 struct usb_device
*dev
= gspca_dev
->dev
;
565 while (--ncmds
>= 0) {
566 ret
= reg_w_riv(dev
, data
->req
, data
->idx
, data
->val
);
569 "Register write failed for 0x%02x, 0x%04x, 0x%04x",
570 data
->req
, data
->val
, data
->idx
);
578 static int spca50x_setup_qtable(struct gspca_dev
*gspca_dev
,
579 const u8 qtable
[2][64])
581 struct usb_device
*dev
= gspca_dev
->dev
;
584 /* loop over y components */
585 for (i
= 0; i
< 64; i
++) {
586 err
= reg_w_riv(dev
, 0x00, 0x2800 + i
, qtable
[0][i
]);
591 /* loop over c components */
592 for (i
= 0; i
< 64; i
++) {
593 err
= reg_w_riv(dev
, 0x00, 0x2840 + i
, qtable
[1][i
]);
600 static void spca504_acknowledged_command(struct gspca_dev
*gspca_dev
,
601 u8 req
, u16 idx
, u16 val
)
603 struct usb_device
*dev
= gspca_dev
->dev
;
606 reg_w_riv(dev
, req
, idx
, val
);
607 notdone
= reg_r_12(gspca_dev
, 0x01, 0x0001, 1);
608 reg_w_riv(dev
, req
, idx
, val
);
610 PDEBUG(D_FRAM
, "before wait 0x%04x", notdone
);
613 notdone
= reg_r_12(gspca_dev
, 0x01, 0x0001, 1);
614 PDEBUG(D_FRAM
, "after wait 0x%04x", notdone
);
617 static void spca504A_acknowledged_command(struct gspca_dev
*gspca_dev
,
619 u16 idx
, u16 val
, u8 stat
, u8 count
)
621 struct usb_device
*dev
= gspca_dev
->dev
;
625 reg_w_riv(dev
, req
, idx
, val
);
626 status
= reg_r_12(gspca_dev
, 0x01, 0x0001, 1);
628 PDEBUG(D_FRAM
, "Status 0x%x Need 0x%04x", status
, stat
);
632 while (--count
> 0) {
634 /* gsmart mini2 write a each wait setting 1 ms is enought */
635 /* reg_w_riv(dev, req, idx, val); */
636 status
= reg_r_12(gspca_dev
, 0x01, 0x0001, 1);
637 if (status
== endcode
) {
638 PDEBUG(D_FRAM
, "status 0x%04x after wait %d",
639 status
, 200 - count
);
645 static int spca504B_PollingDataReady(struct gspca_dev
*gspca_dev
)
649 while (--count
> 0) {
650 reg_r(gspca_dev
, 0x21, 0, 1);
651 if ((gspca_dev
->usb_buf
[0] & 0x01) == 0)
655 return gspca_dev
->usb_buf
[0];
658 static void spca504B_WaitCmdStatus(struct gspca_dev
*gspca_dev
)
662 while (--count
> 0) {
663 reg_r(gspca_dev
, 0x21, 1, 1);
664 if (gspca_dev
->usb_buf
[0] != 0) {
665 reg_w_1(gspca_dev
, 0x21, 0, 1, 0);
666 reg_r(gspca_dev
, 0x21, 1, 1);
667 spca504B_PollingDataReady(gspca_dev
);
674 static void spca50x_GetFirmware(struct gspca_dev
*gspca_dev
)
678 data
= gspca_dev
->usb_buf
;
679 reg_r(gspca_dev
, 0x20, 0, 5);
680 PDEBUG(D_STREAM
, "FirmWare : %d %d %d %d %d ",
681 data
[0], data
[1], data
[2], data
[3], data
[4]);
682 reg_r(gspca_dev
, 0x23, 0, 64);
683 reg_r(gspca_dev
, 0x23, 1, 64);
686 static void spca504B_SetSizeType(struct gspca_dev
*gspca_dev
)
688 struct sd
*sd
= (struct sd
*) gspca_dev
;
689 struct usb_device
*dev
= gspca_dev
->dev
;
693 Size
= gspca_dev
->cam
.cam_mode
[gspca_dev
->curr_mode
].priv
;
694 switch (sd
->bridge
) {
696 reg_w_riv(dev
, 0x31, 0, 0);
697 spca504B_WaitCmdStatus(gspca_dev
);
698 rc
= spca504B_PollingDataReady(gspca_dev
);
699 spca50x_GetFirmware(gspca_dev
);
700 reg_w_1(gspca_dev
, 0x24, 0, 8, 2); /* type */
701 reg_r(gspca_dev
, 0x24, 8, 1);
703 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
704 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
705 rc
= spca504B_PollingDataReady(gspca_dev
);
707 /* Init the cam width height with some values get on init ? */
708 reg_w_riv(dev
, 0x31, 0, 0x04);
709 spca504B_WaitCmdStatus(gspca_dev
);
710 rc
= spca504B_PollingDataReady(gspca_dev
);
713 /* case BRIDGE_SPCA504B: */
714 /* case BRIDGE_SPCA536: */
715 reg_w_1(gspca_dev
, 0x25, 0, 4, Size
);
716 reg_r(gspca_dev
, 0x25, 4, 1); /* size */
717 reg_w_1(gspca_dev
, 0x27, 0, 0, 6);
718 reg_r(gspca_dev
, 0x27, 0, 1); /* type */
719 rc
= spca504B_PollingDataReady(gspca_dev
);
723 if (sd
->subtype
== AiptekMiniPenCam13
) {
724 /* spca504a aiptek */
725 spca504A_acknowledged_command(gspca_dev
,
727 0x80 | (Size
& 0x0f), 1);
728 spca504A_acknowledged_command(gspca_dev
,
731 spca504_acknowledged_command(gspca_dev
, 0x08, Size
, 0);
734 case BRIDGE_SPCA504C
:
736 reg_w_riv(dev
, 0xa0, (0x0500 | (Size
& 0x0f)), 0x00);
737 reg_w_riv(dev
, 0x20, 0x01, 0x0500 | (Size
& 0x0f));
742 static void spca504_wait_status(struct gspca_dev
*gspca_dev
)
748 /* With this we get the status, when return 0 it's all ok */
749 if (reg_r_12(gspca_dev
, 0x06, 0x00, 1) == 0)
755 static void spca504B_setQtable(struct gspca_dev
*gspca_dev
)
757 reg_w_1(gspca_dev
, 0x26, 0, 0, 3);
758 reg_r(gspca_dev
, 0x26, 0, 1);
759 spca504B_PollingDataReady(gspca_dev
);
762 static void setbrightness(struct gspca_dev
*gspca_dev
)
764 struct sd
*sd
= (struct sd
*) gspca_dev
;
765 struct usb_device
*dev
= gspca_dev
->dev
;
768 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f0 : 0x21a7;
769 reg_w_riv(dev
, 0x00, reg
, sd
->brightness
);
772 static void setcontrast(struct gspca_dev
*gspca_dev
)
774 struct sd
*sd
= (struct sd
*) gspca_dev
;
775 struct usb_device
*dev
= gspca_dev
->dev
;
778 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f1 : 0x21a8;
779 reg_w_riv(dev
, 0x00, reg
, sd
->contrast
);
782 static void setcolors(struct gspca_dev
*gspca_dev
)
784 struct sd
*sd
= (struct sd
*) gspca_dev
;
785 struct usb_device
*dev
= gspca_dev
->dev
;
788 reg
= sd
->bridge
== BRIDGE_SPCA536
? 0x20f6 : 0x21ae;
789 reg_w_riv(dev
, 0x00, reg
, sd
->colors
);
792 static void init_ctl_reg(struct gspca_dev
*gspca_dev
)
794 struct sd
*sd
= (struct sd
*) gspca_dev
;
795 struct usb_device
*dev
= gspca_dev
->dev
;
798 setbrightness(gspca_dev
);
799 setcontrast(gspca_dev
);
800 setcolors(gspca_dev
);
802 switch (sd
->bridge
) {
804 case BRIDGE_SPCA504C
:
808 /* case BRIDGE_SPCA533: */
809 /* case BRIDGE_SPCA504B: */
810 reg_w_riv(dev
, 0, 0x00, 0x21ad); /* hue */
811 reg_w_riv(dev
, 0, 0x01, 0x21ac); /* sat/hue */
812 reg_w_riv(dev
, 0, 0x00, 0x21a3); /* gamma */
815 reg_w_riv(dev
, 0, 0x40, 0x20f5);
816 reg_w_riv(dev
, 0, 0x01, 0x20f4);
817 reg_w_riv(dev
, 0, 0x00, 0x2089);
821 spca504B_PollingDataReady(gspca_dev
);
824 /* this function is called at probe time */
825 static int sd_config(struct gspca_dev
*gspca_dev
,
826 const struct usb_device_id
*id
)
828 struct sd
*sd
= (struct sd
*) gspca_dev
;
831 cam
= &gspca_dev
->cam
;
833 sd
->bridge
= id
->driver_info
>> 8;
834 sd
->subtype
= id
->driver_info
;
836 if (sd
->subtype
== AiptekMiniPenCam13
) {
837 /* try to get the firmware as some cam answer 2.0.1.2.2
838 * and should be a spca504b then overwrite that setting */
839 reg_r(gspca_dev
, 0x20, 0, 1);
840 switch (gspca_dev
->usb_buf
[0]) {
842 break; /* (right bridge/subtype) */
844 sd
->bridge
= BRIDGE_SPCA504B
;
852 switch (sd
->bridge
) {
854 /* case BRIDGE_SPCA504B: */
855 /* case BRIDGE_SPCA504: */
856 /* case BRIDGE_SPCA536: */
857 cam
->cam_mode
= vga_mode
;
858 cam
->nmodes
=ARRAY_SIZE(vga_mode
);
861 cam
->cam_mode
= custom_mode
;
862 if (sd
->subtype
== MegaImageVI
) /* 320x240 only */
863 cam
->nmodes
= ARRAY_SIZE(custom_mode
) - 1;
865 cam
->nmodes
= ARRAY_SIZE(custom_mode
);
867 case BRIDGE_SPCA504C
:
868 cam
->cam_mode
= vga_mode2
;
869 cam
->nmodes
= ARRAY_SIZE(vga_mode2
);
872 sd
->brightness
= BRIGHTNESS_DEF
;
873 sd
->contrast
= CONTRAST_DEF
;
874 sd
->colors
= COLOR_DEF
;
875 sd
->autogain
= AUTOGAIN_DEF
;
876 sd
->quality
= QUALITY_DEF
;
880 /* this function is called at probe and resume time */
881 static int sd_init(struct gspca_dev
*gspca_dev
)
883 struct sd
*sd
= (struct sd
*) gspca_dev
;
884 struct usb_device
*dev
= gspca_dev
->dev
;
888 switch (sd
->bridge
) {
889 case BRIDGE_SPCA504B
:
890 reg_w_riv(dev
, 0x1d, 0x00, 0);
891 reg_w_riv(dev
, 0, 0x01, 0x2306);
892 reg_w_riv(dev
, 0, 0x00, 0x0d04);
893 reg_w_riv(dev
, 0, 0x00, 0x2000);
894 reg_w_riv(dev
, 0, 0x13, 0x2301);
895 reg_w_riv(dev
, 0, 0x00, 0x2306);
898 spca504B_PollingDataReady(gspca_dev
);
899 spca50x_GetFirmware(gspca_dev
);
902 spca50x_GetFirmware(gspca_dev
);
903 reg_r(gspca_dev
, 0x00, 0x5002, 1);
904 reg_w_1(gspca_dev
, 0x24, 0, 0, 0);
905 reg_r(gspca_dev
, 0x24, 0, 1);
906 spca504B_PollingDataReady(gspca_dev
);
907 reg_w_riv(dev
, 0x34, 0, 0);
908 spca504B_WaitCmdStatus(gspca_dev
);
910 case BRIDGE_SPCA504C
: /* pccam600 */
911 PDEBUG(D_STREAM
, "Opening SPCA504 (PC-CAM 600)");
912 reg_w_riv(dev
, 0xe0, 0x0000, 0x0000);
913 reg_w_riv(dev
, 0xe0, 0x0000, 0x0001); /* reset */
914 spca504_wait_status(gspca_dev
);
915 if (sd
->subtype
== LogitechClickSmart420
)
916 write_vector(gspca_dev
,
917 spca504A_clicksmart420_open_data
,
918 ARRAY_SIZE(spca504A_clicksmart420_open_data
));
920 write_vector(gspca_dev
, spca504_pccam600_open_data
,
921 ARRAY_SIZE(spca504_pccam600_open_data
));
922 err_code
= spca50x_setup_qtable(gspca_dev
,
923 qtable_creative_pccam
);
925 PDEBUG(D_ERR
|D_STREAM
, "spca50x_setup_qtable failed");
930 /* case BRIDGE_SPCA504: */
931 PDEBUG(D_STREAM
, "Opening SPCA504");
932 if (sd
->subtype
== AiptekMiniPenCam13
) {
933 /*****************************/
934 for (i
= 0; i
< 6; i
++)
935 info
[i
] = reg_r_1(gspca_dev
, i
);
937 "Read info: %d %d %d %d %d %d."
938 " Should be 1,0,2,2,0,0",
939 info
[0], info
[1], info
[2],
940 info
[3], info
[4], info
[5]);
941 /* spca504a aiptek */
942 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
943 spca504A_acknowledged_command(gspca_dev
, 0x24,
945 /* Twice sequencial need status 0xff->0x9e->0x9d */
946 spca504A_acknowledged_command(gspca_dev
, 0x24,
949 spca504A_acknowledged_command(gspca_dev
, 0x24,
951 /******************************/
952 /* spca504a aiptek */
953 spca504A_acknowledged_command(gspca_dev
, 0x08,
955 /* reg_write (dev, 0, 0x2000, 0); */
956 /* reg_write (dev, 0, 0x2883, 1); */
957 /* spca504A_acknowledged_command (gspca_dev, 0x08,
959 /* spca504A_acknowledged_command (gspca_dev, 0x24,
961 reg_w_riv(dev
, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */
962 reg_w_riv(dev
, 0x00, 0x2310, 0x05);
963 spca504A_acknowledged_command(gspca_dev
, 0x01,
967 reg_w_riv(dev
, 0, 0x2000, 0);
968 reg_w_riv(dev
, 0, 0x2883, 1);
969 err_code
= spca50x_setup_qtable(gspca_dev
,
970 qtable_spca504_default
);
972 PDEBUG(D_ERR
, "spca50x_setup_qtable failed");
980 static int sd_start(struct gspca_dev
*gspca_dev
)
982 struct sd
*sd
= (struct sd
*) gspca_dev
;
983 struct usb_device
*dev
= gspca_dev
->dev
;
988 /* create the JPEG header */
989 sd
->jpeg_hdr
= kmalloc(JPEG_HDR_SZ
, GFP_KERNEL
);
992 jpeg_define(sd
->jpeg_hdr
, gspca_dev
->height
, gspca_dev
->width
,
993 0x22); /* JPEG 411 */
994 jpeg_set_qual(sd
->jpeg_hdr
, sd
->quality
);
996 if (sd
->bridge
== BRIDGE_SPCA504B
)
997 spca504B_setQtable(gspca_dev
);
998 spca504B_SetSizeType(gspca_dev
);
999 switch (sd
->bridge
) {
1001 /* case BRIDGE_SPCA504B: */
1002 /* case BRIDGE_SPCA533: */
1003 /* case BRIDGE_SPCA536: */
1004 switch (sd
->subtype
) {
1006 case LogitechClickSmart820
:
1008 reg_w_riv(dev
, 0xf0, 0, 0);
1009 spca504B_WaitCmdStatus(gspca_dev
);
1010 reg_r(gspca_dev
, 0xf0, 4, 0);
1011 spca504B_WaitCmdStatus(gspca_dev
);
1014 reg_w_riv(dev
, 0x31, 0, 0x04);
1015 spca504B_WaitCmdStatus(gspca_dev
);
1016 spca504B_PollingDataReady(gspca_dev
);
1020 case BRIDGE_SPCA504
:
1021 if (sd
->subtype
== AiptekMiniPenCam13
) {
1022 for (i
= 0; i
< 6; i
++)
1023 info
[i
] = reg_r_1(gspca_dev
, i
);
1025 "Read info: %d %d %d %d %d %d."
1026 " Should be 1,0,2,2,0,0",
1027 info
[0], info
[1], info
[2],
1028 info
[3], info
[4], info
[5]);
1029 /* spca504a aiptek */
1030 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1031 spca504A_acknowledged_command(gspca_dev
, 0x24,
1033 /* Twice sequencial need status 0xff->0x9e->0x9d */
1034 spca504A_acknowledged_command(gspca_dev
, 0x24,
1036 spca504A_acknowledged_command(gspca_dev
, 0x24,
1039 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
1040 for (i
= 0; i
< 6; i
++)
1041 info
[i
] = reg_r_1(gspca_dev
, i
);
1043 "Read info: %d %d %d %d %d %d."
1044 " Should be 1,0,2,2,0,0",
1045 info
[0], info
[1], info
[2],
1046 info
[3], info
[4], info
[5]);
1047 spca504_acknowledged_command(gspca_dev
, 0x24, 8, 3);
1048 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
1050 spca504B_SetSizeType(gspca_dev
);
1051 reg_w_riv(dev
, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */
1052 reg_w_riv(dev
, 0x00, 0x2310, 0x05);
1054 case BRIDGE_SPCA504C
:
1055 if (sd
->subtype
== LogitechClickSmart420
) {
1056 write_vector(gspca_dev
,
1057 spca504A_clicksmart420_init_data
,
1058 ARRAY_SIZE(spca504A_clicksmart420_init_data
));
1060 write_vector(gspca_dev
, spca504_pccam600_init_data
,
1061 ARRAY_SIZE(spca504_pccam600_init_data
));
1063 enable
= (sd
->autogain
? 0x04 : 0x01);
1064 reg_w_riv(dev
, 0x0c, 0x0000, enable
); /* auto exposure */
1065 reg_w_riv(dev
, 0xb0, 0x0000, enable
); /* auto whiteness */
1067 /* set default exposure compensation and whiteness balance */
1068 reg_w_riv(dev
, 0x30, 0x0001, 800); /* ~ 20 fps */
1069 reg_w_riv(dev
, 0x30, 0x0002, 1600);
1070 spca504B_SetSizeType(gspca_dev
);
1073 init_ctl_reg(gspca_dev
);
1077 static void sd_stopN(struct gspca_dev
*gspca_dev
)
1079 struct sd
*sd
= (struct sd
*) gspca_dev
;
1080 struct usb_device
*dev
= gspca_dev
->dev
;
1082 switch (sd
->bridge
) {
1084 /* case BRIDGE_SPCA533: */
1085 /* case BRIDGE_SPCA536: */
1086 /* case BRIDGE_SPCA504B: */
1087 reg_w_riv(dev
, 0x31, 0, 0);
1088 spca504B_WaitCmdStatus(gspca_dev
);
1089 spca504B_PollingDataReady(gspca_dev
);
1091 case BRIDGE_SPCA504
:
1092 case BRIDGE_SPCA504C
:
1093 reg_w_riv(dev
, 0x00, 0x2000, 0x0000);
1095 if (sd
->subtype
== AiptekMiniPenCam13
) {
1096 /* spca504a aiptek */
1097 /* spca504A_acknowledged_command(gspca_dev, 0x08,
1099 spca504A_acknowledged_command(gspca_dev
, 0x24,
1100 0x00, 0x00, 0x9d, 1);
1101 spca504A_acknowledged_command(gspca_dev
, 0x01,
1102 0x0f, 0x00, 0xff, 1);
1104 spca504_acknowledged_command(gspca_dev
, 0x24, 0, 0);
1105 reg_w_riv(dev
, 0x01, 0x000f, 0x0000);
1111 static void sd_stop0(struct gspca_dev
*gspca_dev
)
1113 struct sd
*sd
= (struct sd
*) gspca_dev
;
1115 kfree(sd
->jpeg_hdr
);
1118 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
1119 struct gspca_frame
*frame
, /* target */
1120 u8
*data
, /* isoc packet */
1121 int len
) /* iso packet length */
1123 struct sd
*sd
= (struct sd
*) gspca_dev
;
1125 static u8 ffd9
[] = {0xff, 0xd9};
1127 /* frames are jpeg 4.1.1 without 0xff escape */
1128 switch (sd
->bridge
) {
1129 case BRIDGE_SPCA533
:
1130 if (data
[0] == 0xff) {
1131 if (data
[1] != 0x01) { /* drop packet */
1132 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1136 data
+= SPCA533_OFFSET_DATA
;
1137 len
-= SPCA533_OFFSET_DATA
;
1143 case BRIDGE_SPCA536
:
1144 if (data
[0] == 0xff) {
1146 data
+= SPCA536_OFFSET_DATA
;
1147 len
-= SPCA536_OFFSET_DATA
;
1154 /* case BRIDGE_SPCA504: */
1155 /* case BRIDGE_SPCA504B: */
1157 case 0xfe: /* start of frame */
1159 data
+= SPCA50X_OFFSET_DATA
;
1160 len
-= SPCA50X_OFFSET_DATA
;
1162 case 0xff: /* drop packet */
1163 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1171 case BRIDGE_SPCA504C
:
1173 case 0xfe: /* start of frame */
1175 data
+= SPCA504_PCCAM600_OFFSET_DATA
;
1176 len
-= SPCA504_PCCAM600_OFFSET_DATA
;
1178 case 0xff: /* drop packet */
1179 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1188 if (sof
) { /* start of frame */
1189 frame
= gspca_frame_add(gspca_dev
, LAST_PACKET
, frame
,
1192 /* put the JPEG header in the new frame */
1193 gspca_frame_add(gspca_dev
, FIRST_PACKET
, frame
,
1194 sd
->jpeg_hdr
, JPEG_HDR_SZ
);
1197 /* add 0x00 after 0xff */
1200 if (data
[i
] == 0xff) {
1201 gspca_frame_add(gspca_dev
, INTER_PACKET
, frame
,
1210 gspca_frame_add(gspca_dev
, INTER_PACKET
, frame
, data
, len
);
1213 static int sd_setbrightness(struct gspca_dev
*gspca_dev
, __s32 val
)
1215 struct sd
*sd
= (struct sd
*) gspca_dev
;
1217 sd
->brightness
= val
;
1218 if (gspca_dev
->streaming
)
1219 setbrightness(gspca_dev
);
1223 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
)
1225 struct sd
*sd
= (struct sd
*) gspca_dev
;
1227 *val
= sd
->brightness
;
1231 static int sd_setcontrast(struct gspca_dev
*gspca_dev
, __s32 val
)
1233 struct sd
*sd
= (struct sd
*) gspca_dev
;
1236 if (gspca_dev
->streaming
)
1237 setcontrast(gspca_dev
);
1241 static int sd_getcontrast(struct gspca_dev
*gspca_dev
, __s32
*val
)
1243 struct sd
*sd
= (struct sd
*) gspca_dev
;
1245 *val
= sd
->contrast
;
1249 static int sd_setcolors(struct gspca_dev
*gspca_dev
, __s32 val
)
1251 struct sd
*sd
= (struct sd
*) gspca_dev
;
1254 if (gspca_dev
->streaming
)
1255 setcolors(gspca_dev
);
1259 static int sd_getcolors(struct gspca_dev
*gspca_dev
, __s32
*val
)
1261 struct sd
*sd
= (struct sd
*) gspca_dev
;
1267 static int sd_setautogain(struct gspca_dev
*gspca_dev
, __s32 val
)
1269 struct sd
*sd
= (struct sd
*) gspca_dev
;
1275 static int sd_getautogain(struct gspca_dev
*gspca_dev
, __s32
*val
)
1277 struct sd
*sd
= (struct sd
*) gspca_dev
;
1279 *val
= sd
->autogain
;
1283 static int sd_set_jcomp(struct gspca_dev
*gspca_dev
,
1284 struct v4l2_jpegcompression
*jcomp
)
1286 struct sd
*sd
= (struct sd
*) gspca_dev
;
1288 if (jcomp
->quality
< QUALITY_MIN
)
1289 sd
->quality
= QUALITY_MIN
;
1290 else if (jcomp
->quality
> QUALITY_MAX
)
1291 sd
->quality
= QUALITY_MAX
;
1293 sd
->quality
= jcomp
->quality
;
1294 if (gspca_dev
->streaming
)
1295 jpeg_set_qual(sd
->jpeg_hdr
, sd
->quality
);
1299 static int sd_get_jcomp(struct gspca_dev
*gspca_dev
,
1300 struct v4l2_jpegcompression
*jcomp
)
1302 struct sd
*sd
= (struct sd
*) gspca_dev
;
1304 memset(jcomp
, 0, sizeof *jcomp
);
1305 jcomp
->quality
= sd
->quality
;
1306 jcomp
->jpeg_markers
= V4L2_JPEG_MARKER_DHT
1307 | V4L2_JPEG_MARKER_DQT
;
1311 /* sub-driver description */
1312 static const struct sd_desc sd_desc
= {
1313 .name
= MODULE_NAME
,
1315 .nctrls
= ARRAY_SIZE(sd_ctrls
),
1316 .config
= sd_config
,
1321 .pkt_scan
= sd_pkt_scan
,
1322 .get_jcomp
= sd_get_jcomp
,
1323 .set_jcomp
= sd_set_jcomp
,
1326 /* -- module initialisation -- */
1327 #define BS(bridge, subtype) \
1328 .driver_info = (BRIDGE_ ## bridge << 8) \
1330 static const __devinitdata
struct usb_device_id device_table
[] = {
1331 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C
, 0)},
1332 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C
, 0)},
1333 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C
, 0)},
1334 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B
, 0)},
1335 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533
, 0)},
1336 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533
, LogitechClickSmart820
)},
1337 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C
, LogitechClickSmart420
)},
1338 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B
, 0)},
1339 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B
, 0)},
1340 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533
, 0)},
1341 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533
, 0)},
1342 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B
, 0)},
1343 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B
, 0)},
1344 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504
, AiptekMiniPenCam13
)},
1345 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B
, 0)},
1346 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533
, 0)},
1347 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536
, 0)},
1348 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B
, 0)},
1349 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533
, MegapixV4
)},
1350 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533
, MegaImageVI
)},
1351 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533
, 0)},
1352 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B
, 0)},
1353 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B
, 0)},
1354 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536
, 0)},
1355 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533
, 0)},
1356 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533
, 0)},
1357 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536
, 0)},
1358 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504
, 0)},
1359 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533
, 0)},
1360 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533
, 0)},
1361 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504
, 0)},
1362 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533
, 0)},
1363 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533
, 0)},
1364 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533
, 0)},
1365 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533
, 0)},
1366 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B
, 0)},
1367 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533
, 0)},
1368 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533
, 0)},
1369 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533
, 0)},
1370 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533
, 0)},
1371 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533
, 0)},
1372 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536
, 0)},
1373 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536
, 0)},
1374 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533
, 0)},
1375 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533
, 0)},
1376 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B
, 0)},
1377 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533
, 0)},
1378 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B
, 0)},
1379 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B
, 0)},
1380 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533
, 0)},
1381 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533
, 0)},
1382 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536
, 0)},
1383 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533
, 0)},
1384 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536
, 0)},
1385 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536
, 0)},
1386 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536
, 0)},
1387 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536
, 0)},
1388 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536
, 0)},
1391 MODULE_DEVICE_TABLE(usb
, device_table
);
1393 /* -- device connect -- */
1394 static int sd_probe(struct usb_interface
*intf
,
1395 const struct usb_device_id
*id
)
1397 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
1401 static struct usb_driver sd_driver
= {
1402 .name
= MODULE_NAME
,
1403 .id_table
= device_table
,
1405 .disconnect
= gspca_disconnect
,
1407 .suspend
= gspca_suspend
,
1408 .resume
= gspca_resume
,
1412 /* -- module insert / remove -- */
1413 static int __init
sd_mod_init(void)
1416 ret
= usb_register(&sd_driver
);
1419 PDEBUG(D_PROBE
, "registered");
1422 static void __exit
sd_mod_exit(void)
1424 usb_deregister(&sd_driver
);
1425 PDEBUG(D_PROBE
, "deregistered");
1428 module_init(sd_mod_init
);
1429 module_exit(sd_mod_exit
);