pac7311.c 18.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 *		Pixart PAC7311 library
 *		Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
 *
 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

22 23 24 25 26
/* Some documentation about various registers as determined by trial and error.

   Register page 1:

   Address	Description
27
   0x08		Unknown compressor related, must always be 8 except when not
28
		in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
29
   0x1b		Auto white balance related, bit 0 is AWB enable (inverted)
30 31
		bits 345 seem to toggle per color gains on/off (inverted)
   0x78		Global control, bit 6 controls the LED (inverted)
32
   0x80		JPEG compression ratio ? Best not touched
33

34
   Register page 4:
35 36 37

   Address	Description
   0x02		Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
38
		the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
39 40
   0x0f		Master gain 1-245, low value = high gain
   0x10		Another gain 0-15, limited influence (1-2x gain I guess)
41
   0x21		Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
42
   0x27		Seems to toggle various gains on / off, Setting bit 7 seems to
43 44
		completely disable the analog amplification block. Set to 0x68
		for max gain, 0x14 for minimal gain.
45 46
*/

47 48
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

49 50
#define MODULE_NAME "pac7311"

51
#include <linux/input.h>
52
#include "gspca.h"
53 54
/* Include pac common sof detection functions */
#include "pac_common.h"
55 56 57 58 59

MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
MODULE_DESCRIPTION("Pixart PAC7311");
MODULE_LICENSE("GPL");

60 61 62 63 64 65 66 67 68 69
enum e_ctrl {
	CONTRAST,
	GAIN,
	EXPOSURE,
	AUTOGAIN,
	HFLIP,
	VFLIP,
	NCTRLS		/* number of controls */
};

70 71
struct sd {
	struct gspca_dev gspca_dev;		/* !! must be the first item */
72
	struct gspca_ctrl ctrls[NCTRLS];
73 74
	int exp_too_low_cnt;
	int exp_too_high_cnt;
75

76 77 78 79
	u8 sof_read;
	u8 autogain_ignore_frames;

	atomic_t avg_lum;
80 81 82
};

/* V4L2 controls supported by the driver */
83 84 85 86
static void setcontrast(struct gspca_dev *gspca_dev);
static void setgain(struct gspca_dev *gspca_dev);
static void setexposure(struct gspca_dev *gspca_dev);
static void sethvflip(struct gspca_dev *gspca_dev);
87

88
static const struct ctrl sd_ctrls[] = {
89
[CONTRAST] = {
90 91 92 93 94
	    {
		.id      = V4L2_CID_CONTRAST,
		.type    = V4L2_CTRL_TYPE_INTEGER,
		.name    = "Contrast",
		.minimum = 0,
95
		.maximum = 15,
96
		.step    = 1,
97
		.default_value = 7,
98
	    },
99
	    .set_control = setcontrast
100
	},
101
[GAIN] = {
102 103 104 105 106
	    {
		.id      = V4L2_CID_GAIN,
		.type    = V4L2_CTRL_TYPE_INTEGER,
		.name    = "Gain",
		.minimum = 0,
107
		.maximum = 244,
108
		.step    = 1,
109
		.default_value = 122,
110
	    },
111
	    .set_control = setgain,
112
	},
113
[EXPOSURE] = {
114 115 116 117
	    {
		.id      = V4L2_CID_EXPOSURE,
		.type    = V4L2_CTRL_TYPE_INTEGER,
		.name    = "Exposure",
118
		.minimum = 2,
119
		.maximum = 63,
120
		.step    = 1,
121
		.default_value = 3, /* 20 fps, avoid using high compr. */
122
	    },
123
	    .set_control = setexposure,
124
	},
125
[AUTOGAIN] = {
126 127 128 129 130 131 132
	    {
		.id      = V4L2_CID_AUTOGAIN,
		.type    = V4L2_CTRL_TYPE_BOOLEAN,
		.name    = "Auto Gain",
		.minimum = 0,
		.maximum = 1,
		.step    = 1,
133
		.default_value = 1,
134 135
	    },
	},
136
[HFLIP] = {
137 138 139 140 141 142 143
	    {
		.id      = V4L2_CID_HFLIP,
		.type    = V4L2_CTRL_TYPE_BOOLEAN,
		.name    = "Mirror",
		.minimum = 0,
		.maximum = 1,
		.step    = 1,
144
		.default_value = 0,
145
	    },
146
	    .set_control = sethvflip,
147
	},
148
[VFLIP] = {
149 150 151 152 153 154 155
	    {
		.id      = V4L2_CID_VFLIP,
		.type    = V4L2_CTRL_TYPE_BOOLEAN,
		.name    = "Vflip",
		.minimum = 0,
		.maximum = 1,
		.step    = 1,
156
		.default_value = 0,
157
	    },
158
	    .set_control = sethvflip,
159
	},
160 161
};

162
static const struct v4l2_pix_format vga_mode[] = {
163
	{160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
164 165 166 167
		.bytesperline = 160,
		.sizeimage = 160 * 120 * 3 / 8 + 590,
		.colorspace = V4L2_COLORSPACE_JPEG,
		.priv = 2},
168
	{320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
169 170 171 172
		.bytesperline = 320,
		.sizeimage = 320 * 240 * 3 / 8 + 590,
		.colorspace = V4L2_COLORSPACE_JPEG,
		.priv = 1},
173
	{640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
174 175 176 177
		.bytesperline = 640,
		.sizeimage = 640 * 480 * 3 / 8 + 590,
		.colorspace = V4L2_COLORSPACE_JPEG,
		.priv = 0},
178 179
};

180 181 182
#define LOAD_PAGE4		254
#define END_OF_SEQUENCE		0

183
static const __u8 init_7311[] = {
184 185 186
	0x78, 0x40,	/* Bit_0=start stream, Bit_6=LED */
	0x78, 0x40,	/* Bit_0=start stream, Bit_6=LED */
	0x78, 0x44,	/* Bit_0=start stream, Bit_6=LED */
187 188 189 190 191 192 193 194 195 196 197
	0xff, 0x04,
	0x27, 0x80,
	0x28, 0xca,
	0x29, 0x53,
	0x2a, 0x0e,
	0xff, 0x01,
	0x3e, 0x20,
};

static const __u8 start_7311[] = {
/*	index, len, [value]* */
198 199
	0xff, 1,	0x01,		/* page 1 */
	0x02, 43,	0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
200 201 202 203 204
			0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
			0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
			0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, 0x00, 0x00,
205
	0x3e, 42,	0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
206 207 208 209 210 211 212 213 214 215 216 217 218
			0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
			0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
			0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
			0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
			0xd0, 0xff,
	0x78, 6,	0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
	0x7f, 18,	0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
			0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
			0x18, 0x20,
	0x96, 3,	0x01, 0x08, 0x04,
	0xa0, 4,	0x44, 0x44, 0x44, 0x04,
	0xf0, 13,	0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
			0x3f, 0x00, 0x0a, 0x01, 0x00,
219
	0xff, 1,	0x04,		/* page 4 */
220
	0, LOAD_PAGE4,			/* load the page 4 */
221
	0x11, 1,	0x01,
222
	0, END_OF_SEQUENCE		/* end of sequence */
223 224
};

225
#define SKIP		0xaa
226
/* page 4 - the value SKIP says skip the index - see reg_w_page() */
227
static const __u8 page4_7311[] = {
228 229 230 231 232
	SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
	0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
	0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
	SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
233 234 235 236
	0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
	0x23, 0x28, 0x04, 0x11, 0x00, 0x00
};

237
static void reg_w_buf(struct gspca_dev *gspca_dev,
238
		  __u8 index,
239
		  const u8 *buffer, int len)
240
{
241 242
	int ret;

243 244
	if (gspca_dev->usb_err < 0)
		return;
245
	memcpy(gspca_dev->usb_buf, buffer, len);
246
	ret = usb_control_msg(gspca_dev->dev,
247
			usb_sndctrlpipe(gspca_dev->dev, 0),
248
			0,		/* request */
249
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
250
			0,		/* value */
251
			index, gspca_dev->usb_buf, len,
252
			500);
253
	if (ret < 0) {
254 255
		pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
		       index, ret);
256 257
		gspca_dev->usb_err = ret;
	}
258 259 260
}


261
static void reg_w(struct gspca_dev *gspca_dev,
262
		  __u8 index,
263
		  __u8 value)
264
{
265 266
	int ret;

267 268
	if (gspca_dev->usb_err < 0)
		return;
269
	gspca_dev->usb_buf[0] = value;
270
	ret = usb_control_msg(gspca_dev->dev,
271
			usb_sndctrlpipe(gspca_dev->dev, 0),
272 273
			0,			/* request */
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
274
			0, index, gspca_dev->usb_buf, 1,
275
			500);
276
	if (ret < 0) {
277 278
		pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
		       index, value, ret);
279 280
		gspca_dev->usb_err = ret;
	}
281 282
}

283
static void reg_w_seq(struct gspca_dev *gspca_dev,
284 285 286
		const __u8 *seq, int len)
{
	while (--len >= 0) {
287
		reg_w(gspca_dev, seq[0], seq[1]);
288 289 290 291 292
		seq += 2;
	}
}

/* load the beginning of a page */
293
static void reg_w_page(struct gspca_dev *gspca_dev,
294 295 296
			const __u8 *page, int len)
{
	int index;
297
	int ret = 0;
298

299 300
	if (gspca_dev->usb_err < 0)
		return;
301
	for (index = 0; index < len; index++) {
302
		if (page[index] == SKIP)		/* skip this index */
303 304
			continue;
		gspca_dev->usb_buf[0] = page[index];
305
		ret = usb_control_msg(gspca_dev->dev,
306 307 308 309 310
				usb_sndctrlpipe(gspca_dev->dev, 0),
				0,			/* request */
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
				0, index, gspca_dev->usb_buf, 1,
				500);
311
		if (ret < 0) {
312 313
			pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
			       index, page[index], ret);
314
			gspca_dev->usb_err = ret;
315 316
			break;
		}
317 318 319 320
	}
}

/* output a variable sequence */
321
static void reg_w_var(struct gspca_dev *gspca_dev,
322 323
			const __u8 *seq,
			const __u8 *page4, unsigned int page4_len)
324 325 326 327 328 329 330
{
	int index, len;

	for (;;) {
		index = *seq++;
		len = *seq++;
		switch (len) {
331
		case END_OF_SEQUENCE:
332
			return;
333
		case LOAD_PAGE4:
334
			reg_w_page(gspca_dev, page4, page4_len);
335 336
			break;
		default:
337
			if (len > USB_BUF_SZ) {
338 339
				PDEBUG(D_ERR|D_STREAM,
					"Incorrect variable sequence");
340
				return;
341 342 343
			}
			while (len > 0) {
				if (len < 8) {
344
					reg_w_buf(gspca_dev,
345
						index, seq, len);
346 347 348
					seq += len;
					break;
				}
349
				reg_w_buf(gspca_dev, index, seq, 8);
350 351 352 353 354 355 356 357 358
				seq += 8;
				index += 8;
				len -= 8;
			}
		}
	}
	/* not reached */
}

359
/* this function is called at probe time for pac7311 */
360 361 362 363
static int sd_config(struct gspca_dev *gspca_dev,
			const struct usb_device_id *id)
{
	struct sd *sd = (struct sd *) gspca_dev;
364
	struct cam *cam = &gspca_dev->cam;
365

366 367
	cam->cam_mode = vga_mode;
	cam->nmodes = ARRAY_SIZE(vga_mode);
368

369 370
	gspca_dev->cam.ctrls = sd->ctrls;

371 372 373
	return 0;
}

374
static void setcontrast(struct gspca_dev *gspca_dev)
375 376
{
	struct sd *sd = (struct sd *) gspca_dev;
377

378
	reg_w(gspca_dev, 0xff, 0x04);
379
	reg_w(gspca_dev, 0x10, sd->ctrls[CONTRAST].val);
380
	/* load registers to sensor (Bit 0, auto clear) */
381
	reg_w(gspca_dev, 0x11, 0x01);
382 383
}

384
static void setgain(struct gspca_dev *gspca_dev)
385 386
{
	struct sd *sd = (struct sd *) gspca_dev;
387

388 389
	reg_w(gspca_dev, 0xff, 0x04);			/* page 4 */
	reg_w(gspca_dev, 0x0e, 0x00);
390
	reg_w(gspca_dev, 0x0f, sd->ctrls[GAIN].max - sd->ctrls[GAIN].val + 1);
391 392

	/* load registers to sensor (Bit 0, auto clear) */
393
	reg_w(gspca_dev, 0x11, 0x01);
394 395
}

396
static void setexposure(struct gspca_dev *gspca_dev)
397 398 399
{
	struct sd *sd = (struct sd *) gspca_dev;

400
	reg_w(gspca_dev, 0xff, 0x04);			/* page 4 */
401
	reg_w(gspca_dev, 0x02, sd->ctrls[EXPOSURE].val);
402

403 404 405
	/* load registers to sensor (Bit 0, auto clear) */
	reg_w(gspca_dev, 0x11, 0x01);

406
	/* Page 1 register 8 must always be 0x08 except when not in
407
	   640x480 mode and page 4 reg 2 <= 3 then it must be 9 */
408
	reg_w(gspca_dev, 0xff, 0x01);
409
	if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
410
			sd->ctrls[EXPOSURE].val <= 3) {
411
		reg_w(gspca_dev, 0x08, 0x09);
412
	} else {
413
		reg_w(gspca_dev, 0x08, 0x08);
414
	}
415

416
	/* load registers to sensor (Bit 0, auto clear) */
417
	reg_w(gspca_dev, 0x11, 0x01);
418 419
}

420
static void sethvflip(struct gspca_dev *gspca_dev)
421 422 423 424
{
	struct sd *sd = (struct sd *) gspca_dev;
	__u8 data;

425
	reg_w(gspca_dev, 0xff, 0x04);			/* page 4 */
426 427
	data = (sd->ctrls[HFLIP].val ? 0x04 : 0x00) |
	       (sd->ctrls[VFLIP].val ? 0x08 : 0x00);
428 429
	reg_w(gspca_dev, 0x21, data);

430
	/* load registers to sensor (Bit 0, auto clear) */
431
	reg_w(gspca_dev, 0x11, 0x01);
432 433
}

434
/* this function is called at probe and resume time for pac7311 */
435
static int sd_init(struct gspca_dev *gspca_dev)
436
{
437 438
	reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
	return gspca_dev->usb_err;
439 440
}

441
static int sd_start(struct gspca_dev *gspca_dev)
442
{
443 444
	struct sd *sd = (struct sd *) gspca_dev;

445
	sd->sof_read = 0;
446

447
	reg_w_var(gspca_dev, start_7311,
448
		page4_7311, sizeof(page4_7311));
449 450 451 452
	setcontrast(gspca_dev);
	setgain(gspca_dev);
	setexposure(gspca_dev);
	sethvflip(gspca_dev);
453 454

	/* set correct resolution */
455
	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
456
	case 2:					/* 160x120 */
457 458 459
		reg_w(gspca_dev, 0xff, 0x01);
		reg_w(gspca_dev, 0x17, 0x20);
		reg_w(gspca_dev, 0x87, 0x10);
460
		break;
461
	case 1:					/* 320x240 */
462 463 464
		reg_w(gspca_dev, 0xff, 0x01);
		reg_w(gspca_dev, 0x17, 0x30);
		reg_w(gspca_dev, 0x87, 0x11);
465 466
		break;
	case 0:					/* 640x480 */
467 468 469
		reg_w(gspca_dev, 0xff, 0x01);
		reg_w(gspca_dev, 0x17, 0x00);
		reg_w(gspca_dev, 0x87, 0x12);
470 471 472
		break;
	}

473 474 475
	sd->sof_read = 0;
	sd->autogain_ignore_frames = 0;
	atomic_set(&sd->avg_lum, -1);
476 477

	/* start stream */
478 479
	reg_w(gspca_dev, 0xff, 0x01);
	reg_w(gspca_dev, 0x78, 0x05);
480

481
	return gspca_dev->usb_err;
482 483 484 485
}

static void sd_stopN(struct gspca_dev *gspca_dev)
{
486 487 488 489 490 491 492 493 494 495
	reg_w(gspca_dev, 0xff, 0x04);
	reg_w(gspca_dev, 0x27, 0x80);
	reg_w(gspca_dev, 0x28, 0xca);
	reg_w(gspca_dev, 0x29, 0x53);
	reg_w(gspca_dev, 0x2a, 0x0e);
	reg_w(gspca_dev, 0xff, 0x01);
	reg_w(gspca_dev, 0x3e, 0x20);
	reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
	reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
	reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
496 497
}

498
#define WANT_COARSE_EXPO_AUTOGAIN
499
#include "autogain_functions.h"
500

501
static void do_autogain(struct gspca_dev *gspca_dev)
502
{
503 504
	struct sd *sd = (struct sd *) gspca_dev;
	int avg_lum = atomic_read(&sd->avg_lum);
505
	int desired_lum, deadzone;
506

507
	if (sd->ctrls[AUTOGAIN].val == 0 || avg_lum == -1)
508 509
		return;

510 511
	desired_lum = 200;
	deadzone = 20;
512 513 514

	if (sd->autogain_ignore_frames > 0)
		sd->autogain_ignore_frames--;
515 516
	else if (coarse_grained_expo_autogain(gspca_dev, avg_lum, desired_lum,
			deadzone))
517
		sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
518 519
}

520
/* JPEG header, part 1 */
521
static const unsigned char pac_jpeg_header1[] = {
522 523 524 525 526 527 528
  0xff, 0xd8,		/* SOI: Start of Image */

  0xff, 0xc0,		/* SOF0: Start of Frame (Baseline DCT) */
  0x00, 0x11,		/* length = 17 bytes (including this length field) */
  0x08			/* Precision: 8 */
  /* 2 bytes is placed here: number of image lines */
  /* 2 bytes is placed here: samples per line */
529 530
};

531
/* JPEG header, continued */
532
static const unsigned char pac_jpeg_header2[] = {
533 534 535 536 537 538 539 540 541 542 543 544 545
  0x03,			/* Number of image components: 3 */
  0x01, 0x21, 0x00,	/* ID=1, Subsampling 1x1, Quantization table: 0 */
  0x02, 0x11, 0x01,	/* ID=2, Subsampling 2x1, Quantization table: 1 */
  0x03, 0x11, 0x01,	/* ID=3, Subsampling 2x1, Quantization table: 1 */

  0xff, 0xda,		/* SOS: Start Of Scan */
  0x00, 0x0c,		/* length = 12 bytes (including this length field) */
  0x03,			/* number of components: 3 */
  0x01, 0x00,		/* selector 1, table 0x00 */
  0x02, 0x11,		/* selector 2, table 0x11 */
  0x03, 0x11,		/* selector 3, table 0x11 */
  0x00, 0x3f,		/* Spectral selection: 0 .. 63 */
  0x00			/* Successive approximation: 0 */
546 547
};

548 549 550 551 552
static void pac_start_frame(struct gspca_dev *gspca_dev,
		__u16 lines, __u16 samples_per_line)
{
	unsigned char tmpbuf[4];

553
	gspca_frame_add(gspca_dev, FIRST_PACKET,
554 555 556 557 558 559 560
		pac_jpeg_header1, sizeof(pac_jpeg_header1));

	tmpbuf[0] = lines >> 8;
	tmpbuf[1] = lines & 0xff;
	tmpbuf[2] = samples_per_line >> 8;
	tmpbuf[3] = samples_per_line & 0xff;

561
	gspca_frame_add(gspca_dev, INTER_PACKET,
562
		tmpbuf, sizeof(tmpbuf));
563
	gspca_frame_add(gspca_dev, INTER_PACKET,
564 565 566
		pac_jpeg_header2, sizeof(pac_jpeg_header2));
}

567
/* this function is run at interrupt level */
568
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
569
			u8 *data,			/* isoc packet */
570 571 572
			int len)			/* iso packet length */
{
	struct sd *sd = (struct sd *) gspca_dev;
573
	u8 *image;
574 575
	unsigned char *sof;

576
	sof = pac_find_sof(&sd->sof_read, data, len);
577 578 579
	if (sof) {
		int n, lum_offset, footer_length;

580 581 582 583 584 585
		/* 6 bytes after the FF D9 EOF marker a number of lumination
		   bytes are send corresponding to different parts of the
		   image, the 14th and 15th byte after the EOF seem to
		   correspond to the center of the image */
		lum_offset = 24 + sizeof pac_sof_marker;
		footer_length = 26;
586 587 588 589

		/* Finish decoding current frame */
		n = (sof - data) - (footer_length + sizeof pac_sof_marker);
		if (n < 0) {
590
			gspca_dev->image_len += n;
591
			n = 0;
592 593
		} else {
			gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
594
		}
595 596
		image = gspca_dev->image;
		if (image != NULL
597 598 599
		 && image[gspca_dev->image_len - 2] == 0xff
		 && image[gspca_dev->image_len - 1] == 0xd9)
			gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
600 601 602 603 604 605 606

		n = sof - data;
		len -= n;
		data = sof;

		/* Get average lumination */
		if (gspca_dev->last_packet_type == LAST_PACKET &&
607 608
				n >= lum_offset)
			atomic_set(&sd->avg_lum, data[-lum_offset] +
609
						data[-lum_offset + 1]);
610
		else
611 612 613
			atomic_set(&sd->avg_lum, -1);

		/* Start the new frame with the jpeg header */
614
		pac_start_frame(gspca_dev,
615
			gspca_dev->height, gspca_dev->width);
616
	}
617
	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
618 619
}

620
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
			u8 *data,		/* interrupt packet data */
			int len)		/* interrupt packet length */
{
	int ret = -EINVAL;
	u8 data0, data1;

	if (len == 2) {
		data0 = data[0];
		data1 = data[1];
		if ((data0 == 0x00 && data1 == 0x11) ||
		    (data0 == 0x22 && data1 == 0x33) ||
		    (data0 == 0x44 && data1 == 0x55) ||
		    (data0 == 0x66 && data1 == 0x77) ||
		    (data0 == 0x88 && data1 == 0x99) ||
		    (data0 == 0xaa && data1 == 0xbb) ||
		    (data0 == 0xcc && data1 == 0xdd) ||
		    (data0 == 0xee && data1 == 0xff)) {
			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
			input_sync(gspca_dev->input_dev);
			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
			input_sync(gspca_dev->input_dev);
			ret = 0;
		}
	}

	return ret;
}
#endif

651
static const struct sd_desc sd_desc = {
652 653 654 655
	.name = MODULE_NAME,
	.ctrls = sd_ctrls,
	.nctrls = ARRAY_SIZE(sd_ctrls),
	.config = sd_config,
656
	.init = sd_init,
657 658 659
	.start = sd_start,
	.stopN = sd_stopN,
	.pkt_scan = sd_pkt_scan,
660
	.dq_callback = do_autogain,
661
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
662 663
	.int_pkt_scan = sd_int_pkt_scan,
#endif
664 665 666
};

/* -- module initialisation -- */
667
static const struct usb_device_id device_table[] = {
668 669 670 671 672 673
	{USB_DEVICE(0x093a, 0x2600)},
	{USB_DEVICE(0x093a, 0x2601)},
	{USB_DEVICE(0x093a, 0x2603)},
	{USB_DEVICE(0x093a, 0x2608)},
	{USB_DEVICE(0x093a, 0x260e)},
	{USB_DEVICE(0x093a, 0x260f)},
674 675 676 677 678
	{}
};
MODULE_DEVICE_TABLE(usb, device_table);

/* -- device connect -- */
679
static int sd_probe(struct usb_interface *intf,
680 681 682 683 684 685 686 687 688 689 690
			const struct usb_device_id *id)
{
	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
				THIS_MODULE);
}

static struct usb_driver sd_driver = {
	.name = MODULE_NAME,
	.id_table = device_table,
	.probe = sd_probe,
	.disconnect = gspca_disconnect,
691 692 693 694
#ifdef CONFIG_PM
	.suspend = gspca_suspend,
	.resume = gspca_resume,
#endif
695 696
};

697
module_usb_driver(sd_driver);