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