2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
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
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.
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
22 #define MODULE_NAME "sunplus"
27 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 1)
28 static const char version[] = "2.1.1";
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
32 MODULE_LICENSE("GPL");
34 /* specific webcam descriptor */
36 struct gspca_dev gspca_dev; /* !! must be the first item */
38 unsigned char packet[ISO_MAX_SIZE + 128];
39 /* !! no more than 128 ff in an ISO packet */
41 unsigned char brightness;
42 unsigned char contrast;
44 unsigned char autogain;
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
54 #define AiptekMiniPenCam13 1
55 #define LogitechClickSmart420 2
56 #define LogitechClickSmart820 3
60 /* V4L2 controls supported by the driver */
61 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
62 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
63 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
70 static struct ctrl sd_ctrls[] = {
71 #define SD_BRIGHTNESS 0
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
82 .set = sd_setbrightness,
83 .get = sd_getbrightness,
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
94 .default_value = 0x20,
96 .set = sd_setcontrast,
97 .get = sd_getcontrast,
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
108 .default_value = 0x1a,
113 #define SD_AUTOGAIN 3
116 .id = V4L2_CID_AUTOGAIN,
117 .type = V4L2_CTRL_TYPE_BOOLEAN,
124 .set = sd_setautogain,
125 .get = sd_getautogain,
129 static struct cam_mode vga_mode[] = {
130 {V4L2_PIX_FMT_JPEG, 320, 240, 2},
131 {V4L2_PIX_FMT_JPEG, 640, 480, 1},
134 static struct cam_mode custom_mode[] = {
135 {V4L2_PIX_FMT_JPEG, 320, 240, 2},
136 {V4L2_PIX_FMT_JPEG, 464, 480, 1},
139 static struct cam_mode vga_mode2[] = {
140 {V4L2_PIX_FMT_JPEG, 176, 144, 4},
141 {V4L2_PIX_FMT_JPEG, 320, 240, 3},
142 {V4L2_PIX_FMT_JPEG, 352, 288, 2},
143 {V4L2_PIX_FMT_JPEG, 640, 480, 1},
146 #define SPCA50X_OFFSET_DATA 10
147 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
148 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
149 #define SPCA504_PCCAM600_OFFSET_MODE 5
150 #define SPCA504_PCCAM600_OFFSET_DATA 14
151 /* Frame packet header offsets for the spca533 */
152 #define SPCA533_OFFSET_DATA 16
153 #define SPCA533_OFFSET_FRAMSEQ 15
154 /* Frame packet header offsets for the spca536 */
155 #define SPCA536_OFFSET_DATA 4
156 #define SPCA536_OFFSET_FRAMSEQ 1
158 /* Initialisation data for the Creative PC-CAM 600 */
159 static __u16 spca504_pccam600_init_data[][3] = {
160 /* {0xa0, 0x0000, 0x0503}, * capture mode */
161 {0x00, 0x0000, 0x2000},
162 {0x00, 0x0013, 0x2301},
163 {0x00, 0x0003, 0x2000},
164 {0x00, 0x0001, 0x21ac},
165 {0x00, 0x0001, 0x21a6},
166 {0x00, 0x0000, 0x21a7}, /* brightness */
167 {0x00, 0x0020, 0x21a8}, /* contrast */
168 {0x00, 0x0001, 0x21ac}, /* sat/hue */
169 {0x00, 0x0000, 0x21ad}, /* hue */
170 {0x00, 0x001a, 0x21ae}, /* saturation */
171 {0x00, 0x0002, 0x21a3}, /* gamma */
172 {0x30, 0x0154, 0x0008},
173 {0x30, 0x0004, 0x0006},
174 {0x30, 0x0258, 0x0009},
175 {0x30, 0x0004, 0x0000},
176 {0x30, 0x0093, 0x0004},
177 {0x30, 0x0066, 0x0005},
178 {0x00, 0x0000, 0x2000},
179 {0x00, 0x0013, 0x2301},
180 {0x00, 0x0003, 0x2000},
181 {0x00, 0x0013, 0x2301},
182 {0x00, 0x0003, 0x2000},
186 /* Creative PC-CAM 600 specific open data, sent before using the
187 * generic initialisation data from spca504_open_data.
189 static __u16 spca504_pccam600_open_data[][3] = {
190 {0x00, 0x0001, 0x2501},
191 {0x20, 0x0500, 0x0001}, /* snapshot mode */
192 {0x00, 0x0003, 0x2880},
193 {0x00, 0x0001, 0x2881},
197 /* Initialisation data for the logitech clicksmart 420 */
198 static __u16 spca504A_clicksmart420_init_data[][3] = {
199 /* {0xa0, 0x0000, 0x0503}, * capture mode */
200 {0x00, 0x0000, 0x2000},
201 {0x00, 0x0013, 0x2301},
202 {0x00, 0x0003, 0x2000},
203 {0x00, 0x0001, 0x21ac},
204 {0x00, 0x0001, 0x21a6},
205 {0x00, 0x0000, 0x21a7}, /* brightness */
206 {0x00, 0x0020, 0x21a8}, /* contrast */
207 {0x00, 0x0001, 0x21ac}, /* sat/hue */
208 {0x00, 0x0000, 0x21ad}, /* hue */
209 {0x00, 0x001a, 0x21ae}, /* saturation */
210 {0x00, 0x0002, 0x21a3}, /* gamma */
211 {0x30, 0x0004, 0x000a},
212 {0xb0, 0x0001, 0x0000},
215 {0x0a1, 0x0080, 0x0001},
216 {0x30, 0x0049, 0x0000},
217 {0x30, 0x0060, 0x0005},
218 {0x0c, 0x0004, 0x0000},
219 {0x00, 0x0000, 0x0000},
220 {0x00, 0x0000, 0x2000},
221 {0x00, 0x0013, 0x2301},
222 {0x00, 0x0003, 0x2000},
223 {0x00, 0x0000, 0x2000},
228 /* clicksmart 420 open data ? */
229 static __u16 spca504A_clicksmart420_open_data[][3] = {
230 {0x00, 0x0001, 0x2501},
231 {0x20, 0x0502, 0x0000},
232 {0x06, 0x0000, 0x0000},
233 {0x00, 0x0004, 0x2880},
234 {0x00, 0x0001, 0x2881},
235 /* look like setting a qTable */
236 {0x00, 0x0006, 0x2800},
237 {0x00, 0x0004, 0x2801},
238 {0x00, 0x0004, 0x2802},
239 {0x00, 0x0006, 0x2803},
240 {0x00, 0x000a, 0x2804},
241 {0x00, 0x0010, 0x2805},
242 {0x00, 0x0014, 0x2806},
243 {0x00, 0x0018, 0x2807},
244 {0x00, 0x0005, 0x2808},
245 {0x00, 0x0005, 0x2809},
246 {0x00, 0x0006, 0x280a},
247 {0x00, 0x0008, 0x280b},
248 {0x00, 0x000a, 0x280c},
249 {0x00, 0x0017, 0x280d},
250 {0x00, 0x0018, 0x280e},
251 {0x00, 0x0016, 0x280f},
253 {0x00, 0x0006, 0x2810},
254 {0x00, 0x0005, 0x2811},
255 {0x00, 0x0006, 0x2812},
256 {0x00, 0x000a, 0x2813},
257 {0x00, 0x0010, 0x2814},
258 {0x00, 0x0017, 0x2815},
259 {0x00, 0x001c, 0x2816},
260 {0x00, 0x0016, 0x2817},
261 {0x00, 0x0006, 0x2818},
262 {0x00, 0x0007, 0x2819},
263 {0x00, 0x0009, 0x281a},
264 {0x00, 0x000c, 0x281b},
265 {0x00, 0x0014, 0x281c},
266 {0x00, 0x0023, 0x281d},
267 {0x00, 0x0020, 0x281e},
268 {0x00, 0x0019, 0x281f},
270 {0x00, 0x0007, 0x2820},
271 {0x00, 0x0009, 0x2821},
272 {0x00, 0x000f, 0x2822},
273 {0x00, 0x0016, 0x2823},
274 {0x00, 0x001b, 0x2824},
275 {0x00, 0x002c, 0x2825},
276 {0x00, 0x0029, 0x2826},
277 {0x00, 0x001f, 0x2827},
278 {0x00, 0x000a, 0x2828},
279 {0x00, 0x000e, 0x2829},
280 {0x00, 0x0016, 0x282a},
281 {0x00, 0x001a, 0x282b},
282 {0x00, 0x0020, 0x282c},
283 {0x00, 0x002a, 0x282d},
284 {0x00, 0x002d, 0x282e},
285 {0x00, 0x0025, 0x282f},
287 {0x00, 0x0014, 0x2830},
288 {0x00, 0x001a, 0x2831},
289 {0x00, 0x001f, 0x2832},
290 {0x00, 0x0023, 0x2833},
291 {0x00, 0x0029, 0x2834},
292 {0x00, 0x0030, 0x2835},
293 {0x00, 0x0030, 0x2836},
294 {0x00, 0x0028, 0x2837},
295 {0x00, 0x001d, 0x2838},
296 {0x00, 0x0025, 0x2839},
297 {0x00, 0x0026, 0x283a},
298 {0x00, 0x0027, 0x283b},
299 {0x00, 0x002d, 0x283c},
300 {0x00, 0x0028, 0x283d},
301 {0x00, 0x0029, 0x283e},
302 {0x00, 0x0028, 0x283f},
304 {0x00, 0x0007, 0x2840},
305 {0x00, 0x0007, 0x2841},
306 {0x00, 0x000a, 0x2842},
307 {0x00, 0x0013, 0x2843},
308 {0x00, 0x0028, 0x2844},
309 {0x00, 0x0028, 0x2845},
310 {0x00, 0x0028, 0x2846},
311 {0x00, 0x0028, 0x2847},
312 {0x00, 0x0007, 0x2848},
313 {0x00, 0x0008, 0x2849},
314 {0x00, 0x000a, 0x284a},
315 {0x00, 0x001a, 0x284b},
316 {0x00, 0x0028, 0x284c},
317 {0x00, 0x0028, 0x284d},
318 {0x00, 0x0028, 0x284e},
319 {0x00, 0x0028, 0x284f},
321 {0x00, 0x000a, 0x2850},
322 {0x00, 0x000a, 0x2851},
323 {0x00, 0x0016, 0x2852},
324 {0x00, 0x0028, 0x2853},
325 {0x00, 0x0028, 0x2854},
326 {0x00, 0x0028, 0x2855},
327 {0x00, 0x0028, 0x2856},
328 {0x00, 0x0028, 0x2857},
329 {0x00, 0x0013, 0x2858},
330 {0x00, 0x001a, 0x2859},
331 {0x00, 0x0028, 0x285a},
332 {0x00, 0x0028, 0x285b},
333 {0x00, 0x0028, 0x285c},
334 {0x00, 0x0028, 0x285d},
335 {0x00, 0x0028, 0x285e},
336 {0x00, 0x0028, 0x285f},
338 {0x00, 0x0028, 0x2860},
339 {0x00, 0x0028, 0x2861},
340 {0x00, 0x0028, 0x2862},
341 {0x00, 0x0028, 0x2863},
342 {0x00, 0x0028, 0x2864},
343 {0x00, 0x0028, 0x2865},
344 {0x00, 0x0028, 0x2866},
345 {0x00, 0x0028, 0x2867},
346 {0x00, 0x0028, 0x2868},
347 {0x00, 0x0028, 0x2869},
348 {0x00, 0x0028, 0x286a},
349 {0x00, 0x0028, 0x286b},
350 {0x00, 0x0028, 0x286c},
351 {0x00, 0x0028, 0x286d},
352 {0x00, 0x0028, 0x286e},
353 {0x00, 0x0028, 0x286f},
355 {0x00, 0x0028, 0x2870},
356 {0x00, 0x0028, 0x2871},
357 {0x00, 0x0028, 0x2872},
358 {0x00, 0x0028, 0x2873},
359 {0x00, 0x0028, 0x2874},
360 {0x00, 0x0028, 0x2875},
361 {0x00, 0x0028, 0x2876},
362 {0x00, 0x0028, 0x2877},
363 {0x00, 0x0028, 0x2878},
364 {0x00, 0x0028, 0x2879},
365 {0x00, 0x0028, 0x287a},
366 {0x00, 0x0028, 0x287b},
367 {0x00, 0x0028, 0x287c},
368 {0x00, 0x0028, 0x287d},
369 {0x00, 0x0028, 0x287e},
370 {0x00, 0x0028, 0x287f},
372 {0xa0, 0x0000, 0x0503},
376 static unsigned char qtable_creative_pccam[2][64] = {
377 { /* Q-table Y-components */
378 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
379 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
380 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
381 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
382 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
383 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
384 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
385 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
386 { /* Q-table C-components */
387 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
388 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
389 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
390 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
391 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
392 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
393 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
394 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
397 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
398 * except for one byte. Possibly a typo?
401 static unsigned char qtable_spca504_default[2][64] = {
402 { /* Q-table Y-components */
403 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
404 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
405 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
406 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
407 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
408 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
409 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
410 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
412 { /* Q-table C-components */
413 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
414 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
415 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
416 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
417 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
418 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
419 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
420 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
423 static void spca5xxRegRead(struct usb_device *dev,
426 __u8 *buffer, __u16 length)
429 usb_rcvctrlpipe(dev, 0),
431 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
433 index, buffer, length,
437 static void spca5xxRegWrite(struct usb_device *dev,
441 __u8 *buffer, __u16 length)
444 usb_sndctrlpipe(dev, 0),
446 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
447 value, index, buffer, length,
451 static int reg_write(struct usb_device *dev,
452 __u16 req, __u16 index, __u16 value)
456 ret = usb_control_msg(dev,
457 usb_sndctrlpipe(dev, 0),
459 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
460 value, index, NULL, 0, 500);
461 PDEBUG(D_PACK, "reg write: 0x%02x,0x%02x:0x%02x, 0x%x",
462 req, index, value, ret);
464 PDEBUG(D_ERR, "reg write: error %d", ret);
468 static int reg_read_info(struct usb_device *dev,
469 __u16 value) /* wValue */
474 ret = usb_control_msg(dev,
475 usb_rcvctrlpipe(dev, 0),
477 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
483 PDEBUG(D_ERR, "reg_read_info err %d", ret);
489 /* returns: negative is error, pos or zero is data */
490 static int reg_read(struct usb_device *dev,
491 __u16 req, /* bRequest */
492 __u16 index, /* wIndex */
493 __u16 length) /* wLength (1 or 2 only) */
499 ret = usb_control_msg(dev,
500 usb_rcvctrlpipe(dev, 0),
502 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
508 PDEBUG(D_ERR, "reg_read err %d", ret);
511 return (buf[1] << 8) + buf[0];
514 static int write_vector(struct gspca_dev *gspca_dev,
517 struct usb_device *dev = gspca_dev->dev;
520 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
521 ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
524 "Register write failed for 0x%x,0x%x,0x%x",
525 data[i][0], data[i][1], data[i][2]);
533 static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
534 unsigned int request,
537 unsigned char qtable[2][64])
539 struct usb_device *dev = gspca_dev->dev;
542 /* loop over y components */
543 for (i = 0; i < 64; i++) {
544 err = reg_write(dev, request, ybase + i, qtable[0][i]);
549 /* loop over c components */
550 for (i = 0; i < 64; i++) {
551 err = reg_write(dev, request, cbase + i, qtable[1][i]);
558 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
559 __u16 req, __u16 idx, __u16 val)
561 struct usb_device *dev = gspca_dev->dev;
564 reg_write(dev, req, idx, val);
565 notdone = reg_read(dev, 0x01, 0x0001, 1);
566 reg_write(dev, req, idx, val);
568 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
571 notdone = reg_read(dev, 0x01, 0x0001, 1);
572 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
575 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
577 __u16 idx, __u16 val, __u8 stat, __u8 count)
579 struct usb_device *dev = gspca_dev->dev;
583 reg_write(dev, req, idx, val);
584 status = reg_read(dev, 0x01, 0x0001, 1);
586 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
590 while (--count > 0) {
592 /* gsmart mini2 write a each wait setting 1 ms is enought */
593 /* reg_write(dev, req, idx, val); */
594 status = reg_read(dev, 0x01, 0x0001, 1);
595 if (status == endcode) {
596 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
597 status, 200 - count);
603 static int spca504B_PollingDataReady(struct usb_device *dev)
608 while (--count > 0) {
609 spca5xxRegRead(dev, 0x21, 0, &DataReady, 1);
610 if ((DataReady & 0x01) == 0)
617 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
619 struct usb_device *dev = gspca_dev->dev;
623 while (--count > 0) {
624 spca5xxRegRead(dev, 0x21, 1, &DataReady, 1);
628 spca5xxRegWrite(dev, 0x21, 0, 1, &DataReady, 1);
629 spca5xxRegRead(dev, 0x21, 1, &DataReady, 1);
630 spca504B_PollingDataReady(dev);
637 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
639 struct usb_device *dev = gspca_dev->dev;
641 __u8 ProductInfo[64];
643 spca5xxRegRead(dev, 0x20, 0, FW, 5);
644 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
645 FW[0], FW[1], FW[2], FW[3], FW[4]);
646 spca5xxRegRead(dev, 0x23, 0, ProductInfo, 64);
647 spca5xxRegRead(dev, 0x23, 1, ProductInfo, 64);
650 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
652 struct sd *sd = (struct sd *) gspca_dev;
653 struct usb_device *dev = gspca_dev->dev;
658 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
660 switch (sd->bridge) {
662 spca5xxRegWrite(dev, 0x31, 0, 0, NULL, 0);
663 spca504B_WaitCmdStatus(gspca_dev);
664 rc = spca504B_PollingDataReady(dev);
665 spca50x_GetFirmware(gspca_dev);
667 spca5xxRegWrite(dev, 0x24, 0, 8, &Type, 1);
668 spca5xxRegRead(dev, 0x24, 8, &Type, 1);
670 spca5xxRegWrite(dev, 0x25, 0, 4, &Size, 1);
671 spca5xxRegRead(dev, 0x25, 4, &Size, 1);
672 rc = spca504B_PollingDataReady(dev);
674 /* Init the cam width height with some values get on init ? */
675 spca5xxRegWrite(dev, 0x31, 0, 4, NULL, 0);
676 spca504B_WaitCmdStatus(gspca_dev);
677 rc = spca504B_PollingDataReady(dev);
680 /* case BRIDGE_SPCA504B: */
681 /* case BRIDGE_SPCA536: */
683 spca5xxRegWrite(dev, 0x25, 0, 4, &Size, 1);
684 spca5xxRegRead(dev, 0x25, 4, &Size, 1);
685 spca5xxRegWrite(dev, 0x27, 0, 0, &Type, 1);
686 spca5xxRegRead(dev, 0x27, 0, &Type, 1);
687 rc = spca504B_PollingDataReady(dev);
691 if (sd->subtype == AiptekMiniPenCam13) {
692 /* spca504a aiptek */
693 spca504A_acknowledged_command(gspca_dev,
695 0x80 | (Size & 0x0f), 1);
696 spca504A_acknowledged_command(gspca_dev,
699 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
702 case BRIDGE_SPCA504C:
704 reg_write(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x0);
705 reg_write(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
710 static void spca504_wait_status(struct gspca_dev *gspca_dev)
712 struct usb_device *dev = gspca_dev->dev;
717 /* With this we get the status, when return 0 it's all ok */
718 if (reg_read(dev, 0x06, 0x00, 1) == 0)
724 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
726 struct usb_device *dev = gspca_dev->dev;
729 spca5xxRegWrite(dev, 0x26, 0, 0, &Data, 1);
730 spca5xxRegRead(dev, 0x26, 0, &Data, 1);
731 spca504B_PollingDataReady(dev);
734 static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
736 struct sd *sd = (struct sd *) gspca_dev;
737 struct usb_device *dev = gspca_dev->dev;
740 switch (sd->bridge) {
742 case BRIDGE_SPCA504C:
746 /* case BRIDGE_SPCA533: */
747 /* case BRIDGE_SPCA504B: */
748 spca5xxRegWrite(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
749 spca5xxRegWrite(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
750 spca5xxRegWrite(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
751 spca5xxRegWrite(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
752 spca5xxRegWrite(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
753 spca5xxRegWrite(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
756 spca5xxRegWrite(dev, 0, 0, 0x20f0, NULL, 0);
757 spca5xxRegWrite(dev, 0, 0x21, 0x20f1, NULL, 0);
758 spca5xxRegWrite(dev, 0, 0x40, 0x20f5, NULL, 0);
759 spca5xxRegWrite(dev, 0, 1, 0x20f4, NULL, 0);
760 spca5xxRegWrite(dev, 0, 0x40, 0x20f6, NULL, 0);
761 spca5xxRegWrite(dev, 0, 0, 0x2089, NULL, 0);
765 spca504B_PollingDataReady(dev);
768 /* this function is called at probe time */
769 static int sd_config(struct gspca_dev *gspca_dev,
770 const struct usb_device_id *id)
772 struct sd *sd = (struct sd *) gspca_dev;
773 struct usb_device *dev = gspca_dev->dev;
779 vendor = id->idVendor;
780 product = id->idProduct;
782 case 0x041e: /* Creative cameras */
783 /* switch (product) { */
787 /* sd->bridge = BRIDGE_SPCA504C; */
791 case 0x0458: /* Genius KYE cameras */
792 /* switch (product) { */
794 sd->bridge = BRIDGE_SPCA504B;
798 case 0x046d: /* Logitech Labtec */
801 sd->subtype = LogitechClickSmart820;
802 sd->bridge = BRIDGE_SPCA533;
805 sd->subtype = LogitechClickSmart420;
806 sd->bridge = BRIDGE_SPCA504C;
810 case 0x0471: /* Philips */
811 /* switch (product) { */
813 sd->bridge = BRIDGE_SPCA504B;
817 case 0x04a5: /* Benq */
820 sd->bridge = BRIDGE_SPCA504B;
824 sd->bridge = BRIDGE_SPCA533;
828 case 0x04f1: /* JVC */
829 /* switch (product) { */
831 sd->bridge = BRIDGE_SPCA504B;
835 case 0x04fc: /* SunPlus */
838 sd->bridge = BRIDGE_SPCA504B;
841 /* try to get the firmware as some cam answer 2.0.1.2.2
842 * and should be a spca504b then overwrite that setting */
843 spca5xxRegRead(dev, 0x20, 0, &fw, 1);
845 sd->subtype = AiptekMiniPenCam13;
846 sd->bridge = BRIDGE_SPCA504;
847 } else if (fw == 2) {
848 sd->bridge = BRIDGE_SPCA504B;
853 sd->bridge = BRIDGE_SPCA504B;
856 sd->bridge = BRIDGE_SPCA533;
859 sd->bridge = BRIDGE_SPCA536;
862 sd->bridge = BRIDGE_SPCA504B;
866 case 0x052b: /* ?? Megapix */
867 /* switch (product) { */
869 sd->subtype = MegapixV4;
870 sd->bridge = BRIDGE_SPCA533;
874 case 0x0546: /* Polaroid */
877 sd->bridge = BRIDGE_SPCA533;
881 sd->bridge = BRIDGE_SPCA504B;
885 case 0x055f: /* Mustek cameras */
888 sd->bridge = BRIDGE_SPCA536;
892 sd->bridge = BRIDGE_SPCA533;
895 sd->bridge = BRIDGE_SPCA536;
898 sd->bridge = BRIDGE_SPCA504;
902 sd->bridge = BRIDGE_SPCA533;
905 sd->bridge = BRIDGE_SPCA504;
911 sd->bridge = BRIDGE_SPCA533;
915 case 0x05da: /* Digital Dream cameras */
916 /* switch (product) { */
918 sd->bridge = BRIDGE_SPCA504B;
922 case 0x06d6: /* Trust */
923 /* switch (product) { */
925 sd->bridge = BRIDGE_SPCA533; /* SPCA533A */
929 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
935 sd->bridge = BRIDGE_SPCA533;
939 sd->bridge = BRIDGE_SPCA536;
943 case 0x08ca: /* Aiptek */
947 sd->bridge = BRIDGE_SPCA533;
950 sd->bridge = BRIDGE_SPCA504B;
953 sd->bridge = BRIDGE_SPCA533;
957 sd->bridge = BRIDGE_SPCA504B;
961 sd->bridge = BRIDGE_SPCA533;
964 sd->bridge = BRIDGE_SPCA536;
967 sd->bridge = BRIDGE_SPCA533;
972 sd->bridge = BRIDGE_SPCA536;
976 case 0x0d64: /* SunPlus */
977 /* switch (product) { */
979 sd->bridge = BRIDGE_SPCA536;
985 cam = &gspca_dev->cam;
986 cam->dev_name = (char *) id->driver_info;
989 switch (sd->bridge) {
991 /* case BRIDGE_SPCA504B: */
992 /* case BRIDGE_SPCA504: */
993 /* case BRIDGE_SPCA536: */
994 cam->cam_mode = vga_mode;
995 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
998 cam->cam_mode = custom_mode;
999 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
1001 case BRIDGE_SPCA504C:
1002 cam->cam_mode = vga_mode2;
1003 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
1006 sd->qindex = 5; /* set the quantization table */
1007 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1008 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1009 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1013 /* this function is called at open time */
1014 static int sd_open(struct gspca_dev *gspca_dev)
1016 struct sd *sd = (struct sd *) gspca_dev;
1017 struct usb_device *dev = gspca_dev->dev;
1024 switch (sd->bridge) {
1025 case BRIDGE_SPCA504B:
1026 spca5xxRegWrite(dev, 0x1d, 0, 0, NULL, 0);
1027 spca5xxRegWrite(dev, 0, 1, 0x2306, NULL, 0);
1028 spca5xxRegWrite(dev, 0, 0, 0x0d04, NULL, 0);
1029 spca5xxRegWrite(dev, 0, 0, 0x2000, NULL, 0);
1030 spca5xxRegWrite(dev, 0, 0x13, 0x2301, NULL, 0);
1031 spca5xxRegWrite(dev, 0, 0, 0x2306, NULL, 0);
1033 case BRIDGE_SPCA533:
1034 rc = spca504B_PollingDataReady(dev);
1035 spca50x_GetFirmware(gspca_dev);
1037 case BRIDGE_SPCA536:
1038 spca50x_GetFirmware(gspca_dev);
1039 spca5xxRegRead(dev, 0x00, 0x5002, &Data, 1);
1041 spca5xxRegWrite(dev, 0x24, 0, 0, &Data, 1);
1042 spca5xxRegRead(dev, 0x24, 0, &Data, 1);
1043 rc = spca504B_PollingDataReady(dev);
1044 spca5xxRegWrite(dev, 0x34, 0, 0, NULL, 0);
1045 spca504B_WaitCmdStatus(gspca_dev);
1047 case BRIDGE_SPCA504C: /* pccam600 */
1048 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
1049 reg_write(dev, 0xe0, 0x0000, 0x0000);
1050 reg_write(dev, 0xe0, 0x0000, 0x0001); /* reset */
1051 spca504_wait_status(gspca_dev);
1052 if (sd->subtype == LogitechClickSmart420)
1053 write_vector(gspca_dev,
1054 spca504A_clicksmart420_open_data);
1056 write_vector(gspca_dev, spca504_pccam600_open_data);
1057 err_code = spca50x_setup_qtable(gspca_dev,
1059 0x2840, qtable_creative_pccam);
1061 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
1066 /* case BRIDGE_SPCA504: */
1067 PDEBUG(D_STREAM, "Opening SPCA504");
1068 if (sd->subtype == AiptekMiniPenCam13) {
1069 /*****************************/
1070 for (i = 0; i < 6; i++)
1071 info[i] = reg_read_info(dev, i);
1073 "Read info: %d %d %d %d %d %d."
1074 " Should be 1,0,2,2,0,0",
1075 info[0], info[1], info[2],
1076 info[3], info[4], info[5]);
1077 /* spca504a aiptek */
1078 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1079 spca504A_acknowledged_command(gspca_dev, 0x24,
1081 /* Twice sequencial need status 0xff->0x9e->0x9d */
1082 spca504A_acknowledged_command(gspca_dev, 0x24,
1085 spca504A_acknowledged_command(gspca_dev, 0x24,
1087 /******************************/
1088 /* spca504a aiptek */
1089 spca504A_acknowledged_command(gspca_dev, 0x08,
1091 /* reg_write (dev, 0, 0x2000, 0); */
1092 /* reg_write (dev, 0, 0x2883, 1); */
1093 /* spca504A_acknowledged_command (gspca_dev, 0x08,
1095 /* spca504A_acknowledged_command (gspca_dev, 0x24,
1097 reg_write(dev, 0x0, 0x270c, 0x5); /* L92 sno1t.txt */
1098 reg_write(dev, 0x0, 0x2310, 0x5);
1099 spca504A_acknowledged_command(gspca_dev, 0x01,
1103 reg_write(dev, 0, 0x2000, 0);
1104 reg_write(dev, 0, 0x2883, 1);
1105 err_code = spca50x_setup_qtable(gspca_dev,
1108 qtable_spca504_default);
1110 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
1118 static void sd_start(struct gspca_dev *gspca_dev)
1120 struct sd *sd = (struct sd *) gspca_dev;
1121 struct usb_device *dev = gspca_dev->dev;
1127 if (sd->bridge == BRIDGE_SPCA504B)
1128 spca504B_setQtable(gspca_dev);
1129 spca504B_SetSizeType(gspca_dev);
1130 switch (sd->bridge) {
1132 /* case BRIDGE_SPCA504B: */
1133 /* case BRIDGE_SPCA533: */
1134 /* case BRIDGE_SPCA536: */
1135 if (sd->subtype == MegapixV4 ||
1136 sd->subtype == LogitechClickSmart820) {
1137 spca5xxRegWrite(dev, 0xf0, 0, 0, NULL, 0);
1138 spca504B_WaitCmdStatus(gspca_dev);
1139 spca5xxRegRead(dev, 0xf0, 4, NULL, 0);
1140 spca504B_WaitCmdStatus(gspca_dev);
1142 spca5xxRegWrite(dev, 0x31, 0, 4, NULL, 0);
1143 spca504B_WaitCmdStatus(gspca_dev);
1144 rc = spca504B_PollingDataReady(dev);
1147 case BRIDGE_SPCA504:
1148 if (sd->subtype == AiptekMiniPenCam13) {
1149 for (i = 0; i < 6; i++)
1150 info[i] = reg_read_info(dev, i);
1152 "Read info: %d %d %d %d %d %d."
1153 " Should be 1,0,2,2,0,0",
1154 info[0], info[1], info[2],
1155 info[3], info[4], info[5]);
1156 /* spca504a aiptek */
1157 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1158 spca504A_acknowledged_command(gspca_dev, 0x24,
1160 /* Twice sequencial need status 0xff->0x9e->0x9d */
1161 spca504A_acknowledged_command(gspca_dev, 0x24,
1163 spca504A_acknowledged_command(gspca_dev, 0x24,
1166 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1167 for (i = 0; i < 6; i++)
1168 info[i] = reg_read_info(dev, i);
1170 "Read info: %d %d %d %d %d %d."
1171 " Should be 1,0,2,2,0,0",
1172 info[0], info[1], info[2],
1173 info[3], info[4], info[5]);
1174 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1175 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1177 spca504B_SetSizeType(gspca_dev);
1178 reg_write(dev, 0x0, 0x270c, 0x5); /* L92 sno1t.txt */
1179 reg_write(dev, 0x0, 0x2310, 0x5);
1181 case BRIDGE_SPCA504C:
1182 if (sd->subtype == LogitechClickSmart420) {
1183 write_vector(gspca_dev,
1184 spca504A_clicksmart420_init_data);
1186 write_vector(gspca_dev, spca504_pccam600_init_data);
1188 enable = (sd->autogain ? 0x4 : 0x1);
1189 reg_write(dev, 0x0c, 0x0000, enable); /* auto exposure */
1190 reg_write(dev, 0xb0, 0x0000, enable); /* auto whiteness */
1192 /* set default exposure compensation and whiteness balance */
1193 reg_write(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1194 reg_write(dev, 0x30, 0x0002, 1600);
1195 spca504B_SetSizeType(gspca_dev);
1198 sp5xx_initContBrigHueRegisters(gspca_dev);
1201 static void sd_stopN(struct gspca_dev *gspca_dev)
1203 struct sd *sd = (struct sd *) gspca_dev;
1204 struct usb_device *dev = gspca_dev->dev;
1206 switch (sd->bridge) {
1208 /* case BRIDGE_SPCA533: */
1209 /* case BRIDGE_SPCA536: */
1210 /* case BRIDGE_SPCA504B: */
1211 spca5xxRegWrite(dev, 0x31, 0, 0, NULL, 0);
1212 spca504B_WaitCmdStatus(gspca_dev);
1213 spca504B_PollingDataReady(dev);
1215 case BRIDGE_SPCA504:
1216 case BRIDGE_SPCA504C:
1217 reg_write(dev, 0x00, 0x2000, 0x0000);
1219 if (sd->subtype == AiptekMiniPenCam13) {
1220 /* spca504a aiptek */
1221 /* spca504A_acknowledged_command(gspca_dev, 0x08,
1223 spca504A_acknowledged_command(gspca_dev, 0x24,
1224 0x00, 0x00, 0x9d, 1);
1225 spca504A_acknowledged_command(gspca_dev, 0x01,
1226 0x0f, 0x00, 0xff, 1);
1228 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1229 reg_write(dev, 0x01, 0x000f, 0x0);
1235 static void sd_stop0(struct gspca_dev *gspca_dev)
1239 static void sd_close(struct gspca_dev *gspca_dev)
1243 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1244 struct gspca_frame *frame, /* target */
1245 unsigned char *data, /* isoc packet */
1246 int len) /* iso packet length */
1248 struct sd *sd = (struct sd *) gspca_dev;
1250 unsigned char *s, *d;
1251 static unsigned char ffd9[] = {0xff, 0xd9};
1253 /* frames are jpeg 4.1.1 without 0xff escape */
1254 switch (sd->bridge) {
1255 case BRIDGE_SPCA533:
1256 if (data[0] == 0xff) {
1257 if (data[1] != 0x01) { /* drop packet */
1258 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1262 data += SPCA533_OFFSET_DATA;
1263 len -= SPCA533_OFFSET_DATA;
1269 case BRIDGE_SPCA536:
1270 if (data[0] == 0xff) {
1272 data += SPCA536_OFFSET_DATA;
1273 len -= SPCA536_OFFSET_DATA;
1280 /* case BRIDGE_SPCA504: */
1281 /* case BRIDGE_SPCA504B: */
1283 case 0xfe: /* start of frame */
1285 data += SPCA50X_OFFSET_DATA;
1286 len -= SPCA50X_OFFSET_DATA;
1288 case 0xff: /* drop packet */
1289 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1297 case BRIDGE_SPCA504C:
1299 case 0xfe: /* start of frame */
1301 data += SPCA504_PCCAM600_OFFSET_DATA;
1302 len -= SPCA504_PCCAM600_OFFSET_DATA;
1304 case 0xff: /* drop packet */
1305 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1314 if (sof) { /* start of frame */
1315 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1318 /* put the JPEG header in the new frame */
1319 jpeg_put_header(gspca_dev, frame,
1320 ((struct sd *) gspca_dev)->qindex,
1324 /* add 0x00 after 0xff */
1325 for (i = len; --i >= 0; )
1326 if (data[i] == 0xff)
1328 if (i < 0) { /* no 0xff */
1329 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1334 for (i = 0; i < len; i++) {
1339 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1340 sd->packet, d - sd->packet);
1343 static void setbrightness(struct gspca_dev *gspca_dev)
1345 struct sd *sd = (struct sd *) gspca_dev;
1346 struct usb_device *dev = gspca_dev->dev;
1348 switch (sd->bridge) {
1350 /* case BRIDGE_SPCA533: */
1351 /* case BRIDGE_SPCA504B: */
1352 /* case BRIDGE_SPCA504: */
1353 /* case BRIDGE_SPCA504C: */
1354 reg_write(dev, 0x0, 0x21a7, sd->brightness);
1356 case BRIDGE_SPCA536:
1357 reg_write(dev, 0x0, 0x20f0, sd->brightness);
1362 static void getbrightness(struct gspca_dev *gspca_dev)
1364 struct sd *sd = (struct sd *) gspca_dev;
1365 struct usb_device *dev = gspca_dev->dev;
1366 __u16 brightness = 0;
1368 switch (sd->bridge) {
1370 /* case BRIDGE_SPCA533: */
1371 /* case BRIDGE_SPCA504B: */
1372 /* case BRIDGE_SPCA504: */
1373 /* case BRIDGE_SPCA504C: */
1374 brightness = reg_read(dev, 0x0, 0x21a7, 2);
1376 case BRIDGE_SPCA536:
1377 brightness = reg_read(dev, 0x0, 0x20f0, 2);
1380 sd->brightness = ((brightness & 0xff) - 128) % 255;
1383 static void setcontrast(struct gspca_dev *gspca_dev)
1385 struct sd *sd = (struct sd *) gspca_dev;
1386 struct usb_device *dev = gspca_dev->dev;
1388 switch (sd->bridge) {
1390 /* case BRIDGE_SPCA533: */
1391 /* case BRIDGE_SPCA504B: */
1392 /* case BRIDGE_SPCA504: */
1393 /* case BRIDGE_SPCA504C: */
1394 reg_write(dev, 0x0, 0x21a8, sd->contrast);
1396 case BRIDGE_SPCA536:
1397 reg_write(dev, 0x0, 0x20f1, sd->contrast);
1402 static void getcontrast(struct gspca_dev *gspca_dev)
1404 struct sd *sd = (struct sd *) gspca_dev;
1405 struct usb_device *dev = gspca_dev->dev;
1407 switch (sd->bridge) {
1409 /* case BRIDGE_SPCA533: */
1410 /* case BRIDGE_SPCA504B: */
1411 /* case BRIDGE_SPCA504: */
1412 /* case BRIDGE_SPCA504C: */
1413 sd->contrast = reg_read(dev, 0x0, 0x21a8, 2);
1415 case BRIDGE_SPCA536:
1416 sd->contrast = reg_read(dev, 0x0, 0x20f1, 2);
1421 static void setcolors(struct gspca_dev *gspca_dev)
1423 struct sd *sd = (struct sd *) gspca_dev;
1424 struct usb_device *dev = gspca_dev->dev;
1426 switch (sd->bridge) {
1428 /* case BRIDGE_SPCA533: */
1429 /* case BRIDGE_SPCA504B: */
1430 /* case BRIDGE_SPCA504: */
1431 /* case BRIDGE_SPCA504C: */
1432 reg_write(dev, 0x0, 0x21ae, sd->colors);
1434 case BRIDGE_SPCA536:
1435 reg_write(dev, 0x0, 0x20f6, sd->colors);
1440 static void getcolors(struct gspca_dev *gspca_dev)
1442 struct sd *sd = (struct sd *) gspca_dev;
1443 struct usb_device *dev = gspca_dev->dev;
1445 switch (sd->bridge) {
1447 /* case BRIDGE_SPCA533: */
1448 /* case BRIDGE_SPCA504B: */
1449 /* case BRIDGE_SPCA504: */
1450 /* case BRIDGE_SPCA504C: */
1451 sd->colors = reg_read(dev, 0x0, 0x21ae, 2) >> 1;
1453 case BRIDGE_SPCA536:
1454 sd->colors = reg_read(dev, 0x0, 0x20f6, 2) >> 1;
1459 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1461 struct sd *sd = (struct sd *) gspca_dev;
1463 sd->brightness = val;
1464 if (gspca_dev->streaming)
1465 setbrightness(gspca_dev);
1469 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1471 struct sd *sd = (struct sd *) gspca_dev;
1473 getbrightness(gspca_dev);
1474 *val = sd->brightness;
1478 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1480 struct sd *sd = (struct sd *) gspca_dev;
1483 if (gspca_dev->streaming)
1484 setcontrast(gspca_dev);
1488 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1490 struct sd *sd = (struct sd *) gspca_dev;
1492 getcontrast(gspca_dev);
1493 *val = sd->contrast;
1497 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1499 struct sd *sd = (struct sd *) gspca_dev;
1502 if (gspca_dev->streaming)
1503 setcolors(gspca_dev);
1507 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1509 struct sd *sd = (struct sd *) gspca_dev;
1511 getcolors(gspca_dev);
1516 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1518 struct sd *sd = (struct sd *) gspca_dev;
1524 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1526 struct sd *sd = (struct sd *) gspca_dev;
1528 *val = sd->autogain;
1532 /* sub-driver description */
1533 static struct sd_desc sd_desc = {
1534 .name = MODULE_NAME,
1536 .nctrls = ARRAY_SIZE(sd_ctrls),
1537 .config = sd_config,
1543 .pkt_scan = sd_pkt_scan,
1546 /* -- module initialisation -- */
1547 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1548 static __devinitdata struct usb_device_id device_table[] = {
1549 {USB_DEVICE(0x041e, 0x400b), DVNM("Creative PC-CAM 600")},
1550 {USB_DEVICE(0x041e, 0x4012), DVNM("PC-Cam350")},
1551 {USB_DEVICE(0x041e, 0x4013), DVNM("Creative Pccam750")},
1552 {USB_DEVICE(0x0458, 0x7006), DVNM("Genius Dsc 1.3 Smart")},
1553 {USB_DEVICE(0x046d, 0x0905), DVNM("Logitech ClickSmart 820")},
1554 {USB_DEVICE(0x046d, 0x0960), DVNM("Logitech ClickSmart 420")},
1555 {USB_DEVICE(0x0471, 0x0322), DVNM("Philips DMVC1300K")},
1556 {USB_DEVICE(0x04a5, 0x3003), DVNM("Benq DC 1300")},
1557 {USB_DEVICE(0x04a5, 0x3008), DVNM("Benq DC 1500")},
1558 {USB_DEVICE(0x04a5, 0x300a), DVNM("Benq DC3410")},
1559 {USB_DEVICE(0x04f1, 0x1001), DVNM("JVC GC A50")},
1560 {USB_DEVICE(0x04fc, 0x500c), DVNM("Sunplus CA500C")},
1561 {USB_DEVICE(0x04fc, 0x504a), DVNM("Aiptek Mini PenCam 1.3")},
1562 {USB_DEVICE(0x04fc, 0x504b), DVNM("Maxell MaxPocket LE 1.3")},
1563 {USB_DEVICE(0x04fc, 0x5330), DVNM("Digitrex 2110")},
1564 {USB_DEVICE(0x04fc, 0x5360), DVNM("Sunplus Generic")},
1565 {USB_DEVICE(0x04fc, 0xffff), DVNM("Pure DigitalDakota")},
1566 {USB_DEVICE(0x052b, 0x1513), DVNM("Megapix V4")},
1567 {USB_DEVICE(0x0546, 0x3155), DVNM("Polaroid PDC3070")},
1568 {USB_DEVICE(0x0546, 0x3191), DVNM("Polaroid Ion 80")},
1569 {USB_DEVICE(0x0546, 0x3273), DVNM("Polaroid PDC2030")},
1570 {USB_DEVICE(0x055f, 0xc211), DVNM("Kowa Bs888e Microcamera")},
1571 {USB_DEVICE(0x055f, 0xc230), DVNM("Mustek Digicam 330K")},
1572 {USB_DEVICE(0x055f, 0xc232), DVNM("Mustek MDC3500")},
1573 {USB_DEVICE(0x055f, 0xc360), DVNM("Mustek DV4000 Mpeg4 ")},
1574 {USB_DEVICE(0x055f, 0xc420), DVNM("Mustek gSmart Mini 2")},
1575 {USB_DEVICE(0x055f, 0xc430), DVNM("Mustek Gsmart LCD 2")},
1576 {USB_DEVICE(0x055f, 0xc440), DVNM("Mustek DV 3000")},
1577 {USB_DEVICE(0x055f, 0xc520), DVNM("Mustek gSmart Mini 3")},
1578 {USB_DEVICE(0x055f, 0xc530), DVNM("Mustek Gsmart LCD 3")},
1579 {USB_DEVICE(0x055f, 0xc540), DVNM("Gsmart D30")},
1580 {USB_DEVICE(0x055f, 0xc630), DVNM("Mustek MDC4000")},
1581 {USB_DEVICE(0x055f, 0xc650), DVNM("Mustek MDC5500Z")},
1582 {USB_DEVICE(0x05da, 0x1018), DVNM("Digital Dream Enigma 1.3")},
1583 {USB_DEVICE(0x06d6, 0x0031), DVNM("Trust 610 LCD PowerC@m Zoom")},
1584 {USB_DEVICE(0x0733, 0x1311), DVNM("Digital Dream Epsilon 1.3")},
1585 {USB_DEVICE(0x0733, 0x1314), DVNM("Mercury 2.1MEG Deluxe Classic Cam")},
1586 {USB_DEVICE(0x0733, 0x2211), DVNM("Jenoptik jdc 21 LCD")},
1587 {USB_DEVICE(0x0733, 0x2221), DVNM("Mercury Digital Pro 3.1p")},
1588 {USB_DEVICE(0x0733, 0x3261), DVNM("Concord 3045 spca536a")},
1589 {USB_DEVICE(0x0733, 0x3281), DVNM("Cyberpix S550V")},
1590 {USB_DEVICE(0x08ca, 0x0104), DVNM("Aiptek PocketDVII 1.3")},
1591 {USB_DEVICE(0x08ca, 0x0106), DVNM("Aiptek Pocket DV3100+")},
1592 {USB_DEVICE(0x08ca, 0x2008), DVNM("Aiptek Mini PenCam 2 M")},
1593 {USB_DEVICE(0x08ca, 0x2010), DVNM("Aiptek PocketCam 3M")},
1594 {USB_DEVICE(0x08ca, 0x2016), DVNM("Aiptek PocketCam 2 Mega")},
1595 {USB_DEVICE(0x08ca, 0x2018), DVNM("Aiptek Pencam SD 2M")},
1596 {USB_DEVICE(0x08ca, 0x2020), DVNM("Aiptek Slim 3000F")},
1597 {USB_DEVICE(0x08ca, 0x2022), DVNM("Aiptek Slim 3200")},
1598 {USB_DEVICE(0x08ca, 0x2024), DVNM("Aiptek DV3500 Mpeg4 ")},
1599 {USB_DEVICE(0x08ca, 0x2028), DVNM("Aiptek PocketCam4M")},
1600 {USB_DEVICE(0x08ca, 0x2040), DVNM("Aiptek PocketDV4100M")},
1601 {USB_DEVICE(0x08ca, 0x2042), DVNM("Aiptek PocketDV5100")},
1602 {USB_DEVICE(0x08ca, 0x2060), DVNM("Aiptek PocketDV5300")},
1603 {USB_DEVICE(0x0d64, 0x0303), DVNM("Sunplus FashionCam DXG")},
1606 MODULE_DEVICE_TABLE(usb, device_table);
1608 /* -- device connect -- */
1609 static int sd_probe(struct usb_interface *intf,
1610 const struct usb_device_id *id)
1612 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1616 static struct usb_driver sd_driver = {
1617 .name = MODULE_NAME,
1618 .id_table = device_table,
1620 .disconnect = gspca_disconnect,
1623 /* -- module insert / remove -- */
1624 static int __init sd_mod_init(void)
1626 if (usb_register(&sd_driver) < 0)
1628 PDEBUG(D_PROBE, "v%s registered", version);
1631 static void __exit sd_mod_exit(void)
1633 usb_deregister(&sd_driver);
1634 PDEBUG(D_PROBE, "deregistered");
1637 module_init(sd_mod_init);
1638 module_exit(sd_mod_exit);