]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/video/gspca/pac7311.c
V4L/DVB (8195): gspca: Input buffer overwritten in spca561 + cleanup code.
[linux-2.6-omap-h63xx.git] / drivers / media / video / gspca / pac7311.c
1 /*
2  *              Pixart PAC7311 library
3  *              Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
4  *
5  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21
22 #define MODULE_NAME "pac7311"
23
24 #include "gspca.h"
25
26 #define DRIVER_VERSION_NUMBER   KERNEL_VERSION(2, 1, 4)
27 static const char version[] = "2.1.4";
28
29 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
30 MODULE_DESCRIPTION("Pixart PAC7311");
31 MODULE_LICENSE("GPL");
32
33 /* specific webcam descriptor */
34 struct sd {
35         struct gspca_dev gspca_dev;             /* !! must be the first item */
36
37         int avg_lum;
38
39         unsigned char brightness;
40         unsigned char contrast;
41         unsigned char colors;
42         unsigned char autogain;
43
44         char ffseq;
45         signed char ag_cnt;
46 #define AG_CNT_START 13
47 };
48
49 /* V4L2 controls supported by the driver */
50 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
51 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
52 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
53 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
54 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
55 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
56 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
57 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
58
59 static struct ctrl sd_ctrls[] = {
60         {
61             {
62                 .id      = V4L2_CID_BRIGHTNESS,
63                 .type    = V4L2_CTRL_TYPE_INTEGER,
64                 .name    = "Brightness",
65                 .minimum = 0,
66 #define BRIGHTNESS_MAX 0x20
67                 .maximum = BRIGHTNESS_MAX,
68                 .step    = 1,
69 #define BRIGHTNESS_DEF 0x10
70                 .default_value = BRIGHTNESS_DEF,
71             },
72             .set = sd_setbrightness,
73             .get = sd_getbrightness,
74         },
75         {
76             {
77                 .id      = V4L2_CID_CONTRAST,
78                 .type    = V4L2_CTRL_TYPE_INTEGER,
79                 .name    = "Contrast",
80                 .minimum = 0,
81                 .maximum = 255,
82                 .step    = 1,
83 #define CONTRAST_DEF 127
84                 .default_value = CONTRAST_DEF,
85             },
86             .set = sd_setcontrast,
87             .get = sd_getcontrast,
88         },
89         {
90             {
91                 .id      = V4L2_CID_SATURATION,
92                 .type    = V4L2_CTRL_TYPE_INTEGER,
93                 .name    = "Color",
94                 .minimum = 0,
95                 .maximum = 255,
96                 .step    = 1,
97 #define COLOR_DEF 127
98                 .default_value = COLOR_DEF,
99             },
100             .set = sd_setcolors,
101             .get = sd_getcolors,
102         },
103         {
104             {
105                 .id      = V4L2_CID_AUTOGAIN,
106                 .type    = V4L2_CTRL_TYPE_BOOLEAN,
107                 .name    = "Auto Gain",
108                 .minimum = 0,
109                 .maximum = 1,
110                 .step    = 1,
111 #define AUTOGAIN_DEF 1
112                 .default_value = AUTOGAIN_DEF,
113             },
114             .set = sd_setautogain,
115             .get = sd_getautogain,
116         },
117 };
118
119 static struct cam_mode vga_mode[] = {
120         {V4L2_PIX_FMT_JPEG, 160, 120, 2},
121         {V4L2_PIX_FMT_JPEG, 320, 240, 1},
122         {V4L2_PIX_FMT_JPEG, 640, 480, 0},
123 };
124
125 #define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header)   /* (594) */
126
127 static const __u8 pac7311_jpeg_header[] = {
128         0xff, 0xd8,
129         0xff, 0xe0, 0x00, 0x03, 0x20,
130         0xff, 0xc0, 0x00, 0x11, 0x08,
131                 0x01, 0xe0,                     /* 12: height */
132                 0x02, 0x80,                     /* 14: width */
133                 0x03,                           /* 16 */
134                         0x01, 0x21, 0x00,
135                         0x02, 0x11, 0x01,
136                         0x03, 0x11, 0x01,
137         0xff, 0xdb, 0x00, 0x84,
138         0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d,
139         0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16,
140         0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d,
141         0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40,
142         0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f,
143         0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
144         0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18,
145         0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
146         0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
147         0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
148         0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
149         0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
150         0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
151         0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
152         0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153         0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
154         0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
155         0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
156         0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
157         0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
158         0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
159         0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
160         0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
161         0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
162         0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
163         0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
164         0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
165         0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
166         0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
167         0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
168         0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
169         0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
170         0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
171         0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
172         0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
173         0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174         0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
175         0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
176         0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
177         0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
178         0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
179         0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
180         0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
181         0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
182         0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
183         0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
184         0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
185         0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
186         0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
187         0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
188         0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
189         0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
190         0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
191         0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
192         0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
193         0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
194         0x11, 0x00, 0x3f, 0x00
195 };
196
197 static void reg_w(struct usb_device *dev,
198                   __u16 index,
199                   const char *buffer, __u16 len)
200 {
201         __u8 tmpbuf[8];
202
203         memcpy(tmpbuf, buffer, len);
204         usb_control_msg(dev,
205                         usb_sndctrlpipe(dev, 0),
206                         1,              /* request */
207                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
208                         0,              /* value */
209                         index, tmpbuf, len,
210                         500);
211 }
212
213 static void pac7311_reg_read(struct usb_device *dev, __u16 index,
214                             __u8 *buffer)
215 {
216         usb_control_msg(dev,
217                         usb_rcvctrlpipe(dev, 0),
218                         0,                      /* request */
219                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
220                         0,                      /* value */
221                         index, buffer, 1,
222                         500);
223 }
224
225 static void pac7311_reg_write(struct usb_device *dev,
226                               __u16 index,
227                               __u8 value)
228 {
229         __u8 buf;
230
231         buf = value;
232         usb_control_msg(dev,
233                         usb_sndctrlpipe(dev, 0),
234                         0,                      /* request */
235                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
236                         value, index, &buf, 1,
237                         500);
238 }
239
240 /* this function is called at probe time */
241 static int sd_config(struct gspca_dev *gspca_dev,
242                         const struct usb_device_id *id)
243 {
244         struct sd *sd = (struct sd *) gspca_dev;
245         struct usb_device *dev = gspca_dev->dev;
246         struct cam *cam;
247
248         PDEBUG(D_CONF, "Find Sensor PAC7311");
249         pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
250         pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
251         pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
252         pac7311_reg_write(dev, 0xff, 0x04);
253         pac7311_reg_write(dev, 0x27, 0x80);
254         pac7311_reg_write(dev, 0x28, 0xca);
255         pac7311_reg_write(dev, 0x29, 0x53);
256         pac7311_reg_write(dev, 0x2a, 0x0e);
257         pac7311_reg_write(dev, 0xff, 0x01);
258         pac7311_reg_write(dev, 0x3e, 0x20);
259
260         cam = &gspca_dev->cam;
261         cam->dev_name = (char *) id->driver_info;
262         cam->epaddr = 0x05;
263         cam->cam_mode = vga_mode;
264         cam->nmodes = ARRAY_SIZE(vga_mode);
265
266         sd->brightness = BRIGHTNESS_DEF;
267         sd->contrast = CONTRAST_DEF;
268         sd->colors = COLOR_DEF;
269         sd->autogain = AUTOGAIN_DEF;
270         return 0;
271 }
272
273 static void setbrightness(struct gspca_dev *gspca_dev)
274 {
275         struct sd *sd = (struct sd *) gspca_dev;
276         int brightness;
277
278 /*jfm: inverted?*/
279         brightness = BRIGHTNESS_MAX - sd->brightness;
280         pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
281 /*      pac7311_reg_write(gspca_dev->dev, 0x0e, 0x00); */
282         pac7311_reg_write(gspca_dev->dev, 0x0f, brightness);
283         /* load registers to sensor (Bit 0, auto clear) */
284         pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
285         PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
286 }
287
288 static void setcontrast(struct gspca_dev *gspca_dev)
289 {
290         struct sd *sd = (struct sd *) gspca_dev;
291
292         pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
293         pac7311_reg_write(gspca_dev->dev, 0x80, sd->contrast);
294         /* load registers to sensor (Bit 0, auto clear) */
295         pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
296         PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
297 }
298
299 static void setcolors(struct gspca_dev *gspca_dev)
300 {
301         struct sd *sd = (struct sd *) gspca_dev;
302
303         pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
304         pac7311_reg_write(gspca_dev->dev, 0x10, sd->colors);
305         /* load registers to sensor (Bit 0, auto clear) */
306         pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
307         PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
308 }
309
310 /* this function is called at open time */
311 static int sd_open(struct gspca_dev *gspca_dev)
312 {
313         pac7311_reg_write(gspca_dev->dev, 0x78, 0x00);  /* Turn on LED */
314         return 0;
315 }
316
317 static void sd_start(struct gspca_dev *gspca_dev)
318 {
319         struct usb_device *dev = gspca_dev->dev;
320         struct sd *sd = (struct sd *) gspca_dev;
321
322         pac7311_reg_write(dev, 0xff, 0x01);
323         reg_w(dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
324         reg_w(dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
325         reg_w(dev, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
326         reg_w(dev, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
327         reg_w(dev, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
328         reg_w(dev, 0x002a, "\x00\x00\x00", 3);
329         reg_w(dev, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
330         reg_w(dev, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
331         reg_w(dev, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
332         reg_w(dev, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
333         reg_w(dev, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
334         reg_w(dev, 0x0066, "\xd0\xff", 2);
335         reg_w(dev, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
336         reg_w(dev, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
337         reg_w(dev, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
338         reg_w(dev, 0x008f, "\x18\x20", 2);
339         reg_w(dev, 0x0096, "\x01\x08\x04", 3);
340         reg_w(dev, 0x00a0, "\x44\x44\x44\x04", 4);
341         reg_w(dev, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
342         reg_w(dev, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
343
344         pac7311_reg_write(dev, 0xff, 0x04);
345         pac7311_reg_write(dev, 0x02, 0x04);
346         pac7311_reg_write(dev, 0x03, 0x54);
347         pac7311_reg_write(dev, 0x04, 0x07);
348         pac7311_reg_write(dev, 0x05, 0x2b);
349         pac7311_reg_write(dev, 0x06, 0x09);
350         pac7311_reg_write(dev, 0x07, 0x0f);
351         pac7311_reg_write(dev, 0x08, 0x09);
352         pac7311_reg_write(dev, 0x09, 0x00);
353         pac7311_reg_write(dev, 0x0c, 0x07);
354         pac7311_reg_write(dev, 0x0d, 0x00);
355         pac7311_reg_write(dev, 0x0e, 0x00);
356         pac7311_reg_write(dev, 0x0f, 0x62);
357         pac7311_reg_write(dev, 0x10, 0x08);
358         pac7311_reg_write(dev, 0x12, 0x07);
359         pac7311_reg_write(dev, 0x13, 0x00);
360         pac7311_reg_write(dev, 0x14, 0x00);
361         pac7311_reg_write(dev, 0x15, 0x00);
362         pac7311_reg_write(dev, 0x16, 0x00);
363         pac7311_reg_write(dev, 0x17, 0x00);
364         pac7311_reg_write(dev, 0x18, 0x00);
365         pac7311_reg_write(dev, 0x19, 0x00);
366         pac7311_reg_write(dev, 0x1a, 0x00);
367         pac7311_reg_write(dev, 0x1b, 0x03);
368         pac7311_reg_write(dev, 0x1c, 0xa0);
369         pac7311_reg_write(dev, 0x1d, 0x01);
370         pac7311_reg_write(dev, 0x1e, 0xf4);
371         pac7311_reg_write(dev, 0x21, 0x00);
372         pac7311_reg_write(dev, 0x22, 0x08);
373         pac7311_reg_write(dev, 0x24, 0x03);
374         pac7311_reg_write(dev, 0x26, 0x00);
375         pac7311_reg_write(dev, 0x27, 0x01);
376         pac7311_reg_write(dev, 0x28, 0xca);
377         pac7311_reg_write(dev, 0x29, 0x10);
378         pac7311_reg_write(dev, 0x2a, 0x06);
379         pac7311_reg_write(dev, 0x2b, 0x78);
380         pac7311_reg_write(dev, 0x2c, 0x00);
381         pac7311_reg_write(dev, 0x2d, 0x00);
382         pac7311_reg_write(dev, 0x2e, 0x00);
383         pac7311_reg_write(dev, 0x2f, 0x00);
384         pac7311_reg_write(dev, 0x30, 0x23);
385         pac7311_reg_write(dev, 0x31, 0x28);
386         pac7311_reg_write(dev, 0x32, 0x04);
387         pac7311_reg_write(dev, 0x33, 0x11);
388         pac7311_reg_write(dev, 0x34, 0x00);
389         pac7311_reg_write(dev, 0x35, 0x00);
390         pac7311_reg_write(dev, 0x11, 0x01);
391         setcontrast(gspca_dev);
392         setbrightness(gspca_dev);
393         setcolors(gspca_dev);
394
395         /* set correct resolution */
396         switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
397         case 2:                                 /* 160x120 */
398                 pac7311_reg_write(dev, 0xff, 0x04);
399                 pac7311_reg_write(dev, 0x02, 0x03);
400                 pac7311_reg_write(dev, 0xff, 0x01);
401                 pac7311_reg_write(dev, 0x08, 0x09);
402                 pac7311_reg_write(dev, 0x17, 0x20);
403                 pac7311_reg_write(dev, 0x1b, 0x00);
404 /*              pac7311_reg_write(dev, 0x80, 0x69); */
405                 pac7311_reg_write(dev, 0x87, 0x10);
406                 break;
407         case 1:                                 /* 320x240 */
408                 pac7311_reg_write(dev, 0xff, 0x04);
409                 pac7311_reg_write(dev, 0x02, 0x03);
410                 pac7311_reg_write(dev, 0xff, 0x01);
411                 pac7311_reg_write(dev, 0x08, 0x09);
412                 pac7311_reg_write(dev, 0x17, 0x30);
413 /*              pac7311_reg_write(dev, 0x80, 0x3f); */
414                 pac7311_reg_write(dev, 0x87, 0x11);
415                 break;
416         case 0:                                 /* 640x480 */
417                 pac7311_reg_write(dev, 0xff, 0x04);
418                 pac7311_reg_write(dev, 0x02, 0x03);
419                 pac7311_reg_write(dev, 0xff, 0x01);
420                 pac7311_reg_write(dev, 0x08, 0x08);
421                 pac7311_reg_write(dev, 0x17, 0x00);
422 /*              pac7311_reg_write(dev, 0x80, 0x1c); */
423                 pac7311_reg_write(dev, 0x87, 0x12);
424                 break;
425         }
426
427         /* start stream */
428         pac7311_reg_write(dev, 0xff, 0x01);
429         pac7311_reg_write(dev, 0x78, 0x04);
430         pac7311_reg_write(dev, 0x78, 0x05);
431
432         if (sd->autogain) {
433                 sd->ag_cnt = AG_CNT_START;
434                 sd->avg_lum = 0;
435         } else {
436                 sd->ag_cnt = -1;
437         }
438 }
439
440 static void sd_stopN(struct gspca_dev *gspca_dev)
441 {
442         struct usb_device *dev = gspca_dev->dev;
443
444         pac7311_reg_write(dev, 0xff, 0x04);
445         pac7311_reg_write(dev, 0x27, 0x80);
446         pac7311_reg_write(dev, 0x28, 0xca);
447         pac7311_reg_write(dev, 0x29, 0x53);
448         pac7311_reg_write(dev, 0x2a, 0x0e);
449         pac7311_reg_write(dev, 0xff, 0x01);
450         pac7311_reg_write(dev, 0x3e, 0x20);
451         pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
452         pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
453         pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
454 }
455
456 static void sd_stop0(struct gspca_dev *gspca_dev)
457 {
458 }
459
460 /* this function is called at close time */
461 static void sd_close(struct gspca_dev *gspca_dev)
462 {
463         struct usb_device *dev = gspca_dev->dev;
464
465         pac7311_reg_write(dev, 0xff, 0x04);
466         pac7311_reg_write(dev, 0x27, 0x80);
467         pac7311_reg_write(dev, 0x28, 0xca);
468         pac7311_reg_write(dev, 0x29, 0x53);
469         pac7311_reg_write(dev, 0x2a, 0x0e);
470         pac7311_reg_write(dev, 0xff, 0x01);
471         pac7311_reg_write(dev, 0x3e, 0x20);
472         pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
473         pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
474         pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
475 }
476
477 static void setautogain(struct gspca_dev *gspca_dev, int luma)
478 {
479         int luma_mean = 128;
480         int luma_delta = 20;
481         __u8 spring = 5;
482         __u8 Pxclk;
483         int Gbright;
484
485         pac7311_reg_read(gspca_dev->dev, 0x02, &Pxclk);
486         Gbright = Pxclk;
487         PDEBUG(D_FRAM, "luma mean %d", luma);
488         if (luma < luma_mean - luma_delta ||
489             luma > luma_mean + luma_delta) {
490                 Gbright += (luma_mean - luma) >> spring;
491                 if (Gbright > 0x1a)
492                         Gbright = 0x1a;
493                 else if (Gbright < 4)
494                         Gbright = 4;
495                 PDEBUG(D_FRAM, "gbright %d", Gbright);
496                 pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
497                 pac7311_reg_write(gspca_dev->dev, 0x0f, Gbright);
498                 /* load registers to sensor (Bit 0, auto clear) */
499                 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
500         }
501 }
502
503 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
504                         struct gspca_frame *frame,      /* target */
505                         __u8 *data,                     /* isoc packet */
506                         int len)                        /* iso packet length */
507 {
508         struct sd *sd = (struct sd *) gspca_dev;
509         unsigned char tmpbuf[4];
510         int i, p, ffseq;
511
512 /*      if (len < 5) { */
513         if (len < 6) {
514 /*              gspca_dev->last_packet_type = DISCARD_PACKET; */
515                 return;
516         }
517
518         ffseq = sd->ffseq;
519
520         for (p = 0; p < len - 6; p++) {
521                 if ((data[0 + p] == 0xff)
522                     && (data[1 + p] == 0xff)
523                     && (data[2 + p] == 0x00)
524                     && (data[3 + p] == 0xff)
525                     && (data[4 + p] == 0x96)) {
526
527                         /* start of frame */
528                         if (sd->ag_cnt >= 0 && p > 28) {
529                                 sd->avg_lum += data[p - 23];
530                                 if (--sd->ag_cnt < 0) {
531                                         sd->ag_cnt = AG_CNT_START;
532                                         setautogain(gspca_dev,
533                                                 sd->avg_lum / AG_CNT_START);
534                                         sd->avg_lum = 0;
535                                 }
536                         }
537
538                         /* copy the end of data to the current frame */
539                         frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
540                                                 data, p);
541
542                         /* put the JPEG header in the new frame */
543                         gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
544                                         (unsigned char *) pac7311_jpeg_header,
545                                         12);
546                         tmpbuf[0] = gspca_dev->height >> 8;
547                         tmpbuf[1] = gspca_dev->height & 0xff;
548                         tmpbuf[2] = gspca_dev->width >> 8;
549                         tmpbuf[3] = gspca_dev->width & 0xff;
550                         gspca_frame_add(gspca_dev, INTER_PACKET, frame,
551                                         tmpbuf, 4);
552                         gspca_frame_add(gspca_dev, INTER_PACKET, frame,
553                                 (unsigned char *) &pac7311_jpeg_header[16],
554                                 PAC7311_JPEG_HEADER_SIZE - 16);
555
556                         data += p + 7;
557                         len -= p + 7;
558                         ffseq = 0;
559                         break;
560                 }
561         }
562
563         /* remove the 'ff ff ff xx' sequences */
564         switch (ffseq) {
565         case 3:
566                 data += 1;
567                 len -= 1;
568                 break;
569         case 2:
570                 if (data[0] == 0xff) {
571                         data += 2;
572                         len -= 2;
573                         frame->data_end -= 2;
574                 }
575                 break;
576         case 1:
577                 if (data[0] == 0xff
578                     && data[1] == 0xff) {
579                         data += 3;
580                         len -= 3;
581                         frame->data_end -= 1;
582                 }
583                 break;
584         }
585         for (i = 0; i < len - 4; i++) {
586                 if (data[i] == 0xff
587                     && data[i + 1] == 0xff
588                     && data[i + 2] == 0xff) {
589                         memmove(&data[i], &data[i + 4], len - i - 4);
590                         len -= 4;
591                 }
592         }
593         ffseq = 0;
594         if (data[len - 4] == 0xff) {
595                 if (data[len - 3] == 0xff
596                     && data[len - 2] == 0xff) {
597                         len -= 4;
598                 }
599         } else if (data[len - 3] == 0xff) {
600                 if (data[len - 2] == 0xff
601                     && data[len - 1] == 0xff)
602                         ffseq = 3;
603         } else if (data[len - 2] == 0xff) {
604                 if (data[len - 1] == 0xff)
605                         ffseq = 2;
606         } else if (data[len - 1] == 0xff)
607                 ffseq = 1;
608         sd->ffseq = ffseq;
609         gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
610 }
611
612 static void getbrightness(struct gspca_dev *gspca_dev)
613 {
614 /*      __u8 brightness = 0;
615
616         pac7311_reg_read(gspca_dev->dev, 0x0008, &brightness);
617         spca50x->brightness = brightness;
618         return spca50x->brightness;     */
619 /*      PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
620 }
621
622
623
624 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
625 {
626         struct sd *sd = (struct sd *) gspca_dev;
627
628         sd->brightness = val;
629         if (gspca_dev->streaming)
630                 setbrightness(gspca_dev);
631         return 0;
632 }
633
634 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
635 {
636         struct sd *sd = (struct sd *) gspca_dev;
637
638         getbrightness(gspca_dev);
639         *val = sd->brightness;
640         return 0;
641 }
642
643 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
644 {
645         struct sd *sd = (struct sd *) gspca_dev;
646
647         sd->contrast = val;
648         if (gspca_dev->streaming)
649                 setcontrast(gspca_dev);
650         return 0;
651 }
652
653 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
654 {
655         struct sd *sd = (struct sd *) gspca_dev;
656
657 /*      getcontrast(gspca_dev); */
658         *val = sd->contrast;
659         return 0;
660 }
661
662 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
663 {
664         struct sd *sd = (struct sd *) gspca_dev;
665
666         sd->colors = val;
667         if (gspca_dev->streaming)
668                 setcolors(gspca_dev);
669         return 0;
670 }
671
672 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
673 {
674         struct sd *sd = (struct sd *) gspca_dev;
675
676 /*      getcolors(gspca_dev); */
677         *val = sd->colors;
678         return 0;
679 }
680
681 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
682 {
683         struct sd *sd = (struct sd *) gspca_dev;
684
685         sd->autogain = val;
686         if (val) {
687                 sd->ag_cnt = AG_CNT_START;
688                 sd->avg_lum = 0;
689         } else {
690                 sd->ag_cnt = -1;
691         }
692         return 0;
693 }
694
695 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
696 {
697         struct sd *sd = (struct sd *) gspca_dev;
698
699         *val = sd->autogain;
700         return 0;
701 }
702
703 /* sub-driver description */
704 static struct sd_desc sd_desc = {
705         .name = MODULE_NAME,
706         .ctrls = sd_ctrls,
707         .nctrls = ARRAY_SIZE(sd_ctrls),
708         .config = sd_config,
709         .open = sd_open,
710         .start = sd_start,
711         .stopN = sd_stopN,
712         .stop0 = sd_stop0,
713         .close = sd_close,
714         .pkt_scan = sd_pkt_scan,
715 };
716
717 /* -- module initialisation -- */
718 #define DVNM(name) .driver_info = (kernel_ulong_t) name
719 static __devinitdata struct usb_device_id device_table[] = {
720         {USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")},
721         {USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")},
722         {USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")},
723         {USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")},
724         {USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera")},
725                         /* and also ', Trust WB-3350p, SIGMA cam 2350' */
726         {USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")},
727         {USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")},
728         {}
729 };
730 MODULE_DEVICE_TABLE(usb, device_table);
731
732 /* -- device connect -- */
733 static int sd_probe(struct usb_interface *intf,
734                         const struct usb_device_id *id)
735 {
736         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
737                                 THIS_MODULE);
738 }
739
740 static struct usb_driver sd_driver = {
741         .name = MODULE_NAME,
742         .id_table = device_table,
743         .probe = sd_probe,
744         .disconnect = gspca_disconnect,
745 };
746
747 /* -- module insert / remove -- */
748 static int __init sd_mod_init(void)
749 {
750         if (usb_register(&sd_driver) < 0)
751                 return -1;
752         PDEBUG(D_PROBE, "v%s registered", version);
753         return 0;
754 }
755 static void __exit sd_mod_exit(void)
756 {
757         usb_deregister(&sd_driver);
758         PDEBUG(D_PROBE, "deregistered");
759 }
760
761 module_init(sd_mod_init);
762 module_exit(sd_mod_exit);