15b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/*
25b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * spca1528 subdriver
35b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine *
40dd826962716ff6984a14038d1604be816d759c3Jean-François Moine * Copyright (C) 2010-2011 Jean-Francois Moine (http://moinejf.free.fr)
55b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine *
65b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * This program is free software; you can redistribute it and/or modify
75b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * it under the terms of the GNU General Public License as published by
85b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * the Free Software Foundation; either version 2 of the License, or
95b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * any later version.
105b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine *
115b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * This program is distributed in the hope that it will be useful,
125b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * but WITHOUT ANY WARRANTY; without even the implied warranty of
135b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
145b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * GNU General Public License for more details.
155b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine *
165b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * You should have received a copy of the GNU General Public License
175b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * along with this program; if not, write to the Free Software
185b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
195b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine */
205b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
21133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches
235b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#define MODULE_NAME "spca1528"
245b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
255b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#include "gspca.h"
265b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#include "jpeg.h"
275b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
285b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François MoineMODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
295b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François MoineMODULE_DESCRIPTION("SPCA1528 USB Camera Driver");
305b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François MoineMODULE_LICENSE("GPL");
315b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
325b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/* specific webcam descriptor */
335b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestruct sd {
345b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct gspca_dev gspca_dev;	/* !! must be the first item */
355b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
365b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	u8 brightness;
375b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	u8 contrast;
385b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	u8 hue;
395b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	u8 color;
405b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	u8 sharpness;
415b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
425b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	u8 pkt_seq;
435b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
445b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	u8 jpeg_hdr[JPEG_HDR_SZ];
455b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine};
465b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
475b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/* V4L2 controls supported by the driver */
485b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
495b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
505b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
515b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
525b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
535b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
545b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_setcolor(struct gspca_dev *gspca_dev, __s32 val);
555b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_getcolor(struct gspca_dev *gspca_dev, __s32 *val);
565b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
575b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
585b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
595b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic const struct ctrl sd_ctrls[] = {
605b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	{
615b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    {
625b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.id      = V4L2_CID_BRIGHTNESS,
635b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.type    = V4L2_CTRL_TYPE_INTEGER,
645b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.name    = "Brightness",
655b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.minimum = 0,
665b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.maximum = 255,
675b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.step    = 1,
685b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#define BRIGHTNESS_DEF 128
695b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.default_value = BRIGHTNESS_DEF,
705b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    },
715b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    .set = sd_setbrightness,
725b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    .get = sd_getbrightness,
735b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	},
745b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	{
755b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    {
765b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.id      = V4L2_CID_CONTRAST,
775b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.type    = V4L2_CTRL_TYPE_INTEGER,
785b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.name    = "Contrast",
795b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.minimum = 0,
805b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.maximum = 8,
815b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.step    = 1,
825b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#define CONTRAST_DEF 1
835b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.default_value = CONTRAST_DEF,
845b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    },
855b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    .set = sd_setcontrast,
865b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    .get = sd_getcontrast,
875b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	},
885b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	{
895b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    {
905b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.id      = V4L2_CID_HUE,
915b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.type    = V4L2_CTRL_TYPE_INTEGER,
925b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.name    = "Hue",
935b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.minimum = 0,
945b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.maximum = 255,
955b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.step    = 1,
965b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#define HUE_DEF 0
975b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.default_value = HUE_DEF,
985b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    },
995b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    .set = sd_sethue,
1005b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    .get = sd_gethue,
1015b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	},
1025b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	{
1035b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    {
1045b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.id      = V4L2_CID_SATURATION,
1055b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.type    = V4L2_CTRL_TYPE_INTEGER,
1065b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.name    = "Saturation",
1075b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.minimum = 0,
1085b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.maximum = 8,
1095b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.step    = 1,
1105b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#define COLOR_DEF 1
1115b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.default_value = COLOR_DEF,
1125b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    },
1135b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    .set = sd_setcolor,
1145b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    .get = sd_getcolor,
1155b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	},
1165b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	{
1175b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    {
1185b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.id	 = V4L2_CID_SHARPNESS,
1195b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.type    = V4L2_CTRL_TYPE_INTEGER,
1205b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.name    = "Sharpness",
1215b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.minimum = 0,
1225b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.maximum = 255,
1235b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.step    = 1,
1245b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#define SHARPNESS_DEF 0
1255b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.default_value = SHARPNESS_DEF,
1265b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    },
1275b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    .set = sd_setsharpness,
1285b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	    .get = sd_getsharpness,
1295b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	},
1305b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine};
1315b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
1325b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic const struct v4l2_pix_format vga_mode[] = {
1335b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/*		(does not work correctly)
1345b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
1355b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.bytesperline = 176,
1365b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.sizeimage = 176 * 144 * 5 / 8 + 590,
1375b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.colorspace = V4L2_COLORSPACE_JPEG,
1385b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.priv = 3},
1395b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine*/
1405b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
1415b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.bytesperline = 320,
1425b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.sizeimage = 320 * 240 * 4 / 8 + 590,
1435b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.colorspace = V4L2_COLORSPACE_JPEG,
1445b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.priv = 2},
1455b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
1465b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.bytesperline = 640,
1475b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.sizeimage = 640 * 480 * 3 / 8 + 590,
1485b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.colorspace = V4L2_COLORSPACE_JPEG,
1495b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		.priv = 1},
1505b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine};
1515b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
1525b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/* read <len> bytes to gspca usb_buf */
1535b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void reg_r(struct gspca_dev *gspca_dev,
1545b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			u8 req,
1555b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			u16 index,
1565b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			int len)
1575b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
1585b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#if USB_BUF_SZ < 64
1595b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#error "USB buffer too small"
1605b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#endif
1615b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct usb_device *dev = gspca_dev->dev;
1625b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	int ret;
1635b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
1645b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (gspca_dev->usb_err < 0)
1655b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		return;
1665b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1675b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			req,
1685b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1695b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			0x0000,			/* value */
1705b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			index,
1715b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			gspca_dev->usb_buf, len,
1725b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			500);
1735b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
1745b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			 gspca_dev->usb_buf[0]);
1755b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (ret < 0) {
176133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		pr_err("reg_r err %d\n", ret);
1775b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		gspca_dev->usb_err = ret;
1785b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	}
1795b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
1805b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
1815b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void reg_w(struct gspca_dev *gspca_dev,
1825b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			u8 req,
1835b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			u16 value,
1845b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			u16 index)
1855b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
1865b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct usb_device *dev = gspca_dev->dev;
1875b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	int ret;
1885b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
1895b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (gspca_dev->usb_err < 0)
1905b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		return;
1915b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
1925b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1935b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			req,
1945b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1955b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			value, index,
1965b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			NULL, 0, 500);
1975b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (ret < 0) {
198133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		pr_err("reg_w err %d\n", ret);
1995b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		gspca_dev->usb_err = ret;
2005b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	}
2015b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
2025b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2035b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void reg_wb(struct gspca_dev *gspca_dev,
2045b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			u8 req,
2055b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			u16 value,
2065b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			u16 index,
2075b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			u8 byte)
2085b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
2095b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct usb_device *dev = gspca_dev->dev;
2105b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	int ret;
2115b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2125b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (gspca_dev->usb_err < 0)
2135b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		return;
2145b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	PDEBUG(D_USBO, "SET %02x %04x %04x %02x", req, value, index, byte);
2155b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	gspca_dev->usb_buf[0] = byte;
2165b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
2175b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			req,
2185b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2195b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			value, index,
2205b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			gspca_dev->usb_buf, 1, 500);
2215b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (ret < 0) {
222133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		pr_err("reg_w err %d\n", ret);
2235b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		gspca_dev->usb_err = ret;
2245b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	}
2255b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
2265b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2275b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void wait_status_0(struct gspca_dev *gspca_dev)
2285b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
2299ba4a4ba3c170e618f75213fb03fe2deda754195Jean-François Moine	int i, w;
2305b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2319ba4a4ba3c170e618f75213fb03fe2deda754195Jean-François Moine	i = 16;
2329ba4a4ba3c170e618f75213fb03fe2deda754195Jean-François Moine	w = 0;
2335b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	do {
2345b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		reg_r(gspca_dev, 0x21, 0x0000, 1);
2355b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		if (gspca_dev->usb_buf[0] == 0)
2365b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			return;
2379ba4a4ba3c170e618f75213fb03fe2deda754195Jean-François Moine		w += 15;
2389ba4a4ba3c170e618f75213fb03fe2deda754195Jean-François Moine		msleep(w);
2395b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	} while (--i > 0);
2405b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	PDEBUG(D_ERR, "wait_status_0 timeout");
2415b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	gspca_dev->usb_err = -ETIME;
2425b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
2435b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2445b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void wait_status_1(struct gspca_dev *gspca_dev)
2455b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
2465b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	int i;
2475b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2485b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	i = 10;
2495b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	do {
2505b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		reg_r(gspca_dev, 0x21, 0x0001, 1);
2515b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		msleep(10);
2525b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		if (gspca_dev->usb_buf[0] == 1) {
2535b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			reg_wb(gspca_dev, 0x21, 0x0000, 0x0001, 0x00);
2545b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			reg_r(gspca_dev, 0x21, 0x0001, 1);
2555b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			return;
2565b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		}
2575b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	} while (--i > 0);
2585b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	PDEBUG(D_ERR, "wait_status_1 timeout");
2595b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	gspca_dev->usb_err = -ETIME;
2605b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
2615b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2625b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void setbrightness(struct gspca_dev *gspca_dev)
2635b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
2645b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
2655b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2665b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_wb(gspca_dev, 0xc0, 0x0000, 0x00c0, sd->brightness);
2675b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
2685b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2695b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void setcontrast(struct gspca_dev *gspca_dev)
2705b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
2715b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
2725b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2735b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_wb(gspca_dev, 0xc1, 0x0000, 0x00c1, sd->contrast);
2745b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
2755b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2765b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void sethue(struct gspca_dev *gspca_dev)
2775b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
2785b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
2795b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2805b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_wb(gspca_dev, 0xc2, 0x0000, 0x0000, sd->hue);
2815b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
2825b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2835b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void setcolor(struct gspca_dev *gspca_dev)
2845b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
2855b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
2865b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2875b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_wb(gspca_dev, 0xc3, 0x0000, 0x00c3, sd->color);
2885b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
2895b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2905b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void setsharpness(struct gspca_dev *gspca_dev)
2915b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
2925b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
2935b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2945b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_wb(gspca_dev, 0xc4, 0x0000, 0x00c4, sd->sharpness);
2955b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
2965b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
2975b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/* this function is called at probe time */
2985b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_config(struct gspca_dev *gspca_dev,
2995b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			const struct usb_device_id *id)
3005b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
3015b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
3025b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3035b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	gspca_dev->cam.cam_mode = vga_mode;
3045b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
3055b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	gspca_dev->cam.npkt = 128; /* number of packets per ISOC message */
3065b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			/*fixme: 256 in ms-win traces*/
3075b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3085b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sd->brightness = BRIGHTNESS_DEF;
3095b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sd->contrast = CONTRAST_DEF;
3105b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sd->hue = HUE_DEF;
3115b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sd->color = COLOR_DEF;
3125b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sd->sharpness = SHARPNESS_DEF;
3135b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3145b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return 0;
3155b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
3165b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3175b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/* this function is called at probe and resume time */
3185b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_init(struct gspca_dev *gspca_dev)
3195b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
3205b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_w(gspca_dev, 0x00, 0x0001, 0x2067);
3215b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_w(gspca_dev, 0x00, 0x00d0, 0x206b);
3225b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
3235b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
3245b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	msleep(8);
3255b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_w(gspca_dev, 0x00, 0x00c0, 0x206b);
3265b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
3275b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
3285b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3295b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_r(gspca_dev, 0x20, 0x0000, 1);
3305b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_r(gspca_dev, 0x20, 0x0000, 5);
3315b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_r(gspca_dev, 0x23, 0x0000, 64);
3325b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	PDEBUG(D_PROBE, "%s%s", &gspca_dev->usb_buf[0x1c],
3335b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine				&gspca_dev->usb_buf[0x30]);
3345b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_r(gspca_dev, 0x23, 0x0001, 64);
3355b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return gspca_dev->usb_err;
3365b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
3375b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3385b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/* function called at start time before URB creation */
3395b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_isoc_init(struct gspca_dev *gspca_dev)
3405b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
3415b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	u8 mode;
3425b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3435b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_r(gspca_dev, 0x00, 0x2520, 1);
3445b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	wait_status_0(gspca_dev);
3455b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_w(gspca_dev, 0xc5, 0x0003, 0x0000);
3465b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	wait_status_1(gspca_dev);
3475b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3485b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	wait_status_0(gspca_dev);
3495b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
3505b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
3515b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_r(gspca_dev, 0x25, 0x0004, 1);
3520dd826962716ff6984a14038d1604be816d759c3Jean-François Moine	reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);	/* 420 */
3535b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_r(gspca_dev, 0x27, 0x0000, 1);
3546507b4232c2e136ccc338c3ed5c2f54b32b961b7Jean-François Moine
3556507b4232c2e136ccc338c3ed5c2f54b32b961b7Jean-François Moine/* not useful..
3566507b4232c2e136ccc338c3ed5c2f54b32b961b7Jean-François Moine	gspca_dev->alt = 4;		* use alternate setting 3 */
3576507b4232c2e136ccc338c3ed5c2f54b32b961b7Jean-François Moine
3585b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return gspca_dev->usb_err;
3595b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
3605b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3615b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/* -- start the camera -- */
3625b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_start(struct gspca_dev *gspca_dev)
3635b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
3645b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
3655b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3665b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	/* initialize the JPEG header */
3675b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
3685b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			0x22);		/* JPEG 411 */
3695b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3703e12950d86d695bdaf762476446a60ed5073eedcJean-François Moine	/* the JPEG quality shall be 85% */
3713e12950d86d695bdaf762476446a60ed5073eedcJean-François Moine	jpeg_set_qual(sd->jpeg_hdr, 85);
3725b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3735b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	/* set the controls */
3745b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	setbrightness(gspca_dev);
3755b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	setcontrast(gspca_dev);
3765b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sethue(gspca_dev);
3775b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	setcolor(gspca_dev);
3785b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	setsharpness(gspca_dev);
3795b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3805b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	msleep(5);
3815b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	reg_r(gspca_dev, 0x00, 0x2520, 1);
3825b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	msleep(8);
3835b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3845b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	/* start the capture */
3855b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	wait_status_0(gspca_dev);
3860dd826962716ff6984a14038d1604be816d759c3Jean-François Moine	reg_w(gspca_dev, 0x31, 0x0000, 0x0004);	/* start request */
3875b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	wait_status_1(gspca_dev);
3885b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	wait_status_0(gspca_dev);
3895b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	msleep(200);
3905b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3915b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sd->pkt_seq = 0;
3925b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return gspca_dev->usb_err;
3935b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
3945b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
3955b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void sd_stopN(struct gspca_dev *gspca_dev)
3965b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
3975b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	/* stop the capture */
3985b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	wait_status_0(gspca_dev);
3990dd826962716ff6984a14038d1604be816d759c3Jean-François Moine	reg_w(gspca_dev, 0x31, 0x0000, 0x0000);	/* stop request */
4005b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	wait_status_1(gspca_dev);
4015b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	wait_status_0(gspca_dev);
4025b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
4035b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4045b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/* move a packet adding 0x00 after 0xff */
4055b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void add_packet(struct gspca_dev *gspca_dev,
4065b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			u8 *data,
4075b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			int len)
4085b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
4095b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	int i;
4105b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4115b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	i = 0;
4125b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	do {
4135b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		if (data[i] == 0xff) {
4145b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			gspca_frame_add(gspca_dev, INTER_PACKET,
4155b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine					data, i + 1);
4165b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			len -= i;
4175b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			data += i;
4185b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			*data = 0x00;
4195b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			i = 0;
4205b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		}
4215b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	} while (++i < len);
4225b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
4235b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
4245b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4255b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
4265b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			u8 *data,			/* isoc packet */
4275b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			int len)			/* iso packet length */
4285b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
4295b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
4305b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	static const u8 ffd9[] = {0xff, 0xd9};
4315b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4325b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	/* image packets start with:
4335b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	 *	02 8n
4345b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	 * with <n> bit:
4355b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	 *	0x01: even (0) / odd (1) image
4365b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	 *	0x02: end of image when set
4375b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	 */
4385b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (len < 3)
4395b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		return;				/* empty packet */
4405b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (*data == 0x02) {
4415b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		if (data[1] & 0x02) {
4425b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			sd->pkt_seq = !(data[1] & 1);
4435b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			add_packet(gspca_dev, data + 2, len - 2);
4445b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			gspca_frame_add(gspca_dev, LAST_PACKET,
4455b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine					ffd9, 2);
4465b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			return;
4475b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		}
4485b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		if ((data[1] & 1) != sd->pkt_seq)
4495b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			goto err;
4505b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		if (gspca_dev->last_packet_type == LAST_PACKET)
4515b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			gspca_frame_add(gspca_dev, FIRST_PACKET,
4525b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine					sd->jpeg_hdr, JPEG_HDR_SZ);
4535b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		add_packet(gspca_dev, data + 2, len - 2);
4545b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		return;
4555b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	}
4565b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moineerr:
4575b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	gspca_dev->last_packet_type = DISCARD_PACKET;
4585b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
4595b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4605b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
4615b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
4625b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
4635b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4645b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sd->brightness = val;
4655b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (gspca_dev->streaming)
4665b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		setbrightness(gspca_dev);
4675b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return gspca_dev->usb_err;
4685b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
4695b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4705b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
4715b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
4725b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
4735b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4745b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	*val = sd->brightness;
4755b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return 0;
4765b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
4775b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4785b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
4795b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
4805b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
4815b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4825b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sd->contrast = val;
4835b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (gspca_dev->streaming)
4845b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		setcontrast(gspca_dev);
4855b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return gspca_dev->usb_err;
4865b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
4875b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4885b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
4895b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
4905b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
4915b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4925b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	*val = sd->contrast;
4935b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return 0;
4945b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
4955b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
4965b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
4975b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
4985b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
4995b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5005b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sd->hue = val;
5015b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (gspca_dev->streaming)
5025b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		sethue(gspca_dev);
5035b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return gspca_dev->usb_err;
5045b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
5055b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5065b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
5075b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
5085b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
5095b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5105b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	*val = sd->hue;
5115b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return 0;
5125b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
5135b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5145b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_setcolor(struct gspca_dev *gspca_dev, __s32 val)
5155b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
5165b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
5175b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5185b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sd->color = val;
5195b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (gspca_dev->streaming)
5205b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		setcolor(gspca_dev);
5215b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return gspca_dev->usb_err;
5225b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
5235b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5245b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_getcolor(struct gspca_dev *gspca_dev, __s32 *val)
5255b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
5265b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
5275b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5285b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	*val = sd->color;
5295b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return 0;
5305b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
5315b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5325b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
5335b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
5345b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
5355b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5365b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	sd->sharpness = val;
5375b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (gspca_dev->streaming)
5385b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		setsharpness(gspca_dev);
5395b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return gspca_dev->usb_err;
5405b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
5415b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5425b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
5435b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
5445b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
5455b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5465b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	*val = sd->sharpness;
5475b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return 0;
5485b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
5495b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5505b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/* sub-driver description */
5515b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic const struct sd_desc sd_desc = {
5525b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.name = MODULE_NAME,
5535b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.ctrls = sd_ctrls,
5545b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.nctrls = ARRAY_SIZE(sd_ctrls),
5555b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.config = sd_config,
5565b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.init = sd_init,
5575b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.isoc_init = sd_isoc_init,
5585b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.start = sd_start,
5595b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.stopN = sd_stopN,
5605b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.pkt_scan = sd_pkt_scan,
5615b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine};
5625b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5635b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/* -- module initialisation -- */
56495c967c167785eb991cf6b22fb854dd8d61d0ff8Jean-François Moinestatic const struct usb_device_id device_table[] = {
5655b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	{USB_DEVICE(0x04fc, 0x1528)},
5665b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	{}
5675b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine};
5685b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François MoineMODULE_DEVICE_TABLE(usb, device_table);
5695b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5705b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine/* -- device connect -- */
5715b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic int sd_probe(struct usb_interface *intf,
5725b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine			const struct usb_device_id *id)
5735b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine{
5745b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	/* the video interface for isochronous transfer is 1 */
5755b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
5765b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine		return -ENODEV;
5775b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5785b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	return gspca_dev_probe2(intf, id, &sd_desc, sizeof(struct sd),
5795b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine				THIS_MODULE);
5805b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine}
5815b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
5825b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moinestatic struct usb_driver sd_driver = {
5835b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.name = MODULE_NAME,
5845b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.id_table = device_table,
5855b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.probe = sd_probe,
5865b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.disconnect = gspca_disconnect,
5875b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#ifdef CONFIG_PM
5885b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.suspend = gspca_suspend,
5895b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine	.resume = gspca_resume,
5905b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine#endif
5915b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine};
5925b0ff8c43afefbd42a1aa3cd89808eec829bbbb7Jean-François Moine
593ecb3b2b35db49778b6d89e3ffd0c400776c20735Greg Kroah-Hartmanmodule_usb_driver(sd_driver);
594