V4L/DVB: gscpa_pac7311: Add support for camera button
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / video / gspca / pac7311.c
blob44fed9686729340777e9425b1ad5e10e56204651
1 /*
2 * Pixart PAC7311 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 /* Some documentation about various registers as determined by trial and error.
23 When the register addresses differ between the 7202 and the 7311 the 2
24 different addresses are written as 7302addr/7311addr, when one of the 2
25 addresses is a - sign that register description is not valid for the
26 matching IC.
28 Register page 1:
30 Address Description
31 -/0x08 Unknown compressor related, must always be 8 except when not
32 in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
33 -/0x1b Auto white balance related, bit 0 is AWB enable (inverted)
34 bits 345 seem to toggle per color gains on/off (inverted)
35 0x78 Global control, bit 6 controls the LED (inverted)
36 -/0x80 JPEG compression ratio ? Best not touched
38 Register page 3/4:
40 Address Description
41 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
42 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
43 -/0x0f Master gain 1-245, low value = high gain
44 0x10/- Master gain 0-31
45 -/0x10 Another gain 0-15, limited influence (1-2x gain I guess)
46 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
47 -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
48 completely disable the analog amplification block. Set to 0x68
49 for max gain, 0x14 for minimal gain.
52 #define MODULE_NAME "pac7311"
54 #include <linux/input.h>
55 #include "gspca.h"
57 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
58 MODULE_DESCRIPTION("Pixart PAC7311");
59 MODULE_LICENSE("GPL");
61 /* specific webcam descriptor for pac7311 */
62 struct sd {
63 struct gspca_dev gspca_dev; /* !! must be the first item */
65 unsigned char contrast;
66 unsigned char gain;
67 unsigned char exposure;
68 unsigned char autogain;
69 __u8 hflip;
70 __u8 vflip;
72 u8 sof_read;
73 u8 autogain_ignore_frames;
75 atomic_t avg_lum;
78 /* V4L2 controls supported by the driver */
79 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
80 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
81 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
82 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
83 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
84 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
85 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
86 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
87 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
88 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
89 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
90 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
92 static const struct ctrl sd_ctrls[] = {
93 /* This control is for both the 7302 and the 7311 */
96 .id = V4L2_CID_CONTRAST,
97 .type = V4L2_CTRL_TYPE_INTEGER,
98 .name = "Contrast",
99 .minimum = 0,
100 #define CONTRAST_MAX 255
101 .maximum = CONTRAST_MAX,
102 .step = 1,
103 #define CONTRAST_DEF 127
104 .default_value = CONTRAST_DEF,
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
109 /* All controls below are for both the 7302 and the 7311 */
112 .id = V4L2_CID_GAIN,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Gain",
115 .minimum = 0,
116 #define GAIN_MAX 255
117 .maximum = GAIN_MAX,
118 .step = 1,
119 #define GAIN_DEF 127
120 #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
121 .default_value = GAIN_DEF,
123 .set = sd_setgain,
124 .get = sd_getgain,
128 .id = V4L2_CID_EXPOSURE,
129 .type = V4L2_CTRL_TYPE_INTEGER,
130 .name = "Exposure",
131 .minimum = 0,
132 #define EXPOSURE_MAX 255
133 .maximum = EXPOSURE_MAX,
134 .step = 1,
135 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
136 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
137 .default_value = EXPOSURE_DEF,
139 .set = sd_setexposure,
140 .get = sd_getexposure,
144 .id = V4L2_CID_AUTOGAIN,
145 .type = V4L2_CTRL_TYPE_BOOLEAN,
146 .name = "Auto Gain",
147 .minimum = 0,
148 .maximum = 1,
149 .step = 1,
150 #define AUTOGAIN_DEF 1
151 .default_value = AUTOGAIN_DEF,
153 .set = sd_setautogain,
154 .get = sd_getautogain,
158 .id = V4L2_CID_HFLIP,
159 .type = V4L2_CTRL_TYPE_BOOLEAN,
160 .name = "Mirror",
161 .minimum = 0,
162 .maximum = 1,
163 .step = 1,
164 #define HFLIP_DEF 0
165 .default_value = HFLIP_DEF,
167 .set = sd_sethflip,
168 .get = sd_gethflip,
172 .id = V4L2_CID_VFLIP,
173 .type = V4L2_CTRL_TYPE_BOOLEAN,
174 .name = "Vflip",
175 .minimum = 0,
176 .maximum = 1,
177 .step = 1,
178 #define VFLIP_DEF 0
179 .default_value = VFLIP_DEF,
181 .set = sd_setvflip,
182 .get = sd_getvflip,
186 static const struct v4l2_pix_format vga_mode[] = {
187 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
188 .bytesperline = 160,
189 .sizeimage = 160 * 120 * 3 / 8 + 590,
190 .colorspace = V4L2_COLORSPACE_JPEG,
191 .priv = 2},
192 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
193 .bytesperline = 320,
194 .sizeimage = 320 * 240 * 3 / 8 + 590,
195 .colorspace = V4L2_COLORSPACE_JPEG,
196 .priv = 1},
197 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
198 .bytesperline = 640,
199 .sizeimage = 640 * 480 * 3 / 8 + 590,
200 .colorspace = V4L2_COLORSPACE_JPEG,
201 .priv = 0},
204 #define LOAD_PAGE4 254
205 #define END_OF_SEQUENCE 0
207 /* pac 7311 */
208 static const __u8 init_7311[] = {
209 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
210 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
211 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
212 0xff, 0x04,
213 0x27, 0x80,
214 0x28, 0xca,
215 0x29, 0x53,
216 0x2a, 0x0e,
217 0xff, 0x01,
218 0x3e, 0x20,
221 static const __u8 start_7311[] = {
222 /* index, len, [value]* */
223 0xff, 1, 0x01, /* page 1 */
224 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
225 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
226 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
227 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00,
230 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
231 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
232 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
233 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
234 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
235 0xd0, 0xff,
236 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
237 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
238 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
239 0x18, 0x20,
240 0x96, 3, 0x01, 0x08, 0x04,
241 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
242 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
243 0x3f, 0x00, 0x0a, 0x01, 0x00,
244 0xff, 1, 0x04, /* page 4 */
245 0, LOAD_PAGE4, /* load the page 4 */
246 0x11, 1, 0x01,
247 0, END_OF_SEQUENCE /* end of sequence */
250 #define SKIP 0xaa
251 /* page 4 - the value SKIP says skip the index - see reg_w_page() */
252 static const __u8 page4_7311[] = {
253 SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
254 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
255 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
257 SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
258 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
259 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
262 static void reg_w_buf(struct gspca_dev *gspca_dev,
263 __u8 index,
264 const char *buffer, int len)
266 int ret;
268 if (gspca_dev->usb_err < 0)
269 return;
270 memcpy(gspca_dev->usb_buf, buffer, len);
271 ret = usb_control_msg(gspca_dev->dev,
272 usb_sndctrlpipe(gspca_dev->dev, 0),
273 1, /* request */
274 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
275 0, /* value */
276 index, gspca_dev->usb_buf, len,
277 500);
278 if (ret < 0) {
279 PDEBUG(D_ERR, "reg_w_buf(): "
280 "Failed to write registers to index 0x%x, error %i",
281 index, ret);
282 gspca_dev->usb_err = ret;
287 static void reg_w(struct gspca_dev *gspca_dev,
288 __u8 index,
289 __u8 value)
291 int ret;
293 if (gspca_dev->usb_err < 0)
294 return;
295 gspca_dev->usb_buf[0] = value;
296 ret = usb_control_msg(gspca_dev->dev,
297 usb_sndctrlpipe(gspca_dev->dev, 0),
298 0, /* request */
299 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
300 0, index, gspca_dev->usb_buf, 1,
301 500);
302 if (ret < 0) {
303 PDEBUG(D_ERR, "reg_w(): "
304 "Failed to write register to index 0x%x, value 0x%x, error %i",
305 index, value, ret);
306 gspca_dev->usb_err = ret;
310 static void reg_w_seq(struct gspca_dev *gspca_dev,
311 const __u8 *seq, int len)
313 while (--len >= 0) {
314 reg_w(gspca_dev, seq[0], seq[1]);
315 seq += 2;
319 /* load the beginning of a page */
320 static void reg_w_page(struct gspca_dev *gspca_dev,
321 const __u8 *page, int len)
323 int index;
324 int ret = 0;
326 if (gspca_dev->usb_err < 0)
327 return;
328 for (index = 0; index < len; index++) {
329 if (page[index] == SKIP) /* skip this index */
330 continue;
331 gspca_dev->usb_buf[0] = page[index];
332 ret = usb_control_msg(gspca_dev->dev,
333 usb_sndctrlpipe(gspca_dev->dev, 0),
334 0, /* request */
335 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
336 0, index, gspca_dev->usb_buf, 1,
337 500);
338 if (ret < 0) {
339 PDEBUG(D_ERR, "reg_w_page(): "
340 "Failed to write register to index 0x%x, "
341 "value 0x%x, error %i",
342 index, page[index], ret);
343 gspca_dev->usb_err = ret;
344 break;
349 /* output a variable sequence */
350 static void reg_w_var(struct gspca_dev *gspca_dev,
351 const __u8 *seq,
352 const __u8 *page4, unsigned int page4_len)
354 int index, len;
356 for (;;) {
357 index = *seq++;
358 len = *seq++;
359 switch (len) {
360 case END_OF_SEQUENCE:
361 return;
362 case LOAD_PAGE4:
363 reg_w_page(gspca_dev, page4, page4_len);
364 break;
365 default:
366 if (len > USB_BUF_SZ) {
367 PDEBUG(D_ERR|D_STREAM,
368 "Incorrect variable sequence");
369 return;
371 while (len > 0) {
372 if (len < 8) {
373 reg_w_buf(gspca_dev,
374 index, seq, len);
375 seq += len;
376 break;
378 reg_w_buf(gspca_dev, index, seq, 8);
379 seq += 8;
380 index += 8;
381 len -= 8;
385 /* not reached */
388 /* this function is called at probe time for pac7311 */
389 static int sd_config(struct gspca_dev *gspca_dev,
390 const struct usb_device_id *id)
392 struct sd *sd = (struct sd *) gspca_dev;
393 struct cam *cam;
395 cam = &gspca_dev->cam;
397 PDEBUG(D_CONF, "Find Sensor PAC7311");
398 cam->cam_mode = vga_mode;
399 cam->nmodes = ARRAY_SIZE(vga_mode);
401 sd->contrast = CONTRAST_DEF;
402 sd->gain = GAIN_DEF;
403 sd->exposure = EXPOSURE_DEF;
404 sd->autogain = AUTOGAIN_DEF;
405 sd->hflip = HFLIP_DEF;
406 sd->vflip = VFLIP_DEF;
407 return 0;
410 /* This function is used by pac7311 only */
411 static void setcontrast(struct gspca_dev *gspca_dev)
413 struct sd *sd = (struct sd *) gspca_dev;
415 reg_w(gspca_dev, 0xff, 0x04);
416 reg_w(gspca_dev, 0x10, sd->contrast >> 4);
417 /* load registers to sensor (Bit 0, auto clear) */
418 reg_w(gspca_dev, 0x11, 0x01);
421 static void setgain(struct gspca_dev *gspca_dev)
423 struct sd *sd = (struct sd *) gspca_dev;
424 int gain = GAIN_MAX - sd->gain;
426 if (gain < 1)
427 gain = 1;
428 else if (gain > 245)
429 gain = 245;
430 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
431 reg_w(gspca_dev, 0x0e, 0x00);
432 reg_w(gspca_dev, 0x0f, gain);
434 /* load registers to sensor (Bit 0, auto clear) */
435 reg_w(gspca_dev, 0x11, 0x01);
438 static void setexposure(struct gspca_dev *gspca_dev)
440 struct sd *sd = (struct sd *) gspca_dev;
441 __u8 reg;
443 /* register 2 of frame 3/4 contains the clock divider configuring the
444 no fps according to the formula: 60 / reg. sd->exposure is the
445 desired exposure time in ms. */
446 reg = 120 * sd->exposure / 1000;
447 if (reg < 2)
448 reg = 2;
449 else if (reg > 63)
450 reg = 63;
452 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
453 reg_w(gspca_dev, 0x02, reg);
455 /* Page 1 register 8 must always be 0x08 except when not in
456 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
457 reg_w(gspca_dev, 0xff, 0x01);
458 if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
459 reg <= 3) {
460 reg_w(gspca_dev, 0x08, 0x09);
461 } else {
462 reg_w(gspca_dev, 0x08, 0x08);
465 /* load registers to sensor (Bit 0, auto clear) */
466 reg_w(gspca_dev, 0x11, 0x01);
469 static void sethvflip(struct gspca_dev *gspca_dev)
471 struct sd *sd = (struct sd *) gspca_dev;
472 __u8 data;
474 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
475 data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00);
476 reg_w(gspca_dev, 0x21, data);
478 /* load registers to sensor (Bit 0, auto clear) */
479 reg_w(gspca_dev, 0x11, 0x01);
482 /* this function is called at probe and resume time for pac7311 */
483 static int sd_init(struct gspca_dev *gspca_dev)
485 reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
486 return gspca_dev->usb_err;
489 static int sd_start(struct gspca_dev *gspca_dev)
491 struct sd *sd = (struct sd *) gspca_dev;
493 sd->sof_read = 0;
495 reg_w_var(gspca_dev, start_7311,
496 page4_7311, sizeof(page4_7311));
497 setcontrast(gspca_dev);
498 setgain(gspca_dev);
499 setexposure(gspca_dev);
500 sethvflip(gspca_dev);
502 /* set correct resolution */
503 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
504 case 2: /* 160x120 pac7311 */
505 reg_w(gspca_dev, 0xff, 0x01);
506 reg_w(gspca_dev, 0x17, 0x20);
507 reg_w(gspca_dev, 0x87, 0x10);
508 break;
509 case 1: /* 320x240 pac7311 */
510 reg_w(gspca_dev, 0xff, 0x01);
511 reg_w(gspca_dev, 0x17, 0x30);
512 reg_w(gspca_dev, 0x87, 0x11);
513 break;
514 case 0: /* 640x480 */
515 reg_w(gspca_dev, 0xff, 0x01);
516 reg_w(gspca_dev, 0x17, 0x00);
517 reg_w(gspca_dev, 0x87, 0x12);
518 break;
521 sd->sof_read = 0;
522 sd->autogain_ignore_frames = 0;
523 atomic_set(&sd->avg_lum, -1);
525 /* start stream */
526 reg_w(gspca_dev, 0xff, 0x01);
527 reg_w(gspca_dev, 0x78, 0x05);
529 return gspca_dev->usb_err;
532 static void sd_stopN(struct gspca_dev *gspca_dev)
534 reg_w(gspca_dev, 0xff, 0x04);
535 reg_w(gspca_dev, 0x27, 0x80);
536 reg_w(gspca_dev, 0x28, 0xca);
537 reg_w(gspca_dev, 0x29, 0x53);
538 reg_w(gspca_dev, 0x2a, 0x0e);
539 reg_w(gspca_dev, 0xff, 0x01);
540 reg_w(gspca_dev, 0x3e, 0x20);
541 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
542 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
543 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
546 /* called on streamoff with alt 0 and on disconnect for 7311 */
547 static void sd_stop0(struct gspca_dev *gspca_dev)
551 /* Include pac common sof detection functions */
552 #include "pac_common.h"
554 static void do_autogain(struct gspca_dev *gspca_dev)
556 struct sd *sd = (struct sd *) gspca_dev;
557 int avg_lum = atomic_read(&sd->avg_lum);
558 int desired_lum, deadzone;
560 if (avg_lum == -1)
561 return;
563 desired_lum = 200;
564 deadzone = 20;
566 if (sd->autogain_ignore_frames > 0)
567 sd->autogain_ignore_frames--;
568 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
569 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
570 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
573 /* JPEG header, part 1 */
574 static const unsigned char pac_jpeg_header1[] = {
575 0xff, 0xd8, /* SOI: Start of Image */
577 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
578 0x00, 0x11, /* length = 17 bytes (including this length field) */
579 0x08 /* Precision: 8 */
580 /* 2 bytes is placed here: number of image lines */
581 /* 2 bytes is placed here: samples per line */
584 /* JPEG header, continued */
585 static const unsigned char pac_jpeg_header2[] = {
586 0x03, /* Number of image components: 3 */
587 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
588 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
589 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
591 0xff, 0xda, /* SOS: Start Of Scan */
592 0x00, 0x0c, /* length = 12 bytes (including this length field) */
593 0x03, /* number of components: 3 */
594 0x01, 0x00, /* selector 1, table 0x00 */
595 0x02, 0x11, /* selector 2, table 0x11 */
596 0x03, 0x11, /* selector 3, table 0x11 */
597 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
598 0x00 /* Successive approximation: 0 */
601 static void pac_start_frame(struct gspca_dev *gspca_dev,
602 struct gspca_frame *frame,
603 __u16 lines, __u16 samples_per_line)
605 unsigned char tmpbuf[4];
607 gspca_frame_add(gspca_dev, FIRST_PACKET,
608 pac_jpeg_header1, sizeof(pac_jpeg_header1));
610 tmpbuf[0] = lines >> 8;
611 tmpbuf[1] = lines & 0xff;
612 tmpbuf[2] = samples_per_line >> 8;
613 tmpbuf[3] = samples_per_line & 0xff;
615 gspca_frame_add(gspca_dev, INTER_PACKET,
616 tmpbuf, sizeof(tmpbuf));
617 gspca_frame_add(gspca_dev, INTER_PACKET,
618 pac_jpeg_header2, sizeof(pac_jpeg_header2));
621 /* this function is run at interrupt level */
622 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
623 u8 *data, /* isoc packet */
624 int len) /* iso packet length */
626 struct sd *sd = (struct sd *) gspca_dev;
627 unsigned char *sof;
628 struct gspca_frame *frame;
630 sof = pac_find_sof(&sd->sof_read, data, len);
631 if (sof) {
632 int n, lum_offset, footer_length;
634 frame = gspca_get_i_frame(gspca_dev);
635 if (frame == NULL) {
636 gspca_dev->last_packet_type = DISCARD_PACKET;
637 return;
640 /* 6 bytes after the FF D9 EOF marker a number of lumination
641 bytes are send corresponding to different parts of the
642 image, the 14th and 15th byte after the EOF seem to
643 correspond to the center of the image */
644 lum_offset = 24 + sizeof pac_sof_marker;
645 footer_length = 26;
647 /* Finish decoding current frame */
648 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
649 if (n < 0) {
650 frame->data_end += n;
651 n = 0;
653 gspca_frame_add(gspca_dev, INTER_PACKET,
654 data, n);
655 if (gspca_dev->last_packet_type != DISCARD_PACKET &&
656 frame->data_end[-2] == 0xff &&
657 frame->data_end[-1] == 0xd9)
658 gspca_frame_add(gspca_dev, LAST_PACKET,
659 NULL, 0);
661 n = sof - data;
662 len -= n;
663 data = sof;
665 /* Get average lumination */
666 if (gspca_dev->last_packet_type == LAST_PACKET &&
667 n >= lum_offset)
668 atomic_set(&sd->avg_lum, data[-lum_offset] +
669 data[-lum_offset + 1]);
670 else
671 atomic_set(&sd->avg_lum, -1);
673 /* Start the new frame with the jpeg header */
674 pac_start_frame(gspca_dev, frame,
675 gspca_dev->height, gspca_dev->width);
677 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
680 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
682 struct sd *sd = (struct sd *) gspca_dev;
684 sd->contrast = val;
685 if (gspca_dev->streaming) {
686 setcontrast(gspca_dev);
688 return gspca_dev->usb_err;
691 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
693 struct sd *sd = (struct sd *) gspca_dev;
695 *val = sd->contrast;
696 return 0;
699 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
701 struct sd *sd = (struct sd *) gspca_dev;
703 sd->gain = val;
704 if (gspca_dev->streaming)
705 setgain(gspca_dev);
706 return gspca_dev->usb_err;
709 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
711 struct sd *sd = (struct sd *) gspca_dev;
713 *val = sd->gain;
714 return 0;
717 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
719 struct sd *sd = (struct sd *) gspca_dev;
721 sd->exposure = val;
722 if (gspca_dev->streaming)
723 setexposure(gspca_dev);
724 return gspca_dev->usb_err;
727 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
729 struct sd *sd = (struct sd *) gspca_dev;
731 *val = sd->exposure;
732 return 0;
735 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
737 struct sd *sd = (struct sd *) gspca_dev;
739 sd->autogain = val;
740 /* when switching to autogain set defaults to make sure
741 we are on a valid point of the autogain gain /
742 exposure knee graph, and give this change time to
743 take effect before doing autogain. */
744 if (sd->autogain) {
745 sd->exposure = EXPOSURE_DEF;
746 sd->gain = GAIN_DEF;
747 if (gspca_dev->streaming) {
748 sd->autogain_ignore_frames =
749 PAC_AUTOGAIN_IGNORE_FRAMES;
750 setexposure(gspca_dev);
751 setgain(gspca_dev);
755 return gspca_dev->usb_err;
758 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
760 struct sd *sd = (struct sd *) gspca_dev;
762 *val = sd->autogain;
763 return 0;
766 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
768 struct sd *sd = (struct sd *) gspca_dev;
770 sd->hflip = val;
771 if (gspca_dev->streaming)
772 sethvflip(gspca_dev);
773 return gspca_dev->usb_err;
776 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
778 struct sd *sd = (struct sd *) gspca_dev;
780 *val = sd->hflip;
781 return 0;
784 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
786 struct sd *sd = (struct sd *) gspca_dev;
788 sd->vflip = val;
789 if (gspca_dev->streaming)
790 sethvflip(gspca_dev);
791 return gspca_dev->usb_err;
794 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
796 struct sd *sd = (struct sd *) gspca_dev;
798 *val = sd->vflip;
799 return 0;
802 #ifdef CONFIG_INPUT
803 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
804 u8 *data, /* interrupt packet data */
805 int len) /* interrupt packet length */
807 int ret = -EINVAL;
808 u8 data0, data1;
810 if (len == 2) {
811 data0 = data[0];
812 data1 = data[1];
813 if ((data0 == 0x00 && data1 == 0x11) ||
814 (data0 == 0x22 && data1 == 0x33) ||
815 (data0 == 0x44 && data1 == 0x55) ||
816 (data0 == 0x66 && data1 == 0x77) ||
817 (data0 == 0x88 && data1 == 0x99) ||
818 (data0 == 0xaa && data1 == 0xbb) ||
819 (data0 == 0xcc && data1 == 0xdd) ||
820 (data0 == 0xee && data1 == 0xff)) {
821 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
822 input_sync(gspca_dev->input_dev);
823 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
824 input_sync(gspca_dev->input_dev);
825 ret = 0;
829 return ret;
831 #endif
833 /* sub-driver description for pac7311 */
834 static const struct sd_desc sd_desc = {
835 .name = MODULE_NAME,
836 .ctrls = sd_ctrls,
837 .nctrls = ARRAY_SIZE(sd_ctrls),
838 .config = sd_config,
839 .init = sd_init,
840 .start = sd_start,
841 .stopN = sd_stopN,
842 .stop0 = sd_stop0,
843 .pkt_scan = sd_pkt_scan,
844 .dq_callback = do_autogain,
845 #ifdef CONFIG_INPUT
846 .int_pkt_scan = sd_int_pkt_scan,
847 #endif
850 /* -- module initialisation -- */
851 static const struct usb_device_id device_table[] __devinitconst = {
852 {USB_DEVICE(0x093a, 0x2600)},
853 {USB_DEVICE(0x093a, 0x2601)},
854 {USB_DEVICE(0x093a, 0x2603)},
855 {USB_DEVICE(0x093a, 0x2608)},
856 {USB_DEVICE(0x093a, 0x260e)},
857 {USB_DEVICE(0x093a, 0x260f)},
860 MODULE_DEVICE_TABLE(usb, device_table);
862 /* -- device connect -- */
863 static int __devinit sd_probe(struct usb_interface *intf,
864 const struct usb_device_id *id)
866 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
867 THIS_MODULE);
870 static struct usb_driver sd_driver = {
871 .name = MODULE_NAME,
872 .id_table = device_table,
873 .probe = sd_probe,
874 .disconnect = gspca_disconnect,
875 #ifdef CONFIG_PM
876 .suspend = gspca_suspend,
877 .resume = gspca_resume,
878 #endif
881 /* -- module insert / remove -- */
882 static int __init sd_mod_init(void)
884 int ret;
885 ret = usb_register(&sd_driver);
886 if (ret < 0)
887 return ret;
888 PDEBUG(D_PROBE, "registered");
889 return 0;
891 static void __exit sd_mod_exit(void)
893 usb_deregister(&sd_driver);
894 PDEBUG(D_PROBE, "deregistered");
897 module_init(sd_mod_init);
898 module_exit(sd_mod_exit);