blob: 4e69a8e16357e1a6db5bedd50f591d864074e204 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 *Notes: * t613 + tas5130A
3 * * Focus to light do not balance well as in win.
4 * Quality in win is not good, but its kinda better.
5 * * Fix some "extraneous bytes", most of apps will show the image anyway
6 * * Gamma table, is there, but its really doing something?
7 * * 7~8 Fps, its ok, max on win its 10.
8 * Costantino Leandro
9 *
10 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#define MODULE_NAME "t613"
28#include "gspca.h"
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030029#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 4)
30static const char version[] = "2.1.4";
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030031
32#define MAX_GAMMA 0x10 /* 0 to 15 */
33
34/* From LUVCVIEW */
35#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
36
37MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
38MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
39MODULE_LICENSE("GPL");
40
41struct sd {
42 struct gspca_dev gspca_dev; /* !! must be the first item */
43
44 unsigned char brightness;
45 unsigned char contrast;
46 unsigned char colors;
47 unsigned char autogain;
48 unsigned char gamma;
49 unsigned char sharpness;
50 unsigned char freq;
51 unsigned char whitebalance;
52 unsigned char mirror;
53 unsigned char effect;
54};
55
56/* V4L2 controls supported by the driver */
57static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
58static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
59static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
60static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
61static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_querymenu(struct gspca_dev *gspca_dev,
78 struct v4l2_querymenu *menu);
79
80static struct ctrl sd_ctrls[] = {
81#define SD_BRIGHTNESS 0
82 {
83 {
84 .id = V4L2_CID_BRIGHTNESS,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "Brightness",
87 .minimum = 0,
88 .maximum = 0x0f,
89 .step = 1,
90 .default_value = 0x09,
91 },
92 .set = sd_setbrightness,
93 .get = sd_getbrightness,
94 },
95#define SD_CONTRAST 1
96 {
97 {
98 .id = V4L2_CID_CONTRAST,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Contrast",
101 .minimum = 0,
102 .maximum = 0x0d,
103 .step = 1,
104 .default_value = 0x07,
105 },
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
108 },
109#define SD_COLOR 2
110 {
111 {
112 .id = V4L2_CID_SATURATION,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Color",
115 .minimum = 0,
116 .maximum = 0x0f,
117 .step = 1,
118 .default_value = 0x05,
119 },
120 .set = sd_setcolors,
121 .get = sd_getcolors,
122 },
123#define SD_GAMMA 3
124 {
125 {
126 .id = V4L2_CID_GAMMA, /* (gamma on win) */
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Gamma (Untested)",
129 .minimum = 0,
130 .maximum = MAX_GAMMA,
131 .step = 1,
132 .default_value = 0x09,
133 },
134 .set = sd_setgamma,
135 .get = sd_getgamma,
136 },
137#define SD_AUTOGAIN 4
138 {
139 {
140 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
141 * some apps dont bring up the
142 * backligth_compensation control) */
143 .type = V4L2_CTRL_TYPE_INTEGER,
144 .name = "Low Light",
145 .minimum = 0,
146 .maximum = 1,
147 .step = 1,
148 .default_value = 0x01,
149 },
150 .set = sd_setlowlight,
151 .get = sd_getlowlight,
152 },
153#define SD_MIRROR 5
154 {
155 {
156 .id = V4L2_CID_HFLIP,
157 .type = V4L2_CTRL_TYPE_BOOLEAN,
158 .name = "Mirror Image",
159 .minimum = 0,
160 .maximum = 1,
161 .step = 1,
162 .default_value = 0,
163 },
164 .set = sd_setflip,
165 .get = sd_getflip
166 },
167#define SD_LIGHTFREQ 6
168 {
169 {
170 .id = V4L2_CID_POWER_LINE_FREQUENCY,
171 .type = V4L2_CTRL_TYPE_MENU,
172 .name = "Light Frequency Filter",
173 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
174 .maximum = 2,
175 .step = 1,
176 .default_value = 1,
177 },
178 .set = sd_setfreq,
179 .get = sd_getfreq},
180
181#define SD_WHITE_BALANCE 7
182 {
183 {
184 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "White Balance",
187 .minimum = 0,
188 .maximum = 1,
189 .step = 1,
190 .default_value = 1,
191 },
192 .set = sd_setwhitebalance,
193 .get = sd_getwhitebalance
194 },
195#define SD_SHARPNESS 8 /* (aka definition on win) */
196 {
197 {
198 .id = V4L2_CID_SHARPNESS,
199 .type = V4L2_CTRL_TYPE_INTEGER,
200 .name = "Sharpness",
201 .minimum = 0,
202 .maximum = MAX_GAMMA, /* 0 to 16 */
203 .step = 1,
204 .default_value = 0x06,
205 },
206 .set = sd_setsharpness,
207 .get = sd_getsharpness,
208 },
209#define SD_EFFECTS 9
210 {
211 {
212 .id = V4L2_CID_EFFECTS,
213 .type = V4L2_CTRL_TYPE_MENU,
214 .name = "Webcam Effects",
215 .minimum = 0,
216 .maximum = 4,
217 .step = 1,
218 .default_value = 0,
219 },
220 .set = sd_seteffect,
221 .get = sd_geteffect
222 },
223};
224
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300225static char *effects_control[] = {
226 "Normal",
227 "Emboss", /* disabled */
228 "Monochrome",
229 "Sepia",
230 "Sketch",
231 "Sun Effect", /* disabled */
232 "Negative",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300233};
234
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300235static struct cam_mode vga_mode_t16[] = {
236 {V4L2_PIX_FMT_JPEG, 160, 120, 4},
237 {V4L2_PIX_FMT_JPEG, 176, 144, 3},
238 {V4L2_PIX_FMT_JPEG, 320, 240, 2},
239 {V4L2_PIX_FMT_JPEG, 352, 288, 1},
240 {V4L2_PIX_FMT_JPEG, 640, 480, 0},
241};
242
243#define T16_OFFSET_DATA 631
244#define MAX_EFFECTS 7
245/* easily done by soft, this table could be removed,
246 * i keep it here just in case */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300247static const __u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300248 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
249 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
250 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
251 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
252 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
253 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
254 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
255};
256
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300257static const __u8 gamma_table[MAX_GAMMA][34] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300258 {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,
259 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
260 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
261 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
262 0xa0, 0xff},
263 {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75,
264 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD,
265 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4,
266 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7,
267 0xa0, 0xff},
268 {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B,
269 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6,
270 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0,
271 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6,
272 0xa0, 0xff},
273 {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,
274 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E,
275 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB,
276 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
277 0xa0, 0xff},
278 {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55,
279 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
280 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6,
281 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4,
282 0xa0, 0xff},
283 {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48,
284 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
285 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE,
286 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3,
287 0xa0, 0xff},
288 {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,
289 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
290 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
291 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
292 0xa0, 0xff},
293 {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,
294 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70,
295 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0,
296 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0,
297 0xa0, 0xff},
298 {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,
299 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79,
300 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6,
301 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0,
302 0xa0, 0xff},
303 {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,
304 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
305 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
306 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
307 0xa0, 0xff},
308 {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44,
309 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E,
310 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4,
311 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0,
312 0xa0, 0xff},
313 {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52,
314 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B,
315 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB,
316 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
317 0xa0, 0xff},
318 {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E,
319 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8,
320 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3,
321 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6,
322 0xA0, 0xFF},
323 {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83,
324 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7,
325 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC,
326 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9,
327 0xa0, 0xff},
328 {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A,
329 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6,
330 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3,
331 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA,
332 0xa0, 0xff},
333 {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7,
334 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8,
335 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED,
336 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC,
337 0xA0, 0xFF}
338};
339
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300340static const __u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300341 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
342 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
343 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
344 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
345 {},
346};
347
348static void t16RegRead(struct usb_device *dev,
349 __u16 index, __u8 *buffer, __u16 length)
350{
351 usb_control_msg(dev,
352 usb_rcvctrlpipe(dev, 0),
353 0, /* request */
354 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
355 0, /* value */
356 index, buffer, length, 500);
357}
358
359static void t16RegWrite(struct usb_device *dev,
360 __u16 value,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300361 __u16 index,
362 const __u8 *buffer, __u16 len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300363{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300364 if (buffer == NULL) {
365 usb_control_msg(dev,
366 usb_sndctrlpipe(dev, 0),
367 0,
368 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
369 value, index,
370 NULL, 0, 500);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300371 return;
372 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300373 if (len < 16) {
374 __u8 tmpbuf[16];
375
376 memcpy(tmpbuf, buffer, len);
377 usb_control_msg(dev,
378 usb_sndctrlpipe(dev, 0),
379 0,
380 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
381 value, index,
382 tmpbuf, len, 500);
383 } else {
384 __u8 *tmpbuf;
385
386 tmpbuf = kmalloc(len, GFP_KERNEL);
387 memcpy(tmpbuf, buffer, len);
388 usb_control_msg(dev,
389 usb_sndctrlpipe(dev, 0),
390 0,
391 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
392 value, index,
393 tmpbuf, len, 500);
394 kfree(tmpbuf);
395 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300396}
397
398/* this function is called at probe time */
399static int sd_config(struct gspca_dev *gspca_dev,
400 const struct usb_device_id *id)
401{
402 struct sd *sd = (struct sd *) gspca_dev;
403 struct cam *cam;
404
405 cam = &gspca_dev->cam;
406 cam->dev_name = (char *) id->driver_info;
407 cam->epaddr = 0x01;
408
409 cam->cam_mode = vga_mode_t16;
410 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
411
412 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
413 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
414 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
415 sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
416 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
417 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
418 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
419 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
420 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
421 return 0;
422}
423
424static int init_default_parameters(struct gspca_dev *gspca_dev)
425{
426 struct usb_device *dev = gspca_dev->dev;
427
428 /* some of this registers are not really neded, because
429 * they are overriden by setbrigthness, setcontrast, etc,
430 * but wont hurt anyway, and can help someone with similar webcam
431 * to see the initial parameters.*/
432 int i = 0;
433 __u8 test_byte;
434
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300435 static const __u8 read_indexs[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300436 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
437 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300438 static const __u8 n1[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300439 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300440 static const __u8 n2[2] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300441 {0x08, 0x00};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300442 static const __u8 nset[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300443 { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300444 static const __u8 n3[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300445 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300446 static const __u8 n4[0x46] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300447 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
448 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
449 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
450 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
451 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
452 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
453 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
454 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
455 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300456 static const __u8 nset4[18] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300457 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
458 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
459 0xe8, 0xe0
460 };
461 /* ojo puede ser 0xe6 en vez de 0xe9 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300462 static const __u8 nset2[20] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
464 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
465 0xd8, 0xc8, 0xd9, 0xfc
466 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300467 static const __u8 missing[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300468 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300469 static const __u8 nset3[18] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300470 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
471 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
472 0xcf, 0xe0
473 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300474 static const __u8 nset5[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300475 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300476 static const __u8 nset6[34] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300477 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
478 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
479 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
480 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
481 0xa0, 0xff
482 }; /* Gamma */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300483 static const __u8 nset7[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300484 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300485 static const __u8 nset9[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300486 { 0x0b, 0x04, 0x0a, 0x78 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300487 static const __u8 nset8[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300488 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300489 static const __u8 nset10[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300490 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
491
492 t16RegWrite(dev, 0x01, 0x0000, n1, 0x06);
493 t16RegWrite(dev, 0x01, 0x0000, nset, 0x06);
494 t16RegRead(dev, 0x0063, &test_byte, 1);
495 t16RegWrite(dev, 0x01, 0x0000, n2, 0x02);
496
497 while (read_indexs[i] != 0x00) {
498 t16RegRead(dev, read_indexs[i], &test_byte, 1);
499 PDEBUG(D_CONF, "Reg 0x%x => 0x%x", read_indexs[i],
500 test_byte);
501 i++;
502 }
503
504 t16RegWrite(dev, 0x01, 0x0000, n3, 0x06);
505 t16RegWrite(dev, 0x01, 0x0000, n4, 0x46);
506 t16RegRead(dev, 0x0080, &test_byte, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300507 t16RegWrite(dev, 0x00, 0x2c80, NULL, 0x0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300508 t16RegWrite(dev, 0x01, 0x0000, nset2, 0x14);
509 t16RegWrite(dev, 0x01, 0x0000, nset3, 0x12);
510 t16RegWrite(dev, 0x01, 0x0000, nset4, 0x12);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300511 t16RegWrite(dev, 0x00, 0x3880, NULL, 0x0);
512 t16RegWrite(dev, 0x00, 0x3880, NULL, 0x0);
513 t16RegWrite(dev, 0x00, 0x338e, NULL, 0x0);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300514 t16RegWrite(dev, 0x01, 0x0000, nset5, 0x04);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300515 t16RegWrite(dev, 0x00, 0x00a9, NULL, 0x0);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300516 t16RegWrite(dev, 0x01, 0x0000, nset6, 0x22);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300517 t16RegWrite(dev, 0x00, 0x86bb, NULL, 0x0);
518 t16RegWrite(dev, 0x00, 0x4aa6, NULL, 0x0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300519
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300520 t16RegWrite(dev, 0x01, 0x0000, missing, 0x08);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300521
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300522 t16RegWrite(dev, 0x00, 0x2087, NULL, 0x0);
523 t16RegWrite(dev, 0x00, 0x2088, NULL, 0x0);
524 t16RegWrite(dev, 0x00, 0x2089, NULL, 0x0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300525
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300526 t16RegWrite(dev, 0x01, 0x0000, nset7, 0x04);
527 t16RegWrite(dev, 0x01, 0x0000, nset10, 0x06);
528 t16RegWrite(dev, 0x01, 0x0000, nset8, 0x06);
529 t16RegWrite(dev, 0x01, 0x0000, nset9, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300531 t16RegWrite(dev, 0x00, 0x2880, NULL, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532 t16RegWrite(dev, 0x01, 0x0000, nset2, 0x14);
533 t16RegWrite(dev, 0x01, 0x0000, nset3, 0x12);
534 t16RegWrite(dev, 0x01, 0x0000, nset4, 0x12);
535
536 return 0;
537}
538
539static void setbrightness(struct gspca_dev *gspca_dev)
540{
541 struct sd *sd = (struct sd *) gspca_dev;
542 struct usb_device *dev = gspca_dev->dev;
543 unsigned int brightness;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300544 __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300545 brightness = sd->brightness;
546
547 if (brightness < 7) {
548 set6[3] = 0x70 - (brightness * 0xa);
549 } else {
550 set6[1] = 0x24;
551 set6[3] = 0x00 + ((brightness - 7) * 0xa);
552 }
553
554 t16RegWrite(dev, 0x01, 0x0000, set6, 4);
555}
556
557static void setflip(struct gspca_dev *gspca_dev)
558{
559 struct sd *sd = (struct sd *) gspca_dev;
560 struct usb_device *dev = gspca_dev->dev;
561
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300562 __u8 flipcmd[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300563 { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
564
565 if (sd->mirror == 1)
566 flipcmd[3] = 0x01;
567
568 t16RegWrite(dev, 0x01, 0x0000, flipcmd, 8);
569}
570
571static void seteffect(struct gspca_dev *gspca_dev)
572{
573 struct sd *sd = (struct sd *) gspca_dev;
574 struct usb_device *dev = gspca_dev->dev;
575
576 t16RegWrite(dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
577 if (sd->effect == 1 || sd->effect == 5) {
578 PDEBUG(D_CONF,
579 "This effect have been disabled for webcam \"safety\"");
580 return;
581 }
582
583 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300584 t16RegWrite(dev, 0x00, 0x4aa6, NULL, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300585 else
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300586 t16RegWrite(dev, 0x00, 0xfaa6, NULL, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300587}
588
589static void setwhitebalance(struct gspca_dev *gspca_dev)
590{
591 struct sd *sd = (struct sd *) gspca_dev;
592 struct usb_device *dev = gspca_dev->dev;
593
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300594 __u8 white_balance[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300595 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
596
597 if (sd->whitebalance == 1)
598 white_balance[7] = 0x3c;
599
600 t16RegWrite(dev, 0x01, 0x0000, white_balance, 8);
601}
602
603static void setlightfreq(struct gspca_dev *gspca_dev)
604{
605 struct sd *sd = (struct sd *) gspca_dev;
606 struct usb_device *dev = gspca_dev->dev;
607 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
608
609 if (sd->freq == 2) /* 60hz */
610 freq[1] = 0x00;
611
612 t16RegWrite(dev, 0x1, 0x0000, freq, 0x4);
613}
614
615static void setcontrast(struct gspca_dev *gspca_dev)
616{
617 struct sd *sd = (struct sd *) gspca_dev;
618 struct usb_device *dev = gspca_dev->dev;
619 unsigned int contrast = sd->contrast;
620 __u16 reg_to_write = 0x00;
621
622 if (contrast < 7)
623 reg_to_write = 0x8ea9 - (0x200 * contrast);
624 else
625 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
626
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300627 t16RegWrite(dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628}
629
630static void setcolors(struct gspca_dev *gspca_dev)
631{
632 struct sd *sd = (struct sd *) gspca_dev;
633 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300634 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300635
636 reg_to_write = 0xc0bb + sd->colors * 0x100;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300637 t16RegWrite(dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300638}
639
640static void setgamma(struct gspca_dev *gspca_dev)
641{
642}
643
644static void setsharpness(struct gspca_dev *gspca_dev)
645{
646 struct sd *sd = (struct sd *) gspca_dev;
647 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300648 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300649
650 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
651
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300652 t16RegWrite(dev, 0x00, reg_to_write, NULL, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300653}
654
655static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
656{
657 struct sd *sd = (struct sd *) gspca_dev;
658
659 sd->brightness = val;
660 if (gspca_dev->streaming)
661 setbrightness(gspca_dev);
662 return 0;
663}
664
665static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
666{
667 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300668
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300669 *val = sd->brightness;
670 return *val;
671}
672
673static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
674{
675 struct sd *sd = (struct sd *) gspca_dev;
676
677 sd->whitebalance = val;
678 if (gspca_dev->streaming)
679 setwhitebalance(gspca_dev);
680 return 0;
681}
682
683static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
684{
685 struct sd *sd = (struct sd *) gspca_dev;
686
687 *val = sd->whitebalance;
688 return *val;
689}
690
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300691static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
692{
693 struct sd *sd = (struct sd *) gspca_dev;
694
695 sd->mirror = val;
696 if (gspca_dev->streaming)
697 setflip(gspca_dev);
698 return 0;
699}
700
701static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
702{
703 struct sd *sd = (struct sd *) gspca_dev;
704
705 *val = sd->mirror;
706 return *val;
707}
708
709static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
710{
711 struct sd *sd = (struct sd *) gspca_dev;
712
713 sd->effect = val;
714 if (gspca_dev->streaming)
715 seteffect(gspca_dev);
716 return 0;
717}
718
719static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
720{
721 struct sd *sd = (struct sd *) gspca_dev;
722
723 *val = sd->effect;
724 return *val;
725}
726
727static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
728{
729 struct sd *sd = (struct sd *) gspca_dev;
730
731 sd->contrast = val;
732 if (gspca_dev->streaming)
733 setcontrast(gspca_dev);
734 return 0;
735}
736
737static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
738{
739 struct sd *sd = (struct sd *) gspca_dev;
740
741 *val = sd->contrast;
742 return *val;
743}
744
745static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
746{
747 struct sd *sd = (struct sd *) gspca_dev;
748
749 sd->colors = val;
750 if (gspca_dev->streaming)
751 setcolors(gspca_dev);
752 return 0;
753}
754
755static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
756{
757 struct sd *sd = (struct sd *) gspca_dev;
758
759 *val = sd->colors;
760 return 0;
761}
762
763static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
764{
765 struct sd *sd = (struct sd *) gspca_dev;
766
767 sd->gamma = val;
768 if (gspca_dev->streaming)
769 setgamma(gspca_dev);
770 return 0;
771}
772
773static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
774{
775 struct sd *sd = (struct sd *) gspca_dev;
776 *val = sd->gamma;
777 return 0;
778}
779
780static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
781{
782 struct sd *sd = (struct sd *) gspca_dev;
783
784 sd->freq = val;
785 if (gspca_dev->streaming)
786 setlightfreq(gspca_dev);
787 return 0;
788}
789
790static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
791{
792 struct sd *sd = (struct sd *) gspca_dev;
793
794 *val = sd->freq;
795 return 0;
796}
797
798static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
799{
800 struct sd *sd = (struct sd *) gspca_dev;
801
802 sd->sharpness = val;
803 if (gspca_dev->streaming)
804 setsharpness(gspca_dev);
805 return 0;
806}
807
808static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
809{
810 struct sd *sd = (struct sd *) gspca_dev;
811
812 *val = sd->sharpness;
813 return 0;
814}
815
816/* Low Light set here......*/
817static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
818{
819 struct sd *sd = (struct sd *) gspca_dev;
820 struct usb_device *dev = gspca_dev->dev;
821
822 sd->autogain = val;
823 if (val != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300824 t16RegWrite(dev, 0x00, 0xf48e, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300825 else
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300826 t16RegWrite(dev, 0x00, 0xb48e, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300827 return 0;
828}
829
830static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
831{
832 struct sd *sd = (struct sd *) gspca_dev;
833
834 *val = sd->autogain;
835 return 0;
836}
837
838static void sd_start(struct gspca_dev *gspca_dev)
839{
840 struct usb_device *dev = gspca_dev->dev;
841 int mode;
842 __u8 test_byte;
843
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300844 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300846 static const __u8 t3[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300847 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
848 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300849 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300850
851 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. mode;
852 switch (mode) {
853 case 1: /* 352x288 */
854 t2[1] = 0x40;
855 break;
856 case 2: /* 320x240 */
857 t2[1] = 0x10;
858 break;
859 case 3: /* 176x144 */
860 t2[1] = 0x50;
861 break;
862 case 4: /* 160x120 */
863 t2[1] = 0x20;
864 break;
865 default: /* 640x480 (0x00) */
866 break;
867 }
868
869 t16RegWrite(dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
870 t16RegWrite(dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
871 t16RegWrite(dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
872 t16RegWrite(dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300873 t16RegWrite(dev, 0x00, 0x3c80, NULL, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300874 /* just in case and to keep sync with logs (for mine) */
875 t16RegWrite(dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300876 t16RegWrite(dev, 0x00, 0x3c80, NULL, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300877 /* just in case and to keep sync with logs (for mine) */
878 t16RegWrite(dev, 0x01, 0x0000, t1, 4);
879 t16RegWrite(dev, 0x01, 0x0000, t2, 6);
880 t16RegRead(dev, 0x0012, &test_byte, 0x1);
881 t16RegWrite(dev, 0x01, 0x0000, t3, 0x10);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300882 t16RegWrite(dev, 0x00, 0x0013, NULL, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300883 t16RegWrite(dev, 0x01, 0x0000, t4, 0x4);
884 /* restart on each start, just in case, sometimes regs goes wrong
885 * when using controls from app */
886 setbrightness(gspca_dev);
887 setcontrast(gspca_dev);
888 setcolors(gspca_dev);
889}
890
891static void sd_stopN(struct gspca_dev *gspca_dev)
892{
893}
894
895static void sd_stop0(struct gspca_dev *gspca_dev)
896{
897}
898
899static void sd_close(struct gspca_dev *gspca_dev)
900{
901}
902
903static void sd_pkt_scan(struct gspca_dev *gspca_dev,
904 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300905 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300906 int len) /* iso packet length */
907{
908 int sof = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300909 static __u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910
911 if (data[0] == 0x5a) {
912 /* Control Packet, after this came the header again,
913 * but extra bytes came in the packet before this,
914 * sometimes an EOF arrives, sometimes not... */
915 return;
916 }
917
918 if (data[len - 1] == 0xff && data[len] == 0xd9) {
919 /* Just in case, i have seen packets with the marker,
920 * other's do not include it... */
921 data += 2;
922 len -= 4;
923 } else if (data[2] == 0xff && data[3] == 0xd8) {
924 sof = 1;
925 data += 2;
926 len -= 2;
927 } else {
928 data += 2;
929 len -= 2;
930 }
931
932 if (sof) {
933 /* extra bytes....., could be processed too but would be
934 * a waste of time, right now leave the application and
935 * libjpeg do it for ourserlves.. */
936 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
937 ffd9, 2);
938 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
939 return;
940 }
941
942 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
943}
944
945static int sd_querymenu(struct gspca_dev *gspca_dev,
946 struct v4l2_querymenu *menu)
947{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300948 switch (menu->id) {
949 case V4L2_CID_POWER_LINE_FREQUENCY:
950 switch (menu->index) {
951 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300952 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300953 return 0;
954 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300955 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 return 0;
957 }
958 break;
959 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300960 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
961 strncpy((char *) menu->name,
962 effects_control[menu->index], 32);
963 return 0;
964 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300965 break;
966 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300967 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300968}
969
970/* this function is called at open time */
971static int sd_open(struct gspca_dev *gspca_dev)
972{
973 init_default_parameters(gspca_dev);
974 return 0;
975}
976
977/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300978static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300979 .name = MODULE_NAME,
980 .ctrls = sd_ctrls,
981 .nctrls = ARRAY_SIZE(sd_ctrls),
982 .config = sd_config,
983 .open = sd_open,
984 .start = sd_start,
985 .stopN = sd_stopN,
986 .stop0 = sd_stop0,
987 .close = sd_close,
988 .pkt_scan = sd_pkt_scan,
989 .querymenu = sd_querymenu,
990};
991
992/* -- module initialisation -- */
993#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300994static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300995 {USB_DEVICE(0x17a1, 0x0128), DVNM("XPX Webcam")},
996 {}
997};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300998MODULE_DEVICE_TABLE(usb, device_table);
999
1000/* -- device connect -- */
1001static int sd_probe(struct usb_interface *intf,
1002 const struct usb_device_id *id)
1003{
1004 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1005 THIS_MODULE);
1006}
1007
1008static struct usb_driver sd_driver = {
1009 .name = MODULE_NAME,
1010 .id_table = device_table,
1011 .probe = sd_probe,
1012 .disconnect = gspca_disconnect,
1013};
1014
1015/* -- module insert / remove -- */
1016static int __init sd_mod_init(void)
1017{
1018 if (usb_register(&sd_driver) < 0)
1019 return -1;
1020 PDEBUG(D_PROBE, "v%s registered", version);
1021 return 0;
1022}
1023static void __exit sd_mod_exit(void)
1024{
1025 usb_deregister(&sd_driver);
1026 PDEBUG(D_PROBE, "deregistered");
1027}
1028
1029module_init(sd_mod_init);
1030module_exit(sd_mod_exit);