⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qc-driver.c

📁 在Linux下用于webeye的摄像头的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Start of file *//* {{{ [fold] Comments  *//* * qc-usb, Logitech QuickCam video driver with V4L support * Derived from qce-ga, linux V4L driver for the QuickCam Express and Dexxa QuickCam * * qc-driver.c - main driver part * * Copyright (C) 2001  Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland * Copyright (C) 2002,2003  Tuukka Toivonen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * *//* Cam variations of Logitech QuickCam:   P/N 861037:      Sensor HDCS1000        ASIC STV0600   P/N 861050-0010: Sensor HDCS1000        ASIC STV0600   P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 ("QuickCam Express")   P/N 861055:      Sensor ST VV6410       ASIC STV0610 ("LEGO cam")   P/N 861075-0040: Sensor HDCS1000        ASIC   P/N 961179-0700: Sensor ST VV6410       ASIC STV0602 (Dexxa WebCam USB)   P/N 861040-0000: Sensor ST VV6410       ASIC STV0610 ("QuickCam Web")   For any questions ask    	qce-ga-devel@lists.sourceforge.net	- about code   	qce-ga-discussion@lists.sourceforge.net	- about usage*//* }}} *//* {{{ [fold] Includes  */#ifdef NOKERNEL#include "quickcam.h"#else#include <linux/quickcam.h>#endif#include <linux/module.h>#include "qc-memory.h"#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)#include <linux/slab.h>#else#include <linux/malloc.h>#endif#include <linux/kernel.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/list.h>#include <linux/mm.h>#include <linux/proc_fs.h>#include <linux/smp_lock.h>#include <linux/vmalloc.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/page.h>#include <linux/capability.h>#include <linux/poll.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)#include <linux/moduleparam.h>#endif/* }}} *//* {{{ [fold] Module parameters  */MODULE_PARM_DESC(qcdebug, "Sets the debug output (bitfield)");MODULE_PARM(qcdebug, "i");int qcdebug = DEBUGLEVEL;MODULE_PARM_DESC(keepsettings, "Keep picture settings across one open to another (0-1)");MODULE_PARM(keepsettings, "i");static int keepsettings = 0;MODULE_PARM_DESC(settle, "Maximum number of frames to wait picture brightness to settle (0-255)");MODULE_PARM(settle, "i");static int settle = 0;/* Subsampling is used to allow higher scan rate with smaller images. */MODULE_PARM_DESC(subsample, "Sets subsampling (0-1)");MODULE_PARM(subsample, "i");static int subsample = 0;	/* normal or sub-sample (sub-sample to increase the speed) */MODULE_PARM_DESC(compress, "Enable compressed mode (0-1)");MODULE_PARM(compress, "i");static int compress = 0;	/* Enable compressed mode if available (higher framerate) */MODULE_PARM_DESC(frameskip, "How frequently capture frames (0-10)");MODULE_PARM(frameskip, "i");static int frameskip = 0;MODULE_PARM_DESC(quality, "Sets the picture quality (0-5)");MODULE_PARM(quality, "i");static int quality = 5;		/* 5 = generalized adjustable Pei-Tam method */MODULE_PARM_DESC(adaptive, "Automatic adaptive brightness control (0-1)");MODULE_PARM(adaptive, "i");static int adaptive = 1;MODULE_PARM_DESC(equalize, "Equalize image (0-1)");MODULE_PARM(equalize, "i");static int equalize = 0;	/* Disabled by default */MODULE_PARM_DESC(userlut, "Apply user-specified lookup-table (0-1)");MODULE_PARM(userlut, "i");static int userlut = 0;		/* Disabled by default */MODULE_PARM_DESC(retryerrors, "Retry if image capture fails, otherwise return error code (0-1)");MODULE_PARM(retryerrors, "i");static int retryerrors = 1;	/* Enabled by default *//* Bug in Xvideo(?): if the width is not divisible by 8 and Xvideo is used, the frame is shown wrongly */MODULE_PARM_DESC(compatible, "Enable workaround for bugs in application programs (bitfield)");MODULE_PARM(compatible, "i");static int compatible = 0;	/* Disabled by default */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5)MODULE_PARM_DESC(video_nr, "Set videodevice number (/dev/videoX)");MODULE_PARM(video_nr,"i");/* video_nr option allows to specify a certain /dev/videoX device *//* (like /dev/video0 or /dev/video1 ...)                          *//* for autodetect first available use video_nr=-1 (defaultvalue)  */static int video_nr = -1;#endif/* }}} *//* {{{ [fold] Miscellaneous data  */#ifndef MODULE_LICENSE		/* Appeared in 2.4.10 */#ifdef MODULE#define MODULE_LICENSE(license) \static const char __module_license[] __attribute__((section(".modinfo"))) = \	"license=" license#else#define MODULE_LICENSE(license)#endif#endifMODULE_SUPPORTED_DEVICE("video");MODULE_DESCRIPTION("Logitech QuickCam USB driver");MODULE_AUTHOR("See README");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;static const int min_framewidth  = 32;	/* Minimum image size we allow delivering to user application */static const int min_frameheight = 32;static const char qc_proc_name[] = "video/quickcam";#define qc_name (&qc_proc_name[6])static struct usb_device_id qc_device_table[] = {	{ USB_DEVICE(0x046D, 0x0840) },		/* QuickCam Express */	{ USB_DEVICE(0x046D, 0x0850) },		/* LEGO cam / QuickCam Web */	{ USB_DEVICE(0x046D, 0x0870) },		/* Dexxa WebCam USB */	{ }};MODULE_DEVICE_TABLE(usb, qc_device_table);extern const struct qc_sensor qc_sensor_pb0100;extern const struct qc_sensor qc_sensor_hdcs1000;extern const struct qc_sensor qc_sensor_hdcs1020;extern const struct qc_sensor qc_sensor_vv6410;static const struct qc_sensor *sensors[] = {	&qc_sensor_hdcs1000,	&qc_sensor_hdcs1020,	&qc_sensor_pb0100,	&qc_sensor_vv6410,};static LIST_HEAD(quickcam_list);		/* Linked list containing all QuickCams */static DECLARE_MUTEX(quickcam_list_lock);	/* Always lock first quickcam_list_lock, then qc->lock *//* Default values for user-specified lookup-table; may be overwritten by user */static unsigned char userlut_contents[QC_LUT_SIZE] = {	/* Red */	0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,	18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42,	44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69,	71, 71, 73, 75, 77, 78, 80, 81, 82, 84, 85, 87,	88, 89, 90, 91, 93, 94, 95, 97, 98, 98, 99, 101,	102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,	114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124,	125, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134,	134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143,	143, 143, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151,	152, 152, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159,	159, 160, 161, 161, 161, 162, 163, 163, 164, 165, 165, 166,	167, 167, 168, 168, 169, 170, 170, 170, 171, 171, 172, 173,	173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 179, 179,	180, 180, 181, 181, 182, 183, 183, 184, 184, 185, 185, 186,	187, 187, 188, 188, 188, 188, 189, 190, 190, 191, 191, 192,	192, 193, 193, 194, 195, 195, 196, 196, 197, 197, 197, 197,	198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 203, 204,	204, 205, 205, 206, 206, 206, 206, 207, 207, 208, 208, 209,	209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215,	215, 215, 215, 216, 216, 217, 217, 218, 218, 218, 219, 219,	220, 220, 221, 221,	/* Green */	0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,	21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47,	50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77,	79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97,	98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113,	114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126,	127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,	139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149,	150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159,	160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168,	169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177,	177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185,	186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193,	193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200,	201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207,	208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214,	214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220,	221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,	227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233,	233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,	239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244,	245, 245, 246, 246,	/* Blue */	0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,	23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51,	55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84,	86, 88, 90, 92, 94, 95, 97, 100, 101, 103, 104, 106,	107, 110, 111, 112, 114, 115, 116, 118, 119, 121, 122, 124,	125, 126, 127, 128, 129, 132, 133, 134, 135, 136, 137, 138,	139, 140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151,	152, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163,	165, 166, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174,	176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184,	185, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194,	194, 195, 196, 196, 198, 199, 200, 200, 201, 202, 202, 203,	204, 204, 205, 205, 206, 207, 207, 209, 210, 210, 211, 212,	212, 213, 213, 214, 215, 215, 216, 217, 217, 218, 218, 220,	221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,	228, 228, 229, 229, 231, 231, 232, 233, 233, 234, 234, 235,	235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 242, 242,	243, 243, 244, 244, 245, 246, 246, 247, 247, 248, 248, 249,	249, 250, 250, 251, 251, 253, 253, 254, 254, 255, 255, 255,	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,	255, 255, 255, 255};static void qc_usb_exit(struct quickcam *qc);static int qc_capt_init(struct quickcam *qc);static void qc_capt_exit(struct quickcam *qc);static int qc_capt_get(struct quickcam *qc, unsigned char **frame);static int qc_isoc_init(struct quickcam *qc);static void qc_isoc_exit(struct quickcam *qc);/* }}} *//* {{{ [fold] **** Miscellaneous functions ************************************** */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)/* {{{ [fold] usb_kill_urb(struct urb *urb) *//* Unlink URB synchronously (usb_unlink_urb may not be synchronous). * Note: at this moment the URB completion handler must not resubmit the same URB. */static void qc_usb_kill_urb(struct urb *urb) {	int r;	while ((r=usb_unlink_urb(urb)) == -EBUSY) {		/* The URB is not anymore linked (status!=-EINPROGRESS) but 		 * usb_unlink_urb() was asynchronous and URB's completion handler still will run */		set_current_state(TASK_UNINTERRUPTIBLE);		schedule_timeout( (HZ/100)==0 ? 1 : HZ/100);	}	/* if (r!=-EBUSY),	 * usb_unlink_urb() called synchronously the completion handler and	 * there's no need to wait or anything else */	if (r) PDEBUG("qc_usb_kill_urb(%p): r=%i", urb, r);}#undef usb_kill_urb#define usb_kill_urb(urb)	qc_usb_kill_urb(urb)/* }}} */#endif/* {{{ [fold] qc_usleep(long usec) */void qc_usleep(unsigned long usec){	wait_queue_head_t wq;	init_waitqueue_head(&wq);	interruptible_sleep_on_timeout(&wq, usec*HZ/1000000);}/* }}} *//* {{{ [fold] int qc_get_i2c(struct quickcam *qc, const struct qc_sensor *sensor, int reg) *//* Read a sensor byte or word wide register value via STV0600 I2C bus * qc_i2c_init() must be called first! */int qc_get_i2c(struct quickcam *qc, const struct qc_sensor *sensor, int reg){	struct usb_device *dev = qc->dev;	int ret;	if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_get_i2c(qc=%p,sensor=%p,reg=0x%04X)",qc,sensor,reg);	TEST_BUGR(dev==NULL);	if (sizeof(qc->dmabuf)<35) BUG();	/* We need here extra write to the STV register before reading the I2C register */	/* Also wait until there are no pending control URB requests */	if ((ret = qc_stv_set(qc, STV_REG23, sensor->reg23))<0) goto fail;	memset(qc->dmabuf, 0, 35);	qc->dmabuf[0]    = reg;	qc->dmabuf[0x20] = sensor->i2c_addr;	qc->dmabuf[0x21] = 0;			/* 0+1 = 1 value, one byte or word wide register */	qc->dmabuf[0x22] = 3;			/* Read I2C register */	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		0x04,		0x40,		0x1400, 0,			/* Write I2C register address, 35 bytes */		qc->dmabuf, 0x23, 3*HZ);	if (ret < 0) goto fail;	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		0x04,		0xC0,		0x1410, 0, 			/* Read register contents from I2C, 1 or 2 bytes */		qc->dmabuf, sensor->length_id, 3*HZ);	if (ret < 0) goto fail;	ret = qc->dmabuf[0];	if (sensor->length_id>1) ret |= qc->dmabuf[1]<<8;	/* Assume LSB is always first from data received via USB */	if (qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_get_i2c(reg=0x%04X) = %04X", reg, ret);	return ret;fail:	PDEBUG("qc_get_i2c failed, code=%i",ret);	return ret;}/* }}} *//* {{{ [fold] int qc_stv_set(struct quickcam *qc, unsigned short reg, unsigned char val) *//* * Set one byte register in the STV-chip. qc_i2c_init() must be called first! */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -