aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/spca500.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/spca500.c')
-rw-r--r--drivers/media/video/gspca/spca500.c1216
1 files changed, 1216 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
new file mode 100644
index 000000000000..156206118795
--- /dev/null
+++ b/drivers/media/video/gspca/spca500.c
@@ -0,0 +1,1216 @@
1/*
2 * SPCA500 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca500"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA500 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
38 __u8 packet[ISO_MAX_SIZE + 128];
39 /* !! no more than 128 ff in an ISO packet */
40
41 unsigned char brightness;
42 unsigned char contrast;
43 unsigned char colors;
44
45 char qindex;
46 char subtype;
47#define AgfaCl20 0
48#define AiptekPocketDV 1
49#define BenqDC1016 2
50#define CreativePCCam300 3
51#define DLinkDSC350 4
52#define Gsmartmini 5
53#define IntelPocketPCCamera 6
54#define KodakEZ200 7
55#define LogitechClickSmart310 8
56#define LogitechClickSmart510 9
57#define LogitechTraveler 10
58#define MustekGsmart300 11
59#define Optimedia 12
60#define PalmPixDC85 13
61#define ToptroIndus 14
62};
63
64/* V4L2 controls supported by the driver */
65static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
71
72static struct ctrl sd_ctrls[] = {
73 {
74 {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = 0,
79 .maximum = 255,
80 .step = 1,
81#define BRIGHTNESS_DEF 127
82 .default_value = BRIGHTNESS_DEF,
83 },
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
86 },
87 {
88 {
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Contrast",
92 .minimum = 0,
93 .maximum = 63,
94 .step = 1,
95#define CONTRAST_DEF 31
96 .default_value = CONTRAST_DEF,
97 },
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
100 },
101 {
102 {
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Color",
106 .minimum = 0,
107 .maximum = 63,
108 .step = 1,
109#define COLOR_DEF 31
110 .default_value = COLOR_DEF,
111 },
112 .set = sd_setcolors,
113 .get = sd_getcolors,
114 },
115};
116
117static struct v4l2_pix_format vga_mode[] = {
118 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
119 .bytesperline = 320,
120 .sizeimage = 320 * 240 * 3 / 8 + 590,
121 .colorspace = V4L2_COLORSPACE_JPEG,
122 .priv = 1},
123 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
124 .bytesperline = 640,
125 .sizeimage = 640 * 480 * 3 / 8 + 590,
126 .colorspace = V4L2_COLORSPACE_JPEG,
127 .priv = 0},
128};
129
130static struct v4l2_pix_format sif_mode[] = {
131 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
132 .bytesperline = 176,
133 .sizeimage = 176 * 144 * 3 / 8 + 590,
134 .colorspace = V4L2_COLORSPACE_JPEG,
135 .priv = 1},
136 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
137 .bytesperline = 352,
138 .sizeimage = 352 * 288 * 3 / 8 + 590,
139 .colorspace = V4L2_COLORSPACE_JPEG,
140 .priv = 0},
141};
142
143/* Frame packet header offsets for the spca500 */
144#define SPCA500_OFFSET_PADDINGLB 2
145#define SPCA500_OFFSET_PADDINGHB 3
146#define SPCA500_OFFSET_MODE 4
147#define SPCA500_OFFSET_IMGWIDTH 5
148#define SPCA500_OFFSET_IMGHEIGHT 6
149#define SPCA500_OFFSET_IMGMODE 7
150#define SPCA500_OFFSET_QTBLINDEX 8
151#define SPCA500_OFFSET_FRAMSEQ 9
152#define SPCA500_OFFSET_CDSPINFO 10
153#define SPCA500_OFFSET_GPIO 11
154#define SPCA500_OFFSET_AUGPIO 12
155#define SPCA500_OFFSET_DATA 16
156
157
158static const __u16 spca500_visual_defaults[][3] = {
159 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
160 * hue (H byte) = 0,
161 * saturation/hue enable,
162 * brightness/contrast enable.
163 */
164 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
165 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
166 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
167 * hue (H byte) = 0, saturation/hue enable,
168 * brightness/contrast enable.
169 * was 0x0003, now 0x0000.
170 */
171 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
172 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
173 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
174 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
175 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
176 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
177 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
178 {0x0c, 0x0004, 0x0000},
179 /* set interface */
180 {}
181};
182static const __u16 Clicksmart510_defaults[][3] = {
183 {0x00, 0x00, 0x8211},
184 {0x00, 0x01, 0x82c0},
185 {0x00, 0x10, 0x82cb},
186 {0x00, 0x0f, 0x800d},
187 {0x00, 0x82, 0x8225},
188 {0x00, 0x21, 0x8228},
189 {0x00, 0x00, 0x8203},
190 {0x00, 0x00, 0x8204},
191 {0x00, 0x08, 0x8205},
192 {0x00, 0xf8, 0x8206},
193 {0x00, 0x28, 0x8207},
194 {0x00, 0xa0, 0x8208},
195 {0x00, 0x08, 0x824a},
196 {0x00, 0x08, 0x8214},
197 {0x00, 0x80, 0x82c1},
198 {0x00, 0x00, 0x82c2},
199 {0x00, 0x00, 0x82ca},
200 {0x00, 0x80, 0x82c1},
201 {0x00, 0x04, 0x82c2},
202 {0x00, 0x00, 0x82ca},
203 {0x00, 0xfc, 0x8100},
204 {0x00, 0xfc, 0x8105},
205 {0x00, 0x30, 0x8101},
206 {0x00, 0x00, 0x8102},
207 {0x00, 0x00, 0x8103},
208 {0x00, 0x66, 0x8107},
209 {0x00, 0x00, 0x816b},
210 {0x00, 0x00, 0x8155},
211 {0x00, 0x01, 0x8156},
212 {0x00, 0x60, 0x8157},
213 {0x00, 0x40, 0x8158},
214 {0x00, 0x0a, 0x8159},
215 {0x00, 0x06, 0x815a},
216 {0x00, 0x00, 0x813f},
217 {0x00, 0x00, 0x8200},
218 {0x00, 0x19, 0x8201},
219 {0x00, 0x00, 0x82c1},
220 {0x00, 0xa0, 0x82c2},
221 {0x00, 0x00, 0x82ca},
222 {0x00, 0x00, 0x8117},
223 {0x00, 0x00, 0x8118},
224 {0x00, 0x65, 0x8119},
225 {0x00, 0x00, 0x811a},
226 {0x00, 0x00, 0x811b},
227 {0x00, 0x55, 0x811c},
228 {0x00, 0x65, 0x811d},
229 {0x00, 0x55, 0x811e},
230 {0x00, 0x16, 0x811f},
231 {0x00, 0x19, 0x8120},
232 {0x00, 0x80, 0x8103},
233 {0x00, 0x83, 0x816b},
234 {0x00, 0x25, 0x8168},
235 {0x00, 0x01, 0x820f},
236 {0x00, 0xff, 0x8115},
237 {0x00, 0x48, 0x8116},
238 {0x00, 0x50, 0x8151},
239 {0x00, 0x40, 0x8152},
240 {0x00, 0x78, 0x8153},
241 {0x00, 0x40, 0x8154},
242 {0x00, 0x00, 0x8167},
243 {0x00, 0x20, 0x8168},
244 {0x00, 0x00, 0x816a},
245 {0x00, 0x03, 0x816b},
246 {0x00, 0x20, 0x8169},
247 {0x00, 0x60, 0x8157},
248 {0x00, 0x00, 0x8190},
249 {0x00, 0x00, 0x81a1},
250 {0x00, 0x00, 0x81b2},
251 {0x00, 0x27, 0x8191},
252 {0x00, 0x27, 0x81a2},
253 {0x00, 0x27, 0x81b3},
254 {0x00, 0x4b, 0x8192},
255 {0x00, 0x4b, 0x81a3},
256 {0x00, 0x4b, 0x81b4},
257 {0x00, 0x66, 0x8193},
258 {0x00, 0x66, 0x81a4},
259 {0x00, 0x66, 0x81b5},
260 {0x00, 0x79, 0x8194},
261 {0x00, 0x79, 0x81a5},
262 {0x00, 0x79, 0x81b6},
263 {0x00, 0x8a, 0x8195},
264 {0x00, 0x8a, 0x81a6},
265 {0x00, 0x8a, 0x81b7},
266 {0x00, 0x9b, 0x8196},
267 {0x00, 0x9b, 0x81a7},
268 {0x00, 0x9b, 0x81b8},
269 {0x00, 0xa6, 0x8197},
270 {0x00, 0xa6, 0x81a8},
271 {0x00, 0xa6, 0x81b9},
272 {0x00, 0xb2, 0x8198},
273 {0x00, 0xb2, 0x81a9},
274 {0x00, 0xb2, 0x81ba},
275 {0x00, 0xbe, 0x8199},
276 {0x00, 0xbe, 0x81aa},
277 {0x00, 0xbe, 0x81bb},
278 {0x00, 0xc8, 0x819a},
279 {0x00, 0xc8, 0x81ab},
280 {0x00, 0xc8, 0x81bc},
281 {0x00, 0xd2, 0x819b},
282 {0x00, 0xd2, 0x81ac},
283 {0x00, 0xd2, 0x81bd},
284 {0x00, 0xdb, 0x819c},
285 {0x00, 0xdb, 0x81ad},
286 {0x00, 0xdb, 0x81be},
287 {0x00, 0xe4, 0x819d},
288 {0x00, 0xe4, 0x81ae},
289 {0x00, 0xe4, 0x81bf},
290 {0x00, 0xed, 0x819e},
291 {0x00, 0xed, 0x81af},
292 {0x00, 0xed, 0x81c0},
293 {0x00, 0xf7, 0x819f},
294 {0x00, 0xf7, 0x81b0},
295 {0x00, 0xf7, 0x81c1},
296 {0x00, 0xff, 0x81a0},
297 {0x00, 0xff, 0x81b1},
298 {0x00, 0xff, 0x81c2},
299 {0x00, 0x03, 0x8156},
300 {0x00, 0x00, 0x8211},
301 {0x00, 0x20, 0x8168},
302 {0x00, 0x01, 0x8202},
303 {0x00, 0x30, 0x8101},
304 {0x00, 0x00, 0x8111},
305 {0x00, 0x00, 0x8112},
306 {0x00, 0x00, 0x8113},
307 {0x00, 0x00, 0x8114},
308 {}
309};
310
311static const __u8 qtable_creative_pccam[2][64] = {
312 { /* Q-table Y-components */
313 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
314 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
315 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
316 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
317 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
318 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
319 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
320 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
321 { /* Q-table C-components */
322 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
323 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
324 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
325 0x0e, 0x14, 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 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
330};
331
332static const __u8 qtable_kodak_ez200[2][64] = {
333 { /* Q-table Y-components */
334 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
335 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
336 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
337 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
338 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
339 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
340 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
341 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
342 { /* Q-table C-components */
343 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
344 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
345 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
346 0x05, 0x07, 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 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
351};
352
353static const __u8 qtable_pocketdv[2][64] = {
354 { /* Q-table Y-components start registers 0x8800 */
355 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
356 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
357 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
358 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
359 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
360 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
361 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
362 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
363 },
364 { /* Q-table C-components start registers 0x8840 */
365 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
366 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
367 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
368 0x13, 0x1a, 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 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
373};
374
375/* read 'len' bytes to gspca_dev->usb_buf */
376static void reg_r(struct gspca_dev *gspca_dev,
377 __u16 index,
378 __u16 length)
379{
380 usb_control_msg(gspca_dev->dev,
381 usb_rcvctrlpipe(gspca_dev->dev, 0),
382 0,
383 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
384 0, /* value */
385 index, gspca_dev->usb_buf, length, 500);
386}
387
388static int reg_w(struct gspca_dev *gspca_dev,
389 __u16 req, __u16 index, __u16 value)
390{
391 int ret;
392
393 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
394 ret = usb_control_msg(gspca_dev->dev,
395 usb_sndctrlpipe(gspca_dev->dev, 0),
396 req,
397 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
398 value, index, NULL, 0, 500);
399 if (ret < 0)
400 PDEBUG(D_ERR, "reg write: error %d", ret);
401 return ret;
402}
403
404/* returns: negative is error, pos or zero is data */
405static int reg_r_12(struct gspca_dev *gspca_dev,
406 __u16 req, /* bRequest */
407 __u16 index, /* wIndex */
408 __u16 length) /* wLength (1 or 2 only) */
409{
410 int ret;
411
412 gspca_dev->usb_buf[1] = 0;
413 ret = usb_control_msg(gspca_dev->dev,
414 usb_rcvctrlpipe(gspca_dev->dev, 0),
415 req,
416 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
417 0, /* value */
418 index,
419 gspca_dev->usb_buf, length,
420 500); /* timeout */
421 if (ret < 0) {
422 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
423 return -1;
424 }
425 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
426}
427
428/*
429 * Simple function to wait for a given 8-bit value to be returned from
430 * a reg_read call.
431 * Returns: negative is error or timeout, zero is success.
432 */
433static int reg_r_wait(struct gspca_dev *gspca_dev,
434 __u16 reg, __u16 index, __u16 value)
435{
436 int ret, cnt = 20;
437
438 while (--cnt > 0) {
439 ret = reg_r_12(gspca_dev, reg, index, 1);
440 if (ret == value)
441 return 0;
442 msleep(50);
443 }
444 return -EIO;
445}
446
447static int write_vector(struct gspca_dev *gspca_dev,
448 const __u16 data[][3])
449{
450 int ret, i = 0;
451
452 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
453 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
454 if (ret < 0)
455 return ret;
456 i++;
457 }
458 return 0;
459}
460
461static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
462 unsigned int request,
463 unsigned int ybase,
464 unsigned int cbase,
465 const __u8 qtable[2][64])
466{
467 int i, err;
468
469 /* loop over y components */
470 for (i = 0; i < 64; i++) {
471 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
472 if (err < 0)
473 return err;
474 }
475
476 /* loop over c components */
477 for (i = 0; i < 64; i++) {
478 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
479 if (err < 0)
480 return err;
481 }
482 return 0;
483}
484
485static void spca500_ping310(struct gspca_dev *gspca_dev)
486{
487 reg_r(gspca_dev, 0x0d04, 2);
488 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
489 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
490}
491
492static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
493{
494 reg_r(gspca_dev, 0x0d05, 2);
495 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
496 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
497 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
498 spca500_ping310(gspca_dev);
499
500 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
501 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
502 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
503 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
504 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
505 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
506 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
507 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
508 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
509 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
510 /* 00 for adjust shutter */
511 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
512 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
513 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
514}
515
516static void spca500_setmode(struct gspca_dev *gspca_dev,
517 __u8 xmult, __u8 ymult)
518{
519 int mode;
520
521 /* set x multiplier */
522 reg_w(gspca_dev, 0, 0x8001, xmult);
523
524 /* set y multiplier */
525 reg_w(gspca_dev, 0, 0x8002, ymult);
526
527 /* use compressed mode, VGA, with mode specific subsample */
528 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
529 reg_w(gspca_dev, 0, 0x8003, mode << 4);
530}
531
532static int spca500_full_reset(struct gspca_dev *gspca_dev)
533{
534 int err;
535
536 /* send the reset command */
537 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
538 if (err < 0)
539 return err;
540
541 /* wait for the reset to complete */
542 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
543 if (err < 0)
544 return err;
545 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
546 if (err < 0)
547 return err;
548 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
549 if (err < 0) {
550 PDEBUG(D_ERR, "reg_r_wait() failed");
551 return err;
552 }
553 /* all ok */
554 return 0;
555}
556
557/* Synchro the Bridge with sensor */
558/* Maybe that will work on all spca500 chip */
559/* because i only own a clicksmart310 try for that chip */
560/* using spca50x_set_packet_size() cause an Ooops here */
561/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
562/* up-port the same feature as in 2.4.x kernel */
563static int spca500_synch310(struct gspca_dev *gspca_dev)
564{
565 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
566 PDEBUG(D_ERR, "Set packet size: set interface error");
567 goto error;
568 }
569 spca500_ping310(gspca_dev);
570
571 reg_r(gspca_dev, 0x0d00, 1);
572
573 /* need alt setting here */
574 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
575
576 /* Windoze use pipe with altsetting 6 why 7 here */
577 if (usb_set_interface(gspca_dev->dev,
578 gspca_dev->iface,
579 gspca_dev->alt) < 0) {
580 PDEBUG(D_ERR, "Set packet size: set interface error");
581 goto error;
582 }
583 return 0;
584error:
585 return -EBUSY;
586}
587
588static void spca500_reinit(struct gspca_dev *gspca_dev)
589{
590 int err;
591 __u8 Data;
592
593 /* some unknow command from Aiptek pocket dv and family300 */
594
595 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
596 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
597 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
598
599 /* enable drop packet */
600 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
601
602 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
603 qtable_pocketdv);
604 if (err < 0)
605 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
606
607 /* set qtable index */
608 reg_w(gspca_dev, 0x00, 0x8880, 2);
609 /* family cam Quicksmart stuff */
610 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
611 /* Set agc transfer: synced inbetween frames */
612 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
613 /* Init SDRAM - needed for SDRAM access */
614 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
615 /*Start init sequence or stream */
616 reg_w(gspca_dev, 0, 0x8003, 0x00);
617 /* switch to video camera mode */
618 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
619 msleep(2000);
620 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
621 reg_r(gspca_dev, 0x816b, 1);
622 Data = gspca_dev->usb_buf[0];
623 reg_w(gspca_dev, 0x00, 0x816b, Data);
624 }
625}
626
627/* this function is called at probe time */
628static int sd_config(struct gspca_dev *gspca_dev,
629 const struct usb_device_id *id)
630{
631 struct sd *sd = (struct sd *) gspca_dev;
632 struct cam *cam;
633 __u16 vendor;
634 __u16 product;
635
636 vendor = id->idVendor;
637 product = id->idProduct;
638 switch (vendor) {
639 case 0x040a: /* Kodak cameras */
640/* switch (product) { */
641/* case 0x0300: */
642 sd->subtype = KodakEZ200;
643/* break; */
644/* } */
645 break;
646 case 0x041e: /* Creative cameras */
647/* switch (product) { */
648/* case 0x400a: */
649 sd->subtype = CreativePCCam300;
650/* break; */
651/* } */
652 break;
653 case 0x046d: /* Logitech Labtec */
654 switch (product) {
655 case 0x0890:
656 sd->subtype = LogitechTraveler;
657 break;
658 case 0x0900:
659 sd->subtype = LogitechClickSmart310;
660 break;
661 case 0x0901:
662 sd->subtype = LogitechClickSmart510;
663 break;
664 }
665 break;
666 case 0x04a5: /* Benq */
667/* switch (product) { */
668/* case 0x300c: */
669 sd->subtype = BenqDC1016;
670/* break; */
671/* } */
672 break;
673 case 0x04fc: /* SunPlus */
674/* switch (product) { */
675/* case 0x7333: */
676 sd->subtype = PalmPixDC85;
677/* break; */
678/* } */
679 break;
680 case 0x055f: /* Mustek cameras */
681 switch (product) {
682 case 0xc200:
683 sd->subtype = MustekGsmart300;
684 break;
685 case 0xc220:
686 sd->subtype = Gsmartmini;
687 break;
688 }
689 break;
690 case 0x06bd: /* Agfa Cl20 */
691/* switch (product) { */
692/* case 0x0404: */
693 sd->subtype = AgfaCl20;
694/* break; */
695/* } */
696 break;
697 case 0x06be: /* Optimedia */
698/* switch (product) { */
699/* case 0x0800: */
700 sd->subtype = Optimedia;
701/* break; */
702/* } */
703 break;
704 case 0x084d: /* D-Link / Minton */
705/* switch (product) { */
706/* case 0x0003: * DSC-350 / S-Cam F5 */
707 sd->subtype = DLinkDSC350;
708/* break; */
709/* } */
710 break;
711 case 0x08ca: /* Aiptek */
712/* switch (product) { */
713/* case 0x0103: */
714 sd->subtype = AiptekPocketDV;
715/* break; */
716/* } */
717 break;
718 case 0x2899: /* ToptroIndustrial */
719/* switch (product) { */
720/* case 0x012c: */
721 sd->subtype = ToptroIndus;
722/* break; */
723/* } */
724 break;
725 case 0x8086: /* Intel */
726/* switch (product) { */
727/* case 0x0630: * Pocket PC Camera */
728 sd->subtype = IntelPocketPCCamera;
729/* break; */
730/* } */
731 break;
732 }
733 cam = &gspca_dev->cam;
734 cam->dev_name = (char *) id->driver_info;
735 cam->epaddr = 0x01;
736 if (sd->subtype != LogitechClickSmart310) {
737 cam->cam_mode = vga_mode;
738 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
739 } else {
740 cam->cam_mode = sif_mode;
741 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
742 }
743 sd->qindex = 5;
744 sd->brightness = BRIGHTNESS_DEF;
745 sd->contrast = CONTRAST_DEF;
746 sd->colors = COLOR_DEF;
747 return 0;
748}
749
750/* this function is called at open time */
751static int sd_open(struct gspca_dev *gspca_dev)
752{
753 struct sd *sd = (struct sd *) gspca_dev;
754
755 /* initialisation of spca500 based cameras is deferred */
756 PDEBUG(D_STREAM, "SPCA500 init");
757 if (sd->subtype == LogitechClickSmart310)
758 spca500_clksmart310_init(gspca_dev);
759/* else
760 spca500_initialise(gspca_dev); */
761 PDEBUG(D_STREAM, "SPCA500 init done");
762 return 0;
763}
764
765static void sd_start(struct gspca_dev *gspca_dev)
766{
767 struct sd *sd = (struct sd *) gspca_dev;
768 int err;
769 __u8 Data;
770 __u8 xmult, ymult;
771
772 if (sd->subtype == LogitechClickSmart310) {
773 xmult = 0x16;
774 ymult = 0x12;
775 } else {
776 xmult = 0x28;
777 ymult = 0x1e;
778 }
779
780 /* is there a sensor here ? */
781 reg_r(gspca_dev, 0x8a04, 1);
782 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
783 gspca_dev->usb_buf[0]);
784 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
785 gspca_dev->curr_mode, xmult, ymult);
786
787 /* setup qtable */
788 switch (sd->subtype) {
789 case LogitechClickSmart310:
790 spca500_setmode(gspca_dev, xmult, ymult);
791
792 /* enable drop packet */
793 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
794 reg_w(gspca_dev, 0x00, 0x8880, 3);
795 err = spca50x_setup_qtable(gspca_dev,
796 0x00, 0x8800, 0x8840,
797 qtable_creative_pccam);
798 if (err < 0)
799 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
800 /* Init SDRAM - needed for SDRAM access */
801 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
802
803 /* switch to video camera mode */
804 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
805 msleep(500);
806 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
807 PDEBUG(D_ERR, "reg_r_wait() failed");
808
809 reg_r(gspca_dev, 0x816b, 1);
810 Data = gspca_dev->usb_buf[0];
811 reg_w(gspca_dev, 0x00, 0x816b, Data);
812
813 spca500_synch310(gspca_dev);
814
815 write_vector(gspca_dev, spca500_visual_defaults);
816 spca500_setmode(gspca_dev, xmult, ymult);
817 /* enable drop packet */
818 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
819 PDEBUG(D_ERR, "failed to enable drop packet");
820 reg_w(gspca_dev, 0x00, 0x8880, 3);
821 err = spca50x_setup_qtable(gspca_dev,
822 0x00, 0x8800, 0x8840,
823 qtable_creative_pccam);
824 if (err < 0)
825 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
826
827 /* Init SDRAM - needed for SDRAM access */
828 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
829
830 /* switch to video camera mode */
831 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
832
833 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
834 PDEBUG(D_ERR, "reg_r_wait() failed");
835
836 reg_r(gspca_dev, 0x816b, 1);
837 Data = gspca_dev->usb_buf[0];
838 reg_w(gspca_dev, 0x00, 0x816b, Data);
839 break;
840 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
841 case IntelPocketPCCamera: /* FIXME: Temporary fix for
842 * Intel Pocket PC Camera
843 * - NWG (Sat 29th March 2003) */
844
845 /* do a full reset */
846 err = spca500_full_reset(gspca_dev);
847 if (err < 0)
848 PDEBUG(D_ERR, "spca500_full_reset failed");
849
850 /* enable drop packet */
851 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
852 if (err < 0)
853 PDEBUG(D_ERR, "failed to enable drop packet");
854 reg_w(gspca_dev, 0x00, 0x8880, 3);
855 err = spca50x_setup_qtable(gspca_dev,
856 0x00, 0x8800, 0x8840,
857 qtable_creative_pccam);
858 if (err < 0)
859 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
860
861 spca500_setmode(gspca_dev, xmult, ymult);
862 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
863
864 /* switch to video camera mode */
865 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
866
867 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
868 PDEBUG(D_ERR, "reg_r_wait() failed");
869
870 reg_r(gspca_dev, 0x816b, 1);
871 Data = gspca_dev->usb_buf[0];
872 reg_w(gspca_dev, 0x00, 0x816b, Data);
873
874/* write_vector(gspca_dev, spca500_visual_defaults); */
875 break;
876 case KodakEZ200: /* Kodak EZ200 */
877
878 /* do a full reset */
879 err = spca500_full_reset(gspca_dev);
880 if (err < 0)
881 PDEBUG(D_ERR, "spca500_full_reset failed");
882 /* enable drop packet */
883 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
884 reg_w(gspca_dev, 0x00, 0x8880, 0);
885 err = spca50x_setup_qtable(gspca_dev,
886 0x00, 0x8800, 0x8840,
887 qtable_kodak_ez200);
888 if (err < 0)
889 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
890 spca500_setmode(gspca_dev, xmult, ymult);
891
892 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
893
894 /* switch to video camera mode */
895 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
896
897 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
898 PDEBUG(D_ERR, "reg_r_wait() failed");
899
900 reg_r(gspca_dev, 0x816b, 1);
901 Data = gspca_dev->usb_buf[0];
902 reg_w(gspca_dev, 0x00, 0x816b, Data);
903
904/* write_vector(gspca_dev, spca500_visual_defaults); */
905 break;
906
907 case BenqDC1016:
908 case DLinkDSC350: /* FamilyCam 300 */
909 case AiptekPocketDV: /* Aiptek PocketDV */
910 case Gsmartmini: /*Mustek Gsmart Mini */
911 case MustekGsmart300: /* Mustek Gsmart 300 */
912 case PalmPixDC85:
913 case Optimedia:
914 case ToptroIndus:
915 case AgfaCl20:
916 spca500_reinit(gspca_dev);
917 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
918 /* enable drop packet */
919 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
920
921 err = spca50x_setup_qtable(gspca_dev,
922 0x00, 0x8800, 0x8840, qtable_pocketdv);
923 if (err < 0)
924 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
925 reg_w(gspca_dev, 0x00, 0x8880, 2);
926
927 /* familycam Quicksmart pocketDV stuff */
928 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
929 /* Set agc transfer: synced inbetween frames */
930 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
931 /* Init SDRAM - needed for SDRAM access */
932 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
933
934 spca500_setmode(gspca_dev, xmult, ymult);
935 /* switch to video camera mode */
936 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
937
938 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
939
940 reg_r(gspca_dev, 0x816b, 1);
941 Data = gspca_dev->usb_buf[0];
942 reg_w(gspca_dev, 0x00, 0x816b, Data);
943 break;
944 case LogitechTraveler:
945 case LogitechClickSmart510:
946 reg_w(gspca_dev, 0x02, 0x00, 0x00);
947 /* enable drop packet */
948 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
949
950 err = spca50x_setup_qtable(gspca_dev,
951 0x00, 0x8800,
952 0x8840, qtable_creative_pccam);
953 if (err < 0)
954 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
955 reg_w(gspca_dev, 0x00, 0x8880, 3);
956 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
957 /* Init SDRAM - needed for SDRAM access */
958 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
959
960 spca500_setmode(gspca_dev, xmult, ymult);
961
962 /* switch to video camera mode */
963 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
964 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
965
966 reg_r(gspca_dev, 0x816b, 1);
967 Data = gspca_dev->usb_buf[0];
968 reg_w(gspca_dev, 0x00, 0x816b, Data);
969 write_vector(gspca_dev, Clicksmart510_defaults);
970 break;
971 }
972}
973
974static void sd_stopN(struct gspca_dev *gspca_dev)
975{
976 reg_w(gspca_dev, 0, 0x8003, 0x00);
977
978 /* switch to video camera mode */
979 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
980 reg_r(gspca_dev, 0x8000, 1);
981 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
982 gspca_dev->usb_buf[0]);
983}
984
985static void sd_stop0(struct gspca_dev *gspca_dev)
986{
987}
988
989static void sd_close(struct gspca_dev *gspca_dev)
990{
991}
992
993static void sd_pkt_scan(struct gspca_dev *gspca_dev,
994 struct gspca_frame *frame, /* target */
995 __u8 *data, /* isoc packet */
996 int len) /* iso packet length */
997{
998 struct sd *sd = (struct sd *) gspca_dev;
999 int i;
1000 __u8 *s, *d;
1001 static __u8 ffd9[] = {0xff, 0xd9};
1002
1003/* frames are jpeg 4.1.1 without 0xff escape */
1004 if (data[0] == 0xff) {
1005 if (data[1] != 0x01) { /* drop packet */
1006/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1007 return;
1008 }
1009 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1010 ffd9, 2);
1011
1012 /* put the JPEG header in the new frame */
1013 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x22);
1014
1015 data += SPCA500_OFFSET_DATA;
1016 len -= SPCA500_OFFSET_DATA;
1017 } else {
1018 data += 1;
1019 len -= 1;
1020 }
1021
1022 /* add 0x00 after 0xff */
1023 for (i = len; --i >= 0; )
1024 if (data[i] == 0xff)
1025 break;
1026 if (i < 0) { /* no 0xff */
1027 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1028 return;
1029 }
1030 s = data;
1031 d = sd->packet;
1032 for (i = 0; i < len; i++) {
1033 *d++ = *s++;
1034 if (s[-1] == 0xff)
1035 *d++ = 0x00;
1036 }
1037 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1038 sd->packet, d - sd->packet);
1039}
1040
1041static void setbrightness(struct gspca_dev *gspca_dev)
1042{
1043 struct sd *sd = (struct sd *) gspca_dev;
1044
1045 reg_w(gspca_dev, 0x00, 0x8167,
1046 (__u8) (sd->brightness - 128));
1047}
1048
1049static void getbrightness(struct gspca_dev *gspca_dev)
1050{
1051 struct sd *sd = (struct sd *) gspca_dev;
1052 int ret;
1053
1054 ret = reg_r_12(gspca_dev, 0x00, 0x8167, 1);
1055 if (ret >= 0)
1056 sd->brightness = ret + 128;
1057}
1058
1059static void setcontrast(struct gspca_dev *gspca_dev)
1060{
1061 struct sd *sd = (struct sd *) gspca_dev;
1062
1063 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
1064}
1065
1066static void getcontrast(struct gspca_dev *gspca_dev)
1067{
1068 struct sd *sd = (struct sd *) gspca_dev;
1069 int ret;
1070
1071 ret = reg_r_12(gspca_dev, 0x0, 0x8168, 1);
1072 if (ret >= 0)
1073 sd->contrast = ret;
1074}
1075
1076static void setcolors(struct gspca_dev *gspca_dev)
1077{
1078 struct sd *sd = (struct sd *) gspca_dev;
1079
1080 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
1081}
1082
1083static void getcolors(struct gspca_dev *gspca_dev)
1084{
1085 struct sd *sd = (struct sd *) gspca_dev;
1086 int ret;
1087
1088 ret = reg_r_12(gspca_dev, 0x0, 0x8169, 1);
1089 if (ret >= 0)
1090 sd->colors = ret;
1091}
1092
1093static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1094{
1095 struct sd *sd = (struct sd *) gspca_dev;
1096
1097 sd->brightness = val;
1098 if (gspca_dev->streaming)
1099 setbrightness(gspca_dev);
1100 return 0;
1101}
1102
1103static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1104{
1105 struct sd *sd = (struct sd *) gspca_dev;
1106
1107 getbrightness(gspca_dev);
1108 *val = sd->brightness;
1109 return 0;
1110}
1111
1112static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1113{
1114 struct sd *sd = (struct sd *) gspca_dev;
1115
1116 sd->contrast = val;
1117 if (gspca_dev->streaming)
1118 setcontrast(gspca_dev);
1119 return 0;
1120}
1121
1122static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1123{
1124 struct sd *sd = (struct sd *) gspca_dev;
1125
1126 getcontrast(gspca_dev);
1127 *val = sd->contrast;
1128 return 0;
1129}
1130
1131static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1132{
1133 struct sd *sd = (struct sd *) gspca_dev;
1134
1135 sd->colors = val;
1136 if (gspca_dev->streaming)
1137 setcolors(gspca_dev);
1138 return 0;
1139}
1140
1141static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1142{
1143 struct sd *sd = (struct sd *) gspca_dev;
1144
1145 getcolors(gspca_dev);
1146 *val = sd->colors;
1147 return 0;
1148}
1149
1150/* sub-driver description */
1151static struct sd_desc sd_desc = {
1152 .name = MODULE_NAME,
1153 .ctrls = sd_ctrls,
1154 .nctrls = ARRAY_SIZE(sd_ctrls),
1155 .config = sd_config,
1156 .open = sd_open,
1157 .start = sd_start,
1158 .stopN = sd_stopN,
1159 .stop0 = sd_stop0,
1160 .close = sd_close,
1161 .pkt_scan = sd_pkt_scan,
1162};
1163
1164/* -- module initialisation -- */
1165#define DVNM(name) .driver_info = (kernel_ulong_t) name
1166static const __devinitdata struct usb_device_id device_table[] = {
1167 {USB_DEVICE(0x040a, 0x0300), DVNM("Kodak EZ200")},
1168 {USB_DEVICE(0x041e, 0x400a), DVNM("Creative PC-CAM 300")},
1169 {USB_DEVICE(0x046d, 0x0890), DVNM("Logitech QuickCam traveler")},
1170 {USB_DEVICE(0x046d, 0x0900), DVNM("Logitech Inc. ClickSmart 310")},
1171 {USB_DEVICE(0x046d, 0x0901), DVNM("Logitech Inc. ClickSmart 510")},
1172 {USB_DEVICE(0x04a5, 0x300c), DVNM("Benq DC1016")},
1173 {USB_DEVICE(0x04fc, 0x7333), DVNM("PalmPixDC85")},
1174 {USB_DEVICE(0x055f, 0xc200), DVNM("Mustek Gsmart 300")},
1175 {USB_DEVICE(0x055f, 0xc220), DVNM("Gsmart Mini")},
1176 {USB_DEVICE(0x06bd, 0x0404), DVNM("Agfa CL20")},
1177 {USB_DEVICE(0x06be, 0x0800), DVNM("Optimedia")},
1178 {USB_DEVICE(0x084d, 0x0003), DVNM("D-Link DSC-350")},
1179 {USB_DEVICE(0x08ca, 0x0103), DVNM("Aiptek PocketDV")},
1180 {USB_DEVICE(0x2899, 0x012c), DVNM("Toptro Industrial")},
1181 {USB_DEVICE(0x8086, 0x0630), DVNM("Intel Pocket PC Camera")},
1182 {}
1183};
1184MODULE_DEVICE_TABLE(usb, device_table);
1185
1186/* -- device connect -- */
1187static int sd_probe(struct usb_interface *intf,
1188 const struct usb_device_id *id)
1189{
1190 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1191 THIS_MODULE);
1192}
1193
1194static struct usb_driver sd_driver = {
1195 .name = MODULE_NAME,
1196 .id_table = device_table,
1197 .probe = sd_probe,
1198 .disconnect = gspca_disconnect,
1199};
1200
1201/* -- module insert / remove -- */
1202static int __init sd_mod_init(void)
1203{
1204 if (usb_register(&sd_driver) < 0)
1205 return -1;
1206 PDEBUG(D_PROBE, "v%s registered", version);
1207 return 0;
1208}
1209static void __exit sd_mod_exit(void)
1210{
1211 usb_deregister(&sd_driver);
1212 PDEBUG(D_PROBE, "deregistered");
1213}
1214
1215module_init(sd_mod_init);
1216module_exit(sd_mod_exit);