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