Linux Audio

Check our new training course

Loading...
  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/* Some documentation about various registers as determined by trial and error.
 23 *
 24 * Register page 1:
 25 *
 26 * 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 *		bits 345 seem to toggle per color gains on/off (inverted)
 31 * 0x78		Global control, bit 6 controls the LED (inverted)
 32 * 0x80		Compression balance, interesting settings:
 33 *		0x01 Use this to allow the camera to switch to higher compr.
 34 *		     on the fly. Needed to stay within bandwidth @ 640x480@30
 35 *		0x1c From usb captures under Windows for 640x480
 36 *		0x2a Values >= this switch the camera to a lower compression,
 37 *		     using the same table for both luminance and chrominance.
 38 *		     This gives a sharper picture. Usable only at 640x480@ <
 39 *		     15 fps or 320x240 / 160x120. Note currently the driver
 40 *		     does not use this as the quality gain is small and the
 41 *		     generated JPG-s are only understood by v4l-utils >= 0.8.9
 42 *		0x3f From usb captures under Windows for 320x240
 43 *		0x69 From usb captures under Windows for 160x120
 44 *
 45 * Register page 4:
 46 *
 47 * Address	Description
 48 * 0x02		Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
 49 *		the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
 50 * 0x0f		Master gain 1-245, low value = high gain
 51 * 0x10		Another gain 0-15, limited influence (1-2x gain I guess)
 52 * 0x21		Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
 53 *		Note setting vflip disabled leads to a much lower image quality,
 54 *		so we always vflip, and tell userspace to flip it back
 55 * 0x27		Seems to toggle various gains on / off, Setting bit 7 seems to
 56 *		completely disable the analog amplification block. Set to 0x68
 57 *		for max gain, 0x14 for minimal gain.
 58 */
 59
 60#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 61
 62#define MODULE_NAME "pac7311"
 63
 64#include <linux/input.h>
 65#include "gspca.h"
 66/* Include pac common sof detection functions */
 67#include "pac_common.h"
 68
 69#define PAC7311_GAIN_DEFAULT     122
 70#define PAC7311_EXPOSURE_DEFAULT   3 /* 20 fps, avoid using high compr. */
 71
 72MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
 73MODULE_DESCRIPTION("Pixart PAC7311");
 74MODULE_LICENSE("GPL");
 75
 76struct sd {
 77	struct gspca_dev gspca_dev;		/* !! must be the first item */
 78
 79	struct v4l2_ctrl *contrast;
 80	struct v4l2_ctrl *hflip;
 81
 82	u8 sof_read;
 83	u8 autogain_ignore_frames;
 84
 85	atomic_t avg_lum;
 86};
 87
 88static const struct v4l2_pix_format vga_mode[] = {
 89	{160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
 90		.bytesperline = 160,
 91		.sizeimage = 160 * 120 * 3 / 8 + 590,
 92		.colorspace = V4L2_COLORSPACE_JPEG,
 93		.priv = 2},
 94	{320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
 95		.bytesperline = 320,
 96		.sizeimage = 320 * 240 * 3 / 8 + 590,
 97		.colorspace = V4L2_COLORSPACE_JPEG,
 98		.priv = 1},
 99	{640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
100		.bytesperline = 640,
101		.sizeimage = 640 * 480 * 3 / 8 + 590,
102		.colorspace = V4L2_COLORSPACE_JPEG,
103		.priv = 0},
104};
105
106#define LOAD_PAGE4		254
107#define END_OF_SEQUENCE		0
108
109static const __u8 init_7311[] = {
110	0xff, 0x01,
111	0x78, 0x40,	/* Bit_0=start stream, Bit_6=LED */
112	0x78, 0x40,	/* Bit_0=start stream, Bit_6=LED */
113	0x78, 0x44,	/* Bit_0=start stream, Bit_6=LED */
114	0xff, 0x04,
115	0x27, 0x80,
116	0x28, 0xca,
117	0x29, 0x53,
118	0x2a, 0x0e,
119	0xff, 0x01,
120	0x3e, 0x20,
121};
122
123static const __u8 start_7311[] = {
124/*	index, len, [value]* */
125	0xff, 1,	0x01,		/* page 1 */
126	0x02, 43,	0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
127			0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
128			0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
129			0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
130			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131			0x00, 0x00, 0x00,
132	0x3e, 42,	0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
133			0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
134			0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
135			0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
136			0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
137			0xd0, 0xff,
138	0x78, 6,	0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
139	0x7f, 18,	0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
140			0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
141			0x18, 0x20,
142	0x96, 3,	0x01, 0x08, 0x04,
143	0xa0, 4,	0x44, 0x44, 0x44, 0x04,
144	0xf0, 13,	0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
145			0x3f, 0x00, 0x0a, 0x01, 0x00,
146	0xff, 1,	0x04,		/* page 4 */
147	0, LOAD_PAGE4,			/* load the page 4 */
148	0x11, 1,	0x01,
149	0, END_OF_SEQUENCE		/* end of sequence */
150};
151
152#define SKIP		0xaa
153/* page 4 - the value SKIP says skip the index - see reg_w_page() */
154static const __u8 page4_7311[] = {
155	SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
156	0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
157	0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
158	0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
159	SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
160	0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
161	0x23, 0x28, 0x04, 0x11, 0x00, 0x00
162};
163
164static void reg_w_buf(struct gspca_dev *gspca_dev,
165		  __u8 index,
166		  const u8 *buffer, int len)
167{
168	int ret;
169
170	if (gspca_dev->usb_err < 0)
171		return;
172	memcpy(gspca_dev->usb_buf, buffer, len);
173	ret = usb_control_msg(gspca_dev->dev,
174			usb_sndctrlpipe(gspca_dev->dev, 0),
175			0,		/* request */
176			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
177			0,		/* value */
178			index, gspca_dev->usb_buf, len,
179			500);
180	if (ret < 0) {
181		pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
182		       index, ret);
183		gspca_dev->usb_err = ret;
184	}
185}
186
187
188static void reg_w(struct gspca_dev *gspca_dev,
189		  __u8 index,
190		  __u8 value)
191{
192	int ret;
193
194	if (gspca_dev->usb_err < 0)
195		return;
196	gspca_dev->usb_buf[0] = value;
197	ret = usb_control_msg(gspca_dev->dev,
198			usb_sndctrlpipe(gspca_dev->dev, 0),
199			0,			/* request */
200			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
201			0, index, gspca_dev->usb_buf, 1,
202			500);
203	if (ret < 0) {
204		pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
205		       index, value, ret);
206		gspca_dev->usb_err = ret;
207	}
208}
209
210static void reg_w_seq(struct gspca_dev *gspca_dev,
211		const __u8 *seq, int len)
212{
213	while (--len >= 0) {
214		reg_w(gspca_dev, seq[0], seq[1]);
215		seq += 2;
216	}
217}
218
219/* load the beginning of a page */
220static void reg_w_page(struct gspca_dev *gspca_dev,
221			const __u8 *page, int len)
222{
223	int index;
224	int ret = 0;
225
226	if (gspca_dev->usb_err < 0)
227		return;
228	for (index = 0; index < len; index++) {
229		if (page[index] == SKIP)		/* skip this index */
230			continue;
231		gspca_dev->usb_buf[0] = page[index];
232		ret = usb_control_msg(gspca_dev->dev,
233				usb_sndctrlpipe(gspca_dev->dev, 0),
234				0,			/* request */
235			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
236				0, index, gspca_dev->usb_buf, 1,
237				500);
238		if (ret < 0) {
239			pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
240			       index, page[index], ret);
241			gspca_dev->usb_err = ret;
242			break;
243		}
244	}
245}
246
247/* output a variable sequence */
248static void reg_w_var(struct gspca_dev *gspca_dev,
249			const __u8 *seq,
250			const __u8 *page4, unsigned int page4_len)
251{
252	int index, len;
253
254	for (;;) {
255		index = *seq++;
256		len = *seq++;
257		switch (len) {
258		case END_OF_SEQUENCE:
259			return;
260		case LOAD_PAGE4:
261			reg_w_page(gspca_dev, page4, page4_len);
262			break;
263		default:
264			if (len > USB_BUF_SZ) {
265				PDEBUG(D_ERR|D_STREAM,
266					"Incorrect variable sequence");
267				return;
268			}
269			while (len > 0) {
270				if (len < 8) {
271					reg_w_buf(gspca_dev,
272						index, seq, len);
273					seq += len;
274					break;
275				}
276				reg_w_buf(gspca_dev, index, seq, 8);
277				seq += 8;
278				index += 8;
279				len -= 8;
280			}
281		}
282	}
283	/* not reached */
284}
285
286/* this function is called at probe time for pac7311 */
287static int sd_config(struct gspca_dev *gspca_dev,
288			const struct usb_device_id *id)
289{
290	struct cam *cam = &gspca_dev->cam;
291
292	cam->cam_mode = vga_mode;
293	cam->nmodes = ARRAY_SIZE(vga_mode);
294	cam->input_flags = V4L2_IN_ST_VFLIP;
295
296	return 0;
297}
298
299static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
300{
301	reg_w(gspca_dev, 0xff, 0x04);
302	reg_w(gspca_dev, 0x10, val);
303	/* load registers to sensor (Bit 0, auto clear) */
304	reg_w(gspca_dev, 0x11, 0x01);
305}
306
307static void setgain(struct gspca_dev *gspca_dev, s32 val)
308{
309	reg_w(gspca_dev, 0xff, 0x04);			/* page 4 */
310	reg_w(gspca_dev, 0x0e, 0x00);
311	reg_w(gspca_dev, 0x0f, gspca_dev->gain->maximum - val + 1);
312
313	/* load registers to sensor (Bit 0, auto clear) */
314	reg_w(gspca_dev, 0x11, 0x01);
315}
316
317static void setexposure(struct gspca_dev *gspca_dev, s32 val)
318{
319	reg_w(gspca_dev, 0xff, 0x04);			/* page 4 */
320	reg_w(gspca_dev, 0x02, val);
321
322	/* load registers to sensor (Bit 0, auto clear) */
323	reg_w(gspca_dev, 0x11, 0x01);
324
325	/*
326	 * Page 1 register 8 must always be 0x08 except when not in
327	 *  640x480 mode and page 4 reg 2 <= 3 then it must be 9
328	 */
329	reg_w(gspca_dev, 0xff, 0x01);
330	if (gspca_dev->width != 640 && val <= 3)
331		reg_w(gspca_dev, 0x08, 0x09);
332	else
333		reg_w(gspca_dev, 0x08, 0x08);
334
335	/*
336	 * Page1 register 80 sets the compression balance, normally we
337	 * want / use 0x1c, but for 640x480@30fps we must allow the
338	 * camera to use higher compression or we may run out of
339	 * bandwidth.
340	 */
341	if (gspca_dev->width == 640 && val == 2)
342		reg_w(gspca_dev, 0x80, 0x01);
343	else
344		reg_w(gspca_dev, 0x80, 0x1c);
345
346	/* load registers to sensor (Bit 0, auto clear) */
347	reg_w(gspca_dev, 0x11, 0x01);
348}
349
350static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
351{
352	__u8 data;
353
354	reg_w(gspca_dev, 0xff, 0x04);			/* page 4 */
355	data = (hflip ? 0x04 : 0x00) |
356	       (vflip ? 0x08 : 0x00);
357	reg_w(gspca_dev, 0x21, data);
358
359	/* load registers to sensor (Bit 0, auto clear) */
360	reg_w(gspca_dev, 0x11, 0x01);
361}
362
363/* this function is called at probe and resume time for pac7311 */
364static int sd_init(struct gspca_dev *gspca_dev)
365{
366	reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
367	return gspca_dev->usb_err;
368}
369
370static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
371{
372	struct gspca_dev *gspca_dev =
373		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
374	struct sd *sd = (struct sd *)gspca_dev;
375
376	gspca_dev->usb_err = 0;
377
378	if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
379		/* when switching to autogain set defaults to make sure
380		   we are on a valid point of the autogain gain /
381		   exposure knee graph, and give this change time to
382		   take effect before doing autogain. */
383		gspca_dev->exposure->val    = PAC7311_EXPOSURE_DEFAULT;
384		gspca_dev->gain->val        = PAC7311_GAIN_DEFAULT;
385		sd->autogain_ignore_frames  = PAC_AUTOGAIN_IGNORE_FRAMES;
386	}
387
388	if (!gspca_dev->streaming)
389		return 0;
390
391	switch (ctrl->id) {
392	case V4L2_CID_CONTRAST:
393		setcontrast(gspca_dev, ctrl->val);
394		break;
395	case V4L2_CID_AUTOGAIN:
396		if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
397			setexposure(gspca_dev, gspca_dev->exposure->val);
398		if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
399			setgain(gspca_dev, gspca_dev->gain->val);
400		break;
401	case V4L2_CID_HFLIP:
402		sethvflip(gspca_dev, sd->hflip->val, 1);
403		break;
404	default:
405		return -EINVAL;
406	}
407	return gspca_dev->usb_err;
408}
409
410static const struct v4l2_ctrl_ops sd_ctrl_ops = {
411	.s_ctrl = sd_s_ctrl,
412};
413
414/* this function is called at probe time */
415static int sd_init_controls(struct gspca_dev *gspca_dev)
416{
417	struct sd *sd = (struct sd *) gspca_dev;
418	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
419
420	gspca_dev->vdev.ctrl_handler = hdl;
421	v4l2_ctrl_handler_init(hdl, 5);
422
423	sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
424					V4L2_CID_CONTRAST, 0, 15, 1, 7);
425	gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
426					V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
427	gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
428					V4L2_CID_EXPOSURE, 2, 63, 1,
429					PAC7311_EXPOSURE_DEFAULT);
430	gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
431					V4L2_CID_GAIN, 0, 244, 1,
432					PAC7311_GAIN_DEFAULT);
433	sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
434		V4L2_CID_HFLIP, 0, 1, 1, 0);
435
436	if (hdl->error) {
437		pr_err("Could not initialize controls\n");
438		return hdl->error;
439	}
440
441	v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
442	return 0;
443}
444
445/* -- start the camera -- */
446static int sd_start(struct gspca_dev *gspca_dev)
447{
448	struct sd *sd = (struct sd *) gspca_dev;
449
450	sd->sof_read = 0;
451
452	reg_w_var(gspca_dev, start_7311,
453		page4_7311, sizeof(page4_7311));
454	setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
455	setgain(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->gain));
456	setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
457	sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 1);
458
459	/* set correct resolution */
460	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
461	case 2:					/* 160x120 */
462		reg_w(gspca_dev, 0xff, 0x01);
463		reg_w(gspca_dev, 0x17, 0x20);
464		reg_w(gspca_dev, 0x87, 0x10);
465		break;
466	case 1:					/* 320x240 */
467		reg_w(gspca_dev, 0xff, 0x01);
468		reg_w(gspca_dev, 0x17, 0x30);
469		reg_w(gspca_dev, 0x87, 0x11);
470		break;
471	case 0:					/* 640x480 */
472		reg_w(gspca_dev, 0xff, 0x01);
473		reg_w(gspca_dev, 0x17, 0x00);
474		reg_w(gspca_dev, 0x87, 0x12);
475		break;
476	}
477
478	sd->sof_read = 0;
479	sd->autogain_ignore_frames = 0;
480	atomic_set(&sd->avg_lum, -1);
481
482	/* start stream */
483	reg_w(gspca_dev, 0xff, 0x01);
484	reg_w(gspca_dev, 0x78, 0x05);
485
486	return gspca_dev->usb_err;
487}
488
489static void sd_stopN(struct gspca_dev *gspca_dev)
490{
491	reg_w(gspca_dev, 0xff, 0x04);
492	reg_w(gspca_dev, 0x27, 0x80);
493	reg_w(gspca_dev, 0x28, 0xca);
494	reg_w(gspca_dev, 0x29, 0x53);
495	reg_w(gspca_dev, 0x2a, 0x0e);
496	reg_w(gspca_dev, 0xff, 0x01);
497	reg_w(gspca_dev, 0x3e, 0x20);
498	reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
499	reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
500	reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
501}
502
503static void do_autogain(struct gspca_dev *gspca_dev)
504{
505	struct sd *sd = (struct sd *) gspca_dev;
506	int avg_lum = atomic_read(&sd->avg_lum);
507	int desired_lum, deadzone;
508
509	if (avg_lum == -1)
510		return;
511
512	desired_lum = 170;
513	deadzone = 20;
514
515	if (sd->autogain_ignore_frames > 0)
516		sd->autogain_ignore_frames--;
517	else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
518						    desired_lum, deadzone))
519		sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
520}
521
522/* JPEG header, part 1 */
523static const unsigned char pac_jpeg_header1[] = {
524  0xff, 0xd8,		/* SOI: Start of Image */
525
526  0xff, 0xc0,		/* SOF0: Start of Frame (Baseline DCT) */
527  0x00, 0x11,		/* length = 17 bytes (including this length field) */
528  0x08			/* Precision: 8 */
529  /* 2 bytes is placed here: number of image lines */
530  /* 2 bytes is placed here: samples per line */
531};
532
533/* JPEG header, continued */
534static const unsigned char pac_jpeg_header2[] = {
535  0x03,			/* Number of image components: 3 */
536  0x01, 0x21, 0x00,	/* ID=1, Subsampling 1x1, Quantization table: 0 */
537  0x02, 0x11, 0x01,	/* ID=2, Subsampling 2x1, Quantization table: 1 */
538  0x03, 0x11, 0x01,	/* ID=3, Subsampling 2x1, Quantization table: 1 */
539
540  0xff, 0xda,		/* SOS: Start Of Scan */
541  0x00, 0x0c,		/* length = 12 bytes (including this length field) */
542  0x03,			/* number of components: 3 */
543  0x01, 0x00,		/* selector 1, table 0x00 */
544  0x02, 0x11,		/* selector 2, table 0x11 */
545  0x03, 0x11,		/* selector 3, table 0x11 */
546  0x00, 0x3f,		/* Spectral selection: 0 .. 63 */
547  0x00			/* Successive approximation: 0 */
548};
549
550static void pac_start_frame(struct gspca_dev *gspca_dev,
551		__u16 lines, __u16 samples_per_line)
552{
553	unsigned char tmpbuf[4];
554
555	gspca_frame_add(gspca_dev, FIRST_PACKET,
556		pac_jpeg_header1, sizeof(pac_jpeg_header1));
557
558	tmpbuf[0] = lines >> 8;
559	tmpbuf[1] = lines & 0xff;
560	tmpbuf[2] = samples_per_line >> 8;
561	tmpbuf[3] = samples_per_line & 0xff;
562
563	gspca_frame_add(gspca_dev, INTER_PACKET,
564		tmpbuf, sizeof(tmpbuf));
565	gspca_frame_add(gspca_dev, INTER_PACKET,
566		pac_jpeg_header2, sizeof(pac_jpeg_header2));
567}
568
569/* this function is run at interrupt level */
570static void sd_pkt_scan(struct gspca_dev *gspca_dev,
571			u8 *data,			/* isoc packet */
572			int len)			/* iso packet length */
573{
574	struct sd *sd = (struct sd *) gspca_dev;
575	u8 *image;
576	unsigned char *sof;
577
578	sof = pac_find_sof(&sd->sof_read, data, len);
579	if (sof) {
580		int n, lum_offset, footer_length;
581
582		/*
583		 * 6 bytes after the FF D9 EOF marker a number of lumination
584		 * bytes are send corresponding to different parts of the
585		 * image, the 14th and 15th byte after the EOF seem to
586		 * correspond to the center of the image.
587		 */
588		lum_offset = 24 + sizeof pac_sof_marker;
589		footer_length = 26;
590
591		/* Finish decoding current frame */
592		n = (sof - data) - (footer_length + sizeof pac_sof_marker);
593		if (n < 0) {
594			gspca_dev->image_len += n;
595			n = 0;
596		} else {
597			gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
598		}
599		image = gspca_dev->image;
600		if (image != NULL
601		 && image[gspca_dev->image_len - 2] == 0xff
602		 && image[gspca_dev->image_len - 1] == 0xd9)
603			gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
604
605		n = sof - data;
606		len -= n;
607		data = sof;
608
609		/* Get average lumination */
610		if (gspca_dev->last_packet_type == LAST_PACKET &&
611				n >= lum_offset)
612			atomic_set(&sd->avg_lum, data[-lum_offset] +
613						data[-lum_offset + 1]);
614		else
615			atomic_set(&sd->avg_lum, -1);
616
617		/* Start the new frame with the jpeg header */
618		pac_start_frame(gspca_dev,
619			gspca_dev->height, gspca_dev->width);
620	}
621	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
622}
623
624#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
625static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
626			u8 *data,		/* interrupt packet data */
627			int len)		/* interrupt packet length */
628{
629	int ret = -EINVAL;
630	u8 data0, data1;
631
632	if (len == 2) {
633		data0 = data[0];
634		data1 = data[1];
635		if ((data0 == 0x00 && data1 == 0x11) ||
636		    (data0 == 0x22 && data1 == 0x33) ||
637		    (data0 == 0x44 && data1 == 0x55) ||
638		    (data0 == 0x66 && data1 == 0x77) ||
639		    (data0 == 0x88 && data1 == 0x99) ||
640		    (data0 == 0xaa && data1 == 0xbb) ||
641		    (data0 == 0xcc && data1 == 0xdd) ||
642		    (data0 == 0xee && data1 == 0xff)) {
643			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
644			input_sync(gspca_dev->input_dev);
645			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
646			input_sync(gspca_dev->input_dev);
647			ret = 0;
648		}
649	}
650
651	return ret;
652}
653#endif
654
655static const struct sd_desc sd_desc = {
656	.name = MODULE_NAME,
657	.config = sd_config,
658	.init = sd_init,
659	.init_controls = sd_init_controls,
660	.start = sd_start,
661	.stopN = sd_stopN,
662	.pkt_scan = sd_pkt_scan,
663	.dq_callback = do_autogain,
664#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
665	.int_pkt_scan = sd_int_pkt_scan,
666#endif
667};
668
669/* -- module initialisation -- */
670static const struct usb_device_id device_table[] = {
671	{USB_DEVICE(0x093a, 0x2600)},
672	{USB_DEVICE(0x093a, 0x2601)},
673	{USB_DEVICE(0x093a, 0x2603)},
674	{USB_DEVICE(0x093a, 0x2608)},
675	{USB_DEVICE(0x093a, 0x260e)},
676	{USB_DEVICE(0x093a, 0x260f)},
677	{}
678};
679MODULE_DEVICE_TABLE(usb, device_table);
680
681/* -- device connect -- */
682static int sd_probe(struct usb_interface *intf,
683			const struct usb_device_id *id)
684{
685	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
686				THIS_MODULE);
687}
688
689static struct usb_driver sd_driver = {
690	.name = MODULE_NAME,
691	.id_table = device_table,
692	.probe = sd_probe,
693	.disconnect = gspca_disconnect,
694#ifdef CONFIG_PM
695	.suspend = gspca_suspend,
696	.resume = gspca_resume,
697#endif
698};
699
700module_usb_driver(sd_driver);