]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/media/video/gspca/sunplus.c
V4L/DVB (8352): gspca: Buffers for USB exchanges cannot be in the stack.
[mirror_ubuntu-artful-kernel.git] / drivers / media / video / gspca / sunplus.c
CommitLineData
6a7eba24
JFM
1/*
2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
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
10 * any later version.
11 *
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.
16 *
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
20 */
21
22#define MODULE_NAME "sunplus"
23
24#include "gspca.h"
25#include "jpeg.h"
26
739570bb
JFM
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
6a7eba24
JFM
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
a5ae2062 38 __u8 packet[ISO_MAX_SIZE + 128];
6a7eba24
JFM
39 /* !! no more than 128 ff in an ISO packet */
40
41 unsigned char brightness;
42 unsigned char contrast;
43 unsigned char colors;
44 unsigned char autogain;
45
46 char qindex;
47 char bridge;
48#define BRIDGE_SPCA504 0
49#define BRIDGE_SPCA504B 1
50#define BRIDGE_SPCA504C 2
51#define BRIDGE_SPCA533 3
52#define BRIDGE_SPCA536 4
53 char subtype;
54#define AiptekMiniPenCam13 1
55#define LogitechClickSmart420 2
56#define LogitechClickSmart820 3
57#define MegapixV4 4
58};
59
60/* V4L2 controls supported by the driver */
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#define SD_BRIGHTNESS 0
72 {
73 {
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Brightness",
77 .minimum = 0,
78 .maximum = 0xff,
79 .step = 1,
80 .default_value = 0,
81 },
82 .set = sd_setbrightness,
83 .get = sd_getbrightness,
84 },
85#define SD_CONTRAST 1
86 {
87 {
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Contrast",
91 .minimum = 0,
92 .maximum = 0xff,
93 .step = 1,
94 .default_value = 0x20,
95 },
96 .set = sd_setcontrast,
97 .get = sd_getcontrast,
98 },
99#define SD_COLOR 2
100 {
101 {
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Color",
105 .minimum = 0,
106 .maximum = 0xff,
107 .step = 1,
108 .default_value = 0x1a,
109 },
110 .set = sd_setcolors,
111 .get = sd_getcolors,
112 },
113#define SD_AUTOGAIN 3
114 {
115 {
116 .id = V4L2_CID_AUTOGAIN,
117 .type = V4L2_CTRL_TYPE_BOOLEAN,
118 .name = "Auto Gain",
119 .minimum = 0,
120 .maximum = 1,
121 .step = 1,
122 .default_value = 1,
123 },
124 .set = sd_setautogain,
125 .get = sd_getautogain,
126 },
127};
128
c2446b3e
JFM
129static 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},
6a7eba24
JFM
140};
141
c2446b3e
JFM
142static 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},
6a7eba24
JFM
153};
154
c2446b3e
JFM
155static 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},
6a7eba24
JFM
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 /* 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
189
190/* Initialisation data for the Creative PC-CAM 600 */
a5ae2062 191static const __u16 spca504_pccam600_init_data[][3] = {
6a7eba24
JFM
192/* {0xa0, 0x0000, 0x0503}, * capture mode */
193 {0x00, 0x0000, 0x2000},
194 {0x00, 0x0013, 0x2301},
195 {0x00, 0x0003, 0x2000},
196 {0x00, 0x0001, 0x21ac},
197 {0x00, 0x0001, 0x21a6},
198 {0x00, 0x0000, 0x21a7}, /* brightness */
199 {0x00, 0x0020, 0x21a8}, /* contrast */
200 {0x00, 0x0001, 0x21ac}, /* sat/hue */
201 {0x00, 0x0000, 0x21ad}, /* hue */
202 {0x00, 0x001a, 0x21ae}, /* saturation */
203 {0x00, 0x0002, 0x21a3}, /* gamma */
204 {0x30, 0x0154, 0x0008},
205 {0x30, 0x0004, 0x0006},
206 {0x30, 0x0258, 0x0009},
207 {0x30, 0x0004, 0x0000},
208 {0x30, 0x0093, 0x0004},
209 {0x30, 0x0066, 0x0005},
210 {0x00, 0x0000, 0x2000},
211 {0x00, 0x0013, 0x2301},
212 {0x00, 0x0003, 0x2000},
213 {0x00, 0x0013, 0x2301},
214 {0x00, 0x0003, 0x2000},
215 {}
216};
217
218/* Creative PC-CAM 600 specific open data, sent before using the
219 * generic initialisation data from spca504_open_data.
220 */
a5ae2062 221static const __u16 spca504_pccam600_open_data[][3] = {
6a7eba24
JFM
222 {0x00, 0x0001, 0x2501},
223 {0x20, 0x0500, 0x0001}, /* snapshot mode */
224 {0x00, 0x0003, 0x2880},
225 {0x00, 0x0001, 0x2881},
226 {}
227};
228
229/* Initialisation data for the logitech clicksmart 420 */
a5ae2062 230static const __u16 spca504A_clicksmart420_init_data[][3] = {
6a7eba24
JFM
231/* {0xa0, 0x0000, 0x0503}, * capture mode */
232 {0x00, 0x0000, 0x2000},
233 {0x00, 0x0013, 0x2301},
234 {0x00, 0x0003, 0x2000},
235 {0x00, 0x0001, 0x21ac},
236 {0x00, 0x0001, 0x21a6},
237 {0x00, 0x0000, 0x21a7}, /* brightness */
238 {0x00, 0x0020, 0x21a8}, /* contrast */
239 {0x00, 0x0001, 0x21ac}, /* sat/hue */
240 {0x00, 0x0000, 0x21ad}, /* hue */
241 {0x00, 0x001a, 0x21ae}, /* saturation */
242 {0x00, 0x0002, 0x21a3}, /* gamma */
243 {0x30, 0x0004, 0x000a},
244 {0xb0, 0x0001, 0x0000},
245
246
247 {0x0a1, 0x0080, 0x0001},
248 {0x30, 0x0049, 0x0000},
249 {0x30, 0x0060, 0x0005},
250 {0x0c, 0x0004, 0x0000},
251 {0x00, 0x0000, 0x0000},
252 {0x00, 0x0000, 0x2000},
253 {0x00, 0x0013, 0x2301},
254 {0x00, 0x0003, 0x2000},
255 {0x00, 0x0000, 0x2000},
256
257 {}
258};
259
260/* clicksmart 420 open data ? */
a5ae2062 261static const __u16 spca504A_clicksmart420_open_data[][3] = {
6a7eba24
JFM
262 {0x00, 0x0001, 0x2501},
263 {0x20, 0x0502, 0x0000},
264 {0x06, 0x0000, 0x0000},
265 {0x00, 0x0004, 0x2880},
266 {0x00, 0x0001, 0x2881},
267/* look like setting a qTable */
268 {0x00, 0x0006, 0x2800},
269 {0x00, 0x0004, 0x2801},
270 {0x00, 0x0004, 0x2802},
271 {0x00, 0x0006, 0x2803},
272 {0x00, 0x000a, 0x2804},
273 {0x00, 0x0010, 0x2805},
274 {0x00, 0x0014, 0x2806},
275 {0x00, 0x0018, 0x2807},
276 {0x00, 0x0005, 0x2808},
277 {0x00, 0x0005, 0x2809},
278 {0x00, 0x0006, 0x280a},
279 {0x00, 0x0008, 0x280b},
280 {0x00, 0x000a, 0x280c},
281 {0x00, 0x0017, 0x280d},
282 {0x00, 0x0018, 0x280e},
283 {0x00, 0x0016, 0x280f},
284
285 {0x00, 0x0006, 0x2810},
286 {0x00, 0x0005, 0x2811},
287 {0x00, 0x0006, 0x2812},
288 {0x00, 0x000a, 0x2813},
289 {0x00, 0x0010, 0x2814},
290 {0x00, 0x0017, 0x2815},
291 {0x00, 0x001c, 0x2816},
292 {0x00, 0x0016, 0x2817},
293 {0x00, 0x0006, 0x2818},
294 {0x00, 0x0007, 0x2819},
295 {0x00, 0x0009, 0x281a},
296 {0x00, 0x000c, 0x281b},
297 {0x00, 0x0014, 0x281c},
298 {0x00, 0x0023, 0x281d},
299 {0x00, 0x0020, 0x281e},
300 {0x00, 0x0019, 0x281f},
301
302 {0x00, 0x0007, 0x2820},
303 {0x00, 0x0009, 0x2821},
304 {0x00, 0x000f, 0x2822},
305 {0x00, 0x0016, 0x2823},
306 {0x00, 0x001b, 0x2824},
307 {0x00, 0x002c, 0x2825},
308 {0x00, 0x0029, 0x2826},
309 {0x00, 0x001f, 0x2827},
310 {0x00, 0x000a, 0x2828},
311 {0x00, 0x000e, 0x2829},
312 {0x00, 0x0016, 0x282a},
313 {0x00, 0x001a, 0x282b},
314 {0x00, 0x0020, 0x282c},
315 {0x00, 0x002a, 0x282d},
316 {0x00, 0x002d, 0x282e},
317 {0x00, 0x0025, 0x282f},
318
319 {0x00, 0x0014, 0x2830},
320 {0x00, 0x001a, 0x2831},
321 {0x00, 0x001f, 0x2832},
322 {0x00, 0x0023, 0x2833},
323 {0x00, 0x0029, 0x2834},
324 {0x00, 0x0030, 0x2835},
325 {0x00, 0x0030, 0x2836},
326 {0x00, 0x0028, 0x2837},
327 {0x00, 0x001d, 0x2838},
328 {0x00, 0x0025, 0x2839},
329 {0x00, 0x0026, 0x283a},
330 {0x00, 0x0027, 0x283b},
331 {0x00, 0x002d, 0x283c},
332 {0x00, 0x0028, 0x283d},
333 {0x00, 0x0029, 0x283e},
334 {0x00, 0x0028, 0x283f},
335
336 {0x00, 0x0007, 0x2840},
337 {0x00, 0x0007, 0x2841},
338 {0x00, 0x000a, 0x2842},
339 {0x00, 0x0013, 0x2843},
340 {0x00, 0x0028, 0x2844},
341 {0x00, 0x0028, 0x2845},
342 {0x00, 0x0028, 0x2846},
343 {0x00, 0x0028, 0x2847},
344 {0x00, 0x0007, 0x2848},
345 {0x00, 0x0008, 0x2849},
346 {0x00, 0x000a, 0x284a},
347 {0x00, 0x001a, 0x284b},
348 {0x00, 0x0028, 0x284c},
349 {0x00, 0x0028, 0x284d},
350 {0x00, 0x0028, 0x284e},
351 {0x00, 0x0028, 0x284f},
352
353 {0x00, 0x000a, 0x2850},
354 {0x00, 0x000a, 0x2851},
355 {0x00, 0x0016, 0x2852},
356 {0x00, 0x0028, 0x2853},
357 {0x00, 0x0028, 0x2854},
358 {0x00, 0x0028, 0x2855},
359 {0x00, 0x0028, 0x2856},
360 {0x00, 0x0028, 0x2857},
361 {0x00, 0x0013, 0x2858},
362 {0x00, 0x001a, 0x2859},
363 {0x00, 0x0028, 0x285a},
364 {0x00, 0x0028, 0x285b},
365 {0x00, 0x0028, 0x285c},
366 {0x00, 0x0028, 0x285d},
367 {0x00, 0x0028, 0x285e},
368 {0x00, 0x0028, 0x285f},
369
370 {0x00, 0x0028, 0x2860},
371 {0x00, 0x0028, 0x2861},
372 {0x00, 0x0028, 0x2862},
373 {0x00, 0x0028, 0x2863},
374 {0x00, 0x0028, 0x2864},
375 {0x00, 0x0028, 0x2865},
376 {0x00, 0x0028, 0x2866},
377 {0x00, 0x0028, 0x2867},
378 {0x00, 0x0028, 0x2868},
379 {0x00, 0x0028, 0x2869},
380 {0x00, 0x0028, 0x286a},
381 {0x00, 0x0028, 0x286b},
382 {0x00, 0x0028, 0x286c},
383 {0x00, 0x0028, 0x286d},
384 {0x00, 0x0028, 0x286e},
385 {0x00, 0x0028, 0x286f},
386
387 {0x00, 0x0028, 0x2870},
388 {0x00, 0x0028, 0x2871},
389 {0x00, 0x0028, 0x2872},
390 {0x00, 0x0028, 0x2873},
391 {0x00, 0x0028, 0x2874},
392 {0x00, 0x0028, 0x2875},
393 {0x00, 0x0028, 0x2876},
394 {0x00, 0x0028, 0x2877},
395 {0x00, 0x0028, 0x2878},
396 {0x00, 0x0028, 0x2879},
397 {0x00, 0x0028, 0x287a},
398 {0x00, 0x0028, 0x287b},
399 {0x00, 0x0028, 0x287c},
400 {0x00, 0x0028, 0x287d},
401 {0x00, 0x0028, 0x287e},
402 {0x00, 0x0028, 0x287f},
403
404 {0xa0, 0x0000, 0x0503},
405 {}
406};
407
a5ae2062 408static const __u8 qtable_creative_pccam[2][64] = {
6a7eba24
JFM
409 { /* Q-table Y-components */
410 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
411 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
412 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
413 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
414 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
415 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
416 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
417 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
418 { /* Q-table C-components */
419 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
420 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
421 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
424 0x1e, 0x1e, 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};
428
429/* FIXME: This Q-table is identical to the Creative PC-CAM one,
430 * except for one byte. Possibly a typo?
431 * NWG: 18/05/2003.
432 */
a5ae2062 433static const __u8 qtable_spca504_default[2][64] = {
6a7eba24
JFM
434 { /* Q-table Y-components */
435 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
436 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
437 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
438 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
439 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
440 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
441 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
442 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
443 },
444 { /* Q-table C-components */
445 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
446 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
447 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
450 0x1e, 0x1e, 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};
454
739570bb 455static void reg_r(struct usb_device *dev,
6a7eba24
JFM
456 __u16 req,
457 __u16 index,
458 __u8 *buffer, __u16 length)
459{
460 usb_control_msg(dev,
461 usb_rcvctrlpipe(dev, 0),
462 req,
463 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
464 0, /* value */
465 index, buffer, length,
466 500);
467}
468
739570bb 469static void reg_w(struct usb_device *dev,
6a7eba24
JFM
470 __u16 req,
471 __u16 value,
472 __u16 index,
473 __u8 *buffer, __u16 length)
474{
475 usb_control_msg(dev,
476 usb_sndctrlpipe(dev, 0),
477 req,
478 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
479 value, index, buffer, length,
480 500);
481}
482
739570bb
JFM
483/* write req / index / value */
484static int reg_w_riv(struct usb_device *dev,
6a7eba24
JFM
485 __u16 req, __u16 index, __u16 value)
486{
487 int ret;
488
489 ret = usb_control_msg(dev,
490 usb_sndctrlpipe(dev, 0),
491 req,
bf7f0b98 492 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
6a7eba24 493 value, index, NULL, 0, 500);
739570bb 494 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
956e42d2 495 req, index, value, ret);
6a7eba24
JFM
496 if (ret < 0)
497 PDEBUG(D_ERR, "reg write: error %d", ret);
498 return ret;
499}
500
739570bb
JFM
501/* read 1 byte */
502static int reg_r_1(struct gspca_dev *gspca_dev,
6a7eba24
JFM
503 __u16 value) /* wValue */
504{
505 int ret;
6a7eba24 506
739570bb
JFM
507 ret = usb_control_msg(gspca_dev->dev,
508 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
509 0x20, /* request */
510 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
511 value,
512 0, /* index */
739570bb 513 gspca_dev->usb_buf, 1,
6a7eba24
JFM
514 500); /* timeout */
515 if (ret < 0) {
739570bb 516 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
6a7eba24
JFM
517 return 0;
518 }
739570bb 519 return gspca_dev->usb_buf[0];
6a7eba24
JFM
520}
521
739570bb
JFM
522/* read 1 or 2 bytes - returns < 0 if error */
523static int reg_r_12(struct gspca_dev *gspca_dev,
6a7eba24
JFM
524 __u16 req, /* bRequest */
525 __u16 index, /* wIndex */
526 __u16 length) /* wLength (1 or 2 only) */
527{
528 int ret;
6a7eba24 529
739570bb
JFM
530 gspca_dev->usb_buf[1] = 0;
531 ret = usb_control_msg(gspca_dev->dev,
532 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
533 req,
534 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
535 0, /* value */
536 index,
739570bb 537 gspca_dev->usb_buf, length,
6a7eba24
JFM
538 500);
539 if (ret < 0) {
540 PDEBUG(D_ERR, "reg_read err %d", ret);
541 return -1;
542 }
739570bb 543 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
6a7eba24
JFM
544}
545
546static int write_vector(struct gspca_dev *gspca_dev,
a5ae2062 547 const __u16 data[][3])
6a7eba24
JFM
548{
549 struct usb_device *dev = gspca_dev->dev;
550 int ret, i = 0;
551
552 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
739570bb 553 ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
6a7eba24
JFM
554 if (ret < 0) {
555 PDEBUG(D_ERR,
556 "Register write failed for 0x%x,0x%x,0x%x",
557 data[i][0], data[i][1], data[i][2]);
558 return ret;
559 }
560 i++;
561 }
562 return 0;
563}
564
565static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
566 unsigned int request,
567 unsigned int ybase,
568 unsigned int cbase,
a5ae2062 569 const __u8 qtable[2][64])
6a7eba24
JFM
570{
571 struct usb_device *dev = gspca_dev->dev;
572 int i, err;
573
574 /* loop over y components */
575 for (i = 0; i < 64; i++) {
739570bb 576 err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
6a7eba24
JFM
577 if (err < 0)
578 return err;
579 }
580
581 /* loop over c components */
582 for (i = 0; i < 64; i++) {
739570bb 583 err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
6a7eba24
JFM
584 if (err < 0)
585 return err;
586 }
587 return 0;
588}
589
590static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
591 __u16 req, __u16 idx, __u16 val)
592{
593 struct usb_device *dev = gspca_dev->dev;
594 __u8 notdone;
595
739570bb
JFM
596 reg_w_riv(dev, req, idx, val);
597 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
598 reg_w_riv(dev, req, idx, val);
6a7eba24
JFM
599
600 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
601
602 msleep(200);
739570bb 603 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
6a7eba24
JFM
604 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
605}
606
607static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
608 __u16 req,
609 __u16 idx, __u16 val, __u8 stat, __u8 count)
610{
611 struct usb_device *dev = gspca_dev->dev;
612 __u8 status;
613 __u8 endcode;
614
739570bb
JFM
615 reg_w_riv(dev, req, idx, val);
616 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
6a7eba24
JFM
617 endcode = stat;
618 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
619 if (!count)
620 return;
621 count = 200;
622 while (--count > 0) {
623 msleep(10);
624 /* gsmart mini2 write a each wait setting 1 ms is enought */
739570bb
JFM
625/* reg_w_riv(dev, req, idx, val); */
626 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
6a7eba24
JFM
627 if (status == endcode) {
628 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
629 status, 200 - count);
630 break;
631 }
632 }
633}
634
739570bb 635static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
6a7eba24 636{
6a7eba24
JFM
637 int count = 10;
638
639 while (--count > 0) {
739570bb
JFM
640 reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1);
641 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
6a7eba24
JFM
642 break;
643 msleep(10);
644 }
739570bb 645 return gspca_dev->usb_buf[0];
6a7eba24
JFM
646}
647
648static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
649{
650 struct usb_device *dev = gspca_dev->dev;
6a7eba24
JFM
651 int count = 50;
652
653 while (--count > 0) {
739570bb
JFM
654 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
655 if (gspca_dev->usb_buf[0] != 0) {
656 gspca_dev->usb_buf[0] = 0;
657 reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1);
658 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
659 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
660 break;
661 }
662 msleep(10);
663 }
664}
665
666static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
667{
668 struct usb_device *dev = gspca_dev->dev;
739570bb 669 __u8 *data;
6a7eba24 670
739570bb
JFM
671 data = kmalloc(64, GFP_KERNEL);
672 reg_r(dev, 0x20, 0, data, 5);
6a7eba24 673 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
739570bb
JFM
674 data[0], data[1], data[2], data[3], data[4]);
675 reg_r(dev, 0x23, 0, data, 64);
676 reg_r(dev, 0x23, 1, data, 64);
677 kfree(data);
6a7eba24
JFM
678}
679
680static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
683 struct usb_device *dev = gspca_dev->dev;
684 __u8 Size;
685 __u8 Type;
686 int rc;
687
c2446b3e 688 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
6a7eba24
JFM
689 Type = 0;
690 switch (sd->bridge) {
691 case BRIDGE_SPCA533:
739570bb 692 reg_w(dev, 0x31, 0, 0, NULL, 0);
6a7eba24 693 spca504B_WaitCmdStatus(gspca_dev);
739570bb 694 rc = spca504B_PollingDataReady(gspca_dev);
6a7eba24 695 spca50x_GetFirmware(gspca_dev);
739570bb
JFM
696 gspca_dev->usb_buf[0] = 2; /* type */
697 reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1);
698 reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1);
6a7eba24 699
739570bb
JFM
700 gspca_dev->usb_buf[0] = Size;
701 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
702 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
703 rc = spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
704
705 /* Init the cam width height with some values get on init ? */
739570bb 706 reg_w(dev, 0x31, 0, 4, NULL, 0);
6a7eba24 707 spca504B_WaitCmdStatus(gspca_dev);
739570bb 708 rc = spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
709 break;
710 default:
711/* case BRIDGE_SPCA504B: */
712/* case BRIDGE_SPCA536: */
739570bb
JFM
713 gspca_dev->usb_buf[0] = Size;
714 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
715 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
6a7eba24 716 Type = 6;
739570bb
JFM
717 gspca_dev->usb_buf[0] = Type;
718 reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1);
719 reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1); /* type */
720 rc = spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
721 break;
722 case BRIDGE_SPCA504:
723 Size += 3;
724 if (sd->subtype == AiptekMiniPenCam13) {
725 /* spca504a aiptek */
726 spca504A_acknowledged_command(gspca_dev,
727 0x08, Size, 0,
728 0x80 | (Size & 0x0f), 1);
729 spca504A_acknowledged_command(gspca_dev,
730 1, 3, 0, 0x9f, 0);
731 } else {
732 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
733 }
734 break;
735 case BRIDGE_SPCA504C:
736 /* capture mode */
739570bb
JFM
737 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
738 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
6a7eba24
JFM
739 break;
740 }
741}
742
743static void spca504_wait_status(struct gspca_dev *gspca_dev)
744{
6a7eba24
JFM
745 int cnt;
746
747 cnt = 256;
748 while (--cnt > 0) {
749 /* With this we get the status, when return 0 it's all ok */
739570bb 750 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
6a7eba24
JFM
751 return;
752 msleep(10);
753 }
754}
755
756static void spca504B_setQtable(struct gspca_dev *gspca_dev)
757{
758 struct usb_device *dev = gspca_dev->dev;
6a7eba24 759
739570bb
JFM
760 gspca_dev->usb_buf[0] = 3;
761 reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1);
762 reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1);
763 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
764}
765
766static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
767{
768 struct sd *sd = (struct sd *) gspca_dev;
769 struct usb_device *dev = gspca_dev->dev;
770 int pollreg = 1;
771
772 switch (sd->bridge) {
773 case BRIDGE_SPCA504:
774 case BRIDGE_SPCA504C:
775 pollreg = 0;
776 /* fall thru */
777 default:
778/* case BRIDGE_SPCA533: */
779/* case BRIDGE_SPCA504B: */
739570bb
JFM
780 reg_w(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
781 reg_w(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
782 reg_w(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
783 reg_w(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
784 reg_w(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
785 reg_w(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
6a7eba24
JFM
786 break;
787 case BRIDGE_SPCA536:
739570bb
JFM
788 reg_w(dev, 0, 0, 0x20f0, NULL, 0);
789 reg_w(dev, 0, 0x21, 0x20f1, NULL, 0);
790 reg_w(dev, 0, 0x40, 0x20f5, NULL, 0);
791 reg_w(dev, 0, 1, 0x20f4, NULL, 0);
792 reg_w(dev, 0, 0x40, 0x20f6, NULL, 0);
793 reg_w(dev, 0, 0, 0x2089, NULL, 0);
6a7eba24
JFM
794 break;
795 }
796 if (pollreg)
739570bb 797 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
798}
799
800/* this function is called at probe time */
801static int sd_config(struct gspca_dev *gspca_dev,
802 const struct usb_device_id *id)
803{
804 struct sd *sd = (struct sd *) gspca_dev;
805 struct usb_device *dev = gspca_dev->dev;
806 struct cam *cam;
807 __u16 vendor;
808 __u16 product;
809 __u8 fw;
810
811 vendor = id->idVendor;
812 product = id->idProduct;
813 switch (vendor) {
814 case 0x041e: /* Creative cameras */
815/* switch (product) { */
816/* case 0x400b: */
817/* case 0x4012: */
818/* case 0x4013: */
819/* sd->bridge = BRIDGE_SPCA504C; */
820/* break; */
821/* } */
822 break;
823 case 0x0458: /* Genius KYE cameras */
824/* switch (product) { */
825/* case 0x7006: */
826 sd->bridge = BRIDGE_SPCA504B;
827/* break; */
828/* } */
829 break;
830 case 0x046d: /* Logitech Labtec */
831 switch (product) {
832 case 0x0905:
833 sd->subtype = LogitechClickSmart820;
834 sd->bridge = BRIDGE_SPCA533;
835 break;
836 case 0x0960:
837 sd->subtype = LogitechClickSmart420;
838 sd->bridge = BRIDGE_SPCA504C;
839 break;
840 }
841 break;
842 case 0x0471: /* Philips */
843/* switch (product) { */
844/* case 0x0322: */
845 sd->bridge = BRIDGE_SPCA504B;
846/* break; */
847/* } */
848 break;
849 case 0x04a5: /* Benq */
850 switch (product) {
851 case 0x3003:
852 sd->bridge = BRIDGE_SPCA504B;
853 break;
854 case 0x3008:
855 case 0x300a:
856 sd->bridge = BRIDGE_SPCA533;
857 break;
858 }
859 break;
860 case 0x04f1: /* JVC */
861/* switch (product) { */
862/* case 0x1001: */
863 sd->bridge = BRIDGE_SPCA504B;
864/* break; */
865/* } */
866 break;
867 case 0x04fc: /* SunPlus */
868 switch (product) {
869 case 0x500c:
870 sd->bridge = BRIDGE_SPCA504B;
871 break;
872 case 0x504a:
873/* try to get the firmware as some cam answer 2.0.1.2.2
874 * and should be a spca504b then overwrite that setting */
739570bb
JFM
875 reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
876 fw = gspca_dev->usb_buf[0];
6a7eba24
JFM
877 if (fw == 1) {
878 sd->subtype = AiptekMiniPenCam13;
879 sd->bridge = BRIDGE_SPCA504;
880 } else if (fw == 2) {
881 sd->bridge = BRIDGE_SPCA504B;
882 } else
883 return -ENODEV;
884 break;
885 case 0x504b:
886 sd->bridge = BRIDGE_SPCA504B;
887 break;
888 case 0x5330:
889 sd->bridge = BRIDGE_SPCA533;
890 break;
891 case 0x5360:
892 sd->bridge = BRIDGE_SPCA536;
893 break;
894 case 0xffff:
895 sd->bridge = BRIDGE_SPCA504B;
896 break;
897 }
898 break;
899 case 0x052b: /* ?? Megapix */
900/* switch (product) { */
901/* case 0x1513: */
902 sd->subtype = MegapixV4;
903 sd->bridge = BRIDGE_SPCA533;
904/* break; */
905/* } */
906 break;
907 case 0x0546: /* Polaroid */
908 switch (product) {
909 case 0x3155:
910 sd->bridge = BRIDGE_SPCA533;
911 break;
912 case 0x3191:
913 case 0x3273:
914 sd->bridge = BRIDGE_SPCA504B;
915 break;
916 }
917 break;
918 case 0x055f: /* Mustek cameras */
919 switch (product) {
920 case 0xc211:
921 sd->bridge = BRIDGE_SPCA536;
922 break;
923 case 0xc230:
924 case 0xc232:
925 sd->bridge = BRIDGE_SPCA533;
926 break;
927 case 0xc360:
928 sd->bridge = BRIDGE_SPCA536;
929 break;
930 case 0xc420:
931 sd->bridge = BRIDGE_SPCA504;
932 break;
933 case 0xc430:
934 case 0xc440:
935 sd->bridge = BRIDGE_SPCA533;
936 break;
937 case 0xc520:
938 sd->bridge = BRIDGE_SPCA504;
939 break;
940 case 0xc530:
941 case 0xc540:
942 case 0xc630:
943 case 0xc650:
944 sd->bridge = BRIDGE_SPCA533;
945 break;
946 }
947 break;
948 case 0x05da: /* Digital Dream cameras */
949/* switch (product) { */
950/* case 0x1018: */
951 sd->bridge = BRIDGE_SPCA504B;
952/* break; */
953/* } */
954 break;
955 case 0x06d6: /* Trust */
956/* switch (product) { */
957/* case 0x0031: */
958 sd->bridge = BRIDGE_SPCA533; /* SPCA533A */
959/* break; */
960/* } */
961 break;
962 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
963 switch (product) {
964 case 0x1311:
965 case 0x1314:
966 case 0x2211:
967 case 0x2221:
968 sd->bridge = BRIDGE_SPCA533;
969 break;
970 case 0x3261:
971 case 0x3281:
972 sd->bridge = BRIDGE_SPCA536;
973 break;
974 }
975 break;
976 case 0x08ca: /* Aiptek */
977 switch (product) {
978 case 0x0104:
979 case 0x0106:
980 sd->bridge = BRIDGE_SPCA533;
981 break;
982 case 0x2008:
983 sd->bridge = BRIDGE_SPCA504B;
984 break;
985 case 0x2010:
986 sd->bridge = BRIDGE_SPCA533;
987 break;
988 case 0x2016:
989 case 0x2018:
990 sd->bridge = BRIDGE_SPCA504B;
991 break;
992 case 0x2020:
993 case 0x2022:
994 sd->bridge = BRIDGE_SPCA533;
995 break;
996 case 0x2024:
997 sd->bridge = BRIDGE_SPCA536;
998 break;
999 case 0x2028:
1000 sd->bridge = BRIDGE_SPCA533;
1001 break;
1002 case 0x2040:
1003 case 0x2042:
1004 case 0x2060:
1005 sd->bridge = BRIDGE_SPCA536;
1006 break;
1007 }
1008 break;
1009 case 0x0d64: /* SunPlus */
1010/* switch (product) { */
1011/* case 0x0303: */
1012 sd->bridge = BRIDGE_SPCA536;
1013/* break; */
1014/* } */
1015 break;
1016 }
1017
1018 cam = &gspca_dev->cam;
1019 cam->dev_name = (char *) id->driver_info;
1020 cam->epaddr = 0x01;
1021
1022 switch (sd->bridge) {
1023 default:
1024/* case BRIDGE_SPCA504B: */
1025/* case BRIDGE_SPCA504: */
1026/* case BRIDGE_SPCA536: */
1027 cam->cam_mode = vga_mode;
1028 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1029 break;
1030 case BRIDGE_SPCA533:
1031 cam->cam_mode = custom_mode;
1032 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
1033 break;
1034 case BRIDGE_SPCA504C:
1035 cam->cam_mode = vga_mode2;
1036 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
1037 break;
1038 }
1039 sd->qindex = 5; /* set the quantization table */
1040 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1041 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1042 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1043 return 0;
1044}
1045
1046/* this function is called at open time */
1047static int sd_open(struct gspca_dev *gspca_dev)
1048{
1049 struct sd *sd = (struct sd *) gspca_dev;
1050 struct usb_device *dev = gspca_dev->dev;
1051 int rc;
6a7eba24
JFM
1052 __u8 i;
1053 __u8 info[6];
1054 int err_code;
1055
1056 switch (sd->bridge) {
1057 case BRIDGE_SPCA504B:
739570bb
JFM
1058 reg_w(dev, 0x1d, 0, 0, NULL, 0);
1059 reg_w(dev, 0, 1, 0x2306, NULL, 0);
1060 reg_w(dev, 0, 0, 0x0d04, NULL, 0);
1061 reg_w(dev, 0, 0, 0x2000, NULL, 0);
1062 reg_w(dev, 0, 0x13, 0x2301, NULL, 0);
1063 reg_w(dev, 0, 0, 0x2306, NULL, 0);
6a7eba24
JFM
1064 /* fall thru */
1065 case BRIDGE_SPCA533:
739570bb 1066 rc = spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
1067 spca50x_GetFirmware(gspca_dev);
1068 break;
1069 case BRIDGE_SPCA536:
1070 spca50x_GetFirmware(gspca_dev);
739570bb
JFM
1071 reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1);
1072 gspca_dev->usb_buf[0] = 0;
1073 reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1);
1074 reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1);
1075 rc = spca504B_PollingDataReady(gspca_dev);
1076 reg_w(dev, 0x34, 0, 0, NULL, 0);
6a7eba24
JFM
1077 spca504B_WaitCmdStatus(gspca_dev);
1078 break;
1079 case BRIDGE_SPCA504C: /* pccam600 */
1080 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
739570bb
JFM
1081 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
1082 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
6a7eba24
JFM
1083 spca504_wait_status(gspca_dev);
1084 if (sd->subtype == LogitechClickSmart420)
1085 write_vector(gspca_dev,
1086 spca504A_clicksmart420_open_data);
1087 else
1088 write_vector(gspca_dev, spca504_pccam600_open_data);
1089 err_code = spca50x_setup_qtable(gspca_dev,
1090 0x00, 0x2800,
1091 0x2840, qtable_creative_pccam);
1092 if (err_code < 0) {
1093 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
1094 return err_code;
1095 }
1096 break;
1097 default:
1098/* case BRIDGE_SPCA504: */
1099 PDEBUG(D_STREAM, "Opening SPCA504");
1100 if (sd->subtype == AiptekMiniPenCam13) {
1101 /*****************************/
1102 for (i = 0; i < 6; i++)
739570bb 1103 info[i] = reg_r_1(gspca_dev, i);
6a7eba24
JFM
1104 PDEBUG(D_STREAM,
1105 "Read info: %d %d %d %d %d %d."
1106 " Should be 1,0,2,2,0,0",
1107 info[0], info[1], info[2],
1108 info[3], info[4], info[5]);
1109 /* spca504a aiptek */
1110 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1111 spca504A_acknowledged_command(gspca_dev, 0x24,
1112 8, 3, 0x9e, 1);
1113 /* Twice sequencial need status 0xff->0x9e->0x9d */
1114 spca504A_acknowledged_command(gspca_dev, 0x24,
1115 8, 3, 0x9e, 0);
1116
1117 spca504A_acknowledged_command(gspca_dev, 0x24,
1118 0, 0, 0x9d, 1);
1119 /******************************/
1120 /* spca504a aiptek */
1121 spca504A_acknowledged_command(gspca_dev, 0x08,
1122 6, 0, 0x86, 1);
1123/* reg_write (dev, 0, 0x2000, 0); */
1124/* reg_write (dev, 0, 0x2883, 1); */
1125/* spca504A_acknowledged_command (gspca_dev, 0x08,
1126 6, 0, 0x86, 1); */
1127/* spca504A_acknowledged_command (gspca_dev, 0x24,
1128 0, 0, 0x9D, 1); */
739570bb
JFM
1129 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1130 reg_w_riv(dev, 0x0, 0x2310, 0x05);
6a7eba24
JFM
1131 spca504A_acknowledged_command(gspca_dev, 0x01,
1132 0x0f, 0, 0xff, 0);
1133 }
1134 /* setup qtable */
739570bb
JFM
1135 reg_w_riv(dev, 0, 0x2000, 0);
1136 reg_w_riv(dev, 0, 0x2883, 1);
6a7eba24
JFM
1137 err_code = spca50x_setup_qtable(gspca_dev,
1138 0x00, 0x2800,
1139 0x2840,
1140 qtable_spca504_default);
1141 if (err_code < 0) {
1142 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
1143 return err_code;
1144 }
1145 break;
1146 }
1147 return 0;
1148}
1149
1150static void sd_start(struct gspca_dev *gspca_dev)
1151{
1152 struct sd *sd = (struct sd *) gspca_dev;
1153 struct usb_device *dev = gspca_dev->dev;
1154 int rc;
1155 int enable;
1156 __u8 i;
1157 __u8 info[6];
1158
1159 if (sd->bridge == BRIDGE_SPCA504B)
1160 spca504B_setQtable(gspca_dev);
1161 spca504B_SetSizeType(gspca_dev);
1162 switch (sd->bridge) {
1163 default:
1164/* case BRIDGE_SPCA504B: */
1165/* case BRIDGE_SPCA533: */
1166/* case BRIDGE_SPCA536: */
1167 if (sd->subtype == MegapixV4 ||
1168 sd->subtype == LogitechClickSmart820) {
739570bb 1169 reg_w(dev, 0xf0, 0, 0, NULL, 0);
6a7eba24 1170 spca504B_WaitCmdStatus(gspca_dev);
739570bb 1171 reg_r(dev, 0xf0, 4, NULL, 0);
6a7eba24
JFM
1172 spca504B_WaitCmdStatus(gspca_dev);
1173 } else {
739570bb 1174 reg_w(dev, 0x31, 0, 4, NULL, 0);
6a7eba24 1175 spca504B_WaitCmdStatus(gspca_dev);
739570bb 1176 rc = spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
1177 }
1178 break;
1179 case BRIDGE_SPCA504:
1180 if (sd->subtype == AiptekMiniPenCam13) {
1181 for (i = 0; i < 6; i++)
739570bb 1182 info[i] = reg_r_1(gspca_dev, i);
6a7eba24
JFM
1183 PDEBUG(D_STREAM,
1184 "Read info: %d %d %d %d %d %d."
1185 " Should be 1,0,2,2,0,0",
1186 info[0], info[1], info[2],
1187 info[3], info[4], info[5]);
1188 /* spca504a aiptek */
1189 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1190 spca504A_acknowledged_command(gspca_dev, 0x24,
1191 8, 3, 0x9e, 1);
1192 /* Twice sequencial need status 0xff->0x9e->0x9d */
1193 spca504A_acknowledged_command(gspca_dev, 0x24,
1194 8, 3, 0x9e, 0);
1195 spca504A_acknowledged_command(gspca_dev, 0x24,
1196 0, 0, 0x9d, 1);
1197 } else {
1198 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1199 for (i = 0; i < 6; i++)
739570bb 1200 info[i] = reg_r_1(gspca_dev, i);
6a7eba24
JFM
1201 PDEBUG(D_STREAM,
1202 "Read info: %d %d %d %d %d %d."
1203 " Should be 1,0,2,2,0,0",
1204 info[0], info[1], info[2],
1205 info[3], info[4], info[5]);
1206 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1207 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1208 }
1209 spca504B_SetSizeType(gspca_dev);
739570bb
JFM
1210 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1211 reg_w_riv(dev, 0x0, 0x2310, 0x05);
6a7eba24
JFM
1212 break;
1213 case BRIDGE_SPCA504C:
1214 if (sd->subtype == LogitechClickSmart420) {
1215 write_vector(gspca_dev,
1216 spca504A_clicksmart420_init_data);
1217 } else {
1218 write_vector(gspca_dev, spca504_pccam600_init_data);
1219 }
739570bb
JFM
1220 enable = (sd->autogain ? 0x04 : 0x01);
1221 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1222 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
6a7eba24
JFM
1223
1224 /* set default exposure compensation and whiteness balance */
739570bb
JFM
1225 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1226 reg_w_riv(dev, 0x30, 0x0002, 1600);
6a7eba24
JFM
1227 spca504B_SetSizeType(gspca_dev);
1228 break;
1229 }
1230 sp5xx_initContBrigHueRegisters(gspca_dev);
1231}
1232
1233static void sd_stopN(struct gspca_dev *gspca_dev)
1234{
1235 struct sd *sd = (struct sd *) gspca_dev;
1236 struct usb_device *dev = gspca_dev->dev;
1237
1238 switch (sd->bridge) {
1239 default:
1240/* case BRIDGE_SPCA533: */
1241/* case BRIDGE_SPCA536: */
1242/* case BRIDGE_SPCA504B: */
739570bb 1243 reg_w(dev, 0x31, 0, 0, NULL, 0);
6a7eba24 1244 spca504B_WaitCmdStatus(gspca_dev);
739570bb 1245 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
1246 break;
1247 case BRIDGE_SPCA504:
1248 case BRIDGE_SPCA504C:
739570bb 1249 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
6a7eba24
JFM
1250
1251 if (sd->subtype == AiptekMiniPenCam13) {
1252 /* spca504a aiptek */
1253/* spca504A_acknowledged_command(gspca_dev, 0x08,
1254 6, 0, 0x86, 1); */
1255 spca504A_acknowledged_command(gspca_dev, 0x24,
1256 0x00, 0x00, 0x9d, 1);
1257 spca504A_acknowledged_command(gspca_dev, 0x01,
1258 0x0f, 0x00, 0xff, 1);
1259 } else {
1260 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
739570bb 1261 reg_w_riv(dev, 0x01, 0x000f, 0x00);
6a7eba24
JFM
1262 }
1263 break;
1264 }
1265}
1266
1267static void sd_stop0(struct gspca_dev *gspca_dev)
1268{
1269}
1270
1271static void sd_close(struct gspca_dev *gspca_dev)
1272{
1273}
1274
1275static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1276 struct gspca_frame *frame, /* target */
a5ae2062 1277 __u8 *data, /* isoc packet */
6a7eba24
JFM
1278 int len) /* iso packet length */
1279{
1280 struct sd *sd = (struct sd *) gspca_dev;
1281 int i, sof = 0;
1282 unsigned char *s, *d;
1283 static unsigned char ffd9[] = {0xff, 0xd9};
1284
1285/* frames are jpeg 4.1.1 without 0xff escape */
1286 switch (sd->bridge) {
1287 case BRIDGE_SPCA533:
1288 if (data[0] == 0xff) {
1289 if (data[1] != 0x01) { /* drop packet */
1290/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1291 return;
1292 }
1293 sof = 1;
1294 data += SPCA533_OFFSET_DATA;
1295 len -= SPCA533_OFFSET_DATA;
1296 } else {
1297 data += 1;
1298 len -= 1;
1299 }
1300 break;
1301 case BRIDGE_SPCA536:
1302 if (data[0] == 0xff) {
1303 sof = 1;
1304 data += SPCA536_OFFSET_DATA;
1305 len -= SPCA536_OFFSET_DATA;
1306 } else {
1307 data += 2;
1308 len -= 2;
1309 }
1310 break;
1311 default:
1312/* case BRIDGE_SPCA504: */
1313/* case BRIDGE_SPCA504B: */
1314 switch (data[0]) {
1315 case 0xfe: /* start of frame */
1316 sof = 1;
1317 data += SPCA50X_OFFSET_DATA;
1318 len -= SPCA50X_OFFSET_DATA;
1319 break;
1320 case 0xff: /* drop packet */
1321/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1322 return;
1323 default:
1324 data += 1;
1325 len -= 1;
1326 break;
1327 }
1328 break;
1329 case BRIDGE_SPCA504C:
1330 switch (data[0]) {
1331 case 0xfe: /* start of frame */
1332 sof = 1;
1333 data += SPCA504_PCCAM600_OFFSET_DATA;
1334 len -= SPCA504_PCCAM600_OFFSET_DATA;
1335 break;
1336 case 0xff: /* drop packet */
1337/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1338 return;
1339 default:
1340 data += 1;
1341 len -= 1;
1342 break;
1343 }
1344 break;
1345 }
1346 if (sof) { /* start of frame */
1347 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1348 ffd9, 2);
1349
1350 /* put the JPEG header in the new frame */
1351 jpeg_put_header(gspca_dev, frame,
1352 ((struct sd *) gspca_dev)->qindex,
1353 0x22);
1354 }
1355
1356 /* add 0x00 after 0xff */
1357 for (i = len; --i >= 0; )
1358 if (data[i] == 0xff)
1359 break;
1360 if (i < 0) { /* no 0xff */
1361 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1362 return;
1363 }
1364 s = data;
1365 d = sd->packet;
1366 for (i = 0; i < len; i++) {
1367 *d++ = *s++;
1368 if (s[-1] == 0xff)
1369 *d++ = 0x00;
1370 }
1371 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1372 sd->packet, d - sd->packet);
1373}
1374
1375static void setbrightness(struct gspca_dev *gspca_dev)
1376{
1377 struct sd *sd = (struct sd *) gspca_dev;
1378 struct usb_device *dev = gspca_dev->dev;
1379
1380 switch (sd->bridge) {
1381 default:
1382/* case BRIDGE_SPCA533: */
1383/* case BRIDGE_SPCA504B: */
1384/* case BRIDGE_SPCA504: */
1385/* case BRIDGE_SPCA504C: */
739570bb 1386 reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
6a7eba24
JFM
1387 break;
1388 case BRIDGE_SPCA536:
739570bb 1389 reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
6a7eba24
JFM
1390 break;
1391 }
1392}
1393
1394static void getbrightness(struct gspca_dev *gspca_dev)
1395{
1396 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
1397 __u16 brightness = 0;
1398
1399 switch (sd->bridge) {
1400 default:
1401/* case BRIDGE_SPCA533: */
1402/* case BRIDGE_SPCA504B: */
1403/* case BRIDGE_SPCA504: */
1404/* case BRIDGE_SPCA504C: */
739570bb 1405 brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2);
6a7eba24
JFM
1406 break;
1407 case BRIDGE_SPCA536:
739570bb 1408 brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2);
6a7eba24
JFM
1409 break;
1410 }
1411 sd->brightness = ((brightness & 0xff) - 128) % 255;
1412}
1413
1414static void setcontrast(struct gspca_dev *gspca_dev)
1415{
1416 struct sd *sd = (struct sd *) gspca_dev;
1417 struct usb_device *dev = gspca_dev->dev;
1418
1419 switch (sd->bridge) {
1420 default:
1421/* case BRIDGE_SPCA533: */
1422/* case BRIDGE_SPCA504B: */
1423/* case BRIDGE_SPCA504: */
1424/* case BRIDGE_SPCA504C: */
739570bb 1425 reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
6a7eba24
JFM
1426 break;
1427 case BRIDGE_SPCA536:
739570bb 1428 reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
6a7eba24
JFM
1429 break;
1430 }
1431}
1432
1433static void getcontrast(struct gspca_dev *gspca_dev)
1434{
1435 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
1436
1437 switch (sd->bridge) {
1438 default:
1439/* case BRIDGE_SPCA533: */
1440/* case BRIDGE_SPCA504B: */
1441/* case BRIDGE_SPCA504: */
1442/* case BRIDGE_SPCA504C: */
739570bb 1443 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2);
6a7eba24
JFM
1444 break;
1445 case BRIDGE_SPCA536:
739570bb 1446 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2);
6a7eba24
JFM
1447 break;
1448 }
1449}
1450
1451static void setcolors(struct gspca_dev *gspca_dev)
1452{
1453 struct sd *sd = (struct sd *) gspca_dev;
1454 struct usb_device *dev = gspca_dev->dev;
1455
1456 switch (sd->bridge) {
1457 default:
1458/* case BRIDGE_SPCA533: */
1459/* case BRIDGE_SPCA504B: */
1460/* case BRIDGE_SPCA504: */
1461/* case BRIDGE_SPCA504C: */
739570bb 1462 reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
6a7eba24
JFM
1463 break;
1464 case BRIDGE_SPCA536:
739570bb 1465 reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
6a7eba24
JFM
1466 break;
1467 }
1468}
1469
1470static void getcolors(struct gspca_dev *gspca_dev)
1471{
1472 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
1473
1474 switch (sd->bridge) {
1475 default:
1476/* case BRIDGE_SPCA533: */
1477/* case BRIDGE_SPCA504B: */
1478/* case BRIDGE_SPCA504: */
1479/* case BRIDGE_SPCA504C: */
739570bb 1480 sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1;
6a7eba24
JFM
1481 break;
1482 case BRIDGE_SPCA536:
739570bb 1483 sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1;
6a7eba24
JFM
1484 break;
1485 }
1486}
1487
1488static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1489{
1490 struct sd *sd = (struct sd *) gspca_dev;
1491
1492 sd->brightness = val;
1493 if (gspca_dev->streaming)
1494 setbrightness(gspca_dev);
1495 return 0;
1496}
1497
1498static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1499{
1500 struct sd *sd = (struct sd *) gspca_dev;
1501
1502 getbrightness(gspca_dev);
1503 *val = sd->brightness;
1504 return 0;
1505}
1506
1507static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1508{
1509 struct sd *sd = (struct sd *) gspca_dev;
1510
1511 sd->contrast = val;
1512 if (gspca_dev->streaming)
1513 setcontrast(gspca_dev);
1514 return 0;
1515}
1516
1517static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1518{
1519 struct sd *sd = (struct sd *) gspca_dev;
1520
1521 getcontrast(gspca_dev);
1522 *val = sd->contrast;
1523 return 0;
1524}
1525
1526static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1527{
1528 struct sd *sd = (struct sd *) gspca_dev;
1529
1530 sd->colors = val;
1531 if (gspca_dev->streaming)
1532 setcolors(gspca_dev);
1533 return 0;
1534}
1535
1536static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1537{
1538 struct sd *sd = (struct sd *) gspca_dev;
1539
1540 getcolors(gspca_dev);
1541 *val = sd->colors;
1542 return 0;
1543}
1544
1545static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1546{
1547 struct sd *sd = (struct sd *) gspca_dev;
1548
1549 sd->autogain = val;
1550 return 0;
1551}
1552
1553static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1554{
1555 struct sd *sd = (struct sd *) gspca_dev;
1556
1557 *val = sd->autogain;
1558 return 0;
1559}
1560
1561/* sub-driver description */
a5ae2062 1562static const struct sd_desc sd_desc = {
6a7eba24
JFM
1563 .name = MODULE_NAME,
1564 .ctrls = sd_ctrls,
1565 .nctrls = ARRAY_SIZE(sd_ctrls),
1566 .config = sd_config,
1567 .open = sd_open,
1568 .start = sd_start,
1569 .stopN = sd_stopN,
1570 .stop0 = sd_stop0,
1571 .close = sd_close,
1572 .pkt_scan = sd_pkt_scan,
1573};
1574
1575/* -- module initialisation -- */
1576#define DVNM(name) .driver_info = (kernel_ulong_t) name
a5ae2062 1577static const __devinitdata struct usb_device_id device_table[] = {
6a7eba24
JFM
1578 {USB_DEVICE(0x041e, 0x400b), DVNM("Creative PC-CAM 600")},
1579 {USB_DEVICE(0x041e, 0x4012), DVNM("PC-Cam350")},
1580 {USB_DEVICE(0x041e, 0x4013), DVNM("Creative Pccam750")},
1581 {USB_DEVICE(0x0458, 0x7006), DVNM("Genius Dsc 1.3 Smart")},
1582 {USB_DEVICE(0x046d, 0x0905), DVNM("Logitech ClickSmart 820")},
1583 {USB_DEVICE(0x046d, 0x0960), DVNM("Logitech ClickSmart 420")},
1584 {USB_DEVICE(0x0471, 0x0322), DVNM("Philips DMVC1300K")},
1585 {USB_DEVICE(0x04a5, 0x3003), DVNM("Benq DC 1300")},
1586 {USB_DEVICE(0x04a5, 0x3008), DVNM("Benq DC 1500")},
1587 {USB_DEVICE(0x04a5, 0x300a), DVNM("Benq DC3410")},
1588 {USB_DEVICE(0x04f1, 0x1001), DVNM("JVC GC A50")},
1589 {USB_DEVICE(0x04fc, 0x500c), DVNM("Sunplus CA500C")},
1590 {USB_DEVICE(0x04fc, 0x504a), DVNM("Aiptek Mini PenCam 1.3")},
1591 {USB_DEVICE(0x04fc, 0x504b), DVNM("Maxell MaxPocket LE 1.3")},
1592 {USB_DEVICE(0x04fc, 0x5330), DVNM("Digitrex 2110")},
1593 {USB_DEVICE(0x04fc, 0x5360), DVNM("Sunplus Generic")},
1594 {USB_DEVICE(0x04fc, 0xffff), DVNM("Pure DigitalDakota")},
1595 {USB_DEVICE(0x052b, 0x1513), DVNM("Megapix V4")},
1596 {USB_DEVICE(0x0546, 0x3155), DVNM("Polaroid PDC3070")},
1597 {USB_DEVICE(0x0546, 0x3191), DVNM("Polaroid Ion 80")},
1598 {USB_DEVICE(0x0546, 0x3273), DVNM("Polaroid PDC2030")},
1599 {USB_DEVICE(0x055f, 0xc211), DVNM("Kowa Bs888e Microcamera")},
1600 {USB_DEVICE(0x055f, 0xc230), DVNM("Mustek Digicam 330K")},
1601 {USB_DEVICE(0x055f, 0xc232), DVNM("Mustek MDC3500")},
1602 {USB_DEVICE(0x055f, 0xc360), DVNM("Mustek DV4000 Mpeg4 ")},
1603 {USB_DEVICE(0x055f, 0xc420), DVNM("Mustek gSmart Mini 2")},
1604 {USB_DEVICE(0x055f, 0xc430), DVNM("Mustek Gsmart LCD 2")},
1605 {USB_DEVICE(0x055f, 0xc440), DVNM("Mustek DV 3000")},
1606 {USB_DEVICE(0x055f, 0xc520), DVNM("Mustek gSmart Mini 3")},
1607 {USB_DEVICE(0x055f, 0xc530), DVNM("Mustek Gsmart LCD 3")},
1608 {USB_DEVICE(0x055f, 0xc540), DVNM("Gsmart D30")},
1609 {USB_DEVICE(0x055f, 0xc630), DVNM("Mustek MDC4000")},
1610 {USB_DEVICE(0x055f, 0xc650), DVNM("Mustek MDC5500Z")},
1611 {USB_DEVICE(0x05da, 0x1018), DVNM("Digital Dream Enigma 1.3")},
1612 {USB_DEVICE(0x06d6, 0x0031), DVNM("Trust 610 LCD PowerC@m Zoom")},
1613 {USB_DEVICE(0x0733, 0x1311), DVNM("Digital Dream Epsilon 1.3")},
1614 {USB_DEVICE(0x0733, 0x1314), DVNM("Mercury 2.1MEG Deluxe Classic Cam")},
1615 {USB_DEVICE(0x0733, 0x2211), DVNM("Jenoptik jdc 21 LCD")},
1616 {USB_DEVICE(0x0733, 0x2221), DVNM("Mercury Digital Pro 3.1p")},
1617 {USB_DEVICE(0x0733, 0x3261), DVNM("Concord 3045 spca536a")},
1618 {USB_DEVICE(0x0733, 0x3281), DVNM("Cyberpix S550V")},
1619 {USB_DEVICE(0x08ca, 0x0104), DVNM("Aiptek PocketDVII 1.3")},
1620 {USB_DEVICE(0x08ca, 0x0106), DVNM("Aiptek Pocket DV3100+")},
1621 {USB_DEVICE(0x08ca, 0x2008), DVNM("Aiptek Mini PenCam 2 M")},
1622 {USB_DEVICE(0x08ca, 0x2010), DVNM("Aiptek PocketCam 3M")},
1623 {USB_DEVICE(0x08ca, 0x2016), DVNM("Aiptek PocketCam 2 Mega")},
1624 {USB_DEVICE(0x08ca, 0x2018), DVNM("Aiptek Pencam SD 2M")},
1625 {USB_DEVICE(0x08ca, 0x2020), DVNM("Aiptek Slim 3000F")},
1626 {USB_DEVICE(0x08ca, 0x2022), DVNM("Aiptek Slim 3200")},
1627 {USB_DEVICE(0x08ca, 0x2024), DVNM("Aiptek DV3500 Mpeg4 ")},
1628 {USB_DEVICE(0x08ca, 0x2028), DVNM("Aiptek PocketCam4M")},
1629 {USB_DEVICE(0x08ca, 0x2040), DVNM("Aiptek PocketDV4100M")},
1630 {USB_DEVICE(0x08ca, 0x2042), DVNM("Aiptek PocketDV5100")},
1631 {USB_DEVICE(0x08ca, 0x2060), DVNM("Aiptek PocketDV5300")},
1632 {USB_DEVICE(0x0d64, 0x0303), DVNM("Sunplus FashionCam DXG")},
1633 {}
1634};
1635MODULE_DEVICE_TABLE(usb, device_table);
1636
1637/* -- device connect -- */
1638static int sd_probe(struct usb_interface *intf,
1639 const struct usb_device_id *id)
1640{
1641 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1642 THIS_MODULE);
1643}
1644
1645static struct usb_driver sd_driver = {
1646 .name = MODULE_NAME,
1647 .id_table = device_table,
1648 .probe = sd_probe,
1649 .disconnect = gspca_disconnect,
1650};
1651
1652/* -- module insert / remove -- */
1653static int __init sd_mod_init(void)
1654{
1655 if (usb_register(&sd_driver) < 0)
1656 return -1;
1657 PDEBUG(D_PROBE, "v%s registered", version);
1658 return 0;
1659}
1660static void __exit sd_mod_exit(void)
1661{
1662 usb_deregister(&sd_driver);
1663 PDEBUG(D_PROBE, "deregistered");
1664}
1665
1666module_init(sd_mod_init);
1667module_exit(sd_mod_exit);