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

📄 ov511.c

📁 是一个linux下的摄像头驱动,网上的驱动源码比较难找,这个基本能用,根据具体的摄像头配置和设置改下,linux下可编译
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 voidrvfree(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);}#endif	/* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 5) *//********************************************************************** * /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;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;	unsigned char exp;	if (!ov || !ov->dev)		return -ENODEV;	sensor_get_picture(ov, &p);	sensor_get_exposure(ov, &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, "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);#ifdef OV511_ALLOW_CONVERSION	out += sprintf(out, "data_format     : %s\n",		       force_rgb ? "RGB" : "BGR");#endif	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",			       ov->frame[i].depth);		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, "  data_buffer   : 0x%p\n",			       ov->frame[i].data);	}	out += sprintf(out, "snap_enabled    : %s\n", YES_NO(ov->snap_enabled));	out += sprintf(out, "bridge          : %s\n",		       symbolic(brglist, ov->bridge));	out += sprintf(out, "sensor          : %s\n",		       symbolic(senlist, ov->sensor));	out += sprintf(out, "packet_size     : %d\n", ov->packet_size);	out += sprintf(out, "framebuffer     : 0x%p\n", ov->fbuf);	out += sprintf(out, "packet_numbering: %d\n", ov->packet_numbering);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)	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	len = out - page;	len -= off;	if (len < count) {		*eof = 1;		if (len <= 0)			return 0;	} else		len = count;	*start = page + off;	return len;}/* /proc/video/ov511/<minor#>/button * * When the camera's button is pressed, the output of this will change from a * 0 to a 1 (ASCII). It will retain this value until it is read, after which * it will reset to zero. * * SECURITY NOTE: Since reading this file can change the state of the snapshot * status, it is important for applications that open it to keep it locked * against access by other processes, using flock() or a similar mechanism. No * locking is provided by this driver. */static intov511_read_proc_button(char *page, char **start, off_t off, int count, int *eof,		       void *data){	char *out = page;	int len, status;	struct usb_ov511 *ov = data;	if (!ov || !ov->dev)		return -ENODEV;	status = ov51x_check_snapshot(ov);	out += sprintf(out, "%d", status);	if (status)		ov51x_clear_snapshot(ov);	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_ov511_cam(struct usb_ov511 *ov){	char dirname[10];	if (!ov511_proc_entry || !ov)		return;	/* Create per-device directory */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 10)	snprintf(dirname, 10, "%d", ov->vdev.minor);#else	sprintf(dirname, "%d", ov->vdev.minor);#endif	PDEBUG(4, "creating /proc/video/ov511/%s/", dirname);	ov->proc_devdir = create_proc_entry(dirname, S_IFDIR, ov511_proc_entry);	if (!ov->proc_devdir)		return;	ov->proc_devdir->owner = THIS_MODULE;	/* Create "info" entry (human readable device information) */	PDEBUG(4, "creating /proc/video/ov511/%s/info", dirname);	ov->proc_info = create_proc_read_entry("info", S_IFREG|S_IRUGO|S_IWUSR,		ov->proc_devdir, ov511_read_proc_info, ov);	if (!ov->proc_info)		return;	ov->proc_info->owner = THIS_MODULE;	/* Don't create it if old snapshot mode on (would cause race cond.) */	if (!snapshot) {		/* Create "button" entry (snapshot button status) */		PDEBUG(4, "creating /proc/video/ov511/%s/button", dirname);		ov->proc_button = create_proc_read_entry("button",			S_IFREG|S_IRUGO|S_IWUSR, ov->proc_devdir,			ov511_read_proc_button, ov);		if (!ov->proc_button)			return;		ov->proc_button->owner = THIS_MODULE;	}	/* Create "control" entry (ioctl() interface) */	PDEBUG(4, "creating /proc/video/ov511/%s/control", dirname);	lock_kernel();	ov->proc_control = create_proc_entry("control",	S_IFREG|S_IRUGO|S_IWUSR,		ov->proc_devdir);	if (!ov->proc_control) {		unlock_kernel();		return;	}	ov->proc_control->owner = THIS_MODULE;	ov->proc_control->data = ov;	ov->proc_control->proc_fops = &ov511_control_fops;	unlock_kernel();}static voiddestroy_proc_ov511_cam(struct usb_ov511 *ov){	char dirname[10];	if (!ov || !ov->proc_devdir)		return;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 10)	snprintf(dirname, 10, "%d", ov->vdev.minor);#else	sprintf(dirname, "%d", ov->vdev.minor);#endif	/* Destroy "control" entry */	if (ov->proc_control) {		PDEBUG(4, "destroying /proc/video/ov511/%s/control", dirname);		remove_proc_entry("control", ov->proc_devdir);		ov->proc_control = NULL;	}	/* Destroy "button" entry */	if (ov->proc_button) {		PDEBUG(4, "destroying /proc/video/ov511/%s/button", dirname);		remove_proc_entry("button", ov->proc_devdir);		ov->proc_button = NULL;	}	/* Destroy "info" entry */	if (ov->proc_info) {		PDEBUG(4, "destroying /proc/video/ov511/%s/info", dirname);		remove_proc_entry("info", ov->proc_devdir);		ov->proc_info = NULL;	}	/* Destroy per-device directory */	PDEBUG(4, "destroying /proc/video/ov511/%s/", dirname);	remove_proc_entry(dirname, ov511_proc_entry);	ov->proc_devdir = NULL;}static voidproc_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("Error: /proc/video/ does not exist");		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 create /proc/video/ov511");}static voidproc_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 *//********************************************************************** * * Register I/O * **********************************************************************//* Write an OV51x register */static intreg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value){	int rc;	PDEBUG(5, "0x%02X:0x%02X", reg, value);	down(&ov->cbuf_lock);	ov->cbuf[0] = value;	rc = usb_control_msg(ov->dev,			     usb_sndctrlpipe(ov->dev, 0),			     (ov->bclass == BCL_OV518)?1:2 /* REG_IO */,			     USB_TYPE_VENDOR | USB_RECIP_DEVICE,			     0, (__u16)reg, &ov->cbuf[0], 1, HZ);	up(&ov->cbuf_lock);	if (rc < 0)		err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc));	return rc;}/* Read from an OV51x register *//* returns: negative is error, pos or zero is data */static intreg_r(struct usb_ov511 *ov, unsigned char reg){	int rc;	down(&ov->cbuf_lock);	rc = usb_control_msg(ov->dev,			     usb_rcvctrlpipe(ov->dev, 0),			     (ov->bclass == BCL_OV518)?1:3 /* REG_IO */,			     USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,			     0, (__u16)reg, &ov->cbuf[0], 1, HZ);	if (rc < 0) {		err("reg read: error %d: %s", rc, symbolic(urb_errlist, rc));	} else {		rc = ov->cbuf[0];		PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]);	}	up(&ov->cbuf_lock);	return rc;}/* * Writes bits at positions specified by mask to an OV51x reg. Bits that are in * the same position as 1's in "mask" are cleared and set to "value". Bits * that are in the same position as 0's in "mask" are preserved, regardless * of their respective state in "value". */static intreg_w_mask(struct usb_ov511 *ov,	   unsigned char reg,	   unsigned char value,	   unsigned char mask){	int ret;	unsigned char oldval, newval;	ret = reg_r(ov, reg);	if (ret < 0)		return ret;	oldval = (unsigned char) ret;	oldval &= (~mask);		/* Clear the masked bits */	value &= mask;			/* Enforce mask on value */	newval = oldval | value;	/* Set the desired bits */	return (reg_w(ov, reg, newval));}/*  * Writes multiple (n) byte value to a single register. Only valid with certain * registers (0x30 and 0xc4 - 0xce). */static intov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n){	int rc;	PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n);	down(&ov->cbuf_lock);	*((u32 *)ov->cbuf) = __cpu_to_le32(val);	rc = usb_control_msg(ov->dev,			     usb_sndctrlpipe(ov->dev, 0),			     1 /* REG_IO */,			     USB_TYPE_VENDOR | USB_RECIP_DEVICE,			     0, (__u16)reg, ov->cbuf, n, HZ);	up(&ov->cbuf_lock);	if (rc < 0)		err("reg write multiple: error %d: %s", rc,		    symbolic(urb_errlist, rc));	return rc;}static intov511_upload_quan_tables(struct usb_ov511 *ov){	unsigned char *pYTable = yQuanTable511;	unsigned char *pUVTable = uvQuanTable511;	unsigned char val0, val1;	int i, rc, reg = R511_COMP_LUT_BEGIN;	PDEBUG(4, "Uploading quantization tables");	for (i = 0; i < OV511_QUANTABLESIZE / 2; i++) {		if (ENABLE_Y_QUANTABLE)	{			val0 = *pYTable++;			val1 = *pYTable++;			val0 &= 0x0f;			val1 &= 0x0f;			val0 |= val1 << 4;			rc = reg_w(ov, reg, val0);			if (rc < 0)				return rc;		}		if (ENABLE_UV_QUANTABLE) {			val0 = *pUVTable++;			val1 = *pUVTable++;			val0 &= 0x0f;			val1 &= 0x0f;			val0 |= val1 << 4;			rc = reg_w(ov, reg + OV511_QUANTABLESIZE/2, val0);			if (rc < 0)				return rc;		}		reg++;	}	return 0;}/* OV518 quantization tables are 8x4 (instead of 8x8) */static intov518_upload_quan_tables(struct usb_ov511 *ov){	unsigned char *pYTable = yQuanTable518;	unsigned char *pUVTable = uvQuanTable518;	unsigned char val0, val1;	int i, rc, reg = R511_COMP_LUT_BEGIN;	PDEBUG(4, "Uploading quantization tables");	for (i = 0; i < OV518_QUANTABLESIZE / 2; i++) {		if (ENABLE_Y_QUANTABLE) {			val0 = *pYTable++;			val1 = *pYTable++;			val0 &= 0x0f;			val1 &= 0x0f;			val0 |= val1 << 4;			rc = reg_w(ov, reg, val0);			if (rc < 0)				return rc;		}		if (ENABLE_UV_QUANTABLE) {			val0 = *pUVTable++;			val1 = *pUVTable++;			val0 &= 0x0f;			val1 &= 0x0f;			val0 |= val1 << 4;			rc = reg_w(ov, reg + OV518_QUANTABLESIZE/2, val0);			if (rc < 0)				return rc;		}		reg++;	}	return 0;}static intov51x_reset(struct usb_ov511 *ov, unsigned char reset_type){	int rc;	/* Setting bit 0 not allowed on 518/518Plus */	if (ov->bclass == BCL_OV518)		reset_type &= 0xfe;	PDEBUG(4, "Reset: type=0x%02X", reset_type);	rc = reg_w(ov, R51x_SYS_RESET, reset_type);	rc = reg_w(ov, R51x_SYS_RESET, 0);	if (rc < 0)		err("reset: command failed");	return rc;}/********************************************************************** * * Low-level I2C I/O functions * **********************************************************************//* NOTE: Do not call this function directly! * The OV518 I2C I/O procedure is different, hence, this function. * This is normally only called from i2c_w(). Note that this function * always succeeds regardless of whether the sensor is present and working.

⌨️ 快捷键说明

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