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

📄 ov511.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * OmniVision OV511 Camera-to-USB Bridge Driver * * Copyright (c) 1999-2000 Mark W. McClelland * 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> *  * Based on the Linux CPiA driver written by Peter Pregler, * Scott J. Bertin and Johannes Erdfelt. *  * Please see the file: linux/Documentation/usb/ov511.txt  * and the website at:  http://alpha.dyndns.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. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */static const char version[] = "1.28";#define __NO_VERSION__#include <linux/config.h>#include <linux/module.h>#include <linux/version.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/vmalloc.h>#include <linux/slab.h>#include <linux/proc_fs.h>#include <linux/ctype.h>#include <linux/pagemap.h>#include <linux/usb.h>#include <asm/io.h>#include <asm/semaphore.h>#include <linux/wrapper.h>#include "ov511.h"#define OV511_I2C_RETRIES 3/* Video Size 640 x 480 x 3 bytes for RGB */#define MAX_FRAME_SIZE (640 * 480 * 3)#define MAX_DATA_SIZE (MAX_FRAME_SIZE + sizeof(struct timeval))#define GET_SEGSIZE(p) ((p) == VIDEO_PALETTE_GREY ? 256 : 384)/* PARAMETER VARIABLES: */static int autoadjust = 1;    /* CCD dynamically changes exposure, etc... *//* 0=no debug messages * 1=init/detection/unload and other significant messages, * 2=some warning messages * 3=config/control function calls * 4=most function calls and data parsing messages * 5=highly repetitive mesgs * NOTE: This should be changed to 0, 1, or 2 for production kernels */static int debug = 0;/* Fix vertical misalignment of red and blue at 640x480 */static int fix_rgb_offset = 0;/* Snapshot mode enabled flag */static int snapshot = 0;/* Sensor detection override (global for all attached cameras) */static int sensor = 0;/* Increase this if you are getting "Failed to read sensor ID..." */static int i2c_detect_tries = 5;/* For legal values, see the OV7610/7620 specs under register Common F, * upper nybble  (set to 0-F) */static int aperture = -1;/* Force image to be read in RGB instead of BGR. This option allow * programs that expect RGB data (e.g. gqcam) to work with this driver. */static int force_rgb = 0;/* Number of seconds before inactive buffers are deallocated */static int buf_timeout = 5;/* Number of cameras to stream from simultaneously */static int cams = 1;/* Prevent apps from timing out if frame is not done in time */static int retry_sync = 0;/* Enable compression. This is for experimentation only; compressed images * still cannot be decoded yet. */static int compress = 0;/* Display test pattern - doesn't work yet either */static int testpat = 0;/* Setting this to 1 will make the sensor output GBR422 instead on YUV420. Only * affects RGB24 mode. */static int sensor_gbr = 0;/* Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details. */static int dumppix = 0;MODULE_PARM(autoadjust, "i");MODULE_PARM_DESC(autoadjust, "CCD dynamically changes exposure");MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug level: 0=none, 1=init/detection, 2=warning, 3=config/control, 4=function call, 5=max");MODULE_PARM(fix_rgb_offset, "i");MODULE_PARM_DESC(fix_rgb_offset, "Fix vertical misalignment of red and blue at 640x480");MODULE_PARM(snapshot, "i");MODULE_PARM_DESC(snapshot, "Enable snapshot mode");MODULE_PARM(sensor, "i");MODULE_PARM_DESC(sensor, "Override sensor detection");MODULE_PARM(i2c_detect_tries, "i");MODULE_PARM_DESC(i2c_detect_tries, "Number of tries to detect sensor");MODULE_PARM(aperture, "i");MODULE_PARM_DESC(aperture, "Read the OV7610/7620 specs");MODULE_PARM(force_rgb, "i");MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR");MODULE_PARM(buf_timeout, "i");MODULE_PARM_DESC(buf_timeout, "Number of seconds before buffer deallocation");MODULE_PARM(cams, "i");MODULE_PARM_DESC(cams, "Number of simultaneous cameras");MODULE_PARM(retry_sync, "i");MODULE_PARM_DESC(retry_sync, "Prevent apps from timing out");MODULE_PARM(compress, "i");MODULE_PARM_DESC(compress, "Turn on compression (not functional yet)");MODULE_PARM(testpat, "i");MODULE_PARM_DESC(testpat, "Replace image with vertical bar testpattern (only partially working)");MODULE_PARM(sensor_gbr, "i");MODULE_PARM_DESC(sensor_gbr, "Make sensor output GBR422 rather than YUV420");MODULE_PARM(dumppix, "i");MODULE_PARM_DESC(dumppix, "Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details");MODULE_AUTHOR("Mark McClelland <mwm@i.am> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>");MODULE_DESCRIPTION("OV511 USB Camera Driver");char kernel_version[] = UTS_RELEASE;static struct usb_driver ov511_driver;/* I know, I know, global variables suck. This is only a temporary hack */int output_offset;/********************************************************************** * List of known OV511-based cameras **********************************************************************/static struct cam_list clist[] = {	{   0, "generic model (no ID)" },	{   3, "D-Link DSB-C300" },	{   4, "generic OV511/OV7610" },	{   5, "Puretek PT-6007" },	{  21, "Creative Labs WebCam 3" },	{  36, "Koala-Cam" },	{  38, "Lifeview USB Life TV" },	/* No support yet! */	{ 100, "Lifeview RoboCam" },	{ 102, "AverMedia InterCam Elite" },	{ 112, "MediaForte MV300" },	/* or OV7110 evaluation kit */	{  -1, NULL }};static __devinitdata struct usb_device_id device_table [] = {	{ USB_DEVICE(0x05a9, 0x0511) },  /* OV511 */	{ USB_DEVICE(0x05a9, 0xA511) },  /* OV511+ */	{ USB_DEVICE(0x0813, 0x0002) },  /* Intel Play Me2Cam OV511+ */	{ }  /* Terminating entry */};MODULE_DEVICE_TABLE (usb, device_table);#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)static struct palette_list 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 }};#endif/********************************************************************** * * Memory management * * This is a shameless copy from the USB-cpia driver (linux kernel * version 2.3.29 or so, I have no idea what this code actually does ;). * Actually it seems to be a copy of a shameless copy of the bttv-driver. * Or that is a copy of a shameless copy of ... (To the powers: is there * no generic kernel-function to do this sort of stuff?) * * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says * there will be one, but apparentely not yet -jerdfelt * * So I copied it again for the OV511 driver -claudio **********************************************************************//* Given PGD from the address space's page table, return the kernel * virtual mapping of the physical memory mapped at ADR. */static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr){	unsigned long ret = 0UL;	pmd_t *pmd;	pte_t *ptep, pte;	if (!pgd_none(*pgd)) {		pmd = pmd_offset(pgd, adr);		if (!pmd_none(*pmd)) {			ptep = pte_offset(pmd, adr);			pte = *ptep;			if (pte_present(pte)) {				ret = (unsigned long) page_address(pte_page(pte));				ret |= (adr & (PAGE_SIZE - 1));			}		}	}	return ret;}/* Here we want the physical address of the memory. * This is used when initializing the contents of the * area and marking the pages as reserved. */static inline unsigned long kvirt_to_pa(unsigned long adr){	unsigned long va, kva, ret;	va = VMALLOC_VMADDR(adr);	kva = uvirt_to_kva(pgd_offset_k(va), va);	ret = __pa(kva);	return ret;}static void *rvmalloc(unsigned long size){	void *mem;	unsigned long adr, page;	/* Round it off to PAGE_SIZE */	size += (PAGE_SIZE - 1);	size &= ~(PAGE_SIZE - 1);	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) {		page = kvirt_to_pa(adr);		mem_map_reserve(virt_to_page(__va(page)));		adr += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	return mem;}static void rvfree(void *mem, unsigned long size){	unsigned long adr, page;	if (!mem)		return;	size += (PAGE_SIZE - 1);	size &= ~(PAGE_SIZE - 1);	adr=(unsigned long) mem;	while (size > 0) {		page = kvirt_to_pa(adr);		mem_map_unreserve(virt_to_page(__va(page)));		adr += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	vfree(mem);}/********************************************************************** * /proc interface * Based on the CPiA driver version 0.7.4 -claudio **********************************************************************/#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)static struct proc_dir_entry *ov511_proc_entry = NULL;extern struct proc_dir_entry *video_proc_entry;#define YES_NO(x) ((x) ? "yes" : "no")static int ov511_read_proc(char *page, char **start, off_t off,                          int count, int *eof, void *data){	char *out = page;	int i, j, len;	struct usb_ov511 *ov511 = data;	/* IMPORTANT: This output MUST be kept under PAGE_SIZE	 *            or we need to get more sophisticated. */	out += sprintf (out, "driver_version  : %s\n", version);	out += sprintf (out, "custom_id       : %d\n", ov511->customid);	out += sprintf (out, "model           : %s\n", ov511->desc ?		clist[ov511->desc].description : "unknown");	out += sprintf (out, "streaming       : %s\n", YES_NO (ov511->streaming));	out += sprintf (out, "grabbing        : %s\n", YES_NO (ov511->grabbing));	out += sprintf (out, "compress        : %s\n", YES_NO (ov511->compress));	out += sprintf (out, "subcapture      : %s\n", YES_NO (ov511->sub_flag));	out += sprintf (out, "sub_size        : %d %d %d %d\n",		ov511->subx, ov511->suby, ov511->subw, ov511->subh);	out += sprintf (out, "data_format     : %s\n", force_rgb ? "RGB" : "BGR");	out += sprintf (out, "brightness      : %d\n", ov511->brightness >> 8);	out += sprintf (out, "colour          : %d\n", ov511->colour >> 8);	out += sprintf (out, "contrast        : %d\n", ov511->contrast >> 8);	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",			ov511->frame[i].depth);		out += sprintf (out, "  size          : %d %d\n",			ov511->frame[i].width, ov511->frame[i].height);		out += sprintf (out, "  format        : ");		for (j = 0; plist[j].num >= 0; j++) {			if (plist[j].num == ov511->frame[i].format) {				out += sprintf (out, "%s\n", plist[j].name);				break;			}		}		if (plist[j].num < 0)			out += sprintf (out, "unknown\n");		out += sprintf (out, "  segsize       : %d\n",			ov511->frame[i].segsize);		out += sprintf (out, "  data_buffer   : 0x%p\n",			ov511->frame[i].data);	}	out += sprintf (out, "snap_enabled    : %s\n", YES_NO (ov511->snap_enabled));	out += sprintf (out, "bridge          : %s\n",		ov511->bridge == BRG_OV511 ? "OV511" :		ov511->bridge == BRG_OV511PLUS ? "OV511+" :		"unknown");	out += sprintf (out, "sensor          : %s\n",		ov511->sensor == SEN_OV6620 ? "OV6620" :		ov511->sensor == SEN_OV7610 ? "OV7610" :		ov511->sensor == SEN_OV7620 ? "OV7620" :		ov511->sensor == SEN_OV7620AE ? "OV7620AE" :		"unknown");	out += sprintf (out, "packet_size     : %d\n", ov511->packet_size);	out += sprintf (out, "framebuffer     : 0x%p\n", ov511->fbuf);		len = out - page;	len -= off;	if (len < count) {		*eof = 1;		if (len <= 0) return 0;	} else		len = count;	*start = page + off;	return len;}static int ov511_write_proc(struct file *file, const char *buffer,                           unsigned long count, void *data){	return -EINVAL;}static void create_proc_ov511_cam (struct usb_ov511 *ov511){	char name[7];	struct proc_dir_entry *ent;		if (!ov511_proc_entry || !ov511)		return;	sprintf(name, "video%d", ov511->vdev.minor);	PDEBUG (4, "creating /proc/video/ov511/%s", name);		ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_entry);	if (!ent)		return;	ent->data = ov511;	ent->read_proc = ov511_read_proc;	ent->write_proc = ov511_write_proc;	ov511->proc_entry = ent;}static void destroy_proc_ov511_cam (struct usb_ov511 *ov511){	char name[7];		if (!ov511 || !ov511->proc_entry)		return;		sprintf(name, "video%d", ov511->vdev.minor);	PDEBUG (4, "destroying %s", name);	remove_proc_entry(name, ov511_proc_entry);	ov511->proc_entry = NULL;}static void proc_ov511_create(void){	/* No current standard here. Alan prefers /proc/video/ as it keeps	 * /proc "less cluttered than /proc/randomcardifoundintheshed/"	 * -claudio	 */	if (video_proc_entry == NULL) {		err("Unable to initialise /proc/video/ov511");		return;	}	ov511_proc_entry = create_proc_entry("ov511", S_IFDIR, video_proc_entry);	if (ov511_proc_entry)		ov511_proc_entry->owner = THIS_MODULE;	else		err("Unable to initialise /proc/ov511");}static void proc_ov511_destroy(void){	PDEBUG (3, "removing /proc/video/ov511");	if (ov511_proc_entry == NULL)		return;	remove_proc_entry("ov511", video_proc_entry);}#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS *//********************************************************************** * * Camera interface * **********************************************************************/static int ov511_reg_write(struct usb_device *dev,			   unsigned char reg,			   unsigned char value){	int rc;	rc = usb_control_msg(dev,		usb_sndctrlpipe(dev, 0),		2 /* REG_IO */,		USB_TYPE_CLASS | USB_RECIP_DEVICE,		0, (__u16)reg, &value, 1, HZ);		PDEBUG(5, "reg write: 0x%02X:0x%02X, 0x%x", reg, value, rc);	if (rc < 0)		err("reg write: error %d", rc);	return rc;}/* returns: negative is error, pos or zero is data */static int ov511_reg_read(struct usb_device *dev, unsigned char reg){	int rc;	unsigned char buffer[1];	rc = usb_control_msg(dev,		usb_rcvctrlpipe(dev, 0),		2 /* REG_IO */,		USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,		0, (__u16)reg, buffer, 1, HZ);                               

⌨️ 快捷键说明

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