cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pac7311.c (19356B)


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