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

📄 ov511.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct video_picture p;	unsigned char exp;	if (!ov511 || !ov511->dev)		return -ENODEV;	sensor_get_picture(ov511, &p);	sensor_get_exposure(ov511, &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", 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", 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",			       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, "  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+" :			ov511->bridge == BRG_OV518 ? "OV518" :			ov511->bridge == BRG_OV518PLUS ? "OV518+" :			"unknown");	out += sprintf(out, "sensor          : %s\n",		       ov511->sensor == SEN_OV6620 ? "OV6620" :			ov511->sensor == SEN_OV6630 ? "OV6630" :			ov511->sensor == SEN_OV7610 ? "OV7610" :			ov511->sensor == SEN_OV7620 ? "OV7620" :			ov511->sensor == SEN_OV7620AE ? "OV7620AE" :			ov511->sensor == SEN_OV8600 ? "OV8600" :			ov511->sensor == SEN_KS0127 ? "KS0127" :			ov511->sensor == SEN_KS0127B ? "KS0127B" :			ov511->sensor == SEN_SAA7111A ? "SAA7111A" :			"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;}/* /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 int ov511_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 *ov511 = data;	if (!ov511 || !ov511->dev)		return -ENODEV;	status = ov51x_check_snapshot(ov511);	out += sprintf(out, "%d", status);	if (status)		ov51x_clear_snapshot(ov511);	len = out - page;	len -= off;	if (len < count) {		*eof = 1;		if (len <= 0)			return 0;	} else {		len = count;	}	*start = page + off;	return len;}static void create_proc_ov511_cam(struct usb_ov511 *ov511){	char dirname[4];	if (!ov511_proc_entry || !ov511)		return;	/* Create per-device directory */	sprintf(dirname, "%d", ov511->vdev.minor);	PDEBUG(4, "creating /proc/video/ov511/%s/", dirname);	ov511->proc_devdir = create_proc_entry(dirname, S_IFDIR,		ov511_proc_entry);	if (!ov511->proc_devdir)		return;	/* Create "info" entry (human readable device information) */	PDEBUG(4, "creating /proc/video/ov511/%s/info", dirname);	ov511->proc_info = create_proc_read_entry("info",		S_IFREG|S_IRUGO|S_IWUSR, ov511->proc_devdir,		ov511_read_proc_info, ov511);	if (!ov511->proc_info)		return;	/* 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);		ov511->proc_button = create_proc_read_entry("button",			S_IFREG|S_IRUGO|S_IWUSR, ov511->proc_devdir,			ov511_read_proc_button, ov511);		if (!ov511->proc_button)			return;	}	/* Create "control" entry (ioctl() interface) */	PDEBUG(4, "creating /proc/video/ov511/%s/control", dirname);	lock_kernel();	ov511->proc_control = create_proc_entry("control",		S_IFREG|S_IRUGO|S_IWUSR, ov511->proc_devdir);	if (!ov511->proc_control) {		unlock_kernel();		return;	}	ov511->proc_control->data = ov511;	ov511->proc_control->proc_fops = &ov511_control_fops;	unlock_kernel();}static void destroy_proc_ov511_cam(struct usb_ov511 *ov511){	char dirname[4];		if (!ov511 || !ov511->proc_devdir)		return;	sprintf(dirname, "%d", ov511->vdev.minor);	/* Destroy "control" entry */	if (ov511->proc_control) {		PDEBUG(4, "destroying /proc/video/ov511/%s/control", dirname);		remove_proc_entry("control", ov511->proc_devdir);		ov511->proc_control = NULL;	}	/* Destroy "button" entry */	if (ov511->proc_button) {		PDEBUG(4, "destroying /proc/video/ov511/%s/button", dirname);		remove_proc_entry("button", ov511->proc_devdir);		ov511->proc_button = NULL;	}	/* Destroy "info" entry */	if (ov511->proc_info) {		PDEBUG(4, "destroying /proc/video/ov511/%s/info", dirname);		remove_proc_entry("info", ov511->proc_devdir);		ov511->proc_info = NULL;	}	/* Destroy per-device directory */	PDEBUG(4, "destroying /proc/video/ov511/%s/", dirname);	remove_proc_entry(dirname, ov511_proc_entry);	ov511->proc_devdir = 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("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 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 *//********************************************************************** * * Register I/O * **********************************************************************/static int ov511_reg_write(struct usb_device *dev, unsigned char reg, unsigned char value){	int rc;	PDEBUG(5, "0x%02X:0x%02X", reg, value);	rc = usb_control_msg(dev,			     usb_sndctrlpipe(dev, 0),			     2 /* REG_IO */,			     USB_TYPE_CLASS | USB_RECIP_DEVICE,			     0, (__u16)reg, &value, 1, HZ);		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);                               	PDEBUG(5, "0x%02X:0x%02X", reg, buffer[0]);		if (rc < 0) {		err("reg read: error %d", rc);		return rc;	} else {		return buffer[0];		}}/* * Writes bits at positions specified by mask to a 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 int ov511_reg_write_mask(struct usb_device *dev,		     unsigned char reg,		     unsigned char value,		     unsigned char mask){	int ret;	unsigned char oldval, newval;	ret = ov511_reg_read(dev, 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 (ov511_reg_write(dev, reg, newval));}/* Writes multiple (n) values to a single register. Only valid with certain * registers (0x30 and 0xc4 - 0xce). Used for writing 16 and 24-bit values. */static int ov518_reg_write_multi(struct usb_device *dev,		      unsigned char reg,		      unsigned char *values,		      int n){	int rc;	PDEBUG(5, "0x%02X:[multiple], n=%d", reg, n);  // FIXME	if (values == NULL) {		err("reg write multiple: NULL buffer");		return -EINVAL;	}	rc = usb_control_msg(dev,			     usb_sndctrlpipe(dev, 0),			     2 /* REG_IO */,			     USB_TYPE_CLASS | USB_RECIP_DEVICE,			     0, (__u16)reg, values, n, HZ);		if (rc < 0)		err("reg write multiple: error %d", rc);	return rc;}static int ov511_upload_quan_tables(struct usb_device *dev){	unsigned char *pYTable = yQuanTable511;	unsigned char *pUVTable = uvQuanTable511;	unsigned char val0, val1;	int i, rc, reg = OV511_OMNICE_Y_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 = ov511_reg_write(dev, reg, val0);			if (rc < 0)				return rc;		}		if (ENABLE_UV_QUANTABLE)		{			val0 = *pUVTable++;			val1 = *pUVTable++;			val0 &= 0x0f;			val1 &= 0x0f;			val0 |= val1 << 4;			rc = ov511_reg_write(dev, reg + OV511_QUANTABLESIZE / 2,				val0);			if (rc < 0)				return rc;		}		reg++;	}	return 0;}/* OV518 quantization tables are 8x4 (instead of 8x8) */static int ov518_upload_quan_tables(struct usb_device *dev){	unsigned char *pYTable = yQuanTable518;	unsigned char *pUVTable = uvQuanTable518;	unsigned char val0, val1;	int i, rc, reg = OV511_OMNICE_Y_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 = ov511_reg_write(dev, reg, val0);			if (rc < 0)				return rc;		}		if (ENABLE_UV_QUANTABLE)		{			val0 = *pUVTable++;			val1 = *pUVTable++;			val0 &= 0x0f;			val1 &= 0x0f;			val0 |= val1 << 4;			rc = ov511_reg_write(dev, reg + OV518_QUANTABLESIZE / 2,				val0);			if (rc < 0)				return rc;		}		reg++;	}	return 0;}/* NOTE: Do not call this function directly! * The OV518 I2C I/O procedure is different, hence, this function. * This is normally only called from ov51x_i2c_write(). Note that this function * always succeeds regardless of whether the sensor is present and working. */static int ov518_i2c_write_internal(struct usb_device *dev,			 unsigned char reg,			 unsigned char value){	int rc;	PDEBUG(5, "0x%02X:0x%02X", reg, value);	/* Select camera register */	rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg);	if (rc < 0) goto error;	/* Write "value" to I2C data port of OV511 */	rc = ov511_reg_write(dev, OV511_REG_I2C_DATA_PORT, value);	if (rc < 0) goto error;	/* Initiate 3-byte write cycle */	rc = ov511_reg_write(dev, OV518_REG_I2C_CONTROL, 0x01);	if (rc < 0) goto error;	return 0;error:	err("ov518 i2c write: error %d", rc);	return rc;}/* NOTE: Do not call this function directly! */static int ov511_i2c_write_internal(struct usb_device *dev,			 unsigned char reg,			 unsigned char value){	int rc, retries;	PDEBUG(5, "0x%02X:0x%02X", reg, value);	/* Three byte write cycle */	for (retries = OV511_I2C_RETRIES; ; ) {		/* Select camera register */		rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE,				     reg);		if (rc < 0) goto error;		/* Write "value" to I2C data port of OV511 */		rc = ov511_reg_write(dev, OV511_REG_I2C_DATA_PORT, value);			if (rc < 0) goto error;		/* Initiate 3-byte write cycle */		rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x01);		if (rc < 0) goto error;		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */		if (rc < 0) goto error;		if ((rc&2) == 0) /* Ack? */			break;#if 0		/* I2C abort */			ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);#endif		if (--retries < 0) {			err("i2c write retries exhausted");			rc = -1;

⌨️ 快捷键说明

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