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

📄 ov511_core.c

📁 支持linux2.6和linux2.4的ov511摄像头驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* OmniVision OV511 Camera-to-USB Bridge Driver * * Copyright (c) 1999-2006 Mark McClelland <mark@ovcam.org> * Original decompression code Copyright 1998-2000 OmniVision Technologies * Many improvements by Bret Wallach <bwallac1@san.rr.com> * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000) * Snapshot code by Kevin Moore * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org> * Changes by Claudio Matsuoka <claudio@conectiva.com> * Kernel I2C interface improvements by Ky鰏ti M鋖kki * URB error messages and device_hint from pwc driver by Nemosoft * Small V4L pieces from bttv by Ralph & Marcus Metzler, Gerd Knorr, and *  Justin Schoeman * Memory management (rvmalloc) code from bttv driver, by Gerd Knorr and others * * Based on the Linux CPiA driver written by Peter Pregler, * Scott J. Bertin and Johannes Erdfelt. *  * Please see the file: Documentation/usb/ov511.txt  * and the website at:  http://ovcam.org/ov511 * for more info. * * 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. NO WARRANTY OF ANY KIND is expressed or implied. */#include <linux/config.h>#include <linux/version.h>/* 2.6 Doesn't support /proc/video, but this is still defined somewhere */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)#  undef CONFIG_VIDEO_PROC_FS#endif#if defined(CONFIG_VIDEO_PROC_FS)#  include <asm/io.h>#endif#include <asm/semaphore.h>#include <asm/processor.h>#include <linux/module.h>#include <linux/init.h>#include <linux/vmalloc.h>#include <linux/slab.h>#if defined(CONFIG_VIDEO_PROC_FS)#  include <linux/fs.h>#  include <linux/proc_fs.h>#endif#include <linux/ctype.h>#include <linux/pagemap.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 68)#  include <linux/wrapper.h>#endif#include <linux/video_decoder.h>#include <linux/mm.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)#  include <linux/device.h>#endif#include "ov511.h"#include "id.h"#include "driver_version.h"#if defined(OUTSIDE_KERNEL)#  include "tuner.h"#else#  if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)#    include "../media/video/tuner.h"#  else#    include <media/tuner.h>#  endif#endif/* Driver will compile with older kernels, but will oops on open() */#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19)#  error "Kernel 2.4.19 is the minimum for this driver"#endif/* * Version Information */#if 0	/* Version is in driver_version.h */#define DRIVER_VERSION "vX.XX"#define DRIVER_VERSION_CODE KERNEL_VERSION(X,XX,0)#endif#define EMAIL "mark@ovcam.org"#define DRIVER_AUTHOR "Mark McClelland <mark@ovcam.org> & Bret Wallach \	& Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \	<cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"#define DRIVER_DESC "ov511 USB Camera Driver"#define OV511_I2C_RETRIES    6#define OV511_MAX_UNIT_VIDEO 16#define OV511_MAX_DEV_HINTS  16/* Pixel count * bytes per YUV420 pixel (1.5) */#define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3 / 2)#define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval))/* Max size * bytes per YUV420 pixel (1.5) + one extra isoc frame for safety */#define MAX_RAW_DATA_SIZE(w, h) ((w) * (h) * 3 / 2 + 1024)#define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM)#if defined (HAVE_V4L2)/* No private controls defined yet */#define OV51X_CID_LASTP1     (V4L2_CID_PRIVATE_BASE + 0)/* CID offsets for various components */#define OV51X_CID_OFFSET    0#define SENSOR_CID_OFFSET   (OV51X_CID_OFFSET + \                             (OVCAMCHIP_V4L2_CID_LASTP1 - \                              V4L2_CID_PRIVATE_BASE))#endif/********************************************************************** * Module Parameters * (See ov511.txt for detailed descriptions of these) **********************************************************************//* These variables (and all static globals) default to zero */static int autobright		= 1;static int autoexp		= 1;#ifdef OV511_DEBUGstatic int debug;int ov511_debug		= 0; /* Same as debug; for external compilation units */#endifstatic int snapshot;static int cams			= 1;static int compress;static int dumppix;static int led 			= 1;static int dump_bridge;static int printph;static int phy			= 0x1f;static int phuv			= 0x05;static int pvy			= 0x06;static int pvuv			= 0x06;static int qhy			= 0x14;static int qhuv			= 0x03;static int qvy			= 0x04;static int qvuv			= 0x04;static int lightfreq;static int bandingfilter;static int clockdiv		= -1;static int packetsize		= -1;static int framedrop		= -1;static int fastset;static int force_palette;static int tuner		= -1;static int backlight;static int unit_video[OV511_MAX_UNIT_VIDEO];static int remove_zeros;static int mirror;int ov518_color 		= 1;static int i2c_clockdiv		= 1;static char *dev_hint[OV511_MAX_DEV_HINTS] = { };#if defined (HAVE_V4L2)static int v4l2;#endifmodule_param(autobright, int, 0);MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness");module_param(autoexp, int, 0);MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure");#ifdef OV511_DEBUGmodule_param(debug, int, 0);MODULE_PARM_DESC(debug,  "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max");#endifmodule_param(snapshot, int, 0);MODULE_PARM_DESC(snapshot, "Enable snapshot mode");module_param(cams, int, 0);MODULE_PARM_DESC(cams, "Number of simultaneous cameras");module_param(compress, int, 0);MODULE_PARM_DESC(compress, "Turn on compression");module_param(dumppix, int, 0);MODULE_PARM_DESC(dumppix, "Dump raw pixel data");module_param(led, int, 0);MODULE_PARM_DESC(led,  "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)");module_param(dump_bridge, int, 0);MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers");module_param(printph, int, 0);MODULE_PARM_DESC(printph, "Print frame start/end headers");module_param(phy, int, 0);MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)");module_param(phuv, int, 0);MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)");module_param(pvy, int, 0);MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)");module_param(pvuv, int, 0);MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)");module_param(qhy, int, 0);MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)");module_param(qhuv, int, 0);MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)");module_param(qvy, int, 0);MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)");module_param(qvuv, int, 0);MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)");module_param(lightfreq, int, 0);MODULE_PARM_DESC(lightfreq,  "Light frequency. Set to 50 or 60 Hz, or zero for default settings");module_param(bandingfilter, int, 0);MODULE_PARM_DESC(bandingfilter,  "Enable banding filter (to reduce effects of fluorescent lighting)");module_param(clockdiv, int, 0);MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value");module_param(packetsize, int, 0);MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size");module_param(framedrop, int, 0);MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting");module_param(fastset, int, 0);MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately");module_param(force_palette, int, 0);MODULE_PARM_DESC(force_palette, "Force the palette to a specific value");module_param(tuner, int, 0);MODULE_PARM_DESC(tuner, "Set tuner type, if not autodetected");module_param(backlight, int, 0);MODULE_PARM_DESC(backlight, "For objects that are lit from behind");#if defined(module_param_array)static int num_uv;module_param_array(unit_video, int, &num_uv, 0);#elseMODULE_PARM(unit_video, "1-" __MODULE_STRING(OV511_MAX_UNIT_VIDEO) "i");#endifMODULE_PARM_DESC(unit_video,  "Force use of specific minor number(s). 0 is not allowed.");module_param(remove_zeros, int, 0);MODULE_PARM_DESC(remove_zeros,  "Remove zero-padding from uncompressed incoming data");module_param(mirror, int, 0);MODULE_PARM_DESC(mirror, "Reverse image horizontally");module_param(ov518_color, int, 0);MODULE_PARM_DESC(ov518_color, "Enable OV518 color");module_param(i2c_clockdiv, int, 0);MODULE_PARM_DESC(i2c_clockdiv, "Set I2C clock divider");#if defined(module_param_array)static int num_dev_hint;module_param_array(dev_hint, charp, &num_dev_hint, 0);#elseMODULE_PARM(dev_hint, "0-" __MODULE_STRING(OV511_MAX_DEV_HINTS) "s");#endifMODULE_PARM_DESC(dev_hint, "Device node hints");#if defined HAVE_V4L2module_param(v4l2, int, 0);MODULE_PARM_DESC(v4l2, "Enable Video4Linux 2 support");#endifMODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);#if defined(MODULE_LICENSE)	/* Introduced in ~2.4.10 */MODULE_LICENSE("GPL");#endif/********************************************************************** * Miscellaneous Globals **********************************************************************/static struct usb_driver ov511_driver;/* Prevents double-free of ov struct */static struct semaphore ov_free_lock;static struct usb_device_id device_table [] = {	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV518) },	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) },	{ USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) },	{ }  /* Terminating entry */};MODULE_DEVICE_TABLE (usb, device_table);static unsigned char yQuanTable511[] = OV511_YQUANTABLE;static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE;static unsigned char yQuanTable518[] = OV518_YQUANTABLE;static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE;struct device_hint {	int cid;	int minor;} device_hint[OV511_MAX_UNIT_VIDEO];/********************************************************************** * Symbolic Names **********************************************************************//* Known OV511-based cameras */static struct symbolic_list camlist[] = {	{   0, "Generic Camera" },	{   1, "Mustek WCam 3X" },	{   3, "D-Link DSB-C300" },	{   4, "Generic OV511/OV7610" },	{   5, "Puretek PT-6007" },	{   6, "Lifeview USB Life TV (NTSC)" },	{  10, "Aiptek HyperVcam Home" },	{  21, "Creative Labs WebCam 3" },	{  22, "Lifeview USB Life TV (PAL D/K+B/G)" },	{  36, "Koala-Cam" },	{  38, "Lifeview USB Life TV (PAL)" },	{  41, "Samsung Anycam MPC-M10" },	{  43, "Mtekvision Zeca MV402" },	{  44, "LG Electronics LPC-UM10" },	{  46, "Suma eON" },	{  70, "Lifeview USB Life TV (PAL/SECAM)" },	{ 100, "Lifeview RoboCam" },	{ 102, "AverMedia InterCam Elite" },	{ 108, "Alpha Vision Tech. AlphaCam SE" },	{ 112, "MediaForte MV300" },	/* or OV7110 evaluation kit */	{ 134, "Ezonics EZCam II" },	{ 150, "Lifeview USB Life TV/FM (PAL D/K+B/G)" },	{ 192, "Webeye 2000B" },	{ 193, "Interbiometrics Securecam" },	{ 194, "Interbiometrics Securecam" },	{ 195, "Interbiometrics Securecam" },	{ 196, "Interbiometrics Securecam" },	{ 253, "Alpha Vision Tech. AlphaCam SE" },	{  -1, NULL }};/* Video4Linux1 Palettes */static struct symbolic_list v4l1_plist[] = {	{ VIDEO_PALETTE_GREY,	"GREY" },	{ VIDEO_PALETTE_HI240,	"HI240" },	{ VIDEO_PALETTE_RGB565,	"RGB565" },	{ VIDEO_PALETTE_RGB24,	"RGB24" },	{ VIDEO_PALETTE_RGB32,	"RGB32" },	{ VIDEO_PALETTE_RGB555,	"RGB555" },	{ VIDEO_PALETTE_YUV422,	"YUV422" },	{ VIDEO_PALETTE_YUYV,	"YUYV" },	{ VIDEO_PALETTE_UYVY,	"UYVY" },	{ VIDEO_PALETTE_YUV420,	"YUV420" },	{ VIDEO_PALETTE_YUV411,	"YUV411" },	{ VIDEO_PALETTE_RAW,	"RAW" },	{ VIDEO_PALETTE_YUV422P,"YUV422P" },	{ VIDEO_PALETTE_YUV411P,"YUV411P" },	{ VIDEO_PALETTE_YUV420P,"YUV420P" },	{ VIDEO_PALETTE_YUV410P,"YUV410P" },	{ -1, NULL }};static struct symbolic_list brglist[] = {	{ BRG_OV511,		"OV511" },	{ BRG_OV511PLUS,	"OV511+" },	{ BRG_OV518,		"OV518" },	{ BRG_OV518PLUS,	"OV518+" },	{ -1, NULL }};#if defined(CONFIG_VIDEO_PROC_FS) || defined(HAVE_V4L2)static struct symbolic_list senlist[] = {	{ CC_OV76BE,	"OV76BE" },	{ CC_OV7610,	"OV7610" },	{ CC_OV7620,	"OV7620" },	{ CC_OV7620AE,	"OV7620AE" },	{ CC_OV6620,	"OV6620" },	{ CC_OV6630,	"OV6630" },	{ CC_OV6630AE,	"OV6630AE" },	{ CC_OV6630AF,	"OV6630AF" },	{ SEN_SAA7111A,	"SAA7111A" },	{ -1, NULL }};#endif/* URB error codes: */static struct symbolic_list urb_errlist[] = {	{ -ENOSR,	"Buffer error (overrun)" },	{ -EPIPE,	"Stalled (device not responding)" },	{ -EOVERFLOW,	"Babble (bad cable?)" },	{ -EPROTO,	"Bit-stuff error (bad cable?)" },	{ -EILSEQ,	"CRC/Timeout" },	{ -ETIMEDOUT,	"NAK (device does not respond)" },	{ -1, NULL }};#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)static const char *v4l1_ioctls[] = {	"?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",	"CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",	"SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",	"GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",	"SMICROCODE", "GVBIFMT", "SVBIFMT" };#define NUM_V4L1_IOCTLS (sizeof(v4l1_ioctls)/sizeof(char*))#endif/********************************************************************** * Prototypes **********************************************************************/static int saa7111a_configure(struct usb_ov511 *);static int ov7xx0_configure(struct usb_ov511 *);static int ov6xx0_configure(struct usb_ov511 *);/********************************************************************** * Memory management **********************************************************************/#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)/* Here we want the physical address of the memory. * This is used when initializing the contents of the area. */static inline unsigned longkvirt_to_pa(unsigned long adr){	unsigned long kva, ret;	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));	kva |= adr & (PAGE_SIZE-1); /* restore the offset */	ret = __pa(kva);	return ret;}#endifstatic void *rvmalloc(unsigned long size){	void *mem;	unsigned long adr;	size = PAGE_ALIGN(size);	mem = vmalloc_32(size);	if (!mem)		return NULL;	memset(mem, 0, size); /* Clear the ram out, no junk to the user */	adr = (unsigned long) mem;	while (size > 0) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 68)		SetPageReserved(vmalloc_to_page((void *)adr));#else		mem_map_reserve(vmalloc_to_page((void *)adr));#endif		adr += PAGE_SIZE;		size -= PAGE_SIZE;	}	return mem;}static voidrvfree(void *mem, unsigned long size){	unsigned long adr;	if (!mem)		return;	adr = (unsigned long) mem;	while ((long) size > 0) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 68)		ClearPageReserved(vmalloc_to_page((void *)adr));#else		mem_map_unreserve(vmalloc_to_page((void *)adr));#endif		adr += PAGE_SIZE;		size -= PAGE_SIZE;	}	vfree(mem);}/********************************************************************** * /proc interface * Based on the CPiA driver version 0.7.4 -claudio **********************************************************************/#if defined(CONFIG_VIDEO_PROC_FS)static struct proc_dir_entry *ov511_proc_entry = NULL;extern struct proc_dir_entry *video_proc_entry;/* Prototypes */static int sensor_get_picture(struct usb_ov511 *, struct video_picture *);static int sensor_get_control(struct usb_ov511 *, int, int *);static int ov51x_check_snapshot(struct usb_ov511 *);static void ov51x_clear_snapshot(struct usb_ov511 *);static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int,			       unsigned long);static struct file_operations ov511_control_fops = {	.ioctl =	ov51x_control_ioctl,};#define YES_NO(x) ((x) ? "yes" : "no")/* /proc/video/ov511/<minor#>/info */static intov511_read_proc_info(char *page, char **start, off_t off, int count, int *eof,		     void *data){	char *out = page;	int i, len;	struct usb_ov511 *ov = data;	struct video_picture p;	int exp = 0;	if (!ov || !ov->dev)		return -ENODEV;	sensor_get_picture(ov, &p);	sensor_get_control(ov, OVCAMCHIP_CID_EXP, &exp);	/* IMPORTANT: This output MUST be kept under PAGE_SIZE	 *            or we need to get more sophisticated. */	out += sprintf(out, "driver_version  : %s\n", DRIVER_VERSION);	out += sprintf(out, "custom_id       : %d\n", ov->customid);	out += sprintf(out, "model           : %s\n", ov->desc);	out += sprintf(out, "streaming       : %s\n", YES_NO(ov->streaming));	out += sprintf(out, "grabbing        : %s\n", YES_NO(ov->grabbing));	out += sprintf(out, "can_decompress  : %s\n", YES_NO(ov->decomp_ops));	out += sprintf(out, "compress        : %s\n", YES_NO(ov->compress));	out += sprintf(out, "subcapture      : %s\n", YES_NO(ov->sub_flag));	out += sprintf(out, "sub_size        : %d %d %d %d\n",		       ov->subx, ov->suby, ov->subw, ov->subh);	out += sprintf(out, "brightness      : %d\n", p.brightness >> 8);	out += sprintf(out, "colour          : %d\n", p.colour >> 8);	out += sprintf(out, "contrast        : %d\n", p.contrast >> 8);	out += sprintf(out, "hue             : %d\n", p.hue >> 8);	out += sprintf(out, "exposure        : %d\n", exp);	out += sprintf(out, "num_frames      : %d\n", OV511_NUMFRAMES);	for (i = 0; i < OV511_NUMFRAMES; i++) {		out += sprintf(out, "frame           : %d\n", i);		out += sprintf(out, "  depth         : %d\n",

⌨️ 快捷键说明

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