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

📄 ovfx2.c

📁 支持linux2.6和linux2.4的ov511摄像头驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* OmniVision/Cypress FX2 Camera-to-USB Bridge Driver * * Copyright (c) 1999-2006 Mark McClelland <mark@ovcam.org>, David Brownell * Many improvements by Bret Wallach <bwallac1@san.rr.com> * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000) * 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 from pwc driver by Nemosoft * Memory management (rvmalloc) code from bttv driver, by Gerd Knorr and others * * Based on the Linux OV511 driver by Mark W. McClelland, which is * based on the Linux CPiA driver written by Peter Pregler, * Scott J. Bertin and Johannes Erdfelt. *  * Please see 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/mm.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)#  include <linux/device.h>#endif#include "ovfx2.h"#include "id.h"#include "driver_version.h"/* 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 "ovfx2 USB Camera Driver"#define OVFX2_MAX_UNIT_VIDEO 16/* Pixel count * 3 bytes per pixel (for BGR24) */#define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3)#define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval))/* Max size * 2 bytes per pixel average + safety margin */#define MAX_RAW_DATA_SIZE(w, h) ((w) * (h) * 2)#define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM)#if defined (HAVE_V4L2)/* No private controls defined yet */#define OVFX2_CID_LASTP1     (V4L2_CID_PRIVATE_BASE + 0)/* CID offsets for various components */#define OVFX2_CID_OFFSET    0#define SENSOR_CID_OFFSET   (OVFX2_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 OVFX2_DEBUGstatic int debug;#endifstatic int dumppix;static int dump_bridge;static int lightfreq;static int bandingfilter;static int clockdiv		= -1;static int framedrop		= -1;static int fastset;static int force_palette;static int backlight;static int unit_video[OVFX2_MAX_UNIT_VIDEO];static int mirror;#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 OVFX2_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(dumppix, int, 0);MODULE_PARM_DESC(dumppix, "Dump raw pixel data");module_param(dump_bridge, int, 0);MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers");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(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(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(OVFX2_MAX_UNIT_VIDEO) "i");#endifMODULE_PARM_DESC(unit_video,  "Force use of specific minor number(s). 0 is not allowed.");module_param(mirror, int, 0);MODULE_PARM_DESC(mirror, "Reverse image horizontally");#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 ovfx2_driver;/* Prevents double-free of ov struct */static struct semaphore ov_free_lock;/* * Omnivision provided a reference design and firmware connecting an FX2 * to many of their I2C-aware sensor arrays.  Different products using * this design could have different sensors. */static struct usb_device_id device_table [] = {	/*	 * Orange Micro "iBOT2" uses an ov7620. It does not have a snapshot	 * button or L.E.D.	 *	 * HIGH SPEED:	 *	 * T:  Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=480 MxCh= 0	 * D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1	 * P:  Vendor=0b62 ProdID=0059 Rev= 1.00	 * S:  Manufacturer=Orange Micro	 * S:  Product=iBOT2 Camera	 * C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=400mA	 * I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)	 * E:  Ad=81(I) Atr=03(Int.) MxPS=   4 Ivl=  4ms	 * E:  Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=  1ms	 *	 * FULL SPEED:	 *	 * T:  Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  3 Spd=12  MxCh= 0	 * D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1	 * P:  Vendor=0b62 ProdID=0059 Rev= 1.00	 * S:  Manufacturer=Orange Micro	 * S:  Product=iBOT2 Camera	 * C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=400mA	 * I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)	 * E:  Ad=81(I) Atr=03(Int.) MxPS=   4 Ivl=  1ms	 * E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=  1ms	 *	 */	{ USB_DEVICE (VEND_ORANGE_MICRO, PROD_IBOT2),		.driver_info = (unsigned long) "Orange Micro iBOT2",		},	/* OmniVision "2800" reference board, which supports almost all	 * of their camera chips. The following boards are known to work:	 *   - OV7620-ECX	 */	{ USB_DEVICE (VEND_OMNIVISION, PROD_2800),		.driver_info = (unsigned long) "OmniVision \"2800\" ref. board",		},	/* Trust Sp@cec@m 380 (OV7620),	 * Aplux MU2-35 (OV7620),	 * Aplux MU2-48 (OV86108), or	 * Aplux MU2-130 (OV9620).	 *	 * These are all based on the "2800" reference design. They have a	 * snapshot button and an L.E.D.	 */ 	{ USB_DEVICE (VEND_APLUX, PROD_MU2CAM),		.driver_info = (unsigned long)			"Aplux MU2-35/48/130 or Trust 380",		},	{ }};MODULE_DEVICE_TABLE (usb, device_table);/********************************************************************** * Symbolic Names **********************************************************************//* 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 }};#if defined(CONFIG_VIDEO_PROC_FS) \ || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || 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" },	{ -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 ov7xx0_configure(struct usb_ovfx2 *);/********************************************************************** * 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 *ovfx2_proc_entry = NULL;extern struct proc_dir_entry *video_proc_entry;/* Prototypes */static int sensor_get_picture(struct usb_ovfx2 *, struct video_picture *);static int sensor_get_control(struct usb_ovfx2 *, int, int *);#define YES_NO(x) ((x) ? "yes" : "no")/* /proc/video/ovfx2/<minor#>/info */static intovfx2_read_proc_info(char *page, char **start, off_t off, int count, int *eof,		     void *data){	char *out = page;	int i, len;	struct usb_ovfx2 *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, "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, "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", OVFX2_NUMFRAMES);	for (i = 0; i < OVFX2_NUMFRAMES; i++) {		out += sprintf(out, "frame           : %d\n", i);		out += sprintf(out, "  size          : %d %d\n",			       ov->frame[i].width, ov->frame[i].height);		out += sprintf(out, "  format        : %s\n",			       symbolic(v4l1_plist, ov->frame[i].format));	}	out += sprintf(out, "sensor          : %s\n",		       symbolic(senlist, ov->sensor));#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 20)	out += sprintf(out, "topology        : %s\n", ov->usb_path);#else	out += sprintf(out, "usb_bus         : %d\n", ov->dev->bus->busnum);	out += sprintf(out, "usb_device      : %d\n", ov->dev->devnum);#endif	out += sprintf(out, "i2c_adap_id     : %d\n",	               i2c_adapter_id(&ov->i2c_adap));	len = out - page;	len -= off;	if (len < count) {		*eof = 1;		if (len <= 0)			return 0;	} else		len = count;	*start = page + off;	return len;}static voidcreate_proc_ovfx2_cam(struct usb_ovfx2 *ov){	char dirname[10];	if (!ovfx2_proc_entry || !ov)		return;	/* Create per-device directory */	snprintf(dirname, 10, "%d", ov->vdev->minor);	ov->proc_devdir = create_proc_entry(dirname, S_IFDIR, ovfx2_proc_entry);	if (!ov->proc_devdir)		return;	ov->proc_devdir->owner = THIS_MODULE;	/* Create "info" entry (human readable device information) */	ov->proc_info = create_proc_read_entry("info", S_IFREG|S_IRUGO|S_IWUSR,		ov->proc_devdir, ovfx2_read_proc_info, ov);	if (!ov->proc_info)		return;	ov->proc_info->owner = THIS_MODULE;}static voiddestroy_proc_ovfx2_cam(struct usb_ovfx2 *ov){	char dirname[10];	if (!ov || !ov->proc_devdir)		return;	snprintf(dirname, 10, "%d", ov->vdev->minor);	/* Destroy "info" entry */	if (ov->proc_info) {		remove_proc_entry("info", ov->proc_devdir);		ov->proc_info = NULL;	}	/* Destroy per-device directory */	remove_proc_entry(dirname, ovfx2_proc_entry);	ov->proc_devdir = NULL;}static voidproc_ovfx2_create(void){	if (video_proc_entry == NULL) {		err("Error: /proc/video/ does not exist");		return;	}	ovfx2_proc_entry = create_proc_entry("ovfx2", S_IFDIR,					     video_proc_entry);	if (ovfx2_proc_entry)		ovfx2_proc_entry->owner = THIS_MODULE;	else		err("Unable to create /proc/video/ovfx2");}static voidproc_ovfx2_destroy(void){	if (ovfx2_proc_entry == NULL)		return;	remove_proc_entry("ovfx2", video_proc_entry);}#elsestatic inline void create_proc_ovfx2_cam(struct usb_ovfx2 *ov) { }static inline void destroy_proc_ovfx2_cam(struct usb_ovfx2 *ov) { }static inline void proc_ovfx2_create(void) { }static inline void proc_ovfx2_destroy(void) { }#endif /* #ifdef CONFIG_VIDEO_PROC_FS *//********************************************************************** * * Register I/O * **********************************************************************//* Write an OVFX2 register */static intreg_w(struct usb_ovfx2 *ov, unsigned char reg, unsigned char value){

⌨️ 快捷键说明

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