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 "spca500"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31
32struct sd {
33 struct gspca_dev gspca_dev;
34
35 unsigned char brightness;
36 unsigned char contrast;
37 unsigned char colors;
38 u8 quality;
39#define QUALITY_MIN 70
40#define QUALITY_MAX 95
41#define QUALITY_DEF 85
42
43 char subtype;
44#define AgfaCl20 0
45#define AiptekPocketDV 1
46#define BenqDC1016 2
47#define CreativePCCam300 3
48#define DLinkDSC350 4
49#define Gsmartmini 5
50#define IntelPocketPCCamera 6
51#define KodakEZ200 7
52#define LogitechClickSmart310 8
53#define LogitechClickSmart510 9
54#define LogitechTraveler 10
55#define MustekGsmart300 11
56#define Optimedia 12
57#define PalmPixDC85 13
58#define ToptroIndus 14
59
60 u8 jpeg_hdr[JPEG_HDR_SZ];
61};
62
63
64static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
70
71static const struct ctrl sd_ctrls[] = {
72 {
73 {
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Brightness",
77 .minimum = 0,
78 .maximum = 255,
79 .step = 1,
80#define BRIGHTNESS_DEF 127
81 .default_value = BRIGHTNESS_DEF,
82 },
83 .set = sd_setbrightness,
84 .get = sd_getbrightness,
85 },
86 {
87 {
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Contrast",
91 .minimum = 0,
92 .maximum = 63,
93 .step = 1,
94#define CONTRAST_DEF 31
95 .default_value = CONTRAST_DEF,
96 },
97 .set = sd_setcontrast,
98 .get = sd_getcontrast,
99 },
100 {
101 {
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Color",
105 .minimum = 0,
106 .maximum = 63,
107 .step = 1,
108#define COLOR_DEF 31
109 .default_value = COLOR_DEF,
110 },
111 .set = sd_setcolors,
112 .get = sd_getcolors,
113 },
114};
115
116static const struct v4l2_pix_format vga_mode[] = {
117 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
118 .bytesperline = 320,
119 .sizeimage = 320 * 240 * 3 / 8 + 590,
120 .colorspace = V4L2_COLORSPACE_JPEG,
121 .priv = 1},
122 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
123 .bytesperline = 640,
124 .sizeimage = 640 * 480 * 3 / 8 + 590,
125 .colorspace = V4L2_COLORSPACE_JPEG,
126 .priv = 0},
127};
128
129static const struct v4l2_pix_format sif_mode[] = {
130 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 176,
132 .sizeimage = 176 * 144 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 1},
135 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 352,
137 .sizeimage = 352 * 288 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 0},
140};
141
142
143#define SPCA500_OFFSET_PADDINGLB 2
144#define SPCA500_OFFSET_PADDINGHB 3
145#define SPCA500_OFFSET_MODE 4
146#define SPCA500_OFFSET_IMGWIDTH 5
147#define SPCA500_OFFSET_IMGHEIGHT 6
148#define SPCA500_OFFSET_IMGMODE 7
149#define SPCA500_OFFSET_QTBLINDEX 8
150#define SPCA500_OFFSET_FRAMSEQ 9
151#define SPCA500_OFFSET_CDSPINFO 10
152#define SPCA500_OFFSET_GPIO 11
153#define SPCA500_OFFSET_AUGPIO 12
154#define SPCA500_OFFSET_DATA 16
155
156
157static const __u16 spca500_visual_defaults[][3] = {
158 {0x00, 0x0003, 0x816b},
159
160
161
162
163 {0x00, 0x0000, 0x8167},
164 {0x00, 0x0020, 0x8168},
165 {0x00, 0x0003, 0x816b},
166
167
168
169
170 {0x00, 0x0000, 0x816a},
171 {0x00, 0x0020, 0x8169},
172 {0x00, 0x0050, 0x8157},
173 {0x00, 0x0030, 0x8158},
174 {0x00, 0x0028, 0x8159},
175 {0x00, 0x000a, 0x815a},
176 {0x00, 0x0001, 0x8202},
177 {0x0c, 0x0004, 0x0000},
178
179 {}
180};
181static const __u16 Clicksmart510_defaults[][3] = {
182 {0x00, 0x00, 0x8211},
183 {0x00, 0x01, 0x82c0},
184 {0x00, 0x10, 0x82cb},
185 {0x00, 0x0f, 0x800d},
186 {0x00, 0x82, 0x8225},
187 {0x00, 0x21, 0x8228},
188 {0x00, 0x00, 0x8203},
189 {0x00, 0x00, 0x8204},
190 {0x00, 0x08, 0x8205},
191 {0x00, 0xf8, 0x8206},
192 {0x00, 0x28, 0x8207},
193 {0x00, 0xa0, 0x8208},
194 {0x00, 0x08, 0x824a},
195 {0x00, 0x08, 0x8214},
196 {0x00, 0x80, 0x82c1},
197 {0x00, 0x00, 0x82c2},
198 {0x00, 0x00, 0x82ca},
199 {0x00, 0x80, 0x82c1},
200 {0x00, 0x04, 0x82c2},
201 {0x00, 0x00, 0x82ca},
202 {0x00, 0xfc, 0x8100},
203 {0x00, 0xfc, 0x8105},
204 {0x00, 0x30, 0x8101},
205 {0x00, 0x00, 0x8102},
206 {0x00, 0x00, 0x8103},
207 {0x00, 0x66, 0x8107},
208 {0x00, 0x00, 0x816b},
209 {0x00, 0x00, 0x8155},
210 {0x00, 0x01, 0x8156},
211 {0x00, 0x60, 0x8157},
212 {0x00, 0x40, 0x8158},
213 {0x00, 0x0a, 0x8159},
214 {0x00, 0x06, 0x815a},
215 {0x00, 0x00, 0x813f},
216 {0x00, 0x00, 0x8200},
217 {0x00, 0x19, 0x8201},
218 {0x00, 0x00, 0x82c1},
219 {0x00, 0xa0, 0x82c2},
220 {0x00, 0x00, 0x82ca},
221 {0x00, 0x00, 0x8117},
222 {0x00, 0x00, 0x8118},
223 {0x00, 0x65, 0x8119},
224 {0x00, 0x00, 0x811a},
225 {0x00, 0x00, 0x811b},
226 {0x00, 0x55, 0x811c},
227 {0x00, 0x65, 0x811d},
228 {0x00, 0x55, 0x811e},
229 {0x00, 0x16, 0x811f},
230 {0x00, 0x19, 0x8120},
231 {0x00, 0x80, 0x8103},
232 {0x00, 0x83, 0x816b},
233 {0x00, 0x25, 0x8168},
234 {0x00, 0x01, 0x820f},
235 {0x00, 0xff, 0x8115},
236 {0x00, 0x48, 0x8116},
237 {0x00, 0x50, 0x8151},
238 {0x00, 0x40, 0x8152},
239 {0x00, 0x78, 0x8153},
240 {0x00, 0x40, 0x8154},
241 {0x00, 0x00, 0x8167},
242 {0x00, 0x20, 0x8168},
243 {0x00, 0x00, 0x816a},
244 {0x00, 0x03, 0x816b},
245 {0x00, 0x20, 0x8169},
246 {0x00, 0x60, 0x8157},
247 {0x00, 0x00, 0x8190},
248 {0x00, 0x00, 0x81a1},
249 {0x00, 0x00, 0x81b2},
250 {0x00, 0x27, 0x8191},
251 {0x00, 0x27, 0x81a2},
252 {0x00, 0x27, 0x81b3},
253 {0x00, 0x4b, 0x8192},
254 {0x00, 0x4b, 0x81a3},
255 {0x00, 0x4b, 0x81b4},
256 {0x00, 0x66, 0x8193},
257 {0x00, 0x66, 0x81a4},
258 {0x00, 0x66, 0x81b5},
259 {0x00, 0x79, 0x8194},
260 {0x00, 0x79, 0x81a5},
261 {0x00, 0x79, 0x81b6},
262 {0x00, 0x8a, 0x8195},
263 {0x00, 0x8a, 0x81a6},
264 {0x00, 0x8a, 0x81b7},
265 {0x00, 0x9b, 0x8196},
266 {0x00, 0x9b, 0x81a7},
267 {0x00, 0x9b, 0x81b8},
268 {0x00, 0xa6, 0x8197},
269 {0x00, 0xa6, 0x81a8},
270 {0x00, 0xa6, 0x81b9},
271 {0x00, 0xb2, 0x8198},
272 {0x00, 0xb2, 0x81a9},
273 {0x00, 0xb2, 0x81ba},
274 {0x00, 0xbe, 0x8199},
275 {0x00, 0xbe, 0x81aa},
276 {0x00, 0xbe, 0x81bb},
277 {0x00, 0xc8, 0x819a},
278 {0x00, 0xc8, 0x81ab},
279 {0x00, 0xc8, 0x81bc},
280 {0x00, 0xd2, 0x819b},
281 {0x00, 0xd2, 0x81ac},
282 {0x00, 0xd2, 0x81bd},
283 {0x00, 0xdb, 0x819c},
284 {0x00, 0xdb, 0x81ad},
285 {0x00, 0xdb, 0x81be},
286 {0x00, 0xe4, 0x819d},
287 {0x00, 0xe4, 0x81ae},
288 {0x00, 0xe4, 0x81bf},
289 {0x00, 0xed, 0x819e},
290 {0x00, 0xed, 0x81af},
291 {0x00, 0xed, 0x81c0},
292 {0x00, 0xf7, 0x819f},
293 {0x00, 0xf7, 0x81b0},
294 {0x00, 0xf7, 0x81c1},
295 {0x00, 0xff, 0x81a0},
296 {0x00, 0xff, 0x81b1},
297 {0x00, 0xff, 0x81c2},
298 {0x00, 0x03, 0x8156},
299 {0x00, 0x00, 0x8211},
300 {0x00, 0x20, 0x8168},
301 {0x00, 0x01, 0x8202},
302 {0x00, 0x30, 0x8101},
303 {0x00, 0x00, 0x8111},
304 {0x00, 0x00, 0x8112},
305 {0x00, 0x00, 0x8113},
306 {0x00, 0x00, 0x8114},
307 {}
308};
309
310static const __u8 qtable_creative_pccam[2][64] = {
311 {
312 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
313 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
314 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
315 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
316 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
317 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
318 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
319 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
320 {
321 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
322 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
323 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
324 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
325 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
326 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
327 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
328 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
329};
330
331static const __u8 qtable_kodak_ez200[2][64] = {
332 {
333 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
334 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
335 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
336 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
337 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
338 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
339 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
340 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
341 {
342 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
343 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
344 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
345 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
346 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
347 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
348 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
349 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
350};
351
352static const __u8 qtable_pocketdv[2][64] = {
353 {
354 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
355 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
356 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
357 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
358 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
359 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
360 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
361 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
362 },
363 {
364 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
365 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
366 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
367 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
368 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
369 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
370 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
371 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
372};
373
374
375static void reg_r(struct gspca_dev *gspca_dev,
376 __u16 index,
377 __u16 length)
378{
379 usb_control_msg(gspca_dev->dev,
380 usb_rcvctrlpipe(gspca_dev->dev, 0),
381 0,
382 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
383 0,
384 index, gspca_dev->usb_buf, length, 500);
385}
386
387static int reg_w(struct gspca_dev *gspca_dev,
388 __u16 req, __u16 index, __u16 value)
389{
390 int ret;
391
392 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
393 ret = usb_control_msg(gspca_dev->dev,
394 usb_sndctrlpipe(gspca_dev->dev, 0),
395 req,
396 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
397 value, index, NULL, 0, 500);
398 if (ret < 0)
399 err("reg write: error %d", ret);
400 return ret;
401}
402
403
404static int reg_r_12(struct gspca_dev *gspca_dev,
405 __u16 req,
406 __u16 index,
407 __u16 length)
408{
409 int ret;
410
411 gspca_dev->usb_buf[1] = 0;
412 ret = usb_control_msg(gspca_dev->dev,
413 usb_rcvctrlpipe(gspca_dev->dev, 0),
414 req,
415 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
416 0,
417 index,
418 gspca_dev->usb_buf, length,
419 500);
420 if (ret < 0) {
421 err("reg_r_12 err %d", ret);
422 return ret;
423 }
424 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
425}
426
427
428
429
430
431
432static int reg_r_wait(struct gspca_dev *gspca_dev,
433 __u16 reg, __u16 index, __u16 value)
434{
435 int ret, cnt = 20;
436
437 while (--cnt > 0) {
438 ret = reg_r_12(gspca_dev, reg, index, 1);
439 if (ret == value)
440 return 0;
441 msleep(50);
442 }
443 return -EIO;
444}
445
446static int write_vector(struct gspca_dev *gspca_dev,
447 const __u16 data[][3])
448{
449 int ret, i = 0;
450
451 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
452 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
453 if (ret < 0)
454 return ret;
455 i++;
456 }
457 return 0;
458}
459
460static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
461 unsigned int request,
462 unsigned int ybase,
463 unsigned int cbase,
464 const __u8 qtable[2][64])
465{
466 int i, err;
467
468
469 for (i = 0; i < 64; i++) {
470 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
471 if (err < 0)
472 return err;
473 }
474
475
476 for (i = 0; i < 64; i++) {
477 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
478 if (err < 0)
479 return err;
480 }
481 return 0;
482}
483
484static void spca500_ping310(struct gspca_dev *gspca_dev)
485{
486 reg_r(gspca_dev, 0x0d04, 2);
487 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
488 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
489}
490
491static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
492{
493 reg_r(gspca_dev, 0x0d05, 2);
494 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
495 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
496 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
497 spca500_ping310(gspca_dev);
498
499 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
500 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
501 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
502 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
503 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
504 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
505 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
506 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
507 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
508 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
509
510 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
511 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
512 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
513}
514
515static void spca500_setmode(struct gspca_dev *gspca_dev,
516 __u8 xmult, __u8 ymult)
517{
518 int mode;
519
520
521 reg_w(gspca_dev, 0, 0x8001, xmult);
522
523
524 reg_w(gspca_dev, 0, 0x8002, ymult);
525
526
527 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
528 reg_w(gspca_dev, 0, 0x8003, mode << 4);
529}
530
531static int spca500_full_reset(struct gspca_dev *gspca_dev)
532{
533 int err;
534
535
536 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
537 if (err < 0)
538 return err;
539
540
541 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
542 if (err < 0)
543 return err;
544 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
545 if (err < 0)
546 return err;
547 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
548 if (err < 0) {
549 PDEBUG(D_ERR, "reg_r_wait() failed");
550 return err;
551 }
552
553 return 0;
554}
555
556
557
558
559
560
561
562static int spca500_synch310(struct gspca_dev *gspca_dev)
563{
564 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
565 PDEBUG(D_ERR, "Set packet size: set interface error");
566 goto error;
567 }
568 spca500_ping310(gspca_dev);
569
570 reg_r(gspca_dev, 0x0d00, 1);
571
572
573 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
574
575
576 if (usb_set_interface(gspca_dev->dev,
577 gspca_dev->iface,
578 gspca_dev->alt) < 0) {
579 PDEBUG(D_ERR, "Set packet size: set interface error");
580 goto error;
581 }
582 return 0;
583error:
584 return -EBUSY;
585}
586
587static void spca500_reinit(struct gspca_dev *gspca_dev)
588{
589 int err;
590 __u8 Data;
591
592
593
594 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
595 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
596 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
597
598
599 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
600
601 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
602 qtable_pocketdv);
603 if (err < 0)
604 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
605
606
607 reg_w(gspca_dev, 0x00, 0x8880, 2);
608
609 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
610
611 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
612
613 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
614
615 reg_w(gspca_dev, 0, 0x8003, 0x00);
616
617 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
618 msleep(2000);
619 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
620 reg_r(gspca_dev, 0x816b, 1);
621 Data = gspca_dev->usb_buf[0];
622 reg_w(gspca_dev, 0x00, 0x816b, Data);
623 }
624}
625
626
627static int sd_config(struct gspca_dev *gspca_dev,
628 const struct usb_device_id *id)
629{
630 struct sd *sd = (struct sd *) gspca_dev;
631 struct cam *cam;
632
633 cam = &gspca_dev->cam;
634 sd->subtype = id->driver_info;
635 if (sd->subtype != LogitechClickSmart310) {
636 cam->cam_mode = vga_mode;
637 cam->nmodes = ARRAY_SIZE(vga_mode);
638 } else {
639 cam->cam_mode = sif_mode;
640 cam->nmodes = ARRAY_SIZE(sif_mode);
641 }
642 sd->brightness = BRIGHTNESS_DEF;
643 sd->contrast = CONTRAST_DEF;
644 sd->colors = COLOR_DEF;
645 sd->quality = QUALITY_DEF;
646 return 0;
647}
648
649
650static int sd_init(struct gspca_dev *gspca_dev)
651{
652 struct sd *sd = (struct sd *) gspca_dev;
653
654
655 PDEBUG(D_STREAM, "SPCA500 init");
656 if (sd->subtype == LogitechClickSmart310)
657 spca500_clksmart310_init(gspca_dev);
658
659
660 PDEBUG(D_STREAM, "SPCA500 init done");
661 return 0;
662}
663
664static int sd_start(struct gspca_dev *gspca_dev)
665{
666 struct sd *sd = (struct sd *) gspca_dev;
667 int err;
668 __u8 Data;
669 __u8 xmult, ymult;
670
671
672 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
673 0x22);
674 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
675
676 if (sd->subtype == LogitechClickSmart310) {
677 xmult = 0x16;
678 ymult = 0x12;
679 } else {
680 xmult = 0x28;
681 ymult = 0x1e;
682 }
683
684
685 reg_r(gspca_dev, 0x8a04, 1);
686 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
687 gspca_dev->usb_buf[0]);
688 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
689 gspca_dev->curr_mode, xmult, ymult);
690
691
692 switch (sd->subtype) {
693 case LogitechClickSmart310:
694 spca500_setmode(gspca_dev, xmult, ymult);
695
696
697 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
698 reg_w(gspca_dev, 0x00, 0x8880, 3);
699 err = spca50x_setup_qtable(gspca_dev,
700 0x00, 0x8800, 0x8840,
701 qtable_creative_pccam);
702 if (err < 0)
703 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
704
705 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
706
707
708 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
709 msleep(500);
710 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
711 PDEBUG(D_ERR, "reg_r_wait() failed");
712
713 reg_r(gspca_dev, 0x816b, 1);
714 Data = gspca_dev->usb_buf[0];
715 reg_w(gspca_dev, 0x00, 0x816b, Data);
716
717 spca500_synch310(gspca_dev);
718
719 write_vector(gspca_dev, spca500_visual_defaults);
720 spca500_setmode(gspca_dev, xmult, ymult);
721
722 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
723 if (err < 0)
724 PDEBUG(D_ERR, "failed to enable drop packet");
725 reg_w(gspca_dev, 0x00, 0x8880, 3);
726 err = spca50x_setup_qtable(gspca_dev,
727 0x00, 0x8800, 0x8840,
728 qtable_creative_pccam);
729 if (err < 0)
730 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
731
732
733 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
734
735
736 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
737
738 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
739 PDEBUG(D_ERR, "reg_r_wait() failed");
740
741 reg_r(gspca_dev, 0x816b, 1);
742 Data = gspca_dev->usb_buf[0];
743 reg_w(gspca_dev, 0x00, 0x816b, Data);
744 break;
745 case CreativePCCam300:
746 case IntelPocketPCCamera:
747
748
749
750
751 err = spca500_full_reset(gspca_dev);
752 if (err < 0)
753 PDEBUG(D_ERR, "spca500_full_reset failed");
754
755
756 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
757 if (err < 0)
758 PDEBUG(D_ERR, "failed to enable drop packet");
759 reg_w(gspca_dev, 0x00, 0x8880, 3);
760 err = spca50x_setup_qtable(gspca_dev,
761 0x00, 0x8800, 0x8840,
762 qtable_creative_pccam);
763 if (err < 0)
764 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
765
766 spca500_setmode(gspca_dev, xmult, ymult);
767 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
768
769
770 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
771
772 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
773 PDEBUG(D_ERR, "reg_r_wait() failed");
774
775 reg_r(gspca_dev, 0x816b, 1);
776 Data = gspca_dev->usb_buf[0];
777 reg_w(gspca_dev, 0x00, 0x816b, Data);
778
779
780 break;
781 case KodakEZ200:
782
783
784 err = spca500_full_reset(gspca_dev);
785 if (err < 0)
786 PDEBUG(D_ERR, "spca500_full_reset failed");
787
788 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
789 reg_w(gspca_dev, 0x00, 0x8880, 0);
790 err = spca50x_setup_qtable(gspca_dev,
791 0x00, 0x8800, 0x8840,
792 qtable_kodak_ez200);
793 if (err < 0)
794 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
795 spca500_setmode(gspca_dev, xmult, ymult);
796
797 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
798
799
800 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
801
802 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
803 PDEBUG(D_ERR, "reg_r_wait() failed");
804
805 reg_r(gspca_dev, 0x816b, 1);
806 Data = gspca_dev->usb_buf[0];
807 reg_w(gspca_dev, 0x00, 0x816b, Data);
808
809
810 break;
811
812 case BenqDC1016:
813 case DLinkDSC350:
814 case AiptekPocketDV:
815 case Gsmartmini:
816 case MustekGsmart300:
817 case PalmPixDC85:
818 case Optimedia:
819 case ToptroIndus:
820 case AgfaCl20:
821 spca500_reinit(gspca_dev);
822 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
823
824 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
825
826 err = spca50x_setup_qtable(gspca_dev,
827 0x00, 0x8800, 0x8840, qtable_pocketdv);
828 if (err < 0)
829 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
830 reg_w(gspca_dev, 0x00, 0x8880, 2);
831
832
833 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
834
835 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
836
837 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
838
839 spca500_setmode(gspca_dev, xmult, ymult);
840
841 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
842
843 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
844
845 reg_r(gspca_dev, 0x816b, 1);
846 Data = gspca_dev->usb_buf[0];
847 reg_w(gspca_dev, 0x00, 0x816b, Data);
848 break;
849 case LogitechTraveler:
850 case LogitechClickSmart510:
851 reg_w(gspca_dev, 0x02, 0x00, 0x00);
852
853 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
854
855 err = spca50x_setup_qtable(gspca_dev,
856 0x00, 0x8800,
857 0x8840, qtable_creative_pccam);
858 if (err < 0)
859 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
860 reg_w(gspca_dev, 0x00, 0x8880, 3);
861 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
862
863 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
864
865 spca500_setmode(gspca_dev, xmult, ymult);
866
867
868 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
869 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
870
871 reg_r(gspca_dev, 0x816b, 1);
872 Data = gspca_dev->usb_buf[0];
873 reg_w(gspca_dev, 0x00, 0x816b, Data);
874 write_vector(gspca_dev, Clicksmart510_defaults);
875 break;
876 }
877 return 0;
878}
879
880static void sd_stopN(struct gspca_dev *gspca_dev)
881{
882 reg_w(gspca_dev, 0, 0x8003, 0x00);
883
884
885 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
886 reg_r(gspca_dev, 0x8000, 1);
887 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
888 gspca_dev->usb_buf[0]);
889}
890
891static void sd_pkt_scan(struct gspca_dev *gspca_dev,
892 u8 *data,
893 int len)
894{
895 struct sd *sd = (struct sd *) gspca_dev;
896 int i;
897 static __u8 ffd9[] = {0xff, 0xd9};
898
899
900 if (data[0] == 0xff) {
901 if (data[1] != 0x01) {
902
903 return;
904 }
905 gspca_frame_add(gspca_dev, LAST_PACKET,
906 ffd9, 2);
907
908
909 gspca_frame_add(gspca_dev, FIRST_PACKET,
910 sd->jpeg_hdr, JPEG_HDR_SZ);
911
912 data += SPCA500_OFFSET_DATA;
913 len -= SPCA500_OFFSET_DATA;
914 } else {
915 data += 1;
916 len -= 1;
917 }
918
919
920 i = 0;
921 do {
922 if (data[i] == 0xff) {
923 gspca_frame_add(gspca_dev, INTER_PACKET,
924 data, i + 1);
925 len -= i;
926 data += i;
927 *data = 0x00;
928 i = 0;
929 }
930 i++;
931 } while (i < len);
932 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
933}
934
935static void setbrightness(struct gspca_dev *gspca_dev)
936{
937 struct sd *sd = (struct sd *) gspca_dev;
938
939 reg_w(gspca_dev, 0x00, 0x8167,
940 (__u8) (sd->brightness - 128));
941}
942
943static void setcontrast(struct gspca_dev *gspca_dev)
944{
945 struct sd *sd = (struct sd *) gspca_dev;
946
947 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
948}
949
950static void setcolors(struct gspca_dev *gspca_dev)
951{
952 struct sd *sd = (struct sd *) gspca_dev;
953
954 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
955}
956
957static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
958{
959 struct sd *sd = (struct sd *) gspca_dev;
960
961 sd->brightness = val;
962 if (gspca_dev->streaming)
963 setbrightness(gspca_dev);
964 return 0;
965}
966
967static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
968{
969 struct sd *sd = (struct sd *) gspca_dev;
970
971 *val = sd->brightness;
972 return 0;
973}
974
975static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
976{
977 struct sd *sd = (struct sd *) gspca_dev;
978
979 sd->contrast = val;
980 if (gspca_dev->streaming)
981 setcontrast(gspca_dev);
982 return 0;
983}
984
985static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
986{
987 struct sd *sd = (struct sd *) gspca_dev;
988
989 *val = sd->contrast;
990 return 0;
991}
992
993static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
994{
995 struct sd *sd = (struct sd *) gspca_dev;
996
997 sd->colors = val;
998 if (gspca_dev->streaming)
999 setcolors(gspca_dev);
1000 return 0;
1001}
1002
1003static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1004{
1005 struct sd *sd = (struct sd *) gspca_dev;
1006
1007 *val = sd->colors;
1008 return 0;
1009}
1010
1011static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1012 struct v4l2_jpegcompression *jcomp)
1013{
1014 struct sd *sd = (struct sd *) gspca_dev;
1015
1016 if (jcomp->quality < QUALITY_MIN)
1017 sd->quality = QUALITY_MIN;
1018 else if (jcomp->quality > QUALITY_MAX)
1019 sd->quality = QUALITY_MAX;
1020 else
1021 sd->quality = jcomp->quality;
1022 if (gspca_dev->streaming)
1023 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1024 return 0;
1025}
1026
1027static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1028 struct v4l2_jpegcompression *jcomp)
1029{
1030 struct sd *sd = (struct sd *) gspca_dev;
1031
1032 memset(jcomp, 0, sizeof *jcomp);
1033 jcomp->quality = sd->quality;
1034 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1035 | V4L2_JPEG_MARKER_DQT;
1036 return 0;
1037}
1038
1039
1040static const struct sd_desc sd_desc = {
1041 .name = MODULE_NAME,
1042 .ctrls = sd_ctrls,
1043 .nctrls = ARRAY_SIZE(sd_ctrls),
1044 .config = sd_config,
1045 .init = sd_init,
1046 .start = sd_start,
1047 .stopN = sd_stopN,
1048 .pkt_scan = sd_pkt_scan,
1049 .get_jcomp = sd_get_jcomp,
1050 .set_jcomp = sd_set_jcomp,
1051};
1052
1053
1054static const struct usb_device_id device_table[] = {
1055 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
1056 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
1057 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
1058 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
1059 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
1060 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
1061 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
1062 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
1063 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
1064 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
1065 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
1066 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
1067 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
1068 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
1069 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
1070 {}
1071};
1072MODULE_DEVICE_TABLE(usb, device_table);
1073
1074
1075static int sd_probe(struct usb_interface *intf,
1076 const struct usb_device_id *id)
1077{
1078 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1079 THIS_MODULE);
1080}
1081
1082static struct usb_driver sd_driver = {
1083 .name = MODULE_NAME,
1084 .id_table = device_table,
1085 .probe = sd_probe,
1086 .disconnect = gspca_disconnect,
1087#ifdef CONFIG_PM
1088 .suspend = gspca_suspend,
1089 .resume = gspca_resume,
1090#endif
1091};
1092
1093
1094static int __init sd_mod_init(void)
1095{
1096 return usb_register(&sd_driver);
1097}
1098static void __exit sd_mod_exit(void)
1099{
1100 usb_deregister(&sd_driver);
1101}
1102
1103module_init(sd_mod_init);
1104module_exit(sd_mod_exit);
1105