127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/*
227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * SQ905 subdriver
327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker *
427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * Copyright (C) 2008, 2009 Adam Baker and Theodore Kilgore
527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker *
627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * This program is free software; you can redistribute it and/or modify
727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * it under the terms of the GNU General Public License as published by
827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * the Free Software Foundation; either version 2 of the License, or
927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * any later version.
1027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker *
1127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * This program is distributed in the hope that it will be useful,
1227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * but WITHOUT ANY WARRANTY; without even the implied warranty of
1327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * GNU General Public License for more details.
1527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker *
1627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * You should have received a copy of the GNU General Public License
1727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * along with this program; if not, write to the Free Software
1827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker */
2027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
2127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/*
2227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * History and Acknowledgments
2327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker *
2427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * The original Linux driver for SQ905 based cameras was written by
2525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * Marcell Lengyel and furter developed by many other contributors
2627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * and is available from http://sourceforge.net/projects/sqcam/
2727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker *
2827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * This driver takes advantage of the reverse engineering work done for
2927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * that driver and for libgphoto2 but shares no code with them.
3027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker *
3127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * This driver has used as a base the finepix driver and other gspca
3227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * based drivers and may still contain code fragments taken from those
3327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * drivers.
3427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker */
3527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
36133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
37133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches
3827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define MODULE_NAME "sq905"
3927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
4027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#include <linux/workqueue.h>
415a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
4227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#include "gspca.h"
4327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
4427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam BakerMODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>, "
4527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		"Theodore Kilgore <kilgota@auburn.edu>");
4627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam BakerMODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver");
4727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam BakerMODULE_LICENSE("GPL");
4827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
4927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* Default timeouts, in ms */
5027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define SQ905_CMD_TIMEOUT 500
5127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define SQ905_DATA_TIMEOUT 1000
5227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
5327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* Maximum transfer size to use. */
5427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define SQ905_MAX_TRANSFER 0x8000
5527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define FRAME_HEADER_LEN 64
5627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
5727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* The known modes, or registers. These go in the "value" slot. */
5827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
5927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* 00 is "none" obviously */
6027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
6127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define SQ905_BULK_READ	0x03	/* precedes any bulk read */
6227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define SQ905_COMMAND	0x06	/* precedes the command codes below */
6327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define SQ905_PING	0x07	/* when reading an "idling" command */
6427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define SQ905_READ_DONE 0xc0    /* ack bulk read completed */
6527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
663b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker/* Any non-zero value in the bottom 2 bits of the 2nd byte of
673b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker * the ID appears to indicate the camera can do 640*480. If the
683b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker * LSB of that byte is set the image is just upside down, otherwise
693b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker * it is rotated 180 degrees. */
703b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker#define SQ905_HIRES_MASK	0x00000300
713b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker#define SQ905_ORIENTATION_MASK	0x00000100
723b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker
7327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* Some command codes. These go in the "index" slot. */
7427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
7527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define SQ905_ID      0xf0	/* asks for model string */
7627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define SQ905_CONFIG  0x20	/* gets photo alloc. table, not used here */
7727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define SQ905_DATA    0x30	/* accesses photo data, not used here */
7827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#define SQ905_CLEAR   0xa0	/* clear everything */
793b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker#define SQ905_CAPTURE_LOW  0x60	/* Starts capture at 160x120 */
803b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker#define SQ905_CAPTURE_MED  0x61	/* Starts capture at 320x240 */
813b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker#define SQ905_CAPTURE_HIGH 0x62	/* Starts capture at 640x480 (some cams only) */
8227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* note that the capture command also controls the output dimensions */
8327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
8427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* Structure to hold all of our device specific stuff */
8527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstruct sd {
8627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	struct gspca_dev gspca_dev;	/* !! must be the first item */
8727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
8827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	/*
8927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	 * Driver stuff
9027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	 */
9127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	struct work_struct work_struct;
9227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	struct workqueue_struct *work_thread;
9327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker};
9427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
953b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Bakerstatic struct v4l2_pix_format sq905_mode[] = {
963b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker	{ 160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
973b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		.bytesperline = 160,
983b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		.sizeimage = 160 * 120,
993b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		.colorspace = V4L2_COLORSPACE_SRGB,
1003b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		.priv = 0},
10127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	{ 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
10227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		.bytesperline = 320,
10327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		.sizeimage = 320 * 240,
10427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		.colorspace = V4L2_COLORSPACE_SRGB,
1053b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		.priv = 0},
1063b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker	{ 640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
1073b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		.bytesperline = 640,
1083b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		.sizeimage = 640 * 480,
1093b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		.colorspace = V4L2_COLORSPACE_SRGB,
11027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		.priv = 0}
11127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker};
11227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
11327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/*
11427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * Send a command to the camera.
11527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker */
11627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstatic int sq905_command(struct gspca_dev *gspca_dev, u16 index)
11727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker{
11827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	int ret;
11927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
12027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	gspca_dev->usb_buf[0] = '\0';
12127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	ret = usb_control_msg(gspca_dev->dev,
12227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      usb_sndctrlpipe(gspca_dev->dev, 0),
12327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      USB_REQ_SYNCH_FRAME,                /* request */
12427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
12527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      SQ905_COMMAND, index, gspca_dev->usb_buf, 1,
12627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      SQ905_CMD_TIMEOUT);
12727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	if (ret < 0) {
128133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
12927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		return ret;
13027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	}
13127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
13227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	ret = usb_control_msg(gspca_dev->dev,
13327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      usb_sndctrlpipe(gspca_dev->dev, 0),
13427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      USB_REQ_SYNCH_FRAME,                /* request */
13527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
13627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      SQ905_PING, 0, gspca_dev->usb_buf, 1,
13727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      SQ905_CMD_TIMEOUT);
13827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	if (ret < 0) {
139133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		pr_err("%s: usb_control_msg failed 2 (%d)\n", __func__, ret);
14027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		return ret;
14127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	}
14227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
14327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	return 0;
14427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker}
14527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
14627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/*
14727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * Acknowledge the end of a frame - see warning on sq905_command.
14827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker */
14927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstatic int sq905_ack_frame(struct gspca_dev *gspca_dev)
15027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker{
15127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	int ret;
15227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
15327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	gspca_dev->usb_buf[0] = '\0';
15427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	ret = usb_control_msg(gspca_dev->dev,
15527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      usb_sndctrlpipe(gspca_dev->dev, 0),
15627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      USB_REQ_SYNCH_FRAME,                /* request */
15727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
15827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1,
15927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      SQ905_CMD_TIMEOUT);
16027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	if (ret < 0) {
161133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
16227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		return ret;
16327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	}
16427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
16527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	return 0;
16627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker}
16727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
16827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/*
16927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker *  request and read a block of data - see warning on sq905_command.
17027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker */
17127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstatic int
1728519110040ca98dfbc89c473921cca390c81460cHans de Goedesq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
17327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker{
17427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	int ret;
17527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	int act_len;
17627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
17727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	gspca_dev->usb_buf[0] = '\0';
1788519110040ca98dfbc89c473921cca390c81460cHans de Goede	if (need_lock)
1798519110040ca98dfbc89c473921cca390c81460cHans de Goede		mutex_lock(&gspca_dev->usb_lock);
18027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	ret = usb_control_msg(gspca_dev->dev,
18127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      usb_sndctrlpipe(gspca_dev->dev, 0),
18227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      USB_REQ_SYNCH_FRAME,                /* request */
18327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
18427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      SQ905_BULK_READ, size, gspca_dev->usb_buf,
18527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			      1, SQ905_CMD_TIMEOUT);
1868519110040ca98dfbc89c473921cca390c81460cHans de Goede	if (need_lock)
1878519110040ca98dfbc89c473921cca390c81460cHans de Goede		mutex_unlock(&gspca_dev->usb_lock);
18827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	if (ret < 0) {
189133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
19027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		return ret;
19127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	}
19227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	ret = usb_bulk_msg(gspca_dev->dev,
19327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			   usb_rcvbulkpipe(gspca_dev->dev, 0x81),
19427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			   data, size, &act_len, SQ905_DATA_TIMEOUT);
19527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
19627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	/* successful, it returns 0, otherwise  negative */
19727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	if (ret < 0 || act_len != size) {
198133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		pr_err("bulk read fail (%d) len %d/%d\n", ret, act_len, size);
19927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		return -EIO;
20027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	}
20127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	return 0;
20227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker}
20327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
204844db450e6e2cf710752af1a019a877af390b541Hans de Goede/*
205844db450e6e2cf710752af1a019a877af390b541Hans de Goede * This function is called as a workqueue function and runs whenever the camera
20627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * is streaming data. Because it is a workqueue function it is allowed to sleep
20727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker * so we can use synchronous USB calls. To avoid possible collisions with other
208844db450e6e2cf710752af1a019a877af390b541Hans de Goede * threads attempting to use gspca_dev->usb_buf we take the usb_lock when
209844db450e6e2cf710752af1a019a877af390b541Hans de Goede * performing USB operations using it. In practice we don't really need this
210844db450e6e2cf710752af1a019a877af390b541Hans de Goede * as the camera doesn't provide any controls.
21127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker */
21227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstatic void sq905_dostream(struct work_struct *work)
21327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker{
21427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	struct sd *dev = container_of(work, struct sd, work_struct);
21527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	struct gspca_dev *gspca_dev = &dev->gspca_dev;
21627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	int bytes_left; /* bytes remaining in current frame. */
21727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	int data_len;   /* size to use for the next read. */
21827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	int header_read; /* true if we have already read the frame header. */
21927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	int packet_type;
22067e4542558ee589a5196a29640de1ba1157fb450Jean-Francois Moine	int frame_sz;
22127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	int ret;
22227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	u8 *data;
22327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	u8 *buffer;
22427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
22527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
22627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	if (!buffer) {
227133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		pr_err("Couldn't allocate USB buffer\n");
22827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		goto quit_stream;
22927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	}
23027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
23167e4542558ee589a5196a29640de1ba1157fb450Jean-Francois Moine	frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage
23267e4542558ee589a5196a29640de1ba1157fb450Jean-Francois Moine			+ FRAME_HEADER_LEN;
23367e4542558ee589a5196a29640de1ba1157fb450Jean-Francois Moine
234345321dc9c52b774f42c934339f9b3e2f0a39395Hans de Goede	while (gspca_dev->present && gspca_dev->streaming) {
2354ad34da0300d7196be25ef79ef3f054756cdc739Hans Verkuil#ifdef CONFIG_PM
2364ad34da0300d7196be25ef79ef3f054756cdc739Hans Verkuil		if (gspca_dev->frozen)
2374ad34da0300d7196be25ef79ef3f054756cdc739Hans Verkuil			break;
2384ad34da0300d7196be25ef79ef3f054756cdc739Hans Verkuil#endif
23927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		/* request some data and then read it until we have
24027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		 * a complete frame. */
24167e4542558ee589a5196a29640de1ba1157fb450Jean-Francois Moine		bytes_left = frame_sz;
24227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		header_read = 0;
24327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
2448519110040ca98dfbc89c473921cca390c81460cHans de Goede		/* Note we do not check for gspca_dev->streaming here, as
2458519110040ca98dfbc89c473921cca390c81460cHans de Goede		   we must finish reading an entire frame, otherwise the
2468519110040ca98dfbc89c473921cca390c81460cHans de Goede		   next time we stream we start reading in the middle of a
2478519110040ca98dfbc89c473921cca390c81460cHans de Goede		   frame. */
248345321dc9c52b774f42c934339f9b3e2f0a39395Hans de Goede		while (bytes_left > 0 && gspca_dev->present) {
24927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			data_len = bytes_left > SQ905_MAX_TRANSFER ?
25027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				SQ905_MAX_TRANSFER : bytes_left;
2518519110040ca98dfbc89c473921cca390c81460cHans de Goede			ret = sq905_read_data(gspca_dev, buffer, data_len, 1);
25227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			if (ret < 0)
25327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				goto quit_stream;
2548519110040ca98dfbc89c473921cca390c81460cHans de Goede			PDEBUG(D_PACK,
25527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				"Got %d bytes out of %d for frame",
25627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				data_len, bytes_left);
25727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			bytes_left -= data_len;
25827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			data = buffer;
25927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			if (!header_read) {
26027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				packet_type = FIRST_PACKET;
26127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				/* The first 64 bytes of each frame are
26227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				 * a header full of FF 00 bytes */
26327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				data += FRAME_HEADER_LEN;
26427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				data_len -= FRAME_HEADER_LEN;
26527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				header_read = 1;
26627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			} else if (bytes_left == 0) {
26727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				packet_type = LAST_PACKET;
26827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			} else {
26927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker				packet_type = INTER_PACKET;
27027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			}
27176dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			gspca_frame_add(gspca_dev, packet_type,
27276dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine					data, data_len);
27376dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			/* If entire frame fits in one packet we still
27476dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			   need to add a LAST_PACKET */
27576dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			if (packet_type == FIRST_PACKET &&
27676dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			    bytes_left == 0)
27776dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine				gspca_frame_add(gspca_dev, LAST_PACKET,
27876dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine						NULL, 0);
27927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		}
280345321dc9c52b774f42c934339f9b3e2f0a39395Hans de Goede		if (gspca_dev->present) {
2818519110040ca98dfbc89c473921cca390c81460cHans de Goede			/* acknowledge the frame */
2828519110040ca98dfbc89c473921cca390c81460cHans de Goede			mutex_lock(&gspca_dev->usb_lock);
2838519110040ca98dfbc89c473921cca390c81460cHans de Goede			ret = sq905_ack_frame(gspca_dev);
2848519110040ca98dfbc89c473921cca390c81460cHans de Goede			mutex_unlock(&gspca_dev->usb_lock);
2858519110040ca98dfbc89c473921cca390c81460cHans de Goede			if (ret < 0)
2868519110040ca98dfbc89c473921cca390c81460cHans de Goede				goto quit_stream;
2878519110040ca98dfbc89c473921cca390c81460cHans de Goede		}
28827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	}
28927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerquit_stream:
290345321dc9c52b774f42c934339f9b3e2f0a39395Hans de Goede	if (gspca_dev->present) {
2918519110040ca98dfbc89c473921cca390c81460cHans de Goede		mutex_lock(&gspca_dev->usb_lock);
29227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		sq905_command(gspca_dev, SQ905_CLEAR);
2938519110040ca98dfbc89c473921cca390c81460cHans de Goede		mutex_unlock(&gspca_dev->usb_lock);
2948519110040ca98dfbc89c473921cca390c81460cHans de Goede	}
29527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	kfree(buffer);
29627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker}
29727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
29827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* This function is called at probe time just before sd_init */
29927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstatic int sd_config(struct gspca_dev *gspca_dev,
30027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		const struct usb_device_id *id)
30127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker{
30227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	struct cam *cam = &gspca_dev->cam;
30327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	struct sd *dev = (struct sd *) gspca_dev;
30427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
30527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	/* We don't use the buffer gspca allocates so make it small. */
3066929dc6b30dc3a6c9c411f677a11b866e8dd28aaJean-Francois Moine	cam->bulk = 1;
30727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	cam->bulk_size = 64;
30827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
30927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	INIT_WORK(&dev->work_struct, sq905_dostream);
31027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
31127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	return 0;
31227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker}
31327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
31427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* called on streamoff with alt==0 and on disconnect */
31527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* the usb_lock is held at entry - restore on exit */
31627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstatic void sd_stop0(struct gspca_dev *gspca_dev)
31727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker{
31827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	struct sd *dev = (struct sd *) gspca_dev;
31927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
32027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	/* wait for the work queue to terminate */
32127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	mutex_unlock(&gspca_dev->usb_lock);
32227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	/* This waits for sq905_dostream to finish */
32327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	destroy_workqueue(dev->work_thread);
32427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	dev->work_thread = NULL;
32527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	mutex_lock(&gspca_dev->usb_lock);
32627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker}
32727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
32827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* this function is called at probe and resume time */
32927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstatic int sd_init(struct gspca_dev *gspca_dev)
33027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker{
33127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	u32 ident;
33227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	int ret;
33327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
33427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	/* connect to the camera and read
33527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	 * the model ID and process that and put it away.
33627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	 */
33727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	ret = sq905_command(gspca_dev, SQ905_CLEAR);
33827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	if (ret < 0)
33927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		return ret;
34027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	ret = sq905_command(gspca_dev, SQ905_ID);
34127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	if (ret < 0)
34227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		return ret;
3438519110040ca98dfbc89c473921cca390c81460cHans de Goede	ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4, 0);
34427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	if (ret < 0)
34527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		return ret;
3463b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker	/* usb_buf is allocated with kmalloc so is aligned.
3473b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker	 * Camera model number is the right way round if we assume this
3483b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker	 * reverse engineered ID is supposed to be big endian. */
3493b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker	ident = be32_to_cpup((__be32 *)gspca_dev->usb_buf);
35027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	ret = sq905_command(gspca_dev, SQ905_CLEAR);
35127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	if (ret < 0)
35227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		return ret;
3533b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker	PDEBUG(D_CONF, "SQ905 camera ID %08x detected", ident);
3543b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker	gspca_dev->cam.cam_mode = sq905_mode;
3553b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker	gspca_dev->cam.nmodes = ARRAY_SIZE(sq905_mode);
3563b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker	if (!(ident & SQ905_HIRES_MASK))
3573b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		gspca_dev->cam.nmodes--;
358dfa76fa2824967c0ec196fbcba36d3e74b66d3aaAdam Baker
359dfa76fa2824967c0ec196fbcba36d3e74b66d3aaAdam Baker	if (ident & SQ905_ORIENTATION_MASK)
360dfa76fa2824967c0ec196fbcba36d3e74b66d3aaAdam Baker		gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP;
361dfa76fa2824967c0ec196fbcba36d3e74b66d3aaAdam Baker	else
362dfa76fa2824967c0ec196fbcba36d3e74b66d3aaAdam Baker		gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP |
363dfa76fa2824967c0ec196fbcba36d3e74b66d3aaAdam Baker					     V4L2_IN_ST_HFLIP;
36427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	return 0;
36527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker}
36627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
36727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* Set up for getting frames. */
36827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstatic int sd_start(struct gspca_dev *gspca_dev)
36927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker{
37027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	struct sd *dev = (struct sd *) gspca_dev;
37127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	int ret;
37227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
37327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	/* "Open the shutter" and set size, to start capture */
37467e4542558ee589a5196a29640de1ba1157fb450Jean-Francois Moine	switch (gspca_dev->curr_mode) {
37567e4542558ee589a5196a29640de1ba1157fb450Jean-Francois Moine	default:
37667e4542558ee589a5196a29640de1ba1157fb450Jean-Francois Moine/*	case 2: */
3773b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		PDEBUG(D_STREAM, "Start streaming at high resolution");
3783b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_HIGH);
3793b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		break;
38067e4542558ee589a5196a29640de1ba1157fb450Jean-Francois Moine	case 1:
3813b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		PDEBUG(D_STREAM, "Start streaming at medium resolution");
3823b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED);
3833b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		break;
38467e4542558ee589a5196a29640de1ba1157fb450Jean-Francois Moine	case 0:
3853b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		PDEBUG(D_STREAM, "Start streaming at low resolution");
3863b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker		ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_LOW);
3873b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker	}
3883b27591d4e0b455865969d9f9bfae0d19fd6e5c3Adam Baker
38927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	if (ret < 0) {
390c93396e13576928a073154b5715761ff8a998368Theodore Kilgore		PERR("Start streaming command failed");
39127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		return ret;
39227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	}
39327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	/* Start the workqueue function to do the streaming */
39427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
39527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	queue_work(dev->work_thread, &dev->work_struct);
39627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
39727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	return 0;
39827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker}
39927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
40027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* Table of supported USB devices */
40195c967c167785eb991cf6b22fb854dd8d61d0ff8Jean-François Moinestatic const struct usb_device_id device_table[] = {
40227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	{USB_DEVICE(0x2770, 0x9120)},
40327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	{}
40427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker};
40527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
40627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam BakerMODULE_DEVICE_TABLE(usb, device_table);
40727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
40827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* sub-driver description */
40927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstatic const struct sd_desc sd_desc = {
41027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	.name   = MODULE_NAME,
41127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	.config = sd_config,
41227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	.init   = sd_init,
41327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	.start  = sd_start,
41427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	.stop0  = sd_stop0,
41527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker};
41627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
41727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker/* -- device connect -- */
41827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstatic int sd_probe(struct usb_interface *intf,
41927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker		const struct usb_device_id *id)
42027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker{
42127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	return gspca_dev_probe(intf, id,
42227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			&sd_desc,
42327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			sizeof(struct sd),
42427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker			THIS_MODULE);
42527d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker}
42627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
42727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Bakerstatic struct usb_driver sd_driver = {
42827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	.name       = MODULE_NAME,
42927d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	.id_table   = device_table,
43027d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	.probe      = sd_probe,
43127d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	.disconnect = gspca_disconnect,
43227d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#ifdef CONFIG_PM
43327d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	.suspend = gspca_suspend,
43427d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker	.resume  = gspca_resume,
4358bb58964bc139d5ff5285f84aa302977d221754dHans de Goede	.reset_resume = gspca_resume,
43627d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker#endif
43727d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker};
43827d35fc3fb06284edec8a3c9f6872a1ce7405a48Adam Baker
439ecb3b2b35db49778b6d89e3ffd0c400776c20735Greg Kroah-Hartmanmodule_usb_driver(sd_driver);
440