1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#define MODULE_NAME "sunplus"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31
32struct sd {
33 struct gspca_dev gspca_dev;
34
35 s8 brightness;
36 u8 contrast;
37 u8 colors;
38 u8 autogain;
39 u8 quality;
40#define QUALITY_MIN 70
41#define QUALITY_MAX 95
42#define QUALITY_DEF 85
43
44 u8 bridge;
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
50 u8 subtype;
51#define AiptekMiniPenCam13 1
52#define LogitechClickSmart420 2
53#define LogitechClickSmart820 3
54#define MegapixV4 4
55#define MegaImageVI 5
56
57 u8 *jpeg_hdr;
58};
59
60
61static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
69
70static struct ctrl sd_ctrls[] = {
71 {
72 {
73 .id = V4L2_CID_BRIGHTNESS,
74 .type = V4L2_CTRL_TYPE_INTEGER,
75 .name = "Brightness",
76 .minimum = -128,
77 .maximum = 127,
78 .step = 1,
79#define BRIGHTNESS_DEF 0
80 .default_value = BRIGHTNESS_DEF,
81 },
82 .set = sd_setbrightness,
83 .get = sd_getbrightness,
84 },
85 {
86 {
87 .id = V4L2_CID_CONTRAST,
88 .type = V4L2_CTRL_TYPE_INTEGER,
89 .name = "Contrast",
90 .minimum = 0,
91 .maximum = 0xff,
92 .step = 1,
93#define CONTRAST_DEF 0x20
94 .default_value = CONTRAST_DEF,
95 },
96 .set = sd_setcontrast,
97 .get = sd_getcontrast,
98 },
99 {
100 {
101 .id = V4L2_CID_SATURATION,
102 .type = V4L2_CTRL_TYPE_INTEGER,
103 .name = "Color",
104 .minimum = 0,
105 .maximum = 0xff,
106 .step = 1,
107#define COLOR_DEF 0x1a
108 .default_value = COLOR_DEF,
109 },
110 .set = sd_setcolors,
111 .get = sd_getcolors,
112 },
113 {
114 {
115 .id = V4L2_CID_AUTOGAIN,
116 .type = V4L2_CTRL_TYPE_BOOLEAN,
117 .name = "Auto Gain",
118 .minimum = 0,
119 .maximum = 1,
120 .step = 1,
121#define AUTOGAIN_DEF 1
122 .default_value = AUTOGAIN_DEF,
123 },
124 .set = sd_setautogain,
125 .get = sd_getautogain,
126 },
127};
128
129static const struct v4l2_pix_format vga_mode[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 320,
132 .sizeimage = 320 * 240 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 2},
135 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 640,
137 .sizeimage = 640 * 480 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 1},
140};
141
142static const struct v4l2_pix_format custom_mode[] = {
143 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .bytesperline = 320,
145 .sizeimage = 320 * 240 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
147 .priv = 2},
148 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
149 .bytesperline = 464,
150 .sizeimage = 464 * 480 * 3 / 8 + 590,
151 .colorspace = V4L2_COLORSPACE_JPEG,
152 .priv = 1},
153};
154
155static const struct v4l2_pix_format vga_mode2[] = {
156 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
157 .bytesperline = 176,
158 .sizeimage = 176 * 144 * 3 / 8 + 590,
159 .colorspace = V4L2_COLORSPACE_JPEG,
160 .priv = 4},
161 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
162 .bytesperline = 320,
163 .sizeimage = 320 * 240 * 3 / 8 + 590,
164 .colorspace = V4L2_COLORSPACE_JPEG,
165 .priv = 3},
166 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
167 .bytesperline = 352,
168 .sizeimage = 352 * 288 * 3 / 8 + 590,
169 .colorspace = V4L2_COLORSPACE_JPEG,
170 .priv = 2},
171 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
172 .bytesperline = 640,
173 .sizeimage = 640 * 480 * 3 / 8 + 590,
174 .colorspace = V4L2_COLORSPACE_JPEG,
175 .priv = 1},
176};
177
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
184#define SPCA533_OFFSET_DATA 16
185#define SPCA533_OFFSET_FRAMSEQ 15
186
187#define SPCA536_OFFSET_DATA 4
188#define SPCA536_OFFSET_FRAMSEQ 1
189
190struct cmd {
191 u8 req;
192 u16 val;
193 u16 idx;
194};
195
196
197static const struct cmd spca504_pccam600_init_data[] = {
198
199 {0x00, 0x0000, 0x2000},
200 {0x00, 0x0013, 0x2301},
201 {0x00, 0x0003, 0x2000},
202 {0x00, 0x0001, 0x21ac},
203 {0x00, 0x0001, 0x21a6},
204 {0x00, 0x0000, 0x21a7},
205 {0x00, 0x0020, 0x21a8},
206 {0x00, 0x0001, 0x21ac},
207 {0x00, 0x0000, 0x21ad},
208 {0x00, 0x001a, 0x21ae},
209 {0x00, 0x0002, 0x21a3},
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},
221};
222
223
224
225
226static const struct cmd spca504_pccam600_open_data[] = {
227 {0x00, 0x0001, 0x2501},
228 {0x20, 0x0500, 0x0001},
229 {0x00, 0x0003, 0x2880},
230 {0x00, 0x0001, 0x2881},
231};
232
233
234static const struct cmd spca504A_clicksmart420_init_data[] = {
235
236 {0x00, 0x0000, 0x2000},
237 {0x00, 0x0013, 0x2301},
238 {0x00, 0x0003, 0x2000},
239 {0x00, 0x0001, 0x21ac},
240 {0x00, 0x0001, 0x21a6},
241 {0x00, 0x0000, 0x21a7},
242 {0x00, 0x0020, 0x21a8},
243 {0x00, 0x0001, 0x21ac},
244 {0x00, 0x0000, 0x21ad},
245 {0x00, 0x001a, 0x21ae},
246 {0x00, 0x0002, 0x21a3},
247 {0x30, 0x0004, 0x000a},
248 {0xb0, 0x0001, 0x0000},
249
250
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},
260
261};
262
263
264static 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
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},
287
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},
304
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},
321
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},
338
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},
355
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},
372
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},
389
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},
406
407 {0xa0, 0x0000, 0x0503},
408};
409
410static const u8 qtable_creative_pccam[2][64] = {
411 {
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 {
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}
429};
430
431
432
433
434
435static const u8 qtable_spca504_default[2][64] = {
436 {
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 , 0x1e, 0x1f, 0x1e,
445 },
446 {
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}
455};
456
457
458static void reg_r(struct gspca_dev *gspca_dev,
459 u8 req,
460 u16 index,
461 u16 len)
462{
463#ifdef GSPCA_DEBUG
464 if (len > USB_BUF_SZ) {
465 err("reg_r: buffer overflow");
466 return;
467 }
468#endif
469 usb_control_msg(gspca_dev->dev,
470 usb_rcvctrlpipe(gspca_dev->dev, 0),
471 req,
472 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
473 0,
474 index,
475 len ? gspca_dev->usb_buf : NULL, len,
476 500);
477}
478
479
480static void reg_w_1(struct gspca_dev *gspca_dev,
481 u8 req,
482 u16 value,
483 u16 index,
484 u16 byte)
485{
486 gspca_dev->usb_buf[0] = byte;
487 usb_control_msg(gspca_dev->dev,
488 usb_sndctrlpipe(gspca_dev->dev, 0),
489 req,
490 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
491 value, index,
492 gspca_dev->usb_buf, 1,
493 500);
494}
495
496
497static int reg_w_riv(struct usb_device *dev,
498 u8 req, u16 index, u16 value)
499{
500 int ret;
501
502 ret = usb_control_msg(dev,
503 usb_sndctrlpipe(dev, 0),
504 req,
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);
509 if (ret < 0)
510 PDEBUG(D_ERR, "reg write: error %d", ret);
511 return ret;
512}
513
514
515static int reg_r_1(struct gspca_dev *gspca_dev,
516 u16 value)
517{
518 int ret;
519
520 ret = usb_control_msg(gspca_dev->dev,
521 usb_rcvctrlpipe(gspca_dev->dev, 0),
522 0x20,
523 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
524 value,
525 0,
526 gspca_dev->usb_buf, 1,
527 500);
528 if (ret < 0) {
529 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
530 return 0;
531 }
532 return gspca_dev->usb_buf[0];
533}
534
535
536static int reg_r_12(struct gspca_dev *gspca_dev,
537 u8 req,
538 u16 index,
539 u16 length)
540{
541 int ret;
542
543 gspca_dev->usb_buf[1] = 0;
544 ret = usb_control_msg(gspca_dev->dev,
545 usb_rcvctrlpipe(gspca_dev->dev, 0),
546 req,
547 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
548 0,
549 index,
550 gspca_dev->usb_buf, length,
551 500);
552 if (ret < 0) {
553 PDEBUG(D_ERR, "reg_read err %d", ret);
554 return -1;
555 }
556 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
557}
558
559static int write_vector(struct gspca_dev *gspca_dev,
560 const struct cmd *data, int ncmds)
561{
562 struct usb_device *dev = gspca_dev->dev;
563 int ret;
564
565 while (--ncmds >= 0) {
566 ret = reg_w_riv(dev, data->req, data->idx, data->val);
567 if (ret < 0) {
568 PDEBUG(D_ERR,
569 "Register write failed for 0x%02x, 0x%04x, 0x%04x",
570 data->req, data->val, data->idx);
571 return ret;
572 }
573 data++;
574 }
575 return 0;
576}
577
578static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
579 const u8 qtable[2][64])
580{
581 struct usb_device *dev = gspca_dev->dev;
582 int i, err;
583
584
585 for (i = 0; i < 64; i++) {
586 err = reg_w_riv(dev, 0x00, 0x2800 + i, qtable[0][i]);
587 if (err < 0)
588 return err;
589 }
590
591
592 for (i = 0; i < 64; i++) {
593 err = reg_w_riv(dev, 0x00, 0x2840 + i, qtable[1][i]);
594 if (err < 0)
595 return err;
596 }
597 return 0;
598}
599
600static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
601 u8 req, u16 idx, u16 val)
602{
603 struct usb_device *dev = gspca_dev->dev;
604 int notdone;
605
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);
609
610 PDEBUG(D_FRAM, "before wait 0x%04x", notdone);
611
612 msleep(200);
613 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
614 PDEBUG(D_FRAM, "after wait 0x%04x", notdone);
615}
616
617static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
618 u8 req,
619 u16 idx, u16 val, u8 stat, u8 count)
620{
621 struct usb_device *dev = gspca_dev->dev;
622 int status;
623 u8 endcode;
624
625 reg_w_riv(dev, req, idx, val);
626 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
627 endcode = stat;
628 PDEBUG(D_FRAM, "Status 0x%x Need 0x%04x", status, stat);
629 if (!count)
630 return;
631 count = 200;
632 while (--count > 0) {
633 msleep(10);
634
635
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);
640 break;
641 }
642 }
643}
644
645static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
646{
647 int count = 10;
648
649 while (--count > 0) {
650 reg_r(gspca_dev, 0x21, 0, 1);
651 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
652 break;
653 msleep(10);
654 }
655 return gspca_dev->usb_buf[0];
656}
657
658static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
659{
660 int count = 50;
661
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);
668 break;
669 }
670 msleep(10);
671 }
672}
673
674static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
675{
676 u8 *data;
677
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);
684}
685
686static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
687{
688 struct sd *sd = (struct sd *) gspca_dev;
689 struct usb_device *dev = gspca_dev->dev;
690 u8 Size;
691 int rc;
692
693 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
694 switch (sd->bridge) {
695 case BRIDGE_SPCA533:
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);
701 reg_r(gspca_dev, 0x24, 8, 1);
702
703 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
704 reg_r(gspca_dev, 0x25, 4, 1);
705 rc = spca504B_PollingDataReady(gspca_dev);
706
707
708 reg_w_riv(dev, 0x31, 0, 0x04);
709 spca504B_WaitCmdStatus(gspca_dev);
710 rc = spca504B_PollingDataReady(gspca_dev);
711 break;
712 default:
713
714
715 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
716 reg_r(gspca_dev, 0x25, 4, 1);
717 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
718 reg_r(gspca_dev, 0x27, 0, 1);
719 rc = spca504B_PollingDataReady(gspca_dev);
720 break;
721 case BRIDGE_SPCA504:
722 Size += 3;
723 if (sd->subtype == AiptekMiniPenCam13) {
724
725 spca504A_acknowledged_command(gspca_dev,
726 0x08, Size, 0,
727 0x80 | (Size & 0x0f), 1);
728 spca504A_acknowledged_command(gspca_dev,
729 1, 3, 0, 0x9f, 0);
730 } else {
731 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
732 }
733 break;
734 case BRIDGE_SPCA504C:
735
736 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
737 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
738 break;
739 }
740}
741
742static void spca504_wait_status(struct gspca_dev *gspca_dev)
743{
744 int cnt;
745
746 cnt = 256;
747 while (--cnt > 0) {
748
749 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
750 return;
751 msleep(10);
752 }
753}
754
755static void spca504B_setQtable(struct gspca_dev *gspca_dev)
756{
757 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
758 reg_r(gspca_dev, 0x26, 0, 1);
759 spca504B_PollingDataReady(gspca_dev);
760}
761
762static void setbrightness(struct gspca_dev *gspca_dev)
763{
764 struct sd *sd = (struct sd *) gspca_dev;
765 struct usb_device *dev = gspca_dev->dev;
766 u16 reg;
767
768 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
769 reg_w_riv(dev, 0x00, reg, sd->brightness);
770}
771
772static void setcontrast(struct gspca_dev *gspca_dev)
773{
774 struct sd *sd = (struct sd *) gspca_dev;
775 struct usb_device *dev = gspca_dev->dev;
776 u16 reg;
777
778 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
779 reg_w_riv(dev, 0x00, reg, sd->contrast);
780}
781
782static void setcolors(struct gspca_dev *gspca_dev)
783{
784 struct sd *sd = (struct sd *) gspca_dev;
785 struct usb_device *dev = gspca_dev->dev;
786 u16 reg;
787
788 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
789 reg_w_riv(dev, 0x00, reg, sd->colors);
790}
791
792static void init_ctl_reg(struct gspca_dev *gspca_dev)
793{
794 struct sd *sd = (struct sd *) gspca_dev;
795 struct usb_device *dev = gspca_dev->dev;
796 int pollreg = 1;
797
798 setbrightness(gspca_dev);
799 setcontrast(gspca_dev);
800 setcolors(gspca_dev);
801
802 switch (sd->bridge) {
803 case BRIDGE_SPCA504:
804 case BRIDGE_SPCA504C:
805 pollreg = 0;
806
807 default:
808
809
810 reg_w_riv(dev, 0, 0x00, 0x21ad);
811 reg_w_riv(dev, 0, 0x01, 0x21ac);
812 reg_w_riv(dev, 0, 0x00, 0x21a3);
813 break;
814 case BRIDGE_SPCA536:
815 reg_w_riv(dev, 0, 0x40, 0x20f5);
816 reg_w_riv(dev, 0, 0x01, 0x20f4);
817 reg_w_riv(dev, 0, 0x00, 0x2089);
818 break;
819 }
820 if (pollreg)
821 spca504B_PollingDataReady(gspca_dev);
822}
823
824
825static int sd_config(struct gspca_dev *gspca_dev,
826 const struct usb_device_id *id)
827{
828 struct sd *sd = (struct sd *) gspca_dev;
829 struct cam *cam;
830
831 cam = &gspca_dev->cam;
832
833 sd->bridge = id->driver_info >> 8;
834 sd->subtype = id->driver_info;
835
836 if (sd->subtype == AiptekMiniPenCam13) {
837
838
839 reg_r(gspca_dev, 0x20, 0, 1);
840 switch (gspca_dev->usb_buf[0]) {
841 case 1:
842 break;
843 case 2:
844 sd->bridge = BRIDGE_SPCA504B;
845 sd->subtype = 0;
846 break;
847 default:
848 return -ENODEV;
849 }
850 }
851
852 switch (sd->bridge) {
853 default:
854
855
856
857 cam->cam_mode = vga_mode;
858 cam->nmodes =ARRAY_SIZE(vga_mode);
859 break;
860 case BRIDGE_SPCA533:
861 cam->cam_mode = custom_mode;
862 if (sd->subtype == MegaImageVI)
863 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
864 else
865 cam->nmodes = ARRAY_SIZE(custom_mode);
866 break;
867 case BRIDGE_SPCA504C:
868 cam->cam_mode = vga_mode2;
869 cam->nmodes = ARRAY_SIZE(vga_mode2);
870 break;
871 }
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;
877 return 0;
878}
879
880
881static int sd_init(struct gspca_dev *gspca_dev)
882{
883 struct sd *sd = (struct sd *) gspca_dev;
884 struct usb_device *dev = gspca_dev->dev;
885 int i, err_code;
886 u8 info[6];
887
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);
896
897 case BRIDGE_SPCA533:
898 spca504B_PollingDataReady(gspca_dev);
899 spca50x_GetFirmware(gspca_dev);
900 break;
901 case BRIDGE_SPCA536:
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);
909 break;
910 case BRIDGE_SPCA504C:
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);
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));
919 else
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);
924 if (err_code < 0) {
925 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
926 return err_code;
927 }
928 break;
929 default:
930
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);
936 PDEBUG(D_STREAM,
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
942
943 spca504A_acknowledged_command(gspca_dev, 0x24,
944 8, 3, 0x9e, 1);
945
946 spca504A_acknowledged_command(gspca_dev, 0x24,
947 8, 3, 0x9e, 0);
948
949 spca504A_acknowledged_command(gspca_dev, 0x24,
950 0, 0, 0x9d, 1);
951
952
953 spca504A_acknowledged_command(gspca_dev, 0x08,
954 6, 0, 0x86, 1);
955
956
957
958
959
960
961 reg_w_riv(dev, 0x00, 0x270c, 0x05);
962 reg_w_riv(dev, 0x00, 0x2310, 0x05);
963 spca504A_acknowledged_command(gspca_dev, 0x01,
964 0x0f, 0, 0xff, 0);
965 }
966
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);
971 if (err_code < 0) {
972 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
973 return err_code;
974 }
975 break;
976 }
977 return 0;
978}
979
980static int sd_start(struct gspca_dev *gspca_dev)
981{
982 struct sd *sd = (struct sd *) gspca_dev;
983 struct usb_device *dev = gspca_dev->dev;
984 int enable;
985 int i;
986 u8 info[6];
987
988
989 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
990 if (!sd->jpeg_hdr)
991 return -ENOMEM;
992 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
993 0x22);
994 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
995
996 if (sd->bridge == BRIDGE_SPCA504B)
997 spca504B_setQtable(gspca_dev);
998 spca504B_SetSizeType(gspca_dev);
999 switch (sd->bridge) {
1000 default:
1001
1002
1003
1004 switch (sd->subtype) {
1005 case MegapixV4:
1006 case LogitechClickSmart820:
1007 case MegaImageVI:
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);
1012 break;
1013 default:
1014 reg_w_riv(dev, 0x31, 0, 0x04);
1015 spca504B_WaitCmdStatus(gspca_dev);
1016 spca504B_PollingDataReady(gspca_dev);
1017 break;
1018 }
1019 break;
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);
1024 PDEBUG(D_STREAM,
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
1030
1031 spca504A_acknowledged_command(gspca_dev, 0x24,
1032 8, 3, 0x9e, 1);
1033
1034 spca504A_acknowledged_command(gspca_dev, 0x24,
1035 8, 3, 0x9e, 0);
1036 spca504A_acknowledged_command(gspca_dev, 0x24,
1037 0, 0, 0x9d, 1);
1038 } else {
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);
1042 PDEBUG(D_STREAM,
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);
1049 }
1050 spca504B_SetSizeType(gspca_dev);
1051 reg_w_riv(dev, 0x00, 0x270c, 0x05);
1052 reg_w_riv(dev, 0x00, 0x2310, 0x05);
1053 break;
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));
1059 } else {
1060 write_vector(gspca_dev, spca504_pccam600_init_data,
1061 ARRAY_SIZE(spca504_pccam600_init_data));
1062 }
1063 enable = (sd->autogain ? 0x04 : 0x01);
1064 reg_w_riv(dev, 0x0c, 0x0000, enable);
1065 reg_w_riv(dev, 0xb0, 0x0000, enable);
1066
1067
1068 reg_w_riv(dev, 0x30, 0x0001, 800);
1069 reg_w_riv(dev, 0x30, 0x0002, 1600);
1070 spca504B_SetSizeType(gspca_dev);
1071 break;
1072 }
1073 init_ctl_reg(gspca_dev);
1074 return 0;
1075}
1076
1077static void sd_stopN(struct gspca_dev *gspca_dev)
1078{
1079 struct sd *sd = (struct sd *) gspca_dev;
1080 struct usb_device *dev = gspca_dev->dev;
1081
1082 switch (sd->bridge) {
1083 default:
1084
1085
1086
1087 reg_w_riv(dev, 0x31, 0, 0);
1088 spca504B_WaitCmdStatus(gspca_dev);
1089 spca504B_PollingDataReady(gspca_dev);
1090 break;
1091 case BRIDGE_SPCA504:
1092 case BRIDGE_SPCA504C:
1093 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
1094
1095 if (sd->subtype == AiptekMiniPenCam13) {
1096
1097
1098
1099 spca504A_acknowledged_command(gspca_dev, 0x24,
1100 0x00, 0x00, 0x9d, 1);
1101 spca504A_acknowledged_command(gspca_dev, 0x01,
1102 0x0f, 0x00, 0xff, 1);
1103 } else {
1104 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1105 reg_w_riv(dev, 0x01, 0x000f, 0x0000);
1106 }
1107 break;
1108 }
1109}
1110
1111static void sd_stop0(struct gspca_dev *gspca_dev)
1112{
1113 struct sd *sd = (struct sd *) gspca_dev;
1114
1115 kfree(sd->jpeg_hdr);
1116}
1117
1118static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1119 struct gspca_frame *frame,
1120 u8 *data,
1121 int len)
1122{
1123 struct sd *sd = (struct sd *) gspca_dev;
1124 int i, sof = 0;
1125 static u8 ffd9[] = {0xff, 0xd9};
1126
1127
1128 switch (sd->bridge) {
1129 case BRIDGE_SPCA533:
1130 if (data[0] == 0xff) {
1131 if (data[1] != 0x01) {
1132
1133 return;
1134 }
1135 sof = 1;
1136 data += SPCA533_OFFSET_DATA;
1137 len -= SPCA533_OFFSET_DATA;
1138 } else {
1139 data += 1;
1140 len -= 1;
1141 }
1142 break;
1143 case BRIDGE_SPCA536:
1144 if (data[0] == 0xff) {
1145 sof = 1;
1146 data += SPCA536_OFFSET_DATA;
1147 len -= SPCA536_OFFSET_DATA;
1148 } else {
1149 data += 2;
1150 len -= 2;
1151 }
1152 break;
1153 default:
1154
1155
1156 switch (data[0]) {
1157 case 0xfe:
1158 sof = 1;
1159 data += SPCA50X_OFFSET_DATA;
1160 len -= SPCA50X_OFFSET_DATA;
1161 break;
1162 case 0xff:
1163
1164 return;
1165 default:
1166 data += 1;
1167 len -= 1;
1168 break;
1169 }
1170 break;
1171 case BRIDGE_SPCA504C:
1172 switch (data[0]) {
1173 case 0xfe:
1174 sof = 1;
1175 data += SPCA504_PCCAM600_OFFSET_DATA;
1176 len -= SPCA504_PCCAM600_OFFSET_DATA;
1177 break;
1178 case 0xff:
1179
1180 return;
1181 default:
1182 data += 1;
1183 len -= 1;
1184 break;
1185 }
1186 break;
1187 }
1188 if (sof) {
1189 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1190 ffd9, 2);
1191
1192
1193 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
1194 sd->jpeg_hdr, JPEG_HDR_SZ);
1195 }
1196
1197
1198 i = 0;
1199 do {
1200 if (data[i] == 0xff) {
1201 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1202 data, i + 1);
1203 len -= i;
1204 data += i;
1205 *data = 0x00;
1206 i = 0;
1207 }
1208 i++;
1209 } while (i < len);
1210 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1211}
1212
1213static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1214{
1215 struct sd *sd = (struct sd *) gspca_dev;
1216
1217 sd->brightness = val;
1218 if (gspca_dev->streaming)
1219 setbrightness(gspca_dev);
1220 return 0;
1221}
1222
1223static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1224{
1225 struct sd *sd = (struct sd *) gspca_dev;
1226
1227 *val = sd->brightness;
1228 return 0;
1229}
1230
1231static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1232{
1233 struct sd *sd = (struct sd *) gspca_dev;
1234
1235 sd->contrast = val;
1236 if (gspca_dev->streaming)
1237 setcontrast(gspca_dev);
1238 return 0;
1239}
1240
1241static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1242{
1243 struct sd *sd = (struct sd *) gspca_dev;
1244
1245 *val = sd->contrast;
1246 return 0;
1247}
1248
1249static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1250{
1251 struct sd *sd = (struct sd *) gspca_dev;
1252
1253 sd->colors = val;
1254 if (gspca_dev->streaming)
1255 setcolors(gspca_dev);
1256 return 0;
1257}
1258
1259static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1260{
1261 struct sd *sd = (struct sd *) gspca_dev;
1262
1263 *val = sd->colors;
1264 return 0;
1265}
1266
1267static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1268{
1269 struct sd *sd = (struct sd *) gspca_dev;
1270
1271 sd->autogain = val;
1272 return 0;
1273}
1274
1275static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1276{
1277 struct sd *sd = (struct sd *) gspca_dev;
1278
1279 *val = sd->autogain;
1280 return 0;
1281}
1282
1283static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1284 struct v4l2_jpegcompression *jcomp)
1285{
1286 struct sd *sd = (struct sd *) gspca_dev;
1287
1288 if (jcomp->quality < QUALITY_MIN)
1289 sd->quality = QUALITY_MIN;
1290 else if (jcomp->quality > QUALITY_MAX)
1291 sd->quality = QUALITY_MAX;
1292 else
1293 sd->quality = jcomp->quality;
1294 if (gspca_dev->streaming)
1295 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1296 return 0;
1297}
1298
1299static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1300 struct v4l2_jpegcompression *jcomp)
1301{
1302 struct sd *sd = (struct sd *) gspca_dev;
1303
1304 memset(jcomp, 0, sizeof *jcomp);
1305 jcomp->quality = sd->quality;
1306 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1307 | V4L2_JPEG_MARKER_DQT;
1308 return 0;
1309}
1310
1311
1312static const struct sd_desc sd_desc = {
1313 .name = MODULE_NAME,
1314 .ctrls = sd_ctrls,
1315 .nctrls = ARRAY_SIZE(sd_ctrls),
1316 .config = sd_config,
1317 .init = sd_init,
1318 .start = sd_start,
1319 .stopN = sd_stopN,
1320 .stop0 = sd_stop0,
1321 .pkt_scan = sd_pkt_scan,
1322 .get_jcomp = sd_get_jcomp,
1323 .set_jcomp = sd_set_jcomp,
1324};
1325
1326
1327#define BS(bridge, subtype) \
1328 .driver_info = (BRIDGE_ ## bridge << 8) \
1329 | (subtype)
1330static 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)},
1389 {}
1390};
1391MODULE_DEVICE_TABLE(usb, device_table);
1392
1393
1394static int sd_probe(struct usb_interface *intf,
1395 const struct usb_device_id *id)
1396{
1397 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1398 THIS_MODULE);
1399}
1400
1401static struct usb_driver sd_driver = {
1402 .name = MODULE_NAME,
1403 .id_table = device_table,
1404 .probe = sd_probe,
1405 .disconnect = gspca_disconnect,
1406#ifdef CONFIG_PM
1407 .suspend = gspca_suspend,
1408 .resume = gspca_resume,
1409#endif
1410};
1411
1412
1413static int __init sd_mod_init(void)
1414{
1415 int ret;
1416 ret = usb_register(&sd_driver);
1417 if (ret < 0)
1418 return ret;
1419 PDEBUG(D_PROBE, "registered");
1420 return 0;
1421}
1422static void __exit sd_mod_exit(void)
1423{
1424 usb_deregister(&sd_driver);
1425 PDEBUG(D_PROBE, "deregistered");
1426}
1427
1428module_init(sd_mod_init);
1429module_exit(sd_mod_exit);
1430