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